diff --git a/epiphany-core/src/bin/epiphany-operator-snapshot.rs b/epiphany-core/src/bin/epiphany-operator-snapshot.rs index 540283d9..afab13a9 100644 --- a/epiphany-core/src/bin/epiphany-operator-snapshot.rs +++ b/epiphany-core/src/bin/epiphany-operator-snapshot.rs @@ -1,14 +1,11 @@ use anyhow::Context; use anyhow::Result; use chrono::Utc; -use epiphany_core::epiphany_cultmesh_daemon_tool_invocation_from_status_json; use epiphany_core::epiphany_cultmesh_operator_snapshot_from_status_json; use epiphany_core::load_latest_epiphany_cultmesh_operator_snapshot; -use epiphany_core::write_epiphany_cultmesh_daemon_tool_invocation_intent; -use epiphany_core::write_epiphany_cultmesh_daemon_tool_invocation_receipt; use epiphany_core::write_epiphany_cultmesh_operator_snapshot; -use serde_json::Value; use serde_json::json; +use serde_json::Value; use std::env; use std::fs; use std::path::PathBuf; @@ -31,34 +28,13 @@ fn main() -> Result<()> { &status_json, )?; let written = write_epiphany_cultmesh_operator_snapshot(&args.store, snapshot)?; - let latest_tool_invocation = epiphany_cultmesh_daemon_tool_invocation_from_status_json( - args.runtime_id.clone(), - input.to_string_lossy(), - &status_json, - )?; - let mut written_tool_intent = None; - let mut written_tool_receipt = None; - if let Some((intent, receipt)) = latest_tool_invocation { - written_tool_intent = Some(write_epiphany_cultmesh_daemon_tool_invocation_intent( - &args.store, - args.runtime_id.clone(), - intent, - )?); - if let Some(receipt) = receipt { - written_tool_receipt = - Some(write_epiphany_cultmesh_daemon_tool_invocation_receipt( - &args.store, - args.runtime_id.clone(), - receipt, - )?); - } - } print_json(json!({ "status": "written", "store": args.store, "snapshot": written, - "toolInvocationIntent": written_tool_intent, - "toolInvocationReceipt": written_tool_receipt, + "toolInvocationIntent": null, + "toolInvocationReceipt": null, + "toolInvocationAuthority": "runtime-spine-only", }))?; } "latest" => { diff --git a/epiphany-core/src/cultmesh_integration.rs b/epiphany-core/src/cultmesh_integration.rs index 7f6fe4cd..2cd13efc 100644 --- a/epiphany-core/src/cultmesh_integration.rs +++ b/epiphany-core/src/cultmesh_integration.rs @@ -2788,6 +2788,7 @@ pub fn epiphany_cultmesh_operator_snapshot_from_status_json( }) } +#[cfg(test)] pub fn epiphany_cultmesh_daemon_tool_invocation_from_status_json( requesting_cluster_id: impl Into, status_path: impl Into, diff --git a/epiphany-core/src/lib.rs b/epiphany-core/src/lib.rs index 9804c530..858f8a45 100644 --- a/epiphany-core/src/lib.rs +++ b/epiphany-core/src/lib.rs @@ -391,6 +391,7 @@ pub use cultmesh_integration::epiphany_cultmesh_daemon_poke_intent_from_status; pub use cultmesh_integration::epiphany_cultmesh_daemon_poke_receipt_for_intent; pub use cultmesh_integration::epiphany_cultmesh_daemon_statuses; pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_capabilities; +#[cfg(test)] pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_from_status_json; pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_intent_from_capability; pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_receipt_for_intent; diff --git a/notes/epiphany-current-algorithmic-map.md b/notes/epiphany-current-algorithmic-map.md index dab546b6..c6950427 100644 --- a/notes/epiphany-current-algorithmic-map.md +++ b/notes/epiphany-current-algorithmic-map.md @@ -70,6 +70,14 @@ - Forbidden metrics writers: caller cannot provide accepted artifact, model spend, review load, credit, proof, summary, receipt, or status results. - Negative proof: missing requests fail without receipt mutation and response-shaped arguments fail before lookup or write. +## Operator snapshot authority boundary (2026-07-12) + +- Owner: operator snapshot adapter owns only a bounded summary of an edge status artifact. +- Runtime spine owns daemon-tool execution intent and receipt truth. +- Forbidden projection: `/tools/invocations` JSON cannot be promoted into canonical daemon-tool schemas by snapshot import. +- Output explicitly returns null tool intent/receipt fields and `toolInvocationAuthority=runtime-spine-only`. +- Negative proof: forged accepted tool JSON produced a snapshot but no canonical intent or receipt. + This is the source-grounded map of the live machine. Historical route and bridge anatomy belongs in git history and evidence ledgers, not here. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index 3a92f198..ca633bf1 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -32,6 +32,10 @@ Single poke, batch poke, and swarm triage now write only `epiphany.cultmesh.daem `bifrost-artifact-acceptance` and `bifrost-metrics`, plus their wrappers, now inspect the latest Mind-admitted `repo.artifact_acceptance_request` / `repo.metrics_request` map entry and report `pending-maintainer-bifrost` / `pending-bifrost-maintainer`. They write no provider receipts. Artifact/proof/review/ledger/accepted-by/status fields and accepted-artifact/spend/review-load/credit/proof/summary/status fields are rejected respectively. The canonical local Verse currently contains neither request family, so negative proof showed clean missing-request failure, no receipt mutation, and rejection of counterfeit result fields. The original conceptual-substitution audit now records all confirmed substitutions as structurally cut; next audit every remaining production receipt-writer call site for provider provenance. +## 2026-07-12 receipt-writer provenance audit + +The first call-site audit found a new canonical-promotion substitution in `epiphany-operator-snapshot from-status`: arbitrary edge JSON under `/tools/invocations` could be converted into canonical daemon-tool intent and receipt documents. That promotion is removed. The adapter writes only `operator_snapshot`, returns null tool intent/receipt fields, and states `runtime-spine-only` authority; the conversion helper is compiled only for tests. Forgery proof imported an `accepted` fake receipt and confirmed both canonical latest tool intent and receipt remained absent. See `notes/receipt-writer-provenance-audit-2026-07-12.md`. Next quarantine smoke writers, then inspect operator-run and daemon-supervisor evidence binding. + This is the re-entry rite for `E:\Projects\EpiphanyAgent`: the waking chant for the local machine-spirit before it touches the forge. diff --git a/notes/receipt-writer-provenance-audit-2026-07-12.md b/notes/receipt-writer-provenance-audit-2026-07-12.md new file mode 100644 index 00000000..07dcc931 --- /dev/null +++ b/notes/receipt-writer-provenance-audit-2026-07-12.md @@ -0,0 +1,25 @@ +# Receipt Writer Provenance Audit — 2026-07-12 + +## Method + +Inventory every production call to `write_*receipt`, then ask whether the executable is the named owner, a bounded ingest/projection boundary, a test-only fixture, or a caller able to assert the result it records. + +## Classification + +- `epiphany-daemon-supervisor`: owner-aligned for scheduler, lifecycle, and daemon-poke receipts. It performs or observes the lifecycle operation it records. +- `epiphany-eve-provider`: owner-aligned narrow provider receipt writer; verifies the pending intent targets its provider cluster. +- `epiphany-operator-run`: owner-aligned for operator-run receipts and coordinator receipts derived from the run it executes. +- smoke binaries and the `epiphany-verse-query smoke` arm: fixtures, not runtime evidence. They remain a quarantine risk if permitted to target canonical stores. +- `epiphany-work` Weksa lowering: a lowering projection receipt, explicitly non-publication authority; no substitution confirmed in this pass. +- `epiphany-operator-snapshot from-status`: **confirmed substitution and cut**. Arbitrary edge JSON under `/tools/invocations` could previously be converted into canonical daemon-tool intent and receipt documents. The snapshot adapter now writes the operator snapshot only; tool invocation fields return null and authority remains `runtime-spine-only`. The conversion helper is test-only. + +## Negative proof + +A forged operator-status artifact containing `intentId=forged-intent`, `receiptId=forged-receipt`, and `status=accepted` was imported. The operator snapshot was written, while canonical latest daemon-tool intent and receipt both remained absent. + +## Remaining scrutiny + +1. Quarantine smoke writers so they cannot target canonical stores. +2. Inspect `epiphany-operator-run` receipt construction against actual subprocess/runtime evidence rather than command arguments. +3. Inspect daemon-supervisor plan/rehearsal receipts separately from execution receipts so planning cannot masquerade as service mutation. +4. Distill or remove dead public receipt constructors once every named provider executable exists. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 9bdea4f0..c080202e 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index 37646f20..6316c3db 100644 --- a/state/map.yaml +++ b/state/map.yaml @@ -70,7 +70,7 @@ data_flow: - move historical proof to git, commits, smoke artifacts, or distilled evidence rather than plan prose active_subgoals: - - Use `notes/conceptual-substitution-audit-2026-07-12.md` and its resolution ledger as the current authority-corrosion map. Every confirmed caller/provider dual writer in that audit is cut from caller-facing production paths. Artifact-acceptance and metrics commands now surface admitted repo requests, report pending named owners, reject all acceptance/accounting result fields, and write no receipts. Next perform a production call-site provenance audit of every response-receipt writer, then distill obsolete contaminated authority claims from this historical map. + - Use `notes/conceptual-substitution-audit-2026-07-12.md` plus `notes/receipt-writer-provenance-audit-2026-07-12.md` as the current authority-corrosion maps. The fresh call-site audit found and cut operator-snapshot canonical promotion: arbitrary edge status JSON can no longer become canonical daemon-tool intents/receipts. Snapshot output names `runtime-spine-only` authority; the old converter is test-only. Next quarantine smoke receipt writers from canonical stores, then audit operator-run and daemon-supervisor evidence provenance. - `swarm-overview` is an Epiphany-local, renderer-neutral diagnostic projection over provider-owned typed state. It owns no lifecycle, discovery, composition, or mutation authority. Epiphany publishes clean provider-owned Eve surfaces; Odin may discover them; downstream lowerers and compositors remain outside Epiphany's concern. - Idunn owns daemon survival and service lifecycle physiology. Codex/operator sessions may inspect, generate runbooks, and route explicit operator authority, but keeping daemons alive belongs to Idunn-owned service lifecycle receipts, scheduler policy, audits, and aftercare. Do not let Self, diagnostic projections, or ad hoc wrapper summaries become a second daemon-keeper. Global tool readbacks for Self `service-health`, `service-policy-directory`, and `swarm-online-runbook` state `lifecycleOwner=Idunn` and `hostedBody=Epiphany` without service mutation or private-state exposure. - Use `notes/epiphany-cultmesh-dreaming-roadmap.md` as the design authority for distributed Epiphany dreaming. Public dreams are separately authored typed documents distributed through CultMesh/CultNet; private state remains local and cannot be shared by flipping a visibility flag. Foreign dreams are external thought weather until a reviewed local adoption receipt digests them into memory, planning, doctrine, or governance.