harnery 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -96
- package/dist/commands/agents.d.ts +23 -3
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +379 -198
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +5 -4
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts.map +1 -1
- package/dist/commands/semantic.js +54 -2
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +67 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +244 -10
- package/dist/core/agents/live-lifecycle-v3.js +6 -1
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +6 -1
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +24 -7
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +94 -13
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +18 -0
- package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +15 -90
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/artifacts/index.d.ts +21 -0
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +46 -1
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +81 -41
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +17 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.js +3 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +4 -2
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +3 -1
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +13 -21
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +45 -41
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.js +1 -1
- package/dist/core/events/v3/producers/intake.d.ts +7 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +25 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +55 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +353 -24
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
- package/dist/core/hooks/cli.js +212 -30
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +8 -3
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
- package/dist/core/hooks/remediation-cap.js +3 -11
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +8 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +11 -0
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +11 -8
- package/dist/core/semantic/adapters.d.ts.map +1 -1
- package/dist/core/semantic/adapters.js +169 -31
- package/dist/core/semantic/contract.d.ts +532 -48
- package/dist/core/semantic/contract.d.ts.map +1 -1
- package/dist/core/semantic/contract.js +104 -3
- package/dist/core/semantic/index.d.ts +7 -3
- package/dist/core/semantic/index.d.ts.map +1 -1
- package/dist/core/semantic/index.js +7 -3
- package/dist/core/semantic/once.d.ts +6 -1
- package/dist/core/semantic/once.d.ts.map +1 -1
- package/dist/core/semantic/once.js +80 -9
- package/dist/core/semantic/prompt.d.ts.map +1 -1
- package/dist/core/semantic/prompt.js +14 -1
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +14 -3
- package/dist/core/semantic/scheduler.d.ts.map +1 -1
- package/dist/core/semantic/scheduler.js +30 -6
- package/dist/core/semantic/service-status.d.ts +20 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -1
- package/dist/core/semantic/service-status.js +60 -4
- package/dist/core/semantic/service.d.ts +1 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +104 -15
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +11 -1
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +4 -3
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +3 -1
- package/dist/core/semantic/validate.d.ts.map +1 -1
- package/dist/core/semantic/validate.js +34 -1
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +5 -0
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +29 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +324 -112
- package/src/commander.ts +462 -95
- package/src/commands/agents.ts +517 -190
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +6 -7
- package/src/commands/conversations.ts +279 -0
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +66 -1
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +77 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/live-authority-v3.ts +341 -10
- package/src/core/agents/live-lifecycle-v3.ts +6 -1
- package/src/core/agents/live-observation-v3.ts +6 -1
- package/src/core/agents/render/prompt-context.ts +27 -6
- package/src/core/agents/rules/stop-hook.ts +107 -16
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-writer.ts +27 -0
- package/src/core/agents/state/live-coordination-view.ts +16 -105
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/artifacts/index.ts +64 -1
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +17 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +3 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +5 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +64 -46
- package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +1 -1
- package/src/core/events/v3/producers/intake.ts +30 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +571 -33
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +58 -7
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
- package/src/core/hooks/cli.ts +226 -32
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +12 -6
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +18 -0
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +200 -41
- package/src/core/semantic/contract.ts +135 -3
- package/src/core/semantic/index.ts +76 -2
- package/src/core/semantic/once.ts +93 -7
- package/src/core/semantic/prompt.ts +13 -1
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +49 -5
- package/src/core/semantic/service-status.ts +99 -5
- package/src/core/semantic/service.ts +116 -15
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +20 -6
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +31 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/templates.ts +5 -0
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
package/dist/commands/agents.js
CHANGED
|
@@ -14,14 +14,15 @@
|
|
|
14
14
|
*/
|
|
15
15
|
import { spawnSync } from "node:child_process";
|
|
16
16
|
import { existsSync, mkdirSync, mkdtempSync, readdirSync, readFileSync, rmSync, writeFileSync, } from "node:fs";
|
|
17
|
-
import {
|
|
17
|
+
import { tmpdir } from "node:os";
|
|
18
18
|
import { basename, join, resolve } from "node:path";
|
|
19
19
|
import { coordBinPath } from "../core/agents/coord-bin.js";
|
|
20
20
|
import { checkGitFinalization, formatGitFinalizationFailure, readSessionWriteClaims, } from "../core/agents/finalization.js";
|
|
21
21
|
import { emitEventV3, monorepoRoot, nativeSessionIdentity, normalizeAdapter, resolveOwner, resolveOwnerBySessionEnv, resolveOwnerWithSource, sessionIdentityFromEnv, } from "../core/agents/index.js";
|
|
22
|
-
import { reopenLiveCoordinationGenerationV3 } from "../core/agents/live-authority-v3.js";
|
|
22
|
+
import { bootstrapLiveCoordinationAuthorityV3, LiveCoordinationAuthorityV3Error, reopenLiveCoordinationGenerationV3, } from "../core/agents/live-authority-v3.js";
|
|
23
23
|
import { listSessionFinalizationRequestsV3, observeHostDisappearedV3, reconcileSessionFinalizationV3, requestSessionEndExplicitV3, } from "../core/agents/session-finalizer-v3.js";
|
|
24
24
|
import { SESSION_NAME_DISPLAY_NOTE, sessionNameDisplayPending, } from "../core/agents/session-name-display.js";
|
|
25
|
+
import { agentDisplayName } from "../core/agents/state/activity-log.js";
|
|
25
26
|
import { buildLifecycleSuggestedName, buildSuggestedName, readHeartbeat as readHeartbeatCache, } from "../core/agents/state/heartbeat-writer.js";
|
|
26
27
|
import { readLiveCoordinationRow, readLiveCoordinationRows, } from "../core/agents/state/live-coordination-view.js";
|
|
27
28
|
import { foldSessionState, } from "../core/agents/state/session-state.js";
|
|
@@ -29,12 +30,13 @@ import { coordFreshnessSeconds, resolveBinName, sessionFinalizationConfig, } fro
|
|
|
29
30
|
import { readEventV3ControlState } from "../core/events/v3/control.js";
|
|
30
31
|
import { projectCoordinationViewV3 } from "../core/events/v3/coordination-view.js";
|
|
31
32
|
import { liveInstanceIdV3 } from "../core/events/v3/live-routing.js";
|
|
33
|
+
import { countSummarizedSinceV3, listDiagnosticSummariesV3, } from "../core/events/v3/producers/diagnostic-summaries.js";
|
|
32
34
|
import { listHookIntakeGroupsV3, listHookIntakeRecordsV3, } from "../core/events/v3/producers/intake.js";
|
|
33
35
|
import { listHookProducerStateRecordsV3, readHookProducerStateV3, } from "../core/events/v3/producers/recorder.js";
|
|
34
36
|
import { readLedgerV3 } from "../core/events/v3/reader.js";
|
|
35
37
|
import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../core/events/v3/writer.js";
|
|
36
38
|
import { evaluateRunQualityIfDue } from "../core/guard/index.js";
|
|
37
|
-
import { readRuntimeContextUsage } from "../core/hooks/adapter/runtime-telemetry.js";
|
|
39
|
+
import { readRuntimeContextTelemetry, readRuntimeContextUsage, } from "../core/hooks/adapter/runtime-telemetry.js";
|
|
38
40
|
import { readRemoteMachines } from "../core/presence/index.js";
|
|
39
41
|
import { registerContextCommand } from "./context.js";
|
|
40
42
|
function readCurrentCoordinationRow(instanceId) {
|
|
@@ -128,7 +130,7 @@ function lifecycleLabel(hb) {
|
|
|
128
130
|
return state === "blocked" && hb.task_state_reason ? `${state}: ${hb.task_state_reason}` : state;
|
|
129
131
|
}
|
|
130
132
|
let emit;
|
|
131
|
-
export function registerAgentsCommand(program, emitParam, programContext) {
|
|
133
|
+
export function registerAgentsCommand(program, emitParam, programContext, binName = resolveBinName()) {
|
|
132
134
|
emit = emitParam;
|
|
133
135
|
const cmd = program
|
|
134
136
|
.command("agents")
|
|
@@ -207,7 +209,7 @@ export function registerAgentsCommand(program, emitParam, programContext) {
|
|
|
207
209
|
.command("set-task <text...>")
|
|
208
210
|
.description("Declare what this agent is currently working on. Visible to peers in the " +
|
|
209
211
|
"per-prompt snapshot. Pass an empty string ('') to clear.")
|
|
210
|
-
.option("--session-id <id>", `Set the task on the heartbeat with this session_id directly, bypassing the ppid walk. Mirror of \`status --session-id\`: use it when the ppid walk can't resolve self (e.g. Cursor, whose shell tool calls don't descend from a pid-map-registered anchor). Discover the id via \`${
|
|
212
|
+
.option("--session-id <id>", `Set the task on the heartbeat with this session_id directly, bypassing the ppid walk. Mirror of \`status --session-id\`: use it when the ppid walk can't resolve self (e.g. Cursor, whose shell tool calls don't descend from a pid-map-registered anchor). Discover the id via \`${binName} agents list --json\`.`)
|
|
211
213
|
.action((text, opts) => {
|
|
212
214
|
runSetTask(text.join(" "), opts);
|
|
213
215
|
});
|
|
@@ -274,7 +276,7 @@ export function registerAgentsCommand(program, emitParam, programContext) {
|
|
|
274
276
|
});
|
|
275
277
|
cmd
|
|
276
278
|
.command("wait <name>")
|
|
277
|
-
.description(`Block until a peer agent releases files (their \`files_touched\` becomes empty, OR they exit). Pair with \`${
|
|
279
|
+
.description(`Block until a peer agent releases files (their \`files_touched\` becomes empty, OR they exit). Pair with \`${binName} agents ping\` to coordinate hand-offs.`)
|
|
278
280
|
.option("--file <path>", "Wait only for these specific paths (repeatable)", collectPath, [])
|
|
279
281
|
.option("--timeout <dur>", "Give up after this duration; suffix s/m/h/d is required (e.g. 30s, 5m, 1h). Default 60m.", "60m")
|
|
280
282
|
.option("--poll-secs <n>", "Poll interval in seconds (default 5)", "5")
|
|
@@ -319,11 +321,10 @@ export function registerAgentsCommand(program, emitParam, programContext) {
|
|
|
319
321
|
});
|
|
320
322
|
cmd
|
|
321
323
|
.command("heal")
|
|
322
|
-
.description("
|
|
323
|
-
"
|
|
324
|
-
"
|
|
325
|
-
.
|
|
326
|
-
.requiredOption("--kind <kind>", "pidmap | cache")
|
|
324
|
+
.description("Repair the current session's disposable coordination cache from V3. " +
|
|
325
|
+
"Use explicit options to target another generation or repair process attribution.")
|
|
326
|
+
.option("--owner <id>", "Target agent's instance_id. Defaults to the current session.")
|
|
327
|
+
.option("--kind <kind>", "pidmap | cache. Defaults to cache.")
|
|
327
328
|
.option("--session-id <id>", "(--kind cache) native session id used to join the authoritative V3 generation.")
|
|
328
329
|
.option("--adapter <id>", "(--kind cache) adapter used to validate the authoritative V3 generation: " +
|
|
329
330
|
"claude-code | cursor | codex.")
|
|
@@ -331,6 +332,9 @@ export function registerAgentsCommand(program, emitParam, programContext) {
|
|
|
331
332
|
"this shell's ppid chain for a claude process. Pass explicitly " +
|
|
332
333
|
"when calling from outside Claude Code's Bash tool tree (e.g. " +
|
|
333
334
|
"from cron or an external script).")
|
|
335
|
+
.option("--quarantine-transaction <id>", "Quarantine one irreconcilable prepared authority transaction after proving its event was never committed.")
|
|
336
|
+
.option("--approval-record-id <id>", "Durable identifier for the operator approval authorizing transaction quarantine.")
|
|
337
|
+
.option("--yes", "Confirm the exact prepared transaction may be quarantined.")
|
|
334
338
|
.option("--json", "JSON envelope output")
|
|
335
339
|
.action((opts) => {
|
|
336
340
|
runHeal(opts);
|
|
@@ -605,13 +609,10 @@ function runIdentityAssume(target, opts) {
|
|
|
605
609
|
process.exit(1);
|
|
606
610
|
}
|
|
607
611
|
if (!opts.sessionId)
|
|
608
|
-
|
|
612
|
+
ensureAdapterSession(root);
|
|
609
613
|
const owner = opts.sessionId ?? resolveOwner();
|
|
610
614
|
if (!owner) {
|
|
611
|
-
emit.error(
|
|
612
|
-
code: "no_pidmap_entry",
|
|
613
|
-
message: "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)",
|
|
614
|
-
});
|
|
615
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)"));
|
|
615
616
|
process.exit(1);
|
|
616
617
|
}
|
|
617
618
|
try {
|
|
@@ -791,14 +792,11 @@ function runWhoami(opts) {
|
|
|
791
792
|
});
|
|
792
793
|
process.exit(1);
|
|
793
794
|
}
|
|
794
|
-
|
|
795
|
+
ensureAdapterSession(root);
|
|
795
796
|
const resolved = resolveOwnerWithSource();
|
|
796
797
|
const myOwner = resolved.owner;
|
|
797
798
|
if (!myOwner) {
|
|
798
|
-
emit.error(
|
|
799
|
-
code: "no_pidmap_entry",
|
|
800
|
-
message: "not in an agent session; ppid walk found no pid-map entry",
|
|
801
|
-
});
|
|
799
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry"));
|
|
802
800
|
process.exit(1);
|
|
803
801
|
}
|
|
804
802
|
const hb = readLiveCoordinationRow(root, myOwner);
|
|
@@ -1231,49 +1229,88 @@ function cursorEnvSessionId() {
|
|
|
1231
1229
|
return null;
|
|
1232
1230
|
return raw.startsWith("bc-") && raw.length > 3 ? raw.slice(3) : raw;
|
|
1233
1231
|
}
|
|
1234
|
-
function
|
|
1235
|
-
|
|
1232
|
+
function commandSessionBootstrap() {
|
|
1233
|
+
const cursorSessionId = cursorEnvSessionId();
|
|
1234
|
+
if (process.env.CURSOR_AGENT === "1" && cursorSessionId) {
|
|
1235
|
+
return { adapter: "cursor", sessionId: cursorSessionId };
|
|
1236
|
+
}
|
|
1237
|
+
if (process.env.HARNERY_AGENT_COORD_BRIDGE?.trim() === "codex-wsl") {
|
|
1238
|
+
const sessionId = sessionIdentityFromEnv();
|
|
1239
|
+
if (sessionId)
|
|
1240
|
+
return { adapter: "codex", sessionId };
|
|
1241
|
+
}
|
|
1242
|
+
const claudeSessionId = process.env.CLAUDE_CODE_SESSION_ID?.trim();
|
|
1243
|
+
if (claudeSessionId) {
|
|
1244
|
+
return { adapter: "claude-code", sessionId: claudeSessionId };
|
|
1245
|
+
}
|
|
1246
|
+
return null;
|
|
1236
1247
|
}
|
|
1237
|
-
function
|
|
1238
|
-
|
|
1248
|
+
function ensureAdapterSession(root) {
|
|
1249
|
+
const bootstrap = commandSessionBootstrap();
|
|
1250
|
+
if (!bootstrap)
|
|
1251
|
+
return;
|
|
1252
|
+
// Claude Code owns a reliable native SessionStart hook. Its environment is
|
|
1253
|
+
// accepted by the explicit `agents heal` recovery path, but ordinary
|
|
1254
|
+
// identity and status commands must not impersonate that hook. The heal
|
|
1255
|
+
// bootstrap records derived provenance instead.
|
|
1256
|
+
if (bootstrap.adapter === "claude-code")
|
|
1239
1257
|
return;
|
|
1240
1258
|
// Explicit owner override means the caller already knows who they are.
|
|
1241
1259
|
// Bootstrapping sessionStart inherits that env into the child hook, which
|
|
1242
1260
|
// re-projects a fresh heartbeat onto the override owner and can wipe an
|
|
1243
1261
|
// assumed persona agent_id (seen under Cursor integration fixtures).
|
|
1244
|
-
if (process.env.HARNERY_AGENT_COORD_OWNER?.trim())
|
|
1262
|
+
if (bootstrap.adapter === "cursor" && process.env.HARNERY_AGENT_COORD_OWNER?.trim())
|
|
1245
1263
|
return;
|
|
1246
1264
|
if (resolveOwnerBySessionEnv(root))
|
|
1247
1265
|
return;
|
|
1248
|
-
const sessionId = cursorEnvSessionId();
|
|
1249
|
-
if (!sessionId)
|
|
1250
|
-
return;
|
|
1251
1266
|
const agentHook = coordBinPath("agent-hook", root);
|
|
1252
1267
|
if (!agentHook)
|
|
1253
1268
|
return;
|
|
1254
1269
|
const payload = JSON.stringify({
|
|
1255
|
-
conversation_id: sessionId,
|
|
1256
|
-
session_id: sessionId,
|
|
1270
|
+
...(bootstrap.adapter === "cursor" ? { conversation_id: bootstrap.sessionId } : {}),
|
|
1271
|
+
session_id: bootstrap.sessionId,
|
|
1257
1272
|
hook_event_name: "sessionStart",
|
|
1258
1273
|
workspace_roots: [root],
|
|
1259
1274
|
cwd: root,
|
|
1260
|
-
|
|
1261
|
-
|
|
1275
|
+
...(bootstrap.adapter === "cursor"
|
|
1276
|
+
? { composer_mode: "agent", is_background_agent: false }
|
|
1277
|
+
: { source: "resume" }),
|
|
1262
1278
|
});
|
|
1263
|
-
spawnSync("bash", [agentHook, "session-start", "--adapter",
|
|
1279
|
+
spawnSync("bash", [agentHook, "session-start", "--adapter", bootstrap.adapter], {
|
|
1264
1280
|
input: payload,
|
|
1265
1281
|
cwd: root,
|
|
1266
1282
|
encoding: "utf8",
|
|
1267
1283
|
timeout: 3000,
|
|
1268
1284
|
env: {
|
|
1269
1285
|
...process.env,
|
|
1270
|
-
HARNERY_AGENT_COORD_PLATFORM:
|
|
1286
|
+
HARNERY_AGENT_COORD_PLATFORM: bootstrap.adapter,
|
|
1271
1287
|
HARNERY_COORD_ROOT_OVERRIDE: root,
|
|
1272
|
-
|
|
1273
|
-
|
|
1288
|
+
HARNERY_AGENT_COORD_SESSION_ID: bootstrap.sessionId,
|
|
1289
|
+
...(bootstrap.adapter === "cursor"
|
|
1290
|
+
? {
|
|
1291
|
+
CURSOR_SESSION_ID: bootstrap.sessionId,
|
|
1292
|
+
CURSOR_CONVERSATION_ID: bootstrap.sessionId,
|
|
1293
|
+
}
|
|
1294
|
+
: { CODEX_THREAD_ID: bootstrap.sessionId }),
|
|
1274
1295
|
},
|
|
1275
1296
|
});
|
|
1276
1297
|
}
|
|
1298
|
+
function sessionResolutionFailure(root, fallbackMessage) {
|
|
1299
|
+
if (!sessionIdentityFromEnv())
|
|
1300
|
+
return { code: "no_pidmap_entry", message: fallbackMessage };
|
|
1301
|
+
const control = readEventV3ControlState(root);
|
|
1302
|
+
if (control.state !== "candidate" && control.state !== "active") {
|
|
1303
|
+
const detail = `${control.state}:${control.reason}`;
|
|
1304
|
+
return {
|
|
1305
|
+
code: "event_v3_control_unavailable",
|
|
1306
|
+
message: `the adapter session identity is present, but the V3 control state cannot accept session onboarding (${detail})`,
|
|
1307
|
+
};
|
|
1308
|
+
}
|
|
1309
|
+
return {
|
|
1310
|
+
code: "session_generation_unavailable",
|
|
1311
|
+
message: "the adapter session identity is present, but no current V3 session generation was available after onboarding",
|
|
1312
|
+
};
|
|
1313
|
+
}
|
|
1277
1314
|
function runReleaseClaim(path) {
|
|
1278
1315
|
const root = monorepoRoot();
|
|
1279
1316
|
if (!root) {
|
|
@@ -1285,10 +1322,7 @@ function runReleaseClaim(path) {
|
|
|
1285
1322
|
}
|
|
1286
1323
|
const myOwner = resolveOwner();
|
|
1287
1324
|
if (!myOwner) {
|
|
1288
|
-
emit.error(
|
|
1289
|
-
code: "no_pidmap_entry",
|
|
1290
|
-
message: "not in an agent session; ppid walk found no pid-map entry",
|
|
1291
|
-
});
|
|
1325
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry"));
|
|
1292
1326
|
process.exit(1);
|
|
1293
1327
|
}
|
|
1294
1328
|
// Canonicalize: absolute paths under coordRoot get the prefix stripped;
|
|
@@ -1329,13 +1363,10 @@ function runSetTask(task, opts) {
|
|
|
1329
1363
|
// ritual command. The env id carries the same trust as an explicit
|
|
1330
1364
|
// --session-id, and set-task mints the heartbeat exactly as that path does.
|
|
1331
1365
|
if (!opts?.sessionId)
|
|
1332
|
-
|
|
1366
|
+
ensureAdapterSession(root);
|
|
1333
1367
|
const myOwner = opts?.sessionId ?? resolveOwner() ?? sessionIdentityFromEnv();
|
|
1334
1368
|
if (!myOwner) {
|
|
1335
|
-
emit.error(
|
|
1336
|
-
code: "no_pidmap_entry",
|
|
1337
|
-
message: "not in an agent session; no session-id environment identity and the ppid walk found no pid-map entry (pass --session-id to bypass)",
|
|
1338
|
-
});
|
|
1369
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; no session-id environment identity and the ppid walk found no pid-map entry (pass --session-id to bypass)"));
|
|
1339
1370
|
process.exit(1);
|
|
1340
1371
|
}
|
|
1341
1372
|
// Snapshot BEFORE the mutation: the writer stamps `suggested_session_name`
|
|
@@ -1416,13 +1447,10 @@ function runLifecycle(rawState, opts) {
|
|
|
1416
1447
|
return;
|
|
1417
1448
|
}
|
|
1418
1449
|
if (!opts.sessionId)
|
|
1419
|
-
|
|
1450
|
+
ensureAdapterSession(root);
|
|
1420
1451
|
const myOwner = opts.sessionId ?? resolveOwner() ?? sessionIdentityFromEnv();
|
|
1421
1452
|
if (!myOwner) {
|
|
1422
|
-
emit.error(
|
|
1423
|
-
code: "no_pidmap_entry",
|
|
1424
|
-
message: "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)",
|
|
1425
|
-
});
|
|
1453
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)"));
|
|
1426
1454
|
process.exitCode = 1;
|
|
1427
1455
|
return;
|
|
1428
1456
|
}
|
|
@@ -1581,13 +1609,10 @@ function runSuggestName(descriptionParts, opts) {
|
|
|
1581
1609
|
// Identity: prefer explicit --session-id (ppid-walk-free escape hatch, mirrors
|
|
1582
1610
|
// `status`/`set-task`), fall back to the ppid walk for interactive shell use.
|
|
1583
1611
|
if (!opts.sessionId)
|
|
1584
|
-
|
|
1612
|
+
ensureAdapterSession(root);
|
|
1585
1613
|
const myOwner = opts.sessionId ?? resolveOwner();
|
|
1586
1614
|
if (!myOwner) {
|
|
1587
|
-
emit.error(
|
|
1588
|
-
code: "no_pidmap_entry",
|
|
1589
|
-
message: "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)",
|
|
1590
|
-
});
|
|
1615
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry (pass --session-id to bypass)"));
|
|
1591
1616
|
process.exit(1);
|
|
1592
1617
|
}
|
|
1593
1618
|
const hb = readCurrentCoordinationRow(myOwner);
|
|
@@ -1648,13 +1673,10 @@ function runStatus(opts) {
|
|
|
1648
1673
|
// Identity resolution: prefer explicit --session-id (hook-friendly), fall
|
|
1649
1674
|
// back to ppid walk for interactive shell usage.
|
|
1650
1675
|
if (!opts.sessionId)
|
|
1651
|
-
|
|
1676
|
+
ensureAdapterSession(root);
|
|
1652
1677
|
const myOwner = opts.sessionId ?? resolveOwner();
|
|
1653
1678
|
if (!myOwner) {
|
|
1654
|
-
emit.error(
|
|
1655
|
-
code: "no_pidmap_entry",
|
|
1656
|
-
message: "not in an agent session; ppid walk found no pid-map entry (pass --session-id from a hook payload)",
|
|
1657
|
-
});
|
|
1679
|
+
emit.error(sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry (pass --session-id from a hook payload)"));
|
|
1658
1680
|
process.exit(1);
|
|
1659
1681
|
}
|
|
1660
1682
|
const hb = readCurrentCoordinationRow(myOwner);
|
|
@@ -1685,7 +1707,7 @@ function runStatus(opts) {
|
|
|
1685
1707
|
return;
|
|
1686
1708
|
}
|
|
1687
1709
|
}
|
|
1688
|
-
emitEventV3({
|
|
1710
|
+
const statusEmitted = emitEventV3({
|
|
1689
1711
|
owner: myOwner,
|
|
1690
1712
|
session: nativeSessionIdentity(hb, myOwner),
|
|
1691
1713
|
adapter: normalizeAdapter(hb.platform),
|
|
@@ -1694,6 +1716,16 @@ function runStatus(opts) {
|
|
|
1694
1716
|
status: opts.endTurn ? "end_turn_checked" : opts.json ? "json_checked" : "box_checked",
|
|
1695
1717
|
},
|
|
1696
1718
|
});
|
|
1719
|
+
// The closing box is a success artifact. Never print it when the exact
|
|
1720
|
+
// evidence enforced by the Stop hook did not reach the ledger.
|
|
1721
|
+
if (opts.endTurn && !statusEmitted) {
|
|
1722
|
+
emit.error({
|
|
1723
|
+
code: "status_event_failed",
|
|
1724
|
+
message: `the end-of-turn status event could not be recorded; no status box was issued; rerun \`${resolveBinName(root)} agents status --end-turn\``,
|
|
1725
|
+
});
|
|
1726
|
+
process.exitCode = 1;
|
|
1727
|
+
return;
|
|
1728
|
+
}
|
|
1697
1729
|
let sessionEnd;
|
|
1698
1730
|
if (opts.endSession) {
|
|
1699
1731
|
const canonicalInstanceId = liveInstanceIdV3(hb.instance_id);
|
|
@@ -1753,16 +1785,13 @@ function runStatus(opts) {
|
|
|
1753
1785
|
ctxStr = "unavailable";
|
|
1754
1786
|
}
|
|
1755
1787
|
else if (ctxUsage.percentOnly) {
|
|
1756
|
-
|
|
1757
|
-
// window. Show the percent + window estimate, marked as estimated.
|
|
1758
|
-
const pct = Math.round((ctxUsage.used / ctxUsage.window) * 100);
|
|
1759
|
-
ctxStr = `~${pct}% (Cursor; ${fmtTokens(ctxUsage.window)} window est.)`;
|
|
1788
|
+
ctxStr = `${Math.round(ctxUsage.usedPercent)}% (Cursor first-party)`;
|
|
1760
1789
|
}
|
|
1761
1790
|
else {
|
|
1762
1791
|
ctxStr = `${fmtTokens(ctxUsage.used)} / ${fmtTokens(ctxUsage.window)} (${Math.round((ctxUsage.used / ctxUsage.window) * 100)}%)`;
|
|
1763
1792
|
}
|
|
1764
1793
|
const timeStr = formatLocalTime(new Date());
|
|
1765
|
-
const displayName =
|
|
1794
|
+
const displayName = agentDisplayName(hb.instance_id, hb.name);
|
|
1766
1795
|
// Council pending: list of council IDs where this agent is a member of an
|
|
1767
1796
|
// active council in `open` round_status without a contribution to that round.
|
|
1768
1797
|
// Best-effort: fails silently if .harnery/councils/ doesn't exist.
|
|
@@ -1805,8 +1834,8 @@ function runStatus(opts) {
|
|
|
1805
1834
|
})),
|
|
1806
1835
|
})),
|
|
1807
1836
|
pending_councils: pendingCouncils,
|
|
1808
|
-
context_used: ctxUsage
|
|
1809
|
-
context_window: ctxUsage
|
|
1837
|
+
context_used: ctxUsage && "used" in ctxUsage ? ctxUsage.used : null,
|
|
1838
|
+
context_window: ctxUsage && "window" in ctxUsage ? ctxUsage.window : null,
|
|
1810
1839
|
timestamp_iso: new Date().toISOString(),
|
|
1811
1840
|
timestamp_local: timeStr,
|
|
1812
1841
|
...(quality ? { quality } : {}),
|
|
@@ -1924,15 +1953,15 @@ function formatPeers(peers, cap, staleCount, remoteMachines = []) {
|
|
|
1924
1953
|
}
|
|
1925
1954
|
return main;
|
|
1926
1955
|
}
|
|
1927
|
-
export function collectStatusPeerHealth(root, myOwner, nowMs = Date.now()) {
|
|
1956
|
+
export function collectStatusPeerHealth(root, myOwner, nowMs = Date.now(), readRows = readLiveCoordinationRows, freshnessSeconds = freshnessCutoffSecs()) {
|
|
1928
1957
|
let rows = [];
|
|
1929
1958
|
try {
|
|
1930
|
-
rows =
|
|
1959
|
+
rows = readRows(root);
|
|
1931
1960
|
}
|
|
1932
1961
|
catch {
|
|
1933
1962
|
// V3 authority failures must not resurrect disposable cache rows.
|
|
1934
1963
|
}
|
|
1935
|
-
const cutoffMs = nowMs -
|
|
1964
|
+
const cutoffMs = nowMs - freshnessSeconds * 1000;
|
|
1936
1965
|
const livePeers = [];
|
|
1937
1966
|
let stale = 0;
|
|
1938
1967
|
for (const peer of rows) {
|
|
@@ -1960,85 +1989,21 @@ function readContextUsage(sessionId, platform) {
|
|
|
1960
1989
|
// Dispatch by platform: Codex's JSONL shape is different from Claude Code's
|
|
1961
1990
|
// (event_msg/response_item vs user/assistant), and Codex transcripts live
|
|
1962
1991
|
// under ~/.codex/sessions/YYYY/MM/DD/ rather than ~/.claude/projects/.
|
|
1963
|
-
// Cursor
|
|
1964
|
-
//
|
|
1965
|
-
// readCursorContextUsage reads that via bun:sqlite (percent-only).
|
|
1992
|
+
// Cursor stores a first-party percentage in workspaceStorage. The shared
|
|
1993
|
+
// runtime reader returns it without fabricating a token denominator.
|
|
1966
1994
|
if (platform === "codex")
|
|
1967
1995
|
return readRuntimeContextUsage("codex", sessionId);
|
|
1968
|
-
if (platform === "cursor")
|
|
1969
|
-
|
|
1970
|
-
|
|
1971
|
-
|
|
1972
|
-
|
|
1973
|
-
|
|
1974
|
-
|
|
1975
|
-
|
|
1976
|
-
|
|
1977
|
-
// for parent chats).
|
|
1978
|
-
//
|
|
1979
|
-
// Roots searched: ~/.config/Cursor/User/workspaceStorage (Linux native install)
|
|
1980
|
-
// and /mnt/c/Users/*/AppData/Roaming/Cursor/User/workspaceStorage (WSL).
|
|
1981
|
-
// We don't filter by workspace path; we scan every workspace's state.vscdb
|
|
1982
|
-
// looking for a composerId match. Cheap enough at status time (~60K per file,
|
|
1983
|
-
// <10ms typical). When a match is found, returns synthetic { used, window }
|
|
1984
|
-
// pair where the percent is what's real; absolutes are derived as
|
|
1985
|
-
// (window * percent / 100). Window hard-coded to a Cursor-typical 200K.
|
|
1986
|
-
const roots = [];
|
|
1987
|
-
const linuxRoot = resolve(homedir(), ".config", "Cursor", "User", "workspaceStorage");
|
|
1988
|
-
if (existsSync(linuxRoot))
|
|
1989
|
-
roots.push(linuxRoot);
|
|
1990
|
-
try {
|
|
1991
|
-
if (existsSync("/mnt/c/Users")) {
|
|
1992
|
-
for (const u of readdirSync("/mnt/c/Users")) {
|
|
1993
|
-
const p = `/mnt/c/Users/${u}/AppData/Roaming/Cursor/User/workspaceStorage`;
|
|
1994
|
-
if (existsSync(p))
|
|
1995
|
-
roots.push(p);
|
|
1996
|
-
}
|
|
1997
|
-
}
|
|
1998
|
-
}
|
|
1999
|
-
catch {
|
|
2000
|
-
// ignore
|
|
2001
|
-
}
|
|
2002
|
-
for (const root of roots) {
|
|
2003
|
-
let workspaces;
|
|
2004
|
-
try {
|
|
2005
|
-
workspaces = readdirSync(root);
|
|
2006
|
-
}
|
|
2007
|
-
catch {
|
|
2008
|
-
continue;
|
|
2009
|
-
}
|
|
2010
|
-
for (const ws of workspaces) {
|
|
2011
|
-
const dbPath = `${root}/${ws}/state.vscdb`;
|
|
2012
|
-
if (!existsSync(dbPath))
|
|
2013
|
-
continue;
|
|
2014
|
-
try {
|
|
2015
|
-
// Lazy-import bun:sqlite so non-Bun runtimes (if any) don't choke at load.
|
|
2016
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
2017
|
-
const { Database } = require("bun:sqlite");
|
|
2018
|
-
const db = new Database(dbPath, { readonly: true });
|
|
2019
|
-
const row = db
|
|
2020
|
-
.query("SELECT value FROM ItemTable WHERE key = 'composer.composerData'")
|
|
2021
|
-
.get();
|
|
2022
|
-
db.close();
|
|
2023
|
-
if (!row?.value)
|
|
2024
|
-
continue;
|
|
2025
|
-
const text = typeof row.value === "string" ? row.value : Buffer.from(row.value).toString("utf8");
|
|
2026
|
-
const parsed = JSON.parse(text);
|
|
2027
|
-
const composers = Array.isArray(parsed?.allComposers) ? parsed.allComposers : [];
|
|
2028
|
-
for (const c of composers) {
|
|
2029
|
-
if (c?.composerId === sessionId && typeof c?.contextUsagePercent === "number") {
|
|
2030
|
-
const window = 200000; // hard-coded Cursor-typical window; refine when Cursor exposes the actual ceiling
|
|
2031
|
-
const used = Math.round((window * c.contextUsagePercent) / 100);
|
|
2032
|
-
return { used, window, percentOnly: true };
|
|
2033
|
-
}
|
|
2034
|
-
}
|
|
2035
|
-
}
|
|
2036
|
-
catch {
|
|
2037
|
-
// ignore: DB locked, schema drift, etc. Move on to the next workspace.
|
|
2038
|
-
}
|
|
2039
|
-
}
|
|
1996
|
+
if (platform === "cursor") {
|
|
1997
|
+
const telemetry = readRuntimeContextTelemetry({
|
|
1998
|
+
adapter: "cursor",
|
|
1999
|
+
session_id: sessionId,
|
|
2000
|
+
mode: "status",
|
|
2001
|
+
});
|
|
2002
|
+
return telemetry.state === "observed" && "used_percent" in telemetry
|
|
2003
|
+
? { usedPercent: telemetry.used_percent, percentOnly: true }
|
|
2004
|
+
: null;
|
|
2040
2005
|
}
|
|
2041
|
-
return
|
|
2006
|
+
return readRuntimeContextUsage("claude-code", sessionId);
|
|
2042
2007
|
}
|
|
2043
2008
|
function formatLocalTime(d) {
|
|
2044
2009
|
// "Sat, May 9, 2026, 3:48 AM CDT", rendered in the Chicago timezone.
|
|
@@ -2475,6 +2440,47 @@ export function collectEventLedgerHealthV3(root, nowMs = Date.now()) {
|
|
|
2475
2440
|
catch (error) {
|
|
2476
2441
|
collectionErrors.push(`diagnostics spool unreadable: ${errorText(error)}`);
|
|
2477
2442
|
}
|
|
2443
|
+
// 4b) Coalesced diagnostic summaries: occurrences the producer bounded into
|
|
2444
|
+
// `diagnostic-summaries/` instead of loose files. Counted into the logical
|
|
2445
|
+
// totals so mitigation can never make an active fault look healthy; the
|
|
2446
|
+
// physical loose file count stays visible separately.
|
|
2447
|
+
let summarizedTotal = 0;
|
|
2448
|
+
let summaryFiles = 0;
|
|
2449
|
+
let mitigationFailOpen = 0;
|
|
2450
|
+
try {
|
|
2451
|
+
const listing = listDiagnosticSummariesV3(root);
|
|
2452
|
+
summaryFiles = listing.file_count;
|
|
2453
|
+
mitigationFailOpen = listing.mitigation_health?.fail_open_count ?? 0;
|
|
2454
|
+
if (listing.unreadable_count > 0) {
|
|
2455
|
+
collectionErrors.push(`${listing.unreadable_count} diagnostic summary file(s) unreadable`);
|
|
2456
|
+
}
|
|
2457
|
+
const dayAgoMs = nowMs - 24 * 60 * 60 * 1000;
|
|
2458
|
+
const hourAgoMs = nowMs - 60 * 60 * 1000;
|
|
2459
|
+
for (const summary of listing.summaries) {
|
|
2460
|
+
summarizedTotal += summary.summarized_count;
|
|
2461
|
+
const entry = byCategory[summary.category] ?? { total: 0, last_24h: 0 };
|
|
2462
|
+
const recent = recentByCategory[summary.category] ?? { last_1h: 0, latest_at: null };
|
|
2463
|
+
byCategory[summary.category] = entry;
|
|
2464
|
+
recentByCategory[summary.category] = recent;
|
|
2465
|
+
entry.total += summary.summarized_count;
|
|
2466
|
+
const day = countSummarizedSinceV3([summary], dayAgoMs, undefined, nowMs);
|
|
2467
|
+
const hour = countSummarizedSinceV3([summary], hourAgoMs, undefined, nowMs);
|
|
2468
|
+
entry.last_24h += day;
|
|
2469
|
+
diagnostics24h += day;
|
|
2470
|
+
recent.last_1h += hour;
|
|
2471
|
+
diagnostics1h += hour;
|
|
2472
|
+
const lastMs = summary.last_summarized_at ? Date.parse(summary.last_summarized_at) : NaN;
|
|
2473
|
+
if (Number.isFinite(lastMs)) {
|
|
2474
|
+
latestDiagnosticMs = Math.max(latestDiagnosticMs, lastMs);
|
|
2475
|
+
if (!recent.latest_at || lastMs > Date.parse(recent.latest_at)) {
|
|
2476
|
+
recent.latest_at = new Date(lastMs).toISOString();
|
|
2477
|
+
}
|
|
2478
|
+
}
|
|
2479
|
+
}
|
|
2480
|
+
}
|
|
2481
|
+
catch (error) {
|
|
2482
|
+
collectionErrors.push(`diagnostic summaries unreadable: ${errorText(error)}`);
|
|
2483
|
+
}
|
|
2478
2484
|
return {
|
|
2479
2485
|
state: "live",
|
|
2480
2486
|
mode: control.state,
|
|
@@ -2485,7 +2491,10 @@ export function collectEventLedgerHealthV3(root, nowMs = Date.now()) {
|
|
|
2485
2491
|
pending_finalizations: pending,
|
|
2486
2492
|
intake_spool: { total: intakeTotal, groups: intakeGroups },
|
|
2487
2493
|
diagnostics_spool: {
|
|
2488
|
-
total: diagnosticsTotal,
|
|
2494
|
+
total: diagnosticsTotal + summarizedTotal,
|
|
2495
|
+
loose_total: diagnosticsTotal,
|
|
2496
|
+
summarized_total: summarizedTotal,
|
|
2497
|
+
summary_files: summaryFiles,
|
|
2489
2498
|
last_24h: diagnostics24h,
|
|
2490
2499
|
last_1h: diagnostics1h,
|
|
2491
2500
|
latest_at: Number.isFinite(latestDiagnosticMs)
|
|
@@ -2493,6 +2502,7 @@ export function collectEventLedgerHealthV3(root, nowMs = Date.now()) {
|
|
|
2493
2502
|
: null,
|
|
2494
2503
|
by_category: byCategory,
|
|
2495
2504
|
recent_by_category: recentByCategory,
|
|
2505
|
+
mitigation_fail_open: mitigationFailOpen,
|
|
2496
2506
|
},
|
|
2497
2507
|
span_pressure: spanPressure,
|
|
2498
2508
|
collection_errors: collectionErrors,
|
|
@@ -2943,13 +2953,13 @@ function runTrace(name, opts) {
|
|
|
2943
2953
|
/**
|
|
2944
2954
|
* V3 generations, not disposable heartbeat caches, are the active-agent authority.
|
|
2945
2955
|
*/
|
|
2946
|
-
export function collectActiveAgentHealth(root, nowMs = Date.now()) {
|
|
2956
|
+
export function collectActiveAgentHealth(root, nowMs = Date.now(), readRows = readLiveCoordinationRows, freshnessSeconds = freshnessCutoffSecs()) {
|
|
2947
2957
|
const source = "event-ledger-v3";
|
|
2948
2958
|
let heartbeats = [];
|
|
2949
2959
|
try {
|
|
2950
2960
|
const control = readEventV3ControlState(root);
|
|
2951
2961
|
if (control.state === "candidate" || control.state === "active") {
|
|
2952
|
-
heartbeats =
|
|
2962
|
+
heartbeats = readRows(root);
|
|
2953
2963
|
}
|
|
2954
2964
|
}
|
|
2955
2965
|
catch {
|
|
@@ -2975,7 +2985,7 @@ export function collectActiveAgentHealth(root, nowMs = Date.now()) {
|
|
|
2975
2985
|
const ageMs = Number.isFinite(lastObservedMs)
|
|
2976
2986
|
? nowMs - lastObservedMs
|
|
2977
2987
|
: Number.POSITIVE_INFINITY;
|
|
2978
|
-
if (ageMs >
|
|
2988
|
+
if (ageMs > freshnessSeconds * 1000)
|
|
2979
2989
|
stale += 1;
|
|
2980
2990
|
}
|
|
2981
2991
|
return {
|
|
@@ -2987,6 +2997,17 @@ export function collectActiveAgentHealth(root, nowMs = Date.now()) {
|
|
|
2987
2997
|
stale,
|
|
2988
2998
|
};
|
|
2989
2999
|
}
|
|
3000
|
+
/** Classify a parseable heartbeat cache file without conflating age with corruption. */
|
|
3001
|
+
export function classifyHeartbeatCacheIssue(heartbeat, nowMs, staleAgeMs) {
|
|
3002
|
+
if (!heartbeat.name || heartbeat.name === "unknown")
|
|
3003
|
+
return "no-name";
|
|
3004
|
+
const lastHeartbeatMs = heartbeat.last_heartbeat
|
|
3005
|
+
? Date.parse(heartbeat.last_heartbeat)
|
|
3006
|
+
: Number.NaN;
|
|
3007
|
+
if (!Number.isFinite(lastHeartbeatMs))
|
|
3008
|
+
return "invalid-heartbeat";
|
|
3009
|
+
return nowMs - lastHeartbeatMs > staleAgeMs ? "stale-age" : null;
|
|
3010
|
+
}
|
|
2990
3011
|
function runHealth(opts) {
|
|
2991
3012
|
if (opts.json)
|
|
2992
3013
|
emit.config({ format: "json" });
|
|
@@ -3067,12 +3088,12 @@ function runHealth(opts) {
|
|
|
3067
3088
|
.slice(0, 5)
|
|
3068
3089
|
.map(([agent, count]) => ({ agent, count }));
|
|
3069
3090
|
const activeAgents = collectActiveAgentHealth(root, nowMs);
|
|
3070
|
-
//
|
|
3071
|
-
//
|
|
3072
|
-
//
|
|
3091
|
+
// Heartbeat cache issues: files in active/ that are unparseable, nameless,
|
|
3092
|
+
// invalidly timestamped, or stale. Old parseable timestamps are ordinary
|
|
3093
|
+
// staleness, not evidence of epoch-like timestamp corruption.
|
|
3073
3094
|
let zombieCount = 0;
|
|
3074
3095
|
const zombieSamples = [];
|
|
3075
|
-
const
|
|
3096
|
+
const STALE_HEARTBEAT_AGE_MS = 24 * 60 * 60 * 1000;
|
|
3076
3097
|
if (existsSync(activeDir)) {
|
|
3077
3098
|
for (const file of readdirSync(activeDir)) {
|
|
3078
3099
|
if (!file.endsWith(".json"))
|
|
@@ -3091,15 +3112,11 @@ function runHealth(opts) {
|
|
|
3091
3112
|
zombieSamples.push(`${idFromFile.slice(0, 12)} (unparseable/no-id)`);
|
|
3092
3113
|
continue;
|
|
3093
3114
|
}
|
|
3094
|
-
const
|
|
3095
|
-
|
|
3096
|
-
// Zombie heuristics on a parseable heartbeat: no name, or an age so large
|
|
3097
|
-
// it can only be a broken/epoch timestamp (a real agent would have healed).
|
|
3098
|
-
if (!hb.name || hb.name === "unknown" || ageMs > ABSURD_AGE_MS) {
|
|
3115
|
+
const cacheIssue = classifyHeartbeatCacheIssue(hb, nowMs, STALE_HEARTBEAT_AGE_MS);
|
|
3116
|
+
if (cacheIssue) {
|
|
3099
3117
|
zombieCount++;
|
|
3100
3118
|
if (zombieSamples.length < 5) {
|
|
3101
|
-
|
|
3102
|
-
zombieSamples.push(`${idFromFile.slice(0, 12)} (${why})`);
|
|
3119
|
+
zombieSamples.push(`${idFromFile.slice(0, 12)} (${cacheIssue})`);
|
|
3103
3120
|
}
|
|
3104
3121
|
}
|
|
3105
3122
|
}
|
|
@@ -3149,7 +3166,7 @@ function runHealth(opts) {
|
|
|
3149
3166
|
anomalies.push(`${sweptByReason.unparseable} heartbeat(s) swept as unparseable in ${opts.since}; possible corruption or a non-atomic writer`);
|
|
3150
3167
|
}
|
|
3151
3168
|
if (zombieCount > 0) {
|
|
3152
|
-
anomalies.push(`${zombieCount}
|
|
3169
|
+
anomalies.push(`${zombieCount} heartbeat cache issue(s) in active/ (${zombieSamples.join(", ")}); stale or malformed files the sweep isn't reaping`);
|
|
3153
3170
|
}
|
|
3154
3171
|
if (stopRemediation.total > 0) {
|
|
3155
3172
|
const who = stopRemediation.sessions.length > 0
|
|
@@ -3278,7 +3295,7 @@ function renderHealthBox(report) {
|
|
|
3278
3295
|
`open spans ${ledger.open_spans.total}${orphanGenerations > 0 ? ` (${orphanGenerations} gen turn-closed)` : ""}`,
|
|
3279
3296
|
`pending ends ${ledger.pending_finalizations.length}${pendingAges ? ` (${pendingAges})` : ""}`,
|
|
3280
3297
|
`intake ${ledger.intake_spool.total}`,
|
|
3281
|
-
`diagnostics ${ledger.diagnostics_spool.total} (${ledger.diagnostics_spool.last_1h} in 1h / ${ledger.diagnostics_spool.last_24h} in 24h)`,
|
|
3298
|
+
`diagnostics ${ledger.diagnostics_spool.total}${ledger.diagnostics_spool.summarized_total > 0 ? ` (${ledger.diagnostics_spool.loose_total} loose + ${ledger.diagnostics_spool.summarized_total} summarized)` : ""} (${ledger.diagnostics_spool.last_1h} in 1h / ${ledger.diagnostics_spool.last_24h} in 24h)`,
|
|
3282
3299
|
].join(" · ");
|
|
3283
3300
|
}
|
|
3284
3301
|
const rows = [
|
|
@@ -3298,7 +3315,7 @@ function renderHealthBox(report) {
|
|
|
3298
3315
|
["stream", streamStr],
|
|
3299
3316
|
["event ledger", ledgerStr],
|
|
3300
3317
|
[
|
|
3301
|
-
"
|
|
3318
|
+
"cache issues",
|
|
3302
3319
|
report.zombies.count === 0
|
|
3303
3320
|
? "0"
|
|
3304
3321
|
: `${report.zombies.count} (${report.zombies.samples.join(", ")})`,
|
|
@@ -3682,10 +3699,13 @@ function runPing(name, message, opts) {
|
|
|
3682
3699
|
}
|
|
3683
3700
|
const myOwner = resolveOwner();
|
|
3684
3701
|
if (!myOwner) {
|
|
3685
|
-
|
|
3686
|
-
|
|
3687
|
-
|
|
3688
|
-
|
|
3702
|
+
const root = monorepoRoot();
|
|
3703
|
+
emit.error(root
|
|
3704
|
+
? sessionResolutionFailure(root, "not in an agent session; ppid walk found no pid-map entry")
|
|
3705
|
+
: {
|
|
3706
|
+
code: "no_pidmap_entry",
|
|
3707
|
+
message: "not in an agent session; ppid walk found no pid-map entry",
|
|
3708
|
+
});
|
|
3689
3709
|
process.exit(1);
|
|
3690
3710
|
}
|
|
3691
3711
|
const peerOwner = resolveOwnerByName(name);
|
|
@@ -3827,12 +3847,10 @@ function emitWaitResult(data, opts) {
|
|
|
3827
3847
|
function runHeal(opts) {
|
|
3828
3848
|
if (opts.json)
|
|
3829
3849
|
emit.config({ format: "json" });
|
|
3830
|
-
const
|
|
3831
|
-
const
|
|
3832
|
-
|
|
3833
|
-
|
|
3834
|
-
process.exit(1);
|
|
3835
|
-
}
|
|
3850
|
+
const requestedOwner = opts.owner?.trim() ?? "";
|
|
3851
|
+
const quarantineTransaction = opts.quarantineTransaction?.trim() ?? "";
|
|
3852
|
+
const approvalRecordId = opts.approvalRecordId?.trim() ?? "";
|
|
3853
|
+
const kind = opts.kind?.trim() || "cache";
|
|
3836
3854
|
if (kind !== "pidmap" && kind !== "cache") {
|
|
3837
3855
|
emit.error({
|
|
3838
3856
|
code: "bad_kind",
|
|
@@ -3840,6 +3858,30 @@ function runHeal(opts) {
|
|
|
3840
3858
|
});
|
|
3841
3859
|
process.exit(1);
|
|
3842
3860
|
}
|
|
3861
|
+
if (quarantineTransaction) {
|
|
3862
|
+
if (opts.kind || opts.pid) {
|
|
3863
|
+
emit.error({
|
|
3864
|
+
code: "conflicting_recovery_options",
|
|
3865
|
+
message: "--quarantine-transaction cannot be combined with --kind or --pid",
|
|
3866
|
+
});
|
|
3867
|
+
process.exit(1);
|
|
3868
|
+
}
|
|
3869
|
+
if (!opts.yes || !approvalRecordId) {
|
|
3870
|
+
emit.error({
|
|
3871
|
+
code: "transaction_quarantine_confirmation_required",
|
|
3872
|
+
message: "--quarantine-transaction requires --approval-record-id <id> and --yes; " +
|
|
3873
|
+
"the command abandons one uncommitted authority mutation while preserving its record",
|
|
3874
|
+
});
|
|
3875
|
+
process.exit(1);
|
|
3876
|
+
}
|
|
3877
|
+
}
|
|
3878
|
+
else if (approvalRecordId || opts.yes) {
|
|
3879
|
+
emit.error({
|
|
3880
|
+
code: "transaction_quarantine_target_required",
|
|
3881
|
+
message: "--approval-record-id and --yes require --quarantine-transaction <id>",
|
|
3882
|
+
});
|
|
3883
|
+
process.exit(1);
|
|
3884
|
+
}
|
|
3843
3885
|
if (opts.adapter &&
|
|
3844
3886
|
opts.adapter !== "claude-code" &&
|
|
3845
3887
|
opts.adapter !== "cursor" &&
|
|
@@ -3858,7 +3900,42 @@ function runHeal(opts) {
|
|
|
3858
3900
|
});
|
|
3859
3901
|
process.exit(1);
|
|
3860
3902
|
}
|
|
3861
|
-
const
|
|
3903
|
+
const currentSessionRepair = kind === "cache" &&
|
|
3904
|
+
opts.owner === undefined &&
|
|
3905
|
+
opts.sessionId === undefined &&
|
|
3906
|
+
opts.adapter === undefined &&
|
|
3907
|
+
!quarantineTransaction;
|
|
3908
|
+
const ownerResolution = resolveOwnerWithSource();
|
|
3909
|
+
const bootstrapIdentity = currentSessionRepair ? commandSessionBootstrap() : null;
|
|
3910
|
+
const resolvedCurrentOwner = bootstrapIdentity &&
|
|
3911
|
+
(ownerResolution.source === "none" || ownerResolution.source === "active_singleton")
|
|
3912
|
+
? bootstrapIdentity.sessionId
|
|
3913
|
+
: ownerResolution.owner;
|
|
3914
|
+
const owner = requestedOwner || resolvedCurrentOwner || sessionIdentityFromEnv() || "";
|
|
3915
|
+
if (!owner) {
|
|
3916
|
+
emit.error({
|
|
3917
|
+
code: "session_identity_missing",
|
|
3918
|
+
message: `could not resolve the current session; run ${resolveBinName()} doctor, or pass ` +
|
|
3919
|
+
"--owner <instance-id> --session-id <native-session-id> --adapter <adapter>",
|
|
3920
|
+
});
|
|
3921
|
+
process.exit(1);
|
|
3922
|
+
}
|
|
3923
|
+
const currentRow = readLiveCoordinationRow(root, owner);
|
|
3924
|
+
const inferredAdapter = normalizeAdapter(opts.adapter?.trim() || currentRow?.platform || commandSessionBootstrap()?.adapter);
|
|
3925
|
+
const sessionId = opts.sessionId?.trim() ||
|
|
3926
|
+
(currentSessionRepair ? sessionIdentityFromEnv() : null) ||
|
|
3927
|
+
nativeSessionIdentity(currentRow, owner);
|
|
3928
|
+
if (kind === "cache") {
|
|
3929
|
+
const refusal = cacheHealAuthorityRefusal(root, owner, sessionId, inferredAdapter, currentRow);
|
|
3930
|
+
if (refusal) {
|
|
3931
|
+
emitHealFailure(refusal.reason, refusal.message);
|
|
3932
|
+
}
|
|
3933
|
+
}
|
|
3934
|
+
const action = quarantineTransaction
|
|
3935
|
+
? "quarantine-authority-transaction"
|
|
3936
|
+
: kind === "pidmap"
|
|
3937
|
+
? "heal-pidmap"
|
|
3938
|
+
: "repair-coordination-cache";
|
|
3862
3939
|
// Refuse to materialize a V3 cache at a truncated owner id.
|
|
3863
3940
|
//
|
|
3864
3941
|
// Heartbeats are keyed by the whole instance_id, so healing at an
|
|
@@ -3897,24 +3974,54 @@ function runHeal(opts) {
|
|
|
3897
3974
|
// heal-pidmap <instance_id> [<pid>]
|
|
3898
3975
|
// repair-coordination-cache <instance_id> [<session_id>]
|
|
3899
3976
|
const helperArgs = [action, owner];
|
|
3900
|
-
if (
|
|
3901
|
-
helperArgs.push(
|
|
3902
|
-
|
|
3903
|
-
|
|
3904
|
-
|
|
3905
|
-
|
|
3977
|
+
if (quarantineTransaction) {
|
|
3978
|
+
helperArgs.push(quarantineTransaction, approvalRecordId, sessionId, `--adapter=${inferredAdapter}`);
|
|
3979
|
+
}
|
|
3980
|
+
else {
|
|
3981
|
+
if (kind === "pidmap" && opts.pid)
|
|
3982
|
+
helperArgs.push(opts.pid);
|
|
3983
|
+
if (kind === "cache")
|
|
3984
|
+
helperArgs.push(sessionId, `--adapter=${inferredAdapter}`);
|
|
3985
|
+
}
|
|
3906
3986
|
// Both recovery actions are handled by the bundled agent-coord binary.
|
|
3907
3987
|
const helper = agentCoordOrExit(root);
|
|
3908
|
-
|
|
3988
|
+
let proc = spawnSync(helper, helperArgs, {
|
|
3909
3989
|
encoding: "utf8",
|
|
3910
3990
|
...coordHelperOpts(root),
|
|
3911
3991
|
});
|
|
3912
|
-
|
|
3913
|
-
|
|
3914
|
-
|
|
3915
|
-
|
|
3992
|
+
let bootstrapState;
|
|
3993
|
+
if (proc.status !== 0 &&
|
|
3994
|
+
currentSessionRepair &&
|
|
3995
|
+
missingAuthorityForCurrentSessionBootstrap(root, owner, sessionId)) {
|
|
3996
|
+
const bootstrap = commandSessionBootstrap();
|
|
3997
|
+
if (!bootstrap ||
|
|
3998
|
+
bootstrap.sessionId !== sessionId ||
|
|
3999
|
+
bootstrap.sessionId !== owner ||
|
|
4000
|
+
bootstrap.adapter !== inferredAdapter) {
|
|
4001
|
+
emitHealFailure("native_identity_unverified", "the current adapter did not provide one matching native session id and adapter");
|
|
4002
|
+
}
|
|
4003
|
+
try {
|
|
4004
|
+
const bootstrapped = bootstrapLiveCoordinationAuthorityV3({
|
|
4005
|
+
coordRoot: root,
|
|
4006
|
+
owner,
|
|
4007
|
+
nativeSessionId: bootstrap.sessionId,
|
|
4008
|
+
adapter: bootstrap.adapter,
|
|
4009
|
+
});
|
|
4010
|
+
bootstrapState = bootstrapped.state;
|
|
4011
|
+
}
|
|
4012
|
+
catch (error) {
|
|
4013
|
+
const reason = error instanceof LiveCoordinationAuthorityV3Error
|
|
4014
|
+
? error.reason
|
|
4015
|
+
: "authority_bootstrap_failed";
|
|
4016
|
+
emitHealFailure(reason, "the current native session could not establish authority; no fallback cache was accepted");
|
|
4017
|
+
}
|
|
4018
|
+
proc = spawnSync(helper, helperArgs, {
|
|
4019
|
+
encoding: "utf8",
|
|
4020
|
+
...coordHelperOpts(root),
|
|
3916
4021
|
});
|
|
3917
|
-
|
|
4022
|
+
}
|
|
4023
|
+
if (proc.status !== 0) {
|
|
4024
|
+
emitHealFailure(healFailureReason(root, owner, sessionId, inferredAdapter), spawnFailureMessage(proc, `agent-coord ${action}`));
|
|
3918
4025
|
}
|
|
3919
4026
|
// Read the derived cache to surface post-action state.
|
|
3920
4027
|
let after = null;
|
|
@@ -3924,13 +4031,15 @@ function runHeal(opts) {
|
|
|
3924
4031
|
catch {
|
|
3925
4032
|
after = null;
|
|
3926
4033
|
}
|
|
3927
|
-
const outcome =
|
|
3928
|
-
?
|
|
3929
|
-
|
|
3930
|
-
|
|
3931
|
-
|
|
3932
|
-
|
|
3933
|
-
:
|
|
4034
|
+
const outcome = quarantineTransaction
|
|
4035
|
+
? "transaction_quarantined"
|
|
4036
|
+
: kind === "pidmap"
|
|
4037
|
+
? proc.status === 0
|
|
4038
|
+
? "ok"
|
|
4039
|
+
: "failed"
|
|
4040
|
+
: after
|
|
4041
|
+
? "cache_present"
|
|
4042
|
+
: "cache_absent";
|
|
3934
4043
|
emit.data({
|
|
3935
4044
|
rows: [
|
|
3936
4045
|
{
|
|
@@ -3938,10 +4047,15 @@ function runHeal(opts) {
|
|
|
3938
4047
|
action,
|
|
3939
4048
|
outcome,
|
|
3940
4049
|
after,
|
|
4050
|
+
...(quarantineTransaction ? { recovery: JSON.parse(proc.stdout.trim()) } : {}),
|
|
3941
4051
|
},
|
|
3942
4052
|
],
|
|
3943
4053
|
meta: {
|
|
3944
4054
|
kind,
|
|
4055
|
+
automatic: currentSessionRepair && !quarantineTransaction,
|
|
4056
|
+
authority: "event-ledger-v3",
|
|
4057
|
+
adapter: kind === "cache" ? inferredAdapter : undefined,
|
|
4058
|
+
bootstrap: bootstrapState,
|
|
3945
4059
|
// The path actually spawned, not a guess at the layout: the helper is
|
|
3946
4060
|
// resolved from harnery's own package location, which differs between a
|
|
3947
4061
|
// submodule, an installed dependency, and a standalone checkout.
|
|
@@ -3949,11 +4063,16 @@ function runHeal(opts) {
|
|
|
3949
4063
|
},
|
|
3950
4064
|
});
|
|
3951
4065
|
if (!opts.json) {
|
|
3952
|
-
if (
|
|
4066
|
+
if (quarantineTransaction) {
|
|
4067
|
+
emit.text(`coordination recovered: ${quarantineTransaction} quarantined with approval ${approvalRecordId}; ` +
|
|
4068
|
+
`cache ${after ? "present" : "absent"} (${inferredAdapter})\n`);
|
|
4069
|
+
}
|
|
4070
|
+
else if (kind === "pidmap") {
|
|
3953
4071
|
emit.text(`agent-coord ${action} ok\n`);
|
|
3954
4072
|
}
|
|
3955
4073
|
else {
|
|
3956
|
-
emit.text(`
|
|
4074
|
+
emit.text(`coordination repaired: V3 authority live; ${currentSessionRepair ? "current-session " : ""}` +
|
|
4075
|
+
`cache ${after ? "present" : "absent"} (${inferredAdapter})\n`);
|
|
3957
4076
|
}
|
|
3958
4077
|
}
|
|
3959
4078
|
// Canonical health.* emission is owned by the cache writer, so it fires
|
|
@@ -3962,6 +4081,68 @@ function runHeal(opts) {
|
|
|
3962
4081
|
// event when an already-correct heal no-ops. (Previously emitted here
|
|
3963
4082
|
// unconditionally on every `harn agents heal`, which over-counted no-op heals.)
|
|
3964
4083
|
}
|
|
4084
|
+
function cacheHealAuthorityRefusal(root, owner, sessionId, adapter, currentRow) {
|
|
4085
|
+
if (currentRow && normalizeAdapter(currentRow.platform) !== adapter) {
|
|
4086
|
+
return {
|
|
4087
|
+
reason: "adapter_mismatch",
|
|
4088
|
+
message: `the live generation belongs to adapter ${normalizeAdapter(currentRow.platform)}, not ${adapter}`,
|
|
4089
|
+
};
|
|
4090
|
+
}
|
|
4091
|
+
let producer;
|
|
4092
|
+
try {
|
|
4093
|
+
producer = readHookProducerStateV3(root, adapter, sessionId);
|
|
4094
|
+
}
|
|
4095
|
+
catch {
|
|
4096
|
+
return {
|
|
4097
|
+
reason: "session_mismatch",
|
|
4098
|
+
message: "the native session producer state could not be read safely",
|
|
4099
|
+
};
|
|
4100
|
+
}
|
|
4101
|
+
if (producer?.terminal) {
|
|
4102
|
+
return {
|
|
4103
|
+
reason: "terminal_generation",
|
|
4104
|
+
message: "the matching generation is terminal and cannot be repaired or reopened by heal",
|
|
4105
|
+
};
|
|
4106
|
+
}
|
|
4107
|
+
if (producer && producer.instance_id !== liveInstanceIdV3(owner)) {
|
|
4108
|
+
return {
|
|
4109
|
+
reason: "owner_mismatch",
|
|
4110
|
+
message: "the native session is bound to a different instance owner",
|
|
4111
|
+
};
|
|
4112
|
+
}
|
|
4113
|
+
if (currentRow && (!producer || producer.generation_id !== currentRow.v3_generation_id)) {
|
|
4114
|
+
return {
|
|
4115
|
+
reason: "session_mismatch",
|
|
4116
|
+
message: "the native session does not bind to the requested live generation",
|
|
4117
|
+
};
|
|
4118
|
+
}
|
|
4119
|
+
return null;
|
|
4120
|
+
}
|
|
4121
|
+
function missingAuthorityForCurrentSessionBootstrap(root, owner, sessionId) {
|
|
4122
|
+
if (readLiveCoordinationRow(root, owner))
|
|
4123
|
+
return false;
|
|
4124
|
+
try {
|
|
4125
|
+
const nativeSessionHasProducer = ["claude-code", "codex", "cursor"].some((adapter) => readHookProducerStateV3(root, adapter, sessionId) !== undefined);
|
|
4126
|
+
if (nativeSessionHasProducer)
|
|
4127
|
+
return false;
|
|
4128
|
+
const instanceId = liveInstanceIdV3(owner);
|
|
4129
|
+
return !listHookProducerStateRecordsV3(root, { includeTerminal: true }).some(({ state }) => state.instance_id === instanceId);
|
|
4130
|
+
}
|
|
4131
|
+
catch {
|
|
4132
|
+
return false;
|
|
4133
|
+
}
|
|
4134
|
+
}
|
|
4135
|
+
function healFailureReason(root, owner, sessionId, adapter) {
|
|
4136
|
+
const refusal = cacheHealAuthorityRefusal(root, owner, sessionId, adapter, readLiveCoordinationRow(root, owner));
|
|
4137
|
+
return refusal?.reason ?? "authority_missing";
|
|
4138
|
+
}
|
|
4139
|
+
function emitHealFailure(reason, message) {
|
|
4140
|
+
emit.error({
|
|
4141
|
+
code: "heal_failed",
|
|
4142
|
+
message: `coordination heal refused (reason=${reason}): ${message}`,
|
|
4143
|
+
});
|
|
4144
|
+
process.exit(1);
|
|
4145
|
+
}
|
|
3965
4146
|
/**
|
|
3966
4147
|
* Emit one V3 council audit transition keyed to the exact durable manifest.
|
|
3967
4148
|
* Falls through silently when no live session can attest the observation.
|