From 57e73cb7744ab8e65aba7822f0ead24b6c82116a Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Sun, 12 Jul 2026 23:08:25 +0100 Subject: [PATCH] Delete caller-authored publication authority --- ...piphany-swarm-stop-classification-smoke.rs | 628 ---------------- epiphany-core/src/bin/epiphany-swarm.rs | 4 +- epiphany-core/src/bin/epiphany-work.rs | 680 +----------------- ...onceptual-substitution-audit-2026-07-12.md | 12 + notes/fresh-workspace-handoff.md | 4 + state/ledgers.msgpack | Bin 443380 -> 443847 bytes state/map.yaml | 2 +- 7 files changed, 29 insertions(+), 1301 deletions(-) delete mode 100644 epiphany-core/src/bin/epiphany-swarm-stop-classification-smoke.rs diff --git a/epiphany-core/src/bin/epiphany-swarm-stop-classification-smoke.rs b/epiphany-core/src/bin/epiphany-swarm-stop-classification-smoke.rs deleted file mode 100644 index 8dadf0cd..00000000 --- a/epiphany-core/src/bin/epiphany-swarm-stop-classification-smoke.rs +++ /dev/null @@ -1,628 +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, -} - -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 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")?, - other => return Err(anyhow!("unexpected argument {other:?}")), - } - } - Ok(Self { root, smoke_root }) - } -} - -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!("swarm-stop-classification-{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"); - git(["init", "--bare", path_str(&origin)?], &smoke_dir)?; - - let repo = smoke_dir.join("repo-body"); - fs::create_dir_all(&repo).with_context(|| format!("failed to create {}", repo.display()))?; - git(["init"], &repo)?; - git( - ["config", "user.email", "epiphany-smoke@example.invalid"], - &repo, - )?; - git(["config", "user.name", "Epiphany Smoke"], &repo)?; - fs::write( - repo.join("README.md"), - "# Swarm Stop Classification Smoke\n\nThis repository proves typed repo-swarm run stop classification.\n", - ) - .with_context(|| format!("failed to seed {}", repo.join("README.md").display()))?; - git(["add", "README.md"], &repo)?; - git( - ["commit", "-m", "Seed swarm stop classification smoke"], - &repo, - )?; - git(["branch", "-M", "main"], &repo)?; - git(["remote", "add", "origin", path_str(&origin)?], &repo)?; - git(["push", "-u", "origin", "main"], &repo)?; - - let runtime_id = "swarm-stop-classification-smoke"; - let local_verse = repo.join(".epiphany").join("local-verse.ccmp"); - cargo_json( - &manifest, - "epiphany-repo", - &[ - "init", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--swarm-id", - runtime_id, - "--topic", - "swarm-stop-classification", - ], - &root, - )?; - 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 empty_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", - "1", - "--max-items", - "1", - "--cooldown-seconds", - "0", - ], - &root, - )?; - require_eq( - &empty_run, - &["stopClassification", "schemaVersion"], - "epiphany.repo_swarm_run_stop_classification.v0", - )?; - require_eq( - &empty_run, - &["stopClassification", "category"], - "queue-empty", - )?; - require_eq(&empty_run, &["stopClassification", "owner"], "Self")?; - require_eq( - &empty_run, - &["stopClassification", "authorityGate"], - "repo.work.overview", - )?; - require_eq( - &empty_run, - &["stopClassification", "blocker"], - "no-repo-work-rows", - )?; - require_bool(&empty_run, &["stopClassification", "mutatesState"], false)?; - require_bool( - &empty_run, - &["stopClassification", "requiresElevatedAuthority"], - false, - )?; - require_bool( - &empty_run, - &["stopClassification", "privateStateExposed"], - false, - )?; - - let item = "gate-proof"; - cargo_json( - &manifest, - "epiphany-work", - &[ - "persona-intake", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--runtime-id", - runtime_id, - "--item", - item, - "--message", - "Prove a dry-run swarm pulse can classify a ready-to-run queue row without mutation.", - "--topic", - "swarm-stop-classification", - ], - &root, - )?; - cargo_json( - &manifest, - "epiphany-work", - &[ - "derive-plan", - "--workspace", - path_str(&repo)?, - "--item", - item, - "--action-family", - "repo-status-section", - "--model-ref", - "swarm-stop-classification-smoke-imagination-v1", - "--model-authored", - ], - &root, - )?; - cargo_json( - &manifest, - "epiphany-work", - &["overview", "--workspace", path_str(&repo)?, "--item", item], - &root, - )?; - let dry_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", - "1", - "--max-items", - "1", - "--cooldown-seconds", - "0", - "--dry-run", - ], - &root, - )?; - require_eq( - &dry_run, - &["stopClassification", "schemaVersion"], - "epiphany.repo_swarm_run_stop_classification.v0", - )?; - require_eq( - &dry_run, - &["stopClassification", "category"], - "dry-run-preview", - )?; - require_eq(&dry_run, &["stopClassification", "owner"], "Self")?; - require_eq( - &dry_run, - &["stopClassification", "authorityGate"], - "ready-to-run", - )?; - require_eq(&dry_run, &["stopClassification", "selectedItem"], item)?; - require_bool(&dry_run, &["stopClassification", "mutatesState"], false)?; - require_bool( - &dry_run, - &["stopClassification", "requiresElevatedAuthority"], - false, - )?; - require_bool( - &dry_run, - &["stopClassification", "privateStateExposed"], - false, - )?; - - git( - [ - "checkout", - "-B", - "epiphany/swarm-stop-classification/gate-proof", - ], - &repo, - )?; - let publication_pipeline = 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, - )?; - require_eq( - &publication_pipeline, - &["stopClassification", "category"], - "iteration-limit", - )?; - let publication_gate_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", - "1", - "--max-items", - "1", - "--cooldown-seconds", - "0", - ], - &root, - )?; - require_eq( - &publication_gate_run, - &["stopClassification", "category"], - "authority-gated", - )?; - require_eq( - &publication_gate_run, - &["stopClassification", "owner"], - "Bifrost", - )?; - require_eq( - &publication_gate_run, - &["stopClassification", "authorityGate"], - "awaiting-publication", - )?; - require_eq( - &publication_gate_run, - &["stopClassification", "blocker"], - "bifrost-publication-missing", - )?; - require_bool( - &publication_gate_run, - &["stopClassification", "mutatesState"], - false, - )?; - require_bool( - &publication_gate_run, - &["stopClassification", "requiresElevatedAuthority"], - false, - )?; - require_bool( - &publication_gate_run, - &["stopClassification", "privateStateExposed"], - false, - )?; - - let closure_receipt = repo - .join(".epiphany") - .join("work") - .join(format!("work-close-{item}.json")); - let publish = cargo_json( - &manifest, - "epiphany-work", - &[ - "publish", - "--workspace", - path_str(&repo)?, - "--epiphany-root", - path_str(&root)?, - "--item", - item, - "--closure-receipt", - path_str(&closure_receipt)?, - "--local-verse-store", - path_str(&local_verse)?, - "--change-summary", - "Swarm stop classification publication gate proof.", - "--justification", - "Disposable Bifrost proof for gated repo-swarm stop classification.", - "--ledger-entry-id", - "swarm-stop-classification-publication-ledger", - "--pull-request-url", - "https://example.invalid/GameCult/swarm-stop-classification/pull/1", - "--pull-request-number", - "1", - "--pull-request-title", - "Swarm stop classification publication gate proof", - ], - &root, - )?; - require_eq(&publish, &["status"], "publication-receipts-recorded")?; - cargo_json( - &manifest, - "epiphany-work", - &["overview", "--workspace", path_str(&repo)?, "--item", item], - &root, - )?; - let sync_gate_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", - "1", - "--max-items", - "1", - "--cooldown-seconds", - "0", - ], - &root, - )?; - require_eq( - &sync_gate_run, - &["stopClassification", "category"], - "authority-gated", - )?; - require_eq( - &sync_gate_run, - &["stopClassification", "owner"], - "Bifrost/GitHub", - )?; - require_eq( - &sync_gate_run, - &["stopClassification", "authorityGate"], - "awaiting-upstream-sync", - )?; - require_eq( - &sync_gate_run, - &["stopClassification", "blocker"], - "merge-or-sync-receipt-missing", - )?; - require_bool( - &sync_gate_run, - &["stopClassification", "mutatesState"], - false, - )?; - require_bool( - &sync_gate_run, - &["stopClassification", "requiresElevatedAuthority"], - false, - )?; - require_bool( - &sync_gate_run, - &["stopClassification", "privateStateExposed"], - false, - )?; - - 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:swarm-stop-classification-smoke", - ], - &root, - )?; - require_eq(&sync, &["status"], "upstream-main-synced")?; - - let summary = json!({ - "schemaVersion": "epiphany.repo_swarm_stop_classification_smoke.v0", - "status": "ok", - "smokeDir": smoke_dir, - "repo": repo, - "origin": origin, - "emptyStopCategory": empty_run["stopClassification"]["category"], - "emptyStopOwner": empty_run["stopClassification"]["owner"], - "emptyStopGate": empty_run["stopClassification"]["authorityGate"], - "dryRunStopCategory": dry_run["stopClassification"]["category"], - "dryRunStopOwner": dry_run["stopClassification"]["owner"], - "dryRunStopGate": dry_run["stopClassification"]["authorityGate"], - "dryRunSelectedItem": dry_run["stopClassification"]["selectedItem"], - "publicationStopCategory": publication_gate_run["stopClassification"]["category"], - "publicationStopOwner": publication_gate_run["stopClassification"]["owner"], - "publicationStopGate": publication_gate_run["stopClassification"]["authorityGate"], - "publicationStopBlocker": publication_gate_run["stopClassification"]["blocker"], - "syncStopCategory": sync_gate_run["stopClassification"]["category"], - "syncStopOwner": sync_gate_run["stopClassification"]["owner"], - "syncStopGate": sync_gate_run["stopClassification"]["authorityGate"], - "syncStopBlocker": sync_gate_run["stopClassification"]["blocker"], - "syncStatus": sync["status"], - "upstreamMainSynced": sync["authority"]["upstreamMainSynced"], - "mutatesState": false, - "requiresElevatedAuthority": false, - "privateStateExposed": false, - }); - write_json(&smoke_dir.join("summary.json"), &summary)?; - Ok(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 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 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/epiphany-core/src/bin/epiphany-swarm.rs b/epiphany-core/src/bin/epiphany-swarm.rs index f640c20b..4ed91259 100644 --- a/epiphany-core/src/bin/epiphany-swarm.rs +++ b/epiphany-core/src/bin/epiphany-swarm.rs @@ -630,10 +630,10 @@ fn classify_run_stop( }; let recommended = match selected_gate.as_str() { "awaiting-publication" => { - "epiphany-work publish --workspace --closure-receipt " + "submit a Bifrost publication intent through the owning integration" } "awaiting-sync" | "awaiting-upstream-sync" => { - "epiphany-work sync --workspace --publish-receipt " + "inspect provider-authored publication and upstream Git ancestry evidence" } "awaiting-closure" => { "epiphany-work close --workspace --execute-receipt " diff --git a/epiphany-core/src/bin/epiphany-work.rs b/epiphany-core/src/bin/epiphany-work.rs index 8d66ac1c..c7304773 100644 --- a/epiphany-core/src/bin/epiphany-work.rs +++ b/epiphany-core/src/bin/epiphany-work.rs @@ -21,7 +21,6 @@ use epiphany_core::HANDS_ACTION_INTENT_SCHEMA_VERSION; use epiphany_core::HANDS_COMMAND_RECEIPT_TYPE; use epiphany_core::HANDS_COMMIT_RECEIPT_TYPE; use epiphany_core::HANDS_PATCH_RECEIPT_TYPE; -use epiphany_core::HANDS_PR_RECEIPT_TYPE; use epiphany_core::HandsActionIntent; use epiphany_core::MIND_GATEWAY_REVIEW_SCHEMA_VERSION; use epiphany_core::MindGatewayDecision; @@ -54,7 +53,6 @@ use epiphany_core::hands_action_review_for_intent; use epiphany_core::hands_command_receipt_for_review; use epiphany_core::hands_commit_receipt_for_review; use epiphany_core::hands_patch_receipt_for_review; -use epiphany_core::hands_pr_receipt_for_review; use epiphany_core::initialize_runtime_spine; use epiphany_core::load_agent_memory_entry_for_role; use epiphany_core::load_epiphany_cultmesh_idunn_aftercare_audit_receipt; @@ -75,7 +73,6 @@ use epiphany_core::put_hands_action_review; use epiphany_core::put_hands_command_receipt; use epiphany_core::put_hands_commit_receipt; use epiphany_core::put_hands_patch_receipt; -use epiphany_core::put_hands_pr_receipt; use epiphany_core::put_soul_verdict_receipt; use epiphany_core::put_substrate_gate_repo_access_grant_receipt; use epiphany_core::record_weksa_target_lowering_receipt; @@ -84,7 +81,6 @@ use epiphany_core::runtime_hands_action_intent; use epiphany_core::runtime_hands_action_review; use epiphany_core::runtime_hands_commit_receipt; use epiphany_core::runtime_job_snapshot; -use epiphany_core::runtime_latest_hands_receipt_chain_after; use epiphany_core::runtime_repo_work_map_entry; use epiphany_core::runtime_repo_work_modeling_finding; use epiphany_core::runtime_repo_work_modeling_request; @@ -129,8 +125,6 @@ fn main() -> Result<()> { "revise-modeling" | "modeling-retry" => { run_revise_modeling(parse_revise_modeling_args(args)?) } - "publish" => run_publish(parse_publish_args(args)?), - "sync" | "sync-main" => run_sync(parse_sync_args(args)?), "overview" | "proof-bundle" | "status" => run_overview(parse_overview_args(args)?), "readiness" | "readiness-report" | "mvp-readiness" => { run_readiness(parse_readiness_args(args)?) @@ -313,43 +307,6 @@ enum ClosurePhase { Full, } -#[derive(Clone, Debug)] -struct PublishArgs { - workspace: PathBuf, - epiphany_root: PathBuf, - item: Option, - adopt_receipt: Option, - closure_receipt: Option, - runtime_store: Option, - local_verse_store: Option, - artifact_dir: Option, - commit_receipt_id: Option, - hands_pr_receipt_id: Option, - target_branch: Option, - change_summary: String, - justification: String, - verification_receipts: Vec, - review_receipts: Vec, - author_agents: Vec, - credit_subjects: Vec, - credit_receipt_ids: Option>, - ledger_entry_id: String, - pull_request_url: String, - pull_request_number: String, - pull_request_title: String, - publication_status: String, -} - -#[derive(Clone, Debug)] -struct SyncArgs { - workspace: PathBuf, - item: Option, - publish_receipt: Option, - artifact_dir: Option, - upstream_ref: String, - merge_receipts: Vec, -} - #[derive(Clone, Debug)] struct OverviewArgs { workspace: PathBuf, @@ -981,192 +938,6 @@ fn parse_revise_modeling_args(args: impl Iterator) -> Result) -> Result { - let mut workspace = None; - let mut epiphany_root = None; - let mut item = None; - let mut adopt_receipt = None; - let mut closure_receipt = None; - let mut runtime_store = None; - let mut local_verse_store = None; - let mut artifact_dir = None; - let mut commit_receipt_id = None; - let mut hands_pr_receipt_id = None; - let mut target_branch = None; - let mut change_summary = None; - let mut justification = None; - let mut verification_receipts = Vec::new(); - let mut review_receipts = Vec::new(); - let mut author_agents = Vec::new(); - let mut credit_subjects = Vec::new(); - let mut credit_receipt_ids = Vec::new(); - let mut ledger_entry_id = None; - let mut pull_request_url = None; - let mut pull_request_number = None; - let mut pull_request_title = None; - let mut publication_status = None; - - let mut args = args.peekable(); - while let Some(arg) = args.next() { - match arg.as_str() { - "--workspace" => workspace = Some(take_path(&mut args, "--workspace")?), - "--epiphany-root" => epiphany_root = Some(take_path(&mut args, "--epiphany-root")?), - "--item" => item = Some(take_string(&mut args, "--item")?), - "--adopt-receipt" => adopt_receipt = Some(take_path(&mut args, "--adopt-receipt")?), - "--closure-receipt" | "--close-receipt" => { - closure_receipt = Some(take_path(&mut args, "--closure-receipt")?); - } - "--runtime-store" => runtime_store = Some(take_path(&mut args, "--runtime-store")?), - "--local-verse-store" | "--store" => { - local_verse_store = Some(take_path(&mut args, "--local-verse-store")?); - } - "--artifact-dir" => artifact_dir = Some(take_path(&mut args, "--artifact-dir")?), - "--commit-receipt-id" => { - commit_receipt_id = Some(take_string(&mut args, "--commit-receipt-id")?); - } - "--hands-pr-receipt-id" => { - hands_pr_receipt_id = Some(take_string(&mut args, "--hands-pr-receipt-id")?); - } - "--target-branch" => target_branch = Some(take_string(&mut args, "--target-branch")?), - "--change-summary" => { - change_summary = Some(take_string(&mut args, "--change-summary")?) - } - "--justification" => justification = Some(take_string(&mut args, "--justification")?), - "--verification-receipt" | "--soul-receipt" => { - verification_receipts.push(take_string(&mut args, "--verification-receipt")?); - } - "--review-receipt" | "--mind-review-receipt" => { - review_receipts.push(take_string(&mut args, "--review-receipt")?); - } - "--author-agent" => author_agents.push(take_string(&mut args, "--author-agent")?), - "--credit-subject" => credit_subjects.push(take_string(&mut args, "--credit-subject")?), - "--credit-receipt-id" => { - credit_receipt_ids.push(take_string(&mut args, "--credit-receipt-id")?); - } - "--ledger-entry-id" => { - ledger_entry_id = Some(take_string(&mut args, "--ledger-entry-id")?); - } - "--pull-request-url" | "--publication-url" => { - pull_request_url = Some(take_string(&mut args, "--pull-request-url")?); - } - "--pull-request-number" => { - pull_request_number = Some(take_string(&mut args, "--pull-request-number")?); - } - "--pull-request-title" => { - pull_request_title = Some(take_string(&mut args, "--pull-request-title")?); - } - "--publication-status" => { - publication_status = Some(take_string(&mut args, "--publication-status")?); - } - other => return Err(anyhow!("unexpected publish argument {other:?}")), - } - } - if let Some(path) = closure_receipt.as_ref() { - let closure = read_json(path)?; - if closure.get("status").and_then(Value::as_str) != Some("closed") { - return Err(anyhow!("closure receipt {} is not closed", path.display())); - } - if verification_receipts.is_empty() { - if let Some(id) = string_from_json(&closure, &["soul", "verdictReceiptId"]) { - verification_receipts.push(id); - } - } - if review_receipts.is_empty() { - if let Some(id) = string_from_json(&closure, &["mind", "stateCommitReceiptId"]) { - review_receipts.push(id); - } - } - } - if verification_receipts.is_empty() { - return Err(anyhow!( - "publish requires at least one --verification-receipt from Soul" - )); - } - if review_receipts.is_empty() { - return Err(anyhow!( - "publish requires at least one --review-receipt from Mind or maintainer review" - )); - } - Ok(PublishArgs { - workspace: workspace.context("missing --workspace")?, - epiphany_root: epiphany_root - .unwrap_or(env::current_dir().context("failed to resolve current directory")?), - item, - adopt_receipt, - closure_receipt, - runtime_store, - local_verse_store, - artifact_dir, - commit_receipt_id, - hands_pr_receipt_id, - target_branch, - change_summary: change_summary.context("missing --change-summary")?, - justification: justification.context("missing --justification")?, - verification_receipts, - review_receipts, - author_agents: if author_agents.is_empty() { - vec!["epiphany.Hands".to_string()] - } else { - author_agents - }, - credit_subjects: if credit_subjects.is_empty() { - vec!["epiphany.Hands".to_string()] - } else { - credit_subjects - }, - credit_receipt_ids: if credit_receipt_ids.is_empty() { - None - } else { - Some(credit_receipt_ids) - }, - ledger_entry_id: ledger_entry_id.context("missing --ledger-entry-id")?, - pull_request_url: pull_request_url.context("missing --pull-request-url")?, - pull_request_number: pull_request_number.unwrap_or_else(|| "unknown".to_string()), - pull_request_title: pull_request_title.context("missing --pull-request-title")?, - publication_status: publication_status - .unwrap_or_else(|| "accepted-for-github-publication".to_string()), - }) -} - -fn parse_sync_args(args: impl Iterator) -> Result { - let mut workspace = None; - let mut item = None; - let mut publish_receipt = None; - let mut artifact_dir = None; - let mut upstream_ref = None; - let mut merge_receipts = Vec::new(); - - let mut args = args.peekable(); - while let Some(arg) = args.next() { - match arg.as_str() { - "--workspace" => workspace = Some(take_path(&mut args, "--workspace")?), - "--item" => item = Some(take_string(&mut args, "--item")?), - "--publish-receipt" => { - publish_receipt = Some(take_path(&mut args, "--publish-receipt")?); - } - "--artifact-dir" => artifact_dir = Some(take_path(&mut args, "--artifact-dir")?), - "--upstream-ref" => upstream_ref = Some(take_string(&mut args, "--upstream-ref")?), - "--merge-receipt" | "--sync-receipt" => { - merge_receipts.push(take_string(&mut args, "--merge-receipt")?); - } - other => return Err(anyhow!("unexpected sync argument {other:?}")), - } - } - if merge_receipts.is_empty() { - return Err(anyhow!( - "sync requires at least one --merge-receipt or --sync-receipt from Bifrost or maintainer review" - )); - } - Ok(SyncArgs { - workspace: workspace.context("missing --workspace")?, - item, - publish_receipt, - artifact_dir, - upstream_ref: upstream_ref.unwrap_or_else(|| "origin/main".to_string()), - merge_receipts, - }) -} - fn parse_overview_args(args: impl Iterator) -> Result { let mut workspace = None; let mut item = None; @@ -11122,7 +10893,7 @@ fn run_execute(args: ExecuteArgs) -> Result { "privateStateExposed": false }, "privateStateExposed": false, - "nextSafeMove": "Route Soul verification and Mind review before publication; use epiphany-work publish only after review receipts exist." + "nextSafeMove": "Route Soul verification and Mind review, then submit a Bifrost publication intent through the owning integration." }); let receipt_path = artifact_dir.join(format!("work-execute-{item_slug}.json")); write_json(&receipt_path, &execute_receipt)?; @@ -11869,7 +11640,7 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { "privateStateExposed": false }, "privateStateExposed": false, - "nextSafeMove": "Use epiphany-work publish --closure-receipt with Bifrost/GitHub refs; merge remains gated by maintainers and sync receipts." + "nextSafeMove": "Submit a Bifrost publication intent through the owning integration; merge remains gated by provider-authored maintainer evidence." }); write_json(&closure_receipt_path, &closure_receipt)?; Ok(json!({ @@ -11890,416 +11661,6 @@ fn run_closure_pipeline(args: CloseArgs, phase: ClosurePhase) -> Result { })) } -fn run_publish(args: PublishArgs) -> Result { - let workspace = args - .workspace - .canonicalize() - .with_context(|| format!("failed to resolve {}", args.workspace.display()))?; - ensure_git_repo(&workspace)?; - let epiphany_root = args - .epiphany_root - .canonicalize() - .with_context(|| format!("failed to resolve {}", args.epiphany_root.display()))?; - let manifest_path = epiphany_root.join("epiphany-core").join("Cargo.toml"); - if !manifest_path.exists() { - return Err(anyhow!( - "could not find epiphany-core manifest at {}", - manifest_path.display() - )); - } - let adopt_receipt_path = - resolve_adopt_receipt(&workspace, args.item.as_deref(), args.adopt_receipt)?; - let adopt_receipt = read_json(&adopt_receipt_path)?; - let run_receipt_path = path_from_json(&adopt_receipt, &["runReceiptPath"]) - .ok_or_else(|| anyhow!("adopt receipt has no runReceiptPath"))?; - let run_receipt = read_json(&run_receipt_path)?; - let online_receipt_path = path_from_json(&run_receipt, &["onlineReceiptPath"]) - .ok_or_else(|| anyhow!("run receipt has no onlineReceiptPath"))?; - let online_receipt = read_json(&online_receipt_path)?; - let runtime_id = string_from_json(&adopt_receipt, &["runtimeId"]) - .or_else(|| string_from_json(&run_receipt, &["runtimeId"])) - .or_else(|| string_from_json(&online_receipt, &["runtimeId"])) - .unwrap_or_else(|| "repo-swarm-local".to_string()); - let runtime_store = args.runtime_store.unwrap_or_else(|| { - path_from_json(&adopt_receipt, &["runtimeStore"]).unwrap_or_else(|| { - workspace - .join(".epiphany") - .join("state") - .join("runtime-spine.msgpack") - }) - }); - let local_verse_store = args.local_verse_store.unwrap_or_else(|| { - path_from_json(&online_receipt, &["localVerseStore"]) - .unwrap_or_else(|| workspace.join(".epiphany").join("local-verse.ccmp")) - }); - let artifact_dir = args - .artifact_dir - .unwrap_or_else(|| workspace.join(".epiphany").join("work")); - fs::create_dir_all(&artifact_dir) - .with_context(|| format!("failed to create {}", artifact_dir.display()))?; - - let gate = adopt_receipt - .get("handsActionGate") - .ok_or_else(|| anyhow!("adopt receipt has no handsActionGate"))?; - let intent_id = gate - .get("intentId") - .and_then(Value::as_str) - .ok_or_else(|| anyhow!("adopt receipt handsActionGate has no intentId"))?; - let review_id = gate - .get("reviewId") - .and_then(Value::as_str) - .ok_or_else(|| anyhow!("adopt receipt handsActionGate has no reviewId"))?; - let intent = runtime_hands_action_intent(&runtime_store, intent_id)? - .ok_or_else(|| anyhow!("runtime-spine has no Hands intent {intent_id}"))?; - let review = runtime_hands_action_review(&runtime_store, review_id)? - .ok_or_else(|| anyhow!("runtime-spine has no Hands review {review_id}"))?; - if review.intent_id != intent.intent_id { - return Err(anyhow!( - "Hands review {} belongs to {}, not {}", - review.review_id, - review.intent_id, - intent.intent_id - )); - } - if review.decision != "approved" { - return Err(anyhow!( - "Hands review {} decision is {}, not approved", - review.review_id, - review.decision - )); - } - - let commit_receipt = if let Some(commit_receipt_id) = args.commit_receipt_id.clone() { - runtime_hands_commit_receipt(&runtime_store, &commit_receipt_id)? - .ok_or_else(|| anyhow!("Hands commit receipt {commit_receipt_id} was not found"))? - } else { - let lower_bound = adopt_receipt - .get("createdAt") - .and_then(Value::as_str) - .ok_or_else(|| anyhow!("adopt receipt has no createdAt timestamp"))?; - let chain = runtime_latest_hands_receipt_chain_after(&runtime_store, lower_bound)? - .ok_or_else(|| anyhow!("no complete Hands patch/command/commit chain after adoption; pass --commit-receipt-id after recording branch-local work"))?; - runtime_hands_commit_receipt(&runtime_store, &chain.commit_receipt_id)?.ok_or_else( - || { - anyhow!( - "Hands commit receipt {} was not found", - chain.commit_receipt_id - ) - }, - )? - }; - if commit_receipt.intent_id != intent.intent_id || commit_receipt.review_id != review.review_id - { - return Err(anyhow!( - "Hands commit receipt {} belongs to intent {}/review {}, not {}/{}", - commit_receipt.receipt_id, - commit_receipt.intent_id, - commit_receipt.review_id, - intent.intent_id, - review.review_id - )); - } - - let now = Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); - let mut publication_review = review.clone(); - if !publication_review - .allowed_operations - .iter() - .any(|operation| operation == "pr") - { - publication_review.allowed_operations.push("pr".to_string()); - } - if !publication_review - .required_receipts - .iter() - .any(|receipt| receipt == HANDS_PR_RECEIPT_TYPE) - { - publication_review - .required_receipts - .push(HANDS_PR_RECEIPT_TYPE.to_string()); - } - publication_review.reviewed_at = now.clone(); - publication_review.reasons.push(format!( - "Bifrost publication routing approved after verification refs [{}] and review refs [{}].", - args.verification_receipts.join(", "), - args.review_receipts.join(", ") - )); - put_hands_action_review(&runtime_store, &publication_review)?; - - let item = adopt_receipt - .get("item") - .and_then(Value::as_str) - .unwrap_or("work-item") - .to_string(); - let item_slug = sanitize(&item); - let hands_pr_receipt_id = args - .hands_pr_receipt_id - .clone() - .unwrap_or_else(|| format!("repo-work-publish-{item_slug}-hands-pr")); - let bifrost_intent_id = format!("repo-work-publish-{item_slug}-bifrost-intent"); - let bifrost_publication_receipt_id = - format!("repo-work-publish-{item_slug}-bifrost-publication"); - let github_publication_receipt_id = format!("repo-work-publish-{item_slug}-github"); - let target_branch = args - .target_branch - .clone() - .unwrap_or_else(|| commit_receipt.branch.clone()); - let target_repository = format!("repo:{}", workspace.display()); - let body_domain = target_repository.clone(); - - let mut verse_args = vec![ - "bifrost-publication".to_string(), - "--store".to_string(), - local_verse_store.display().to_string(), - "--runtime-id".to_string(), - runtime_id.clone(), - "--intent-id".to_string(), - bifrost_intent_id.clone(), - "--receipt-id".to_string(), - bifrost_publication_receipt_id.clone(), - "--github-receipt-id".to_string(), - github_publication_receipt_id.clone(), - "--target-repository".to_string(), - target_repository.clone(), - "--target-branch".to_string(), - target_branch.clone(), - "--change-summary".to_string(), - args.change_summary.clone(), - "--justification".to_string(), - args.justification.clone(), - "--ledger-entry-id".to_string(), - args.ledger_entry_id.clone(), - "--hands-pr-receipt-id".to_string(), - hands_pr_receipt_id.clone(), - "--publication-url".to_string(), - args.pull_request_url.clone(), - "--pull-request-number".to_string(), - args.pull_request_number.clone(), - "--commit-sha".to_string(), - commit_receipt.commit_sha.clone(), - "--source-cluster-id".to_string(), - "epiphany.cluster.hands".to_string(), - "--source-agent-id".to_string(), - "epiphany.Hands".to_string(), - "--body-domain".to_string(), - body_domain, - "--receipt-status".to_string(), - args.publication_status.clone(), - ]; - for path in &commit_receipt.changed_paths { - verse_args.extend(["--changed-path".to_string(), path.clone()]); - } - for receipt in &args.verification_receipts { - verse_args.extend(["--verification-receipt".to_string(), receipt.clone()]); - } - for receipt in &args.review_receipts { - verse_args.extend(["--review-receipt".to_string(), receipt.clone()]); - } - for author in &args.author_agents { - verse_args.extend(["--author-agent".to_string(), author.clone()]); - } - for subject in &args.credit_subjects { - verse_args.extend(["--credit-subject".to_string(), subject.clone()]); - } - if let Some(credit_receipts) = &args.credit_receipt_ids { - for receipt in credit_receipts { - verse_args.extend(["--credit-receipt".to_string(), receipt.clone()]); - } - } - let bifrost = cargo_json(&manifest_path, "epiphany-verse-query", &verse_args)?; - - let pr_receipt = hands_pr_receipt_for_review( - hands_pr_receipt_id.clone(), - &intent, - &publication_review, - &commit_receipt, - args.pull_request_url.clone(), - args.pull_request_number.clone(), - args.pull_request_title.clone(), - bifrost_publication_receipt_id.clone(), - format!("Published repo work item {item} through Bifrost receipts."), - now.clone(), - ); - put_hands_pr_receipt(&runtime_store, &pr_receipt)?; - - let publish_receipt = json!({ - "schemaVersion": "epiphany.repo_work_publish_receipt.v0", - "createdAt": now, - "workspace": workspace, - "runtimeId": runtime_id, - "runtimeStore": runtime_store, - "localVerseStore": local_verse_store, - "adoptReceiptPath": adopt_receipt_path, - "runReceiptPath": run_receipt_path, - "onlineReceiptPath": online_receipt_path, - "closureReceiptPath": args.closure_receipt, - "item": item, - "status": "publication-receipts-recorded", - "targetRepository": target_repository, - "targetBranch": target_branch, - "changedPaths": commit_receipt.changed_paths, - "handsActionGate": { - "intentId": intent.intent_id, - "reviewId": publication_review.review_id, - "decision": publication_review.decision, - "allowedOperations": publication_review.allowed_operations, - "requiredReceipts": publication_review.required_receipts - }, - "handsReceipts": { - "commitReceiptId": commit_receipt.receipt_id, - "commitSha": commit_receipt.commit_sha, - "branch": commit_receipt.branch, - "prReceiptId": pr_receipt.receipt_id, - "pullRequestUrl": pr_receipt.pull_request_url, - "pullRequestNumber": pr_receipt.pull_request_number, - "pullRequestTitle": pr_receipt.pull_request_title - }, - "bifrost": { - "intentId": bifrost["intentId"], - "publicationReceiptId": bifrost["publicationReceiptId"], - "githubPublicationReceiptId": bifrost["githubPublicationReceiptId"], - "ledgerEntryId": bifrost["ledgerEntryId"], - "creditReceiptIds": bifrost["creditReceiptIds"], - "pullRequestUrl": bifrost["pullRequestUrl"] - }, - "verificationReceipts": args.verification_receipts, - "reviewReceipts": args.review_receipts, - "authority": { - "publicationAuthorized": true, - "upstreamMainSynced": false, - "mergeAuthorized": false, - "mergeGate": "maintainer_or_bifrost_merge_receipt", - "privateStateExposed": false - }, - "nextSafeMove": "Maintain the PR/publication receipt chain; do not claim upstream main is synced until a merge/sync receipt exists." - }); - let receipt_path = artifact_dir.join(format!("work-publish-{item_slug}.json")); - write_json(&receipt_path, &publish_receipt)?; - Ok(json!({ - "schemaVersion": "epiphany.repo_work_publish.v0", - "status": publish_receipt["status"], - "workspace": publish_receipt["workspace"], - "runtimeId": publish_receipt["runtimeId"], - "runtimeStore": publish_receipt["runtimeStore"], - "localVerseStore": publish_receipt["localVerseStore"], - "receiptPath": receipt_path, - "item": publish_receipt["item"], - "handsReceipts": publish_receipt["handsReceipts"], - "bifrost": publish_receipt["bifrost"], - "authority": publish_receipt["authority"], - "privateStateExposed": false, - "nextSafeMove": publish_receipt["nextSafeMove"], - })) -} - -fn run_sync(args: SyncArgs) -> Result { - let workspace = args - .workspace - .canonicalize() - .with_context(|| format!("failed to resolve {}", args.workspace.display()))?; - ensure_git_repo(&workspace)?; - let publish_receipt_path = - resolve_publish_receipt(&workspace, args.item.as_deref(), args.publish_receipt)?; - let publish_receipt = read_json(&publish_receipt_path)?; - let artifact_dir = args - .artifact_dir - .unwrap_or_else(|| workspace.join(".epiphany").join("work")); - fs::create_dir_all(&artifact_dir) - .with_context(|| format!("failed to create {}", artifact_dir.display()))?; - - let item = publish_receipt - .get("item") - .and_then(Value::as_str) - .unwrap_or("work-item") - .to_string(); - let item_slug = sanitize(&item); - let published_commit_sha = publish_receipt - .get("handsReceipts") - .and_then(|hands| hands.get("commitSha")) - .and_then(Value::as_str) - .ok_or_else(|| anyhow!("publish receipt has no handsReceipts.commitSha"))? - .to_string(); - let commit_receipt_id = publish_receipt - .get("handsReceipts") - .and_then(|hands| hands.get("commitReceiptId")) - .and_then(Value::as_str) - .unwrap_or("unknown") - .to_string(); - let pr_receipt_id = publish_receipt - .get("handsReceipts") - .and_then(|hands| hands.get("prReceiptId")) - .and_then(Value::as_str) - .unwrap_or("unknown") - .to_string(); - let upstream_commit_sha = - git_output(&workspace, &["rev-parse", "--verify", &args.upstream_ref]) - .with_context(|| format!("failed to resolve upstream ref {}", args.upstream_ref))?; - let canonical_published_commit = git_output( - &workspace, - &["rev-parse", "--verify", &published_commit_sha], - ) - .with_context(|| format!("failed to resolve published commit {published_commit_sha}"))?; - let upstream_main_synced = git_status_success( - &workspace, - &[ - "merge-base", - "--is-ancestor", - &canonical_published_commit, - &args.upstream_ref, - ], - )?; - let status = if upstream_main_synced { - "upstream-main-synced" - } else { - "upstream-main-not-synced" - }; - let now = Utc::now().to_rfc3339_opts(chrono::SecondsFormat::Secs, true); - let sync_receipt = json!({ - "schemaVersion": "epiphany.repo_work_sync_receipt.v0", - "createdAt": now, - "workspace": workspace, - "publishReceiptPath": publish_receipt_path, - "item": item, - "status": status, - "upstreamRef": args.upstream_ref, - "upstreamCommitSha": upstream_commit_sha, - "publishedCommitSha": canonical_published_commit, - "mergeReceipts": args.merge_receipts, - "handsReceipts": { - "commitReceiptId": commit_receipt_id, - "prReceiptId": pr_receipt_id - }, - "bifrost": publish_receipt["bifrost"], - "authority": { - "publicationAuthorized": true, - "upstreamMainSynced": upstream_main_synced, - "mergeAuthorized": upstream_main_synced, - "mergeAuthorityReceipts": args.merge_receipts, - "privateStateExposed": false - }, - "nextSafeMove": if upstream_main_synced { - "Update durable map/Mind receipts and proof bundle; upstream main now contains the published work." - } else { - "Wait for maintainer/Bifrost merge, then rerun epiphany-work sync against upstream main." - } - }); - let receipt_path = artifact_dir.join(format!("work-sync-{item_slug}.json")); - write_json(&receipt_path, &sync_receipt)?; - Ok(json!({ - "schemaVersion": "epiphany.repo_work_sync.v0", - "status": sync_receipt["status"], - "workspace": sync_receipt["workspace"], - "receiptPath": receipt_path, - "item": sync_receipt["item"], - "upstreamRef": sync_receipt["upstreamRef"], - "upstreamCommitSha": sync_receipt["upstreamCommitSha"], - "publishedCommitSha": sync_receipt["publishedCommitSha"], - "authority": sync_receipt["authority"], - "privateStateExposed": false, - "nextSafeMove": sync_receipt["nextSafeMove"], - })) -} - fn run_overview(args: OverviewArgs) -> Result { let workspace = args .workspace @@ -14660,7 +14021,8 @@ fn run_tick(args: TickArgs) -> Result { reason = "publication receipt exists; scheduler stops before merge/sync authority".to_string(); next_safe_move = - "Wait for maintainer/Bifrost merge receipt, then run epiphany-work sync.".to_string(); + "Wait for provider-authored merge evidence, then inspect upstream Git ancestry." + .to_string(); } else if close_receipt_path.exists() && read_json(&close_receipt_path)? .get("status") @@ -14671,8 +14033,7 @@ fn run_tick(args: TickArgs) -> Result { status = "noop".to_string(); reason = "Soul/Modeling/Mind closure is recorded; scheduler stops before Bifrost publication authority".to_string(); next_safe_move = - "Route Bifrost/GitHub publication through epiphany-work publish --closure-receipt." - .to_string(); + "Submit a Bifrost publication intent through the owning integration.".to_string(); } else if close_receipt_path.exists() { let partial_close = read_json(&close_receipt_path)?; let runtime_store = args @@ -15092,25 +14453,6 @@ fn resolve_adopt_receipt( }) } -fn resolve_publish_receipt( - workspace: &Path, - item: Option<&str>, - explicit: Option, -) -> Result { - if let Some(path) = explicit { - return Ok(path); - } - let work_dir = workspace.join(".epiphany").join("work"); - if let Some(item) = item { - return Ok(work_dir.join(format!("work-publish-{}.json", sanitize(item)))); - } - latest_receipt_in(&work_dir, "work-publish-").ok_or_else(|| { - anyhow!( - "no work publish receipt found; run epiphany-work publish first or pass --publish-receipt" - ) - }) -} - fn resolve_execute_receipt( workspace: &Path, item: Option<&str>, @@ -15228,7 +14570,7 @@ fn bifrost_publication_readiness_row(path: &Path, receipt: Option<&Value>) -> Re "bifrost-publication", "Bifrost/GitHub", "epiphany.repo_work_publish_receipt.v0 + gamecult.bifrost.body_change_publication_receipt.v0 + gamecult.bifrost.github_publication_receipt.v0", - "Run epiphany-work publish so Bifrost and GitHub publication receipts exist before readiness review.", + "Wait for Bifrost and the GitHub adapter to publish their receipts before readiness review.", )); }; @@ -15374,7 +14716,7 @@ fn upstream_main_sync_readiness_row( "upstream-main-sync", "Bifrost/GitHub", "epiphany.repo_work_sync_receipt.v0 + git merge-base ancestry proof", - "Run epiphany-work sync after maintainer/Bifrost merge authority so upstream main containment is proved.", + "Inspect provider-authored merge evidence and upstream Git ancestry.", )); }; @@ -16015,7 +15357,7 @@ fn repo_work_overview_gate( ( "awaiting-upstream-sync", "merge-or-sync-receipt-missing", - "After maintainer/Bifrost merge, run epiphany-work sync.", + "After provider-authored merge evidence arrives, inspect upstream Git ancestry.", ) } else if close .and_then(|receipt| receipt.get("status")) @@ -16025,7 +15367,7 @@ fn repo_work_overview_gate( ( "awaiting-publication", "bifrost-publication-missing", - "Run epiphany-work publish --closure-receipt when publication is authorized.", + "Submit a Bifrost publication intent through the owning integration.", ) } else if close .and_then(|receipt| receipt.get("status")) @@ -17442,7 +16784,7 @@ fn sanitize(value: &str) -> String { fn print_usage() { eprintln!( - "usage: epiphany-work ...\n\ + "usage: epiphany-work ...\n\ persona-intake --workspace --item --message [--topic ] [--store ] [--runtime-id ]\n\ accept --workspace --from --item [--summary ] [--topic ] [--store ] [--runtime-id ] [--online-receipt ] [--public-discussion-ref ] [--candidate-action-ref ]\n\ derive-plan --workspace [--item ] [--accept-receipt ] [--action-family append-worklog|planning-note|checklist-note|section-note|repo-status-section|task-card|repo-manifest|repo-tool-capabilities|repo-tool-request|repo-eve-surface|repo-collaboration-policy|repo-collaboration-topic|repo-consensus-brief|repo-planning-brief|repo-interpreter-brief|repo-objective-draft|repo-adoption-request|repo-scheduling-request|repo-work-order|repo-verification-request|repo-publication-request|repo-sync-request|repo-maintainer-review-request|repo-pr-request|repo-credit-request|repo-artifact-acceptance-request|repo-metrics-request|repo-readiness-review-request|repo-doctrine-update-request|repo-secret-policy-request|repo-dependency-policy-request|repo-deployment-config|repo-deployment-request] [--target-path ] [--model-ref ] [--model-authored] [--action-summary ] [--verification-ask ] [--stop-condition ] [--escalation-reason ] [--assumption ] [--constraint ] [--non-goal ] [--open-question ] [--decision-point ] [--evidence-need ]\n\ @@ -17451,8 +16793,6 @@ fn print_usage() { adopt --workspace [--item ] [--run-receipt ] [--from-plan ] [--plan-summary ] [--adoption-evidence-ref ] [--mind-adoption-rationale ]\n\ execute --workspace [--item ] [--from-plan ] [--command ] [--changed-path ] [--commit-message ]\n\ close --workspace [--item ] [--execute-receipt ] [--verification-command ] --closure-model-ref --model-authored --closure-model-verdict passed|failed|needs-work|blocked --closure-model-finding [--require-source-grounding]\n\ - publish --workspace [--item ] --change-summary --justification --verification-receipt --review-receipt --ledger-entry-id --pull-request-url --pull-request-title \n\ - sync --workspace [--item ] [--publish-receipt ] [--upstream-ref origin/main] --merge-receipt \n\ overview --workspace [--item ] [--accept-receipt ] [--no-write]\n\ readiness --workspace [--item ] [--accept-receipt ] [--public-proof ] [--idunn-lifecycle-receipt ] [--deployment-aftercare-audit-receipt |--deployment-aftercare-audit-receipt-ref ] [--tool-directory-receipt ] [--no-write]\n\ deployment-config-audit --workspace [--artifact-dir ] [--no-write]\n\ diff --git a/notes/conceptual-substitution-audit-2026-07-12.md b/notes/conceptual-substitution-audit-2026-07-12.md index 2b3d74c4..fb83e273 100644 --- a/notes/conceptual-substitution-audit-2026-07-12.md +++ b/notes/conceptual-substitution-audit-2026-07-12.md @@ -328,3 +328,15 @@ 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. + +## Caller-authored publication and merge authority + +The deleted smoke exposed a surviving production authority. `epiphany-work +publish` accepted arbitrary verification/review/PR/ledger strings, rewrote a +Hands review to add PR permission, invoked the now request-only Bifrost command +with forbidden provider-result arguments, and wrote +`publicationAuthorized=true`. `epiphany-work sync` accepted arbitrary merge +strings and promoted Git ancestry into `mergeAuthorized=true`. Both commands +and the whole-path stop-classification smoke that depended on them are deleted. +The coherent split is Bifrost intent submission, provider-authored publication +and review receipts, and read-only Git ancestry inspection. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 9d37281c..08b6f12a 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -76,6 +76,10 @@ The confirmed conceptual substitutions have been cut: - 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. +- `epiphany-work publish` and `sync` are deleted. The first promoted arbitrary + receipt strings into publication authority; the second promoted arbitrary + merge strings plus Git ancestry into merge authority. Bifrost intent, + provider receipts, and read-only ancestry are separate paths. 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 ac001dc56627f90a3d5a2d51e5ce07399628f147..69025f13e1a83118405ec357712c2f2af19a7171 100644 GIT binary patch delta 484 zcmZ9Ize)o^5XQY2qgdL7APm^%lJoFSh^?TNM6t4wy}e0p$^JQa_YzX2un1^t%me5H z2o_?eAo>ns?GyL_?jiM`Z z8W%iQ`8)5b=xX6%TqvDBuUtKbLAd1y+x~iZ9EQ!HF**G7DvR&l%`S4Bd|VgH!@3zr z3Pi?W6NDI3lrc&R#;Vk(oEXE}j1tR~gnptp`YEvq7@@jYgH{%CW)dKjVrnr4N;pRi z8Y!~W)>}t)j&aBR7^|7=m@0_Ol3cm(mo_PriFn>xs+51F||qb z6p>MzX_s&Sne0l{ms6fp!1E18Wtw81-Ho|3n*5|<2g1$32_mqLX=V;N_ai2OCX=U& I(vnyE27J-3MgRZ+ delta 56 zcmX@!E&ZikdV?e*m$8+hS=2EGwnG;;D>D`{GRibhWon