diff --git a/epiphany-core/src/bin/epiphany-repo-close-mind-adoption-guard-smoke.rs b/epiphany-core/src/bin/epiphany-repo-close-mind-adoption-guard-smoke.rs index d75ac987..4c384eab 100644 --- a/epiphany-core/src/bin/epiphany-repo-close-mind-adoption-guard-smoke.rs +++ b/epiphany-core/src/bin/epiphany-repo-close-mind-adoption-guard-smoke.rs @@ -2,6 +2,7 @@ use anyhow::Context; use anyhow::Result; use anyhow::anyhow; use chrono::Utc; +use serde::Deserialize; use serde_json::Value; use serde_json::json; use std::env; @@ -10,6 +11,29 @@ use std::path::Path; use std::path::PathBuf; use std::process::Command; +#[derive(Clone, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct RepoWorkMapStore { + schema_version: String, + entries: Vec, + private_state_exposed: bool, +} + +#[derive(Clone, Debug, Deserialize)] +#[serde(rename_all = "camelCase")] +struct RepoWorkMapEntry { + schema_version: String, + item: String, + changed_paths: Vec, + commit_sha: String, + safe_action_family: String, + soul_verdict_receipt_id: String, + mind_gateway_review_id: String, + mind_state_commit_receipt_id: String, + durable_state_admitted: bool, + private_state_exposed: bool, +} + fn main() -> Result<()> { let args = Args::parse()?; let result = run_smoke(args)?; @@ -285,6 +309,16 @@ fn run_smoke(args: Args) -> Result { "action-item-accepted", false, )?; + let repo_map_path = repo + .join(".epiphany") + .join("state") + .join("repo-work-map.msgpack"); + if repo_map_path.exists() { + return Err(anyhow!( + "failed closure wrote repo map store before Mind/Soul passed: {}", + repo_map_path.display() + )); + } let close = cargo_json( &manifest, @@ -315,6 +349,93 @@ fn run_smoke(args: Args) -> Result { true, )?; require_bool(&close, &["privateStateExposed"], false)?; + require_eq( + &close, + &["mind", "repoMapEntry", "schemaVersion"], + "epiphany.repo_work_map_entry.v0", + )?; + require_eq( + &close, + &["mind", "repoMapEntry", "safeActionFamily"], + "repo.markdown_planning_note", + )?; + require_bool( + &close, + &["mind", "repoMapEntry", "durableStateAdmitted"], + true, + )?; + require_bool( + &close, + &["mind", "repoMapEntry", "privateStateExposed"], + false, + )?; + let map_store = read_repo_work_map_store(&repo_map_path)?; + if map_store.schema_version != "epiphany.repo_work_map_store.v0" { + return Err(anyhow!( + "unexpected repo map schema {}", + map_store.schema_version + )); + } + if map_store.private_state_exposed { + return Err(anyhow!("repo map store exposed private state")); + } + let map_entry = map_store + .entries + .iter() + .find(|entry| entry.item == item) + .ok_or_else(|| anyhow!("repo map store has no entry for {item}"))?; + if map_entry.schema_version != "epiphany.repo_work_map_entry.v0" { + return Err(anyhow!( + "unexpected repo map entry schema {}", + map_entry.schema_version + )); + } + if map_entry.changed_paths != vec![target_path.to_string()] { + return Err(anyhow!( + "unexpected repo map changed paths {:?}", + map_entry.changed_paths + )); + } + require_struct_eq( + &map_entry.commit_sha, + value_at_path(&close, &["handsReceipts", "commitSha"]) + .and_then(Value::as_str) + .ok_or_else(|| anyhow!("close output had no handsReceipts.commitSha"))?, + "repo map commit sha", + )?; + require_struct_eq( + &map_entry.soul_verdict_receipt_id, + value_at_path(&close, &["soul", "verdictReceiptId"]) + .and_then(Value::as_str) + .ok_or_else(|| anyhow!("close output had no soul.verdictReceiptId"))?, + "repo map Soul verdict id", + )?; + require_struct_eq( + &map_entry.mind_gateway_review_id, + value_at_path(&close, &["mind", "gatewayReviewId"]) + .and_then(Value::as_str) + .ok_or_else(|| anyhow!("close output had no mind.gatewayReviewId"))?, + "repo map Mind gateway id", + )?; + require_struct_eq( + &map_entry.mind_state_commit_receipt_id, + value_at_path(&close, &["mind", "stateCommitReceiptId"]) + .and_then(Value::as_str) + .ok_or_else(|| anyhow!("close output had no mind.stateCommitReceiptId"))?, + "repo map Mind commit id", + )?; + require_struct_eq( + &map_entry.safe_action_family, + "repo.markdown_planning_note", + "repo map safe family", + )?; + if !map_entry.durable_state_admitted || map_entry.private_state_exposed { + return Err(anyhow!( + "repo map authority flags were wrong: durable={}, private={}", + map_entry.durable_state_admitted, + map_entry.private_state_exposed + )); + } let summary = json!({ "schemaVersion": "epiphany.repo_close_mind_adoption_guard_smoke.v0", @@ -330,6 +451,9 @@ fn run_smoke(args: Args) -> Result { "closeStatus": close["status"], "soulVerdict": close["soul"]["verdict"], "mindAdoptionReviewStatus": close["closureReview"]["mindAdoptionReview"]["status"], + "repoMapStorePath": repo_map_path, + "repoMapEntrySchema": map_entry.schema_version, + "repoMapDurableStateAdmitted": map_entry.durable_state_admitted, "publicationAuthorized": false, "privateStateExposed": false }); @@ -418,6 +542,23 @@ fn write_json(path: &Path, value: &Value) -> Result<()> { .with_context(|| format!("failed to write {}", path.display())) } +fn read_repo_work_map_store(path: &Path) -> Result { + let bytes = fs::read(path).with_context(|| format!("failed to read {}", path.display()))?; + rmp_serde::from_slice(&bytes).with_context(|| format!("failed to decode {}", path.display())) +} + +fn require_struct_eq(actual: &str, expected: &str, label: &str) -> Result<()> { + if actual == expected { + Ok(()) + } else { + Err(anyhow!( + "expected {label} to be {:?}, got {:?}", + expected, + actual + )) + } +} + fn require_eq(value: &Value, path: &[&str], expected: &str) -> Result<()> { let actual = value_at_path(value, path) .and_then(Value::as_str) diff --git a/epiphany-core/src/bin/epiphany-work.rs b/epiphany-core/src/bin/epiphany-work.rs index 0e0d6c05..fc9550f0 100644 --- a/epiphany-core/src/bin/epiphany-work.rs +++ b/epiphany-core/src/bin/epiphany-work.rs @@ -48,6 +48,8 @@ use epiphany_core::runtime_hands_commit_receipt; use epiphany_core::runtime_latest_hands_receipt_chain_after; use epiphany_core::write_epiphany_cultmesh_repo_work_overview; use epiphany_core::write_epiphany_cultmesh_repo_work_public_proof; +use serde::Deserialize; +use serde::Serialize; use serde_json::Value; use serde_json::json; use sha2::Digest; @@ -58,6 +60,40 @@ use std::path::Path; use std::path::PathBuf; use std::process::Command; +const REPO_WORK_MAP_STORE_SCHEMA_VERSION: &str = "epiphany.repo_work_map_store.v0"; +const REPO_WORK_MAP_ENTRY_SCHEMA_VERSION: &str = "epiphany.repo_work_map_entry.v0"; + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +struct RepoWorkMapStore { + schema_version: String, + updated_at: String, + entries: Vec, + private_state_exposed: bool, +} + +#[derive(Clone, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +struct RepoWorkMapEntry { + schema_version: String, + admitted_at: String, + item: String, + branch: String, + changed_paths: Vec, + commit_sha: String, + safe_action_family: String, + modeling_summary: String, + soul_verdict_receipt_id: String, + mind_gateway_review_id: String, + mind_state_commit_receipt_id: String, + execute_receipt_path: String, + closure_review_path: String, + closure_receipt_path: String, + publication_gate: String, + durable_state_admitted: bool, + private_state_exposed: bool, +} + fn main() -> Result<()> { let mut args = env::args().skip(1); let Some(command) = args.next() else { @@ -7564,6 +7600,95 @@ fn closure_mind_adoption_review(execute_receipt: &Value) -> Result<(Value, bool) )) } +fn repo_work_map_store_path(workspace: &Path) -> PathBuf { + workspace + .join(".epiphany") + .join("state") + .join("repo-work-map.msgpack") +} + +fn load_repo_work_map_store(path: &Path) -> Result { + if !path.exists() { + return Ok(RepoWorkMapStore { + schema_version: REPO_WORK_MAP_STORE_SCHEMA_VERSION.to_string(), + updated_at: Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true), + entries: Vec::new(), + private_state_exposed: false, + }); + } + let bytes = fs::read(path).with_context(|| format!("failed to read {}", path.display()))?; + let store: RepoWorkMapStore = rmp_serde::from_slice(&bytes) + .with_context(|| format!("failed to decode {}", path.display()))?; + if store.schema_version != REPO_WORK_MAP_STORE_SCHEMA_VERSION { + return Err(anyhow!( + "unsupported repo work map schema {} in {}", + store.schema_version, + path.display() + )); + } + Ok(store) +} + +fn write_repo_work_map_store(path: &Path, store: &RepoWorkMapStore) -> Result<()> { + if let Some(parent) = path.parent() { + fs::create_dir_all(parent) + .with_context(|| format!("failed to create {}", parent.display()))?; + } + let bytes = rmp_serde::to_vec_named(store).context("failed to encode repo work map store")?; + fs::write(path, bytes).with_context(|| format!("failed to write {}", path.display())) +} + +fn record_repo_work_map_admission( + workspace: &Path, + item: &str, + branch: &str, + changed_paths: Vec, + commit_sha: &str, + closure_review: &Value, + modeling_summary: &str, + soul_verdict_receipt_id: &str, + mind_gateway_review_id: &str, + mind_state_commit_receipt_id: &str, + execute_receipt_path: &Path, + closure_review_path: &Path, + closure_receipt_path: &Path, +) -> Result<(PathBuf, RepoWorkMapEntry)> { + let map_store_path = repo_work_map_store_path(workspace); + let mut store = load_repo_work_map_store(&map_store_path)?; + let now = Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); + let safe_action_family = + string_from_json(closure_review, &["familyAssertions", "safeActionFamily"]) + .unwrap_or_else(|| "manual-or-unknown".to_string()); + let entry = RepoWorkMapEntry { + schema_version: REPO_WORK_MAP_ENTRY_SCHEMA_VERSION.to_string(), + admitted_at: now.clone(), + item: item.to_string(), + branch: branch.to_string(), + changed_paths, + commit_sha: commit_sha.to_string(), + safe_action_family, + modeling_summary: modeling_summary.to_string(), + soul_verdict_receipt_id: soul_verdict_receipt_id.to_string(), + mind_gateway_review_id: mind_gateway_review_id.to_string(), + mind_state_commit_receipt_id: mind_state_commit_receipt_id.to_string(), + execute_receipt_path: normalize_path_for_receipt(execute_receipt_path), + closure_review_path: normalize_path_for_receipt(closure_review_path), + closure_receipt_path: normalize_path_for_receipt(closure_receipt_path), + publication_gate: "Bifrost".to_string(), + durable_state_admitted: true, + private_state_exposed: false, + }; + store.entries.retain(|existing| existing.item != item); + store.entries.push(entry.clone()); + store + .entries + .sort_by(|left, right| left.item.cmp(&right.item)); + store.updated_at = now; + store.private_state_exposed = false; + write_repo_work_map_store(&map_store_path, &store)?; + Ok((map_store_path, entry)) +} + fn closure_model_review( model_authored: bool, model_ref: Option<&str>, @@ -8927,11 +9052,29 @@ fn run_close(args: CloseArgs) -> Result { vec![ "repoWork.closure".to_string(), "repoWork.modelingSummary".to_string(), + "repoWork.map".to_string(), ], Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true), ); put_mind_state_commit_receipt(&runtime_store, &mind_commit)?; + let branch = git_output(&workspace, &["branch", "--show-current"])?; + let (repo_map_store_path, repo_map_entry) = record_repo_work_map_admission( + &workspace, + &item, + &branch, + declared_changed_paths.clone(), + &commit_sha, + &closure_review, + &modeling_summary, + &soul_verdict.receipt_id, + &mind_review.gateway_id, + &mind_commit.receipt_id, + &execute_receipt_path, + &closure_review_path, + &closure_receipt_path, + )?; + let closure_receipt = json!({ "schemaVersion": "epiphany.repo_work_closure_receipt.v0", "createdAt": now, @@ -8967,7 +9110,9 @@ fn run_close(args: CloseArgs) -> Result { "gatewayReviewId": mind_review.gateway_id, "stateCommitReceiptId": mind_commit.receipt_id, "stateRevision": mind_commit.state_revision, - "changedFields": mind_commit.changed_fields + "changedFields": mind_commit.changed_fields, + "repoMapStorePath": normalize_path_for_receipt(&repo_map_store_path), + "repoMapEntry": repo_map_entry }, "authority": { "branchLocalOnly": true, diff --git a/notes/epiphany-repo-swarm-mvp-contract.md b/notes/epiphany-repo-swarm-mvp-contract.md index 67441538..c55034f5 100644 --- a/notes/epiphany-repo-swarm-mvp-contract.md +++ b/notes/epiphany-repo-swarm-mvp-contract.md @@ -1076,7 +1076,13 @@ refusal; without that flag, older provenance-only model refs remain compatibility evidence instead of a hard gate. Soul then writes `epiphany.soul.verdict_receipt`, Modeling records the execution/commit/closure-review summary, and Mind writes gateway review plus -state-commit receipts into runtime-spine. The final +state-commit receipts into runtime-spine. On successful closure, Mind also +admits a compact latest-per-item repo map entry into +`.epiphany/state/repo-work-map.msgpack` as +`epiphany.repo_work_map_store.v0` / `epiphany.repo_work_map_entry.v0`, carrying +the item, branch, changed paths, commit SHA, safe family, Modeling summary, +Soul verdict id, Mind review/commit ids, closure refs, Bifrost publication gate, +and private-state seal. The final `.epiphany/work/work-close-.json` receipt is `epiphany.repo_work_closure_receipt.v0` with `durableStateAdmitted=true`, `publicationGateSatisfied=true`, and @@ -1147,6 +1153,14 @@ tampered close returned `verification-failed`, Soul `failed`, execute/adopt chain then closed with Soul `passed`, `mindAdoptionReview.status=passed`, and `privateStateExposed=false`. +The same smoke was extended as the first durable repo-map admission proof: +`.epiphany-smoke\repo-close-mind-adoption-guard-20260620-202113` proved the +tampered failed close did not write `.epiphany/state/repo-work-map.msgpack`; the +successful close wrote `epiphany.repo_work_map_store.v0` with an +`epiphany.repo_work_map_entry.v0` for the item, `durableStateAdmitted=true`, +the expected commit SHA, changed path, safe family, Soul verdict id, Mind +gateway id, Mind state-commit id, and `privateStateExposed=false`. + `epiphany-work overview` is the first compact repo work sight/proof surface: ```powershell @@ -1495,7 +1509,7 @@ temptation wearing clean robes. | Imagination planning | `derive-plan` now writes a typed `epiphany.repo_work_imagination_action_items_receipt.v0` before the executable plan receipt. The action-item receipt can carry model provenance, allowed safe family, requested paths, verification asks, stop conditions, escalation reasons, planning facets (assumptions, constraints, non-goals, open questions, decision points, and evidence needs), and private-state seals; command text remains deterministic safe-family lowering for `append-worklog`, `planning-note`, `checklist-note`, `section-note` / `repo.markdown_managed_section`, `repo-status-section` / `repo.status_section`, `task-card` / `repo.task_card`, `repo-manifest` / `repo.body_manifest`, `repo-tool-capabilities` / `repo.tool_capabilities`, `repo-tool-request` / `repo.tool_request`, `repo-eve-surface` / `repo.eve_surface`, `repo-collaboration-policy` / `repo.collaboration_policy`, `repo-collaboration-topic` / `repo.collaboration_topic`, `repo-consensus-brief` / `repo.consensus_brief`, `repo-objective-draft` / `repo.objective_draft`, `repo-adoption-request` / `repo.adoption_request`, `repo-scheduling-request` / `repo.scheduling_request`, `repo-work-order` / `repo.work_order`, `repo-verification-request` / `repo.verification_request`, `repo-publication-request` / `repo.publication_request`, `repo-sync-request` / `repo.sync_request`, `repo-maintainer-review-request` / `repo.maintainer_review_request`, `repo-pr-request` / `repo.pr_request`, `repo-credit-request` / `repo.credit_request`, `repo-artifact-acceptance-request` / `repo.artifact_acceptance_request`, `repo-metrics-request` / `repo.metrics_request`, `repo-doctrine-update-request` / `repo.doctrine_update_request`, `repo-secret-policy-request` / `repo.secret_policy_request`, and `repo-deployment-request` / `repo.deployment_request`. `adopt` now writes `epiphany.repo_work_mind_adoption_decision.v0` before the main adoption receipt cites the decision and grants branch-local Hands authority. `plan` remains manual quarantine scaffolding. | Deepen further interpreter behavior and useful repo-owned configuration/action classes without turning model text into arbitrary shell authority. | | Self scheduling | `tick` and `serve` prove one-step branch-local advancement, brake refusal, active-turn refusal, cooldown, and stale-turn recovery; `tick` now routes executed branch-local work through the existing Soul/Modeling/Mind `close` gate; `queue-run` selects tick-actionable rows from the typed repo-work queue and delegates to `tick`; `epiphany-swarm run` is the bounded operator mouth over that queue/tick physiology; `repo-work-service-plan` and `repo-work-service-runbook` write Idunn lifecycle receipts/artifacts for the same queue-run command without launching it. | Keep any future queue-run service launch/install behind Idunn and explicit operator authority. | | Branch-local Hands work | `adopt` and `execute` create approved Hands gates, run planned commands, stage declared paths, commit on `epiphany/*`, and write receipts. | Keep mutation branch-contained and receipt-backed; broaden only through typed plan families, not ad hoc shell freedom. | -| Soul/Modeling/Mind closure | `close` verifies the Hands commit, writes `epiphany.repo_work_closure_review.v0`, refuses path-scope mismatches, refuses missing/tampered/non-affirmative Mind adoption proof, runs known safe-family content assertions, optionally gates on model-authored closure verdicts, and writes Soul, Modeling, and Mind receipts. | Keep extending closure toward source-grounded semantic review and durable map admission, while preserving deterministic local closure for simple mechanical work. | +| Soul/Modeling/Mind closure | `close` verifies the Hands commit, writes `epiphany.repo_work_closure_review.v0`, refuses path-scope mismatches, refuses missing/tampered/non-affirmative Mind adoption proof, runs known safe-family content assertions, optionally gates on model-authored closure verdicts, writes Soul/Modeling/Mind receipts, and admits a compact typed repo map entry into `.epiphany/state/repo-work-map.msgpack`. | Keep extending closure toward source-grounded semantic review and richer local Verse map projection, while preserving deterministic local closure for simple mechanical work. | | Repo work sight | `overview` emits compact proof rows and mirrors typed `epiphany.cultmesh.repo_work_overview.v0` event documents plus a latest key; Gjallar enumerates the history as queue rows and non-mutating action rows; Persona's Eve surface and Eve connection readbacks expose peer-readable gate/blocker/next-action rows; `queue-run` consumes the same queue for branch-local scheduler pulses. | Deepen the Persona-to-plan loop without moving action authority out of Hands/Self/Bifrost. | | Publication | `publish` routes Bifrost/GitHub receipts from closure or explicit Soul/Mind refs. | Keep publication Bifrost-owned; do not let scheduler publish. | | Upstream main sync | `sync` proves the published commit is contained by upstream main after explicit merge/sync authority. | Treat upstream-main sync as a required final proof for published work. | @@ -1952,11 +1966,17 @@ Required organs before MVP: families, refuses assertion failures even when the path scope matches, can require a model-authored closure verdict before Soul passes, and now verifies the accepted Mind adoption proof by checking the embedded decision snapshot - plus standalone decision receipt before closure passes. The verdict packet - records reviewed inputs, finding text, enforced/skipped gate state, and - private-state seals; focused smokes prove a model `needs-work` verdict blocks - closure even when path scope and safe-family assertions pass, and a tampered - Mind adoption decision blocks closure before publication gates can proceed. + plus standalone decision receipt before closure passes. Successful closure now + writes `epiphany.repo_work_map_store.v0` as MessagePack under + `.epiphany/state/repo-work-map.msgpack`, replacing the item's latest + `epiphany.repo_work_map_entry.v0` with the verified commit, changed paths, + safe family, Modeling summary, Soul verdict id, and Mind review/commit ids. + The verdict packet records reviewed inputs, finding text, + enforced/skipped gate state, and private-state seals; focused smokes prove a + model `needs-work` verdict blocks closure even when path scope and safe-family + assertions pass, a tampered Mind adoption decision blocks closure before + publication gates can proceed, failed closure does not write the map, and + successful closure writes the map entry with `privateStateExposed=false`. - Repo work projection/run surface: local `epiphany-work overview` proof bundles, typed `epiphany.cultmesh.repo_work_overview.v0` event history plus latest-key projection, and Gjallar multi-item `repo-work-overview` action/readback rows @@ -1994,11 +2014,12 @@ Required organs before MVP: redacted proof row through `gamecult.bifrost.public_proof_publication_receipt.v0` with public Verse target, public room, ledger, review, credit, proof ref, and SHA-256 readback. - Remaining work is deeper semantic review and durable repo-map admission, not - basic safe-family planning cargo, local public-proof export, local CultMesh - readback, Bifrost/GitHub/sync row visibility, public-proof publication - closure, Mind-adoption closure proof, or the standard wrapper mouth for those - closures. + Remaining work is deeper semantic review, local Verse projection of the + durable repo map, and richer map updates beyond latest work-item consequence; + it is not basic safe-family planning cargo, local public-proof export, local + CultMesh readback, Bifrost/GitHub/sync row visibility, public-proof + publication closure, Mind-adoption closure proof, first durable repo-map + admission, or the standard wrapper mouth for those closures. Scheduler authority is intentionally narrow. It may advance `accept -> plan -> run -> adopt -> execute` only when each upstream receipt @@ -2237,6 +2258,14 @@ Required cuts: - Add a compact repo work ledger view for current work item, branch, last verified consequence, current blocker, and next safe action. +First live cut: successful `epiphany-work close` now performs the Soul -> +Modeling -> Mind part for branch-local repo-work consequences. It writes +`.epiphany/state/repo-work-map.msgpack` as a typed MessagePack +`epiphany.repo_work_map_store.v0` with latest `epiphany.repo_work_map_entry.v0` +rows keyed by item. This is a narrow repo-work map store, not yet the full +semantic architecture map; local Verse projection and richer map lenses remain +Phase 5 work. + MVP exit proof: - After a Hands commit, Soul verifies the changed Body. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 58d99bbc..a91f0705 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -106,6 +106,7 @@ remembers doctrine; the branch remembers the blade. - `notes/epiphany-repo-swarm-mvp-contract.md` is the repo-swarm MVP authority map and migration plan. It states the live seventeen-front-door chain from `epiphany-repo init` through `epiphany-swarm run`, `epiphany-work persona-intake`, `derive-plan`, `close`, `overview`, `export-proof`, `tick`, `queue-run`, `publish`, and `sync`, documents the operator-safe proof receipts already proved with `privateStateExposed=false`, and names the remaining MVP organs as deeper interpreter/adoption semantics, more useful repo-owned configuration/action families, and Idunn-owned queue-run service lifecycle under explicit operator authority. Autonomous branch-local work inside the owned repo Body is in scope and desired; Bifrost gates publication/merge/escalation, Idunn owns daemon lifecycle, and `epiphany-work tick` may only advance one safe receipt-backed branch-local step per pulse before stopping at publication gates. `epiphany-work derive-plan` now consumes accepted Persona/Bifrost pressure, writes typed Imagination action-item receipts, then lowers allowlisted safe families into Imagination/Self action plans: `append-worklog` appends to `EPIPHANY_WORKLOG.md`, `planning-note` creates a contained markdown note under `notes/epiphany-work/.md`, `checklist-note` creates a contained checklist, `section-note` / `repo.markdown_managed_section` creates or replaces one marker-bounded markdown section, `repo-status-section` / `repo.status_section` updates a marker-bounded operator-safe status section in `README.md` by default, and `task-card` / `repo.task_card` writes a structured TOML task card under `notes/epiphany-work/-task-card.toml`; the receipts carry `operatorAuthoredShellDetails=false`, authority seals, and no private-state exposure. Disposable smokes proved append-worklog, planning-note, checklist-note, section-note, task-card, and repo-status-section routes through branch-local Hands commits; `.epiphany-smoke\repo-status-section-20260620-140245` reached close with `repo.status_section`, `modelAuthored=true`, a committed `README.md` status section bounded by Epiphany status markers, Soul `passed`, `pathScopeMatched=true`, and `privateStateExposed=false`. Native repeatable smoke `epiphany-repo-swarm-mvp-smoke` now proves a fresh repo from disposable origin through init, online, Persona intake, model-authored repo-status plan, overview queue projection, `epiphany-swarm run`, Soul close, Bifrost publication receipts, disposable maintainer merge to `origin/main`, upstream-main sync, overview, and public-proof export; `.epiphany-smoke\fresh-repo-mvp-20260620-133452` reported branch `epiphany/fresh-repo-smoke/mvp-proof`, Hands commit `76f8d5ebb023951a513864bdf8555a524d89c5dc`, Soul `passed`, `familyAssertions.status=passed`, `publishStatus=publication-receipts-recorded`, `syncStatus=upstream-main-synced`, `upstreamMainSynced=true`, `publicProofStatus=public-proof-exported`, and `privateStateExposed=false`. `epiphany-work overview` now reads the repo work receipt chain and writes an Eyes/Gjallar-owned sight/proof bundle with current gate, blocker, next safe action, branch, changed paths, commit SHA, Soul verdict, compact rows, and private-state seal; it also mirrors a typed `epiphany.cultmesh.repo_work_overview.v0` document into the repo-local Verse when a local Verse store is known. `epiphany-work export-proof` mirrors redacted public proofs into local Verse, and `epiphany-verse-query bifrost-public-proof` plus wrapper `tools/epiphany_local_run.ps1 -Mode bifrost-public-proof` now publish an existing redacted proof row as `gamecult.bifrost.public_proof_publication_receipt.v0` with public Verse target, public room, ledger, review, credit, proof ref/SHA, and `privateStateExposed=false`; smoke `.epiphany-smoke\checklist-note-20260620-031347` plus wrapper artifact `local-20260620-132418-144-62ba9369` proved latest `bifrost-public-proof-publication-wrapper-checklist` in `bifrost-ledger` and `receipt-directory`. The tick pulse reads the repo-local CultMesh swarm brake and writes `refused-by-swarm-brake` without creating run/adopt/execute receipts when the brake is engaged. It also writes active-turn and last-completed scheduler receipts, refuses live duplicate pulses as `refused-active-turn`, refuses explicit completion-anchored cooldown as `refused-by-cooldown`, clears stale active markers after `--active-timeout-seconds`, and records `physiology.recoveredActiveTurn.recovered=true` when recovery proceeds. `epiphany-work queue-run` reads the repo-local typed overview queue, selects tick-actionable rows for the current repo Body through `awaiting-closure`, delegates to `tick`, refreshes overview after real advancement, and is wrapped by `tools/epiphany_local_run.ps1 -Mode repo-work-queue-run`; `epiphany-swarm run` is the bounded operator mouth over that same queue/tick artery. `epiphany-work serve` wraps the item-scoped tick artery in Self-owned cadence: bounded `--max-iterations` proof mode writes `work-scheduler-serve-.json`, unbounded service mode relies on per-pulse tick receipts, and unbounded zero-second polling is refused. `epiphany-work close` consumes branch-local execute receipts, verifies the Hands commit, writes `epiphany.repo_work_closure_review.v0` with verification command/exit code, declared-vs-actual git changed paths, commit stat, optional model-review provenance, optional/required model-authored closure verdicts, committed-content assertions for known safe families, and authority seals; Soul refuses path-scope mismatches, safe-family assertion failures, and supplied or required model verdicts that do not pass before Modeling/Mind closure, even when the changed path list and family assertions match. Focused smoke `.epiphany-smoke\closure-model-gate-20260620-135103` proved a passing required model verdict closes and a `needs-work` model verdict blocks closure with `familyAssertions.status=passed`, `pathScopeMatched=true`, and `privateStateExposed=false`. The close receipt still grants no publication, merge, service lifecycle, cross-repo mutation, or private-state exposure; tick now calls deterministic close after execution unless a caller explicitly supplies the model verdict gate. `epiphany-work publish --closure-receipt` can consume the closure's Soul/Mind ids, while tick no-ops once closure exists before Bifrost publication authority. - 2026-06-20: The same repo-swarm note now carries the explicit migration thesis, MVP status board, Epiphany Online cut order, authority matrix, local CultMesh tool availability doctrine, and upstream-main sync doctrine. `tools/epiphany_local_run.ps1 -Mode repo-work-service-plan` and `-Mode repo-work-service-runbook` now write Idunn-owned non-mutating lifecycle receipts/artifacts for the real `epiphany-work queue-run` command; proofs `local-20260620-021415-094-58439baf` and `local-20260620-021415-147-067c36b0` planned/wrote the queue-run command vector with `privateStateExposed=false` and no service launch/install. Use that note when answering "are we headed toward a functional swarm?" The answer is yes, and the remaining cuts must preserve typed organ ownership: deeper model-authored closure review, further non-planning action classes, and Idunn-owned queue-run service lifecycle under explicit operator authority. Persona is the mouth, Imagination plans, Self schedules, Hands acts, Soul verifies, Modeling maps, Mind admits, Gjallar sees, Odin discovers, Idunn keeps daemon physiology alive, Bifrost publishes and credits, and Eve/CultUI renders without becoming truth. - 2026-06-20: Soul closure now proves the accepted Mind adoption decision before a branch-local Hands commit can close. `epiphany-work close` embeds `epiphany.repo_work_mind_adoption_closure_review.v0`, checks the adopt receipt's embedded `epiphany.repo_work_mind_adoption_decision.v0` snapshot plus standalone decision receipt, and refuses missing/tampered/non-affirmative Mind adoption even when verification, path scope, and safe-family content assertions pass. Proof `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-201153` forged a tampered adopt receipt and got `verification-failed` / Soul `failed` / `mindAdoptionReview.status=failed`, then closed the original chain with Soul `passed`, `mindAdoptionReview.status=passed`, and `privateStateExposed=false`. Remaining closure work is deeper semantic review and durable repo-map admission, not proving the basic adoption chain again. +- 2026-06-20: The first durable repo-map admission slice is live. Successful `epiphany-work close` now writes `.epiphany/state/repo-work-map.msgpack` as typed MessagePack `epiphany.repo_work_map_store.v0`, replacing the item latest `epiphany.repo_work_map_entry.v0` only after Soul passes, Mind writes gateway/state-commit receipts, and closure remains branch-local/Bifrost-gated. Proof `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-202113` also proved the tampered failed close did not write the map, while the original close wrote a map entry with the expected commit SHA, changed path, safe family, Soul verdict id, Mind review/commit ids, `durableStateAdmitted=true`, and `privateStateExposed=false`. Remaining Phase 5 work is local Verse projection and richer semantic map lenses, not first map persistence. - 2026-06-20: Native repo-work queue-run service lifecycle proof is now landed. Smoke `.epiphany-smoke\repo-work-service-lifecycle-20260620-185853` proves Idunn can write non-mutating `service-plan` and `service-runbook` receipts for exact service id `epiphany-repo-work-queue-runner`, with service args including `queue-run --dry-run`, runbook SHA-256 `f2ec67c4f8243a3ebc2f9e915b6b9f5ae2ac2d99d2cdb86905b54667adc456f8`, receipt-directory `service-lifecycle` readback present, `lifecycleOwner=Idunn`, `hostedBody=repo-work`, `mutatesServiceManager=false`, `launchesService=false`, `requiresElevatedAuthority=false`, and `privateStateExposed=false`. The remaining scar is elevated install/start execution and complete aftercare audit under explicit operator authority, not basic plan/runbook proof. - 2026-06-20: The first repo Persona intake mouth is live. `epiphany-work persona-intake` requires a repo-swarm online receipt, records a Persona bubble/speech-audit witness into repo-local CultMesh, creates public discussion and candidate action refs, delegates to `accept`, and seals `work-persona-intake-.json` without Hands, durable-state, publication, service lifecycle, cross-repo, elevation, or private-state authority. Wrapper mode `tools/epiphany_local_run.ps1 -Mode repo-persona-intake -RepoWorkItem -PersonaInput ''` exposes the operator surface. Disposable proof `.epiphany-smoke\persona-intake-20260620-022500` wrote direct item `persona-request` with speech audit `persona-speech-audit-cdcd20a7`, feedback `repo-work-feedback-persona-request`, consensus `repo-work-consensus-persona-request`, and `privateStateExposed=false`; wrapper artifact `local-20260620-022551-566-5576908e` wrote item `persona-wrapper`, speech audit `persona-speech-audit-55f74218`, feedback `repo-work-feedback-persona-wrapper`, consensus `repo-work-consensus-persona-wrapper`, and candidate action `candidate-action://repo-swarm-local/persona-wrapper/persona-speech-audit-55f74218`. The next cut is deeper model-authored closure review, further non-planning action classes, or Idunn-owned queue-run service execution; not another intake/display surface. - 2026-06-20: Typed Imagination action-item receipts are live in `epiphany-work derive-plan`. The command now writes `work-action-items-.json` with schema `epiphany.repo_work_imagination_action_items_receipt.v0` before writing `work-plan-.json`; the receipt carries model provenance, safe action family, requested paths, verification asks, stop conditions, escalation reasons, rollback hints, public/candidate refs, `operatorAuthoredShellDetails=false`, and no Hands/durable-state/publication/service/cross-repo authority. The plan derivation cites the action-item receipt, while command text remains deterministic safe-family lowering. Disposable proof `.epiphany-smoke\action-items-20260620-023240` wrote action receipt `repo-work-action-items-action-items-request` with `modelAuthored=true`, `safeActionFamily=repo.markdown_planning_note`, requested path `notes/epiphany-work/action-items-request.md`, plan citation present, and `privateStateExposed=false`. The next cut is deeper model-authored closure review, further non-planning action classes, or Idunn-owned queue-run service execution; not another basic action-item schema. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 6d3a06dc..a65493f6 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index e8274ccc..4ad42e2e 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -634,5 +634,5 @@ current_status: - `tools/epiphany_local_run.ps1 -Mode swarm-online-runbook` now emits an explicit Idunn preflight summary before the operator elevation boundary. Its JSON and one-line summary report `preflightStatus`, child artifact present/hash-verified/mismatch/missing counts, aggregate service execution failed/missing check counts, child preflight rows with expected/actual SHA-256s, and private-state exposure. Live proof `local-20260619-025627-410-9724e2f6` generated the non-mutating parent artifact with `preflightStatus=ready-for-elevated-operator`, two child runbooks present, two hashes verified, zero mismatches, zero missing artifacts, eleven failed sealed service checks, zero missing checks, explicit aftercare audits, and `privateStateExposed=false`. The remaining scar is still explicit elevated operator execution followed by complete Idunn audits, not missing parent/child artifact readiness. - 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: Soul closure now verifies accepted Mind adoption proof before closing branch-local repo work. `epiphany-work close` embeds `epiphany.repo_work_mind_adoption_closure_review.v0`, checks the cited adoption receipt's embedded `epiphany.repo_work_mind_adoption_decision.v0` snapshot plus standalone decision receipt, and refuses missing/tampered/non-affirmative Mind decisions even when verification, path scope, and safe-family assertions pass. Proof `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-201153` showed counterfeit adoption produced `verification-failed` / Soul `failed` / `mindAdoptionReview.status=failed`, while the original chain closed with Soul `passed`, `mindAdoptionReview.status=passed`, and `privateStateExposed=false`. - next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. Typed Gjallar repo-work history/queue sight, peer-readable Persona Eve lowering, Self-owned `epiphany-work queue-run`, bounded `epiphany-swarm run`, execute-to-close scheduler handoff through `close-from-execute`, deterministic `derive-plan` families `append-worklog`, `planning-note`, `checklist-note`, `section-note` / `repo.markdown_managed_section`, `task-card` / `repo.task_card`, `repo-status-section` / `repo.status_section`, `repo-manifest` / `repo.body_manifest`, `repo-tool-capabilities` / `repo.tool_capabilities`, `repo-tool-request` / `repo.tool_request`, `repo-eve-surface` / `repo.eve_surface`, `repo-collaboration-policy` / `repo.collaboration_policy`, `repo-collaboration-topic` / `repo.collaboration_topic`, `repo-consensus-brief` / `repo.consensus_brief`, `repo-objective-draft` / `repo.objective_draft`, `repo-adoption-request` / `repo.adoption_request`, `repo-scheduling-request` / `repo.scheduling_request`, `repo-work-order` / `repo.work_order`, `repo-verification-request` / `repo.verification_request`, `repo-publication-request` / `repo.publication_request`, `repo-sync-request` / `repo.sync_request`, `repo-maintainer-review-request` / `repo.maintainer_review_request`, `repo-pr-request` / `repo.pr_request`, `repo-credit-request` / `repo.credit_request`, `repo-artifact-acceptance-request` / `repo.artifact_acceptance_request`, `repo-metrics-request` / `repo.metrics_request`, `repo-doctrine-update-request` / `repo.doctrine_update_request`, `repo-secret-policy-request` / `repo.secret_policy_request`, and `repo-deployment-request` / `repo.deployment_request`, typed Imagination action-item receipts over allowlisted safe families, `epiphany.repo_work_mind_interpretation.v0` plus `epiphany.repo_work_mind_adoption_decision.v0` Mind interpreter receipts, explicit safe-family allowlist refusal, explicit requested-path/plan-changed-path mismatch refusal, and Soul closure's Mind-adoption proof guard before branch-local Hands consequences reach publication gates, hash-backed local proof bundles with Bifrost/GitHub/credit/PR/upstream-main publication rows, redacted `epiphany-work export-proof` public bundles plus local Verse `epiphany.cultmesh.repo_work_public_proof.v0` Gjallar readback, Bifrost-owned `gamecult.bifrost.public_proof_publication_receipt.v0` closure plus wrapper `bifrost-public-proof` for redacted public proofs, Idunn-hosted non-mutating queue-run lifecycle plan/runbook receipts including native proof `.epiphany-smoke\repo-work-service-lifecycle-20260620-185853`, and the speech-audited `epiphany-work persona-intake` mouth plus wrapper `repo-persona-intake` are live with `privateStateExposed=false`; proofs `.epiphany-smoke\fresh-repo-mvp-20260620-180024`, `.epiphany-smoke\swarm-stop-classification-20260620-184717`, `.epiphany-smoke\repo-mind-safe-family-guard-20260620-194425`, `.epiphany-smoke\repo-mind-path-guard-20260620-194239`, `.epiphany-smoke\repo-doctrine-update-request-family-20260620-192140`, `.epiphany-smoke\repo-secret-policy-request-family-20260620-193046`, `.epiphany-smoke\repo-deployment-request-family-20260620-195605`, and `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-201153` show fresh-repo iteration-limit stop classification, empty-queue Gjallar classification, dry-run planning-preview Self classification, Bifrost publication-gate classification, Bifrost/GitHub upstream-sync gate classification, Mind refusal for unsupported safe-family cargo and mismatched requested paths, reviewed doctrine/security/deployment request cargo, closure refusal for counterfeit Mind adoption, closure, publication receipts, upstream-main sync, public-proof export, and private-state sealing. The contract note now explicitly answers that Epiphany is headed toward a functional repo swarm but is not fully online until the typed artery runs as a living repo organism. The next cut is deeper semantic review and durable repo-map admission, further useful repo-owned config/action request families, or explicit Idunn deployment execution/audit under operator authority. Preserve Idunn service lifecycle ownership and existing CultMesh/Odin/Eve tool directories; service install/start/deployment execution still requires explicit elevated operator authority. + last_completed_repo_swarm_cut: Successful repo-work closure now performs the first durable repo-map admission. `epiphany-work close` writes `.epiphany/state/repo-work-map.msgpack` as typed MessagePack `epiphany.repo_work_map_store.v0`, replacing the item's latest `epiphany.repo_work_map_entry.v0` only after Soul passes, Mind writes gateway/state-commit receipts, and closure remains branch-local/Bifrost-gated. Proof `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-202113` showed a counterfeit Mind-adoption close failed without writing the map, while the original chain wrote a map entry with expected commit SHA, changed path, safe family, Soul verdict id, Mind review/commit ids, `durableStateAdmitted=true`, and `privateStateExposed=false`. + next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. Typed Gjallar repo-work history/queue sight, peer-readable Persona Eve lowering, Self-owned `epiphany-work queue-run`, bounded `epiphany-swarm run`, execute-to-close scheduler handoff through `close-from-execute`, deterministic `derive-plan` families `append-worklog`, `planning-note`, `checklist-note`, `section-note` / `repo.markdown_managed_section`, `task-card` / `repo.task_card`, `repo-status-section` / `repo.status_section`, `repo-manifest` / `repo.body_manifest`, `repo-tool-capabilities` / `repo.tool_capabilities`, `repo-tool-request` / `repo.tool_request`, `repo-eve-surface` / `repo.eve_surface`, `repo-collaboration-policy` / `repo.collaboration_policy`, `repo-collaboration-topic` / `repo.collaboration_topic`, `repo-consensus-brief` / `repo.consensus_brief`, `repo-objective-draft` / `repo.objective_draft`, `repo-adoption-request` / `repo.adoption_request`, `repo-scheduling-request` / `repo.scheduling_request`, `repo-work-order` / `repo.work_order`, `repo-verification-request` / `repo.verification_request`, `repo-publication-request` / `repo.publication_request`, `repo-sync-request` / `repo.sync_request`, `repo-maintainer-review-request` / `repo.maintainer_review_request`, `repo-pr-request` / `repo.pr_request`, `repo-credit-request` / `repo.credit_request`, `repo-artifact-acceptance-request` / `repo.artifact_acceptance_request`, `repo-metrics-request` / `repo.metrics_request`, `repo-doctrine-update-request` / `repo.doctrine_update_request`, `repo-secret-policy-request` / `repo.secret_policy_request`, and `repo-deployment-request` / `repo.deployment_request`, typed Imagination action-item receipts over allowlisted safe families, `epiphany.repo_work_mind_interpretation.v0` plus `epiphany.repo_work_mind_adoption_decision.v0` Mind interpreter receipts, explicit safe-family allowlist refusal, explicit requested-path/plan-changed-path mismatch refusal, Soul closure's Mind-adoption proof guard, and durable repo-work map admission before branch-local Hands consequences reach publication gates, hash-backed local proof bundles with Bifrost/GitHub/credit/PR/upstream-main publication rows, redacted `epiphany-work export-proof` public bundles plus local Verse `epiphany.cultmesh.repo_work_public_proof.v0` Gjallar readback, Bifrost-owned `gamecult.bifrost.public_proof_publication_receipt.v0` closure plus wrapper `bifrost-public-proof` for redacted public proofs, Idunn-hosted non-mutating queue-run lifecycle plan/runbook receipts including native proof `.epiphany-smoke\repo-work-service-lifecycle-20260620-185853`, and the speech-audited `epiphany-work persona-intake` mouth plus wrapper `repo-persona-intake` are live with `privateStateExposed=false`; proofs `.epiphany-smoke\fresh-repo-mvp-20260620-180024`, `.epiphany-smoke\swarm-stop-classification-20260620-184717`, `.epiphany-smoke\repo-mind-safe-family-guard-20260620-194425`, `.epiphany-smoke\repo-mind-path-guard-20260620-194239`, `.epiphany-smoke\repo-doctrine-update-request-family-20260620-192140`, `.epiphany-smoke\repo-secret-policy-request-family-20260620-193046`, `.epiphany-smoke\repo-deployment-request-family-20260620-195605`, `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-201153`, and `.epiphany-smoke\repo-close-mind-adoption-guard-20260620-202113` show fresh-repo iteration-limit stop classification, empty-queue Gjallar classification, dry-run planning-preview Self classification, Bifrost publication-gate classification, Bifrost/GitHub upstream-sync gate classification, Mind refusal for unsupported safe-family cargo and mismatched requested paths, reviewed doctrine/security/deployment request cargo, closure refusal for counterfeit Mind adoption, durable repo-map admission only after passing closure, closure, publication receipts, upstream-main sync, public-proof export, and private-state sealing. The contract note now explicitly answers that Epiphany is headed toward a functional repo swarm but is not fully online until the typed artery runs as a living repo organism. The next cut is local Verse projection of the durable repo map, deeper semantic review/map lenses, further useful repo-owned config/action request families, or explicit Idunn deployment execution/audit under operator authority. Preserve Idunn service lifecycle ownership and existing CultMesh/Odin/Eve tool directories; service install/start/deployment execution still requires explicit elevated operator authority.