harnery 0.32.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/README.md +2 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +7 -1
- 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 +1408 -565
- 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 +2 -2
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +2 -2
- 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.d.ts +4 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +55 -7
- 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 +10 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +233 -51
- package/dist/commands/instructions.d.ts +4 -0
- package/dist/commands/instructions.d.ts.map +1 -0
- package/dist/commands/instructions.js +100 -0
- 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 +15 -6
- 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 +27 -25
- package/dist/core/agents/cli.js +212 -235
- 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 -70
- 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 +5 -5
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +5 -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 +10 -4
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +61 -55
- 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 +15 -33
- 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 +29 -46
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +59 -199
- 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 +45 -0
- package/dist/core/agents/state/session-state.d.ts.map +1 -0
- package/dist/core/agents/state/session-state.js +90 -0
- 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 +13 -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 +64 -24
- 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 +345 -400
- package/dist/core/hooks/codex-authorization.d.ts +30 -0
- package/dist/core/hooks/codex-authorization.d.ts.map +1 -0
- package/dist/core/hooks/codex-authorization.js +199 -0
- 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 +8 -3
- package/dist/core/presence/blob.d.ts.map +1 -1
- package/dist/core/presence/blob.js +54 -41
- 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/index.js +15 -1
- 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/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 +33 -0
- package/dist/lib/instructions/bundle.d.ts.map +1 -0
- package/dist/lib/instructions/bundle.js +149 -0
- 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 +27 -6
- 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 +7 -1
- package/src/commands/adapter.ts +2 -2
- package/src/commands/agents.ts +1737 -570
- 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 +7 -5
- 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 +73 -8
- package/src/commands/events.ts +256 -0
- package/src/commands/governor.ts +18 -4
- package/src/commands/init.ts +264 -57
- package/src/commands/instructions.ts +129 -0
- package/src/commands/journal.ts +4 -13
- package/src/commands/ledger-v3.ts +111 -0
- package/src/commands/presence.ts +18 -11
- 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 +39 -28
- package/src/core/agents/cli.ts +242 -263
- package/src/core/agents/codex-archive-v3.ts +138 -0
- package/src/core/agents/coord-client.ts +75 -177
- package/src/core/agents/finalization.ts +120 -38
- package/src/core/agents/index.ts +5 -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 +89 -55
- package/src/core/agents/render/session-context.ts +23 -32
- 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 +98 -242
- package/src/core/agents/state/live-coordination-view.ts +290 -0
- package/src/core/agents/state/session-state.ts +143 -0
- 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 +15 -6
- package/src/core/hooks/adapter/output.ts +7 -2
- package/src/core/hooks/adapter/parse.ts +81 -36
- package/src/core/hooks/adapter/wiring.ts +119 -13
- package/src/core/hooks/cli.ts +398 -422
- package/src/core/hooks/codex-authorization.ts +253 -0
- 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 +63 -38
- package/src/core/presence/codec-digest.ts +215 -0
- package/src/core/presence/index.ts +18 -1
- 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/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 +199 -0
- 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 -65
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +0 -1
- package/dist/core/agents/state/heartbeat-projector.js +0 -527
- 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 -312
- 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 -582
- 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 -538
- package/src/core/hooks/events/ulid.ts +0 -51
- package/src/lib/docs-frontmatter-migrate.ts +0 -427
package/src/core/hooks/cli.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
* 4. Resolve instance_id (env → payload → pid-map walk).
|
|
9
9
|
* 5. Map event-name → canonical event_type.
|
|
10
10
|
* 6. Build event data from payload + resolvers (intent, transcript scan).
|
|
11
|
-
* 7.
|
|
11
|
+
* 7. Record the normalized observation in the canonical V3 ledger.
|
|
12
12
|
* 8. (Still also writes a debug breadcrumb to .harnery/debug/ for visibility.)
|
|
13
13
|
*
|
|
14
14
|
* Phase 2 ship criterion: confirms parser correctness across thousands of
|
|
@@ -21,19 +21,26 @@ import { spawnSync } from "node:child_process";
|
|
|
21
21
|
import { appendFileSync, existsSync, mkdirSync, readFileSync } from "node:fs";
|
|
22
22
|
import { dirname, join } from "node:path";
|
|
23
23
|
import { coordEnv } from "../../lib/env.ts";
|
|
24
|
-
import {
|
|
24
|
+
import { buildInstructionBundle } from "../../lib/instructions/bundle.ts";
|
|
25
|
+
import type { Adapter } from "../adapter.ts";
|
|
25
26
|
import { coordBinPath } from "../agents/coord-bin.ts";
|
|
26
|
-
import { consumeSince, writeCursor } from "../agents/events/consume.ts";
|
|
27
27
|
import {
|
|
28
28
|
type ClaimFinalizationDecision,
|
|
29
29
|
type ClaimFinalizationDescriptor,
|
|
30
30
|
classifyWriteClaimFinalization,
|
|
31
31
|
formatWriteClaimFinalizationDenial,
|
|
32
32
|
} from "../agents/finalization.ts";
|
|
33
|
-
import { evaluateStopHook } from "../agents/rules/stop-hook.ts";
|
|
34
|
-
import {
|
|
33
|
+
import { evaluateStopHook, STOP_REMEDIATION_MARKER } from "../agents/rules/stop-hook.ts";
|
|
34
|
+
import {
|
|
35
|
+
assistantTextStartsWithSessionNameBlock,
|
|
36
|
+
isSessionNameRemediationCommand,
|
|
37
|
+
sessionNameDisplayInstruction,
|
|
38
|
+
sessionNameDisplayPending,
|
|
39
|
+
toolResponseMintedSessionName,
|
|
40
|
+
} from "../agents/session-name-display.ts";
|
|
41
|
+
import { stampSessionNameSeen } from "../agents/state/heartbeat-writer.ts";
|
|
42
|
+
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.ts";
|
|
35
43
|
import { writePidmapRow } from "../agents/state/pidmap.ts";
|
|
36
|
-
import { shellMutationPaths } from "../agents/state/shell-mutation.ts";
|
|
37
44
|
import { agentsRequireGitFinalization, resolveBinName } from "../config.ts";
|
|
38
45
|
import {
|
|
39
46
|
checkpointContext,
|
|
@@ -45,8 +52,15 @@ import {
|
|
|
45
52
|
readContextState,
|
|
46
53
|
recordContextSample,
|
|
47
54
|
} from "../context/index.ts";
|
|
48
|
-
import {
|
|
49
|
-
import {
|
|
55
|
+
import { tryWriteLiveDisplayV3 } from "../events/v3/live-feed.ts";
|
|
56
|
+
import {
|
|
57
|
+
recordLiveHookSignalV3,
|
|
58
|
+
resolveLiveEventLedgerRouteV3,
|
|
59
|
+
} from "../events/v3/live-routing.ts";
|
|
60
|
+
import { captureSpanClockV3 } from "../events/v3/span-state.ts";
|
|
61
|
+
import { fetchPresence } from "../presence/index.ts";
|
|
62
|
+
import { stableScopeId } from "../workflow/scope-id.ts";
|
|
63
|
+
import { detectAdapter, shouldSkipHookAdapter } from "./adapter/detect.ts";
|
|
50
64
|
import {
|
|
51
65
|
extractBashCommand,
|
|
52
66
|
extractToolDescription,
|
|
@@ -69,21 +83,21 @@ import {
|
|
|
69
83
|
journalJanitor,
|
|
70
84
|
journalRecoveryCue,
|
|
71
85
|
playSound,
|
|
86
|
+
recordImageArtifactsV3,
|
|
72
87
|
resetSoundCounters,
|
|
73
88
|
runSessionSyncExtension,
|
|
74
|
-
runTurnSummary,
|
|
75
89
|
soundForEvent,
|
|
76
90
|
} from "./effects/index.ts";
|
|
77
|
-
import {
|
|
78
|
-
import type { Adapter } from "./events/schema.ts";
|
|
91
|
+
import { toolInputHash, toolTargetHash } from "./events/input-hash.ts";
|
|
79
92
|
import { canonicalize } from "./guard-path.ts";
|
|
80
93
|
import { adapterPidFromEnv, parsePsChainLine, selectAnchorPid } from "./resolve/anchor.ts";
|
|
81
94
|
import { findCoordRoot } from "./resolve/coord-root.ts";
|
|
82
95
|
import { extractIntentComment, resolveIntent } from "./resolve/intent.ts";
|
|
83
96
|
import { resolveOwner } from "./resolve/owner.ts";
|
|
84
97
|
import {
|
|
85
|
-
|
|
98
|
+
inspectSessionNameDisplayImmediately,
|
|
86
99
|
scanAssistantTextIncludes,
|
|
100
|
+
scanSessionNameDisplayedImmediately,
|
|
87
101
|
scanStatusBoxPresent,
|
|
88
102
|
scanTranscriptModel,
|
|
89
103
|
} from "./resolve/transcript.ts";
|
|
@@ -170,7 +184,7 @@ function logError(coordRoot: string | null, err: unknown, context: Record<string
|
|
|
170
184
|
/**
|
|
171
185
|
* Spawn `agent-coord assign-name <owner> <kind>` to mint or recover the
|
|
172
186
|
* hurricane-style name for this owner. Returns null on any failure so
|
|
173
|
-
* session.
|
|
187
|
+
* session.started emission never breaks the adapter flow.
|
|
174
188
|
*
|
|
175
189
|
* Lives at agent-hooks side (not agent-coord) to keep emitter/consumer
|
|
176
190
|
* separation: we spawn rather than import.
|
|
@@ -207,7 +221,7 @@ function assignNameViaAgentCoord(
|
|
|
207
221
|
|
|
208
222
|
/**
|
|
209
223
|
* Direct (in-process) pidmap write, avoiding the spawn overhead of going via
|
|
210
|
-
* the agent-coord CLI for every session.
|
|
224
|
+
* the agent-coord CLI for every session.started signal. Pid-map rows
|
|
211
225
|
* are essential for `harn agents whoami` ppid resolution.
|
|
212
226
|
*
|
|
213
227
|
* This used to inline its own copy of the write to keep this module's
|
|
@@ -249,6 +263,7 @@ interface BuildContext {
|
|
|
249
263
|
raw: string;
|
|
250
264
|
adapter: Adapter;
|
|
251
265
|
instanceId: string;
|
|
266
|
+
eventName: string;
|
|
252
267
|
}
|
|
253
268
|
|
|
254
269
|
function buildEventData(
|
|
@@ -257,7 +272,7 @@ function buildEventData(
|
|
|
257
272
|
): Record<string, unknown> {
|
|
258
273
|
const p = ctx.payload;
|
|
259
274
|
switch (eventType) {
|
|
260
|
-
case "session.
|
|
275
|
+
case "session.started": {
|
|
261
276
|
const adapterPlatform =
|
|
262
277
|
ctx.adapter === "claude-code"
|
|
263
278
|
? "claude-code"
|
|
@@ -265,11 +280,11 @@ function buildEventData(
|
|
|
265
280
|
? "cursor"
|
|
266
281
|
: "codex";
|
|
267
282
|
// Recorded fork lineage is NOT detected here. On claude-code a fork
|
|
268
|
-
// never fires its own session.
|
|
283
|
+
// never fires its own session.started — SessionStart fires under the
|
|
269
284
|
// PARENT's session id (source=resume) before the fork id is minted
|
|
270
285
|
// (verified 2026-08-05) — so detection at this point can only mislabel
|
|
271
286
|
// the resumed parent. The fork's new instance is caught by the
|
|
272
|
-
// tool.
|
|
287
|
+
// tool.requested heal path instead. The forkedFrom plumbing below stays
|
|
273
288
|
// for adapters that DO report a parent at session start.
|
|
274
289
|
const forkedFrom: string | undefined = undefined;
|
|
275
290
|
// Assign (or recover) name + kind via agent-coord. Idempotent: resume
|
|
@@ -290,12 +305,13 @@ function buildEventData(
|
|
|
290
305
|
if (adapterPid) {
|
|
291
306
|
writePidmapViaAgentCoord(ctx.coordRoot, adapterPid, ctx.instanceId, adapterPlatform);
|
|
292
307
|
}
|
|
308
|
+
const bundle = safeInstructionBundle(ctx.coordRoot, p?.cwd ?? process.cwd(), ctx.adapter);
|
|
293
309
|
return {
|
|
294
310
|
started_at: new Date().toISOString(),
|
|
295
311
|
cwd: p?.cwd ?? process.cwd(),
|
|
296
312
|
// Claude Code's SessionStart payload omits `model` (Codex + Cursor
|
|
297
313
|
// supply it). Fall back to the transcript, populated on `resume`, and
|
|
298
|
-
// backfilled later by `turn.
|
|
314
|
+
// backfilled later by `turn.completed` for a fresh startup session.
|
|
299
315
|
model: p?.model ?? scanTranscriptModel(p?.transcript_path),
|
|
300
316
|
pid: adapterPid,
|
|
301
317
|
source: p?.source,
|
|
@@ -303,6 +319,14 @@ function buildEventData(
|
|
|
303
319
|
name: assigned?.name,
|
|
304
320
|
kind: "session",
|
|
305
321
|
agent_id: ctx.instanceId,
|
|
322
|
+
...(bundle
|
|
323
|
+
? {
|
|
324
|
+
instruction_bundle_id: bundle.instruction_bundle_id,
|
|
325
|
+
instruction_source_id: bundle.canonical_source_id,
|
|
326
|
+
instruction_profile_root: bundle.profile_root,
|
|
327
|
+
instruction_component_count: bundle.components.length,
|
|
328
|
+
}
|
|
329
|
+
: {}),
|
|
306
330
|
// Recorded fork lineage rides the canonical event too, so full replay
|
|
307
331
|
// and derived readers converge on the same parent linkage that
|
|
308
332
|
// .name-history carries (the ADR 0017 dual-write pattern).
|
|
@@ -324,26 +348,35 @@ function buildEventData(
|
|
|
324
348
|
};
|
|
325
349
|
}
|
|
326
350
|
|
|
327
|
-
case "session.
|
|
351
|
+
case "session.ended":
|
|
328
352
|
return {
|
|
329
353
|
ended_at: new Date().toISOString(),
|
|
330
354
|
clean_exit: p?.clean_exit ?? true,
|
|
331
355
|
};
|
|
332
356
|
|
|
333
|
-
case "
|
|
357
|
+
case "turn.started": {
|
|
358
|
+
// Cursor can deliver beforeSubmitPrompt before sessionStart. Ensure that
|
|
359
|
+
// high-confidence prompt bootstrap also mints durable display identity;
|
|
360
|
+
// a later SessionStart remains idempotent.
|
|
361
|
+
if (
|
|
362
|
+
ctx.adapter === "cursor" &&
|
|
363
|
+
!readLiveCoordinationRow(ctx.coordRoot, ctx.instanceId)?.name
|
|
364
|
+
) {
|
|
365
|
+
assignNameViaAgentCoord(ctx.coordRoot, ctx.instanceId, "session");
|
|
366
|
+
}
|
|
334
367
|
const prompt = p?.prompt ?? "";
|
|
335
368
|
const { value, truncated } = clampString(prompt, 4000);
|
|
336
369
|
return { prompt_text: value, ...(truncated ? { truncated: true } : {}) };
|
|
337
370
|
}
|
|
338
371
|
|
|
339
|
-
case "turn.
|
|
372
|
+
case "turn.completed": {
|
|
340
373
|
const lastAssistantMessage = (p?.raw.last_assistant_message as string | undefined) ?? "";
|
|
341
374
|
const fileLinkTelemetry =
|
|
342
375
|
ctx.adapter === "codex"
|
|
343
376
|
? codexWslFileLinkTelemetry(ctx.coordRoot, p?.cwd, lastAssistantMessage)
|
|
344
377
|
: null;
|
|
345
378
|
return {
|
|
346
|
-
// Backfill the model for adapters that omit it at session.
|
|
379
|
+
// Backfill the model for adapters that omit it at session.started
|
|
347
380
|
// (Claude Code). The transcript is populated with assistant turns by
|
|
348
381
|
// Stop-hook time, so this resolves even for fresh `startup` sessions.
|
|
349
382
|
model: p?.model ?? scanTranscriptModel(p?.transcript_path),
|
|
@@ -357,7 +390,7 @@ function buildEventData(
|
|
|
357
390
|
// Box present if the transcript scan finds it OR the final assistant
|
|
358
391
|
// message carries the `┌─ agent-` prefix. The latter covers codex's
|
|
359
392
|
// text-only stop (box in last_assistant_message, no transcript), which
|
|
360
|
-
// the verdict now sees because agent-hook emits this turn.
|
|
393
|
+
// the verdict now sees because agent-hook emits this turn.completed itself
|
|
361
394
|
// (the previous path passed those via the no-history fail-open).
|
|
362
395
|
status_box_present:
|
|
363
396
|
scanStatusBoxPresent(p?.transcript_path) || lastAssistantMessage.includes("┌─ agent-"),
|
|
@@ -377,15 +410,19 @@ function buildEventData(
|
|
|
377
410
|
// and which name that refers to. Reported on every stop while a name
|
|
378
411
|
// exists (the stop-hook.session_name verdict reads it per turn); the
|
|
379
412
|
// transcript scan itself stops once the name has been sighted.
|
|
380
|
-
...sessionNamePresence(ctx.coordRoot, ctx.instanceId,
|
|
381
|
-
|
|
413
|
+
...sessionNamePresence(ctx.coordRoot, ctx.instanceId, (name) =>
|
|
414
|
+
scanSessionNameDisplayedImmediately(
|
|
415
|
+
p?.transcript_path,
|
|
416
|
+
name,
|
|
417
|
+
assistantTextStartsWithSessionNameBlock,
|
|
418
|
+
),
|
|
382
419
|
),
|
|
383
420
|
...(fileLinkTelemetry ?? {}),
|
|
384
421
|
stop_hook_active: p?.stop_hook_active,
|
|
385
422
|
};
|
|
386
423
|
}
|
|
387
424
|
|
|
388
|
-
case "
|
|
425
|
+
case "agent.started": {
|
|
389
426
|
const subagentCallId =
|
|
390
427
|
(p?.raw.subagent_id as string | undefined) ?? (p?.raw.agent_id as string | undefined);
|
|
391
428
|
// Subagents inherit parent's name via the resolve-name session_id path
|
|
@@ -406,14 +443,14 @@ function buildEventData(
|
|
|
406
443
|
};
|
|
407
444
|
}
|
|
408
445
|
|
|
409
|
-
case "
|
|
446
|
+
case "agent.completed": {
|
|
410
447
|
const status = p?.exit_status;
|
|
411
448
|
const normalized: "ok" | "error" | "interrupted" =
|
|
412
449
|
status === "error" || status === "interrupted" ? status : "ok";
|
|
413
450
|
return { exit_status: normalized, reason: p?.reason };
|
|
414
451
|
}
|
|
415
452
|
|
|
416
|
-
case "tool.
|
|
453
|
+
case "tool.requested": {
|
|
417
454
|
const toolName = p?.tool_name ?? "unknown";
|
|
418
455
|
const command = extractBashCommand(toolName, p?.tool_input);
|
|
419
456
|
const description = extractToolDescription(p?.tool_input);
|
|
@@ -428,6 +465,8 @@ function buildEventData(
|
|
|
428
465
|
return {
|
|
429
466
|
tool_name: toolName,
|
|
430
467
|
tool_input: clamped.value,
|
|
468
|
+
input_hash: toolInputHash(toolName, p?.tool_input ?? null),
|
|
469
|
+
target_hash: toolTargetHash(toolName, p?.tool_input ?? null),
|
|
431
470
|
intent,
|
|
432
471
|
intent_source: source,
|
|
433
472
|
tool_use_id: p?.tool_use_id,
|
|
@@ -435,32 +474,38 @@ function buildEventData(
|
|
|
435
474
|
};
|
|
436
475
|
}
|
|
437
476
|
|
|
438
|
-
case "
|
|
439
|
-
const
|
|
440
|
-
const
|
|
477
|
+
case "wait.started": {
|
|
478
|
+
const description = extractToolDescription(p?.tool_input);
|
|
479
|
+
const reason = description ? clampString(description, 500).value : undefined;
|
|
441
480
|
return {
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
duration_ms: 0, // Phase 3 pairs pre/post via tool_use_id
|
|
446
|
-
tool_use_id: p?.tool_use_id,
|
|
447
|
-
...(summary.truncated ? { truncated: true } : {}),
|
|
481
|
+
request_kind: "permission",
|
|
482
|
+
tool_name: p?.tool_name,
|
|
483
|
+
...(reason ? { reason } : {}),
|
|
448
484
|
};
|
|
449
485
|
}
|
|
450
486
|
|
|
451
|
-
case "tool.
|
|
487
|
+
case "tool.completed": {
|
|
452
488
|
const toolName = p?.tool_name ?? "unknown";
|
|
453
489
|
const summary = summarizeOutput(p?.tool_response);
|
|
454
|
-
return
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
490
|
+
return ctx.eventName === "post-tool-use-failure"
|
|
491
|
+
? {
|
|
492
|
+
tool_name: toolName,
|
|
493
|
+
error: summary.summary,
|
|
494
|
+
duration_ms: 0,
|
|
495
|
+
tool_use_id: p?.tool_use_id,
|
|
496
|
+
...(summary.truncated ? { truncated: true } : {}),
|
|
497
|
+
}
|
|
498
|
+
: {
|
|
499
|
+
tool_name: toolName,
|
|
500
|
+
output_summary: summary.summary,
|
|
501
|
+
exit_status: "ok" as const,
|
|
502
|
+
duration_ms: 0,
|
|
503
|
+
tool_use_id: p?.tool_use_id,
|
|
504
|
+
...(summary.truncated ? { truncated: true } : {}),
|
|
505
|
+
};
|
|
461
506
|
}
|
|
462
507
|
|
|
463
|
-
case "context.
|
|
508
|
+
case "context.compaction_started": {
|
|
464
509
|
const metadata = objectRecord(p?.raw.compact_metadata);
|
|
465
510
|
return {
|
|
466
511
|
trigger: stringField(p?.raw.trigger) ?? stringField(metadata?.trigger),
|
|
@@ -471,7 +516,7 @@ function buildEventData(
|
|
|
471
516
|
};
|
|
472
517
|
}
|
|
473
518
|
|
|
474
|
-
case "context.
|
|
519
|
+
case "context.compaction_completed": {
|
|
475
520
|
const metadata = objectRecord(p?.raw.compact_metadata);
|
|
476
521
|
return {
|
|
477
522
|
trigger: stringField(p?.raw.trigger) ?? stringField(metadata?.trigger),
|
|
@@ -488,6 +533,15 @@ function buildEventData(
|
|
|
488
533
|
}
|
|
489
534
|
}
|
|
490
535
|
|
|
536
|
+
function safeInstructionBundle(coordRoot: string, cwd: string, adapter: Adapter) {
|
|
537
|
+
try {
|
|
538
|
+
return buildInstructionBundle({ coordRoot, cwd, adapter });
|
|
539
|
+
} catch (err) {
|
|
540
|
+
logError(coordRoot, err, { phase: "instruction-bundle-identity" });
|
|
541
|
+
return null;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
|
|
491
545
|
function objectRecord(value: unknown): Record<string, unknown> | undefined {
|
|
492
546
|
return typeof value === "object" && value !== null && !Array.isArray(value)
|
|
493
547
|
? (value as Record<string, unknown>)
|
|
@@ -503,10 +557,38 @@ function numberField(value: unknown): number | undefined {
|
|
|
503
557
|
}
|
|
504
558
|
|
|
505
559
|
async function main(): Promise<number> {
|
|
560
|
+
const hookStartedAt = performance.now();
|
|
561
|
+
const hookClock = captureSpanClockV3();
|
|
506
562
|
const { eventName, extra } = parseArgv(process.argv.slice(2));
|
|
507
563
|
const adapter = detectAdapter(process.argv.slice(2));
|
|
508
564
|
const raw = await readStdin();
|
|
509
565
|
|
|
566
|
+
// Cursor executes the Claude Code project hooks too on hosts wired for both
|
|
567
|
+
// adapters, piping them its own payload (identifiable by the top-level
|
|
568
|
+
// cursor_version envelope field). That stray `--adapter claude-code`
|
|
569
|
+
// dispatch must not record (twin generation) or play Claude-Code-only
|
|
570
|
+
// sounds, so it bails here, before every effect. Cursor's own
|
|
571
|
+
// `--adapter cursor` dispatch of the same payload carries the session.
|
|
572
|
+
if (shouldSkipHookAdapter(adapter, raw)) {
|
|
573
|
+
if (coordEnv("AGENT_COORD_OFF") !== "1") {
|
|
574
|
+
const coordRoot = findCoordRoot(process.cwd());
|
|
575
|
+
if (coordRoot) {
|
|
576
|
+
appendDebug(coordRoot, {
|
|
577
|
+
ts: new Date().toISOString(),
|
|
578
|
+
event_name: eventName,
|
|
579
|
+
adapter,
|
|
580
|
+
extra_argv: extra,
|
|
581
|
+
payload_bytes: raw.length,
|
|
582
|
+
cwd: process.cwd(),
|
|
583
|
+
pid: process.pid,
|
|
584
|
+
ppid: process.ppid,
|
|
585
|
+
skipped: "cursor-payload-claude-adapter",
|
|
586
|
+
});
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
return 0;
|
|
590
|
+
}
|
|
591
|
+
|
|
510
592
|
// Kill-switch-INDEPENDENT effects: notification sounds fire BEFORE the
|
|
511
593
|
// HARNERY_AGENT_COORD_OFF gate so audible feedback survives incident-triage
|
|
512
594
|
// bypass: sound playback happens before the kill-switch bailout.
|
|
@@ -536,6 +618,7 @@ async function main(): Promise<number> {
|
|
|
536
618
|
|
|
537
619
|
const coordRoot = findCoordRoot(process.cwd());
|
|
538
620
|
if (!coordRoot) return 0;
|
|
621
|
+
const ledgerRoute = resolveLiveEventLedgerRouteV3(coordRoot);
|
|
539
622
|
|
|
540
623
|
// Always log a breadcrumb, useful when an event_type maps to null or owner
|
|
541
624
|
// resolution fails. Stays cheap (one append) and self-prunes via repo log
|
|
@@ -563,7 +646,10 @@ async function main(): Promise<number> {
|
|
|
563
646
|
}
|
|
564
647
|
|
|
565
648
|
const payload = parsePayload(raw, adapter);
|
|
566
|
-
const owner = resolveOwner({
|
|
649
|
+
const owner = resolveOwner({
|
|
650
|
+
payload: payload?.raw ?? null,
|
|
651
|
+
coordRoot,
|
|
652
|
+
});
|
|
567
653
|
if (!owner) {
|
|
568
654
|
appendDebug(coordRoot, {
|
|
569
655
|
...debugBase,
|
|
@@ -581,25 +667,108 @@ async function main(): Promise<number> {
|
|
|
581
667
|
raw,
|
|
582
668
|
adapter,
|
|
583
669
|
instanceId: owner.instance_id,
|
|
670
|
+
eventName,
|
|
584
671
|
});
|
|
672
|
+
const turnRitual =
|
|
673
|
+
norm.event_type === "turn.completed"
|
|
674
|
+
? {
|
|
675
|
+
status_box_present: data.status_box_present === true,
|
|
676
|
+
status_box_present_strict: data.status_box_present_strict === true,
|
|
677
|
+
session_name_required: typeof data.session_name_present_for === "string",
|
|
678
|
+
session_name_present: data.session_name_present === true,
|
|
679
|
+
}
|
|
680
|
+
: undefined;
|
|
681
|
+
const stopRemediation =
|
|
682
|
+
norm.event_type === "turn.started" &&
|
|
683
|
+
typeof data.prompt_text === "string" &&
|
|
684
|
+
data.prompt_text.includes(STOP_REMEDIATION_MARKER);
|
|
585
685
|
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
686
|
+
if (ledgerRoute.state === "blocked") {
|
|
687
|
+
appendDebug(coordRoot, {
|
|
688
|
+
...debugBase,
|
|
689
|
+
skipped: "v3-control-blocked",
|
|
690
|
+
reason: ledgerRoute.reason,
|
|
691
|
+
event_type: norm.event_type,
|
|
692
|
+
owner_source: owner.source,
|
|
693
|
+
});
|
|
694
|
+
return 0;
|
|
695
|
+
}
|
|
696
|
+
|
|
697
|
+
let capturedImages: ReturnType<typeof captureImages> = [];
|
|
698
|
+
if (
|
|
699
|
+
norm.event_type === "tool.requested" ||
|
|
700
|
+
(norm.event_type === "tool.completed" && eventName === "post-tool-use")
|
|
701
|
+
) {
|
|
702
|
+
try {
|
|
703
|
+
capturedImages = captureImages(coordRoot, norm.event_type, payload);
|
|
704
|
+
} catch (err) {
|
|
705
|
+
logError(coordRoot, err, { phase: "image-capture" });
|
|
706
|
+
}
|
|
707
|
+
}
|
|
708
|
+
|
|
709
|
+
const v3Result = recordLiveHookSignalV3({
|
|
710
|
+
coordRoot,
|
|
711
|
+
route: ledgerRoute,
|
|
712
|
+
eventName,
|
|
713
|
+
payload,
|
|
593
714
|
adapter,
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
715
|
+
instanceId: owner.instance_id,
|
|
716
|
+
...(coordEnv("WORKFLOW_CHILD") === "1" && coordEnv("WORKFLOW_RUN_ID")
|
|
717
|
+
? {
|
|
718
|
+
run_id: stableScopeId("run", coordEnv("WORKFLOW_RUN_ID")!),
|
|
719
|
+
workflow_id: stableScopeId("wf", coordEnv("WORKFLOW_RUN_ID")!),
|
|
720
|
+
...(coordEnv("WORKFLOW_AGENT_ID")
|
|
721
|
+
? { workflow_agent_id: coordEnv("WORKFLOW_AGENT_ID") }
|
|
722
|
+
: {}),
|
|
723
|
+
}
|
|
724
|
+
: {}),
|
|
725
|
+
...(adapter === "codex" && isWslUncPath(payload?.cwd) ? { bridge: "codex-wsl" as const } : {}),
|
|
726
|
+
hook_name: eventName,
|
|
727
|
+
hook_duration_ms: Math.max(0, Math.floor(performance.now() - hookStartedAt)),
|
|
728
|
+
monotonic_ns: hookClock.monotonic_ns,
|
|
729
|
+
...(stopRemediation ? { stop_remediation: true } : {}),
|
|
730
|
+
...(turnRitual ? { turn_ritual: turnRitual } : {}),
|
|
731
|
+
...(coordEnv("EXPERIMENT_DEFER_V3_DRAIN") === "1" ? { defer_drain: true } : {}),
|
|
732
|
+
});
|
|
733
|
+
const v3EventId =
|
|
734
|
+
v3Result && "event" in v3Result
|
|
735
|
+
? v3Result.event.event_id
|
|
736
|
+
: v3Result && "event_id" in v3Result
|
|
737
|
+
? v3Result.event_id
|
|
738
|
+
: undefined;
|
|
739
|
+
|
|
740
|
+
if (v3Result?.state === "recorded" && capturedImages.length > 0) {
|
|
741
|
+
try {
|
|
742
|
+
recordImageArtifactsV3(coordRoot, v3Result.event, capturedImages);
|
|
743
|
+
} catch (err) {
|
|
744
|
+
logError(coordRoot, err, { phase: "image-artifact-observation" });
|
|
745
|
+
}
|
|
746
|
+
}
|
|
747
|
+
|
|
748
|
+
if (
|
|
749
|
+
norm.event_type === "tool.requested" &&
|
|
750
|
+
v3Result &&
|
|
751
|
+
v3Result.state === "recorded" &&
|
|
752
|
+
"generation_id" in v3Result.event.scope
|
|
753
|
+
) {
|
|
754
|
+
const intent = typeof data.intent === "string" ? data.intent : undefined;
|
|
755
|
+
if (intent && intent !== "(no intent)") {
|
|
756
|
+
tryWriteLiveDisplayV3(coordRoot, {
|
|
757
|
+
generation_id: v3Result.event.scope.generation_id,
|
|
758
|
+
event_id: v3Result.event.event_id,
|
|
759
|
+
...(typeof data.tool_name === "string" ? { executable: data.tool_name } : {}),
|
|
760
|
+
intent_display: intent,
|
|
761
|
+
});
|
|
762
|
+
}
|
|
763
|
+
}
|
|
597
764
|
|
|
598
765
|
appendDebug(coordRoot, {
|
|
599
766
|
...debugBase,
|
|
600
767
|
event_type: norm.event_type,
|
|
601
768
|
owner_source: owner.source,
|
|
602
|
-
|
|
769
|
+
...(v3EventId ? { event_v3_id: v3EventId } : {}),
|
|
770
|
+
...(v3Result ? { event_v3_state: v3Result.state } : {}),
|
|
771
|
+
...(v3Result && "reason" in v3Result ? { event_v3_reason: v3Result.reason } : {}),
|
|
603
772
|
});
|
|
604
773
|
|
|
605
774
|
// Context telemetry is opportunistic and truthful: only persist a sample
|
|
@@ -616,22 +785,7 @@ async function main(): Promise<number> {
|
|
|
616
785
|
});
|
|
617
786
|
if (sample) {
|
|
618
787
|
const recorded = recordContextSample(coordRoot, owner.instance_id, sample);
|
|
619
|
-
|
|
620
|
-
emit(coordRoot, {
|
|
621
|
-
event_type: "context.sampled",
|
|
622
|
-
instance_id: owner.instance_id,
|
|
623
|
-
session_id: sessionId,
|
|
624
|
-
adapter,
|
|
625
|
-
data: {
|
|
626
|
-
model: sample.model,
|
|
627
|
-
used_tokens: sample.used_tokens,
|
|
628
|
-
window_tokens: sample.window_tokens,
|
|
629
|
-
used_percent: sample.used_percent,
|
|
630
|
-
telemetry_source: sample.source,
|
|
631
|
-
confidence: sample.confidence,
|
|
632
|
-
},
|
|
633
|
-
});
|
|
634
|
-
}
|
|
788
|
+
void recorded;
|
|
635
789
|
}
|
|
636
790
|
} catch (err) {
|
|
637
791
|
logError(coordRoot, err, { phase: "context-sample" });
|
|
@@ -641,7 +795,7 @@ async function main(): Promise<number> {
|
|
|
641
795
|
// A native pre-compaction signal is the safest available point to capture
|
|
642
796
|
// external work state. The operation is idempotent until recovery, so a
|
|
643
797
|
// adapter retry cannot create a storm of near-identical capsules.
|
|
644
|
-
if (norm.event_type === "context.
|
|
798
|
+
if (norm.event_type === "context.compaction_started") {
|
|
645
799
|
try {
|
|
646
800
|
const checkpoint = checkpointContext(coordRoot, {
|
|
647
801
|
sessionId,
|
|
@@ -651,25 +805,13 @@ async function main(): Promise<number> {
|
|
|
651
805
|
reason: "pre_compact",
|
|
652
806
|
model: payload?.model,
|
|
653
807
|
});
|
|
654
|
-
|
|
655
|
-
event_type: "context.checkpoint.created",
|
|
656
|
-
instance_id: owner.instance_id,
|
|
657
|
-
session_id: sessionId,
|
|
658
|
-
adapter,
|
|
659
|
-
data: {
|
|
660
|
-
capsule_id: checkpoint.capsule.capsule_id,
|
|
661
|
-
generation: checkpoint.capsule.generation,
|
|
662
|
-
path: checkpoint.state.latest_capsule ?? "",
|
|
663
|
-
reason: checkpoint.capsule.reason,
|
|
664
|
-
reused: checkpoint.reused,
|
|
665
|
-
},
|
|
666
|
-
});
|
|
808
|
+
void checkpoint;
|
|
667
809
|
} catch (err) {
|
|
668
810
|
logError(coordRoot, err, { phase: "context-checkpoint" });
|
|
669
811
|
}
|
|
670
812
|
}
|
|
671
813
|
|
|
672
|
-
if (norm.event_type === "context.
|
|
814
|
+
if (norm.event_type === "context.compaction_completed") {
|
|
673
815
|
try {
|
|
674
816
|
markContextCompactionCompleted(coordRoot, {
|
|
675
817
|
sessionId,
|
|
@@ -685,29 +827,15 @@ async function main(): Promise<number> {
|
|
|
685
827
|
// systemMessage JSON (peer table + wiring check + council invites).
|
|
686
828
|
// Adapter-agnostic since v0.5.0; replaces the previous bash UX layer
|
|
687
829
|
// and the equivalent per-adapter bash session_start handlers.
|
|
688
|
-
if (norm.event_type === "session.
|
|
830
|
+
if (norm.event_type === "session.started") {
|
|
689
831
|
// Effect (claude-code): prune stale journal archives + sweep orphans.
|
|
690
832
|
// The recovery-cue is merged into the
|
|
691
833
|
// session-start additionalContext inside emitSessionStartSystemMessage.
|
|
692
834
|
if (adapter === "claude-code") journalJanitor(coordRoot);
|
|
693
|
-
|
|
694
|
-
// agnostic, cheap (one readdir), fail-soft. Paired with journalJanitor as a
|
|
695
|
-
// session-start "tidy the coord layer" step.
|
|
696
|
-
try {
|
|
697
|
-
imageJanitor(coordRoot);
|
|
698
|
-
} catch (err) {
|
|
699
|
-
logError(coordRoot, err, { phase: "session-start-image-janitor" });
|
|
700
|
-
}
|
|
835
|
+
imageJanitor(coordRoot);
|
|
701
836
|
let recovery: PreparedContextRecovery | null = null;
|
|
702
837
|
if (payload?.source === "compact") {
|
|
703
838
|
try {
|
|
704
|
-
emit(coordRoot, {
|
|
705
|
-
event_type: "context.compaction.completed",
|
|
706
|
-
instance_id: owner.instance_id,
|
|
707
|
-
session_id: sessionId,
|
|
708
|
-
adapter,
|
|
709
|
-
data: { trigger: "auto" },
|
|
710
|
-
});
|
|
711
839
|
markContextCompactionCompleted(coordRoot, {
|
|
712
840
|
sessionId,
|
|
713
841
|
instanceId: owner.instance_id,
|
|
@@ -731,25 +859,15 @@ async function main(): Promise<number> {
|
|
|
731
859
|
recovery?.briefing ?? "",
|
|
732
860
|
);
|
|
733
861
|
if (injected && recovery) {
|
|
734
|
-
completeRecoveryInjection(
|
|
735
|
-
coordRoot,
|
|
736
|
-
owner.instance_id,
|
|
737
|
-
sessionId,
|
|
738
|
-
adapter,
|
|
739
|
-
recovery,
|
|
740
|
-
"SessionStart",
|
|
741
|
-
);
|
|
862
|
+
completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
|
|
742
863
|
}
|
|
743
864
|
} catch (err) {
|
|
744
865
|
logError(coordRoot, err, { phase: "session-start-systemMessage" });
|
|
745
866
|
}
|
|
746
|
-
//
|
|
747
|
-
//
|
|
748
|
-
// When a relay is configured, also make sure the live-socket daemon runs.
|
|
867
|
+
// Pull advisory cross-machine presence. V3 never publishes from the
|
|
868
|
+
// disposable heartbeat cache.
|
|
749
869
|
try {
|
|
750
|
-
publishPresence(coordRoot);
|
|
751
870
|
fetchPresence(coordRoot);
|
|
752
|
-
ensureRelayDaemon(coordRoot);
|
|
753
871
|
} catch (err) {
|
|
754
872
|
logError(coordRoot, err, { phase: "session-start-presence" });
|
|
755
873
|
}
|
|
@@ -757,7 +875,7 @@ async function main(): Promise<number> {
|
|
|
757
875
|
|
|
758
876
|
// Phase 8: SessionEnd cleanup: delete heartbeat + pid-map rows. Adapter-
|
|
759
877
|
// agnostic since v0.5.0.
|
|
760
|
-
if (norm.event_type === "session.
|
|
878
|
+
if (norm.event_type === "session.ended") {
|
|
761
879
|
try {
|
|
762
880
|
cleanupSessionEnd(coordRoot, owner.instance_id, (data.reason as string) ?? "unknown");
|
|
763
881
|
} catch (err) {
|
|
@@ -769,19 +887,12 @@ async function main(): Promise<number> {
|
|
|
769
887
|
journalArchive(coordRoot, owner.instance_id);
|
|
770
888
|
runSessionSyncExtension(coordRoot, true);
|
|
771
889
|
}
|
|
772
|
-
// Presence: publish the post-cleanup state so peers see this session gone
|
|
773
|
-
// promptly rather than waiting out the remote-stale window.
|
|
774
|
-
try {
|
|
775
|
-
publishPresence(coordRoot);
|
|
776
|
-
} catch (err) {
|
|
777
|
-
logError(coordRoot, err, { phase: "session-end-presence" });
|
|
778
|
-
}
|
|
779
890
|
}
|
|
780
891
|
|
|
781
892
|
// Phase 8: SubagentStart: sync-project to create the subagent heartbeat,
|
|
782
893
|
// log the lifecycle event, and emit a context message announcing the
|
|
783
894
|
// subagent (claude-code + cursor; codex doesn't fan out subagents today).
|
|
784
|
-
if (norm.event_type === "
|
|
895
|
+
if (norm.event_type === "agent.started") {
|
|
785
896
|
try {
|
|
786
897
|
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
787
898
|
if (existsSync(agentCoordBin)) {
|
|
@@ -808,7 +919,7 @@ async function main(): Promise<number> {
|
|
|
808
919
|
}
|
|
809
920
|
|
|
810
921
|
// Phase 8: SubagentStop: delete subagent heartbeat + log.
|
|
811
|
-
if (norm.event_type === "
|
|
922
|
+
if (norm.event_type === "agent.completed") {
|
|
812
923
|
try {
|
|
813
924
|
cleanupSessionEnd(coordRoot, owner.instance_id, (data.reason as string) ?? "unknown");
|
|
814
925
|
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
@@ -831,7 +942,7 @@ async function main(): Promise<number> {
|
|
|
831
942
|
|
|
832
943
|
// Phase 8: UserPromptSubmit: render dedup'd peer table + council pending
|
|
833
944
|
// and emit the adapter-shaped systemMessage JSON. Adapter-agnostic since v0.5.0.
|
|
834
|
-
if (norm.event_type === "
|
|
945
|
+
if (norm.event_type === "turn.started") {
|
|
835
946
|
// Effects (claude-code): reset per-turn sound rate-limit counters + run
|
|
836
947
|
// presence detection on the prompt.
|
|
837
948
|
if (adapter === "claude-code") {
|
|
@@ -872,81 +983,27 @@ async function main(): Promise<number> {
|
|
|
872
983
|
recovery?.briefing ?? "",
|
|
873
984
|
);
|
|
874
985
|
if (injected && recovery) {
|
|
875
|
-
completeRecoveryInjection(
|
|
876
|
-
coordRoot,
|
|
877
|
-
owner.instance_id,
|
|
878
|
-
sessionId,
|
|
879
|
-
adapter,
|
|
880
|
-
recovery,
|
|
881
|
-
"UserPromptSubmit",
|
|
882
|
-
);
|
|
986
|
+
completeRecoveryInjection(coordRoot, owner.instance_id, sessionId, recovery);
|
|
883
987
|
}
|
|
884
988
|
} catch (err) {
|
|
885
989
|
logError(coordRoot, err, { phase: "user-prompt-submit-systemMessage" });
|
|
886
990
|
}
|
|
887
991
|
}
|
|
888
992
|
|
|
889
|
-
// turn.
|
|
993
|
+
// turn.completed: telemetry, then the stop verdict. The
|
|
890
994
|
// verdict + codex-replay previously lived in the per-adapter shell adapters;
|
|
891
995
|
// agent-hook owns them now. Runs on the normal "stop" event only;
|
|
892
996
|
// "stop-failure" (API error) gets no gate, matching the previous
|
|
893
997
|
// stop vs stop-failure split.
|
|
894
|
-
if (norm.event_type === "turn.
|
|
895
|
-
//
|
|
896
|
-
// the status_checked / task_set / status_box_present evidence (codex
|
|
897
|
-
// doesn't emit those live; this re-emits turn.stop after agent-hook's own,
|
|
898
|
-
// so the verdict reads the replay's box signal as the latest).
|
|
899
|
-
if (adapter === "codex" && payload?.transcript_path && existsSync(payload.transcript_path)) {
|
|
900
|
-
try {
|
|
901
|
-
replayCodexJsonl({
|
|
902
|
-
coordRoot,
|
|
903
|
-
jsonlPath: payload.transcript_path,
|
|
904
|
-
sessionId,
|
|
905
|
-
instanceId: owner.instance_id,
|
|
906
|
-
lastAssistantMessage: (payload.raw.last_assistant_message as string | undefined) ?? "",
|
|
907
|
-
});
|
|
908
|
-
} catch (err) {
|
|
909
|
-
logError(coordRoot, err, { phase: "codex-replay" });
|
|
910
|
-
}
|
|
911
|
-
}
|
|
912
|
-
|
|
913
|
-
// CC effects: rate-limited session-telemetry sync + turn-summary Haiku
|
|
914
|
-
// auto-summary.
|
|
998
|
+
if (norm.event_type === "turn.completed" && eventName === "stop") {
|
|
999
|
+
// Claude Code session telemetry sync remains an independent side effect.
|
|
915
1000
|
if (adapter === "claude-code") {
|
|
916
1001
|
runSessionSyncExtension(coordRoot, false);
|
|
917
|
-
runTurnSummary(coordRoot, owner.instance_id, sessionId, payload?.transcript_path);
|
|
918
|
-
}
|
|
919
|
-
|
|
920
|
-
// Master-state heartbeat projection. Drains events.ndjson since the last
|
|
921
|
-
// cursor → per-owner heartbeats. Was a SECOND binary (`agent-coord project`)
|
|
922
|
-
// pinned to Claude Code Stop only; folded in here so it (a) is one
|
|
923
|
-
// entry per event like everything else and (b) fires on EVERY adapter's stop,
|
|
924
|
-
// not just CC. Runs unconditionally before the verdict's possible exit-2 return
|
|
925
|
-
// (the events are real regardless of whether the agent gets nagged), and after
|
|
926
|
-
// codex-replay above so codex's replayed events are included in the drain.
|
|
927
|
-
// Not an emitter (consumes + writes heartbeats), so no emitter/consumer conflict.
|
|
928
|
-
try {
|
|
929
|
-
const result = consumeSince(coordRoot);
|
|
930
|
-
projectHeartbeats(coordRoot, result.events);
|
|
931
|
-
if (result.lastEventId) writeCursor(coordRoot, result.lastEventId);
|
|
932
|
-
} catch (err) {
|
|
933
|
-
logError(coordRoot, err, { phase: "stop-projection" });
|
|
934
1002
|
}
|
|
935
1003
|
|
|
936
|
-
//
|
|
937
|
-
//
|
|
938
|
-
//
|
|
939
|
-
// re-ensured here too — it self-exits on idle, and the next turn revives it.
|
|
940
|
-
try {
|
|
941
|
-
publishPresence(coordRoot);
|
|
942
|
-
ensureRelayDaemon(coordRoot);
|
|
943
|
-
} catch (err) {
|
|
944
|
-
logError(coordRoot, err, { phase: "stop-presence" });
|
|
945
|
-
}
|
|
946
|
-
|
|
947
|
-
// Stop verdict (status-box + set-task gate). Direct in-process call: the
|
|
948
|
-
// rule lives in harnery. agent-hook already emitted this turn.stop (with
|
|
949
|
-
// status_box_present) above, so the evidence is in the stream.
|
|
1004
|
+
// Stop verdict (V3 ritual + task/status gate). Direct in-process call: the
|
|
1005
|
+
// rule lives in Harnery. agent-hook already emitted this turn.completed
|
|
1006
|
+
// with privacy-safe ritual observations, so the evidence is in the stream.
|
|
950
1007
|
const verdict = evaluateStopHook(coordRoot, {
|
|
951
1008
|
rule: "stop-hook",
|
|
952
1009
|
instance_id: owner.instance_id,
|
|
@@ -956,13 +1013,28 @@ async function main(): Promise<number> {
|
|
|
956
1013
|
workflow_child: coordEnv("WORKFLOW_CHILD") === "1",
|
|
957
1014
|
});
|
|
958
1015
|
if (!verdict.allow) {
|
|
959
|
-
// Adapter-aware enforcement channel: Claude Code
|
|
960
|
-
//
|
|
961
|
-
//
|
|
962
|
-
// writes the right shape and returns the exit code to use.
|
|
1016
|
+
// Adapter-aware enforcement channel: Claude Code honors exit-2 + stderr
|
|
1017
|
+
// as a turn block; Cursor ignores exit codes and re-prompts only via a
|
|
1018
|
+
// `followup_message` it auto-submits. Codex returned observe-only above.
|
|
1019
|
+
// emitStopBlock writes the right shape and returns the exit code to use.
|
|
963
1020
|
const { emitStopBlock } = await import("./adapter/output.ts");
|
|
964
1021
|
return emitStopBlock(adapter, verdict, coordRoot);
|
|
965
1022
|
}
|
|
1023
|
+
|
|
1024
|
+
// An explicit end requested from inside this turn cannot be authoritative
|
|
1025
|
+
// until the adapter has committed turn.completed above. Reconcile only
|
|
1026
|
+
// when such a request exists; any later real work cancels it in the
|
|
1027
|
+
// finalizer instead of being terminated underneath the agent.
|
|
1028
|
+
try {
|
|
1029
|
+
const { hasPendingExplicitSessionEndV3, reconcileSessionFinalizationV3 } = await import(
|
|
1030
|
+
"../agents/session-finalizer-v3.ts"
|
|
1031
|
+
);
|
|
1032
|
+
if (hasPendingExplicitSessionEndV3(coordRoot)) {
|
|
1033
|
+
reconcileSessionFinalizationV3(coordRoot);
|
|
1034
|
+
}
|
|
1035
|
+
} catch (err) {
|
|
1036
|
+
logError(coordRoot, err, { phase: "stop-explicit-session-finalization" });
|
|
1037
|
+
}
|
|
966
1038
|
}
|
|
967
1039
|
|
|
968
1040
|
// Phase 7: PreToolUse: heartbeat + pid-map self-heal on every tool call.
|
|
@@ -974,41 +1046,35 @@ async function main(): Promise<number> {
|
|
|
974
1046
|
// side-by-side in the previous pre-tool-use adapter. The Phase 4-6 refactor
|
|
975
1047
|
// preserved the heartbeat half but dropped the pid-map half; the pid-map
|
|
976
1048
|
// call was restored here afterward.
|
|
977
|
-
if (norm.event_type === "tool.
|
|
1049
|
+
if (norm.event_type === "tool.requested") {
|
|
978
1050
|
try {
|
|
979
1051
|
// Recorded fork lineage, heal-path flavor. A forked CC conversation
|
|
980
|
-
// never fires its own session.
|
|
1052
|
+
// never fires its own session.started (SessionStart fires under the
|
|
981
1053
|
// PARENT's session id with source=resume, before the fork id is
|
|
982
1054
|
// minted; verified 2026-08-05), so the fork's new instance first
|
|
983
1055
|
// materializes right here. Gate detection on "no heartbeat yet" so the
|
|
984
1056
|
// transcript scan runs once per instance lifetime, not per tool call.
|
|
985
|
-
let forkedFrom: string | undefined;
|
|
986
|
-
if (
|
|
987
|
-
adapter === "claude-code" &&
|
|
988
|
-
payload?.transcript_path &&
|
|
989
|
-
!existsSync(join(coordRoot, ".harnery", "active", `${owner.instance_id}.json`))
|
|
990
|
-
) {
|
|
991
|
-
forkedFrom = detectForkParent(payload.transcript_path, owner.instance_id);
|
|
992
|
-
}
|
|
993
|
-
healHeartbeatViaCli(coordRoot, owner.instance_id, sessionId, adapter, forkedFrom);
|
|
994
1057
|
refreshPidmap(coordRoot, owner.instance_id, adapter, payload?.pid);
|
|
995
1058
|
} catch (err) {
|
|
996
1059
|
logError(coordRoot, err, { phase: "pre-tool-use-heal" });
|
|
997
1060
|
}
|
|
998
1061
|
|
|
999
|
-
//
|
|
1000
|
-
//
|
|
1062
|
+
// The suggested name is a pending display latch. The set-task call itself
|
|
1063
|
+
// runs before a name exists; every later tool waits until the exact block
|
|
1064
|
+
// is the first assistant text after the mint result. Cursor supplies
|
|
1065
|
+
// agent_message directly; Claude Code and Codex are resolved from their
|
|
1066
|
+
// JSONL transcripts. Later commentary must not erase an already-correct
|
|
1067
|
+
// display, and an unreadable transcript must not deadlock every tool.
|
|
1001
1068
|
try {
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
payload,
|
|
1006
|
-
instanceId: owner.instance_id,
|
|
1007
|
-
sessionId,
|
|
1069
|
+
const displayAllowed = await enforcePendingSessionNameDisplay(
|
|
1070
|
+
coordRoot,
|
|
1071
|
+
owner.instance_id,
|
|
1008
1072
|
adapter,
|
|
1009
|
-
|
|
1073
|
+
payload,
|
|
1074
|
+
);
|
|
1075
|
+
if (!displayAllowed) return 0;
|
|
1010
1076
|
} catch (err) {
|
|
1011
|
-
logError(coordRoot, err, { phase: "pre-tool-use-
|
|
1077
|
+
logError(coordRoot, err, { phase: "pre-tool-use-session-name" });
|
|
1012
1078
|
}
|
|
1013
1079
|
|
|
1014
1080
|
// Windows-native Codex + WSL UNC only: block the one cross-shell shape
|
|
@@ -1022,13 +1088,6 @@ async function main(): Promise<number> {
|
|
|
1022
1088
|
toolInput: payload?.tool_input,
|
|
1023
1089
|
});
|
|
1024
1090
|
if (unsafeShellReason) {
|
|
1025
|
-
emit(coordRoot, {
|
|
1026
|
-
event_type: "decision.block",
|
|
1027
|
-
instance_id: owner.instance_id,
|
|
1028
|
-
session_id: sessionId,
|
|
1029
|
-
adapter,
|
|
1030
|
-
data: { rule: "unsafe_cross_shell", reason: unsafeShellReason },
|
|
1031
|
-
});
|
|
1032
1091
|
const { emitDeny } = await import("./adapter/output.ts");
|
|
1033
1092
|
emitDeny(adapter, unsafeShellReason);
|
|
1034
1093
|
return 0;
|
|
@@ -1042,80 +1101,41 @@ async function main(): Promise<number> {
|
|
|
1042
1101
|
// apply_patch (codex) parses paths from the patch body and runs verdict
|
|
1043
1102
|
// per-path; Edit/Write/NotebookEdit resolve a single target. Non-write tools
|
|
1044
1103
|
// (incl. Agent) yield no targets and pass through with no deny.
|
|
1104
|
+
let guardAllowed = true;
|
|
1045
1105
|
try {
|
|
1046
|
-
await runPreToolUseGuard(
|
|
1106
|
+
guardAllowed = await runPreToolUseGuard(
|
|
1107
|
+
coordRoot,
|
|
1108
|
+
owner.instance_id,
|
|
1109
|
+
sessionId,
|
|
1110
|
+
data,
|
|
1111
|
+
adapter,
|
|
1112
|
+
);
|
|
1047
1113
|
} catch (err) {
|
|
1048
1114
|
logError(coordRoot, err, { phase: "pre-tool-use-guard" });
|
|
1049
1115
|
}
|
|
1050
|
-
|
|
1051
|
-
// Shell-mutation warn (warn-only, never blocks). Was the cursor
|
|
1052
|
-
// beforeShellExecution + codex preToolUse-Bash shell-mutation-claim-log in
|
|
1053
|
-
// the per-adapter shell adapters. Cursor sends the command at payload.command;
|
|
1054
|
-
// codex Bash at tool_input.command. Emits a decision.warn per candidate-mutated
|
|
1055
|
-
// path so a peer sees the write in events.ndjson. (CC never did this,
|
|
1056
|
-
// preserved; it emits with its own hooks-side emitter per the
|
|
1057
|
-
// independent-emitter rule.)
|
|
1058
|
-
const shellCmd =
|
|
1059
|
-
eventName === "before-shell-execution"
|
|
1060
|
-
? ((payload?.raw.command as string | undefined) ?? "")
|
|
1061
|
-
: adapter === "codex" && data.tool_name === "Bash"
|
|
1062
|
-
? (((payload?.raw.tool_input as Record<string, unknown> | undefined)?.command as
|
|
1063
|
-
| string
|
|
1064
|
-
| undefined) ?? "")
|
|
1065
|
-
: "";
|
|
1066
|
-
if (shellCmd) {
|
|
1067
|
-
try {
|
|
1068
|
-
const paths = shellMutationPaths(shellCmd, coordRoot);
|
|
1069
|
-
const truncated = shellCmd.length > 80 ? shellCmd.slice(0, 80) : shellCmd;
|
|
1070
|
-
const platform = adapterPlatform(adapter);
|
|
1071
|
-
for (const p of paths) {
|
|
1072
|
-
emit(coordRoot, {
|
|
1073
|
-
event_type: "decision.warn",
|
|
1074
|
-
instance_id: owner.instance_id,
|
|
1075
|
-
session_id: sessionId,
|
|
1076
|
-
adapter,
|
|
1077
|
-
data: {
|
|
1078
|
-
rule: "shell_mutation_candidate",
|
|
1079
|
-
reason: `path=${p} cmd=${truncated} platform=${platform}`,
|
|
1080
|
-
},
|
|
1081
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
1082
|
-
} as Parameters<typeof emit>[1]);
|
|
1083
|
-
}
|
|
1084
|
-
} catch (err) {
|
|
1085
|
-
logError(coordRoot, err, { phase: "shell-mutation-warn" });
|
|
1086
|
-
}
|
|
1087
|
-
}
|
|
1116
|
+
if (!guardAllowed) return 0;
|
|
1088
1117
|
}
|
|
1089
1118
|
|
|
1090
|
-
|
|
1091
|
-
|
|
1092
|
-
|
|
1119
|
+
if (norm.event_type === "tool.completed" && eventName === "post-tool-use") {
|
|
1120
|
+
// Inject only at the successful tool boundary that actually minted a name:
|
|
1121
|
+
// the first non-empty set-task or the transition to lifecycle done. The
|
|
1122
|
+
// coordination row intentionally remains pending until transcript evidence
|
|
1123
|
+
// catches up; reading that latch alone here would re-inject after every
|
|
1124
|
+
// later tool and make the agent print the same block repeatedly.
|
|
1093
1125
|
try {
|
|
1094
|
-
|
|
1095
|
-
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
// Image feed: a Bash command that wrote an image (harn browse, harn image,
|
|
1100
|
-
// --diff, …) is the "agent produced this" signal. Scan the command + its
|
|
1101
|
-
// output for freshly-written image paths and capture them.
|
|
1102
|
-
try {
|
|
1103
|
-
captureImages(coordRoot, {
|
|
1104
|
-
eventType: "tool.post_use",
|
|
1105
|
-
data,
|
|
1106
|
-
payload,
|
|
1107
|
-
instanceId: owner.instance_id,
|
|
1108
|
-
sessionId,
|
|
1109
|
-
adapter,
|
|
1110
|
-
});
|
|
1126
|
+
const name = sessionNameDisplayPending(readLiveCoordinationRow(coordRoot, owner.instance_id));
|
|
1127
|
+
if (name && toolResponseMintedSessionName(payload?.tool_response, name)) {
|
|
1128
|
+
const { emitContext } = await import("./adapter/output.ts");
|
|
1129
|
+
emitContext(adapter, "PostToolUse", sessionNameDisplayInstruction(name));
|
|
1130
|
+
}
|
|
1111
1131
|
} catch (err) {
|
|
1112
|
-
logError(coordRoot, err, { phase: "post-tool-use-
|
|
1132
|
+
logError(coordRoot, err, { phase: "post-tool-use-session-name" });
|
|
1113
1133
|
}
|
|
1114
1134
|
}
|
|
1115
1135
|
|
|
1116
1136
|
// Phase 7: PostToolUseFailure: release claim on failed Edit (the file
|
|
1117
1137
|
// never landed; the claim is stale). Adapter-agnostic.
|
|
1118
|
-
if (norm.event_type === "tool.
|
|
1138
|
+
if (norm.event_type === "tool.completed" && eventName === "post-tool-use-failure") {
|
|
1119
1139
|
try {
|
|
1120
1140
|
releaseClaimOnFailure(coordRoot, owner.instance_id, data, payload?.raw);
|
|
1121
1141
|
} catch (err) {
|
|
@@ -1126,16 +1146,60 @@ async function main(): Promise<number> {
|
|
|
1126
1146
|
return 0;
|
|
1127
1147
|
}
|
|
1128
1148
|
|
|
1149
|
+
async function enforcePendingSessionNameDisplay(
|
|
1150
|
+
coordRoot: string,
|
|
1151
|
+
instanceId: string,
|
|
1152
|
+
adapter: Adapter,
|
|
1153
|
+
payload: ParsedPayload | null,
|
|
1154
|
+
): Promise<boolean> {
|
|
1155
|
+
const name = sessionNameDisplayPending(readLiveCoordinationRow(coordRoot, instanceId));
|
|
1156
|
+
if (!name) return true;
|
|
1157
|
+
|
|
1158
|
+
const command = extractBashCommand(payload?.tool_name, payload?.tool_input);
|
|
1159
|
+
if (isSessionNameRemediationCommand(command, resolveBinName(coordRoot))) return true;
|
|
1160
|
+
|
|
1161
|
+
const inspection =
|
|
1162
|
+
payload?.agent_message !== undefined
|
|
1163
|
+
? {
|
|
1164
|
+
state: assistantTextStartsWithSessionNameBlock(payload.agent_message, name)
|
|
1165
|
+
? ("present" as const)
|
|
1166
|
+
: ("absent" as const),
|
|
1167
|
+
}
|
|
1168
|
+
: inspectSessionNameDisplayImmediately(
|
|
1169
|
+
payload?.transcript_path,
|
|
1170
|
+
name,
|
|
1171
|
+
assistantTextStartsWithSessionNameBlock,
|
|
1172
|
+
);
|
|
1173
|
+
if (inspection.state === "present") {
|
|
1174
|
+
stampSessionNameSeen(coordRoot, instanceId, name);
|
|
1175
|
+
return true;
|
|
1176
|
+
}
|
|
1177
|
+
|
|
1178
|
+
if (inspection.state === "unavailable") {
|
|
1179
|
+
const { emitContext } = await import("./adapter/output.ts");
|
|
1180
|
+
emitContext(
|
|
1181
|
+
adapter,
|
|
1182
|
+
"PreToolUse",
|
|
1183
|
+
"Harnery could not verify the pending session-name display because the adapter transcript is unavailable or not flushed yet. This tool is allowed so the session cannot deadlock; display the requested block before later work. Verification remains pending.",
|
|
1184
|
+
);
|
|
1185
|
+
return true;
|
|
1186
|
+
}
|
|
1187
|
+
|
|
1188
|
+
const { emitDeny } = await import("./adapter/output.ts");
|
|
1189
|
+
emitDeny(adapter, sessionNameDisplayInstruction(name));
|
|
1190
|
+
return false;
|
|
1191
|
+
}
|
|
1192
|
+
|
|
1129
1193
|
async function runPreToolUseGuard(
|
|
1130
1194
|
coordRoot: string,
|
|
1131
1195
|
instanceId: string,
|
|
1132
1196
|
sessionId: string,
|
|
1133
1197
|
data: Record<string, unknown>,
|
|
1134
1198
|
adapter: Adapter,
|
|
1135
|
-
): Promise<
|
|
1199
|
+
): Promise<boolean> {
|
|
1136
1200
|
const toolName = (data.tool_name as string | undefined) ?? "";
|
|
1137
1201
|
const rawTargets = collectGuardTargets(toolName, data);
|
|
1138
|
-
if (rawTargets.length === 0) return;
|
|
1202
|
+
if (rawTargets.length === 0) return true;
|
|
1139
1203
|
|
|
1140
1204
|
let targets: Array<{ path: string; finalization?: ClaimFinalizationDescriptor }>;
|
|
1141
1205
|
if (agentsRequireGitFinalization(coordRoot)) {
|
|
@@ -1144,7 +1208,7 @@ async function runPreToolUseGuard(
|
|
|
1144
1208
|
if (denied && !denied.allow) {
|
|
1145
1209
|
const { emitDeny } = await import("./adapter/output.ts");
|
|
1146
1210
|
emitDeny(adapter, formatWriteClaimFinalizationDenial(denied, resolveBinName(coordRoot)));
|
|
1147
|
-
return;
|
|
1211
|
+
return false;
|
|
1148
1212
|
}
|
|
1149
1213
|
const allowed = decisions.filter(
|
|
1150
1214
|
(decision): decision is Extract<ClaimFinalizationDecision, { allow: true }> => decision.allow,
|
|
@@ -1159,7 +1223,7 @@ async function runPreToolUseGuard(
|
|
|
1159
1223
|
.filter((path): path is string => path !== null)
|
|
1160
1224
|
.map((path) => ({ path }));
|
|
1161
1225
|
}
|
|
1162
|
-
if (targets.length === 0) return;
|
|
1226
|
+
if (targets.length === 0) return true;
|
|
1163
1227
|
|
|
1164
1228
|
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
1165
1229
|
if (!existsSync(agentCoordBin)) {
|
|
@@ -1169,8 +1233,9 @@ async function runPreToolUseGuard(
|
|
|
1169
1233
|
adapter,
|
|
1170
1234
|
"Harnery denied the write before mutation because the claim coordinator is unavailable; repair the project's Harnery installation and retry.",
|
|
1171
1235
|
);
|
|
1236
|
+
return false;
|
|
1172
1237
|
}
|
|
1173
|
-
return;
|
|
1238
|
+
return true;
|
|
1174
1239
|
}
|
|
1175
1240
|
|
|
1176
1241
|
// For apply_patch (multi-file), collect siblings so the deny reason names
|
|
@@ -1210,27 +1275,10 @@ async function runPreToolUseGuard(
|
|
|
1210
1275
|
}
|
|
1211
1276
|
const { emitDeny } = await import("./adapter/output.ts");
|
|
1212
1277
|
emitDeny(adapter, reason);
|
|
1213
|
-
return;
|
|
1278
|
+
return false;
|
|
1214
1279
|
}
|
|
1215
|
-
|
|
1216
|
-
// The verdict mutates the live heartbeat immediately, but that file is a
|
|
1217
|
-
// projection and can be rebuilt at any later hook. Persist the acquisition
|
|
1218
|
-
// in the canonical stream too. This matters most for Codex apply_patch:
|
|
1219
|
-
// one tool call can claim several files, and tool.pre_use's clamped payload
|
|
1220
|
-
// is not a durable ownership representation for those targets.
|
|
1221
|
-
emit(coordRoot, {
|
|
1222
|
-
event_type: "claim.acquire",
|
|
1223
|
-
instance_id: instanceId,
|
|
1224
|
-
session_id: sessionId,
|
|
1225
|
-
adapter,
|
|
1226
|
-
source: "agent-hooks",
|
|
1227
|
-
data: {
|
|
1228
|
-
path: target.path,
|
|
1229
|
-
mode: "write",
|
|
1230
|
-
...(target.finalization ? { finalization: target.finalization } : {}),
|
|
1231
|
-
},
|
|
1232
|
-
});
|
|
1233
1280
|
}
|
|
1281
|
+
return true;
|
|
1234
1282
|
}
|
|
1235
1283
|
|
|
1236
1284
|
/** Canonicalize a path to monorepo-relative form. Absolute paths under
|
|
@@ -1289,33 +1337,10 @@ function parseApplyPatchPaths(data: Record<string, unknown>): string[] {
|
|
|
1289
1337
|
return out;
|
|
1290
1338
|
}
|
|
1291
1339
|
|
|
1292
|
-
function healHeartbeatViaCli(
|
|
1293
|
-
coordRoot: string,
|
|
1294
|
-
instanceId: string,
|
|
1295
|
-
sessionId: string,
|
|
1296
|
-
adapter: string,
|
|
1297
|
-
forkedFrom?: string,
|
|
1298
|
-
): void {
|
|
1299
|
-
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
1300
|
-
if (!existsSync(agentCoordBin)) return;
|
|
1301
|
-
// Pass the detected adapter so a pruned Cursor/Codex heartbeat is recreated
|
|
1302
|
-
// with the correct platform; without it, healHeartbeat defaults to
|
|
1303
|
-
// claude-code and the dashboard mislabels the agent. See
|
|
1304
|
-
// heartbeat-writer.healHeartbeat. --forked-from carries detected fork
|
|
1305
|
-
// lineage for an instance that never session.started (the CC fork flow).
|
|
1306
|
-
const args = ["heal-heartbeat", instanceId, sessionId, `--adapter=${adapter}`];
|
|
1307
|
-
if (forkedFrom) args.push(`--forked-from=${forkedFrom}`);
|
|
1308
|
-
spawnSync(agentCoordBin, args, {
|
|
1309
|
-
encoding: "utf8",
|
|
1310
|
-
timeout: 2000,
|
|
1311
|
-
env: childEnv(coordRoot),
|
|
1312
|
-
});
|
|
1313
|
-
}
|
|
1314
|
-
|
|
1315
1340
|
/**
|
|
1316
1341
|
* Walk up the ppid chain on Linux/WSL looking for the adapter anchor PID,
|
|
1317
1342
|
* the PID of the claude / cursor / codex binary. Finds the agent PID. Used by
|
|
1318
|
-
* `tool.
|
|
1343
|
+
* `tool.requested` pid-map self-heal so a re-parented adapter binary (the
|
|
1319
1344
|
* VS Code 2.1.x sibling-claude spawn case) gets its pid-map row rewritten on
|
|
1320
1345
|
* the next tool call rather than going invisible until SessionStart fires
|
|
1321
1346
|
* again, which it may never do.
|
|
@@ -1382,9 +1407,7 @@ function findAdapterAnchorPid(adapter?: Adapter): number | undefined {
|
|
|
1382
1407
|
}
|
|
1383
1408
|
|
|
1384
1409
|
/**
|
|
1385
|
-
* Pid-map self-heal for `tool.
|
|
1386
|
-
* `healHeartbeatViaCli`; the two were paired before the Phase 6 refactor split
|
|
1387
|
-
* them apart, then restored together afterward.
|
|
1410
|
+
* Pid-map self-heal for `tool.requested`.
|
|
1388
1411
|
*
|
|
1389
1412
|
* The pid argument prefers the payload's `pid` (CC populates it on
|
|
1390
1413
|
* SessionStart and may also send it on PreToolUse), then
|
|
@@ -1407,40 +1430,6 @@ function refreshPidmap(
|
|
|
1407
1430
|
writePidmapViaAgentCoord(coordRoot, pid, instanceId, adapterPlatform(adapter));
|
|
1408
1431
|
}
|
|
1409
1432
|
|
|
1410
|
-
function stampToolActivity(
|
|
1411
|
-
coordRoot: string,
|
|
1412
|
-
instanceId: string,
|
|
1413
|
-
data: Record<string, unknown>,
|
|
1414
|
-
): void {
|
|
1415
|
-
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
1416
|
-
if (!existsSync(agentCoordBin)) return;
|
|
1417
|
-
const toolName = (data.tool_name as string | undefined) ?? "";
|
|
1418
|
-
// Extract a 1-line target from the tool_input blob (file path / command head).
|
|
1419
|
-
const toolInputRaw = data.tool_input;
|
|
1420
|
-
let target = "";
|
|
1421
|
-
if (typeof toolInputRaw === "string") {
|
|
1422
|
-
try {
|
|
1423
|
-
const parsed = JSON.parse(toolInputRaw) as Record<string, unknown>;
|
|
1424
|
-
target =
|
|
1425
|
-
(parsed.file_path as string | undefined) ??
|
|
1426
|
-
(parsed.path as string | undefined) ??
|
|
1427
|
-
(parsed.notebook_path as string | undefined) ??
|
|
1428
|
-
(parsed.command as string | undefined) ??
|
|
1429
|
-
(parsed.url as string | undefined) ??
|
|
1430
|
-
(parsed.pattern as string | undefined) ??
|
|
1431
|
-
"";
|
|
1432
|
-
} catch {
|
|
1433
|
-
/* skip */
|
|
1434
|
-
}
|
|
1435
|
-
}
|
|
1436
|
-
if (target.length > 200) target = target.slice(0, 200);
|
|
1437
|
-
spawnSync(agentCoordBin, ["stamp-tool-activity", instanceId, toolName, target], {
|
|
1438
|
-
encoding: "utf8",
|
|
1439
|
-
timeout: 2000,
|
|
1440
|
-
env: childEnv(coordRoot),
|
|
1441
|
-
});
|
|
1442
|
-
}
|
|
1443
|
-
|
|
1444
1433
|
function releaseClaimOnFailure(
|
|
1445
1434
|
coordRoot: string,
|
|
1446
1435
|
instanceId: string,
|
|
@@ -1484,6 +1473,12 @@ function releaseClaimOnFailure(
|
|
|
1484
1473
|
: filePath;
|
|
1485
1474
|
}
|
|
1486
1475
|
|
|
1476
|
+
// In V3 the release is an authority event, not a heartbeat mutation. Avoid
|
|
1477
|
+
// creating a disposable cache for a failure that never acquired a claim,
|
|
1478
|
+
// but release the exact path when the validated projection says it is held.
|
|
1479
|
+
const row = readLiveCoordinationRow(coordRoot, instanceId);
|
|
1480
|
+
if (!row?.files_touched?.includes(canonical)) return;
|
|
1481
|
+
|
|
1487
1482
|
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
1488
1483
|
if (!existsSync(agentCoordBin)) return;
|
|
1489
1484
|
spawnSync(agentCoordBin, ["release-claim", instanceId, canonical], {
|
|
@@ -1494,15 +1489,6 @@ function releaseClaimOnFailure(
|
|
|
1494
1489
|
}
|
|
1495
1490
|
|
|
1496
1491
|
function cleanupSessionEnd(coordRoot: string, instanceId: string, reason: string): void {
|
|
1497
|
-
// Remove heartbeat from the canonical .harnery/active/ dir.
|
|
1498
|
-
const path = join(coordRoot, ".harnery", "active", `${instanceId}.json`);
|
|
1499
|
-
try {
|
|
1500
|
-
if (existsSync(path)) {
|
|
1501
|
-
require("node:fs").unlinkSync(path);
|
|
1502
|
-
}
|
|
1503
|
-
} catch {
|
|
1504
|
-
/* swallow */
|
|
1505
|
-
}
|
|
1506
1492
|
// Sweep pid-map entries pointing to this instance
|
|
1507
1493
|
const pidmapDir = join(coordRoot, ".harnery", "pid-map");
|
|
1508
1494
|
if (existsSync(pidmapDir)) {
|
|
@@ -1547,29 +1533,20 @@ async function emitUserPromptSubmitSystemMessage(
|
|
|
1547
1533
|
let additionalContext = "";
|
|
1548
1534
|
|
|
1549
1535
|
if (existsSync(agentCoordBin)) {
|
|
1550
|
-
// Look up the agent's name from its heartbeat (for council pending rendering).
|
|
1551
|
-
let agentName = "";
|
|
1552
|
-
try {
|
|
1553
|
-
const fs = require("node:fs") as typeof import("node:fs");
|
|
1554
|
-
const hbPath = join(coordRoot, ".harnery", "active", `${instanceId}.json`);
|
|
1555
|
-
if (fs.existsSync(hbPath)) {
|
|
1556
|
-
const hb = JSON.parse(fs.readFileSync(hbPath, "utf8")) as { name?: string };
|
|
1557
|
-
agentName = hb.name ?? "";
|
|
1558
|
-
}
|
|
1559
|
-
} catch {
|
|
1560
|
-
/* fall through with empty name; peer table still renders */
|
|
1561
|
-
}
|
|
1562
|
-
|
|
1563
1536
|
const args = ["prompt-context", "--instance", instanceId, "--session", sessionId];
|
|
1564
|
-
if (agentName) args.push("--name", agentName);
|
|
1565
1537
|
// Every human-facing adapter gets the first-session naming reminder from
|
|
1566
1538
|
// the shared hook path. Cursor + Codex additionally get ongoing set-task
|
|
1567
1539
|
// staleness nudges; Claude Code enforces those via its Stop transcript.
|
|
1568
1540
|
// Codex gets a fresh status-footer reminder on every prompt. Its Stop hook
|
|
1569
1541
|
// stays observe-only, so missing the footer never replaces the answer.
|
|
1542
|
+
// Claude Code + Cursor (the Stop-ENFORCING adapters) get a fresh per-turn
|
|
1543
|
+
// ritual reminder: satisfying the contract up front is far cheaper than
|
|
1544
|
+
// the bounce-and-retry the Stop hook otherwise forces.
|
|
1570
1545
|
args.push("--session-name-nudge");
|
|
1571
1546
|
if (adapter === "cursor" || adapter === "codex") args.push("--task-nudge");
|
|
1572
1547
|
if (adapter === "codex") args.push("--status-footer-nudge");
|
|
1548
|
+
if (adapter === "claude-code" || adapter === "cursor")
|
|
1549
|
+
args.push("--turn-ritual-nudge", adapter);
|
|
1573
1550
|
const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
|
|
1574
1551
|
if (result.status === 0 && result.stdout) additionalContext = result.stdout.trim();
|
|
1575
1552
|
}
|
|
@@ -1597,7 +1574,7 @@ function emitSubagentStartContext(
|
|
|
1597
1574
|
adapter: Adapter,
|
|
1598
1575
|
): void {
|
|
1599
1576
|
// Look up the subagent's assigned name (just-written by agent-coord assignName
|
|
1600
|
-
// in session.
|
|
1577
|
+
// in session.started data) + the parent's short id for the "you are a subagent
|
|
1601
1578
|
// of X" framing.
|
|
1602
1579
|
const subagentName = (data.name as string | undefined) ?? "";
|
|
1603
1580
|
if (!subagentName) return;
|
|
@@ -1642,13 +1619,19 @@ async function emitSessionStartSystemMessage(
|
|
|
1642
1619
|
recoveryBriefing = "",
|
|
1643
1620
|
): Promise<boolean> {
|
|
1644
1621
|
const agentCoordBin = coordBinPath("agent-coord", coordRoot) ?? "";
|
|
1622
|
+
const workflowChild = coordEnv("WORKFLOW_CHILD") === "1";
|
|
1645
1623
|
let additionalContext = "";
|
|
1646
1624
|
if (existsSync(agentCoordBin)) {
|
|
1647
1625
|
// Sync-project so the heartbeat exists for downstream readers (peer table,
|
|
1648
1626
|
// wiring check, council invites).
|
|
1649
1627
|
spawnSync(agentCoordBin, ["project"], { encoding: "utf8", timeout: 3000 });
|
|
1650
|
-
//
|
|
1651
|
-
|
|
1628
|
+
// Opportunistic reconciliation makes normal session starts a failsafe for
|
|
1629
|
+
// archive, idle, cascade, and host lifecycle observations.
|
|
1630
|
+
spawnSync(agentCoordBin, ["reconcile-finalization"], {
|
|
1631
|
+
encoding: "utf8",
|
|
1632
|
+
timeout: 5000,
|
|
1633
|
+
env: { ...process.env, HARNERY_COORD_ROOT_OVERRIDE: coordRoot },
|
|
1634
|
+
});
|
|
1652
1635
|
|
|
1653
1636
|
// SESSION_START activity log line, fired across all adapters.
|
|
1654
1637
|
const model = (emittedData.model as string | undefined) ?? "unknown";
|
|
@@ -1665,32 +1648,37 @@ async function emitSessionStartSystemMessage(
|
|
|
1665
1648
|
{ encoding: "utf8", timeout: 2000 },
|
|
1666
1649
|
);
|
|
1667
1650
|
|
|
1668
|
-
//
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1676
|
-
|
|
1651
|
+
// Workflow children retain lifecycle/event capture but do not receive
|
|
1652
|
+
// operator-facing peer, council, or init-remediation context. Injecting
|
|
1653
|
+
// that context can make a bounded child follow housekeeping instructions
|
|
1654
|
+
// instead of its assigned prompt.
|
|
1655
|
+
if (!workflowChild) {
|
|
1656
|
+
const agentName = (emittedData.name as string | undefined) ?? "";
|
|
1657
|
+
const args = ["session-context", "--instance", instanceId, "--session", sessionId];
|
|
1658
|
+
if (agentName) args.push("--name", agentName);
|
|
1659
|
+
// The "You are agent-X." prefix in session-context renders unqualified by
|
|
1660
|
+
// default (claude-code-style). For cursor/codex the bash dispatchers add
|
|
1661
|
+
// a "(Cursor)" / "(Codex)" suffix; pass it through as --platform-label.
|
|
1662
|
+
if (adapter !== "claude-code") {
|
|
1663
|
+
args.push("--platform-label", platform === "cursor" ? "Cursor" : "Codex");
|
|
1664
|
+
}
|
|
1665
|
+
const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
|
|
1666
|
+
if (result.status === 0 && result.stdout) additionalContext = result.stdout.trim();
|
|
1677
1667
|
}
|
|
1678
|
-
const result = spawnSync(agentCoordBin, args, { encoding: "utf8", timeout: 3000 });
|
|
1679
|
-
if (result.status === 0 && result.stdout) additionalContext = result.stdout.trim();
|
|
1680
1668
|
}
|
|
1681
1669
|
|
|
1682
1670
|
// Effect (claude-code): merge the journal recovery cue into the session-start
|
|
1683
1671
|
// context. Was a standalone additionalContext emission from the previous
|
|
1684
1672
|
// journal-on-start adapter; now that agent-hook is the single SessionStart
|
|
1685
1673
|
// entry, it folds in here.
|
|
1686
|
-
if (adapter === "claude-code") {
|
|
1674
|
+
if (adapter === "claude-code" && !workflowChild) {
|
|
1687
1675
|
const cue = journalRecoveryCue(coordRoot);
|
|
1688
1676
|
if (cue) additionalContext = [additionalContext, cue].filter(Boolean).join("\n\n");
|
|
1689
1677
|
}
|
|
1690
|
-
if (recoveryBriefing) {
|
|
1678
|
+
if (recoveryBriefing && !workflowChild) {
|
|
1691
1679
|
additionalContext = [additionalContext, recoveryBriefing].filter(Boolean).join("\n\n");
|
|
1692
1680
|
}
|
|
1693
|
-
if (adapter === "codex" && isWslUncPath(emittedData.cwd)) {
|
|
1681
|
+
if (adapter === "codex" && !workflowChild && isWslUncPath(emittedData.cwd)) {
|
|
1694
1682
|
const fileLinkContext = renderCodexWslFileLinkContext(coordRoot, emittedData.cwd);
|
|
1695
1683
|
if (fileLinkContext) {
|
|
1696
1684
|
additionalContext = [additionalContext, fileLinkContext].filter(Boolean).join("\n\n");
|
|
@@ -1716,22 +1704,10 @@ function completeRecoveryInjection(
|
|
|
1716
1704
|
coordRoot: string,
|
|
1717
1705
|
instanceId: string,
|
|
1718
1706
|
sessionId: string,
|
|
1719
|
-
adapter: Adapter,
|
|
1720
1707
|
recovery: PreparedContextRecovery,
|
|
1721
|
-
injectionEvent: "SessionStart" | "UserPromptSubmit",
|
|
1722
1708
|
): void {
|
|
1723
1709
|
completeContextRecovery(coordRoot, { sessionId, instanceId });
|
|
1724
|
-
|
|
1725
|
-
event_type: "context.recovery.injected",
|
|
1726
|
-
instance_id: instanceId,
|
|
1727
|
-
session_id: sessionId,
|
|
1728
|
-
adapter,
|
|
1729
|
-
data: {
|
|
1730
|
-
capsule_id: recovery.capsule.capsule_id,
|
|
1731
|
-
generation: recovery.capsule.generation,
|
|
1732
|
-
injection_event: injectionEvent,
|
|
1733
|
-
},
|
|
1734
|
-
});
|
|
1710
|
+
void recovery;
|
|
1735
1711
|
}
|
|
1736
1712
|
|
|
1737
1713
|
main()
|