harnery 0.33.0 → 0.34.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.map +1 -1
- package/dist/commander.js +4 -0
- package/dist/commands/adapter.js +2 -2
- package/dist/commands/agents.d.ts +144 -1
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +1220 -588
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +7 -6
- package/dist/commands/backup.d.ts +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +29 -16
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +234 -12
- package/dist/commands/checkpoint.d.ts.map +1 -1
- package/dist/commands/checkpoint.js +3 -2
- package/dist/commands/claude-desktop.d.ts +1 -1
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +3 -74
- package/dist/commands/context.js +1 -6
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +22 -38
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +91 -28
- package/dist/commands/doctor.js +10 -1
- package/dist/commands/events.d.ts +5 -0
- package/dist/commands/events.d.ts.map +1 -0
- package/dist/commands/events.js +189 -0
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +13 -4
- package/dist/commands/init.d.ts +9 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +223 -51
- package/dist/commands/journal.d.ts.map +1 -1
- package/dist/commands/journal.js +4 -13
- package/dist/commands/ledger-v3.d.ts +5 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -0
- package/dist/commands/ledger-v3.js +91 -0
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +11 -5
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.js +1 -1
- package/dist/commands/web.d.ts +6 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +67 -7
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +22 -5
- package/dist/core/adapter.d.ts +5 -0
- package/dist/core/adapter.d.ts.map +1 -0
- package/dist/core/adapter.js +1 -0
- package/dist/core/adapters/attest.d.ts +5 -2
- package/dist/core/adapters/attest.d.ts.map +1 -1
- package/dist/core/adapters/attest.js +8 -3
- package/dist/core/adapters/profiles.d.ts +6 -6
- package/dist/core/adapters/profiles.d.ts.map +1 -1
- package/dist/core/adapters/profiles.js +4 -4
- package/dist/core/agents/canonical-emit.d.ts +17 -15
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +22 -22
- package/dist/core/agents/cli.js +207 -234
- package/dist/core/agents/codex-archive-v3.d.ts +14 -0
- package/dist/core/agents/codex-archive-v3.d.ts.map +1 -0
- package/dist/core/agents/codex-archive-v3.js +110 -0
- package/dist/core/agents/coord-client.d.ts +19 -81
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +65 -155
- package/dist/core/agents/finalization.d.ts +4 -1
- package/dist/core/agents/finalization.d.ts.map +1 -1
- package/dist/core/agents/finalization.js +89 -32
- package/dist/core/agents/index.d.ts +4 -5
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +4 -5
- package/dist/core/agents/live-authority-v3.d.ts +59 -0
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -0
- package/dist/core/agents/live-authority-v3.js +233 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts +20 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -0
- package/dist/core/agents/live-lifecycle-v3.js +91 -0
- package/dist/core/agents/live-observation-v3.d.ts +25 -0
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -0
- package/dist/core/agents/live-observation-v3.js +157 -0
- package/dist/core/agents/render/prompt-context.d.ts +4 -4
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +23 -58
- package/dist/core/agents/render/session-context.d.ts +1 -1
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +8 -32
- package/dist/core/agents/rules/claim-conflict.d.ts +3 -3
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +79 -127
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +3 -18
- package/dist/core/agents/rules/stop-hook.d.ts +9 -50
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +193 -236
- package/dist/core/agents/session-events.d.ts +5 -7
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +127 -95
- package/dist/core/agents/session-finalization-state-v3.d.ts +30 -0
- package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -0
- package/dist/core/agents/session-finalization-state-v3.js +40 -0
- package/dist/core/agents/session-finalizer-v3.d.ts +107 -0
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -0
- package/dist/core/agents/session-finalizer-v3.js +734 -0
- package/dist/core/agents/session-name-display.d.ts +40 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -0
- package/dist/core/agents/session-name-display.js +119 -0
- package/dist/core/agents/state/activity-log.d.ts +3 -3
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +7 -16
- package/dist/core/agents/state/heartbeat-writer.d.ts +23 -55
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +56 -228
- package/dist/core/agents/state/live-coordination-view.d.ts +31 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-view.js +209 -0
- package/dist/core/agents/state/session-state.d.ts +4 -3
- package/dist/core/agents/state/session-state.d.ts.map +1 -1
- package/dist/core/agents/state/session-state.js +18 -9
- package/dist/core/agents/state/stale-sweep.d.ts +1 -1
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +26 -15
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +5 -7
- package/dist/core/config.d.ts +33 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -2
- package/dist/core/context/index.d.ts +1 -4
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +9 -9
- package/dist/core/events/span-parent.d.ts +15 -0
- package/dist/core/events/span-parent.d.ts.map +1 -0
- package/dist/core/events/span-parent.js +34 -0
- package/dist/core/events/v3/advance.d.ts +14 -0
- package/dist/core/events/v3/advance.d.ts.map +1 -0
- package/dist/core/events/v3/advance.js +134 -0
- package/dist/core/events/v3/authority-outbox.d.ts +78 -0
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -0
- package/dist/core/events/v3/authority-outbox.js +399 -0
- package/dist/core/events/v3/base-builder.d.ts +20 -0
- package/dist/core/events/v3/base-builder.d.ts.map +1 -0
- package/dist/core/events/v3/base-builder.js +29 -0
- package/dist/core/events/v3/base-contract.d.ts +7576 -0
- package/dist/core/events/v3/base-contract.d.ts.map +1 -0
- package/dist/core/events/v3/base-contract.js +647 -0
- package/dist/core/events/v3/bootstrap.d.ts +34 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -0
- package/dist/core/events/v3/bootstrap.js +175 -0
- package/dist/core/events/v3/builder.d.ts +20 -0
- package/dist/core/events/v3/builder.d.ts.map +1 -0
- package/dist/core/events/v3/builder.js +28 -0
- package/dist/core/events/v3/canonical.d.ts +31 -0
- package/dist/core/events/v3/canonical.d.ts.map +1 -0
- package/dist/core/events/v3/canonical.js +100 -0
- package/dist/core/events/v3/capabilities.d.ts +31 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/capabilities.js +107 -0
- package/dist/core/events/v3/capability-drift.d.ts +22 -0
- package/dist/core/events/v3/capability-drift.d.ts.map +1 -0
- package/dist/core/events/v3/capability-drift.js +134 -0
- package/dist/core/events/v3/catalog.d.ts +38 -0
- package/dist/core/events/v3/catalog.d.ts.map +1 -0
- package/dist/core/events/v3/catalog.js +135 -0
- package/dist/core/events/v3/clock-order.d.ts +34 -0
- package/dist/core/events/v3/clock-order.d.ts.map +1 -0
- package/dist/core/events/v3/clock-order.js +35 -0
- package/dist/core/events/v3/contract.d.ts +171 -0
- package/dist/core/events/v3/contract.d.ts.map +1 -0
- package/dist/core/events/v3/contract.js +180 -0
- package/dist/core/events/v3/control.d.ts +111 -0
- package/dist/core/events/v3/control.d.ts.map +1 -0
- package/dist/core/events/v3/control.js +419 -0
- package/dist/core/events/v3/coordination-view.d.ts +69 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-view.js +119 -0
- package/dist/core/events/v3/economics.d.ts +77 -0
- package/dist/core/events/v3/economics.d.ts.map +1 -0
- package/dist/core/events/v3/economics.js +274 -0
- package/dist/core/events/v3/finalization-view.d.ts +26 -0
- package/dist/core/events/v3/finalization-view.d.ts.map +1 -0
- package/dist/core/events/v3/finalization-view.js +37 -0
- package/dist/core/events/v3/fingerprint-keys.d.ts +25 -0
- package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -0
- package/dist/core/events/v3/fingerprint-keys.js +217 -0
- package/dist/core/events/v3/generated.d.ts +4 -0
- package/dist/core/events/v3/generated.d.ts.map +1 -0
- package/dist/core/events/v3/generated.js +47 -0
- package/dist/core/events/v3/ids.d.ts +9 -0
- package/dist/core/events/v3/ids.d.ts.map +1 -0
- package/dist/core/events/v3/ids.js +25 -0
- package/dist/core/events/v3/index.d.ts +35 -0
- package/dist/core/events/v3/index.d.ts.map +1 -0
- package/dist/core/events/v3/index.js +33 -0
- package/dist/core/events/v3/latency.d.ts +63 -0
- package/dist/core/events/v3/latency.d.ts.map +1 -0
- package/dist/core/events/v3/latency.js +412 -0
- package/dist/core/events/v3/live-feed.d.ts +45 -0
- package/dist/core/events/v3/live-feed.d.ts.map +1 -0
- package/dist/core/events/v3/live-feed.js +246 -0
- package/dist/core/events/v3/live-observation.d.ts +35 -0
- package/dist/core/events/v3/live-observation.d.ts.map +1 -0
- package/dist/core/events/v3/live-observation.js +1 -0
- package/dist/core/events/v3/live-routing.d.ts +57 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -0
- package/dist/core/events/v3/live-routing.js +107 -0
- package/dist/core/events/v3/producers/command-recorder.d.ts +67 -0
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/command-recorder.js +477 -0
- package/dist/core/events/v3/producers/command.d.ts +50 -0
- package/dist/core/events/v3/producers/command.d.ts.map +1 -0
- package/dist/core/events/v3/producers/command.js +135 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +53 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/coordination-recorder.js +376 -0
- package/dist/core/events/v3/producers/coordination.d.ts +90 -0
- package/dist/core/events/v3/producers/coordination.d.ts.map +1 -0
- package/dist/core/events/v3/producers/coordination.js +229 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +54 -0
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -0
- package/dist/core/events/v3/producers/hook-base.js +424 -0
- package/dist/core/events/v3/producers/hook.d.ts +29 -0
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -0
- package/dist/core/events/v3/producers/hook.js +71 -0
- package/dist/core/events/v3/producers/intake.d.ts +65 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -0
- package/dist/core/events/v3/producers/intake.js +244 -0
- package/dist/core/events/v3/producers/recorder.d.ts +240 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/recorder.js +2176 -0
- package/dist/core/events/v3/projection.d.ts +101 -0
- package/dist/core/events/v3/projection.d.ts.map +1 -0
- package/dist/core/events/v3/projection.js +479 -0
- package/dist/core/events/v3/reader.d.ts +75 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -0
- package/dist/core/events/v3/reader.js +778 -0
- package/dist/core/events/v3/recovery-record.d.ts +47 -0
- package/dist/core/events/v3/recovery-record.d.ts.map +1 -0
- package/dist/core/events/v3/recovery-record.js +167 -0
- package/dist/core/events/v3/recovery.d.ts +22 -0
- package/dist/core/events/v3/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/recovery.js +227 -0
- package/dist/core/events/v3/span-state.d.ts +52 -0
- package/dist/core/events/v3/span-state.d.ts.map +1 -0
- package/dist/core/events/v3/span-state.js +142 -0
- package/dist/core/events/v3/targets.d.ts +23 -0
- package/dist/core/events/v3/targets.d.ts.map +1 -0
- package/dist/core/events/v3/targets.js +134 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +41 -0
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -0
- package/dist/core/events/v3/turn-telemetry.js +168 -0
- package/dist/core/events/v3/validate.d.ts +9 -0
- package/dist/core/events/v3/validate.d.ts.map +1 -0
- package/dist/core/events/v3/validate.js +281 -0
- package/dist/core/events/v3/writer.d.ts +56 -0
- package/dist/core/events/v3/writer.d.ts.map +1 -0
- package/dist/core/events/v3/writer.js +335 -0
- package/dist/core/governor/index.d.ts +1 -1
- package/dist/core/governor/index.d.ts.map +1 -1
- package/dist/core/governor/index.js +1 -1
- package/dist/core/governor/plan-api.d.ts +2 -1
- package/dist/core/governor/plan-api.d.ts.map +1 -1
- package/dist/core/governor/plan-api.js +6 -3
- package/dist/core/governor/read.d.ts +1 -1
- package/dist/core/governor/read.d.ts.map +1 -1
- package/dist/core/governor/read.js +1 -1
- package/dist/core/governor/state.d.ts +9 -0
- package/dist/core/governor/state.d.ts.map +1 -1
- package/dist/core/governor/state.js +40 -3
- package/dist/core/guard/config.d.ts +5 -0
- package/dist/core/guard/config.d.ts.map +1 -0
- package/dist/core/guard/config.js +157 -0
- package/dist/core/guard/coordinator.d.ts +14 -0
- package/dist/core/guard/coordinator.d.ts.map +1 -0
- package/dist/core/guard/coordinator.js +173 -0
- package/dist/core/guard/evaluator.d.ts +4 -0
- package/dist/core/guard/evaluator.d.ts.map +1 -0
- package/dist/core/guard/evaluator.js +242 -0
- package/dist/core/guard/evidence-v3.d.ts +15 -0
- package/dist/core/guard/evidence-v3.d.ts.map +1 -0
- package/dist/core/guard/evidence-v3.js +171 -0
- package/dist/core/guard/index.d.ts +10 -0
- package/dist/core/guard/index.d.ts.map +1 -0
- package/dist/core/guard/index.js +6 -0
- package/dist/core/guard/live-source-v3.d.ts +40 -0
- package/dist/core/guard/live-source-v3.d.ts.map +1 -0
- package/dist/core/guard/live-source-v3.js +128 -0
- package/dist/core/guard/storage.d.ts +27 -0
- package/dist/core/guard/storage.d.ts.map +1 -0
- package/dist/core/guard/storage.js +140 -0
- package/dist/core/guard/types.d.ts +119 -0
- package/dist/core/guard/types.d.ts.map +1 -0
- package/dist/core/guard/types.js +1 -0
- package/dist/core/hooks/adapter/detect.d.ts +18 -1
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +29 -0
- package/dist/core/hooks/adapter/events.d.ts +7 -4
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +12 -4
- package/dist/core/hooks/adapter/output.d.ts +2 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.d.ts +7 -4
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +63 -25
- package/dist/core/hooks/adapter/wiring.d.ts +30 -4
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +89 -11
- package/dist/core/hooks/cli.d.ts +1 -1
- package/dist/core/hooks/cli.js +305 -444
- package/dist/core/hooks/effects/image-capture.d.ts +20 -34
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +212 -221
- package/dist/core/hooks/effects/index.d.ts +1 -9
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +1 -24
- package/dist/core/hooks/events/input-hash.d.ts +7 -0
- package/dist/core/hooks/events/input-hash.d.ts.map +1 -0
- package/dist/core/hooks/events/input-hash.js +43 -0
- package/dist/core/hooks/index.d.ts +4 -3
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +2 -3
- package/dist/core/hooks/resolve/coord-root.d.ts +1 -1
- package/dist/core/hooks/resolve/coord-root.js +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +16 -15
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +51 -42
- package/dist/core/hooks/resolve/transcript.d.ts +33 -3
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +155 -14
- package/dist/core/hooks/session-name-presence.d.ts +9 -10
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +15 -15
- package/dist/core/hooks/unsafe-cross-shell.d.ts +1 -1
- package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -1
- package/dist/core/journal/index.d.ts +2 -2
- package/dist/core/journal/index.d.ts.map +1 -1
- package/dist/core/journal/index.js +9 -22
- package/dist/core/presence/blob.d.ts +4 -3
- package/dist/core/presence/blob.d.ts.map +1 -1
- package/dist/core/presence/blob.js +45 -44
- package/dist/core/presence/codec-digest.d.ts +29 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -0
- package/dist/core/presence/codec-digest.js +170 -0
- package/dist/core/presence/relay-client.d.ts +1 -1
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +5 -5
- package/dist/core/work/index.d.ts +1 -1
- package/dist/core/work/index.d.ts.map +1 -1
- package/dist/core/work/index.js +1 -1
- package/dist/core/work/read.d.ts +1 -1
- package/dist/core/work/read.d.ts.map +1 -1
- package/dist/core/work/read.js +1 -1
- package/dist/core/work/runner.d.ts.map +1 -1
- package/dist/core/work/runner.js +6 -0
- package/dist/core/work/state.d.ts +9 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +17 -3
- package/dist/core/workflow/engine.js +24 -25
- package/dist/core/workflow/live-session-v3.d.ts +19 -0
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -0
- package/dist/core/workflow/live-session-v3.js +86 -0
- package/dist/core/workflow/scope-id.d.ts +3 -0
- package/dist/core/workflow/scope-id.d.ts.map +1 -0
- package/dist/core/workflow/scope-id.js +5 -0
- package/dist/core/workflow/workspaces/leases.d.ts +4 -0
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +53 -19
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/browser/client.d.ts +41 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +203 -0
- package/dist/lib/browser/critique.d.ts +28 -2
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +74 -18
- package/dist/lib/browser/geometry.d.ts +1 -1
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +130 -6
- package/dist/lib/browser/index.d.ts +3 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +3 -0
- package/dist/lib/browser/qa-plan.d.ts +174 -0
- package/dist/lib/browser/qa-plan.d.ts.map +1 -0
- package/dist/lib/browser/qa-plan.js +321 -0
- package/dist/lib/browser/qa-reuse.d.ts +99 -0
- package/dist/lib/browser/qa-reuse.d.ts.map +1 -0
- package/dist/lib/browser/qa-reuse.js +222 -0
- package/dist/lib/browser/qa-snapshot.d.ts +64 -0
- package/dist/lib/browser/qa-snapshot.d.ts.map +1 -0
- package/dist/lib/browser/qa-snapshot.js +171 -0
- package/dist/lib/browser/runts.d.ts.map +1 -1
- package/dist/lib/browser/runts.js +22 -1
- package/dist/lib/browser/tiling.d.ts +71 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -0
- package/dist/lib/browser/tiling.js +118 -0
- package/dist/lib/claude-desktop.d.ts +0 -47
- package/dist/lib/claude-desktop.d.ts.map +1 -1
- package/dist/lib/claude-desktop.js +1 -169
- package/dist/lib/context/index.d.ts +0 -3
- package/dist/lib/context/index.d.ts.map +1 -1
- package/dist/lib/context/index.js +20 -42
- package/dist/lib/council/index.d.ts +2 -2
- package/dist/lib/council/index.d.ts.map +1 -1
- package/dist/lib/council/index.js +9 -20
- package/dist/lib/docs-frontmatter.d.ts +1 -6
- package/dist/lib/docs-frontmatter.d.ts.map +1 -1
- package/dist/lib/docs-frontmatter.js +12 -78
- package/dist/lib/docs-index.d.ts +9 -0
- package/dist/lib/docs-index.d.ts.map +1 -1
- package/dist/lib/docs-index.js +32 -3
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +14 -30
- package/dist/lib/docs-metadata-audit.d.ts +19 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -0
- package/dist/lib/docs-metadata-audit.js +132 -0
- package/dist/lib/docs-metadata-managed.d.ts +23 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -0
- package/dist/lib/docs-metadata-managed.js +78 -0
- package/dist/lib/docs-metadata-sync.d.ts +20 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -0
- package/dist/lib/docs-metadata-sync.js +222 -0
- package/dist/lib/docs-metadata-v2-schema.d.ts +273 -0
- package/dist/lib/docs-metadata-v2-schema.d.ts.map +1 -0
- package/dist/lib/docs-metadata-v2-schema.js +134 -0
- package/dist/lib/docs-metadata-v2.d.ts +21 -0
- package/dist/lib/docs-metadata-v2.d.ts.map +1 -0
- package/dist/lib/docs-metadata-v2.js +424 -0
- package/dist/lib/docs-new.d.ts +11 -0
- package/dist/lib/docs-new.d.ts.map +1 -0
- package/dist/lib/docs-new.js +52 -0
- package/dist/lib/docs-sweep.d.ts.map +1 -1
- package/dist/lib/docs-sweep.js +45 -29
- package/dist/lib/headless/index.d.ts +98 -0
- package/dist/lib/headless/index.d.ts.map +1 -0
- package/dist/lib/headless/index.js +211 -0
- package/dist/lib/identities/assume.d.ts +4 -4
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +52 -68
- package/dist/lib/instructions/apply.d.ts +5 -4
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +32 -20
- package/dist/lib/instructions/bundle.d.ts +1 -1
- package/dist/lib/instructions/bundle.d.ts.map +1 -1
- package/dist/lib/instructions/bundle.js +1 -1
- package/dist/lib/instructions/splice.d.ts +0 -1
- package/dist/lib/instructions/splice.d.ts.map +1 -1
- package/dist/lib/instructions/splice.js +22 -6
- package/dist/lib/instructions/templates.d.ts +7 -5
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +79 -9
- package/package.json +26 -5
- package/schemas/config.schema.json +120 -2
- package/schemas/docs-metadata-v2.schema.json +441 -0
- package/schemas/event-v3.schema.json +24472 -0
- package/src/commander.ts +4 -0
- package/src/commands/adapter.ts +2 -2
- package/src/commands/agents.ts +1512 -592
- package/src/commands/artifacts.ts +7 -6
- package/src/commands/backup.ts +29 -21
- package/src/commands/browse.ts +349 -8
- package/src/commands/checkpoint.ts +4 -3
- package/src/commands/claude-desktop.ts +2 -101
- package/src/commands/context.ts +1 -6
- package/src/commands/decision.ts +27 -44
- package/src/commands/docs.ts +100 -33
- package/src/commands/doctor.ts +14 -1
- package/src/commands/events.ts +256 -0
- package/src/commands/governor.ts +18 -4
- package/src/commands/init.ts +253 -57
- package/src/commands/instructions.ts +1 -1
- package/src/commands/journal.ts +4 -13
- package/src/commands/ledger-v3.ts +111 -0
- package/src/commands/presence.ts +11 -10
- package/src/commands/sync.ts +1 -1
- package/src/commands/web.ts +67 -8
- package/src/commands/work.ts +28 -5
- package/src/core/adapter.ts +5 -0
- package/src/core/adapters/attest.ts +8 -3
- package/src/core/adapters/profiles.ts +4 -6
- package/src/core/agents/canonical-emit.ts +34 -25
- package/src/core/agents/cli.ts +236 -262
- package/src/core/agents/codex-archive-v3.ts +138 -0
- package/src/core/agents/coord-client.ts +75 -188
- package/src/core/agents/finalization.ts +120 -38
- package/src/core/agents/index.ts +4 -5
- package/src/core/agents/live-authority-v3.ts +375 -0
- package/src/core/agents/live-lifecycle-v3.ts +140 -0
- package/src/core/agents/live-observation-v3.ts +216 -0
- package/src/core/agents/render/prompt-context.ts +29 -60
- package/src/core/agents/render/session-context.ts +10 -31
- package/src/core/agents/rules/claim-conflict.ts +85 -126
- package/src/core/agents/rules/commit-conflict.ts +3 -14
- package/src/core/agents/rules/stop-hook.ts +239 -293
- package/src/core/agents/session-events.ts +137 -104
- package/src/core/agents/session-finalization-state-v3.ts +90 -0
- package/src/core/agents/session-finalizer-v3.ts +953 -0
- package/src/core/agents/session-name-display.ts +149 -0
- package/src/core/agents/state/activity-log.ts +6 -14
- package/src/core/agents/state/heartbeat-writer.ts +82 -277
- package/src/core/agents/state/live-coordination-view.ts +290 -0
- package/src/core/agents/state/session-state.ts +24 -12
- package/src/core/agents/state/stale-sweep.ts +40 -17
- package/src/core/artifacts/index.ts +4 -5
- package/src/core/config.ts +148 -3
- package/src/core/context/index.ts +9 -17
- package/src/core/events/span-parent.ts +46 -0
- package/src/core/events/v3/advance.ts +168 -0
- package/src/core/events/v3/authority-outbox.ts +548 -0
- package/src/core/events/v3/base-builder.ts +60 -0
- package/src/core/events/v3/base-contract.ts +882 -0
- package/src/core/events/v3/bootstrap.ts +226 -0
- package/src/core/events/v3/builder.ts +59 -0
- package/src/core/events/v3/canonical.ts +153 -0
- package/src/core/events/v3/capabilities.ts +171 -0
- package/src/core/events/v3/capability-drift.ts +177 -0
- package/src/core/events/v3/catalog.ts +202 -0
- package/src/core/events/v3/clock-order.ts +41 -0
- package/src/core/events/v3/contract.ts +365 -0
- package/src/core/events/v3/control.ts +576 -0
- package/src/core/events/v3/coordination-view.ts +193 -0
- package/src/core/events/v3/economics.ts +384 -0
- package/src/core/events/v3/finalization-view.ts +67 -0
- package/src/core/events/v3/fingerprint-keys.ts +260 -0
- package/src/core/events/v3/generated.ts +48 -0
- package/src/core/events/v3/ids.ts +33 -0
- package/src/core/events/v3/index.ts +322 -0
- package/src/core/events/v3/latency.ts +551 -0
- package/src/core/events/v3/live-feed.ts +319 -0
- package/src/core/events/v3/live-observation.ts +39 -0
- package/src/core/events/v3/live-routing.ts +135 -0
- package/src/core/events/v3/producers/command-recorder.ts +631 -0
- package/src/core/events/v3/producers/command.ts +201 -0
- package/src/core/events/v3/producers/coordination-recorder.ts +538 -0
- package/src/core/events/v3/producers/coordination.ts +355 -0
- package/src/core/events/v3/producers/hook-base.ts +578 -0
- package/src/core/events/v3/producers/hook.ts +119 -0
- package/src/core/events/v3/producers/intake.ts +319 -0
- package/src/core/events/v3/producers/recorder.ts +2805 -0
- package/src/core/events/v3/projection.ts +653 -0
- package/src/core/events/v3/reader.ts +1127 -0
- package/src/core/events/v3/recovery-record.ts +244 -0
- package/src/core/events/v3/recovery.ts +271 -0
- package/src/core/events/v3/span-state.ts +187 -0
- package/src/core/events/v3/targets.ts +182 -0
- package/src/core/events/v3/turn-telemetry.ts +259 -0
- package/src/core/events/v3/validate.ts +361 -0
- package/src/core/events/v3/writer.ts +419 -0
- package/src/core/governor/index.ts +3 -0
- package/src/core/governor/plan-api.ts +10 -2
- package/src/core/governor/read.ts +3 -0
- package/src/core/governor/state.ts +52 -5
- package/src/core/guard/config.ts +206 -0
- package/src/core/guard/coordinator.ts +227 -0
- package/src/core/guard/evaluator.ts +343 -0
- package/src/core/guard/evidence-v3.ts +227 -0
- package/src/core/guard/index.ts +35 -0
- package/src/core/guard/live-source-v3.ts +204 -0
- package/src/core/guard/storage.ts +188 -0
- package/src/core/guard/types.ts +152 -0
- package/src/core/hooks/adapter/detect.ts +28 -1
- package/src/core/hooks/adapter/events.ts +14 -6
- package/src/core/hooks/adapter/output.ts +7 -2
- package/src/core/hooks/adapter/parse.ts +80 -38
- package/src/core/hooks/adapter/wiring.ts +119 -13
- package/src/core/hooks/cli.ts +351 -466
- package/src/core/hooks/effects/image-capture.ts +228 -238
- package/src/core/hooks/effects/index.ts +1 -36
- package/src/core/hooks/events/input-hash.ts +47 -0
- package/src/core/hooks/index.ts +4 -11
- package/src/core/hooks/resolve/coord-root.ts +1 -1
- package/src/core/hooks/resolve/owner.ts +52 -45
- package/src/core/hooks/resolve/transcript.ts +165 -14
- package/src/core/hooks/session-name-presence.ts +14 -15
- package/src/core/hooks/unsafe-cross-shell.ts +1 -1
- package/src/core/journal/index.ts +15 -22
- package/src/core/presence/blob.ts +48 -41
- package/src/core/presence/codec-digest.ts +215 -0
- package/src/core/presence/relay-client.ts +5 -5
- package/src/core/work/index.ts +3 -0
- package/src/core/work/read.ts +3 -0
- package/src/core/work/runner.ts +6 -0
- package/src/core/work/state.ts +27 -3
- package/src/core/workflow/engine.ts +24 -24
- package/src/core/workflow/live-session-v3.ts +126 -0
- package/src/core/workflow/scope-id.ts +6 -0
- package/src/core/workflow/workspaces/leases.ts +56 -19
- package/src/index.ts +1 -1
- package/src/lib/browser/client.ts +230 -0
- package/src/lib/browser/critique.ts +104 -27
- package/src/lib/browser/geometry.ts +143 -14
- package/src/lib/browser/index.ts +34 -0
- package/src/lib/browser/qa-plan.ts +501 -0
- package/src/lib/browser/qa-reuse.ts +306 -0
- package/src/lib/browser/qa-snapshot.ts +223 -0
- package/src/lib/browser/runts.ts +27 -2
- package/src/lib/browser/tiling.ts +164 -0
- package/src/lib/claude-desktop.ts +1 -232
- package/src/lib/context/index.ts +22 -46
- package/src/lib/council/index.ts +9 -21
- package/src/lib/docs-frontmatter.ts +8 -79
- package/src/lib/docs-index.ts +33 -3
- package/src/lib/docs-lint.ts +15 -29
- package/src/lib/docs-metadata-audit.ts +166 -0
- package/src/lib/docs-metadata-managed.ts +83 -0
- package/src/lib/docs-metadata-sync.ts +262 -0
- package/src/lib/docs-metadata-v2-schema.ts +138 -0
- package/src/lib/docs-metadata-v2.ts +646 -0
- package/src/lib/docs-new.ts +63 -0
- package/src/lib/docs-sweep.ts +42 -28
- package/src/lib/headless/index.ts +287 -0
- package/src/lib/identities/assume.ts +67 -86
- package/src/lib/instructions/apply.ts +33 -20
- package/src/lib/instructions/bundle.ts +2 -2
- package/src/lib/instructions/splice.ts +21 -7
- package/src/lib/instructions/templates.ts +85 -13
- package/dist/core/agents/cli-emit.d.ts +0 -27
- package/dist/core/agents/cli-emit.d.ts.map +0 -1
- package/dist/core/agents/cli-emit.js +0 -57
- package/dist/core/agents/codex-replay.d.ts +0 -29
- package/dist/core/agents/codex-replay.d.ts.map +0 -1
- package/dist/core/agents/codex-replay.js +0 -138
- package/dist/core/agents/events/consume.d.ts +0 -82
- package/dist/core/agents/events/consume.d.ts.map +0 -1
- package/dist/core/agents/events/consume.js +0 -195
- package/dist/core/agents/events/emit.d.ts +0 -42
- package/dist/core/agents/events/emit.d.ts.map +0 -1
- package/dist/core/agents/events/emit.js +0 -75
- package/dist/core/agents/events/ulid.d.ts +0 -11
- package/dist/core/agents/events/ulid.d.ts.map +0 -1
- package/dist/core/agents/events/ulid.js +0 -47
- package/dist/core/agents/state/heartbeat-projector.d.ts +0 -76
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +0 -1
- package/dist/core/agents/state/heartbeat-projector.js +0 -581
- package/dist/core/hooks/events/emit.d.ts +0 -31
- package/dist/core/hooks/events/emit.d.ts.map +0 -1
- package/dist/core/hooks/events/emit.js +0 -93
- package/dist/core/hooks/events/rotate.d.ts +0 -43
- package/dist/core/hooks/events/rotate.d.ts.map +0 -1
- package/dist/core/hooks/events/rotate.js +0 -142
- package/dist/core/hooks/events/schema.d.ts +0 -341
- package/dist/core/hooks/events/schema.d.ts.map +0 -1
- package/dist/core/hooks/events/schema.js +0 -12
- package/dist/core/hooks/events/ulid.d.ts +0 -10
- package/dist/core/hooks/events/ulid.d.ts.map +0 -1
- package/dist/core/hooks/events/ulid.js +0 -47
- package/dist/lib/docs-frontmatter-migrate.d.ts +0 -33
- package/dist/lib/docs-frontmatter-migrate.d.ts.map +0 -1
- package/dist/lib/docs-frontmatter-migrate.js +0 -364
- package/src/core/agents/cli-emit.ts +0 -64
- package/src/core/agents/codex-replay.ts +0 -163
- package/src/core/agents/events/consume.ts +0 -254
- package/src/core/agents/events/emit.ts +0 -115
- package/src/core/agents/events/ulid.ts +0 -51
- package/src/core/agents/state/heartbeat-projector.ts +0 -645
- package/src/core/hooks/events/emit.ts +0 -125
- package/src/core/hooks/events/rotate.ts +0 -151
- package/src/core/hooks/events/schema.ts +0 -582
- package/src/core/hooks/events/ulid.ts +0 -51
- package/src/lib/docs-frontmatter-migrate.ts +0 -427
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The suggested session name is a small display protocol, not ordinary prose.
|
|
3
|
+
* Keep its exact block and pending-state rules in one adapter-neutral module so
|
|
4
|
+
* prompt context, PostToolUse injection, and PreToolUse enforcement cannot
|
|
5
|
+
* drift apart.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface SessionNameDisplayState {
|
|
9
|
+
suggested_session_name?: string;
|
|
10
|
+
session_name_seen_for?: string;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export const SESSION_NAME_DISPLAY_NOTE =
|
|
14
|
+
"Next, before any prose or another tool call, send suggested_session_name verbatim by itself in a fenced code block.";
|
|
15
|
+
|
|
16
|
+
export function sessionNameDisplayPending(
|
|
17
|
+
row: SessionNameDisplayState | null | undefined,
|
|
18
|
+
): string | null {
|
|
19
|
+
const name = row?.suggested_session_name;
|
|
20
|
+
if (!name || row?.session_name_seen_for === name) return null;
|
|
21
|
+
return name;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
export function sessionNameDisplayBlock(name: string): string {
|
|
25
|
+
return `\`\`\`\n${name}\n\`\`\``;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
export function sessionNameDisplayInstruction(name: string): string {
|
|
29
|
+
return [
|
|
30
|
+
"Session name display required.",
|
|
31
|
+
"Before any prose or another tool call, send this exact fenced block as your next assistant text:",
|
|
32
|
+
"",
|
|
33
|
+
sessionNameDisplayBlock(name),
|
|
34
|
+
"",
|
|
35
|
+
"Do not put commentary before the block. Harnery will reject tool calls until it is shown.",
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
/**
|
|
40
|
+
* A PostToolUse result should announce the display protocol only when that
|
|
41
|
+
* exact tool call minted the current suggestion. The coordination row keeps
|
|
42
|
+
* the suggestion pending until transcript evidence catches up, so checking
|
|
43
|
+
* the row alone would re-announce the same name after every later tool.
|
|
44
|
+
*
|
|
45
|
+
* Adapter responses vary between a direct command envelope and wrapper
|
|
46
|
+
* objects whose `output`/content field contains the JSON as one line. Walk
|
|
47
|
+
* both shapes, but require the command's explicit mint flag as well as the
|
|
48
|
+
* exact current name. Ordinary status output can carry the name without
|
|
49
|
+
* activating the display ritual.
|
|
50
|
+
*/
|
|
51
|
+
export function toolResponseMintedSessionName(response: unknown, name: string): boolean {
|
|
52
|
+
if (!name) return false;
|
|
53
|
+
return responseContainsSessionNameMint(response, name, new Set<object>(), 0);
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
function responseContainsSessionNameMint(
|
|
57
|
+
value: unknown,
|
|
58
|
+
name: string,
|
|
59
|
+
seen: Set<object>,
|
|
60
|
+
depth: number,
|
|
61
|
+
): boolean {
|
|
62
|
+
if (depth > 8 || value === null || value === undefined) return false;
|
|
63
|
+
|
|
64
|
+
if (typeof value === "string") {
|
|
65
|
+
const candidates = [value.trim(), ...value.split(/\r?\n/).map((line) => line.trim())];
|
|
66
|
+
for (const candidate of candidates) {
|
|
67
|
+
if (!candidate.startsWith("{") && !candidate.startsWith("[")) continue;
|
|
68
|
+
try {
|
|
69
|
+
if (
|
|
70
|
+
responseContainsSessionNameMint(JSON.parse(candidate) as unknown, name, seen, depth + 1)
|
|
71
|
+
) {
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
} catch {
|
|
75
|
+
// Wrapper prose and partial JSON are not authoritative mint evidence.
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
return false;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (typeof value !== "object") return false;
|
|
82
|
+
if (seen.has(value)) return false;
|
|
83
|
+
seen.add(value);
|
|
84
|
+
|
|
85
|
+
if (Array.isArray(value)) {
|
|
86
|
+
return value.some((item) => responseContainsSessionNameMint(item, name, seen, depth + 1));
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
const row = value as Record<string, unknown>;
|
|
90
|
+
if (
|
|
91
|
+
row.suggested_session_name === name &&
|
|
92
|
+
(row.first_of_session === true || row.name_reminted === true)
|
|
93
|
+
) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return Object.values(row).some((item) =>
|
|
98
|
+
responseContainsSessionNameMint(item, name, seen, depth + 1),
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Accept the exact unlabelled block Harnery requests. `text` and `plaintext`
|
|
104
|
+
* are tolerated for older prompts, but the code block may contain only the
|
|
105
|
+
* suggested name and must be the first non-whitespace user-facing content.
|
|
106
|
+
*/
|
|
107
|
+
export function assistantTextStartsWithSessionNameBlock(text: string, name: string): boolean {
|
|
108
|
+
if (!text || !name) return false;
|
|
109
|
+
const normalized = text.replace(/\r\n?/g, "\n").trimStart();
|
|
110
|
+
const match = /^```(?:text|plaintext)?[ \t]*\n([^\n]*)\n```(?:[ \t]*(?:\n|$))/.exec(normalized);
|
|
111
|
+
return match?.[1] === name;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/**
|
|
115
|
+
* A trailing stream redirect to `/dev/null` or another descriptor. Agents append
|
|
116
|
+
* these habitually when capturing output, and unlike a pipe or `&&` they cannot
|
|
117
|
+
* smuggle a second command, so they must not disable the remediation exemption
|
|
118
|
+
* below. Deliberately excludes redirects to a named file.
|
|
119
|
+
*/
|
|
120
|
+
const BENIGN_REDIRECT_SUFFIX = /\s*[012]?>>?\s*(?:&[012]|\/dev\/null)\s*$/;
|
|
121
|
+
|
|
122
|
+
/**
|
|
123
|
+
* The display latch must not block the two coordination commands that can
|
|
124
|
+
* repair a turn or close it cleanly. Keep this intentionally narrower than
|
|
125
|
+
* "any harn command" and reject shell control syntax before matching.
|
|
126
|
+
*/
|
|
127
|
+
export function isSessionNameRemediationCommand(
|
|
128
|
+
command: string | undefined,
|
|
129
|
+
binName: string,
|
|
130
|
+
): boolean {
|
|
131
|
+
if (!command || !binName) return false;
|
|
132
|
+
let body = command.replace(/^(?:[ \t]*#\s*intent:[^\n]*\n)+/i, "").trim();
|
|
133
|
+
|
|
134
|
+
// Strip benign trailing redirects before the control-syntax check. Without
|
|
135
|
+
// this, `<bin> agents status --end-turn 2>&1` fails the `&` test, which
|
|
136
|
+
// disables the one exemption that can close a latched turn and leaves the
|
|
137
|
+
// session unable to satisfy either the latch or the end-of-turn rule.
|
|
138
|
+
for (let next = body.replace(BENIGN_REDIRECT_SUFFIX, "").trim(); next !== body; ) {
|
|
139
|
+
body = next;
|
|
140
|
+
next = body.replace(BENIGN_REDIRECT_SUFFIX, "").trim();
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (!body || /[\n;&|<>`$]/.test(body)) return false;
|
|
144
|
+
const escapedBin = binName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
145
|
+
const pattern = new RegExp(
|
|
146
|
+
`^(?:codex-wsl\\s+--\\s+)?${escapedBin}\\s+agents\\s+(?:set-task|status)(?:\\s+.*)?$`,
|
|
147
|
+
);
|
|
148
|
+
return pattern.test(body);
|
|
149
|
+
}
|
|
@@ -2,32 +2,24 @@
|
|
|
2
2
|
* Display-name resolution for the coord layer.
|
|
3
3
|
*
|
|
4
4
|
* This module once housed `coordLog`, the writer for a human-readable
|
|
5
|
-
* activity log. That log has been retired; the canonical
|
|
6
|
-
*
|
|
5
|
+
* activity log. That log has been retired; the canonical V3 ledger is the
|
|
6
|
+
* single source of truth, and the
|
|
7
7
|
* per-event telemetry that had consumers (heals → health.*, councils →
|
|
8
8
|
* council.*, shell-mutation candidates → decision.warn) is emitted there
|
|
9
9
|
* directly. `coordLog` and its call sites are gone; only `resolveShortName`
|
|
10
10
|
* remains (still used for display-name resolution).
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
|
-
import {
|
|
14
|
-
import { join } from "node:path";
|
|
13
|
+
import { readLiveCoordinationRow } from "./live-coordination-view.ts";
|
|
15
14
|
|
|
16
15
|
/**
|
|
17
|
-
* Resolve `agent-<name>` display string. Looks up the
|
|
16
|
+
* Resolve `agent-<name>` display string. Looks up the V3 projection's `name`
|
|
18
17
|
* field; falls back to `agent-<8-char-hex>` if name is empty (mirrors bash
|
|
19
18
|
* coord_owner_short). Returns `agent-unknown` when instanceId is null.
|
|
20
19
|
*/
|
|
21
20
|
export function resolveShortName(coordRoot: string, instanceId: string | null): string {
|
|
22
21
|
if (!instanceId) return "agent-unknown";
|
|
23
|
-
const
|
|
24
|
-
if (
|
|
25
|
-
try {
|
|
26
|
-
const hb = JSON.parse(readFileSync(path, "utf8")) as { name?: string };
|
|
27
|
-
if (hb.name && hb.name.length > 0) return `agent-${hb.name}`;
|
|
28
|
-
} catch {
|
|
29
|
-
/* fall through to short-id */
|
|
30
|
-
}
|
|
31
|
-
}
|
|
22
|
+
const row = readLiveCoordinationRow(coordRoot, instanceId);
|
|
23
|
+
if (row?.name) return `agent-${row.name}`;
|
|
32
24
|
return `agent-${instanceId.slice(0, 8)}`;
|
|
33
25
|
}
|
|
@@ -9,7 +9,8 @@
|
|
|
9
9
|
* half-written intermediate. Concurrent writers serialize via the rename
|
|
10
10
|
* (last write wins).
|
|
11
11
|
*
|
|
12
|
-
*
|
|
12
|
+
* Cache identity invariant: every action operates on the generation-bound row at
|
|
13
|
+
* `.harnery/active/<instance_id>.json`; the canonical V3 ledger remains authoritative.
|
|
13
14
|
* (the file IS the heartbeat). No mutations happen elsewhere.
|
|
14
15
|
*/
|
|
15
16
|
|
|
@@ -22,60 +23,9 @@ import {
|
|
|
22
23
|
unlinkSync,
|
|
23
24
|
writeFileSync,
|
|
24
25
|
} from "node:fs";
|
|
25
|
-
import { dirname, join } from "node:path";
|
|
26
|
-
import {
|
|
27
|
-
import {
|
|
28
|
-
type AgentActivity,
|
|
29
|
-
applySessionStateEvent,
|
|
30
|
-
type SessionStateEvidenceEvent,
|
|
31
|
-
type TaskState,
|
|
32
|
-
} from "./session-state.ts";
|
|
33
|
-
|
|
34
|
-
/** Inline adapter normalizer (mirrors canonical-emit.normalizeAdapter), kept
|
|
35
|
-
* local so the writer's only cross-module dep is the in-process emit(). */
|
|
36
|
-
function adapterOf(platform: string | undefined): "claude-code" | "cursor" | "codex" {
|
|
37
|
-
if (platform === "cursor") return "cursor";
|
|
38
|
-
if (platform === "codex") return "codex";
|
|
39
|
-
return "claude-code";
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
/** Preserve the canonical adapter id in heartbeat state. Mirrors
|
|
43
|
-
* heartbeat-projector.adapterToPlatform so a healed heartbeat carries the same
|
|
44
|
-
* platform value projection would have written. */
|
|
45
|
-
function adapterToPlatform(adapter: string | undefined): string {
|
|
46
|
-
if (adapter === "cursor") return "cursor";
|
|
47
|
-
if (adapter === "codex") return "codex";
|
|
48
|
-
return "claude-code";
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
/**
|
|
52
|
-
* Emit a canonical `health.*` event for an actual self-heal write. This is the
|
|
53
|
-
* single source of truth for heal telemetry across BOTH the live auto-heal
|
|
54
|
-
* (the pre-tool-use hook → agent-coord heal-heartbeat) and the manual `harn agents
|
|
55
|
-
* heal` path. Write-only by construction (callers only invoke it after a real
|
|
56
|
-
* write), so an already-correct heal records nothing.
|
|
57
|
-
* Best-effort: never throws into the heal path.
|
|
58
|
-
*/
|
|
59
|
-
function emitHealthHeal(
|
|
60
|
-
coordRoot: string,
|
|
61
|
-
type: "health.pidmap_heal" | "health.heartbeat_heal",
|
|
62
|
-
instanceId: string,
|
|
63
|
-
hb: Heartbeat | null,
|
|
64
|
-
data: Record<string, unknown>,
|
|
65
|
-
): void {
|
|
66
|
-
try {
|
|
67
|
-
emit(coordRoot, {
|
|
68
|
-
event_type: type,
|
|
69
|
-
instance_id: instanceId,
|
|
70
|
-
session_id: hb?.session_id ?? instanceId,
|
|
71
|
-
adapter: adapterOf(hb?.platform),
|
|
72
|
-
source: "agent-coord",
|
|
73
|
-
data,
|
|
74
|
-
});
|
|
75
|
-
} catch {
|
|
76
|
-
/* telemetry only, never break a heal */
|
|
77
|
-
}
|
|
78
|
-
}
|
|
26
|
+
import { basename, dirname, join } from "node:path";
|
|
27
|
+
import { assertSafeInstanceId, resolveContainedFile } from "../coord-client.ts";
|
|
28
|
+
import type { AgentActivity, TaskState } from "./session-state.ts";
|
|
79
29
|
|
|
80
30
|
export interface Heartbeat {
|
|
81
31
|
schema_version?: number;
|
|
@@ -84,6 +34,8 @@ export interface Heartbeat {
|
|
|
84
34
|
kind?: string;
|
|
85
35
|
agent_id?: string;
|
|
86
36
|
session_id: string;
|
|
37
|
+
/** Native adapter session ID retained only in a generation-bound local projection. */
|
|
38
|
+
native_session_id?: string;
|
|
87
39
|
subagent_call_id?: string;
|
|
88
40
|
model?: string;
|
|
89
41
|
platform?: string;
|
|
@@ -102,7 +54,7 @@ export interface Heartbeat {
|
|
|
102
54
|
* presence is the "this session has been named" signal the prompt-context
|
|
103
55
|
* nudge and the Stop-hook naming rule key on. */
|
|
104
56
|
suggested_session_name?: string;
|
|
105
|
-
/** Stamped by turn.
|
|
57
|
+
/** Stamped by turn.completed once the suggested name is seen in assistant reply
|
|
106
58
|
* text, ending the per-turn transcript scan. */
|
|
107
59
|
session_name_seen_at?: string;
|
|
108
60
|
/** WHICH name that sighting was for. The scan is skipped only while this
|
|
@@ -110,19 +62,25 @@ export interface Heartbeat {
|
|
|
110
62
|
* again rather than being suppressed by the earlier sighting. */
|
|
111
63
|
session_name_seen_for?: string;
|
|
112
64
|
last_status_at?: string;
|
|
113
|
-
turn_summary?: string | null;
|
|
114
|
-
turn_summary_updated_at?: string | null;
|
|
115
|
-
last_tool?: string;
|
|
116
|
-
last_tool_target?: string;
|
|
117
|
-
last_tool_at?: string;
|
|
118
65
|
current_turn_id?: string;
|
|
119
66
|
parent_instance_id?: string;
|
|
120
67
|
workflow_run_id?: string;
|
|
68
|
+
workflow_agent_id?: string;
|
|
69
|
+
/** Disposable-cache bindings that prove a row belongs to the current V3 generation. */
|
|
70
|
+
v3_instance_id?: `inst_${string}`;
|
|
71
|
+
v3_generation_id?: `gen_${string}`;
|
|
72
|
+
v3_projection_event_id?: string;
|
|
73
|
+
v3_task_state?: "set" | "cleared";
|
|
121
74
|
[extra: string]: unknown;
|
|
122
75
|
}
|
|
123
76
|
|
|
124
77
|
function heartbeatPath(coordRoot: string, instanceId: string): string {
|
|
125
|
-
|
|
78
|
+
assertSafeInstanceId(instanceId);
|
|
79
|
+
const safeInstanceId = basename(instanceId);
|
|
80
|
+
if (safeInstanceId !== instanceId) {
|
|
81
|
+
throw new Error("instance_id must be a direct-child coordination basename");
|
|
82
|
+
}
|
|
83
|
+
return resolveContainedFile(join(coordRoot, ".harnery", "active"), `${safeInstanceId}.json`);
|
|
126
84
|
}
|
|
127
85
|
|
|
128
86
|
function nowIsoSeconds(): string {
|
|
@@ -146,30 +104,21 @@ export function readHeartbeat(coordRoot: string, instanceId: string): Heartbeat
|
|
|
146
104
|
}
|
|
147
105
|
}
|
|
148
106
|
|
|
149
|
-
/**
|
|
150
|
-
|
|
151
|
-
* unrelated projector side effects before a tool authorization verdict. */
|
|
152
|
-
export function stampSessionStateEvent(
|
|
107
|
+
/** Persist operator-facing lifecycle prose in the generation-bound cache only. */
|
|
108
|
+
export function setLifecycleCache(
|
|
153
109
|
coordRoot: string,
|
|
154
110
|
instanceId: string,
|
|
155
|
-
|
|
111
|
+
state: TaskState,
|
|
112
|
+
reason?: string,
|
|
113
|
+
suggestedSessionName?: string,
|
|
156
114
|
): Heartbeat | null {
|
|
157
|
-
return mutate(coordRoot, instanceId, (heartbeat) => {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
...heartbeat,
|
|
165
|
-
activity: state.activity,
|
|
166
|
-
activity_updated_at: state.activity_updated_at,
|
|
167
|
-
activity_source: state.activity_source,
|
|
168
|
-
task_state: state.task_state,
|
|
169
|
-
task_state_updated_at: state.task_state_updated_at,
|
|
170
|
-
task_state_reason: state.task_state_reason,
|
|
171
|
-
};
|
|
172
|
-
});
|
|
115
|
+
return mutate(coordRoot, instanceId, (heartbeat) => ({
|
|
116
|
+
...heartbeat,
|
|
117
|
+
task_state: state,
|
|
118
|
+
task_state_updated_at: nowIsoSeconds(),
|
|
119
|
+
task_state_reason: state === "active" ? undefined : reason,
|
|
120
|
+
...(suggestedSessionName ? { suggested_session_name: suggestedSessionName } : {}),
|
|
121
|
+
}));
|
|
173
122
|
}
|
|
174
123
|
|
|
175
124
|
function mutate(
|
|
@@ -201,11 +150,27 @@ export function setTask(coordRoot: string, instanceId: string, task: string): He
|
|
|
201
150
|
...hb,
|
|
202
151
|
task: cleared ? undefined : task,
|
|
203
152
|
task_updated_at: nowIsoSeconds(),
|
|
153
|
+
...(hb.schema_version === 2 ? { v3_task_state: cleared ? "cleared" : "set" } : {}),
|
|
204
154
|
...(built ? { suggested_session_name: built.suggestedName } : {}),
|
|
205
155
|
};
|
|
206
156
|
});
|
|
207
157
|
}
|
|
208
158
|
|
|
159
|
+
/** Update the disposable identity cache after a canonical V3 attestation. */
|
|
160
|
+
export function setIdentityCache(
|
|
161
|
+
coordRoot: string,
|
|
162
|
+
instanceId: string,
|
|
163
|
+
name: string,
|
|
164
|
+
agentId: string,
|
|
165
|
+
): Heartbeat | null {
|
|
166
|
+
const heartbeat = readHeartbeat(coordRoot, instanceId);
|
|
167
|
+
if (!heartbeat) return null;
|
|
168
|
+
heartbeat.name = name;
|
|
169
|
+
heartbeat.agent_id = agentId;
|
|
170
|
+
atomicWrite(heartbeatPath(coordRoot, instanceId), JSON.stringify(heartbeat, null, 2));
|
|
171
|
+
return heartbeat;
|
|
172
|
+
}
|
|
173
|
+
|
|
209
174
|
/**
|
|
210
175
|
* Build the copy-pasteable session name from the coord identity + the agent's
|
|
211
176
|
* description parts. Pure (no coord-state reads) so it's unit-testable; collapses
|
|
@@ -221,17 +186,17 @@ export function buildSuggestedName(
|
|
|
221
186
|
return { suggestedName: `Agent ${name} - ${description}`, description };
|
|
222
187
|
}
|
|
223
188
|
|
|
224
|
-
/** Build the
|
|
189
|
+
/** Build the sole lifecycle-driven title: the terminal done projection. */
|
|
225
190
|
export function buildLifecycleSuggestedName(
|
|
226
|
-
|
|
227
|
-
task: string | undefined,
|
|
191
|
+
currentSessionName: string | undefined,
|
|
228
192
|
state: TaskState,
|
|
229
193
|
): string | null {
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
194
|
+
if (state !== "done" || !currentSessionName?.trim()) return null;
|
|
195
|
+
const baseName = currentSessionName
|
|
196
|
+
.trim()
|
|
197
|
+
.replace(/^\[DONE\]\s+/, "")
|
|
198
|
+
.replace(/^\[BLOCKED\]\s*-\s*/, "");
|
|
199
|
+
return baseName ? `[DONE] ${baseName}` : null;
|
|
235
200
|
}
|
|
236
201
|
|
|
237
202
|
/** Stamp the sighting once the suggested name has been observed in assistant
|
|
@@ -251,33 +216,36 @@ export function stampSessionNameSeen(
|
|
|
251
216
|
}));
|
|
252
217
|
}
|
|
253
218
|
|
|
254
|
-
export function
|
|
219
|
+
export function releaseClaim(
|
|
255
220
|
coordRoot: string,
|
|
256
221
|
instanceId: string,
|
|
257
|
-
|
|
222
|
+
path: string,
|
|
258
223
|
): Heartbeat | null {
|
|
224
|
+
// files_touched can hold either absolute-under-coordRoot or canonical
|
|
225
|
+
// monorepo-relative entries; normalize both sides so release matches
|
|
226
|
+
// regardless of the form the caller passes (the old exact-string filter
|
|
227
|
+
// silently no-op'd on a form mismatch).
|
|
228
|
+
const norm = (p: string): string =>
|
|
229
|
+
p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
|
|
230
|
+
const target = norm(path);
|
|
259
231
|
return mutate(coordRoot, instanceId, (hb) => ({
|
|
260
232
|
...hb,
|
|
261
|
-
|
|
262
|
-
turn_summary_updated_at: nowIsoSeconds(),
|
|
233
|
+
files_touched: (hb.files_touched ?? []).filter((p) => norm(p) !== target),
|
|
263
234
|
}));
|
|
264
235
|
}
|
|
265
236
|
|
|
266
|
-
|
|
237
|
+
/** Materialize one V3 write-claim authority transition into the heartbeat cache. */
|
|
238
|
+
export function acquireClaim(
|
|
267
239
|
coordRoot: string,
|
|
268
240
|
instanceId: string,
|
|
269
241
|
path: string,
|
|
270
242
|
): Heartbeat | null {
|
|
271
|
-
// files_touched can hold either absolute-under-coordRoot or canonical
|
|
272
|
-
// monorepo-relative entries; normalize both sides so release matches
|
|
273
|
-
// regardless of the form the caller passes (the old exact-string filter
|
|
274
|
-
// silently no-op'd on a form mismatch).
|
|
275
243
|
const norm = (p: string): string =>
|
|
276
244
|
p.startsWith(`${coordRoot}/`) ? p.slice(coordRoot.length + 1) : p;
|
|
277
245
|
const target = norm(path);
|
|
278
246
|
return mutate(coordRoot, instanceId, (hb) => ({
|
|
279
247
|
...hb,
|
|
280
|
-
files_touched: (hb.files_touched ?? []).
|
|
248
|
+
files_touched: [...new Set([...(hb.files_touched ?? []).map(norm), target])].sort(),
|
|
281
249
|
}));
|
|
282
250
|
}
|
|
283
251
|
|
|
@@ -294,7 +262,7 @@ export interface GroupUnclaimHit {
|
|
|
294
262
|
* subagents inherit it) and removes the path from each one's files_touched.
|
|
295
263
|
* Idempotent: heartbeats that don't hold the path are untouched. Returns the
|
|
296
264
|
* heartbeats that actually dropped the path so the caller can emit the
|
|
297
|
-
* durable `
|
|
265
|
+
* durable `coord.claim_changed` release events; a file-only prune is silently reverted by
|
|
298
266
|
* the next projector replay.
|
|
299
267
|
*
|
|
300
268
|
* Tool payloads and release calls can supply either absolute-under-coordRoot or
|
|
@@ -305,7 +273,11 @@ export interface GroupUnclaimHit {
|
|
|
305
273
|
* subagent-held claim that doesn't live on the parent's heartbeat still gets
|
|
306
274
|
* pruned because the walk covers the whole group.
|
|
307
275
|
*/
|
|
308
|
-
export function
|
|
276
|
+
export function findGroupClaims(
|
|
277
|
+
coordRoot: string,
|
|
278
|
+
groupId: string,
|
|
279
|
+
path: string,
|
|
280
|
+
): GroupUnclaimHit[] {
|
|
309
281
|
const hits: GroupUnclaimHit[] = [];
|
|
310
282
|
if (!groupId || !path) return hits;
|
|
311
283
|
const activeDir = join(coordRoot, ".harnery", "active");
|
|
@@ -326,26 +298,17 @@ export function groupUnclaim(coordRoot: string, groupId: string, path: string):
|
|
|
326
298
|
(body.session_id as string | undefined) ?? (body.instance_id as string | undefined);
|
|
327
299
|
if (peerSession !== groupId) continue;
|
|
328
300
|
const files = (body.files_touched as string[] | undefined) ?? [];
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
renameSync(tmp, hbPath);
|
|
336
|
-
hits.push({
|
|
337
|
-
instance_id: (body.instance_id as string | undefined) ?? f.replace(/\.json$/, ""),
|
|
338
|
-
session_id: body.session_id as string | undefined,
|
|
339
|
-
platform: body.platform as string | undefined,
|
|
340
|
-
});
|
|
341
|
-
} catch {
|
|
342
|
-
/* silent */
|
|
343
|
-
}
|
|
301
|
+
if (!files.some((candidate) => norm(candidate) === target)) continue;
|
|
302
|
+
hits.push({
|
|
303
|
+
instance_id: (body.instance_id as string | undefined) ?? f.replace(/\.json$/, ""),
|
|
304
|
+
session_id: body.session_id as string | undefined,
|
|
305
|
+
platform: body.platform as string | undefined,
|
|
306
|
+
});
|
|
344
307
|
}
|
|
345
308
|
return hits;
|
|
346
309
|
}
|
|
347
310
|
|
|
348
|
-
export function
|
|
311
|
+
export function clearCoordinationCache(coordRoot: string, instanceId: string): boolean {
|
|
349
312
|
const path = heartbeatPath(coordRoot, instanceId);
|
|
350
313
|
if (!existsSync(path)) return false;
|
|
351
314
|
try {
|
|
@@ -373,162 +336,4 @@ export function healPidmap(coordRoot: string, instanceId: string, pid: number):
|
|
|
373
336
|
}
|
|
374
337
|
if (existingOwner === instanceId) return;
|
|
375
338
|
atomicWrite(pmPath, `${instanceId}\t${platform}`);
|
|
376
|
-
emitHealthHeal(coordRoot, "health.pidmap_heal", instanceId, hb, {
|
|
377
|
-
reason: existingOwner ? "stale" : "missing",
|
|
378
|
-
pid,
|
|
379
|
-
kind: "pidmap",
|
|
380
|
-
...(existingOwner ? { prior: existingOwner.slice(0, 8) } : {}),
|
|
381
|
-
});
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
export function healHeartbeat(
|
|
385
|
-
coordRoot: string,
|
|
386
|
-
instanceId: string,
|
|
387
|
-
sessionId?: string,
|
|
388
|
-
model?: string,
|
|
389
|
-
adapter?: string,
|
|
390
|
-
opts?: { forkedFrom?: string },
|
|
391
|
-
): Heartbeat | null {
|
|
392
|
-
const path = heartbeatPath(coordRoot, instanceId);
|
|
393
|
-
if (existsSync(path)) {
|
|
394
|
-
// Already alive, return it.
|
|
395
|
-
return readHeartbeat(coordRoot, instanceId);
|
|
396
|
-
}
|
|
397
|
-
const now = nowIsoSeconds();
|
|
398
|
-
|
|
399
|
-
// Recover name + kind from .name-history if present (idempotent across
|
|
400
|
-
// sweeps: same instance_id always gets the same name).
|
|
401
|
-
let name = "";
|
|
402
|
-
let kind = "session";
|
|
403
|
-
let agentId = "";
|
|
404
|
-
try {
|
|
405
|
-
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
406
|
-
const names = require("./names.ts") as typeof import("./names.ts");
|
|
407
|
-
const resolved = names.resolveName(coordRoot, instanceId, sessionId);
|
|
408
|
-
if (resolved) {
|
|
409
|
-
name = resolved.name;
|
|
410
|
-
kind = resolved.kind;
|
|
411
|
-
// An explicitly assumed session carries its durable persona UUID in
|
|
412
|
-
// name-history. Native subagents continue to use instance_id.
|
|
413
|
-
agentId = resolved.agent_id ?? (resolved.kind === "subagent" ? instanceId : "");
|
|
414
|
-
} else if (!sessionId || sessionId === instanceId) {
|
|
415
|
-
// A main session with NO history at all never fired session.start —
|
|
416
|
-
// the CC fork flow (SessionStart fires under the parent's id before
|
|
417
|
-
// the fork id is minted), or a partially-wired adapter. Mint its pool
|
|
418
|
-
// name here instead of leaving a nameless heartbeat, and stamp the
|
|
419
|
-
// detected fork lineage while we're at it. A sessionId that differs
|
|
420
|
-
// from instanceId is left alone: that shape is a subagent whose parent
|
|
421
|
-
// is also unknown, and guessing "session" would be wrong.
|
|
422
|
-
name = names.assignName(
|
|
423
|
-
coordRoot,
|
|
424
|
-
instanceId,
|
|
425
|
-
"session",
|
|
426
|
-
opts?.forkedFrom ? { forkedFrom: opts.forkedFrom } : undefined,
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
} catch {
|
|
430
|
-
/* names module unavailable, fall back to empty */
|
|
431
|
-
}
|
|
432
|
-
|
|
433
|
-
const hb: Heartbeat = {
|
|
434
|
-
schema_version: 1,
|
|
435
|
-
instance_id: instanceId,
|
|
436
|
-
session_id: sessionId ?? instanceId,
|
|
437
|
-
name,
|
|
438
|
-
kind,
|
|
439
|
-
agent_id: agentId,
|
|
440
|
-
model: model ?? "",
|
|
441
|
-
started_at: now,
|
|
442
|
-
last_heartbeat: now,
|
|
443
|
-
files_touched: [],
|
|
444
|
-
// Default to claude-code only when the caller can't tell us the adapter
|
|
445
|
-
// (e.g. manual `harn agents heal`). The live tool.pre_use heal threads the
|
|
446
|
-
// detected adapter so a pruned Cursor/Codex heartbeat is recreated with
|
|
447
|
-
// the correct platform instead of being mislabeled claude-code.
|
|
448
|
-
platform: adapterToPlatform(adapter),
|
|
449
|
-
};
|
|
450
|
-
atomicWrite(path, JSON.stringify(hb, null, 2));
|
|
451
|
-
// Write-only telemetry: only the actual-recreate branch reaches here (the
|
|
452
|
-
// already-alive case returned above), so this records exactly the heals that
|
|
453
|
-
// happened. Recorded fork lineage rides the event too, so derived readers
|
|
454
|
-
// rebuilding from the ledger converge with .name-history.
|
|
455
|
-
emitHealthHeal(coordRoot, "health.heartbeat_heal", instanceId, hb, {
|
|
456
|
-
reason: "missing",
|
|
457
|
-
kind: "heartbeat",
|
|
458
|
-
...(opts?.forkedFrom ? { forked_from: opts.forkedFrom } : {}),
|
|
459
|
-
});
|
|
460
|
-
return hb;
|
|
461
|
-
}
|
|
462
|
-
|
|
463
|
-
/**
|
|
464
|
-
* Register a workflow child in the coordination layer from the ENGINE side.
|
|
465
|
-
*
|
|
466
|
-
* Previously a spawned child was visible only if its adapter fired Harnery's
|
|
467
|
-
* hooks, which made coordination visibility a property of the vendor CLI
|
|
468
|
-
* rather than of the engine. Headless `codex exec` fires no hooks, so codex
|
|
469
|
-
* children never appeared in `harn agents list` and rendered as "no live
|
|
470
|
-
* session" on the run page while actively working — for the entire length of
|
|
471
|
-
* a multi-minute stage.
|
|
472
|
-
*
|
|
473
|
-
* The engine already knows every fact a heartbeat needs at spawn time, so it
|
|
474
|
-
* writes one itself. Hook-firing adapters keep enriching the same file
|
|
475
|
-
* (last_tool, files_touched); non-hook adapters at least become visible and
|
|
476
|
-
* attributable. Pair with `killHeartbeat` when the child ends.
|
|
477
|
-
*
|
|
478
|
-
* Idempotent: re-registering refreshes in place and preserves `started_at`
|
|
479
|
-
* and any claims a hook already recorded.
|
|
480
|
-
*/
|
|
481
|
-
export function registerWorkflowChild(
|
|
482
|
-
coordRoot: string,
|
|
483
|
-
opts: {
|
|
484
|
-
instanceId: string;
|
|
485
|
-
runId: string;
|
|
486
|
-
agentId: string;
|
|
487
|
-
sessionId?: string;
|
|
488
|
-
adapter?: string;
|
|
489
|
-
label?: string;
|
|
490
|
-
model?: string;
|
|
491
|
-
},
|
|
492
|
-
): Heartbeat {
|
|
493
|
-
const now = nowIsoSeconds();
|
|
494
|
-
const prior = readHeartbeat(coordRoot, opts.instanceId);
|
|
495
|
-
const hb: Heartbeat = {
|
|
496
|
-
...(prior ?? {}),
|
|
497
|
-
schema_version: 1,
|
|
498
|
-
instance_id: opts.instanceId,
|
|
499
|
-
// The reader keys children by session_id and skips any heartbeat missing
|
|
500
|
-
// one, so it must always be set even before the adapter mints a real id.
|
|
501
|
-
session_id: prior?.session_id ?? opts.sessionId ?? opts.instanceId,
|
|
502
|
-
name: opts.label || opts.agentId,
|
|
503
|
-
kind: "workflow-child",
|
|
504
|
-
agent_id: opts.agentId,
|
|
505
|
-
model: opts.model ?? prior?.model ?? "",
|
|
506
|
-
platform: adapterToPlatform(opts.adapter),
|
|
507
|
-
started_at: prior?.started_at ?? now,
|
|
508
|
-
last_heartbeat: now,
|
|
509
|
-
files_touched: prior?.files_touched ?? [],
|
|
510
|
-
task: opts.label ?? "",
|
|
511
|
-
workflow_run_id: opts.runId,
|
|
512
|
-
workflow_agent_id: opts.agentId,
|
|
513
|
-
};
|
|
514
|
-
atomicWrite(heartbeatPath(coordRoot, opts.instanceId), JSON.stringify(hb, null, 2));
|
|
515
|
-
return hb;
|
|
516
|
-
}
|
|
517
|
-
|
|
518
|
-
/**
|
|
519
|
-
* Stamp the heartbeat with the most-recent tool name + target. Written from
|
|
520
|
-
* the post-tool-use hook.
|
|
521
|
-
*/
|
|
522
|
-
export function stampToolActivity(
|
|
523
|
-
coordRoot: string,
|
|
524
|
-
instanceId: string,
|
|
525
|
-
toolName: string,
|
|
526
|
-
target: string,
|
|
527
|
-
): Heartbeat | null {
|
|
528
|
-
return mutate(coordRoot, instanceId, (hb) => ({
|
|
529
|
-
...hb,
|
|
530
|
-
last_tool: toolName,
|
|
531
|
-
last_tool_target: target,
|
|
532
|
-
last_tool_at: nowIsoSeconds(),
|
|
533
|
-
}));
|
|
534
339
|
}
|