diff --git a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-gate-smoke.rs b/epiphany-core/src/bin/epiphany-repo-swarm-mvp-gate-smoke.rs index e62514c5..ff20c321 100644 --- a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-gate-smoke.rs +++ b/epiphany-core/src/bin/epiphany-repo-swarm-mvp-gate-smoke.rs @@ -23,6 +23,7 @@ struct Args { fresh_repo_summary: Option, readiness_summary: Option, bifrost_accounting_summary: Option, + deployment_handoff_summary: Option, daemon_survival_summary: Option, } @@ -33,6 +34,7 @@ impl Args { let mut fresh_repo_summary = None; let mut readiness_summary = None; let mut bifrost_accounting_summary = None; + let mut deployment_handoff_summary = None; let mut daemon_survival_summary = None; let mut args = env::args().skip(1).peekable(); while let Some(arg) = args.next() { @@ -49,6 +51,10 @@ impl Args { bifrost_accounting_summary = Some(take_path(&mut args, "--bifrost-accounting-summary")?) } + "--deployment-handoff-summary" => { + deployment_handoff_summary = + Some(take_path(&mut args, "--deployment-handoff-summary")?) + } "--daemon-survival-summary" => { daemon_survival_summary = Some(take_path(&mut args, "--daemon-survival-summary")?) @@ -62,6 +68,7 @@ impl Args { fresh_repo_summary, readiness_summary, bifrost_accounting_summary, + deployment_handoff_summary, daemon_survival_summary, }) } @@ -99,6 +106,9 @@ fn run_smoke(args: Args) -> Result { let bifrost_accounting_summary = args .bifrost_accounting_summary .unwrap_or_else(|| latest_summary(&args.smoke_root, "repo-bifrost-accounting-bundle-")); + let deployment_handoff_summary = args + .deployment_handoff_summary + .unwrap_or_else(|| latest_summary(&args.smoke_root, "repo-deployment-config-family-")); let daemon_survival_summary = args .daemon_survival_summary .unwrap_or_else(|| latest_summary(&args.smoke_root, "daemon-survival-rehearsal-")); @@ -106,11 +116,13 @@ fn run_smoke(args: Args) -> Result { let fresh = read_json(&fresh_repo_summary)?; let readiness = read_json(&readiness_summary)?; let bifrost = read_json(&bifrost_accounting_summary)?; + let deployment_handoff = read_json(&deployment_handoff_summary)?; let daemon_survival = read_json(&daemon_survival_summary)?; verify_fresh_repo(&fresh)?; verify_readiness(&readiness)?; verify_bifrost_accounting(&bifrost)?; + verify_deployment_handoff(&deployment_handoff)?; verify_daemon_survival(&daemon_survival)?; let gate_rows = vec![ @@ -161,6 +173,11 @@ fn run_smoke(args: Args) -> Result { "Bifrost", "readiness, artifact acceptance, and metrics accounting rows are closed", ), + green( + "idunn-deployment-handoff", + "Idunn", + "deployment config, operator runbook, and aftercare receipt readback are sealed", + ), green( "long-running-daemon-proof", "Idunn", @@ -204,10 +221,12 @@ fn run_smoke(args: Args) -> Result { "freshRepoSummary": fresh_repo_summary, "readinessSummary": readiness_summary, "bifrostAccountingSummary": bifrost_accounting_summary, + "deploymentHandoffSummary": deployment_handoff_summary, "daemonSurvivalSummary": daemon_survival_summary, "freshRepoSmokeDir": fresh["smokeDir"], "readinessSmokeDir": readiness["smokeDir"], "bifrostAccountingSmokeDir": bifrost["smokeDir"], + "deploymentHandoffSmokeDir": deployment_handoff["smokeDir"], "daemonSurvivalSmokeDir": daemon_survival["smokeDir"], "mvpReady": false, "demoReady": true, @@ -332,6 +351,35 @@ fn verify_daemon_survival(value: &Value) -> Result<()> { require_bool(value, &["privateStateExposed"], false) } +fn verify_deployment_handoff(value: &Value) -> Result<()> { + require_eq( + value, + &["schemaVersion"], + "epiphany.repo_deployment_config_family_smoke.v0", + )?; + require_eq(value, &["status"], "ok")?; + require_bool(value, &["deploymentConfigEnabled"], false)?; + require_eq( + value, + &["deploymentConfigAuditStatus"], + "ready-for-idunn-review", + )?; + require_bool(value, &["readyForIdunnReview"], true)?; + require_eq( + value, + &["deploymentExecutionRunbookStatus"], + "ready-for-operator-git-push", + )?; + require_eq(value, &["deploymentAftercareAuditStatus"], "complete")?; + require_bool(value, &["deploymentComplete"], true)?; + require_eq(value, &["idunnDeploymentReceiptSource"], "cultmesh")?; + require_eq(value, &["idunnAftercareAuditReceiptSource"], "cultmesh")?; + require_eq(value, &["deploymentTrigger"], "git-push-observed-by-idunn")?; + require_eq(value, &["deploymentOwner"], "Idunn")?; + require_bool(value, &["deploymentAuthority"], false)?; + require_bool(value, &["privateStateExposed"], false) +} + fn green(gate: &str, owner: &str, evidence: &str) -> Value { json!({ "gate": gate, diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 1938c782..4b797a2e 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -194,7 +194,7 @@ remembers doctrine; the branch remembers the blade. - `bifrost-publication` is the compact non-mutating Bifrost publication proof; use it to prove body-change routing, credit, and GitHub publication receipt state without performing GitHub mutation. Its JSON now points back to compact swarm overview and tool-directory readback. - `bifrost-artifact-acceptance` and `bifrost-metrics` are compact Bifrost/Maintainer closure rites for the safe-family planning/accounting lanes. They write typed accepted-artifact and metrics receipts from explicit artifact/public-proof/review/model-spend/review-load/credit refs, verify latest receipt readback, and let `bifrost-ledger` close `artifact-acceptance-request` and `metrics-request` rows from Bifrost-owned receipts instead of request cargo. The request-family smokes now prove both states: `.epiphany-smoke\repo-artifact-acceptance-request-family-20260621-130520` and `.epiphany-smoke\repo-metrics-request-family-20260621-130635` first assert open request rows, then write final receipts and assert closed rows; wrapper proof `local-20260621-140740-750-2815f6f7` read the closed metrics row with `privateStateExposed=False`. `epiphany-repo-bifrost-accounting-bundle-smoke` consumes the closed family summaries and emits one operator-safe aggregate receipt; wrapper mode `tools/epiphany_local_run.ps1 -Mode bifrost-accounting-bundle` now builds/runs that verifier, accepts optional exact summary paths, writes normal operator run receipts, and proved bundle `.epiphany-smoke\repo-bifrost-accounting-bundle-20260621-132815` via wrapper artifact `local-20260621-142716-268-d6bc58b4` with final Bifrost receipt ids, `planningAuthorityOnly=true`, and `privateStateExposed=false`. - `daemon-survival-rehearsal` is the bounded Idunn physiology proof. `epiphany-daemon-survival-rehearsal-smoke` writes a durable restart policy for `epiphany-daemon-self`, runs `epiphany-daemon-supervisor serve --max-iterations 2 --force --loop-interval-seconds 0`, verifies two scheduler pulses and the scheduler receipt row, and keeps service-manager mutation/elevation/private-state exposure false. Wrapper proof `tools/epiphany_local_run.ps1 -Mode daemon-survival-rehearsal -SkipBuild` emitted `.epiphany-smoke\daemon-survival-rehearsal-20260621-135723` via artifact `local-20260621-145723-011-1175e273`. -- `repo-swarm-mvp-gate` is the compact aggregate MVP proof rite. `epiphany-repo-swarm-mvp-gate-smoke` consumes the latest fresh-repo MVP, repo-work readiness, Bifrost accounting-bundle, and daemon survival summaries, verifies the green proof rows, and leaves only Idunn elevated service execution as an explicit warning gate instead of laundering it into completion. Wrapper mode `tools/epiphany_local_run.ps1 -Mode repo-swarm-mvp-gate` proved `.epiphany-smoke\repo-swarm-mvp-gate-20260621-135754` via wrapper artifact `local-20260621-145752-946-d1d4d118`: `demoReady=True`, `mvpReady=False`, `green=12`, `warnings=1`, `blockers=0`, and `privateStateExposed=False`. +- `repo-swarm-mvp-gate` is the compact aggregate MVP proof rite. `epiphany-repo-swarm-mvp-gate-smoke` consumes the latest fresh-repo MVP, repo-work readiness, Bifrost accounting-bundle, Idunn deployment handoff, and daemon survival summaries, verifies the green proof rows, and leaves only Idunn elevated service/install/start/remote execution as an explicit warning gate instead of laundering it into completion. Wrapper mode `tools/epiphany_local_run.ps1 -Mode repo-swarm-mvp-gate -RepoSwarmMvpDeploymentHandoffSummaryPath .\.epiphany-smoke\repo-deployment-config-family-20260621-141231\summary.json` proved `.epiphany-smoke\repo-swarm-mvp-gate-20260621-141554` via wrapper artifact `local-20260621-151512-514-a0c77e3f`: `demoReady=True`, `mvpReady=False`, `green=13`, `warnings=1`, `blockers=0`, and `privateStateExposed=False`. This is live-fire ready for a controlled repo Body; unattended/elevated production service or deployment execution remains an operator-granted Idunn rite. - `bifrost-ledger` is the compact Bifrost/Imagination readback rite; use it after collaboration, publication, accepted-artifact, or metrics writes to see the latest body-change, public-proof, accepted-artifact, metrics, GitHub, feedback, consensus, credit/review-count, and accounting closure rows without opening the full local Verse. - `tool-directory` is the non-mutating daemon tool sight rite; it shows which globally available daemon-hosted tools any agent can invoke through typed intents and receipts, while still exposing host readiness. - `tool-invoke` now embeds compact readbacks for common daemon-hosted tools. Status calls return `daemonStatusReadback`, Eve calls return `eveConnectionReadback`, Self `service-health` returns Idunn-owned `serviceHealthReadback`, Self `service-policy-directory` returns Idunn-owned `servicePolicyDirectoryReadback`, Self `swarm-online-runbook` returns Idunn-owned `swarmOnlineRunbookReadback`, and Hands/Soul authority tools return `authorityToolReadback` with gate, input contract, receipt contract, intent/receipt routes, host cluster, and private-state seal. This proves global tool ergonomics without moving action, verification, or daemon lifecycle ownership into the wrapper; live proofs routed Persona to Hands `repo-action` (`local-20260619-021628-143-7bf7f2e0`), Soul `verify` (`local-20260619-021701-458-852cfa6f`), Self `swarm-online-runbook` (`local-20260619-032244-273-acb3c6a4`), and Self `service-policy-directory` (`local-20260619-035238-138-633f3ff0`) with `privateStateExposed=false`. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 69b8e028..037d248b 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index cf36bd29..3c2f4c22 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -650,4 +650,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: The artifact-acceptance and metrics request family smokes now prove the whole Bifrost accounting transition, not only the request side. Each smoke first asserts the Mind-admitted safe-family request row is `open`, then writes the final Bifrost/Maintainer receipt, rereads `bifrost-ledger`, and asserts the same lane is `closed` from explicit receipt evidence with `privateStateExposed=false`. Latest proofs `.epiphany-smoke\repo-artifact-acceptance-request-family-20260621-130520` and `.epiphany-smoke\repo-metrics-request-family-20260621-130635`; wrapper proof `local-20260621-140740-750-2815f6f7` printed the closed metrics row from a repo-local Verse target. - next_action: Continue repo-swarm MVP work from `notes/epiphany-repo-swarm-mvp-contract.md`. The aggregate MVP gate is now sealed: `tools/epiphany_local_run.ps1 -Mode repo-swarm-mvp-gate` reports `demoReady=true`, `mvpReady=false`, twelve green proof gates, one Idunn elevated-service warning gate, zero blockers, and `privateStateExposed=false`. Useful next cuts are explicit elevated/operator Idunn execution proof only when the human grants that authority, or another repo-owned safe action family only if it materially improves the MVP story. Persona-to-Imagination consensus readback, Mind-owned interpreter brief cargo, safe-family planning depth and closure, Gjallar closure/readiness/readiness-review rows, receipt-directory readiness-review indexing, Bifrost ledger accounting rows including readiness-review closure plus artifact/metrics final receipt closure, readiness wrapper mouth, repo deployment handoff/readback wrappers, readiness deployment-aftercare closure, readiness Idunn/tool-directory receipt validation, readiness Bifrost/GitHub publication-chain validation, readiness upstream-main sync validation, readiness review/adoption receipt validation, aggregate fresh-repo/readiness/Bifrost MVP gate reporting, and bounded Idunn daemon survival rehearsal are sealed; preserve Idunn service lifecycle ownership, Bifrost publication/upstream-main ownership, Mind durable-state admission, and existing CultMesh/Odin/Eve tool directories. Windows service install/start/deployment execution still requires explicit elevated operator authority. + next_action: Continue repo-swarm MVP work from `notes/epiphany-repo-swarm-mvp-contract.md`. The aggregate MVP gate is now sealed: `tools/epiphany_local_run.ps1 -Mode repo-swarm-mvp-gate` reports `demoReady=true`, `mvpReady=false`, thirteen green proof gates, one Idunn elevated-service warning gate, zero blockers, and `privateStateExposed=false`. Useful next cuts are live-fire testing on a disposable or low-stakes repo Body, explicit elevated/operator Idunn execution proof only when the human grants that authority, or another repo-owned safe action family only if it materially improves the MVP story. Persona-to-Imagination consensus readback, Mind-owned interpreter brief cargo, safe-family planning depth and closure, Gjallar closure/readiness/readiness-review rows, receipt-directory readiness-review indexing, Bifrost ledger accounting rows including readiness-review closure plus artifact/metrics final receipt closure, readiness wrapper mouth, repo deployment handoff/readback wrappers, readiness deployment-aftercare closure, readiness Idunn/tool-directory receipt validation, readiness Bifrost/GitHub publication-chain validation, readiness upstream-main sync validation, readiness review/adoption receipt validation, aggregate fresh-repo/readiness/Bifrost/deployment-handoff/daemon-survival MVP gate reporting, and bounded Idunn daemon survival rehearsal are sealed; preserve Idunn service lifecycle ownership, Bifrost publication/upstream-main ownership, Mind durable-state admission, and existing CultMesh/Odin/Eve tool directories. Windows service install/start/deployment execution still requires explicit elevated operator authority. diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 index 31c23acb..86f85105 100644 --- a/tools/epiphany_local_run.ps1 +++ b/tools/epiphany_local_run.ps1 @@ -58,6 +58,7 @@ param( [string]$RepoSwarmMvpFreshRepoSummaryPath = "", [string]$RepoSwarmMvpReadinessSummaryPath = "", [string]$RepoSwarmMvpBifrostAccountingSummaryPath = "", + [string]$RepoSwarmMvpDeploymentHandoffSummaryPath = "", [string]$RepoSwarmMvpDaemonSurvivalSummaryPath = "", [string]$ToolCapabilityId = "epiphany.cluster.hands.tool.repo-action", [string]$ToolRequestingAgentId = "epiphany.Persona", @@ -1011,6 +1012,9 @@ if ($Mode -eq "repo-swarm-mvp-gate") { if ($RepoSwarmMvpBifrostAccountingSummaryPath -ne "") { $gateArgs += @("--bifrost-accounting-summary", $RepoSwarmMvpBifrostAccountingSummaryPath) } + if ($RepoSwarmMvpDeploymentHandoffSummaryPath -ne "") { + $gateArgs += @("--deployment-handoff-summary", $RepoSwarmMvpDeploymentHandoffSummaryPath) + } if ($RepoSwarmMvpDaemonSurvivalSummaryPath -ne "") { $gateArgs += @("--daemon-survival-summary", $RepoSwarmMvpDaemonSurvivalSummaryPath) }