diff --git a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs b/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs deleted file mode 100644 index c82592fb..00000000 --- a/epiphany-core/src/bin/epiphany-repo-swarm-mvp-smoke.rs +++ /dev/null @@ -1,514 +0,0 @@ -use anyhow::Context; -use anyhow::Result; -use anyhow::anyhow; -use chrono::Utc; -use serde_json::Value; -use serde_json::json; -use std::env; -use std::fs; -use std::path::Path; -use std::path::PathBuf; -use std::process::Command; - -fn main() -> Result<()> { - let args = Args::parse()?; - let result = run_smoke(args)?; - println!("{}", serde_json::to_string_pretty(&result)?); - Ok(()) -} - -#[derive(Clone, Debug)] -struct Args { - root: PathBuf, - smoke_root: PathBuf, - keep: bool, -} - -impl Args { - fn parse() -> Result { - let mut root = env::current_dir().context("failed to resolve current directory")?; - let mut smoke_root = root.join(".epiphany-smoke"); - let mut keep = false; - let mut args = env::args().skip(1).peekable(); - while let Some(arg) = args.next() { - match arg.as_str() { - "--root" => root = take_path(&mut args, "--root")?, - "--smoke-root" => smoke_root = take_path(&mut args, "--smoke-root")?, - "--keep" => keep = true, - other => return Err(anyhow!("unexpected argument {other:?}")), - } - } - Ok(Self { - root, - smoke_root, - keep, - }) - } -} - -fn run_smoke(args: Args) -> Result { - let root = args - .root - .canonicalize() - .with_context(|| format!("failed to resolve {}", args.root.display()))?; - let manifest = root.join("epiphany-core").join("Cargo.toml"); - if !manifest.exists() { - return Err(anyhow!( - "could not find epiphany-core manifest at {}", - manifest.display() - )); - } - fs::create_dir_all(&args.smoke_root) - .with_context(|| format!("failed to create {}", args.smoke_root.display()))?; - let stamp = Utc::now().format("%Y%m%d-%H%M%S").to_string(); - let smoke_dir = args.smoke_root.join(format!("fresh-repo-mvp-{stamp}")); - if smoke_dir.exists() { - fs::remove_dir_all(&smoke_dir) - .with_context(|| format!("failed to clear {}", smoke_dir.display()))?; - } - fs::create_dir_all(&smoke_dir) - .with_context(|| format!("failed to create {}", smoke_dir.display()))?; - - let origin = smoke_dir.join("origin.git"); - let repo = smoke_dir.join("repo-body"); - git(["init", "--bare", path_str(&origin)?], &root)?; - git(["clone", path_str(&origin)?, path_str(&repo)?], &root)?; - git( - ["config", "user.email", "epiphany-smoke@example.invalid"], - &repo, - )?; - git(["config", "user.name", "Epiphany Smoke"], &repo)?; - git(["switch", "-c", "main"], &repo)?; - fs::write( - repo.join("README.md"), - "# Fresh Repo MVP Smoke\n\nThis repository starts empty enough for Epiphany to prove birth.\n", - ) - .with_context(|| format!("failed to seed {}", repo.join("README.md").display()))?; - git(["add", "README.md"], &repo)?; - git(["commit", "-m", "Seed fresh repo body"], &repo)?; - git(["push", "-u", "origin", "main"], &repo)?; - - let item = "fresh-repo-mvp"; - let runtime_id = "repo-swarm-fresh-mvp"; - let local_verse = repo.join(".epiphany").join("local-verse.ccmp"); - let init = cargo_json( - &manifest, - "epiphany-repo", - &[ - "init", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--swarm-id", - "fresh-repo-smoke", - "--topic", - "mvp-proof", - "--switch-branch", - ], - &root, - )?; - let online = cargo_json( - &manifest, - "epiphany-swarm", - &[ - "online", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--runtime-id", - runtime_id, - "--local-verse-store", - path_str(&local_verse)?, - ], - &root, - )?; - let intake = cargo_json( - &manifest, - "epiphany-work", - &[ - "persona-intake", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--runtime-id", - runtime_id, - "--item", - item, - "--message", - "Please prove this fresh repository can carry an Epiphany branch-local status update from Persona pressure to verified proof.", - "--topic", - "fresh-repo-mvp", - ], - &root, - )?; - let plan = cargo_json( - &manifest, - "epiphany-work", - &[ - "derive-plan", - "--workspace", - path_str(&repo)?, - "--item", - item, - "--action-family", - "repo-status-section", - "--model-ref", - "fresh-repo-mvp-smoke-imagination-v1", - "--model-authored", - ], - &root, - )?; - let pre_run_overview = cargo_json( - &manifest, - "epiphany-work", - &["overview", "--workspace", path_str(&repo)?, "--item", item], - &root, - )?; - let swarm_run = cargo_json( - &manifest, - "epiphany-swarm", - &[ - "run", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--runtime-id", - runtime_id, - "--local-verse-store", - path_str(&local_verse)?, - "--max-iterations", - "4", - "--max-items", - "1", - "--cooldown-seconds", - "0", - ], - &root, - )?; - let close_receipt = repo - .join(".epiphany") - .join("work") - .join(format!("work-close-{item}.json")); - let close = read_json(&close_receipt)?; - let publish = cargo_json( - &manifest, - "epiphany-work", - &[ - "publish", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--item", - item, - "--closure-receipt", - path_str(&close_receipt)?, - "--local-verse-store", - path_str(&local_verse)?, - "--change-summary", - "Fresh-repo MVP smoke branch-local status proof.", - "--justification", - "Disposable maintainer review for the native fresh-repo MVP smoke.", - "--ledger-entry-id", - "fresh-repo-mvp-smoke-ledger", - "--pull-request-url", - "https://example.invalid/GameCult/fresh-repo-mvp-smoke/pull/1", - "--pull-request-number", - "1", - "--pull-request-title", - "Fresh repo MVP smoke proof", - ], - &root, - )?; - - git(["push", "origin", "HEAD:main"], &repo)?; - git(["fetch", "origin", "main"], &repo)?; - let publish_receipt = repo - .join(".epiphany") - .join("work") - .join(format!("work-publish-{item}.json")); - let sync = cargo_json( - &manifest, - "epiphany-work", - &[ - "sync", - "--workspace", - path_str(&repo)?, - "--item", - item, - "--publish-receipt", - path_str(&publish_receipt)?, - "--upstream-ref", - "origin/main", - "--merge-receipt", - "maintainer-merge:fresh-repo-mvp-smoke", - ], - &root, - )?; - let overview = cargo_json( - &manifest, - "epiphany-work", - &["overview", "--workspace", path_str(&repo)?, "--item", item], - &root, - )?; - let export = cargo_json( - &manifest, - "epiphany-work", - &[ - "export-proof", - "--workspace", - path_str(&repo)?, - "--item", - item, - "--local-verse-store", - path_str(&local_verse)?, - "--runtime-id", - runtime_id, - ], - &root, - )?; - - require_eq(&close, &["status"], "closed")?; - require_eq(&close, &["soul", "verdict"], "passed")?; - require_eq( - &close, - &["closureReview", "familyAssertions", "status"], - "passed", - )?; - require_eq( - &swarm_run, - &["stopClassification", "schemaVersion"], - "epiphany.repo_swarm_run_stop_classification.v0", - )?; - require_eq( - &swarm_run, - &["stopClassification", "category"], - "iteration-limit", - )?; - require_eq(&swarm_run, &["stopClassification", "owner"], "Self")?; - require_eq( - &swarm_run, - &["stopClassification", "authorityGate"], - "self.scheduler-iteration-limit", - )?; - require_bool(&swarm_run, &["stopClassification", "mutatesState"], false)?; - require_bool( - &swarm_run, - &["stopClassification", "requiresElevatedAuthority"], - false, - )?; - require_bool( - &swarm_run, - &["stopClassification", "privateStateExposed"], - false, - )?; - require_eq(&publish, &["status"], "publication-receipts-recorded")?; - require_eq(&sync, &["status"], "upstream-main-synced")?; - require_eq(&export, &["status"], "public-proof-exported")?; - require_non_empty(&intake, &["memoryRecallStatus"])?; - require_non_empty(&intake, &["memoryRecallCacheStatus"])?; - require_non_empty(&intake, &["interpreterDynamicRecallStatus"])?; - require_non_empty(&intake, &["interpreterDynamicRecallCacheStatus"])?; - require_non_empty(&intake, &["weksaLoweringReceiptId"])?; - require_bool(&intake, &["privateStateExposed"], false)?; - require_bool(&overview, &["privateStateExposed"], false)?; - require_bool(&export, &["privateStateExposed"], false)?; - let close_private = close - .pointer("/authority/privateStateExposed") - .and_then(Value::as_bool) - .unwrap_or(false); - if close_private { - return Err(anyhow!("close receipt exposed private state")); - } - let commit_sha = close - .pointer("/handsReceipts/commitSha") - .and_then(Value::as_str) - .unwrap_or("unknown") - .to_string(); - let final_summary = json!({ - "schemaVersion": "epiphany.repo_swarm_fresh_repo_mvp_smoke.v0", - "status": "ok", - "smokeDir": smoke_dir, - "repo": repo, - "origin": origin, - "item": item, - "branch": git_output(["branch", "--show-current"], &repo)?, - "commitSha": commit_sha, - "initStatus": init["status"], - "onlineStatus": online["status"], - "personaIntakeStatus": intake["status"], - "personaMemoryRecallStatus": intake["memoryRecallStatus"], - "personaMemoryRecallCacheStatus": intake["memoryRecallCacheStatus"], - "personaMemoryRecallHitCount": intake["memoryRecallHitCount"], - "personaInterpreterDynamicRecallStatus": intake["interpreterDynamicRecallStatus"], - "personaInterpreterDynamicRecallCacheStatus": intake["interpreterDynamicRecallCacheStatus"], - "personaInterpreterDynamicRecallHitCount": intake["interpreterDynamicRecallHitCount"], - "weksaLoweringReceiptId": intake["weksaLoweringReceiptId"], - "planStatus": plan["status"], - "preRunOverviewGate": pre_run_overview["gate"], - "preRunOverviewBlocker": pre_run_overview["blocker"], - "swarmRunStatus": swarm_run["status"], - "swarmRunStopCategory": swarm_run["stopClassification"]["category"], - "swarmRunStopOwner": swarm_run["stopClassification"]["owner"], - "swarmRunStopGate": swarm_run["stopClassification"]["authorityGate"], - "closeStatus": close["status"], - "soulVerdict": close["soul"]["verdict"], - "familyAssertionsStatus": close["closureReview"]["familyAssertions"]["status"], - "publishStatus": publish["status"], - "syncStatus": sync["status"], - "upstreamMainSynced": sync["authority"]["upstreamMainSynced"], - "overviewGate": overview["gate"], - "overviewBlocker": overview["blocker"], - "publicProofStatus": export["status"], - "publicProofArtifact": export["outputPath"], - "privateStateExposed": false, - "kept": args.keep - }); - let summary_path = smoke_dir.join("summary.json"); - write_json(&summary_path, &final_summary)?; - Ok(final_summary) -} - -fn cargo_json(manifest: &Path, bin: &str, args: &[&str], cwd: &Path) -> Result { - let output = Command::new("cargo") - .arg("run") - .arg("--quiet") - .arg("--manifest-path") - .arg(manifest) - .arg("--bin") - .arg(bin) - .arg("--") - .args(args) - .current_dir(cwd) - .output() - .with_context(|| format!("failed to run cargo bin {bin}"))?; - if !output.status.success() { - return Err(anyhow!( - "{bin} failed with status {:?}\nstdout:\n{}\nstderr:\n{}", - output.status.code(), - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )); - } - serde_json::from_slice(&output.stdout).with_context(|| { - format!( - "{bin} did not emit JSON on stdout:\n{}", - String::from_utf8_lossy(&output.stdout) - ) - }) -} - -fn git(args: [&str; N], cwd: &Path) -> Result<()> { - let output = Command::new("git") - .args(args) - .current_dir(cwd) - .output() - .with_context(|| format!("failed to run git in {}", cwd.display()))?; - if output.status.success() { - Ok(()) - } else { - Err(anyhow!( - "git failed in {} with status {:?}\nstdout:\n{}\nstderr:\n{}", - cwd.display(), - output.status.code(), - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )) - } -} - -fn git_output(args: [&str; N], cwd: &Path) -> Result { - let output = Command::new("git") - .args(args) - .current_dir(cwd) - .output() - .with_context(|| format!("failed to run git in {}", cwd.display()))?; - if output.status.success() { - Ok(String::from_utf8_lossy(&output.stdout).trim().to_string()) - } else { - Err(anyhow!( - "git failed in {} with status {:?}\nstdout:\n{}\nstderr:\n{}", - cwd.display(), - output.status.code(), - String::from_utf8_lossy(&output.stdout), - String::from_utf8_lossy(&output.stderr) - )) - } -} - -fn read_json(path: &Path) -> Result { - let bytes = fs::read(path).with_context(|| format!("failed to read {}", path.display()))?; - serde_json::from_slice(&bytes).with_context(|| format!("failed to parse {}", path.display())) -} - -fn write_json(path: &Path, value: &Value) -> Result<()> { - if let Some(parent) = path.parent() { - fs::create_dir_all(parent) - .with_context(|| format!("failed to create {}", parent.display()))?; - } - fs::write(path, serde_json::to_vec_pretty(value)?) - .with_context(|| format!("failed to write {}", path.display())) -} - -fn require_eq(value: &Value, path: &[&str], expected: &str) -> Result<()> { - let actual = path - .iter() - .try_fold(value, |current, key| current.get(*key)) - .and_then(Value::as_str) - .unwrap_or(""); - if actual == expected { - Ok(()) - } else { - Err(anyhow!( - "expected {} to be {expected:?}, got {actual:?}", - path.join(".") - )) - } -} - -fn require_bool(value: &Value, path: &[&str], expected: bool) -> Result<()> { - let actual = path - .iter() - .try_fold(value, |current, key| current.get(*key)) - .and_then(Value::as_bool); - if actual == Some(expected) { - Ok(()) - } else { - Err(anyhow!( - "expected {} to be {expected}, got {:?}", - path.join("."), - actual - )) - } -} - -fn require_non_empty(value: &Value, path: &[&str]) -> Result<()> { - let actual = path - .iter() - .try_fold(value, |current, key| current.get(*key)) - .and_then(Value::as_str) - .unwrap_or_default(); - if actual.trim().is_empty() { - Err(anyhow!("expected {} to be non-empty", path.join("."))) - } else { - Ok(()) - } -} - -fn take_path( - args: &mut std::iter::Peekable>, - flag: &str, -) -> Result { - args.next() - .map(PathBuf::from) - .with_context(|| format!("missing value for {flag}")) -} - -fn path_str(path: &Path) -> Result<&str> { - path.to_str() - .ok_or_else(|| anyhow!("path is not valid UTF-8: {}", path.display())) -} diff --git a/notes/conceptual-substitution-audit-2026-07-12.md b/notes/conceptual-substitution-audit-2026-07-12.md index 26fd5d63..2b3d74c4 100644 --- a/notes/conceptual-substitution-audit-2026-07-12.md +++ b/notes/conceptual-substitution-audit-2026-07-12.md @@ -319,3 +319,12 @@ The aggregate gate binary, wrapper mode, summary-path inputs, build target, and display projection are deleted. Focused contract tests remain useful, and live fire remains the proper whole-path evidence layer. A pile of green fixture summaries is not a system readiness owner. + +## Fresh-repo smoke as external governance + +`epiphany-repo-swarm-mvp-smoke` performed real disposable Git operations, but +also supplied its own `example.invalid` pull request, maintainer-review prose, +and merge-receipt string. It then asserted Bifrost publication, Soul approval, +and upstream publication as one integrated proof. Git can prove ancestry; it +cannot impersonate the absent publisher, reviewer, or verification organ. The +binary and its live-proof claims are deleted. diff --git a/notes/epiphany-investor-readiness-roadmap.md b/notes/epiphany-investor-readiness-roadmap.md index 18ad28be..f460f2f3 100644 --- a/notes/epiphany-investor-readiness-roadmap.md +++ b/notes/epiphany-investor-readiness-roadmap.md @@ -58,13 +58,10 @@ Every investor-scale Objective Draft should answer: ## Roadmap Shape -1. Fresh-repo Epiphany proof: the native - `epiphany-repo-swarm-mvp-smoke` now demonstrates Persona entry, - Bifrost-linked publication receipts, bounded repo-swarm routing, artifact - production, review, upstream-main sync proof, and sealed operator-safe - evidence on a disposable fresh repo. Keep it repeatable and move the same - loop toward an external or semi-external repo after Bifrost owns the work - item bridge. +1. Fresh-repo Epiphany proof: repo-swarm substrate tests may demonstrate local + Persona entry, bounded routing, artifact production, and Git ancestry. A + genuine Bifrost body and reviewer must supply publication and review proof; + local fixture strings are not substitutes for those authorities. 2. Bifrost-first private alpha: all external swarm work exists as Bifrost topics/work items/bridge receipts/credit, with Bifrost identity and Heimdall-backed outside-account capability references where needed, before diff --git a/notes/epiphany-repo-swarm-mvp-contract.md b/notes/epiphany-repo-swarm-mvp-contract.md index b8b68d03..641d515e 100644 --- a/notes/epiphany-repo-swarm-mvp-contract.md +++ b/notes/epiphany-repo-swarm-mvp-contract.md @@ -2615,12 +2615,12 @@ This is the difference between a demo and a repo swarm: the human talks to the project, the project forms a plan, the branch work happens inside its owned Body, and the proof bundle tells the truth without leaking the private mind. -### Native Fresh Repo MVP Smoke +### Retired Fresh Repo MVP Smoke -The first repeatable Phase 7 proof is now native: +This former proof is retired and its binary deleted: ```powershell -cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-repo-swarm-mvp-smoke +epiphany-repo-swarm-mvp-smoke (deleted) ``` The smoke creates a disposable bare `origin.git`, clones a fresh repo Body, @@ -2647,9 +2647,10 @@ Disposable proof `.epiphany-smoke\fresh-repo-mvp-20260620-133452` reported `familyAssertions.status=passed`, `publishStatus=publication-receipts-recorded`, `syncStatus=upstream-main-synced`, `upstreamMainSynced=true`, `publicProofStatus=public-proof-exported`, and `privateStateExposed=false`. -This proves the operator-facing fresh-repo artery from Persona pressure to -Bifrost publication receipts, upstream-main ancestry proof, and redacted public -proof export without supervisor edits inside the target repo Body. +The Git operations proved local ancestry, but the same smoke supplied an +`example.invalid` pull request, maintainer-review prose, and a synthetic merge +receipt. It therefore could not prove Bifrost publication, external review, or +Soul authority. Keep the record only as rejected historical evidence. ### Phase 0: Authority Freeze diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index a3497865..9d37281c 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -73,6 +73,9 @@ The confirmed conceptual substitutions have been cut: - the aggregate repo-swarm MVP gate and wrapper are deleted. It painted green rows from prior smoke summaries and local fixtures rather than exercising one live end-to-end organism. Use focused tests plus live-fire evidence instead. +- the fresh-repo MVP smoke is deleted. Its disposable Git operations were real, + but its PR, maintainer-review, merge, Bifrost, and Soul evidence was supplied + by the same local caller rather than those owning bodies. The presentation boundary is now plain: `swarm overview` is a generic compact read-only projection. Gjallar is a downstream TUI application on Nightwing and is not an Epiphany organ, provider, owner, runtime, or architectural dependency. Eve/CultUI graphs may be lowered or composited downstream without Epiphany caring which presentation client does it. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 6dfe679b..ac001dc5 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 95946761..8e919f08 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -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. Inventory production projections, caches, adapters, schedulers, coordinators, and compatibility surfaces that assert facts owned elsewhere; map owner, inputs, outputs, forbidden writers, and negative proof before cutting. Audit remaining non-receipt smoke binaries for path escape or destructive scope. + next_action: Continue the conceptual-substitution modeling pass beyond receipt writers. The fresh-repo MVP smoke is deleted because it wrapped real disposable Git operations in caller-authored PR, review, merge, Bifrost, and Soul authority. Inventory remaining production projections, caches, adapters, schedulers, coordinators, and compatibility surfaces that assert facts owned elsewhere; map owner, inputs, outputs, forbidden writers, and negative proof before cutting. Audit remaining non-receipt smoke binaries for path escape or destructive scope.