From 2c3d8f55f7c8abd6d8233f9df5cc96a4906adafd Mon Sep 17 00:00:00 2001 From: Meta Vens Date: Thu, 18 Jun 2026 22:20:58 +0100 Subject: [PATCH] Expose service identity on swarm actions --- epiphany-core/src/bin/epiphany-verse-query.rs | 34 +++++++++++++++++- notes/fresh-workspace-handoff.md | 1 + state/ledgers.msgpack | Bin 273411 -> 273832 bytes state/map.yaml | 2 +- tools/epiphany_local_run.ps1 | 20 +++++++++-- 5 files changed, 53 insertions(+), 4 deletions(-) diff --git a/epiphany-core/src/bin/epiphany-verse-query.rs b/epiphany-core/src/bin/epiphany-verse-query.rs index 7717b861..2b71fccb 100644 --- a/epiphany-core/src/bin/epiphany-verse-query.rs +++ b/epiphany-core/src/bin/epiphany-verse-query.rs @@ -2557,6 +2557,9 @@ fn main() -> Result<()> { && row.completion_audit_wrapper_mode == "cluster-service-execution-audit" && row.completion_audit_wrapper_command == WRAPPER_CLUSTER_SERVICE_EXECUTION_AUDIT_COMMAND + && row.service_id == "epiphany-cluster-daemon-services" + && row.service_route + == "epiphany-cluster-daemon-services::cluster-windows-service-execution-runbook" && row.mutates_state && row.requires_elevated_authority && row.service_execution_failed_check_count == 5 @@ -2570,6 +2573,9 @@ fn main() -> Result<()> { && row.operator_aftercare_command == WRAPPER_SERVICE_EXECUTION_AUDIT_COMMAND && row.completion_audit_wrapper_mode == "service-execution-audit" && row.completion_audit_wrapper_command == WRAPPER_SERVICE_EXECUTION_AUDIT_COMMAND + && row.service_id == "epiphany-daemon-supervisor-service" + && row.service_route + == "epiphany-daemon-supervisor-service::windows-service-execution-runbook" && row.mutates_state && row.requires_elevated_authority && row.service_execution_failed_check_count == 6 @@ -2579,6 +2585,8 @@ fn main() -> Result<()> { || !service_overview.swarm_action_tui_rows.iter().any(|row| { row.contains("service-execution-authority") && row.contains("command=tools/epiphany_local_run.ps1 -Mode cluster-service-execution-runbook") + && row.contains("service=epiphany-cluster-daemon-services") + && row.contains("route=epiphany-cluster-daemon-services::cluster-windows-service-execution-runbook") && row.contains("failedChecks=5") && row.contains("missingChecks=4") && row.contains("artifact=present") @@ -2594,6 +2602,8 @@ fn main() -> Result<()> { || !service_overview.swarm_action_tui_rows.iter().any(|row| { row.contains("service-execution-authority") && row.contains("command=tools/epiphany_local_run.ps1 -Mode service-execution-runbook") + && row.contains("service=epiphany-daemon-supervisor-service") + && row.contains("route=epiphany-daemon-supervisor-service::windows-service-execution-runbook") && row.contains("failedChecks=6") && row.contains("missingChecks=6") && row.contains("artifact=present") @@ -2712,6 +2722,8 @@ fn main() -> Result<()> { private_state_exposed: missing_runbook_row.private_state_exposed, failed_check_count: 0, missing_check_count: 0, + service_id: receipt_directory_row_service_id(&missing_runbook_row) + .unwrap_or_else(|| "unknown-service".to_string()), completion_audit_wrapper_mode: "cluster-service-execution-audit".to_string(), completion_audit_wrapper_command: WRAPPER_CLUSTER_SERVICE_EXECUTION_AUDIT_COMMAND .to_string(), @@ -3162,6 +3174,8 @@ struct SwarmActionRow { requires_elevated_authority: bool, service_execution_failed_check_count: usize, service_execution_missing_check_count: usize, + service_id: String, + service_route: String, reason: String, private_state_exposed: bool, } @@ -3174,6 +3188,7 @@ struct ServiceExecutionRunbookAction { private_state_exposed: bool, failed_check_count: usize, missing_check_count: usize, + service_id: String, completion_audit_wrapper_mode: String, completion_audit_wrapper_command: String, } @@ -3588,6 +3603,8 @@ fn swarm_action_rows( requires_elevated_authority: false, service_execution_failed_check_count: 0, service_execution_missing_check_count: 0, + service_id: "none".to_string(), + service_route: "none".to_string(), reason: "One or more daemon bodies are non-ready; poke liveness before trusting hosted tools.".to_string(), private_state_exposed: false, }); @@ -3618,6 +3635,8 @@ fn swarm_action_rows( requires_elevated_authority: false, service_execution_failed_check_count: 0, service_execution_missing_check_count: 0, + service_id: "none".to_string(), + service_route: "none".to_string(), reason: format!( "Hosted tool capabilities are blocked by non-ready daemon bodies: {blocked}." ), @@ -3647,6 +3666,8 @@ fn swarm_action_rows( requires_elevated_authority: false, service_execution_failed_check_count: 0, service_execution_missing_check_count: 0, + service_id: "none".to_string(), + service_route: "none".to_string(), reason: format!( "Restart policy coverage needs attention: missing={}, disabled={}, attention={}.", policy_report.missing_count, @@ -3677,6 +3698,8 @@ fn swarm_action_rows( requires_elevated_authority: false, service_execution_failed_check_count: 0, service_execution_missing_check_count: 0, + service_id: receipt_directory_row_service_id(row).unwrap_or_else(|| "unknown-service".to_string()), + service_route: row.route.clone(), reason: format!( "Windows service lifecycle receipt {} needs readback/audit before the daemon swarm can be called service-ready.", row.route @@ -3767,6 +3790,8 @@ fn swarm_action_rows( requires_elevated_authority, service_execution_failed_check_count: runbook_action.failed_check_count, service_execution_missing_check_count: runbook_action.missing_check_count, + service_id: runbook_action.service_id.clone(), + service_route: runbook_action.route.clone(), reason, private_state_exposed: runbook_action.private_state_exposed, }); @@ -3792,6 +3817,8 @@ fn swarm_action_rows( requires_elevated_authority: false, service_execution_failed_check_count: 0, service_execution_missing_check_count: 0, + service_id: "none".to_string(), + service_route: "none".to_string(), reason: "No liveness, restart-policy, tool-host, or service-lifecycle attention rows are present.".to_string(), private_state_exposed: false, }); @@ -3805,12 +3832,14 @@ fn swarm_action_rows( fn swarm_action_tui_row(row: &SwarmActionRow) -> String { format!( - "{:03} | {} | {} | {} | {} | command={} | mutates={} | elevated={} | failedChecks={} | missingChecks={} | artifact={} | sha256={} | audit={}", + "{:03} | {} | {} | {} | {} | service={} | route={} | command={} | mutates={} | elevated={} | failedChecks={} | missingChecks={} | artifact={} | sha256={} | audit={}", row.priority, row.family, row.status, row.wrapper_mode, row.authority_gate, + row.service_id, + row.service_route, row.wrapper_command, row.mutates_state, row.requires_elevated_authority, @@ -3854,6 +3883,8 @@ fn service_execution_runbook_actions( private_state_exposed: row.private_state_exposed, failed_check_count: cluster_report.failed_count, missing_check_count: cluster_report.missing_count, + service_id: receipt_directory_row_service_id(row) + .unwrap_or_else(|| "unknown-service".to_string()), completion_audit_wrapper_mode: "cluster-service-execution-audit".to_string(), completion_audit_wrapper_command: WRAPPER_CLUSTER_SERVICE_EXECUTION_AUDIT_COMMAND.to_string(), @@ -3871,6 +3902,7 @@ fn service_execution_runbook_actions( private_state_exposed: row.private_state_exposed, failed_check_count: report.failed_count, missing_check_count: report.missing_count, + service_id, completion_audit_wrapper_mode: "service-execution-audit".to_string(), completion_audit_wrapper_command: WRAPPER_SERVICE_EXECUTION_AUDIT_COMMAND .to_string(), diff --git a/notes/fresh-workspace-handoff.md b/notes/fresh-workspace-handoff.md index f9a082ed..dcc75123 100644 --- a/notes/fresh-workspace-handoff.md +++ b/notes/fresh-workspace-handoff.md @@ -72,6 +72,7 @@ remembers doctrine; the branch remembers the blade. - 2026-06-18: Service execution failed-check rows now carry `serviceId` and the compact TUI/PowerShell summaries render `serviceId::action=status`. Single-service overview audits are scoped to service ids from current service-lifecycle attention rows instead of blending all non-cluster receipts, so old EventLog proof scars cannot masquerade as Epiphany supervisor service evidence. Live wrapper proof `local-20260618-215343-309-3f5dd519` printed cluster failures under `epiphany-cluster-daemon-services::...` and supervisor-service missing checks under `epiphany-daemon-supervisor-service::...`, with `privateStateExposed=false`; standalone `service-execution-audit` proof `local-20260618-215828-537-12b29ecf` printed the supervisor-service prefix on runbook witness and failed-check rows, and standalone `cluster-service-execution-audit` proof `local-20260618-215948-348-7be0110c` printed the cluster service prefix on runbook witness and failed-check rows. - 2026-06-18: The `swarm-overview`/`swarm-triage` action queue now carries aggregate sealed service-execution wound counts on the elevated service-control row as `serviceExecutionFailedCheckCount` and `serviceExecutionMissingCheckCount`, with compact wrapper/TUI rows rendering `failedChecks=` and `missingChecks=`. Non-mutating readback rows keep both counts at zero. Live proofs `local-20260618-220534-199-d8e90287` and `local-20260618-220534-205-59582da5` printed the priority-50 `service-execution-authority` row with `failedChecks=11`, `missingChecks=6`, `artifactStatus=present`, the sealed cluster runbook SHA-256, and `privateStateExposed=false`. - 2026-06-18: The elevated service-control action queue now emits one `service-execution-authority` row per sealed runbook witness instead of attaching all failed checks to the recommended cluster artifact. Source smoke seeds both cluster and single-service runbook witnesses and proves separate scoped rows. Live overview proof `local-20260618-221339-826-b1981064` and triage proof `local-20260618-221340-099-4b4baba8` printed priority 50 for `cluster-service-execution-runbook` with `failedChecks=5`, `missingChecks=0`, SHA-256 `3239ac17008b1ce857970e40b17d37a1ecf1631a3a6636bb2b8678312fb604a0`, and aftercare `cluster-service-execution-audit`; and priority 51 for `service-execution-runbook` with `failedChecks=6`, `missingChecks=6`, SHA-256 `b213a3c11a8f11a03061fcd743f507edaa59bc6767257b79cef63329596375e7`, and aftercare `service-execution-audit`, with no private state exposure. +- 2026-06-18: `SwarmActionRow` now carries explicit `serviceId` and `serviceRoute`, and Rust TUI plus PowerShell wrapper action queues render `service=` and `route=` for service lifecycle/readiness rows. Non-service rows render `none`. Source smoke guards both fields on the cluster and single-service runbook authority rows. Live overview proof `local-20260618-221912-231-805389bf` and triage proof `local-20260618-221912-282-a79ba8bd` showed readback rows and both elevated runbook rows naming `epiphany-cluster-daemon-services` and `epiphany-daemon-supervisor-service` directly, without parsing artifact paths or prose. - Full service lifecycle history now excludes the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror entry. Latest remains readable through the dedicated latest loader; history contains only real per-receipt events. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two writes load as exactly two history receipts while latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage artifacts `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove the compact swarm sights still report service lifecycle attention and the present elevated runbook artifact without daemon pokes or service mutation. A broad unscoped `cargo test service_lifecycle_receipt_history_excludes_latest_mirror` was abandoned after the Windows test harness fanned out across bin targets and hit a broken pipe; use `cargo test --lib service_lifecycle_receipt_history_excludes_latest_mirror` for this check. - The operator snapshot distills typed fields such as thread id, state status, coordinator action, CRRC action, reorient action, available actions, and artifact refs; it does not preserve the raw JSON status blob as internal state. JSON remains display/evidence at the edge. - Local MVP Persona front-door bubbles now route their `epiphany.cultmesh.persona_speech_audit.v0` witness into the same `.epiphany-run/cultmesh/local-verse.ccmp` store and write a final `local-verse-context.json` for MVP mode too. `Persona-bubble.stdout.json` remains display; the local Verse carries the mouth-edge eligibility receipt. diff --git a/state/ledgers.msgpack b/state/ledgers.msgpack index 8c15cc070f56521824faeb53a3ccb8bb77cb98fc..f2016ff08b7d67be79aca3254ae99b2a0614c6b7 100644 GIT binary patch delta 350 zcmXwzF-yZx6opL_a1f!B3SF+~qBJIX#hP|-uY;nsi@3bJ+|);(dHPD-nje#j6>sH_$L8`P@!Dnn>1A3o(){k*T)D-YE2$9*5uEV^G^&g` and `route=` for service lifecycle and service authority rows, while non-service rows render `none`. Source smoke guards both fields, and live overview/triage proofs `local-20260618-221912-231-805389bf` and `local-20260618-221912-282-a79ba8bd` showed the cluster and supervisor-service identities on readback and elevated runbook rows with `privateStateExposed=false`. - Service lifecycle receipt history is now event-only: `load_epiphany_cultmesh_daemon_service_lifecycle_receipts` filters out the `epiphany-local/daemon-service-lifecycle-receipt/latest` mirror, while `load_latest_epiphany_cultmesh_daemon_service_lifecycle_receipt` remains the latest-state reader. Focused unit test `service_lifecycle_receipt_history_excludes_latest_mirror` proves two per-receipt writes return exactly two history records and latest points at the second. Fresh smoke `verse-query-lifecycle-history-filter-smoke` and live overview/triage `local-20260618-145632-497-efac6f0d` / `local-20260618-145632-321-867947af` prove compact swarm sights still expose service lifecycle attention plus the present elevated runbook artifact without daemon pokes or service mutation. Do not use a broad unscoped cargo test filter for this check on Windows; it fans out across bin harnesses and hit a broken pipe during this pass. - `epiphany-verse-query seed-compact` is the compact seed receipt for wrappers and read-only rites. The older `seed` command still prints the full local Verse context for explicit debugging, but compact wrapper modes now avoid full `seed`/final `query` readback after the combined overview proof exposed Windows debug stack overflow from full-context serialization pressure. next_action: Continue the swarm-readiness cuts toward elevated operator install/start execution and completed audit/readiness for the seven installed services. Run generated service execution/install/control runbooks only when the operator grants that authority. The current local Verse proves liveness readiness, scheduler-policy coverage, daemon-body invocation, per-organ launch artifact generation, per-organ install-plan generation, non-elevated install/start/stop execution refusal, read-only installed-service audit, cluster-wide service control planning, service-lifecycle attention surfacing, and cluster execution audit acceptance criteria: `swarm-overview` now reports `status=attention`, `livenessStatus=ready`, `recoveryStatus=attention`, and `recommendedWrapperMode=cluster-service-execution-audit`; `service-tick` can refresh all seven daemon heartbeats through sealed scheduler receipts; `cluster-service-runbook` writes seven explicit `epiphany-cluster-daemon serve` commands with `privateStateExposed=false`; `cluster-service-install-plan` writes seven distinct Windows service install commands with `privateStateExposed=false`; `cluster-service-install-execute`, `cluster-service-start-execute`, and `cluster-service-stop-execute` refuse as `execution-refused-not-elevated` with `executed=false` when the shell lacks service authority; `cluster-service-start-plan` and `cluster-service-stop-plan` emit seven non-mutating planned rows; `cluster-service-audit` currently reports `incomplete` with seven missing services in this non-installed environment; `service-execution-runbook` and `cluster-service-execution-runbook` write elevated wrapper sequences that continue after per-step failure, run final audits in `finally`, exit nonzero after audit when any step failed, and seal typed runbook receipts with aftercare args (`stepFailurePolicy`, `continueAfterStepFailure`, `nonzeroExitFailsStep`, `exitsNonzeroAfterFinalAudit`); and `service-execution-audit` plus `cluster-service-execution-audit` now require those runbook witnesses before considering elevated-ready/install/start/audit/status/reconcile/stop effect receipts. Preserve the existing typed local Verse surfaces: `service-plan`, `service-launch`, `service-runbook`, `cluster-service-runbook`, `cluster-service-install-plan`, `cluster-service-install-execute`, `cluster-service-audit`, `cluster-service-start-plan`, `cluster-service-stop-plan`, `cluster-service-start-execute`, `cluster-service-stop-execute`, `cluster-service-execution-readiness`, `cluster-service-execution-runbook`, `cluster-service-execution-audit`, `service-execution-runbook`, `service-execution-audit`, `service-tick`, `service-policy-directory`, `agent-state-soa`, `swarm-status`, `swarm-poke-down`, `swarm-triage`, `cluster-topology`, `eve-surfaces`, `eve-connect`, `collaboration-feedback`, `bifrost-publication`, `bifrost-ledger`, `receipt-directory`, `tool-directory`, `tool-invoke`, `swarm-overview`, `seed-compact`, service manager status/reconcile/readiness/control wrappers, compact daemon scheduler/policy receipt rows, daemon liveness-gated tool routing, Bifrost/Imagination chains, coordinator-run receipts, Hands gates, role review mirrors, and sealed agent-state SoA summary. Keep the seven-standing-faculty SoA, stale-turn repair, memory lifecycle, shared local Verse witnesses, and typed CultMesh Persona speech gate intact. diff --git a/tools/epiphany_local_run.ps1 b/tools/epiphany_local_run.ps1 index a78abf3e..bee76b02 100644 --- a/tools/epiphany_local_run.ps1 +++ b/tools/epiphany_local_run.ps1 @@ -1834,7 +1834,15 @@ if ($resultPath -ne "" -and (Test-Path -LiteralPath $resultPath)) { if ($null -eq $missingChecks) { $missingChecks = 0 } - "$($_.priority):$($_.family):$($_.wrapperMode):$($_.status):command=${command}:mutates=$($_.mutatesState):elevated=$($_.requiresElevatedAuthority):failedChecks=${failedChecks}:missingChecks=${missingChecks}:artifactStatus=${artifactStatus}:sha256=${artifactSha256}:audit=${audit}:aftercare=${aftercare}:artifact=$artifact" + $serviceId = $_.serviceId + if ($null -eq $serviceId -or $serviceId -eq "") { + $serviceId = "none" + } + $serviceRoute = $_.serviceRoute + if ($null -eq $serviceRoute -or $serviceRoute -eq "") { + $serviceRoute = "none" + } + "$($_.priority):$($_.family):$($_.wrapperMode):$($_.status):service=${serviceId}:route=${serviceRoute}:command=${command}:mutates=$($_.mutatesState):elevated=$($_.requiresElevatedAuthority):failedChecks=${failedChecks}:missingChecks=${missingChecks}:artifactStatus=${artifactStatus}:sha256=${artifactSha256}:audit=${audit}:aftercare=${aftercare}:artifact=$artifact" }) -join "; ") } $serviceExecutionFailedChecks = Format-ServiceExecutionFailedChecks $result.serviceExecutionFailedCheckRows @@ -1914,7 +1922,15 @@ if ($resultPath -ne "" -and (Test-Path -LiteralPath $resultPath)) { if ($null -eq $missingChecks) { $missingChecks = 0 } - "$($_.priority):$($_.family):$($_.wrapperMode):$($_.status):command=${command}:mutates=$($_.mutatesState):elevated=$($_.requiresElevatedAuthority):failedChecks=${failedChecks}:missingChecks=${missingChecks}:artifactStatus=${artifactStatus}:sha256=${artifactSha256}:audit=${audit}:aftercare=${aftercare}:artifact=$artifact" + $serviceId = $_.serviceId + if ($null -eq $serviceId -or $serviceId -eq "") { + $serviceId = "none" + } + $serviceRoute = $_.serviceRoute + if ($null -eq $serviceRoute -or $serviceRoute -eq "") { + $serviceRoute = "none" + } + "$($_.priority):$($_.family):$($_.wrapperMode):$($_.status):service=${serviceId}:route=${serviceRoute}:command=${command}:mutates=$($_.mutatesState):elevated=$($_.requiresElevatedAuthority):failedChecks=${failedChecks}:missingChecks=${missingChecks}:artifactStatus=${artifactStatus}:sha256=${artifactSha256}:audit=${audit}:aftercare=${aftercare}:artifact=$artifact" }) -join "; ") } $serviceExecutionFailedChecks = Format-ServiceExecutionFailedChecks $result.serviceExecutionFailedCheckRows