Add repo work sync proof gate
This commit is contained in:
parent
6c6bc12a11
commit
98b0ebc751
5 changed files with 227 additions and 5 deletions
|
|
@ -48,6 +48,7 @@ fn main() -> Result<()> {
|
|||
"adopt" | "promote" => run_adopt(parse_adopt_args(args)?),
|
||||
"execute" | "exec" => run_execute(parse_execute_args(args)?),
|
||||
"publish" => run_publish(parse_publish_args(args)?),
|
||||
"sync" | "sync-main" => run_sync(parse_sync_args(args)?),
|
||||
other => Err(anyhow!("unknown epiphany-work command {other:?}")),
|
||||
}?;
|
||||
println!("{}", serde_json::to_string_pretty(&result)?);
|
||||
|
|
@ -134,6 +135,16 @@ struct PublishArgs {
|
|||
publication_status: String,
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
struct SyncArgs {
|
||||
workspace: PathBuf,
|
||||
item: Option<String>,
|
||||
publish_receipt: Option<PathBuf>,
|
||||
artifact_dir: Option<PathBuf>,
|
||||
upstream_ref: String,
|
||||
merge_receipts: Vec<String>,
|
||||
}
|
||||
|
||||
fn parse_accept_args(args: impl Iterator<Item = String>) -> Result<AcceptArgs> {
|
||||
let mut workspace = None;
|
||||
let mut epiphany_root = None;
|
||||
|
|
@ -462,6 +473,45 @@ fn parse_publish_args(args: impl Iterator<Item = String>) -> Result<PublishArgs>
|
|||
})
|
||||
}
|
||||
|
||||
fn parse_sync_args(args: impl Iterator<Item = String>) -> Result<SyncArgs> {
|
||||
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 run_accept(args: AcceptArgs) -> Result<Value> {
|
||||
let workspace = args
|
||||
.workspace
|
||||
|
|
@ -1424,6 +1474,114 @@ fn run_publish(args: PublishArgs) -> Result<Value> {
|
|||
}))
|
||||
}
|
||||
|
||||
fn run_sync(args: SyncArgs) -> Result<Value> {
|
||||
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 resolve_accept_receipt(
|
||||
workspace: &Path,
|
||||
item: Option<&str>,
|
||||
|
|
@ -1493,6 +1651,25 @@ fn resolve_adopt_receipt(
|
|||
})
|
||||
}
|
||||
|
||||
fn resolve_publish_receipt(
|
||||
workspace: &Path,
|
||||
item: Option<&str>,
|
||||
explicit: Option<PathBuf>,
|
||||
) -> Result<PathBuf> {
|
||||
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 latest_receipt_in(work_dir: &Path, prefix: &str) -> Option<PathBuf> {
|
||||
let mut candidates = Vec::new();
|
||||
if work_dir.exists() {
|
||||
|
|
@ -1600,6 +1777,16 @@ fn git_output(workspace: &Path, args: &[&str]) -> Result<String> {
|
|||
Ok(String::from_utf8_lossy(&output.stdout).trim().to_string())
|
||||
}
|
||||
|
||||
fn git_status_success(workspace: &Path, args: &[&str]) -> Result<bool> {
|
||||
let output = Command::new("git")
|
||||
.arg("-C")
|
||||
.arg(workspace)
|
||||
.args(args)
|
||||
.output()
|
||||
.with_context(|| format!("failed to run git {}", args.join(" ")))?;
|
||||
Ok(output.status.success())
|
||||
}
|
||||
|
||||
fn git_add_paths(workspace: &Path, paths: &[String]) -> Result<()> {
|
||||
let mut command = Command::new("git");
|
||||
command.arg("-C").arg(workspace).arg("add").arg("--");
|
||||
|
|
@ -1752,10 +1939,11 @@ fn sanitize(value: &str) -> String {
|
|||
|
||||
fn print_usage() {
|
||||
eprintln!(
|
||||
"usage: epiphany-work <accept|run|adopt|publish> ...\n\
|
||||
"usage: epiphany-work <accept|run|adopt|publish|sync> ...\n\
|
||||
accept --workspace <repo> --from <persona|bifrost|persona-or-bifrost> --item <id> [--summary <text>] [--topic <topic>] [--store <local-verse.ccmp>] [--runtime-id <id>] [--online-receipt <path>] [--public-discussion-ref <ref>] [--candidate-action-ref <ref>]\n\
|
||||
run --workspace <repo> [--item <id>] [--accept-receipt <path>] [--runtime-store <path>] [--requested-path <path>]\n\
|
||||
adopt --workspace <repo> [--item <id>] [--run-receipt <path>] --plan-summary <text> --adoption-evidence-ref <ref>\n\
|
||||
publish --workspace <repo> [--item <id>] --change-summary <text> --justification <text> --verification-receipt <ref> --review-receipt <ref> --ledger-entry-id <id> --pull-request-url <url> --pull-request-title <text>"
|
||||
publish --workspace <repo> [--item <id>] --change-summary <text> --justification <text> --verification-receipt <ref> --review-receipt <ref> --ledger-entry-id <id> --pull-request-url <url> --pull-request-title <text>\n\
|
||||
sync --workspace <repo> [--item <id>] [--publish-receipt <path>] [--upstream-ref origin/main] --merge-receipt <ref>"
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ epiphany-work run --workspace <repo>
|
|||
epiphany-work adopt --workspace <repo> --item <id> --plan-summary <text> --adoption-evidence-ref <ref>
|
||||
epiphany-work execute --workspace <repo> --item <id> --command <command> --changed-path <path> --commit-message <text>
|
||||
epiphany-work publish --workspace <repo>
|
||||
epiphany-work sync --workspace <repo> --item <id> --upstream-ref origin/main --merge-receipt <ref>
|
||||
```
|
||||
|
||||
And produce a proof bundle showing:
|
||||
|
|
@ -152,6 +153,7 @@ And produce a proof bundle showing:
|
|||
- Soul verification receipts
|
||||
- Mind admission receipts
|
||||
- Bifrost publication/credit receipts for upstream-facing work
|
||||
- upstream-main sync proof for merged/published work
|
||||
- sealed private state and no raw worker thought leakage
|
||||
|
||||
### Landed Init Front Door
|
||||
|
|
@ -355,6 +357,38 @@ prove upstream main actually matches the accepted publication, plus a less
|
|||
manual planner/executor bridge that supplies executable commands from
|
||||
Imagination/Self rather than operator CLI arguments.
|
||||
|
||||
### Landed Upstream Sync Proof Gate
|
||||
|
||||
The eighth front door exists as native Rust:
|
||||
|
||||
```powershell
|
||||
cargo run --manifest-path .\epiphany-core\Cargo.toml --bin epiphany-work -- sync --workspace <repo> --item <id> --upstream-ref origin/main --merge-receipt <ref>
|
||||
```
|
||||
|
||||
It reads the named or latest work-publish receipt, requires at least one
|
||||
explicit maintainer or Bifrost merge/sync receipt, resolves the published Hands
|
||||
commit and the configured upstream ref, and asks git whether the published
|
||||
commit is an ancestor of upstream main. It does not perform a merge. It writes
|
||||
`.epiphany/work/work-sync-<item>.json` with `upstreamMainSynced=true` only when
|
||||
git ancestry proves the published commit is contained by the upstream ref.
|
||||
|
||||
The first smoke proved both sides of the gate:
|
||||
|
||||
```powershell
|
||||
epiphany-work sync --workspace <repo> --item first-request --upstream-ref main --merge-receipt maintainer-merge:sync-smoke-pre
|
||||
# status: upstream-main-not-synced
|
||||
|
||||
git switch main
|
||||
git merge --ff-only epiphany/smoke/sync
|
||||
|
||||
epiphany-work sync --workspace <repo> --item first-request --upstream-ref main --merge-receipt maintainer-merge:sync-smoke-post
|
||||
# status: upstream-main-synced
|
||||
```
|
||||
|
||||
The synced receipt produced `publicationAuthorized=true`,
|
||||
`upstreamMainSynced=true`, `mergeAuthorized=true`,
|
||||
`mergeAuthorityReceipts=[...]`, and `privateStateExposed=false`.
|
||||
|
||||
## Migration Implication
|
||||
|
||||
The next migration plan must treat autonomous branch-local work as a required
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ remembers doctrine; the branch remembers the blade.
|
|||
- Edge JSON is allowed for schema description, hostile ingress before immediate typed parsing, sealed forensic artifacts, or named quarantine experiments. When both subsystems are ours, runtime data must remain typed CultCache documents and move over CultNet typed contracts. Generic `serde_json::Value` in worker launch/result/selfPatch/runtime flow is contamination until classified and replaced.
|
||||
- Hands now has a first executable action receipt spine. `epiphany-core::hands_gateway` owns `HandsActionIntent`, `HandsActionReview`, `HandsPatchReceipt`, `HandsCommandReceipt`, and `HandsCommitReceipt`; runtime-spine can persist/reread them; `runtime_spine_persists_mind_gateway_review_receipts` includes the Hands chain beside Mind/Eyes/Substrate/Soul/Continuity proofs and proves the post-timestamp Hands receipt-chain detector; `epiphany-hands-action-smoke` emits intent/review/patch/command/commit receipt ids from `.epiphany-smoke\runtime-spine\hands-action-smoke.msgpack`; and the repo-action launch proof profile now requires action intent, action review, and patch receipt together. `epiphany-mvp-coordinator` now turns `continueImplementation` into a persisted Substrate Gate grant plus Hands intent/review gate and includes the receipt ids in the operator step. `epiphany-hands-action` is the native consequence recorder for that gate: `record-patch`, `record-command`, `record-commit`, and turn-level `record-pass` load the stored intent/review or `finalAction.handsActionGate` from `coordinator-summary.json`, require an approved matching review, enforce allowed operations, and keep patch/commit changed paths inside the requested scope. `epiphany-mvp-coordinator-smoke` includes the deterministic Hands pass proof. The coordinator now treats a complete Hands receipt chain after an accepted Soul result as new implementation evidence, launches Soul again, and routes a passing accepted Soul result to Modeling/modeling before another Hands turn. Work-loop telemetry is now typed internal CultMesh state: Verification role launches write `epiphany.cultmesh.work_loop_telemetry.v0` beside runtime-spine, render that packet for Soul with resolved receipt bodies, commit diff preview, source proof notes, verification assertions, and stdout/stderr previews, and Modeling launches read/enrich the latest packet with Soul acceptance receipt ids before Modeling updates the map. Local Verse prompt context now exposes only a sealed `latest_work_loop_summary` digest with telemetry id, Hands receipt ids, path/source/assertion counts, and Soul receipt ids; receipt payload previews, artifact previews, and commit diff previews remain internal telemetry and are leak-guarded by tests plus `epiphany-verse-query -- smoke`.
|
||||
- `notes/epiphany-swarm-readiness-plan.md` is the current live-fire direction gate. The local runner proves startup/status/coordinator wiring; it does not authorize unattended swarm operation. Carry VoidBot's lessons forward: one CTB-style initiative scheduler, typed pause/brake, active-turn freeze, cooldown after completion, stale active-turn recovery receipts, parent-side speech eligibility, memory lifecycle phases, and typed operation proposals instead of prompt-owned governance. `epiphany-verse-query swarm-brake --brake-status engaged|released` can now write the local Verse brake document, and `tools/epiphany_local_run.ps1` refuses live `plan`/`run`/`mvp` modes when that brake is engaged while keeping `status` readable. `epiphany-mvp-coordinator` also checks `--local-verse-store` before app-server startup, and `epiphany-heartbeat-store` guards tick/pump/heat/queue-mention/routine when passed `--local-verse-store`. Daemon tool invocation, daemon lifecycle poke, and `epiphany-daemon-supervisor` restart/tick/serve/service-plan/service-launch/service-runbook/windows-service-install/windows-service-status/windows-service-reconcile/windows-service-execution-readiness/start/stop attempts now fail closed under a matching engaged brake; supervisor restart now has durable per-daemon policy with cooldown/backoff, explicit scheduled tick pulses, latest scheduler receipts, typed service lifecycle plan/launch/runbook/install/status/reconcile/readiness/start/stop receipts, and local operator wrapper modes that write runbook/install/status/reconcile/readiness/control-plan/execution artifacts plus operator run receipts. The installed-service read path, read-only service-policy reconciliation path, execution-readiness path, non-mutating start/stop control-plan path, and non-elevated execution refusal path have been proved against real Windows `EventLog` service-manager state or safe missing-service targets through local Verse receipts, including explicit wrapper install/start/stop execution modes. The next cut is actual elevated install/start/stop execution proof under operator authority.
|
||||
- `notes/epiphany-repo-swarm-mvp-contract.md` corrects the repo-swarm MVP authority boundary: autonomous branch-local work inside the owned repo Body is in scope and desired; Bifrost gates publication/merge/escalation, not every local edit. Seven native repo-swarm front doors are now live: `epiphany-repo init --workspace <repo>` writes the repo-swarm init receipt and branch workbench plan; `epiphany-swarm online --workspace <repo>` seeds repo-local `.epiphany/local-verse.ccmp`, standing-faculty SoA, topology/liveness/tool/overview proof, and `.epiphany/swarm-online/repo-swarm-online-receipt.json`; `epiphany-work accept --workspace <repo> --from persona-or-bifrost --item <id>` routes a Persona/Bifrost item through CultMesh collaboration feedback into Imagination consensus discovery and writes `.epiphany/work/work-accept-<item>.json` with no Hands, durable-state, or publication authority granted; `epiphany-work run --workspace <repo> [--item <id>]` persists a repo-local runtime-spine Substrate Gate read/snapshot grant, Hands intent, and Hands review with `decision=queued-for-adoption`; `epiphany-work adopt --workspace <repo> --item <id> --plan-summary <text> --adoption-evidence-ref <ref>` requires explicit Imagination/Self/Mind adoption evidence and promotes that queued review to an approved branch-local Hands gate; `epiphany-work execute --workspace <repo> --item <id> --command <command> --changed-path <path> --commit-message <text>` consumes the approved gate on an `epiphany/*` branch, runs the command in the repo Body, captures stdout/stderr artifacts, stages only declared paths, commits, and records Hands patch/command/commit receipts; `epiphany-work publish --workspace <repo> --item <id> ...` requires Hands commit proof plus Soul verification and Mind/review refs, routes Bifrost publication/GitHub publication receipts, records a Hands PR receipt, and keeps `upstreamMainSynced=false` / `mergeAuthorized=false`. Fresh-repo smokes proved init, online, accept, run, adopt, execute, and publish with `privateStateExposed=false`; pre-adoption gates still refuse record-pass. Next missing organ: a merge/sync gate that proves upstream main is actually synced after publication, plus a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments.
|
||||
- `notes/epiphany-repo-swarm-mvp-contract.md` corrects the repo-swarm MVP authority boundary: autonomous branch-local work inside the owned repo Body is in scope and desired; Bifrost gates publication/merge/escalation, not every local edit. Eight native repo-swarm front doors are now live: `epiphany-repo init --workspace <repo>` writes the repo-swarm init receipt and branch workbench plan; `epiphany-swarm online --workspace <repo>` seeds repo-local `.epiphany/local-verse.ccmp`, standing-faculty SoA, topology/liveness/tool/overview proof, and `.epiphany/swarm-online/repo-swarm-online-receipt.json`; `epiphany-work accept --workspace <repo> --from persona-or-bifrost --item <id>` routes a Persona/Bifrost item through CultMesh collaboration feedback into Imagination consensus discovery and writes `.epiphany/work/work-accept-<item>.json` with no Hands, durable-state, or publication authority granted; `epiphany-work run --workspace <repo> [--item <id>]` persists a repo-local runtime-spine Substrate Gate read/snapshot grant, Hands intent, and Hands review with `decision=queued-for-adoption`; `epiphany-work adopt --workspace <repo> --item <id> --plan-summary <text> --adoption-evidence-ref <ref>` requires explicit Imagination/Self/Mind adoption evidence and promotes that queued review to an approved branch-local Hands gate; `epiphany-work execute --workspace <repo> --item <id> --command <command> --changed-path <path> --commit-message <text>` consumes the approved gate on an `epiphany/*` branch, runs the command in the repo Body, captures stdout/stderr artifacts, stages only declared paths, commits, and records Hands patch/command/commit receipts; `epiphany-work publish --workspace <repo> --item <id> ...` requires Hands commit proof plus Soul verification and Mind/review refs, routes Bifrost publication/GitHub publication receipts, records a Hands PR receipt, and keeps `upstreamMainSynced=false` / `mergeAuthorized=false`; `epiphany-work sync --workspace <repo> --item <id> --upstream-ref origin/main --merge-receipt <ref>` requires an explicit maintainer/Bifrost merge receipt, verifies the published commit is an ancestor of upstream main, and writes the sync receipt with `upstreamMainSynced=true` only after git proves it. Fresh-repo smokes proved init, online, accept, run, adopt, execute, publish, and sync with `privateStateExposed=false`; the sync smoke proved `upstream-main-not-synced` before fast-forwarding main and `upstream-main-synced` after `git merge --ff-only`. Pre-adoption gates still refuse record-pass. Next missing organs: a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments, plus scheduler physiology for advancing safe branch-local work without manual CLI stepping.
|
||||
- `service-execution-runbook` makes that next cut repeatable: it generates the exact elevated wrapper command sequence without mutating the service manager, continues after per-step failure to preserve more receipts, runs `service-execution-audit` in `finally`, exits nonzero if any step failed, and seals a typed runbook lifecycle receipt. Run the generated artifact only with explicit operator authority.
|
||||
- `service-execution-audit` is the non-mutating acceptance proof after the elevated rite: it reports `complete` only when typed lifecycle receipts prove the runbook witness plus expected elevated chain, and otherwise reports the missing/failed sealed checks.
|
||||
- `service-tick` is the non-elevated scheduler pulse proof: it writes the latest daemon scheduler receipt through durable policy ownership and local wrapper receipts.
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -88,7 +88,7 @@ active_subgoals:
|
|||
- Keep the landed Phase 6 coordinator, limited safe-boundary CRRC automation, and pre-compaction checkpoint intervention ready for the next bridge-equipped dogfood run.
|
||||
- Preserve the Ghostlight-derived heartbeat initiative seam: every lane, including coordinator/Self and Persona, has a organ-state record and competes for heartbeat slots through readiness/reaction timing; initiative heat can raise or cool global, group, arena, role, and agent tempo through typed heartbeat policy; active thinking freezes initiative until completion, so heat never queues a lane already mid-turn; idle winners ruminate instead of inventing project work, and sleep windows distill the accumulated thought pressure into reviewed self-memory or doctrine.
|
||||
- Use `notes/epiphany-swarm-readiness-plan.md` as the live-fire direction gate. The local run path is a compass, not launch clearance: before unattended swarm operation, Epiphany needs typed pause/brake enforcement, one initiative scheduler, completion-gated cooldown, stale active-turn recovery receipts, parent-side Persona speech eligibility, memory lifecycle operations, and CultNet-first operator snapshots/intents/receipts. The local Verse brake document exists, `epiphany-verse-query swarm-brake` can engage/release it, `tools/epiphany_local_run.ps1` refuses live `plan`/`run`/`mvp` modes when the brake is engaged while leaving `status` readable, `epiphany-mvp-coordinator` checks the local Verse brake before app-server startup, and `epiphany-heartbeat-store` guards tick/pump/heat/queue-mention/routine when given `--local-verse-store`. Daemon liveness is now a typed local Verse authority: `epiphany-verse-query daemon-status` writes one daemon status without repainting the table, local Verse seeding preserves existing daemon statuses and swarm brakes, `invoke-tool` refuses when the host daemon is not ready or lacks `submitTypedToolIntent`, and both daemon tool invocation and lifecycle poke fail closed under an engaged matching brake. `epiphany-daemon-supervisor policy` writes durable per-daemon restart policy with command/args/cwd/cooldown/backoff/attempt state plus reconcile cadence and stale-heartbeat threshold; `epiphany-daemon-supervisor reconcile` loads that policy when no override command is supplied, refuses under a matching lifecycle brake, refuses during cooldown/backoff, writes daemon poke intent/receipt, updates daemon status, and updates policy attempt state; `epiphany-daemon-supervisor tick` is an explicit scheduler pulse that scans durable policies, records ready/noop pulses, skips before the configured reconcile interval, marks stale heartbeat status degraded, routes restarts through the same brake/cooldown/poke receipt path, and writes a latest `epiphany.cultmesh.daemon_scheduler_receipt.v0`; `epiphany-daemon-supervisor serve` runs that same pulse on a configurable cadence with bounded `--max-iterations` proof mode or unbounded service mode. `epiphany-daemon-supervisor service-plan`/`install-service` now writes a planned `epiphany.cultmesh.daemon_service_lifecycle_receipt.v0` for the `serve` command, while `service-launch`/`start-service` spawns that `serve` loop through the current executable or `--service-command`, can `--wait-child` for bounded proof, and records command/args/cwd, scheduler id, daemon selector, pid/exit/status, artifact ref, and private-state guard. `service-runbook`, `windows-service-install`/`service-install-plan`, `windows-service-status`, `windows-service-reconcile`, `windows-service-execution-readiness`, and `windows-service-start`/`stop` now record service lifecycle receipts through the same local Verse; the read-only status path has been proved against the real Windows `EventLog` service with receipt `daemon-service-lifecycle-receipt-windows-eventlog-proof-windows-service-status`, status `running`, exit code `0`, and `privateStateExposed=false`; the read-only service-policy reconciliation path has been proved for missing service, real-service drift against `EventLog`, lifecycle-brake refusal, and wrapper/local-Verse receipt `daemon-service-lifecycle-receipt-windows-eventlog-reconcile-proof-windows-service-reconcile`; execution readiness has been proved as a non-mutating `not-elevated` receipt through direct and wrapper paths; start/stop now produce non-mutating `start-planned`/`stop-planned` receipts unless `--execute-control`/`--execute-service-control` is passed, and wrapper `service-start-plan`/`service-stop-plan` proves those receipts against `EventLog`; explicit install/control execution now refuses as `execution-refused-not-elevated` with `executed=false` when the shell lacks Windows administrator authority, and wrapper `service-install-execute`, `service-start-execute`, and `service-stop-execute` prove those refusal receipts without mutation. Service lifecycle actions check the local Verse swarm brake before process launch, artifact writes, service-manager queries, service-policy reconciliation, execution-readiness checks, control planning, elevation-gated execution, or start/stop execution. The local wrapper builds/checks this binary.
|
||||
- Use `notes/epiphany-repo-swarm-mvp-contract.md` as the authority correction for repo-swarm autonomy. Autonomous branch-local work inside an Epiphany-owned Body is in scope and is the desired operating mode; the safety boundary is typed authority, branch containment, interruptibility, receipts, private-state sealing, and Bifrost-gated publication/merge/escalation, not asking a human before every local edit. Seven native repo-swarm front doors are live: `epiphany-repo init --workspace <repo>` writes the repo-swarm init receipt and branch workbench plan; `epiphany-swarm online --workspace <repo>` seeds repo-local `.epiphany/local-verse.ccmp`, standing-faculty SoA, topology/liveness/tool/overview proof, and `.epiphany/swarm-online/repo-swarm-online-receipt.json`; `epiphany-work accept --workspace <repo> --from persona-or-bifrost --item <id>` routes a Persona/Bifrost item through CultMesh collaboration feedback into Imagination consensus discovery and writes `.epiphany/work/work-accept-<item>.json` with no Hands, durable-state, or publication authority granted; `epiphany-work run --workspace <repo> [--item <id>]` persists a repo-local runtime-spine Substrate Gate read/snapshot grant, Hands intent, and Hands review with `decision=queued-for-adoption`; `epiphany-work adopt --workspace <repo> --item <id> --plan-summary <text> --adoption-evidence-ref <ref>` requires explicit Imagination/Self/Mind adoption evidence and promotes that queued review to an approved branch-local Hands gate; `epiphany-work execute --workspace <repo> --item <id> --command <command> --changed-path <path> --commit-message <text>` consumes the approved gate on an `epiphany/*` branch, runs the command in the repo Body, captures stdout/stderr artifacts, stages only declared paths, commits, and records Hands patch/command/commit receipts; `epiphany-work publish --workspace <repo> --item <id> ...` requires Hands commit proof plus Soul verification and Mind/review refs, routes Bifrost publication/GitHub publication receipts, records a Hands PR receipt, and keeps `upstreamMainSynced=false` / `mergeAuthorized=false`. Fresh-repo smokes proved init, online, accept, run, adopt, execute, and publish with `privateStateExposed=false`; pre-adoption gates still refuse record-pass. Next missing organ is a merge/sync gate that proves upstream main is actually synced after publication, plus a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments.
|
||||
- Use `notes/epiphany-repo-swarm-mvp-contract.md` as the authority correction for repo-swarm autonomy. Autonomous branch-local work inside an Epiphany-owned Body is in scope and is the desired operating mode; the safety boundary is typed authority, branch containment, interruptibility, receipts, private-state sealing, and Bifrost-gated publication/merge/escalation, not asking a human before every local edit. Eight native repo-swarm front doors are live: `epiphany-repo init --workspace <repo>` writes the repo-swarm init receipt and branch workbench plan; `epiphany-swarm online --workspace <repo>` seeds repo-local `.epiphany/local-verse.ccmp`, standing-faculty SoA, topology/liveness/tool/overview proof, and `.epiphany/swarm-online/repo-swarm-online-receipt.json`; `epiphany-work accept --workspace <repo> --from persona-or-bifrost --item <id>` routes a Persona/Bifrost item through CultMesh collaboration feedback into Imagination consensus discovery and writes `.epiphany/work/work-accept-<item>.json` with no Hands, durable-state, or publication authority granted; `epiphany-work run --workspace <repo> [--item <id>]` persists a repo-local runtime-spine Substrate Gate read/snapshot grant, Hands intent, and Hands review with `decision=queued-for-adoption`; `epiphany-work adopt --workspace <repo> --item <id> --plan-summary <text> --adoption-evidence-ref <ref>` requires explicit Imagination/Self/Mind adoption evidence and promotes that queued review to an approved branch-local Hands gate; `epiphany-work execute --workspace <repo> --item <id> --command <command> --changed-path <path> --commit-message <text>` consumes the approved gate on an `epiphany/*` branch, runs the command in the repo Body, captures stdout/stderr artifacts, stages only declared paths, commits, and records Hands patch/command/commit receipts; `epiphany-work publish --workspace <repo> --item <id> ...` requires Hands commit proof plus Soul verification and Mind/review refs, routes Bifrost publication/GitHub publication receipts, records a Hands PR receipt, and keeps `upstreamMainSynced=false` / `mergeAuthorized=false`; `epiphany-work sync --workspace <repo> --item <id> --upstream-ref origin/main --merge-receipt <ref>` requires an explicit maintainer/Bifrost merge receipt, verifies the published commit is an ancestor of upstream main, and writes `upstreamMainSynced=true` only after git proves it. Fresh-repo smokes proved init, online, accept, run, adopt, execute, publish, and sync with `privateStateExposed=false`; the sync smoke proved `upstream-main-not-synced` before fast-forwarding main and `upstream-main-synced` after `git merge --ff-only`. Pre-adoption gates still refuse record-pass. Next missing organs are a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments, plus scheduler physiology for advancing safe branch-local work without manual CLI stepping.
|
||||
- Agent memory lifecycle now has a first typed v0 operation surface in `epiphany-core::agent_memory`: `AgentMemoryLifecycleOperation` can revise, retire, crystallize, prune, and merge bounded memory records after role/agent review, and `epiphany-agent-memory-store review-lifecycle|apply-lifecycle` exposes the path at the operator edge. This closes the first explicit lifecycle-operation slice from the swarm-readiness gate; it does not yet make sleep silently mutate identity or project truth.
|
||||
- Persona public speech now has a parent-side eligibility receipt at the Discord/Aquarium mouth edge. `epiphany.persona_speech_audit.v0` records action kind, content fingerprint, opening/topic keys, recent-window counts, repeated opening/topic counts, channel saturation, and allow/block reasons. `epiphany-persona-discord post` blocks repeated public openings before token/webhook work; draft and bubble still emit audit receipts for operator inspection. The compatibility JSON artifact remains for display, but the durable witness is now `epiphany.cultmesh.persona_speech_audit.v0` in CultMesh with latest-key projection through local Verse context. Local MVP Persona bubbles now write that durable witness to `.epiphany-run/cultmesh/local-verse.ccmp`, not a separate mouth-side store. This is posting-edge policy, not a Persona prompt wish.
|
||||
- Grow the VoidBot repo-Persona pattern into Epiphany's product direction: each Epiphany owns one or more repos, has one or more Personas, and exposes project-native conversation through Aquarium, Discord, voice/WebRTC, stream surfaces, CLI, and CultNet clients so humans can talk to projects instead of pre-authoring complete implementation briefs. Persona is special because Imagination acts as Projector, turning typed state into narrative context before the Persona thinks, and Mind acts as Interpreter, turning natural Persona output into reviewed state/side-effect intents after the Persona thinks.
|
||||
|
|
@ -633,4 +633,4 @@ 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.
|
||||
next_action: Continue repo-swarm MVP work from the seven live front doors. The current native chain proves `epiphany-repo init`, `epiphany-swarm online`, `epiphany-work accept`, `epiphany-work run`, `epiphany-work adopt`, `epiphany-work execute`, and `epiphany-work publish` through branch-local Hands receipts and Bifrost/GitHub publication receipts with private state sealed and `upstreamMainSynced=false`. Next build either a merge/sync gate that proves upstream main actually matches the accepted Bifrost publication, or a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments. Preserve Idunn service lifecycle surfaces and the existing CultMesh/Odin/Eve tool directories while doing so; service install/start execution still requires explicit elevated operator authority.
|
||||
next_action: Continue repo-swarm MVP work from the eight live front doors. The current native chain proves `epiphany-repo init`, `epiphany-swarm online`, `epiphany-work accept`, `epiphany-work run`, `epiphany-work adopt`, `epiphany-work execute`, `epiphany-work publish`, and `epiphany-work sync` through branch-local Hands receipts, Bifrost/GitHub publication receipts, and upstream-main ancestry proof with private state sealed. Next build a less-manual planner/executor bridge that supplies executable commands from Imagination/Self rather than operator CLI arguments, then scheduler physiology for advancing safe branch-local work without manual CLI stepping. Preserve Idunn service lifecycle surfaces and the existing CultMesh/Odin/Eve tool directories while doing so; service install/start execution still requires explicit elevated operator authority.
|
||||
|
|
|
|||
Reference in a new issue