Order operator snapshots by generation

This commit is contained in:
Meta Vens 2026-07-13 01:11:56 +01:00
commit d1b2f64cee
5 changed files with 92 additions and 4 deletions

View file

@ -2711,14 +2711,57 @@ pub fn write_epiphany_cultmesh_operator_snapshot(
store_path: impl AsRef<Path>,
snapshot: EpiphanyCultMeshOperatorSnapshotEntry,
) -> Result<EpiphanyCultMeshOperatorSnapshotEntry> {
validate_operator_snapshot(&snapshot)?;
let mut node = open_epiphany_cultmesh_node(&store_path, snapshot.runtime_id.clone())?;
let snapshot_key = epiphany_cultmesh_operator_snapshot_key(&snapshot.snapshot_id);
let written = node.put(snapshot_key.as_str(), &snapshot)?;
node.put(EPIPHANY_CULTMESH_OPERATOR_SNAPSHOT_LATEST_KEY, &written)?;
let current_latest = node.get::<EpiphanyCultMeshOperatorSnapshotEntry>(
EPIPHANY_CULTMESH_OPERATOR_SNAPSHOT_LATEST_KEY,
)?;
if current_latest.as_ref().is_none_or(|current| {
operator_snapshot_generation_key(&written) >= operator_snapshot_generation_key(current)
}) {
node.put(EPIPHANY_CULTMESH_OPERATOR_SNAPSHOT_LATEST_KEY, &written)?;
}
node.flush()?;
Ok(written)
}
fn validate_operator_snapshot(snapshot: &EpiphanyCultMeshOperatorSnapshotEntry) -> Result<()> {
if snapshot.schema_version != EPIPHANY_CULTMESH_OPERATOR_SNAPSHOT_SCHEMA_VERSION {
return Err(anyhow!("operator snapshot has unsupported schema version"));
}
if snapshot.verse_id != EPIPHANY_CULTMESH_INTERNAL_VERSE_ID {
return Err(anyhow!(
"operator snapshot must remain in the internal Verse"
));
}
for (label, value) in [
("runtime id", snapshot.runtime_id.as_str()),
("snapshot id", snapshot.snapshot_id.as_str()),
("source mode", snapshot.source_mode.as_str()),
("source path", snapshot.source_path.as_str()),
("status", snapshot.status.as_str()),
] {
if value.trim().is_empty() {
return Err(anyhow!("operator snapshot missing {label}"));
}
}
DateTime::parse_from_rfc3339(&snapshot.generated_at_utc)
.map_err(|error| anyhow!("operator snapshot has invalid generated_at_utc: {error}"))?;
Ok(())
}
fn operator_snapshot_generation_key(
snapshot: &EpiphanyCultMeshOperatorSnapshotEntry,
) -> (DateTime<FixedOffset>, &str) {
(
DateTime::parse_from_rfc3339(&snapshot.generated_at_utc)
.expect("validated operator snapshot generation timestamp"),
snapshot.snapshot_id.as_str(),
)
}
pub fn load_epiphany_cultmesh_operator_snapshot(
store_path: impl AsRef<Path>,
runtime_id: impl Into<String>,
@ -7288,9 +7331,39 @@ mod tests {
load_epiphany_cultmesh_operator_snapshot(&store, "epiphany-test", "snapshot-test")?,
Some(snapshot.clone())
);
let mut newer = snapshot.clone();
newer.snapshot_id = "snapshot-newer".to_string();
newer.generated_at_utc = "2026-05-27T01:00:00Z".to_string();
newer.coordinator_action = "continue".to_string();
write_epiphany_cultmesh_operator_snapshot(&store, newer.clone())?;
let mut delayed = snapshot.clone();
delayed.snapshot_id = "snapshot-delayed".to_string();
delayed.generated_at_utc = "2026-05-26T23:00:00Z".to_string();
write_epiphany_cultmesh_operator_snapshot(&store, delayed)?;
assert_eq!(
load_latest_epiphany_cultmesh_operator_snapshot(&store, "epiphany-test")?,
Some(snapshot)
Some(newer)
);
let mut invalid_time = snapshot.clone();
invalid_time.snapshot_id = "snapshot-invalid-time".to_string();
invalid_time.generated_at_utc = "not-a-time".to_string();
assert!(
write_epiphany_cultmesh_operator_snapshot(&store, invalid_time)
.unwrap_err()
.to_string()
.contains("invalid generated_at_utc")
);
let mut wrong_verse = snapshot;
wrong_verse.snapshot_id = "snapshot-wrong-verse".to_string();
wrong_verse.verse_id = EPIPHANY_CULTMESH_LOCAL_AREA_VERSE_ID.to_string();
assert!(
write_epiphany_cultmesh_operator_snapshot(&store, wrong_verse)
.unwrap_err()
.to_string()
.contains("internal Verse")
);
let node = open_epiphany_cultmesh_node(&store, "epiphany-test")?;
assert!(

View file

@ -622,6 +622,18 @@ valid RFC3339 generation time, are confined to the local-area Verse, and
advance `latest` by `(generation time, summary ID)`. Delayed stale summaries
cannot replace current swarm self-knowledge.
## Mirror arrival presented as current operator observation
Operator snapshots distill runtime status into typed internal-Verse context for
the human-facing control surface, but their `latest` mirror was arrival-owned
and the writer accepted unvalidated source bindings and timestamps. A delayed
old status snapshot could therefore rewind the observed coordinator action,
jobs, tools, and next action after the runtime had moved on. Snapshot writes
now require the canonical schema, internal Verse, nonempty runtime/snapshot and
source identity, and valid RFC3339 generation time. `latest` advances by
`(generation time, snapshot ID)`; snapshots remain observations and acquire no
coordinator or runtime authority.
## Unresolved: provider receipts without chronology
Bifrost body-change/GitHub publication receipts are externally owned and their

View file

@ -156,6 +156,9 @@ The confirmed conceptual substitutions have been cut:
proof transport cannot replace the current commit/hash evidence projection.
- Agent-state SoA `latest` is generation-time-owned and local-area confined;
delayed summaries cannot rewind prompt/swarm self-knowledge.
- Operator snapshots are validated internal-Verse observations and `latest` is
generation-time-owned; delayed status transport cannot rewind the observed
coordinator/runtime surface.
- Bifrost provider receipt contracts still lack provider timestamp/revision.
Do not invent consumer-side ordering; repair that in a Bifrost-owned schema.
@ -194,4 +197,4 @@ Continue the modeling pass beyond receipt writers. Inventory production paths wh
## Verification baseline
The last completed code pass had 252 library tests passing and all binaries compiling. Re-run focused checks for the next touched surface; use the full library/binary baseline before committing a new architectural cut.
The last completed code pass had 258 library tests passing and all binaries compiling. Re-run focused checks for the next touched surface; use the full library/binary baseline before committing a new architectural cut.

Binary file not shown.

View file

@ -660,4 +660,4 @@ current_status:
- Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass.
- `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure.
last_completed_repo_swarm_cut: Huginn live-fire has crossed the first real repo Body from Persona pressure to branch-local Hands commit and Soul/Mind closure, and now has repeatable closure and redacted-public-proof mouths. On `E:\Projects\Huginn` branch `epiphany/huginn/first-awakening`, `tools/epiphany_local_run.ps1 -Mode repo-persona-intake` accepted item `huginn-inspection-readback-livefire`, Weksa/Persona intake remained sealed, and `epiphany-work derive-plan` lowered it to model-authored safe family `repo.status_section` for `README.md` only. `tools/epiphany_local_run.ps1 -Mode repo-swarm-run` advanced four bounded pulses: run-from-plan, adopt-from-plan, execute-from-plan, and close-from-execute. Huginn commit `e9b07c38fceabbdc89ea35c2156326c80c0393a2` updated only `README.md`; closure receipt `.epiphany\work\work-close-huginn-inspection-readback-livefire.json` records status `closed`, Soul verdict `passed`, Mind state commit `repo-work-close-huginn-inspection-readback-livefire-mind-commit`, safe family `repo.status_section`, path scope `README.md`, Bifrost publication gate, and `privateStateExposed=false`. Verification also ran Huginn's TypeScript compiler through concrete Node path: `C:\Program Files\nodejs\node.exe E:\Projects\Huginn\node_modules\typescript\bin\tsc -p tsconfig.json` passed. Native verifier `epiphany-repo-livefire-closure-smoke --workspace E:\Projects\Huginn --item huginn-inspection-readback-livefire --expected-path README.md --expected-family repo.status_section --expected-gate awaiting-publication --expected-blocker bifrost-publication-missing` checks closure receipt, Mind map entry, overview gate/blocker, authority seals, and `git show` changed paths, returning `status=ok`, `soulVerdict=passed`, `publicationGate=Bifrost`, and `privateStateExposed=false`. Wrapper `tools/epiphany_local_run.ps1 -Mode repo-livefire-closure -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exposes the same read-only proof through the local operator mouth; artifact `local-20260621-190156-803-2f85ba15` printed commit, path, gate, blocker, Soul verdict, Mind commit receipt, and `privateStateExposed=False` without push, merge, publication, or target mutation. New wrapper `tools/epiphany_local_run.ps1 -Mode repo-work-public-proof -Workspace E:\Projects\Huginn -RepoWorkItem huginn-inspection-readback-livefire -SkipBuild` exports the redacted proof bundle and repo-local Verse index without publishing; artifact `local-20260621-190645-345-4555b1dc` wrote `.epiphany\public\proof-bundles\repo-work-public-proof-huginn-inspection-readback-livefire.json`, proof id `repo-work-public-proof-huginn-inspection-readback-livefire`, SHA-256 `857545b199f3e37eb06c2e757e5cfc201958e46667bb1f8403fd333a22620f63`, nine artifact rows, zero publication rows, and `privateStateExposed=False`. swarm overview readback `local-20260621-190701-140-b9519ec6` sees the `REPO-WORK-PUBLIC-PROOF` row and action row from Huginn's repo-local Verse with the same SHA-256 while Bifrost publication remains missing. Launcher compact modes are now named compact operator-context modes instead of read-only modes, and `bifrost-public-proof` summaries print item, target public Verse, room, proof SHA-256, review receipts, and credit receipts so publication receipts are auditable without claiming upstream sync.
next_action: Continue the conceptual-substitution modeling pass beyond receipt writers. Operational/evidence/self-state mirrors with owned clocks are event-time ordered; repo-work projections follow owning time; writerless readiness-review is deleted. Bifrost provider receipts still need a provider-owned chronology contract rather than consumer inference. Continue auditing other evidence/security mirrors, service configuration claims, adapters, and destructive path consumers for borrowed authority.
next_action: Continue the conceptual-substitution modeling pass beyond receipt writers. Operational/evidence/self-state and operator-observation mirrors with owned clocks are event-time ordered; repo-work projections follow owning time; writerless readiness-review is deleted. Bifrost provider receipts still need a provider-owned chronology contract rather than consumer inference. Continue auditing other evidence/security mirrors, service configuration claims, adapters, and destructive path consumers for borrowed authority.