diff --git a/epiphany-core/src/bin/epiphany-eve-provider.rs b/epiphany-core/src/bin/epiphany-eve-provider.rs deleted file mode 100644 index a1151190..00000000 --- a/epiphany-core/src/bin/epiphany-eve-provider.rs +++ /dev/null @@ -1,99 +0,0 @@ -use anyhow::{Context, Result}; -use epiphany_core::{ - epiphany_cultmesh_eve_connection_receipt_for_intent, - load_latest_epiphany_cultmesh_eve_connection_intent, - write_epiphany_cultmesh_eve_connection_receipt, -}; -use serde_json::json; -use std::{env, path::PathBuf}; - -fn main() -> Result<()> { - let args = Args::parse()?; - let intent = - load_latest_epiphany_cultmesh_eve_connection_intent(&args.store, args.runtime_id.clone())? - .context("Eve provider found no pending connection intent")?; - if intent.target_cluster_id != args.provider_cluster_id { - anyhow::bail!( - "Eve provider {} cannot answer intent owned by {}", - args.provider_cluster_id, - intent.target_cluster_id - ); - } - if let Some(expected_intent_id) = args.intent_id.as_deref() { - if intent.intent_id != expected_intent_id { - anyhow::bail!( - "latest Eve connection intent {:?} does not match requested {:?}", - intent.intent_id, - expected_intent_id - ); - } - } - let receipt = - epiphany_cultmesh_eve_connection_receipt_for_intent(args.receipt_id, &intent, args.status); - let written = write_epiphany_cultmesh_eve_connection_receipt( - &args.store, - args.runtime_id.clone(), - receipt, - )?; - println!( - "{}", - serde_json::to_string_pretty(&json!({ - "schemaVersion": "epiphany.eve_provider_connection_receipt.v0", - "status": written.status, - "runtimeId": args.runtime_id, - "providerClusterId": args.provider_cluster_id, - "intentId": written.intent_id, - "receiptId": written.receipt_id, - "feedbackRoute": written.feedback_route, - "privateStateExposed": written.private_state_exposed, - }))? - ); - Ok(()) -} - -struct Args { - store: PathBuf, - runtime_id: String, - provider_cluster_id: String, - intent_id: Option, - receipt_id: String, - status: String, -} - -impl Args { - fn parse() -> Result { - let mut values = env::args().skip(1); - let command = values.next().unwrap_or_else(|| "accept".to_string()); - if command != "accept" { - anyhow::bail!("unknown command {command:?}; use accept"); - } - let mut store = PathBuf::from(".epiphany-run/cultmesh/local-verse.ccmp"); - let mut runtime_id = "epiphany-local".to_string(); - let mut provider_cluster_id = None; - let mut intent_id = None; - let mut receipt_id = None; - let mut status = "accepted".to_string(); - while let Some(arg) = values.next() { - match arg.as_str() { - "--store" => store = PathBuf::from(values.next().context("missing --store")?), - "--runtime-id" => runtime_id = values.next().context("missing --runtime-id")?, - "--provider-cluster-id" => { - provider_cluster_id = - Some(values.next().context("missing --provider-cluster-id")?) - } - "--intent-id" => intent_id = Some(values.next().context("missing --intent-id")?), - "--receipt-id" => receipt_id = Some(values.next().context("missing --receipt-id")?), - "--status" => status = values.next().context("missing --status")?, - _ => anyhow::bail!("unknown argument {arg:?}"), - } - } - Ok(Self { - store, - runtime_id, - provider_cluster_id: provider_cluster_id.context("missing --provider-cluster-id")?, - intent_id, - receipt_id: receipt_id.context("missing --receipt-id")?, - status, - }) - } -} diff --git a/epiphany-core/src/bin/epiphany-verse-query.rs b/epiphany-core/src/bin/epiphany-verse-query.rs index 41d1b1fa..3d48253f 100644 --- a/epiphany-core/src/bin/epiphany-verse-query.rs +++ b/epiphany-core/src/bin/epiphany-verse-query.rs @@ -45,7 +45,6 @@ use epiphany_core::epiphany_cultmesh_daemon_poke_receipt_for_intent; use epiphany_core::epiphany_cultmesh_daemon_tool_invocation_intent_from_capability; use epiphany_core::epiphany_cultmesh_daemon_tool_invocation_receipt_for_intent; use epiphany_core::epiphany_cultmesh_eve_connection_intent_from_advertisement; -use epiphany_core::epiphany_cultmesh_eve_connection_receipt_for_intent; use epiphany_core::epiphany_service_execution_audit_report; use epiphany_core::load_agent_state_soa_entry; use epiphany_core::load_epiphany_cultmesh_cluster_topology; @@ -98,7 +97,6 @@ use epiphany_core::write_epiphany_cultmesh_daemon_status; 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_eve_connection_intent; -use epiphany_core::write_epiphany_cultmesh_eve_connection_receipt; use epiphany_core::write_epiphany_cultmesh_swarm_brake; use epiphany_core::write_epiphany_cultmesh_work_loop_telemetry; use serde::Serialize; @@ -1504,21 +1502,13 @@ fn run_cli() -> Result<()> { args.runtime_id.clone(), intent.clone(), )?; - let receipt = epiphany_cultmesh_eve_connection_receipt_for_intent( - "eve-receipt-smoke", - &intent, - "accepted-for-consensus-discovery", - ); - write_epiphany_cultmesh_eve_connection_receipt( - &args.store, - args.runtime_id.clone(), - receipt, - )?; let context = query_epiphany_local_verse_context(&args.store, args.runtime_id.clone())?; if context.latest_eve_connection_intent.is_none() - || context.latest_eve_connection_receipt.is_none() + || context.latest_eve_connection_receipt.is_some() { - anyhow::bail!("local Verse query smoke lost Eve connection intent/receipt"); + anyhow::bail!( + "local Verse query smoke lost Eve intent or manufactured a provider receipt" + ); } if context.daemon_tool_capabilities.len() < 19 { anyhow::bail!("local Verse query smoke expected daemon tool capabilities"); diff --git a/epiphany-core/src/cultmesh_integration.rs b/epiphany-core/src/cultmesh_integration.rs index d2892973..9371a43b 100644 --- a/epiphany-core/src/cultmesh_integration.rs +++ b/epiphany-core/src/cultmesh_integration.rs @@ -3281,6 +3281,7 @@ pub fn epiphany_cultmesh_eve_connection_intent_from_advertisement( } } +#[cfg(test)] pub fn epiphany_cultmesh_eve_connection_receipt_for_intent( receipt_id: impl Into, intent: &EpiphanyCultMeshEveConnectionIntentEntry, @@ -3321,6 +3322,7 @@ pub fn write_epiphany_cultmesh_eve_connection_intent( Ok(written) } +#[cfg(test)] pub fn write_epiphany_cultmesh_eve_connection_receipt( store_path: impl AsRef, runtime_id: impl Into, @@ -6162,6 +6164,7 @@ fn epiphany_cultmesh_eve_connection_intent_key(intent_id: &str) -> String { format!("epiphany-local/eve-connection-intent/{intent_id}") } +#[cfg(test)] fn epiphany_cultmesh_eve_connection_receipt_key(receipt_id: &str) -> String { format!("epiphany-local/eve-connection-receipt/{receipt_id}") } diff --git a/epiphany-core/src/lib.rs b/epiphany-core/src/lib.rs index e0089677..757c4f3e 100644 --- a/epiphany-core/src/lib.rs +++ b/epiphany-core/src/lib.rs @@ -393,6 +393,7 @@ pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_from_stat pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_intent_from_capability; pub use cultmesh_integration::epiphany_cultmesh_daemon_tool_invocation_receipt_for_intent; pub use cultmesh_integration::epiphany_cultmesh_eve_connection_intent_from_advertisement; +#[cfg(test)] pub use cultmesh_integration::epiphany_cultmesh_eve_connection_receipt_for_intent; pub use cultmesh_integration::epiphany_cultmesh_eyes_contracts; pub use cultmesh_integration::epiphany_cultmesh_global_room_policies; @@ -491,6 +492,7 @@ pub use cultmesh_integration::write_epiphany_cultmesh_daemon_statuses; pub use cultmesh_integration::write_epiphany_cultmesh_daemon_tool_invocation_intent; pub use cultmesh_integration::write_epiphany_cultmesh_daemon_tool_invocation_receipt; pub use cultmesh_integration::write_epiphany_cultmesh_eve_connection_intent; +#[cfg(test)] pub use cultmesh_integration::write_epiphany_cultmesh_eve_connection_receipt; pub use cultmesh_integration::write_epiphany_cultmesh_eyes_contracts; pub use cultmesh_integration::write_epiphany_cultmesh_global_room_policies; diff --git a/notes/conceptual-substitution-audit-2026-07-12.md b/notes/conceptual-substitution-audit-2026-07-12.md index 95d06415..86378751 100644 --- a/notes/conceptual-substitution-audit-2026-07-12.md +++ b/notes/conceptual-substitution-audit-2026-07-12.md @@ -75,7 +75,7 @@ the receipts and projections without first separating those writers. ## Resolution ledger -All confirmed substitutions above have now been structurally cut from their caller-facing production paths. Diagnostics preserve absence; bootstrap does not seed liveness; cluster-daemon owns first heartbeat; discovery loaders do not synthesize providers; tool, Eve, poke, body-change, public-proof, artifact-acceptance, metrics, and Persona-feedback commands write or select requests only; provider/result fields are rejected. `epiphany-eve-provider` is the first narrow provider receipt mouth. Receipt constructors and writers remain available to owning provider binaries and focused contract tests; their mere existence is no longer caller authority. +All confirmed substitutions above have now been structurally cut from their caller-facing production paths. Diagnostics preserve absence; bootstrap does not seed liveness; cluster-daemon owns first heartbeat; discovery loaders do not synthesize providers; tool, Eve, poke, body-change, public-proof, artifact-acceptance, metrics, and Persona-feedback commands write or select requests only; provider/result fields are rejected. Response constructors and writers without participating provider bodies are test-only. Remaining audit work is provenance rather than this original dual-writer cluster: identify every production call site of response-receipt writers, ensure it belongs to a named provider executable or ingest boundary, and distill contaminated historical claims from `state/map.yaml`. @@ -236,3 +236,18 @@ The scattered loader compensators were removed. Full Verse context alone adds projection policy by refusing to describe a nonexistent body. Backing-store and nested diagnostic tests plus rebuilt CLI probes prove that reads and refused daemon/supervisor starts create neither store, lock, nor parent directory. + +## Executable-name/provider-participation split + +`epiphany-eve-provider` appeared to repair Eve receipt provenance by living in a +separate executable and checking that a caller-supplied provider cluster matched +the pending intent target. The alleged provider still did not participate: the +same caller supplied provider identity, receipt ID, and acceptance status. A +binary name and matching string had become substitutes for an executing body. + +The executable is deleted. Eve response construction, persistence, and keying +are test-only until a real target provider daemon or authenticated ingest +boundary owns them. The aggregate Verse smoke now proves the honest pending +state: requester intent present, provider receipt absent. The typed response +schema and reader remain as the wire/ingest contract; they grant no local +response authorship. diff --git a/notes/epiphany-current-algorithmic-map.md b/notes/epiphany-current-algorithmic-map.md index 8662f6f5..d0394317 100644 --- a/notes/epiphany-current-algorithmic-map.md +++ b/notes/epiphany-current-algorithmic-map.md @@ -47,7 +47,7 @@ ## Persona feedback and Imagination consensus boundary (2026-07-12) -- Eve provider: `epiphany-eve-provider accept` loads the pending connection intent, verifies `provider_cluster_id == target_cluster_id`, and writes the provider receipt. +- Eve connection requests remain pending until a real target provider daemon or authenticated ingest boundary supplies the typed response. The former generic `epiphany-eve-provider` CLI is deleted because caller-supplied provider identity and status did not constitute provider participation; local response construction/writing is test-only. - Persona owner: `collaboration-feedback` writes public, bounded feedback only after that provider receipt exists. - Imagination owner: consensus participant selection, packet reference, receipt status/id, and adoption gate. - Persona output: `pending-imagination` with null consensus fields and `responseOwner=Imagination`. diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index f5f79fd3..453d0f26 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -53,6 +53,10 @@ The confirmed conceptual substitutions have been cut: taking a lock when its file is absent, so all readers preserve filesystem absence without per-loader guards. Full context projection refuses a missing Verse; explicit bootstrap or a real writer owns CultMesh body creation. +- the generic `epiphany-eve-provider` CLI is deleted: caller-supplied provider + identity/status was not provider participation. Eve requests remain pending; + local response construction/writing is test-only until a real target daemon + or authenticated ingest boundary owns the receipt. The presentation boundary is now plain: `swarm overview` is a generic compact read-only projection. Gjallar is a downstream TUI application on Nightwing and is not an Epiphany organ, provider, owner, runtime, or architectural dependency. Eve/CultUI graphs may be lowered or composited downstream without Epiphany caring which presentation client does it. diff --git a/notes/receipt-writer-provenance-audit-2026-07-12.md b/notes/receipt-writer-provenance-audit-2026-07-12.md index 7764405b..cd489333 100644 --- a/notes/receipt-writer-provenance-audit-2026-07-12.md +++ b/notes/receipt-writer-provenance-audit-2026-07-12.md @@ -7,7 +7,10 @@ Inventory every production call to `write_*receipt`, then ask whether the execut ## 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. +- Eve connection receipt: no production local writer. The former generic + `epiphany-eve-provider` accepted caller-supplied provider identity and status, + so it was deleted; constructor/writer are test-only pending a real provider + daemon or authenticated ingest boundary. - `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. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index cbae2b31..a6890acc 100644 Binary files a/state/ledgers.msgpack and b/state/ledgers.msgpack differ diff --git a/state/map.yaml b/state/map.yaml index ccd96f65..12648b5b 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` plus `notes/receipt-writer-provenance-audit-2026-07-12.md` as the current authority-corrosion maps. Snapshot promotion, synthetic smoke escape, unbound operator completion, hidden service execution flags, provider/bootstrap collapse, central/all-provider publication, production-side implicit bootstrap, orphaned external response authority, bulk readiness authority, public topology-derived provider builders, bootstrap/template-authored operator observation, writerless operator-status schema authority, SoA projection body creation, and path-selection-as-body-creation are cut. Provider responses and readiness without observers are test-only; the ownerless operator-status family is deleted; templates are private; query mutations require the body. CultCache's backing store now owns missing-read purity by returning before lock acquisition, so missing reads and refused daemon/supervisor starts preserve store, lock, and parent-directory absence without per-loader compensators. Next audit remaining projections, caches, schedulers, adapters, and non-receipt smokes for borrowed authority or path escape. + - 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. Snapshot promotion, synthetic smoke escape, unbound operator completion, hidden service execution flags, provider/bootstrap collapse, central/all-provider publication, production-side implicit bootstrap, orphaned external response authority, bulk readiness authority, public topology-derived provider builders, bootstrap/template-authored operator observation, writerless operator-status schema authority, SoA projection body creation, path-selection-as-body-creation, and executable-name-as-provider-participation are cut. Provider responses and readiness without observers are test-only; the ownerless operator-status family and counterfeit Eve provider CLI are deleted; templates are private; query mutations require the body. CultCache's backing store owns missing-read purity by returning before lock acquisition. Next audit remaining projections, caches, schedulers, adapters, and non-receipt smokes for borrowed authority or path escape. - `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.