diff --git a/epiphany-core/src/bin/epiphany-verse-query.rs b/epiphany-core/src/bin/epiphany-verse-query.rs index a557b8ec..f0c1cb4b 100644 --- a/epiphany-core/src/bin/epiphany-verse-query.rs +++ b/epiphany-core/src/bin/epiphany-verse-query.rs @@ -1212,12 +1212,17 @@ fn run_cli() -> Result<()> { "publicationChainCount": report.publication_chain_count, "publicProofPublicationCount": report.public_proof_publication_count, "collaborationChainCount": report.collaboration_chain_count, + "accountingRowCount": report.accounting_rows.len(), + "closedAccountingRowCount": report.closed_accounting_row_count, + "attentionAccountingRowCount": report.attention_accounting_row_count, "latestBifrostPublicationIntent": report.latest_publication_intent_id, "latestBifrostPublicationReceipt": report.latest_publication_receipt_id, "latestBifrostGithubReceipt": report.latest_github_receipt_id, "latestBifrostPublicProofPublicationReceipt": report.latest_public_proof_publication_receipt_id, "latestBifrostCollaborationFeedback": report.latest_feedback_id, "latestImaginationConsensusReceipt": report.latest_consensus_receipt_id, + "accountingTuiRows": report.accounting_tui_rows, + "accountingRows": report.accounting_rows, "tuiRows": report.tui_rows, "rows": report.rows, "commands": { @@ -2690,6 +2695,9 @@ fn run_cli() -> Result<()> { if bifrost_ledger_report.status != "ok" || bifrost_ledger_report.publication_chain_count != 3 || bifrost_ledger_report.collaboration_chain_count != 2 + || bifrost_ledger_report.accounting_rows.len() != 3 + || bifrost_ledger_report.closed_accounting_row_count != 2 + || bifrost_ledger_report.attention_accounting_row_count != 0 || bifrost_ledger_report.rows.len() != 5 || bifrost_ledger_report.private_state_exposed || !bifrost_ledger_report.tui_rows.iter().any(|row| { @@ -2708,6 +2716,26 @@ fn run_cli() -> Result<()> { ) && row.contains("private=false") }) + || !bifrost_ledger_report.accounting_tui_rows.iter().any(|row| { + row.contains("BIFROST-ACCOUNTING | body-change-publication") + && row.contains("status=closed") + && row.contains("intent=present publication=present github=present") + && row.contains("review=1") + && row.contains("credit=1") + && row.contains("private=false") + }) + || !bifrost_ledger_report.accounting_tui_rows.iter().any(|row| { + row.contains("BIFROST-ACCOUNTING | public-proof-publication") + && row.contains("status=missing") + && row.contains("proof=missing") + && row.contains("private=false") + }) + || !bifrost_ledger_report.accounting_tui_rows.iter().any(|row| { + row.contains("BIFROST-ACCOUNTING | collaboration-consensus") + && row.contains("status=closed") + && row.contains("feedback=present consensus=present") + && row.contains("private=false") + }) { anyhow::bail!("local Verse query smoke lost compact Bifrost ledger readback"); } @@ -4746,9 +4774,13 @@ struct BifrostLedgerReport { status: String, rows: Vec, tui_rows: Vec, + accounting_rows: Vec, + accounting_tui_rows: Vec, publication_chain_count: usize, public_proof_publication_count: usize, collaboration_chain_count: usize, + closed_accounting_row_count: usize, + attention_accounting_row_count: usize, latest_publication_intent_id: Option, latest_publication_receipt_id: Option, latest_github_receipt_id: Option, @@ -4808,6 +4840,22 @@ struct BifrostLedgerRow { private_state_exposed: bool, } +#[derive(Serialize)] +#[serde(rename_all = "camelCase")] +struct BifrostAccountingRow { + lane: String, + owner: String, + status: String, + closure: String, + ledger_entry_id: String, + latest_receipt_id: String, + public_ref: String, + review_receipt_count: usize, + credit_receipt_count: usize, + public_artifact_count: usize, + private_state_exposed: bool, +} + #[derive(Clone, Serialize)] #[serde(rename_all = "camelCase")] struct DaemonToolDirectoryRow { @@ -8039,6 +8087,22 @@ fn bifrost_ledger_report( let public_proof_publication_count = usize::from(latest_public_proof_publication.is_some()); let collaboration_chain_count = usize::from(latest_feedback.is_some()) + usize::from(latest_consensus.is_some()); + let (accounting_rows, accounting_tui_rows) = bifrost_accounting_rows( + latest_intent, + latest_publication, + latest_github, + latest_public_proof_publication, + latest_feedback, + latest_consensus, + ); + let closed_accounting_row_count = accounting_rows + .iter() + .filter(|row| row.status == "closed") + .count(); + let attention_accounting_row_count = accounting_rows + .iter() + .filter(|row| row.status == "attention" || row.private_state_exposed) + .count(); let private_state_exposed = rows.iter().any(|row| row.private_state_exposed); let status = if rows.is_empty() { "empty" @@ -8053,9 +8117,13 @@ fn bifrost_ledger_report( status, rows, tui_rows, + accounting_rows, + accounting_tui_rows, publication_chain_count, public_proof_publication_count, collaboration_chain_count, + closed_accounting_row_count, + attention_accounting_row_count, latest_publication_intent_id: latest_intent.map(|intent| intent.intent_id.clone()), latest_publication_receipt_id: latest_publication.map(|receipt| receipt.receipt_id.clone()), latest_github_receipt_id: latest_github.map(|receipt| receipt.receipt_id.clone()), @@ -8089,6 +8157,220 @@ fn push_bifrost_ledger_row( rows.push(row); } +fn bifrost_accounting_rows( + latest_intent: Option<&EpiphanyCultMeshBifrostBodyChangePublicationIntentEntry>, + latest_publication: Option<&EpiphanyCultMeshBifrostBodyChangePublicationReceiptEntry>, + latest_github: Option<&EpiphanyCultMeshBifrostGithubPublicationReceiptEntry>, + latest_public_proof_publication: Option< + &EpiphanyCultMeshBifrostPublicProofPublicationReceiptEntry, + >, + latest_feedback: Option<&EpiphanyCultMeshBifrostCollaborationFeedbackEntry>, + latest_consensus: Option<&EpiphanyCultMeshImaginationConsensusReceiptEntry>, +) -> (Vec, Vec) { + let mut rows = Vec::new(); + let mut tui_rows = Vec::new(); + + let body_private = latest_intent + .map(|intent| intent.private_state_included) + .unwrap_or(false) + || latest_publication + .map(|receipt| receipt.private_state_exposed) + .unwrap_or(false) + || latest_github + .map(|receipt| receipt.private_state_exposed) + .unwrap_or(false); + let body_review_count = latest_publication + .map(|receipt| receipt.reviewer_ids.len()) + .or_else(|| latest_intent.map(|intent| intent.review_receipt_ids.len())) + .unwrap_or(0); + let body_credit_count = latest_github + .map(|receipt| receipt.credit_receipt_ids.len()) + .or_else(|| latest_publication.map(|receipt| receipt.credit_receipt_ids.len())) + .or_else(|| latest_intent.map(|intent| intent.credit_subjects.len())) + .unwrap_or(0); + let body_chain_closed = latest_intent.is_some() + && latest_publication.is_some() + && latest_github.is_some() + && body_review_count > 0 + && body_credit_count > 0 + && !body_private; + push_bifrost_accounting_row( + &mut rows, + &mut tui_rows, + BifrostAccountingRow { + lane: "body-change-publication".to_string(), + owner: "Bifrost".to_string(), + status: bifrost_accounting_status( + body_chain_closed, + latest_intent.is_some() || latest_publication.is_some() || latest_github.is_some(), + body_private, + ), + closure: format!( + "intent={} publication={} github={} review={} credit={}", + present_word(latest_intent.is_some()), + present_word(latest_publication.is_some()), + present_word(latest_github.is_some()), + body_review_count, + body_credit_count + ), + ledger_entry_id: latest_publication + .map(|receipt| receipt.bifrost_ledger_entry_id.clone()) + .or_else(|| latest_github.map(|receipt| receipt.ledger_entry_id.clone())) + .unwrap_or_else(|| "none".to_string()), + latest_receipt_id: latest_github + .map(|receipt| receipt.receipt_id.clone()) + .or_else(|| latest_publication.map(|receipt| receipt.receipt_id.clone())) + .or_else(|| latest_intent.map(|intent| intent.intent_id.clone())) + .unwrap_or_else(|| "none".to_string()), + public_ref: latest_github + .map(|receipt| receipt.pull_request_url.clone()) + .or_else(|| latest_publication.map(|receipt| receipt.publication_url.clone())) + .or_else(|| latest_intent.map(|intent| intent.target_branch.clone())) + .unwrap_or_else(|| "none".to_string()), + review_receipt_count: body_review_count, + credit_receipt_count: body_credit_count, + public_artifact_count: usize::from(latest_github.is_some()), + private_state_exposed: body_private, + }, + ); + + let proof_private = latest_public_proof_publication + .map(|receipt| receipt.private_state_exposed) + .unwrap_or(false); + let proof_review_count = latest_public_proof_publication + .map(|receipt| receipt.reviewer_ids.len()) + .unwrap_or(0); + let proof_credit_count = latest_public_proof_publication + .map(|receipt| receipt.credit_receipt_ids.len()) + .unwrap_or(0); + let proof_closed = latest_public_proof_publication.is_some() + && proof_review_count > 0 + && proof_credit_count > 0 + && !proof_private; + push_bifrost_accounting_row( + &mut rows, + &mut tui_rows, + BifrostAccountingRow { + lane: "public-proof-publication".to_string(), + owner: "Bifrost".to_string(), + status: bifrost_accounting_status( + proof_closed, + latest_public_proof_publication.is_some(), + proof_private, + ), + closure: format!( + "proof={} review={} credit={}", + present_word(latest_public_proof_publication.is_some()), + proof_review_count, + proof_credit_count + ), + ledger_entry_id: latest_public_proof_publication + .map(|receipt| receipt.bifrost_ledger_entry_id.clone()) + .unwrap_or_else(|| "none".to_string()), + latest_receipt_id: latest_public_proof_publication + .map(|receipt| receipt.receipt_id.clone()) + .unwrap_or_else(|| "none".to_string()), + public_ref: latest_public_proof_publication + .map(|receipt| receipt.publication_url.clone()) + .unwrap_or_else(|| "none".to_string()), + review_receipt_count: proof_review_count, + credit_receipt_count: proof_credit_count, + public_artifact_count: usize::from(latest_public_proof_publication.is_some()), + private_state_exposed: proof_private, + }, + ); + + let collaboration_private = latest_feedback + .map(|feedback| feedback.private_state_included) + .unwrap_or(false) + || latest_consensus + .map(|receipt| receipt.private_state_exposed) + .unwrap_or(false); + let collaboration_public_count = latest_feedback + .map(|feedback| feedback.public_discussion_refs.len()) + .unwrap_or(0) + + latest_consensus + .map(|receipt| receipt.public_feedback_refs.len()) + .unwrap_or(0); + let collaboration_closed = + latest_feedback.is_some() && latest_consensus.is_some() && !collaboration_private; + push_bifrost_accounting_row( + &mut rows, + &mut tui_rows, + BifrostAccountingRow { + lane: "collaboration-consensus".to_string(), + owner: "Persona->Imagination".to_string(), + status: bifrost_accounting_status( + collaboration_closed, + latest_feedback.is_some() || latest_consensus.is_some(), + collaboration_private, + ), + closure: format!( + "feedback={} consensus={} publicRefs={}", + present_word(latest_feedback.is_some()), + present_word(latest_consensus.is_some()), + collaboration_public_count + ), + ledger_entry_id: "none".to_string(), + latest_receipt_id: latest_consensus + .map(|receipt| receipt.receipt_id.clone()) + .or_else(|| latest_feedback.map(|feedback| feedback.feedback_id.clone())) + .unwrap_or_else(|| "none".to_string()), + public_ref: latest_feedback + .map(|feedback| feedback.public_room_id.clone()) + .unwrap_or_else(|| "none".to_string()), + review_receipt_count: 0, + credit_receipt_count: 0, + public_artifact_count: collaboration_public_count, + private_state_exposed: collaboration_private, + }, + ); + + (rows, tui_rows) +} + +fn push_bifrost_accounting_row( + rows: &mut Vec, + tui_rows: &mut Vec, + row: BifrostAccountingRow, +) { + let private = if row.private_state_exposed { + "private=true" + } else { + "private=false" + }; + tui_rows.push(format!( + "BIFROST-ACCOUNTING | {} | owner={} | status={} | {} | ledger={} | receipt={} | public={} | review={} | credit={} | artifacts={} | {private}", + row.lane, + row.owner, + row.status, + row.closure, + row.ledger_entry_id, + row.latest_receipt_id, + row.public_ref, + row.review_receipt_count, + row.credit_receipt_count, + row.public_artifact_count + )); + rows.push(row); +} + +fn bifrost_accounting_status(closed: bool, present: bool, private_state_exposed: bool) -> String { + if private_state_exposed { + "attention".to_string() + } else if closed { + "closed".to_string() + } else if present { + "open".to_string() + } else { + "missing".to_string() + } +} + +fn present_word(present: bool) -> &'static str { + if present { "present" } else { "missing" } +} + fn collaboration_feedback_tui_rows( feedback: &EpiphanyCultMeshBifrostCollaborationFeedbackEntry, consensus: &EpiphanyCultMeshImaginationConsensusReceiptEntry, diff --git a/notes/epiphany-repo-swarm-mvp-contract.md b/notes/epiphany-repo-swarm-mvp-contract.md index e802ba5b..febd6688 100644 --- a/notes/epiphany-repo-swarm-mvp-contract.md +++ b/notes/epiphany-repo-swarm-mvp-contract.md @@ -1552,6 +1552,17 @@ published `repo-work-public-proof-checklist-request` to `bifrost-public-proof-publication-checklist-request`, `status=ok`, and `privateStateExposed=false`. +Bifrost ledger readback now also emits derived external-work accounting rows +without creating a rival ledger. `epiphany-verse-query bifrost-ledger` returns +`accountingRows` and `accountingTuiRows` for `body-change-publication`, +`public-proof-publication`, and `collaboration-consensus`, carrying closure +status, ledger/receipt/public refs, review and credit receipt counts, artifact +count, and the private-state seal. Wrapper proof +`local-20260621-091019-297-aaf2ad07` reported `accountingRows=3`, +`closedAccounting=2`, `attentionAccounting=0`, closed body-change and +collaboration rows, a visible missing public-proof-publication row, and +`privateStateExposed=False`. + Wrapper mode `tools/epiphany_local_run.ps1 -Mode bifrost-public-proof` now exposes the same Bifrost mouth for operators and agents. It reads the latest repo-local public proof row from `\.epiphany\local-verse.ccmp` when diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index bde5fcac..f49e33fb 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -57,7 +57,7 @@ remembers doctrine; the branch remembers the blade. - `epiphany-verse-query connect-eve` and `tools/epiphany_local_run.ps1 -Mode eve-connect` are the compact Odin-to-Eve connection receipt rite. The command now selects its target from the narrow Eve surface directory and verifies latest intent/receipt keys through narrow CultMesh loaders instead of serializing the full local Verse. The wrapper defaults to `epiphany.cluster.persona`, records intent `eve-connection-intent` plus receipt `eve-connection-receipt`, targets `eve://epiphany/persona`, and keeps `privateStateExposed=false`. Verified: direct temp proof and wrapper proof both returned `status=ok`. - `epiphany-verse-query collaboration-feedback` and `tools/epiphany_local_run.ps1 -Mode collaboration-feedback` are the compact public Persona feedback to Imagination consensus receipt rite. The command verifies latest feedback/consensus keys through narrow CultMesh loaders and emits follow-on commands for wrapper feedback, Eve connection, direct Bifrost publication, and wrapper Bifrost publication. It returns TUI rows for the feedback and Imagination consensus receipt with `owner=Persona->Imagination`, `owner=Imagination`, `public=`, candidate action refs, consensus packet ref, adoption gate, and `private=false`. The wrapper first records the prerequisite Eve connection receipt, then writes feedback `collaboration-feedback` plus consensus `imagination-consensus-receipt`; proof `local-20260618-224207-941-2ca01b41` printed both compact rows in `feedbackRows`, including Persona public discussion feedback routed to Imagination consensus discovery, with `privateStateExposed=False`. - `epiphany-verse-query bifrost-publication` and `tools/epiphany_local_run.ps1 -Mode bifrost-publication` are the compact non-mutating body-change publication proof rite. The command verifies latest Bifrost intent/publication/GitHub receipt keys through narrow CultMesh loaders and now emits follow-on commands for swarm overview, tool directory, and wrapper Bifrost publication readback. The wrapper supplies explicit proof defaults for target repo, changed path, verification/review receipts, credit subject, ledger id, Hands PR receipt id, and publication URL, then writes Bifrost intent, Bifrost publication receipt, and GitHub publication receipt with `privateStateExposed=false`. Verified: direct proof and wrapper proof both returned `status=ok`, and wrapper artifact `local-20260618-072118-704-3c5ae3da` carried the command hints. -- `epiphany-verse-query bifrost-ledger` and `tools/epiphany_local_run.ps1 -Mode bifrost-ledger` are the compact read-only Bifrost ledger sight rite. The command reads only the latest Bifrost body-change intent, Bifrost publication receipt, GitHub publication receipt, collaboration feedback, and Imagination consensus receipt through narrow CultMesh loaders, then returns five TUI rows when both chains exist. TUI rows include explicit `owner=`, `public=`, and `private=false`, and wrapper proof `local-20260618-223951-549-747c02f9` prints all five rows in `ledgerRows`: `owner=Bifrost` body-change intent/publication receipt, `owner=Bifrost/GitHub` GitHub publication receipt, `owner=Persona->Imagination` collaboration feedback, and `owner=Imagination` consensus receipt. Verified: source smoke and live wrapper both returned `status=ok`, `publicationChainCount=3`, `collaborationChainCount=2`, `rowCount=5`, and `privateStateExposed=false`. +- `epiphany-verse-query bifrost-ledger` and `tools/epiphany_local_run.ps1 -Mode bifrost-ledger` are the compact read-only Bifrost ledger sight rite. The command reads only the latest Bifrost body-change intent, Bifrost publication receipt, GitHub publication receipt, public-proof publication receipt, collaboration feedback, and Imagination consensus receipt through narrow CultMesh loaders. It returns raw ledger rows plus three derived `BIFROST-ACCOUNTING` rows for body-change publication, public-proof publication, and collaboration consensus, with closure status, ledger/receipt/public refs, review and credit receipt counts, artifact count, and private-state seal. Wrapper proof `local-20260621-091019-297-aaf2ad07` returned `accountingRows=3`, `closedAccounting=2`, `attentionAccounting=0`, closed body-change and collaboration rows, a visible missing public-proof-publication row, and `privateStateExposed=False`. - `epiphany-verse-query receipt-directory` and `tools/epiphany_local_run.ps1 -Mode receipt-directory` are the compact latest-witness directory over local Verse. The command indexes typed projections for operator run, daemon poke, daemon tool invocation, Eve connection, Bifrost publication, Imagination consensus, coordinator run, Hands gate, role review, work-loop, cluster service lifecycle, single-service lifecycle, cluster service execution runbook, single-service execution runbook, scheduler, Persona speech, and agent-state SoA without exposing raw payloads or private worker context. It treats sealed service lifecycle failure states such as `not-elevated`, `execution-refused-not-elevated`, and `incomplete` as operator attention instead of private-state exposure, routes cluster lifecycle wounds to `cluster-service-execution-audit`, preserves `service-execution-audit` for single-service receipts, and exposes the runbook witnesses as separate display-only `cluster-service-execution-runbook` and `service-execution-runbook` rows. The lifecycle projection now reads the typed receipt family, splits `cluster-service-lifecycle` from `service-lifecycle`, selects the latest attention receipt before falling back to latest overall, and renders service lifecycle routes as `service-id::action` so compact rows name the owning lifecycle action without exposing raw audit payloads. Compact TUI rows append `followUp=`, artifact status, and SHA-256; wrapper proof `local-20260618-205920-451-383b0da7` printed all seventeen rows in `receiptRows`, including missing Hands/role/work-loop gates, Bifrost/Imagination witnesses, scheduler follow-up, runbook hashes, and service lifecycle attention. `missingRowCount` remains as a compatibility alias for absent witnesses, not a fault signal. Attention routing is now Rust-owned too: JSON includes `attentionRouteRows` derived from the same predicate as `attentionRowCount`, and the wrapper prints that field instead of matching arbitrary status strings. Live proof `local-20260618-212134-758-c7c56240` showed the stale degraded Hands daemon-poke receipt remains an `OK` historical row while `attentionRoutes` names only the active cluster/single-service lifecycle wounds. Daemon-poke rows now also resolve historical receipt status against current daemon liveness: source smoke proves degraded remains degraded before heartbeat recovery and becomes `resolved` after ready status returns, and live wrapper proof `local-20260618-212649-563-48647018` printed the old Hands poke receipt as `OK | Self | daemon-poke | resolved`. - Public doctrine source `https://gamecult.org/Blog/purge-the-heretek-from-our-daemonic-swarm` sharpens the current swarm audit: Odin sees but must not own, Gjallar is Odin's herald for whole-Verse sight, Idunn-like ledgers must advance instead of freezing old wounds, and Bifrost is the ledger gate for cross-repo purification receipts rather than transcript archaeology. - `tools/epiphany_local_run.ps1` now stamps local run ids as `local-YYYYMMDD-HHMMSS-fff-` instead of second-resolution ids, so concurrent operator rites get separate artifact roots and run receipts. Verified: `collaboration-feedback` and `bifrost-publication` launched in parallel in the same second and completed as `local-20260618-064814-171-dc0b8dd9` and `local-20260618-064814-149-2946d675`. @@ -181,7 +181,7 @@ remembers doctrine; the branch remembers the blade. - `eve-connect` is the compact connection actuator for the advertised Eve surface; use it when the operator wants a typed collaboration receipt for Persona's public surface without opening the whole local Verse. - `collaboration-feedback` is the compact public-feedback actuator; use it after or instead of manual `eve-connect` when Persona/human discussion should be routed to Imagination consensus discovery as typed local Verse receipts. Its JSON now points the next agent at Eve and Bifrost follow-on rites. - `bifrost-publication` is the compact non-mutating Bifrost publication proof; use it to prove body-change routing, credit, and GitHub publication receipt state without performing GitHub mutation. Its JSON now points back to compact swarm overview and tool-directory readback. -- `bifrost-ledger` is the compact Bifrost/Imagination readback rite; use it after collaboration or publication writes to see the latest body-change, GitHub, feedback, and consensus receipts without opening the full local Verse. +- `bifrost-ledger` is the compact Bifrost/Imagination readback rite; use it after collaboration or publication writes to see the latest body-change, public-proof, GitHub, feedback, consensus, credit/review-count, and accounting closure rows without opening the full local Verse. - `tool-directory` is the non-mutating daemon tool sight rite; it shows which globally available daemon-hosted tools any agent can invoke through typed intents and receipts, while still exposing host readiness. - `tool-invoke` now embeds compact readbacks for common daemon-hosted tools. Status calls return `daemonStatusReadback`, Eve calls return `eveConnectionReadback`, Self `service-health` returns Idunn-owned `serviceHealthReadback`, Self `service-policy-directory` returns Idunn-owned `servicePolicyDirectoryReadback`, Self `swarm-online-runbook` returns Idunn-owned `swarmOnlineRunbookReadback`, and Hands/Soul authority tools return `authorityToolReadback` with gate, input contract, receipt contract, intent/receipt routes, host cluster, and private-state seal. This proves global tool ergonomics without moving action, verification, or daemon lifecycle ownership into the wrapper; live proofs routed Persona to Hands `repo-action` (`local-20260619-021628-143-7bf7f2e0`), Soul `verify` (`local-20260619-021701-458-852cfa6f`), Self `swarm-online-runbook` (`local-20260619-032244-273-acb3c6a4`), and Self `service-policy-directory` (`local-20260619-035238-138-633f3ff0`) with `privateStateExposed=false`. - 2026-06-19: The Self service tool readbacks now carry Idunn ownership at the top-level tool mouth, not only inside action rows. `serviceHealthReadback` and `swarmOnlineRunbookReadback` both include `lifecycleOwner=Idunn` and `hostedBody=Epiphany`; source smoke guards both fields; wrapper `tool-invoke` summaries print `owner=Idunn:hostedBody=Epiphany`. Live proofs `local-20260619-034243-246-b5704cd8` (`service-health`) and `local-20260619-034148-683-ea6c0ed6` (`swarm-online-runbook`) stayed non-mutating and `privateStateExposed=False`. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index a11e8d93..89127fbc 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 6af8be23..8ed1cfc2 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -623,7 +623,7 @@ current_status: - `epiphany-verse-query connect-eve` and `tools/epiphany_local_run.ps1 -Mode eve-connect` provide the compact Odin-to-Eve collaboration receipt. The command selects the daemon-published surface through the narrow Eve directory, writes connection intent/receipt documents, verifies latest receipt keys through narrow CultMesh loaders, defaults the wrapper target to `epiphany.cluster.persona`, and exposes no private state. - `epiphany-verse-query collaboration-feedback` and `tools/epiphany_local_run.ps1 -Mode collaboration-feedback` provide the public Persona feedback to Imagination consensus receipt path. The wrapper records the prerequisite Eve connection receipt, writes feedback plus Imagination consensus receipt documents, verifies latest keys through narrow CultMesh loaders, publishes follow-on command hints for wrapper feedback, Eve connection, direct Bifrost publication, and wrapper Bifrost publication, and exposes no private state. The command returns compact TUI rows for the feedback and Imagination consensus receipt with explicit `owner=Persona->Imagination` / `owner=Imagination`, `public=`, candidate action refs, consensus packet ref, adoption gate, and `private=false`; wrapper proof `local-20260618-224207-941-2ca01b41` prints both rows in `feedbackRows`, including Persona public discussion feedback routed to Imagination consensus discovery before Mind/Bifrost adoption. - `epiphany-verse-query bifrost-publication` and `tools/epiphany_local_run.ps1 -Mode bifrost-publication` provide the non-mutating Bifrost body-change publication proof path. It writes Bifrost intent, Bifrost publication receipt, and GitHub publication receipt documents from explicit review/verification/credit inputs, verifies latest keys through narrow CultMesh loaders, publishes follow-on command hints for swarm overview, tool directory, and wrapper Bifrost publication readback, and exposes no private state. - - `epiphany-verse-query bifrost-ledger` and `tools/epiphany_local_run.ps1 -Mode bifrost-ledger` provide the compact Bifrost ledger sight organ. It reads only the latest Bifrost body-change intent, Bifrost publication receipt, GitHub publication receipt, collaboration feedback, and Imagination consensus receipt through narrow CultMesh loaders, returns five agent-friendly TUI rows when both chains exist, publishes follow-on command hints for swarm overview, tool directory, collaboration feedback, Bifrost publication, and Bifrost ledger readback, and exposes no private state. Compact ledger rows carry explicit `owner=`, `public=`, and `private=false`, so body-change/public-feedback proof is inspectable without opening raw local Verse payloads or inferring authority from document names; wrapper proof `local-20260618-223951-549-747c02f9` prints all five rows in `ledgerRows`, covering `owner=Bifrost`, `owner=Bifrost/GitHub`, `owner=Persona->Imagination`, and `owner=Imagination` across the body-change intent, Bifrost publication receipt, GitHub receipt, collaboration feedback, and Imagination consensus receipt. + - `epiphany-verse-query bifrost-ledger` and `tools/epiphany_local_run.ps1 -Mode bifrost-ledger` provide the compact Bifrost ledger sight organ. It reads only the latest Bifrost body-change intent, Bifrost publication receipt, GitHub publication receipt, public-proof publication receipt, collaboration feedback, and Imagination consensus receipt through narrow CultMesh loaders, returns agent-friendly ledger TUI rows, publishes follow-on command hints for swarm overview, tool directory, collaboration feedback, Bifrost publication, and Bifrost ledger readback, and exposes no private state. Compact ledger rows carry explicit `owner=`, `public=`, and `private=false`, so body-change/public-feedback proof is inspectable without opening raw local Verse payloads or inferring authority from document names. Bifrost ledger readback now also derives three `BIFROST-ACCOUNTING` rows for `body-change-publication`, `public-proof-publication`, and `collaboration-consensus`, with closure status, ledger/receipt/public refs, review and credit receipt counts, artifact count, and private-state seal. Wrapper proof `local-20260621-091019-297-aaf2ad07` printed `accountingRows=3`, `closedAccounting=2`, `attentionAccounting=0`, closed body-change and collaboration rows, a visible missing public-proof-publication row, and `privateStateExposed=False`. - `epiphany-verse-query receipt-directory` and `tools/epiphany_local_run.ps1 -Mode receipt-directory` provide the compact latest-witness directory over local Verse. It indexes operator run, daemon poke, daemon tool invocation, Eve connection, Bifrost publication, Imagination consensus, coordinator run, Hands gate, role review, work-loop, cluster service lifecycle, single-service lifecycle, cluster service execution runbook, single-service execution runbook, scheduler, Persona speech, and agent-state SoA witness families from typed local Verse projections; returns agent-friendly `OK`/`ABSENT`/`ATTN` TUI rows with owner, family, status, route, latest id, follow-up command, `presentRowCount`, and `absentRowCount`; preserves `missingRowCount` as compatibility for absent witnesses; flags sealed service lifecycle failure states such as `not-elevated`, `execution-refused-not-elevated`, and `incomplete` as attention without exposing receipt payloads; routes service lifecycle receipts by their typed receipt action through `service_execution_check_follow_up_command` (readiness to readiness, install to install execute, start/stop to control execute, status/reconcile to their readback rites, audit to audit), while cluster/single execution-runbook witnesses route to their runbook regeneration wrappers; and exposes no private state or receipt payload previews. The lifecycle projection now reads the typed receipt family, splits `cluster-service-lifecycle` from `service-lifecycle`, selects the latest attention receipt before falling back to latest overall, and exposes `service-id::action` route values such as `epiphany-cluster-daemon-services::cluster-windows-service-execution-audit`, so agents can see the owning lifecycle action without opening raw audit JSON. Compact receipt TUI rows append `followUp=`, artifact status, and SHA-256; wrapper proof `local-20260618-205920-451-383b0da7` now prints all seventeen compact rows in `receiptRows`, including missing Hands/role/work-loop gates, runbook hashes, scheduler follow-up, Bifrost/Imagination witnesses, and the active service lifecycle attention rows. It also exposes `cluster-service-execution-runbook` plus `service-execution-runbook` as display-only rows, so newer harmless planned/runbook lifecycle receipts cannot hide the active seven-service cluster wound. Receipt-directory JSON now carries Rust-owned `attentionRouteRows` derived from the same policy predicate as `attentionRowCount`, and the wrapper prints that field instead of rebuilding attention from ad hoc status strings; source smoke now proves a `cluster-windows-service-execution-readiness` receipt routes to `cluster-service-execution-readiness` and wrapper mode `cluster-service-execution-readiness` instead of laundering the row through audit. Live proof `local-20260618-212134-758-c7c56240` left the old degraded Hands daemon-poke receipt as an `OK` historical witness while attention routes named only the cluster and single-service lifecycle wounds. Daemon-poke rows now resolve historical receipt status against current daemon liveness: source smoke proves degraded remains degraded before heartbeat recovery and becomes `resolved` after current status returns ready, while live wrapper proof `local-20260618-212649-563-48647018` printed the old Hands poke receipt as `OK | Self | daemon-poke | resolved`. - `tools/epiphany_local_run.ps1 -Mode service-tick` is the wrapper-owned daemon scheduler pulse rite. It runs `epiphany-daemon-supervisor tick` through the same local Verse store, operator run intent/receipt, agent-state SoA refresh, and swarm-brake preflight as other service lifecycle modes, but leaves restart authority inside durable daemon restart policies. The receipt directory scheduler row now follows up with `tools/epiphany_local_run.ps1 -Mode service-tick` instead of passive service status. Proof seeded one disabled Persona restart policy as inert policy metadata, then the wrapper wrote `daemon-scheduler-receipt-epiphany-daemon-supervisor-0` with `status=tickComplete`, `outcomeCount=1`, `skippedCount=1`, `restartedCount=0`, `refusedCount=0`, and `privateStateExposed=false`; the follow-up receipt-directory proof reported the scheduler row as present with route `*`, follow-up command `service-tick`, and no private-state exposure. - `epiphany-cluster-daemon` is the first real per-cluster daemon heartbeat body. It runs as a narrow Rust binary parameterized by daemon id, publishes typed `epiphany.cultmesh.daemon_status.v0` heartbeats into the shared local Verse, can run once or loop, and exposes no private state. Durable restart policies for Self, Hands, Persona, Imagination, Eyes, Modeling, and Soul now invoke `epiphany-cluster-daemon heartbeat`, not the generic query/debug writer. A degraded proof showed `service-tick` invoking all seven daemon bodies through the supervisor and restoring ready liveness with sealed scheduler/poke receipts; a fresh tick no-ops when all heartbeats are current. `epiphany-daemon-supervisor cluster-service-runbook` and wrapper `-Mode cluster-service-runbook` write a non-mutating service runbook plus `daemon_service_lifecycle` receipt for all seven organ daemon `epiphany-cluster-daemon serve` commands. Direct `service-runbook` and `cluster-service-runbook` wrapper summaries now print local artifact SHA-256 plus follow-up/aftercare wrapper routes; live proofs `local-20260618-232133-314-4e55120e` and `local-20260618-232146-541-982dd60b` showed hashes `85a956f768e584a9d098f13a9bf03fc3560915821a2ae7eaab94889dd9ecda85` and `40616423a9210101486949d07291bf795175579a39e99de5e5a759f8e0d7a78c` without service mutation. Wrapper `service-plan` and `service-launch` now expose the native daemon-supervisor service lifecycle surfaces under the same brake gate; `service-launch` silences child stdout/stderr so the parent lifecycle receipt remains the only stdout JSON. Live proof `local-20260618-232935-349-7e3901c8` completed a bounded one-iteration launch with `exitCode=0` and no private-state exposure. `epiphany-daemon-supervisor cluster-service-install-plan` and wrapper `-Mode cluster-service-install-plan` write a non-mutating Windows install script plus lifecycle receipt for seven distinct per-organ Windows services. Wrapper `-Mode cluster-service-install-execute` requests execution through the same typed path and, in non-elevated shells, writes `execution-refused-not-elevated` with `executed=false` instead of mutating services. Direct cluster install wrapper summaries now include `artifactSha256=` and `followUp=tools/epiphany_local_run.ps1 -Mode cluster-service-install-execute`; live proofs `local-20260618-230937-335-71c4fdaa` and `local-20260618-230937-313-cb288388` showed the planned and non-elevated-refused cluster install artifact hash `c6b697e173eb319073da341fc90c2963bcd6bee63d804349205b6309c88df764`. `epiphany-daemon-supervisor cluster-service-audit` and wrapper `-Mode cluster-service-audit` read Windows service-manager state for those seven expected service names, writing an incomplete audit receipt when they are missing; direct audit summaries now point missing cluster services to `cluster-service-install-plan` plus `cluster-service-execution-audit` aftercare, with live proof `local-20260618-232200-992-b842ae01` reporting seven missing services and no mutation. `epiphany-daemon-supervisor cluster-service-start`/`cluster-service-stop` and wrapper `-Mode cluster-service-start-plan`, `cluster-service-stop-plan`, `cluster-service-start-execute`, and `cluster-service-stop-execute` record cluster lifecycle receipts for all seven services: plan modes emit seven `*-planned` rows without mutation, and explicit execute modes refuse as `execution-refused-not-elevated` with seven refused rows when the shell lacks service authority. The cluster install/audit/control wrapper summaries now print compact `serviceRows` for all seven daemon-owned Windows service names with daemon id, status or observed status, cluster id, executed flag, exit code, start type, and `private=false`; live proofs `local-20260618-211051-126-2a89d61c`, `local-20260618-211051-125-cd687ee2`, `local-20260618-211051-063-f0ff980d`, and `local-20260618-211118-108-df5cb8cd` show seven missing audit rows, seven ready/demand install-plan rows, seven start-planned rows, and seven stop-planned rows without service mutation. `cluster-service-execution-runbook` writes an admin-gated wrapper sequence for cluster-native readiness, cluster install, cluster start, cluster audit, cluster stop, and final cluster audit; the artifact now uses `Invoke-EpiphanyRunbookStep` to reset `$LASTEXITCODE`, catch thrown/nonzero failures, continue gathering receipts after a failed step, and always runs `cluster-service-execution-audit` from `finally`; generated child execution runbooks no longer use `Invoke-Expression`, and each step invokes the known wrapper `ScriptPath` with an explicit `Arguments` array. The wrapper calls `epiphany-daemon-supervisor cluster-service-execution-runbook` after artifact generation, so the runbook itself has a typed `daemon_service_lifecycle` receipt with action `cluster-windows-service-execution-runbook`, status `written`, artifact path, final-audit metadata, step-failure policy metadata, and `privateStateExposed=false`. Its wrapper JSON and typed receipt args expose `runbookTryModes`, `finalAuditMode=cluster-service-execution-audit`, `finalAuditRunsInFinally=true`, `stepFailurePolicy=continue-after-step-failure`, `continueAfterStepFailure=true`, `nonzeroExitFailsStep=true`, and `exitsNonzeroAfterFinalAudit=true`; direct wrapper summaries now print the exact `elevatedCommand=Start-Process PowerShell -Verb RunAs -Wait ...` invocation, `artifactSha256=`, and `aftercare=tools/epiphany_local_run.ps1 -Mode cluster-service-execution-audit`. Live proof `local-20260619-010940-407-b0744f08` generated the robust cluster artifact and printed hash `bf116ed4fd5bb2c9dc77f5032d19e792b012941a60b109389b79e5fcb0a2a5f6` without service mutation. `cluster-service-execution-audit` first requires the sealed `cluster-windows-service-execution-runbook` receipt, then checks the latest cluster-native readiness plus cluster install/start/audit/stop lifecycle receipts by receipt timestamp and reports `complete` only when the runbook and elevated effect receipts are sealed and successful. Audit check rows retain lifecycle `operatorArtifactRef`; wrapper summaries now print OK runbook witnesses with SHA-256 before compact failed-check anatomy. Live proof `local-20260618-170322-330-e6cb2117` printed `cluster-windows-service-execution-runbook=...\epiphany-cluster-daemon-services-execution-runbook.ps1:sha256=3239ac17008b1ce857970e40b17d37a1ecf1631a3a6636bb2b8678312fb604a0` and the expected five failed checks without mutating Windows services. @@ -646,4 +646,4 @@ current_status: - Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass. - `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure. last_completed_repo_swarm_cut: Idunn-hosted repo-work queue-run lifecycle now includes bounded launch proof, not only plan/runbook artifacts. `tools/epiphany_local_run.ps1 -Mode repo-work-service-launch` routes the same `epiphany-work queue-run` command vector through `epiphany-daemon-supervisor service-launch --wait-child`, records an Idunn service lifecycle launch receipt, and does not install a Windows service, elevate, publish, merge, cross repos, or expose private state. Native proof `.epiphany-smoke\repo-work-service-lifecycle-20260621-002707` shows plan `planned`, runbook `written`, launch `completed`, launch exit code `0`, runbook directory readback before launch, launch directory readback after launch, `mutatesServiceManager=false`, `launchesService=true`, `waitChild=true`, and `privateStateExposed=false`; wrapper proof `local-20260621-012741-653-dd4fdae2` printed the same bounded launch mouth with owner `Idunn` and hosted body `repo-work`. - next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. The next useful cut is deeper Bifrost-first external work accounting, another useful repo-owned safe action family, or richer Soul/Modeling/Mind closure depth beyond the current semantic/closure map readbacks. Persona-to-Imagination consensus readback, Mind-owned interpreter brief cargo, and Gjallar closure map rows are sealed; preserve Idunn service lifecycle ownership, Bifrost publication/upstream-main ownership, Mind durable-state admission, and existing CultMesh/Odin/Eve tool directories. Windows service install/start/deployment execution still requires explicit elevated operator authority. + next_action: Continue repo-swarm MVP work from the documented Epiphany Online cut order in `notes/epiphany-repo-swarm-mvp-contract.md`. The next useful cut is another useful repo-owned safe action family, richer Soul/Modeling/Mind closure depth beyond the current semantic/closure/Bifrost accounting readbacks, or Idunn-owned queue-run service execution under explicit operator authority. Persona-to-Imagination consensus readback, Mind-owned interpreter brief cargo, Gjallar closure map rows, and Bifrost ledger accounting rows are sealed; preserve Idunn service lifecycle ownership, Bifrost publication/upstream-main ownership, Mind durable-state admission, and existing CultMesh/Odin/Eve tool directories. Windows service install/start/deployment execution still requires explicit elevated operator authority. diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 index 40ba1ee5..3df1fc77 100644 --- a/tools/epiphany_local_run.ps1 +++ b/tools/epiphany_local_run.ps1 @@ -2329,6 +2329,10 @@ if ($resultPath -ne "" -and (Test-Path -LiteralPath $resultPath)) { if ($null -ne $result.tuiRows -and $result.tuiRows.Count -gt 0) { $ledgerRows = ($result.tuiRows -join "; ") } + $accountingRows = "none" + if ($null -ne $result.accountingTuiRows -and $result.accountingTuiRows.Count -gt 0) { + $accountingRows = ($result.accountingTuiRows -join "; ") + } $publicRefs = "none" if ($null -ne $result.rows -and $result.rows.Count -gt 0) { $publicRefs = (($result.rows | ForEach-Object { @@ -2339,7 +2343,7 @@ if ($resultPath -ne "" -and (Test-Path -LiteralPath $resultPath)) { "$($_.documentKind)=${publicRef}" }) -join "; ") } - Write-Host "Bifrost ledger: status=$($result.status), rows=$($result.rowCount), publicationChain=$($result.publicationChainCount), collaborationChain=$($result.collaborationChainCount), publicRefs=$publicRefs, ledgerRows=$ledgerRows, privateStateExposed=$($result.privateStateExposed)" + Write-Host "Bifrost ledger: status=$($result.status), rows=$($result.rowCount), publicationChain=$($result.publicationChainCount), collaborationChain=$($result.collaborationChainCount), accountingRows=$($result.accountingRowCount), closedAccounting=$($result.closedAccountingRowCount), attentionAccounting=$($result.attentionAccountingRowCount), publicRefs=$publicRefs, accounting=$accountingRows, ledgerRows=$ledgerRows, privateStateExposed=$($result.privateStateExposed)" } elseif ($Mode -eq "receipt-directory") { $artifactHashes = "none" $attentionRoutes = "none"