Expose agent SoA contracts in compact rows

This commit is contained in:
Meta Vens 2026-06-18 18:01:06 +01:00
commit f14f07a394
6 changed files with 71 additions and 41 deletions

View file

@ -582,44 +582,7 @@ fn main() -> Result<()> {
}) {
anyhow::bail!("agent state SoA report would expose private state");
}
let tui_rows = summary
.role_ids
.iter()
.enumerate()
.map(|(index, role)| {
format!(
"{} | {} | {} | sem={} epi={} rel={} goals={} values={}",
role,
summary
.agent_ids
.get(index)
.map(String::as_str)
.unwrap_or("?"),
summary
.profile_kinds
.get(index)
.map(String::as_str)
.unwrap_or("?"),
summary
.semantic_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary
.episodic_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary
.relationship_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary.goal_counts.get(index).copied().unwrap_or_default(),
summary.value_counts.get(index).copied().unwrap_or_default(),
)
})
.collect::<Vec<_>>();
let tui_rows = agent_state_soa_tui_rows(&summary);
println!(
"{}",
serde_json::to_string_pretty(&json!({
@ -2304,6 +2267,22 @@ fn main() -> Result<()> {
{
anyhow::bail!("local Verse agent state SoA summary lost standing swarm shape");
}
let agent_state_tui_rows = agent_state_soa_tui_rows(agent_summary);
if !agent_state_tui_rows.iter().any(|row| {
row.contains("Persona")
&& row.contains("epiphany.Persona")
&& row.contains("contract=gamecult.persona_state.v0")
&& row.contains("private=false")
}) || !agent_state_tui_rows.iter().any(|row| {
row.contains("implementation")
&& row.contains("epiphany.hands")
&& row.contains("contract=epiphany.work_organ_state.v0")
&& row.contains("private=false")
}) {
anyhow::bail!(
"local Verse agent state SoA compact rows lost contract/private-state guards"
);
}
let node = open_epiphany_cultmesh_node(&args.store, args.runtime_id.clone())?;
let agent_summary_table = node.soa::<EpiphanyCultMeshAgentStateSoaSummaryEntry>()?;
let summary_ids = agent_summary_table.column::<String>("summaryId")?;
@ -2674,6 +2653,53 @@ struct DaemonLivenessReport {
non_ready_count: usize,
}
fn agent_state_soa_tui_rows(summary: &EpiphanyCultMeshAgentStateSoaSummaryEntry) -> Vec<String> {
summary
.role_ids
.iter()
.enumerate()
.map(|(index, role)| {
format!(
"{} | {} | {} | contract={} | sem={} epi={} rel={} goals={} values={} | private={}",
role,
summary
.agent_ids
.get(index)
.map(String::as_str)
.unwrap_or("?"),
summary
.profile_kinds
.get(index)
.map(String::as_str)
.unwrap_or("?"),
summary
.portable_contracts
.get(index)
.map(String::as_str)
.unwrap_or("?"),
summary
.semantic_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary
.episodic_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary
.relationship_memory_counts
.get(index)
.copied()
.unwrap_or_default(),
summary.goal_counts.get(index).copied().unwrap_or_default(),
summary.value_counts.get(index).copied().unwrap_or_default(),
summary.private_state_exposed
)
})
.collect()
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct DaemonLivenessRow {

View file

@ -49,7 +49,7 @@ remembers doctrine; the branch remembers the blade.
- `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 `.epiphany-run\cultmesh\local-verse.ccmp`, 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 `epiphany-verse-query daemon-status` debug writer. A degraded proof via `service-tick` showed the supervisor invoking all seven daemon bodies and restoring ready liveness with sealed receipts; follow-up service tick no-ops when heartbeats are fresh. `epiphany-daemon-supervisor cluster-service-runbook` and `tools/epiphany_local_run.ps1 -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. `epiphany-daemon-supervisor cluster-service-install-plan` and `tools/epiphany_local_run.ps1 -Mode cluster-service-install-plan` write a non-mutating Windows install script plus lifecycle receipt for seven distinct per-organ Windows services. `tools/epiphany_local_run.ps1 -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. `epiphany-daemon-supervisor cluster-service-audit` and wrapper `-Mode cluster-service-audit` read Windows service-manager state for those seven expected service names; current local proof reports seven missing services and `status=incomplete`. `epiphany-daemon-supervisor cluster-service-start`/`cluster-service-stop` and wrapper modes `cluster-service-start-plan`, `cluster-service-stop-plan`, `cluster-service-start-execute`, and `cluster-service-stop-execute` record lifecycle receipts for all seven expected services; plan modes emit seven planned rows, and execute modes refuse without elevation before mutation. `cluster-service-execution-runbook` writes the admin-gated elevated wrapper sequence starting with cluster-native readiness, then uses `Invoke-EpiphanyRunbookStep` so each install/start/audit/stop step resets `$LASTEXITCODE`, catches thrown/nonzero failures, keeps running to gather more lifecycle receipts, and always runs `cluster-service-execution-audit` from `finally`; the wrapper asks `epiphany-daemon-supervisor cluster-service-execution-runbook` to seal the generated artifact as a typed `daemon_service_lifecycle` receipt with action `cluster-windows-service-execution-runbook`, status `written`, final audit metadata, step-failure policy metadata, and `privateStateExposed=false`. Its JSON and typed receipt args expose `runbookTryModes`, `finalAuditMode`, `finalAuditRunsInFinally=true`, `stepFailurePolicy=continue-after-step-failure`, `continueAfterStepFailure=true`, `nonzeroExitFailsStep=true`, and `exitsNonzeroAfterFinalAudit=true`, and the compact operator line prints those same aftercare facts. Latest proof `local-20260618-161632-376-436227d8` generated and parsed the robust cluster artifact. Cluster execution audit now requires that runbook witness before considering the elevated readiness/install/start/audit/stop effect chain. Current live audit remains correctly `incomplete` until an elevated operator run produces successful effect receipts. `tools/epiphany_local_run.ps1` builds and requires `epiphany-cluster-daemon` for service modes.
- `epiphany-verse-query restart-policy-directory` and `tools/epiphany_local_run.ps1 -Mode service-policy-directory` are the compact scheduler coverage sight rite. They report each daemon's durable restart-policy coverage as `ENABLED`, `DISABLED`, or `MISSING` through a narrow CultMesh restart-policy directory loader without writing policies or commands. Compact rows now include cooldown, reconcile interval, heartbeat stale threshold, failure count, last result, `followUp=<command>`, and `private=false`; the wrapper summary prints all seven policy rows with the `service-tick` follow-up. Disabled policies count as recovery attention, not harmless coverage. Live wrapper artifact `local-20260618-175008-830-e470a387` returned `status=ok`, seven daemons, seven covered policies, seven enabled policies, zero disabled, zero missing, zero attention rows, `last=ready`, `reconcile=60s`, `stale=300s`, and `privateStateExposed=false`. This is real daemon heartbeat coverage, not yet an installed per-organ OS service.
- `epiphany-verse-query poke-down-daemons` and `tools/epiphany_local_run.ps1 -Mode swarm-poke-down` are the current typed "if a service is down, poke it" reflex. They inspect local Verse daemon status rows, write daemon poke intent/receipt documents for every non-ready daemon, respect the same `daemon.lifecycle_poke` swarm brake as single-daemon poke, include target display name/body domain/private Verse id/Eve surface metadata from cluster topology in the operator-safe poke summary, and expose no private state. Verified: live local Verse had seven ready daemons and produced a no-op operator receipt with `pokedDaemonCount=0`; a temp degraded Hands store produced one topology-aware poke receipt; a temp lifecycle brake refused the batch poke; and `epiphany-verse-query smoke` now source-proves the ready no-op plus degraded single-poke path.
- CultMesh now carries the CultCache SoA ergonomic instead of forcing callers to bypass the mesh node. `CultMeshNode::soa<T>()` returns typed SoA tables for registered documents; the CultMesh crate proves the generic path, and Epiphany's agent-state summary test proves local Verse can project sealed `epiphany.cultmesh.agent_state_soa_summary.v0` rows through SoA columns. The seven-row persisted agent-state SoA remains owned by the agent memory store and mirrored into local Verse only as a private-state-sealed summary. `epiphany-verse-query agent-state-report` and `tools/epiphany_local_run.ps1 -Mode agent-state-soa` now expose that mirrored summary as compact TUI/JSON rows from CultMesh SoA columns without full local Verse serialization; live wrapper proof returned `agents=7`, `summaryRows=2` for id/latest projections, and `privateStateExposed=False`.
- CultMesh now carries the CultCache SoA ergonomic instead of forcing callers to bypass the mesh node. `CultMeshNode::soa<T>()` returns typed SoA tables for registered documents; the CultMesh crate proves the generic path, and Epiphany's agent-state summary test proves local Verse can project sealed `epiphany.cultmesh.agent_state_soa_summary.v0` rows through SoA columns. The seven-row persisted agent-state SoA remains owned by the agent memory store and mirrored into local Verse only as a private-state-sealed summary. `epiphany-verse-query agent-state-report` and `tools/epiphany_local_run.ps1 -Mode agent-state-soa` now expose that mirrored summary as compact TUI/JSON rows from CultMesh SoA columns without full local Verse serialization; compact rows include role id, agent id, profile kind, portable contract, memory/goal/value counts, and `private=false`. Live wrapper proof `local-20260618-175913-074-b22ff01c` returned `agents=7`, `summaryRows=2`, printed all seven faculties in `agentRows`, and kept `privateStateExposed=False`.
- `epiphany-verse-query swarm-status` and `tools/epiphany_local_run.ps1 -Mode swarm-status` are the compact read-only liveness surface for the daemon swarm. They use a narrow CultMesh daemon-liveness loader instead of serializing the full local Verse context, return agent-friendly `READY`/`POKE` TUI rows with daemon id, body domain, private Verse id, Eve surface, and `followUp=tools/epiphany_local_run.ps1 -Mode swarm-poke-down`, and expose no private state. Verified: live wrapper artifact `local-20260618-175408-868-81ad22c0` saw seven ready daemons and printed each daemon's private Verse plus Eve surface; a temp degraded Hands report returns `attention`, `nonReadyCount=1`, and a `POKE` row with `privateVerse=epiphany.cluster.hands.private`; `epiphany-verse-query smoke` source-proves ready and degraded report paths.
- `epiphany-verse-query cluster-topology` and `tools/epiphany_local_run.ps1 -Mode cluster-topology` are the compact read-only topology surface for the standing swarm. They use a narrow CultMesh cluster-topology loader, return seven clusters, seven private Verse ids, seven daemon ids, one public Persona discussion cluster, and `privateStateExposed=false`. Verified: direct proof returned `PUBLIC | Persona | epiphany.cluster.persona.private | repo:E:/Projects/EpiphanyAgent | epiphany-daemon-persona | eve://epiphany/persona`; `epiphany-verse-query smoke` source-proves the compact topology invariants; wrapper proof produced `clusters=7`, `privateVerses=7`, `daemons=7`, `publicDiscussion=1`.
- `epiphany-verse-query eve-surfaces` and `tools/epiphany_local_run.ps1 -Mode eve-surfaces` are the compact read-only Odin/Eve surface directory. Odin only reads the local Verse cluster topology, default advertisements, and daemon-owned Eve surface states through a narrow CultMesh loader; the report returns seven TUI rows, exactly one public Persona discussion surface, the `connect-eve` command hint, and `privateStateExposed=false`. TUI rows now include surface id, daemon id, body domain, private Verse id, public-discussion flag, supported actions, exposed document types, advertisement id, and `private=false`. Verified: wrapper proof `local-20260618-173318-552-420d6d66` printed `publicSurfaces=Persona=eve://epiphany/persona@epiphany.cluster.persona.private`, the connection command, `surfaces=7`, `publicDiscussion=1`, and `privateStateExposed=False`; `epiphany-verse-query smoke` source-proves the compact Persona routing row.

Binary file not shown.

Binary file not shown.

View file

@ -71,7 +71,7 @@ data_flow:
active_subgoals:
- 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.
- CultMesh is now the preferred ergonomic Rust abstraction over CultCache and CultNet for Epiphany-owned local database surfaces. The Rust substrate is repo-contained under `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`; the old `E:\Projects\CultLib\crates\*` path is dead in this checkout and must not be reintroduced as a compile-time dependency. Future local Verse/dream/status work should start at CultMesh unless it is explicitly polishing CultMesh internals. `CultMeshNode::get_all_with_keys<T>()` now exposes typed document enumeration through the mesh organ, and `CultMeshNode::soa<T>()` exposes CultCache's typed SoA table projection without bypassing the mesh organ. Compact audits can scan local Verse receipt families, and agent-state summary documents now prove SoA readback through CultMesh columns. `epiphany-verse-query agent-state-report` and wrapper `-Mode agent-state-soa` refresh/mirror the persisted seven-row agent-state SoA into local Verse, then emit a compact TUI/JSON report from CultMesh SoA columns without full local Verse serialization. Preserve the three-Verse boundary: `epiphany-internal` for private sub-agent typed state, `gamecult-local` for trusted LAN/Yggdrasil-tunnel GameCult project sharing, and `epiphany-global` for untrusted public dreams plus topic-specific threaded public rooms for Persona posts.
- CultMesh is now the preferred ergonomic Rust abstraction over CultCache and CultNet for Epiphany-owned local database surfaces. The Rust substrate is repo-contained under `vendor/cultcache-rs`, `vendor/cultnet-rs`, and `vendor/cultmesh-rs`; the old `E:\Projects\CultLib\crates\*` path is dead in this checkout and must not be reintroduced as a compile-time dependency. Future local Verse/dream/status work should start at CultMesh unless it is explicitly polishing CultMesh internals. `CultMeshNode::get_all_with_keys<T>()` now exposes typed document enumeration through the mesh organ, and `CultMeshNode::soa<T>()` exposes CultCache's typed SoA table projection without bypassing the mesh organ. Compact audits can scan local Verse receipt families, and agent-state summary documents now prove SoA readback through CultMesh columns. `epiphany-verse-query agent-state-report` and wrapper `-Mode agent-state-soa` refresh/mirror the persisted seven-row agent-state SoA into local Verse, then emit a compact TUI/JSON report from CultMesh SoA columns without full local Verse serialization. Compact SoA rows now include each standing faculty's role id, agent id, profile kind, portable contract, memory/goal/value counts, and `private=false`; wrapper proof `local-20260618-175913-074-b22ff01c` printed all seven faculties in one sealed line. Preserve the three-Verse boundary: `epiphany-internal` for private sub-agent typed state, `gamecult-local` for trusted LAN/Yggdrasil-tunnel GameCult project sharing, and `epiphany-global` for untrusted public dreams plus topic-specific threaded public rooms for Persona posts.
- Use `notes/epiphany-verse-architecture.md` as the source note for local Verse/Odin/Yggdrasil prompt-context architecture. Odin is the all-seer discovery/coordinator surface for advertised Verse metadata, not a trust-boundary bypass. Yggdrasil is the hosting spine for important trusted GameCult Verses such as Bifrost. The first native local Verse query surface is `epiphany-verse-query`, which seeds/queries compact CultMesh policy/status/contract context for dynamic prompt assembly and operator inspection; `epiphany-prompt-context-smoke` proves that compact local Verse context plus a semantic memory graph context cut can render a bounded dynamic prompt packet, omit unrelated private-looking text, and preserve the packet inside a role worker launch document. Live bridge role/reorient launch paths now feed `dynamicPromptContext` from sibling `local-verse.ccmp` and `memory-graph.msgpack` stores beside runtime-spine, refreshing the memory graph from current typed thread-state repo graphs when absent; the bridge launch-context test proves that packet survives into a persisted runtime-spine worker launch request. `tools/epiphany_local_run.ps1 -Mode status` now uses `.epiphany-run/cultmesh/local-verse.ccmp` as the shared local operator Verse store for run intent, operator snapshot, run receipt, and final `local-verse-context.json`, so the read path sees the latest operator witnesses instead of a policy-only seed packet. Local runs also refresh persisted `epiphany.agent_state_soa.v0` from `state/agents.msgpack` and mirror it into local Verse as sealed `epiphany.cultmesh.agent_state_soa_summary.v0`, preserving seven-faculty row/column shape and contract/count metadata without exposing memory text. `epiphany-verse-query poke-daemon --daemon-id <id>` now records an operator-safe `epiphany.cultmesh.daemon_poke_intent.v0` plus `epiphany.cultmesh.daemon_poke_receipt.v0` in local Verse, so a down daemon has a typed lifecycle intervention path without private Verse rummaging; follow-up daemon status remains the liveness authority. `epiphany-verse-query connect-eve` now selects an Odin advertisement by id or target cluster through the narrow Eve surface directory, records Eve connection intent/receipt documents, and verifies latest receipts through narrow CultMesh loaders; `tools/epiphany_local_run.ps1 -Mode eve-connect` wraps the same receipt path, defaulting to the Persona public discussion surface without full local Verse serialization. `epiphany-verse-query bifrost-publication` now records the Bifrost body-change publication intent, Bifrost publication receipt, and GitHub publication receipt from explicit changed path, verification, review, authorship, credit, ledger, Hands PR, and publication URL inputs, verifies the latest chain through narrow CultMesh loaders, and is wrapped by `tools/epiphany_local_run.ps1 -Mode bifrost-publication` for non-mutating operator proof defaults. `epiphany-verse-query collaboration-feedback` now records public Persona/peer collaboration feedback plus an Imagination consensus-discovery receipt from explicit public refs, Eve receipt, topic, summary, and candidate action refs, verifies latest feedback/consensus through narrow CultMesh loaders, and is wrapped by `tools/epiphany_local_run.ps1 -Mode collaboration-feedback`, which first records the prerequisite Eve receipt; adoption still requires Mind/Bifrost gates. `-Mode mvp` now seeds the same local Verse, routes Persona front-door `bubble` speech audits into that store, and writes final `local-verse-context.json` so the Persona mouth-edge witness is visible beside operator run witnesses. `epiphany-operator-snapshot from-status` now also distills the latest native status `tools.invocations[]` row into local Verse daemon-tool invocation intent/receipt mirrors, so operator-safe runtime tool calls become discoverable as `epiphany.cultmesh.daemon_tool_invocation_*` while runtime-spine remains lifecycle owner and raw MCP JSON stays quarantined behind typed tool documents. Plan/run/MVP coordinator summaries can now mirror their runtime-spine `epiphany.coordinator_run_receipt.v0` into local Verse as `epiphany.cultmesh.coordinator_run_receipt.v0`, referencing sealed artifacts by path only while keeping runtime-spine as lifecycle owner. When that summary contains a `finalAction.handsActionGate`, the same distillation pass writes `epiphany.cultmesh.hands_action_gate.v0` into local Verse with the Hands intent/review ids, Substrate Gate grant id, requested paths, required receipt types, and record-pass command template; runtime-spine Hands/Substrate Gate receipts remain the only action owners. When coordinator steps contain `roleAccept` or `roleFailureReview`, the same pass writes the latest operator-safe `epiphany.cultmesh.role_review_event.v0` mirror with surface, role id, status, source coordinator receipt id, and any exposed acceptance receipt/result/job ids; thread-state acceptance receipts remain the review owner.
- The active priority is Codex starvation and CultNet liberation. Use `notes/codex-starvation-and-cultnet-liberation-plan.md` as the directive and `notes/codex-auth-spine-inventory.md` as the source-grounded keeper list for the retained OpenAI subscription auth/model transport bridge. Classify all Epiphany-relevant JSON contamination, define the native CultNet runtime boundary, keep worker launch/result/selfPatch cargo as typed documents, evacuate Epiphany operator/state/process authority from Codex JSON-RPC, wrap MCP's unavoidable JSON protocol edge in typed Epiphany intent/result/receipt documents, and keep cutting until Epiphany can run its own state and processes without `codex_message_processor.rs` except for bridge compatibility.
- Use `notes/epiphany-anatomy.md` as the canonical anatomy map. Embodied sub-agents are Self, Persona, Imagination, Eyes, Modeling, Hands, and Soul. Body is substrate, Mind is persistent state/state admission, Continuity is recovery/compaction/sleep protocol machinery, and Substrate Gate is substrate access protocol.

View file

@ -1620,7 +1620,11 @@ if ($resultPath -ne "" -and (Test-Path -LiteralPath $resultPath)) {
} elseif ($Mode -eq "status") {
Write-Host "Status: thread=$($result.threadId), coordinator=$($result.coordinator.action), crrc=$($result.crrc.recommendation.action)"
} elseif ($Mode -eq "agent-state-soa") {
Write-Host "Agent state SoA: status=$($result.status), agents=$($result.agentCount), summaryRows=$($result.summarySoaTableRows), privateStateExposed=$($result.privateStateExposed)"
$agentRows = "none"
if ($null -ne $result.tuiRows -and $result.tuiRows.Count -gt 0) {
$agentRows = ($result.tuiRows -join "; ")
}
Write-Host "Agent state SoA: status=$($result.status), agents=$($result.agentCount), summaryRows=$($result.summarySoaTableRows), agentRows=$agentRows, privateStateExposed=$($result.privateStateExposed)"
} elseif ($Mode -eq "swarm-status") {
$daemonRows = "none"
if ($null -ne $result.rows -and $result.rows.Count -gt 0) {