harnery 0.36.0 → 0.38.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commander.d.ts +9 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +10 -1
- package/dist/commands/admission.d.ts +21 -0
- package/dist/commands/admission.d.ts.map +1 -0
- package/dist/commands/admission.js +565 -0
- package/dist/commands/agents.d.ts +7 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +148 -47
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +73 -2
- package/dist/commands/browse-ai.d.ts +2 -2
- package/dist/commands/browse-ai.d.ts.map +1 -1
- package/dist/commands/browse-ai.js +6 -4
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +360 -21
- package/dist/commands/diagnostics.d.ts +4 -0
- package/dist/commands/diagnostics.d.ts.map +1 -0
- package/dist/commands/diagnostics.js +229 -0
- package/dist/commands/fetch.js +1 -0
- package/dist/commands/files.d.ts +12 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -1
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +4 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +71 -2
- package/dist/commands/qa-record.d.ts +144 -0
- package/dist/commands/qa-record.d.ts.map +1 -0
- package/dist/commands/qa-record.js +0 -0
- package/dist/commands/qa-run.d.ts +8 -0
- package/dist/commands/qa-run.d.ts.map +1 -0
- package/dist/commands/qa-run.js +396 -0
- package/dist/commands/qa-status.d.ts +71 -0
- package/dist/commands/qa-status.d.ts.map +1 -0
- package/dist/commands/qa-status.js +490 -0
- package/dist/commands/qa-verify.d.ts +40 -0
- package/dist/commands/qa-verify.d.ts.map +1 -0
- package/dist/commands/qa-verify.js +180 -0
- package/dist/commands/resources.d.ts +4 -0
- package/dist/commands/resources.d.ts.map +1 -0
- package/dist/commands/resources.js +29 -0
- package/dist/commands/review-pack.d.ts +4 -0
- package/dist/commands/review-pack.d.ts.map +1 -0
- package/dist/commands/review-pack.js +1001 -0
- package/dist/commands/supervisor.d.ts +4 -0
- package/dist/commands/supervisor.d.ts.map +1 -0
- package/dist/commands/supervisor.js +101 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +17 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +4 -0
- package/dist/core/agents/cli.js +7 -3
- package/dist/core/agents/health.d.ts +17 -0
- package/dist/core/agents/health.d.ts.map +1 -0
- package/dist/core/agents/health.js +109 -0
- package/dist/core/agents/mailbox.d.ts +92 -0
- package/dist/core/agents/mailbox.d.ts.map +1 -0
- package/dist/core/agents/mailbox.js +325 -0
- package/dist/core/agents/qa-signal.d.ts +111 -0
- package/dist/core/agents/qa-signal.d.ts.map +1 -0
- package/dist/core/agents/qa-signal.js +231 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts +44 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts.map +1 -0
- package/dist/core/agents/reconcile-coordination-v3.js +58 -0
- package/dist/core/agents/render/prompt-context.d.ts +5 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +34 -13
- package/dist/core/agents/render/session-context.d.ts +8 -0
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +34 -3
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +50 -1
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +6 -10
- package/dist/core/agents/session-finalizer-v3.js +4 -1
- package/dist/core/agents/session-name-display.d.ts +20 -5
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +67 -7
- package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +11 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +17 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +5 -0
- package/dist/core/artifacts/constants.d.ts +1 -1
- package/dist/core/artifacts/constants.js +1 -1
- package/dist/core/artifacts/index.d.ts +82 -6
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +410 -15
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +59 -0
- package/dist/core/diagnostics/advice.d.ts +9 -0
- package/dist/core/diagnostics/advice.d.ts.map +1 -0
- package/dist/core/diagnostics/advice.js +112 -0
- package/dist/core/diagnostics/bundle.d.ts +51 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -0
- package/dist/core/diagnostics/bundle.js +968 -0
- package/dist/core/diagnostics/comparison.d.ts +5 -0
- package/dist/core/diagnostics/comparison.d.ts.map +1 -0
- package/dist/core/diagnostics/comparison.js +444 -0
- package/dist/core/diagnostics/contract.d.ts +245 -0
- package/dist/core/diagnostics/contract.d.ts.map +1 -0
- package/dist/core/diagnostics/contract.js +18 -0
- package/dist/core/diagnostics/identity.d.ts +3 -0
- package/dist/core/diagnostics/identity.d.ts.map +1 -0
- package/dist/core/diagnostics/identity.js +10 -0
- package/dist/core/diagnostics/index.d.ts +8 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -0
- package/dist/core/diagnostics/index.js +7 -0
- package/dist/core/diagnostics/replay.d.ts +8 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -0
- package/dist/core/diagnostics/replay.js +213 -0
- package/dist/core/diagnostics/sanitize.d.ts +9 -0
- package/dist/core/diagnostics/sanitize.d.ts.map +1 -0
- package/dist/core/diagnostics/sanitize.js +84 -0
- package/dist/core/events/legacy-storage/compression.d.ts +13 -0
- package/dist/core/events/legacy-storage/compression.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/compression.js +107 -0
- package/dist/core/events/legacy-storage/index.d.ts +1 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/index.js +1 -0
- package/dist/core/events/v3/archive-retention.d.ts +33 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -0
- package/dist/core/events/v3/archive-retention.js +195 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +10 -0
- package/dist/core/events/v3/capabilities.d.ts +1 -1
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +1 -0
- package/dist/core/events/v3/coordination-view.d.ts +3 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +69 -8
- package/dist/core/events/v3/index.d.ts +1 -0
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +1 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +1 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +1 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +13 -2
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +10 -2
- package/dist/core/events/v3/producers/recorder.d.ts +39 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +350 -17
- package/dist/core/hooks/adapter/output.d.ts +8 -0
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +11 -1
- package/dist/core/hooks/cli.js +303 -219
- package/dist/core/hooks/health.d.ts +59 -0
- package/dist/core/hooks/health.d.ts.map +1 -0
- package/dist/core/hooks/health.js +84 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +10 -3
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +4 -1
- package/dist/core/qa-artifacts.d.ts +20 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -0
- package/dist/core/qa-artifacts.js +110 -0
- package/dist/core/resources/contract.d.ts +96 -0
- package/dist/core/resources/contract.d.ts.map +1 -0
- package/dist/core/resources/contract.js +2 -0
- package/dist/core/resources/index.d.ts +6 -0
- package/dist/core/resources/index.d.ts.map +1 -0
- package/dist/core/resources/index.js +5 -0
- package/dist/core/resources/sampler.d.ts +34 -0
- package/dist/core/resources/sampler.d.ts.map +1 -0
- package/dist/core/resources/sampler.js +458 -0
- package/dist/core/resources/service-status.d.ts +3 -0
- package/dist/core/resources/service-status.d.ts.map +1 -0
- package/dist/core/resources/service-status.js +48 -0
- package/dist/core/resources/service.d.ts +26 -0
- package/dist/core/resources/service.d.ts.map +1 -0
- package/dist/core/resources/service.js +292 -0
- package/dist/core/resources/storage.d.ts +13 -0
- package/dist/core/resources/storage.d.ts.map +1 -0
- package/dist/core/resources/storage.js +30 -0
- package/dist/core/storage/atomic-json.d.ts +3 -0
- package/dist/core/storage/atomic-json.d.ts.map +1 -0
- package/dist/core/storage/atomic-json.js +15 -0
- package/dist/core/storage/builtins.d.ts.map +1 -1
- package/dist/core/storage/builtins.js +45 -6
- package/dist/core/storage/logger.d.ts +2 -0
- package/dist/core/storage/logger.d.ts.map +1 -1
- package/dist/core/storage/logger.js +2 -0
- package/dist/core/storage/query.d.ts +14 -0
- package/dist/core/storage/query.d.ts.map +1 -1
- package/dist/core/storage/query.js +51 -0
- package/dist/core/supervisor/activity.d.ts +4 -0
- package/dist/core/supervisor/activity.d.ts.map +1 -0
- package/dist/core/supervisor/activity.js +141 -0
- package/dist/core/supervisor/contract.d.ts +268 -0
- package/dist/core/supervisor/contract.d.ts.map +1 -0
- package/dist/core/supervisor/contract.js +35 -0
- package/dist/core/supervisor/explanations.d.ts +4 -0
- package/dist/core/supervisor/explanations.d.ts.map +1 -0
- package/dist/core/supervisor/explanations.js +71 -0
- package/dist/core/supervisor/findings.d.ts +20 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -0
- package/dist/core/supervisor/findings.js +399 -0
- package/dist/core/supervisor/history.d.ts +9 -0
- package/dist/core/supervisor/history.d.ts.map +1 -0
- package/dist/core/supervisor/history.js +46 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts +14 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-alerts.js +70 -0
- package/dist/core/supervisor/hook-health-storage.d.ts +5 -0
- package/dist/core/supervisor/hook-health-storage.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-storage.js +24 -0
- package/dist/core/supervisor/hook-health.d.ts +72 -0
- package/dist/core/supervisor/hook-health.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health.js +203 -0
- package/dist/core/supervisor/hooks.d.ts +10 -0
- package/dist/core/supervisor/hooks.d.ts.map +1 -0
- package/dist/core/supervisor/hooks.js +28 -0
- package/dist/core/supervisor/index.d.ts +15 -0
- package/dist/core/supervisor/index.d.ts.map +1 -0
- package/dist/core/supervisor/index.js +14 -0
- package/dist/core/supervisor/log-feed.d.ts +9 -0
- package/dist/core/supervisor/log-feed.d.ts.map +1 -0
- package/dist/core/supervisor/log-feed.js +103 -0
- package/dist/core/supervisor/service.d.ts +29 -0
- package/dist/core/supervisor/service.d.ts.map +1 -0
- package/dist/core/supervisor/service.js +450 -0
- package/dist/core/supervisor/services.d.ts +11 -0
- package/dist/core/supervisor/services.d.ts.map +1 -0
- package/dist/core/supervisor/services.js +155 -0
- package/dist/core/supervisor/status.d.ts +3 -0
- package/dist/core/supervisor/status.d.ts.map +1 -0
- package/dist/core/supervisor/status.js +48 -0
- package/dist/core/supervisor/storage.d.ts +30 -0
- package/dist/core/supervisor/storage.d.ts.map +1 -0
- package/dist/core/supervisor/storage.js +73 -0
- package/dist/core/supervisor/timeline.d.ts +3 -0
- package/dist/core/supervisor/timeline.d.ts.map +1 -0
- package/dist/core/supervisor/timeline.js +87 -0
- package/dist/core/workflow/admission.d.ts +23 -0
- package/dist/core/workflow/admission.d.ts.map +1 -0
- package/dist/core/workflow/admission.js +136 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +77 -2
- package/dist/core/workflow/index.d.ts +3 -2
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +2 -1
- package/dist/core/workflow/proof.d.ts +2 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +39 -1
- package/dist/core/workflow/run-state.d.ts +3 -2
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +8 -1
- package/dist/core/workflow/types.d.ts +33 -1
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.js +2 -1
- package/dist/lib/admission.d.ts +71 -0
- package/dist/lib/admission.d.ts.map +1 -0
- package/dist/lib/admission.js +264 -0
- package/dist/lib/agent-browser/client.d.ts +1 -1
- package/dist/lib/agent-browser/client.d.ts.map +1 -1
- package/dist/lib/agent-browser/client.js +1 -5
- package/dist/lib/browser/capture-fidelity.d.ts +39 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -0
- package/dist/lib/browser/capture-fidelity.js +84 -0
- package/dist/lib/browser/client.d.ts +46 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +168 -9
- package/dist/lib/browser/critique.d.ts +38 -1
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +34 -6
- package/dist/lib/browser/index.d.ts +5 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +4 -0
- package/dist/lib/browser/page-review-judge.d.ts +64 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -0
- package/dist/lib/browser/page-review-judge.js +270 -0
- package/dist/lib/browser/page-review-pack.d.ts +613 -0
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -0
- package/dist/lib/browser/page-review-pack.js +1751 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +377 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
- package/dist/lib/browser/qa-run-contracts.js +361 -0
- package/dist/lib/browser/qa-run.d.ts +141 -0
- package/dist/lib/browser/qa-run.d.ts.map +1 -0
- package/dist/lib/browser/qa-run.js +1283 -0
- package/dist/lib/browser/request-diagnostics.d.ts +13 -0
- package/dist/lib/browser/request-diagnostics.d.ts.map +1 -0
- package/dist/lib/browser/request-diagnostics.js +18 -0
- package/dist/lib/browser/tiling.d.ts +19 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +28 -0
- package/dist/lib/cookies/client.d.ts +9 -0
- package/dist/lib/cookies/client.d.ts.map +1 -1
- package/dist/lib/cookies/client.js +197 -44
- package/dist/lib/cookies/extra.d.ts +18 -0
- package/dist/lib/cookies/extra.d.ts.map +1 -0
- package/dist/lib/cookies/extra.js +14 -0
- package/dist/lib/cookies/index.d.ts +2 -1
- package/dist/lib/cookies/index.d.ts.map +1 -1
- package/dist/lib/cookies/index.js +2 -1
- package/dist/lib/coord-root-id.d.ts +9 -0
- package/dist/lib/coord-root-id.d.ts.map +1 -0
- package/dist/lib/coord-root-id.js +17 -0
- package/dist/lib/durable-job.d.ts +124 -0
- package/dist/lib/durable-job.d.ts.map +1 -0
- package/dist/lib/durable-job.js +296 -0
- package/dist/lib/http/client.d.ts +7 -1
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +2 -0
- package/dist/lib/instructions/apply.d.ts +3 -1
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +74 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +11 -2
- package/package.json +19 -2
- package/src/commander.ts +75 -1
- package/src/commands/admission.ts +699 -0
- package/src/commands/agents.ts +189 -50
- package/src/commands/artifacts.ts +132 -18
- package/src/commands/browse-ai.ts +10 -5
- package/src/commands/browse.ts +496 -20
- package/src/commands/diagnostics.ts +271 -0
- package/src/commands/fetch.ts +1 -0
- package/src/commands/files.ts +102 -2
- package/src/commands/governor.ts +8 -0
- package/src/commands/ledger-v3.ts +82 -0
- package/src/commands/qa-record.ts +682 -0
- package/src/commands/qa-run.ts +503 -0
- package/src/commands/qa-status.ts +608 -0
- package/src/commands/qa-verify.ts +238 -0
- package/src/commands/resources.ts +38 -0
- package/src/commands/review-pack.ts +1281 -0
- package/src/commands/supervisor.ts +141 -0
- package/src/commands/web.ts +19 -0
- package/src/commands/workflow.ts +8 -0
- package/src/core/agents/cli.ts +7 -3
- package/src/core/agents/health.ts +142 -0
- package/src/core/agents/mailbox.ts +373 -0
- package/src/core/agents/qa-signal.ts +261 -0
- package/src/core/agents/reconcile-coordination-v3.ts +77 -0
- package/src/core/agents/render/prompt-context.ts +42 -12
- package/src/core/agents/render/session-context.ts +37 -3
- package/src/core/agents/rules/commit-conflict.ts +58 -1
- package/src/core/agents/rules/stop-hook.ts +6 -12
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/session-name-display.ts +78 -7
- package/src/core/agents/state/heartbeat-reader.ts +7 -0
- package/src/core/agents/state/heartbeat-writer.ts +23 -0
- package/src/core/agents/state/live-coordination-view.ts +1 -0
- package/src/core/agents/state/live-coordination-writer.ts +5 -0
- package/src/core/artifacts/constants.ts +1 -1
- package/src/core/artifacts/index.ts +565 -30
- package/src/core/config.ts +134 -2
- package/src/core/diagnostics/advice.ts +147 -0
- package/src/core/diagnostics/bundle.ts +1250 -0
- package/src/core/diagnostics/comparison.ts +565 -0
- package/src/core/diagnostics/contract.ts +311 -0
- package/src/core/diagnostics/identity.ts +11 -0
- package/src/core/diagnostics/index.ts +7 -0
- package/src/core/diagnostics/replay.ts +314 -0
- package/src/core/diagnostics/sanitize.ts +97 -0
- package/src/core/events/legacy-storage/compression.ts +130 -0
- package/src/core/events/legacy-storage/index.ts +1 -0
- package/src/core/events/v3/archive-retention.ts +251 -0
- package/src/core/events/v3/bootstrap.ts +10 -0
- package/src/core/events/v3/capabilities.ts +2 -0
- package/src/core/events/v3/coordination-view.ts +100 -11
- package/src/core/events/v3/index.ts +9 -0
- package/src/core/events/v3/live-routing.ts +1 -0
- package/src/core/events/v3/producers/hook-base.ts +14 -2
- package/src/core/events/v3/producers/intake.ts +10 -2
- package/src/core/events/v3/producers/recorder.ts +420 -17
- package/src/core/hooks/adapter/output.ts +12 -1
- package/src/core/hooks/cli.ts +332 -247
- package/src/core/hooks/health.ts +146 -0
- package/src/core/hooks/resolve/transcript.ts +10 -3
- package/src/core/hooks/session-name-presence.ts +6 -1
- package/src/core/qa-artifacts.ts +126 -0
- package/src/core/resources/contract.ts +105 -0
- package/src/core/resources/index.ts +5 -0
- package/src/core/resources/sampler.ts +590 -0
- package/src/core/resources/service-status.ts +62 -0
- package/src/core/resources/service.ts +337 -0
- package/src/core/resources/storage.ts +44 -0
- package/src/core/storage/atomic-json.ts +15 -0
- package/src/core/storage/builtins.ts +62 -6
- package/src/core/storage/logger.ts +2 -0
- package/src/core/storage/query.ts +58 -0
- package/src/core/supervisor/activity.ts +193 -0
- package/src/core/supervisor/contract.ts +312 -0
- package/src/core/supervisor/explanations.ts +104 -0
- package/src/core/supervisor/findings.ts +788 -0
- package/src/core/supervisor/history.ts +61 -0
- package/src/core/supervisor/hook-health-alerts.ts +108 -0
- package/src/core/supervisor/hook-health-storage.ts +25 -0
- package/src/core/supervisor/hook-health.ts +301 -0
- package/src/core/supervisor/hooks.ts +35 -0
- package/src/core/supervisor/index.ts +14 -0
- package/src/core/supervisor/log-feed.ts +131 -0
- package/src/core/supervisor/service.ts +511 -0
- package/src/core/supervisor/services.ts +203 -0
- package/src/core/supervisor/status.ts +59 -0
- package/src/core/supervisor/storage.ts +126 -0
- package/src/core/supervisor/timeline.ts +133 -0
- package/src/core/workflow/admission.ts +215 -0
- package/src/core/workflow/engine.ts +93 -1
- package/src/core/workflow/index.ts +10 -0
- package/src/core/workflow/proof.ts +54 -1
- package/src/core/workflow/run-state.ts +13 -1
- package/src/core/workflow/types.ts +39 -1
- package/src/lib/admission.ts +347 -0
- package/src/lib/agent-browser/client.ts +2 -10
- package/src/lib/browser/capture-fidelity.ts +98 -0
- package/src/lib/browser/client.ts +212 -10
- package/src/lib/browser/critique.ts +62 -7
- package/src/lib/browser/index.ts +65 -0
- package/src/lib/browser/page-review-judge.ts +360 -0
- package/src/lib/browser/page-review-pack.ts +2384 -0
- package/src/lib/browser/qa-run-contracts.ts +743 -0
- package/src/lib/browser/qa-run.ts +1462 -0
- package/src/lib/browser/request-diagnostics.ts +27 -0
- package/src/lib/browser/tiling.ts +32 -0
- package/src/lib/cookies/client.ts +228 -42
- package/src/lib/cookies/extra.ts +28 -0
- package/src/lib/cookies/index.ts +2 -0
- package/src/lib/coord-root-id.ts +23 -0
- package/src/lib/durable-job.ts +407 -0
- package/src/lib/http/client.ts +13 -1
- package/src/lib/instructions/apply.ts +81 -2
- package/src/lib/instructions/templates.ts +11 -2
|
@@ -141,6 +141,14 @@ interface TurnHarnessTimingV3 {
|
|
|
141
141
|
slowest_hook_ms: number;
|
|
142
142
|
}
|
|
143
143
|
|
|
144
|
+
interface CursorResponseRitualV3 {
|
|
145
|
+
turn_id: `tid_${string}`;
|
|
146
|
+
native_turn_id?: string;
|
|
147
|
+
observed_at: string;
|
|
148
|
+
status_box_present: boolean;
|
|
149
|
+
status_box_present_strict: boolean;
|
|
150
|
+
}
|
|
151
|
+
|
|
144
152
|
interface PendingEventV3 {
|
|
145
153
|
source_id?: `hid_${string}`;
|
|
146
154
|
event: EventV3;
|
|
@@ -201,6 +209,10 @@ export interface HookProducerStateV3 {
|
|
|
201
209
|
current_turn_id?: `tid_${string}`;
|
|
202
210
|
/** Native turn identity retained owner-only for transcript attribution. */
|
|
203
211
|
current_native_turn_id?: string;
|
|
212
|
+
/** Latest completed assistant response for Cursor's open turn. The response
|
|
213
|
+
* body is discarded by agent-hook; only these booleans survive until Stop
|
|
214
|
+
* copies them into the authoritative turn.completed ritual observation. */
|
|
215
|
+
cursor_response_ritual?: CursorResponseRitualV3;
|
|
204
216
|
tool_call_count: number;
|
|
205
217
|
tool_call_count_turn_id?: `tid_${string}`;
|
|
206
218
|
last_event_id?: `evt_${string}`;
|
|
@@ -288,6 +300,12 @@ export type RecordHookSignalV3Result =
|
|
|
288
300
|
/** A late signal for a span already closed in memory; preserved in diagnostics, never re-opened. */
|
|
289
301
|
| { state: "suppressed"; reason: "closed_span" }
|
|
290
302
|
| { state: "ignored" }
|
|
303
|
+
| {
|
|
304
|
+
state: "observed";
|
|
305
|
+
generation_id: `gen_${string}`;
|
|
306
|
+
turn_id: `tid_${string}`;
|
|
307
|
+
observed_at: string;
|
|
308
|
+
}
|
|
291
309
|
/** Durably queued in the intake spool; a lease holder or drain hook records it. */
|
|
292
310
|
| { state: "spooled" }
|
|
293
311
|
| { state: "recorded"; event: EventV3; durability: WriteEventV3Result; recovered: boolean };
|
|
@@ -677,7 +695,7 @@ function processHookSignalLocked(
|
|
|
677
695
|
const durability = writeEventV3(input.coordRoot, pendingEvent, input.writerOptions);
|
|
678
696
|
applyCommittedEvent(state, pendingEvent);
|
|
679
697
|
state.pending = undefined;
|
|
680
|
-
publishProducerState(path, state);
|
|
698
|
+
publishProducerState(input.coordRoot, path, state);
|
|
681
699
|
if (pendingSource && incomingSource === pendingSource) {
|
|
682
700
|
recovered = { state: "recorded", event: pendingEvent, durability, recovered: true };
|
|
683
701
|
}
|
|
@@ -736,7 +754,16 @@ function processHookSignalLocked(
|
|
|
736
754
|
);
|
|
737
755
|
const cursorPromptBootstrap = isCursorPromptBootstrap(input);
|
|
738
756
|
const onboarding = buildMidFlightSessionStart(input, state, rootId, cursorPromptBootstrap);
|
|
739
|
-
|
|
757
|
+
// Onboarding commits eagerly even when the triggering hook defers its
|
|
758
|
+
// drain. The coordination view reads committed history only, so a
|
|
759
|
+
// spooled session.started leaves the session invisible to every
|
|
760
|
+
// authority command (set-task, status --end-turn, heal) until some other
|
|
761
|
+
// writer happens to drain the spool.
|
|
762
|
+
const onboardingInput = withEagerDrain(input);
|
|
763
|
+
commitEventLocked(onboardingInput, state, path, onboarding);
|
|
764
|
+
if (midFlightSignalImpliesOpenTurn(input.signal)) {
|
|
765
|
+
commitMidFlightTurnStart(onboardingInput, state, path, rootId);
|
|
766
|
+
}
|
|
740
767
|
if (!cursorPromptBootstrap) {
|
|
741
768
|
writeProducerDiagnosticV3(input.coordRoot, "mid_flight_onboarding", {
|
|
742
769
|
adapter: input.adapter,
|
|
@@ -863,7 +890,7 @@ function processHookSignalLocked(
|
|
|
863
890
|
span_id: state.current_turn_span?.span_id,
|
|
864
891
|
payload: input.payload,
|
|
865
892
|
});
|
|
866
|
-
publishProducerState(path, state);
|
|
893
|
+
publishProducerState(input.coordRoot, path, state);
|
|
867
894
|
return { state: "ignored" };
|
|
868
895
|
}
|
|
869
896
|
|
|
@@ -871,6 +898,51 @@ function processHookSignalLocked(
|
|
|
871
898
|
// Sample once for the native event and every span it opens or closes so
|
|
872
899
|
// their self-contained timing cannot drift by a millisecond.
|
|
873
900
|
const eventClock = signalClock(input);
|
|
901
|
+
if (input.signal === "after-agent-response") {
|
|
902
|
+
if (
|
|
903
|
+
input.adapter !== "cursor" ||
|
|
904
|
+
!state.current_turn_id ||
|
|
905
|
+
!state.current_turn_span ||
|
|
906
|
+
!input.turn_ritual
|
|
907
|
+
) {
|
|
908
|
+
writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_unbound", {
|
|
909
|
+
adapter: input.adapter,
|
|
910
|
+
instance_id: input.instance_id,
|
|
911
|
+
generation_id: state.generation_id,
|
|
912
|
+
signal: input.signal,
|
|
913
|
+
reason: !state.current_turn_id
|
|
914
|
+
? "no_open_turn"
|
|
915
|
+
: !state.current_turn_span
|
|
916
|
+
? "no_open_turn_span"
|
|
917
|
+
: "ritual_observation_missing",
|
|
918
|
+
});
|
|
919
|
+
publishProducerState(input.coordRoot, path, state);
|
|
920
|
+
return { state: "ignored" };
|
|
921
|
+
}
|
|
922
|
+
const observation: CursorResponseRitualV3 = {
|
|
923
|
+
turn_id: state.current_turn_id,
|
|
924
|
+
...(input.payload.turn_id ? { native_turn_id: input.payload.turn_id } : {}),
|
|
925
|
+
observed_at: eventClock.observed_at,
|
|
926
|
+
status_box_present: input.turn_ritual.status_box_present,
|
|
927
|
+
status_box_present_strict: input.turn_ritual.status_box_present_strict,
|
|
928
|
+
};
|
|
929
|
+
state.cursor_response_ritual = observation;
|
|
930
|
+
publishProducerState(input.coordRoot, path, state);
|
|
931
|
+
writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_observed", {
|
|
932
|
+
instance_id: state.instance_id,
|
|
933
|
+
generation_id: state.generation_id,
|
|
934
|
+
turn_id: observation.turn_id,
|
|
935
|
+
...(observation.native_turn_id ? { native_turn_id: observation.native_turn_id } : {}),
|
|
936
|
+
response_observed_at: observation.observed_at,
|
|
937
|
+
status_box_present_strict: observation.status_box_present_strict,
|
|
938
|
+
});
|
|
939
|
+
return {
|
|
940
|
+
state: "observed",
|
|
941
|
+
generation_id: state.generation_id,
|
|
942
|
+
turn_id: observation.turn_id,
|
|
943
|
+
observed_at: observation.observed_at,
|
|
944
|
+
};
|
|
945
|
+
}
|
|
874
946
|
if (input.signal === "user-prompt-submit" && !state.current_turn_span) {
|
|
875
947
|
state.current_turn_span = openSpanStateV3({
|
|
876
948
|
span_id: spanIdV3(),
|
|
@@ -1096,6 +1168,38 @@ function processHookSignalLocked(
|
|
|
1096
1168
|
// Before the signal's own event: the tool call or turn that carries the
|
|
1097
1169
|
// new effort already ran under it, so it must ride the new attestation.
|
|
1098
1170
|
maybeAttestTuningChange(input, state, path, rootId);
|
|
1171
|
+
const cursorResponseRitual =
|
|
1172
|
+
input.adapter === "cursor" &&
|
|
1173
|
+
(input.signal === "stop" || input.signal === "stop-failure") &&
|
|
1174
|
+
state.current_turn_id &&
|
|
1175
|
+
state.cursor_response_ritual?.turn_id === state.current_turn_id
|
|
1176
|
+
? state.cursor_response_ritual
|
|
1177
|
+
: undefined;
|
|
1178
|
+
const terminalTurnRitual =
|
|
1179
|
+
input.adapter === "cursor" && (input.signal === "stop" || input.signal === "stop-failure")
|
|
1180
|
+
? cursorResponseRitual
|
|
1181
|
+
? {
|
|
1182
|
+
status_box_present: cursorResponseRitual.status_box_present,
|
|
1183
|
+
status_box_present_strict: cursorResponseRitual.status_box_present_strict,
|
|
1184
|
+
session_name_required: false,
|
|
1185
|
+
session_name_present: false,
|
|
1186
|
+
}
|
|
1187
|
+
: undefined
|
|
1188
|
+
: input.turn_ritual;
|
|
1189
|
+
if (cursorResponseRitual) {
|
|
1190
|
+
writeProducerDiagnosticV3(input.coordRoot, "cursor_response_ritual_consumed", {
|
|
1191
|
+
instance_id: state.instance_id,
|
|
1192
|
+
generation_id: state.generation_id,
|
|
1193
|
+
turn_id: cursorResponseRitual.turn_id,
|
|
1194
|
+
...(cursorResponseRitual.native_turn_id
|
|
1195
|
+
? { response_native_turn_id: cursorResponseRitual.native_turn_id }
|
|
1196
|
+
: {}),
|
|
1197
|
+
...(input.payload.turn_id ? { stop_native_turn_id: input.payload.turn_id } : {}),
|
|
1198
|
+
response_observed_at: cursorResponseRitual.observed_at,
|
|
1199
|
+
stop_observed_at: eventClock.observed_at,
|
|
1200
|
+
status_box_present_strict: cursorResponseRitual.status_box_present_strict,
|
|
1201
|
+
});
|
|
1202
|
+
}
|
|
1099
1203
|
const event = normalizeHookEventV3(input.signal, eventInput.payload, {
|
|
1100
1204
|
coordRoot: input.coordRoot,
|
|
1101
1205
|
adapter: input.adapter,
|
|
@@ -1154,7 +1258,7 @@ function processHookSignalLocked(
|
|
|
1154
1258
|
child_generation_id: delegation?.child_generation_id,
|
|
1155
1259
|
agent_role: delegation?.role,
|
|
1156
1260
|
stop_remediation: input.stop_remediation,
|
|
1157
|
-
turn_ritual:
|
|
1261
|
+
turn_ritual: terminalTurnRitual,
|
|
1158
1262
|
});
|
|
1159
1263
|
if (!event) return { state: "ignored" };
|
|
1160
1264
|
if (
|
|
@@ -1710,6 +1814,114 @@ function commitRecoveredToolTurnStart(
|
|
|
1710
1814
|
commitEventLocked(input, state, path, event);
|
|
1711
1815
|
}
|
|
1712
1816
|
|
|
1817
|
+
/**
|
|
1818
|
+
* Signals an adapter can only deliver while a turn is executing. A session
|
|
1819
|
+
* onboarded mid-flight by one of these is provably inside a turn, so the
|
|
1820
|
+
* generation opens with one instead of waiting for the next native prompt.
|
|
1821
|
+
* The native prompt path opens its own turn, session boundaries carry no
|
|
1822
|
+
* turn, and compaction can run between turns.
|
|
1823
|
+
*/
|
|
1824
|
+
function midFlightSignalImpliesOpenTurn(signal: HookSignalV3): boolean {
|
|
1825
|
+
switch (signal) {
|
|
1826
|
+
case "session-start":
|
|
1827
|
+
case "session-end":
|
|
1828
|
+
case "user-prompt-submit":
|
|
1829
|
+
case "pre-compact":
|
|
1830
|
+
case "post-compact":
|
|
1831
|
+
return false;
|
|
1832
|
+
default:
|
|
1833
|
+
return true;
|
|
1834
|
+
}
|
|
1835
|
+
}
|
|
1836
|
+
|
|
1837
|
+
/** Commit through the append path even when the hook asked to defer its drain. */
|
|
1838
|
+
function withEagerDrain(input: RecordHookSignalV3Input): RecordHookSignalV3Input {
|
|
1839
|
+
if (!input.writerOptions?.deferDrain) return input;
|
|
1840
|
+
return { ...input, writerOptions: { ...input.writerOptions, deferDrain: false } };
|
|
1841
|
+
}
|
|
1842
|
+
|
|
1843
|
+
/**
|
|
1844
|
+
* Open a derived turn for a session onboarded mid-flight (ADR 0078) by a
|
|
1845
|
+
* signal that only an executing turn can deliver. Without it the fresh
|
|
1846
|
+
* generation has no current turn: command telemetry refuses to join
|
|
1847
|
+
* (`turn_not_started`), tool spans nest under the session span, and after an
|
|
1848
|
+
* epoch rotation (ADR 0137) the live session cannot satisfy its end-of-turn
|
|
1849
|
+
* gate until a human submits the next prompt. The payload's native turn id
|
|
1850
|
+
* is kept when the adapter supplies one, so the turn already running keeps
|
|
1851
|
+
* its identity across the boundary and later signals join it directly.
|
|
1852
|
+
*/
|
|
1853
|
+
function commitMidFlightTurnStart(
|
|
1854
|
+
input: RecordHookSignalV3Input,
|
|
1855
|
+
state: HookProducerStateV3,
|
|
1856
|
+
path: string,
|
|
1857
|
+
rootId: `root_${string}`,
|
|
1858
|
+
recovery?: {
|
|
1859
|
+
source_event: string;
|
|
1860
|
+
confidence: "high" | "medium" | "low";
|
|
1861
|
+
attribution_method: "native_payload" | "session_env";
|
|
1862
|
+
},
|
|
1863
|
+
): void {
|
|
1864
|
+
const fingerprintContext = fingerprintContextV3(
|
|
1865
|
+
input.coordRoot,
|
|
1866
|
+
rootId,
|
|
1867
|
+
state.generation_id,
|
|
1868
|
+
state.privacy_epoch_id,
|
|
1869
|
+
);
|
|
1870
|
+
const clock = signalClock(input);
|
|
1871
|
+
const span = openSpanStateV3({
|
|
1872
|
+
span_id: spanIdV3(),
|
|
1873
|
+
parent_span_id: state.session_span.span_id,
|
|
1874
|
+
boot_id: state.boot_id,
|
|
1875
|
+
clock,
|
|
1876
|
+
});
|
|
1877
|
+
state.current_turn_span = span;
|
|
1878
|
+
const nativeTurnId = input.payload.turn_id;
|
|
1879
|
+
state.current_native_turn_id = nativeTurnId;
|
|
1880
|
+
const event = normalizeHookEventV3("user-prompt-submit", recoveryBoundaryPayload(input.payload), {
|
|
1881
|
+
coordRoot: input.coordRoot,
|
|
1882
|
+
adapter: input.adapter,
|
|
1883
|
+
adapterVersion: input.adapterVersion,
|
|
1884
|
+
harnessVersion: input.harnessVersion,
|
|
1885
|
+
root_id: rootId,
|
|
1886
|
+
run_id: input.run_id,
|
|
1887
|
+
workflow_id: input.workflow_id,
|
|
1888
|
+
workflow_agent_id: input.workflow_agent_id,
|
|
1889
|
+
instance_id: state.instance_id,
|
|
1890
|
+
generation_id: state.generation_id,
|
|
1891
|
+
attestation_id: state.attestation_id,
|
|
1892
|
+
producer_id: input.producer_id,
|
|
1893
|
+
boot_id: state.boot_id,
|
|
1894
|
+
sequence: state.next_sequence,
|
|
1895
|
+
build_id: input.build_id,
|
|
1896
|
+
platform: input.platform,
|
|
1897
|
+
bridge: input.bridge,
|
|
1898
|
+
capability_profile: state.capability_profile,
|
|
1899
|
+
fingerprintContext,
|
|
1900
|
+
turn_native_id: nativeTurnId ?? `mid-flight:${state.generation_id}:${state.turn_ordinal + 1}`,
|
|
1901
|
+
span_id: span.span_id,
|
|
1902
|
+
caused_by: state.last_event_id ? [state.last_event_id] : [],
|
|
1903
|
+
observed_at: clock.observed_at,
|
|
1904
|
+
monotonic_ns: orderedEventMonotonic(state, input.monotonic_ns),
|
|
1905
|
+
clock_id: state.clock_id,
|
|
1906
|
+
});
|
|
1907
|
+
if (event?.event_type !== "turn.started") {
|
|
1908
|
+
throw new Error("mid-flight turn start could not be normalized");
|
|
1909
|
+
}
|
|
1910
|
+
event.provenance = {
|
|
1911
|
+
...event.provenance,
|
|
1912
|
+
source_event: recovery?.source_event ?? `${input.adapter}.recovery`,
|
|
1913
|
+
attestation: "derived",
|
|
1914
|
+
confidence: recovery?.confidence ?? (nativeTurnId ? "medium" : "low"),
|
|
1915
|
+
attribution: {
|
|
1916
|
+
method: recovery?.attribution_method ?? (nativeTurnId ? "native_payload" : "session_env"),
|
|
1917
|
+
state: "verified",
|
|
1918
|
+
subject_instance_id: state.instance_id,
|
|
1919
|
+
},
|
|
1920
|
+
};
|
|
1921
|
+
assertEventV3(event);
|
|
1922
|
+
commitEventLocked(input, state, path, event);
|
|
1923
|
+
}
|
|
1924
|
+
|
|
1713
1925
|
/** The single pending-publish/write/apply/publish cycle every locked event commit uses. */
|
|
1714
1926
|
function commitEventLocked(
|
|
1715
1927
|
input: RecordHookSignalV3Input,
|
|
@@ -1721,11 +1933,11 @@ function commitEventLocked(
|
|
|
1721
1933
|
markObservedClockRegressionV3(event, state.last_observed_at);
|
|
1722
1934
|
assertEventV3(event);
|
|
1723
1935
|
state.pending = { ...(sourceId ? { source_id: sourceId } : {}), event };
|
|
1724
|
-
publishProducerState(path, state);
|
|
1936
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1725
1937
|
const durability = writeEventV3(input.coordRoot, event, input.writerOptions);
|
|
1726
1938
|
applyCommittedEvent(state, event);
|
|
1727
1939
|
state.pending = undefined;
|
|
1728
|
-
publishProducerState(path, state);
|
|
1940
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1729
1941
|
return durability;
|
|
1730
1942
|
}
|
|
1731
1943
|
|
|
@@ -1782,7 +1994,7 @@ function commitContextObservation(
|
|
|
1782
1994
|
contextProvenance?.source_witness &&
|
|
1783
1995
|
state.last_context_source_witness === contextProvenance.source_witness
|
|
1784
1996
|
) {
|
|
1785
|
-
publishProducerState(path, state);
|
|
1997
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1786
1998
|
return;
|
|
1787
1999
|
}
|
|
1788
2000
|
if (measurement.state === "observed" && contextProvenance?.source_witness) {
|
|
@@ -1913,13 +2125,13 @@ function maybeCommitActiveRuntimeContextObservation(
|
|
|
1913
2125
|
return;
|
|
1914
2126
|
}
|
|
1915
2127
|
if (input.adapter === "cursor" && state.cursor_mode === "cloud") {
|
|
1916
|
-
publishProducerState(path, state);
|
|
2128
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1917
2129
|
return;
|
|
1918
2130
|
}
|
|
1919
2131
|
|
|
1920
2132
|
const transcriptPath = runtimeTranscriptPath(input, state);
|
|
1921
2133
|
if (!transcriptPath && input.adapter !== "cursor") {
|
|
1922
|
-
publishProducerState(path, state);
|
|
2134
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1923
2135
|
return;
|
|
1924
2136
|
}
|
|
1925
2137
|
const runtime = readRuntimeContextTelemetry(
|
|
@@ -1938,7 +2150,7 @@ function maybeCommitActiveRuntimeContextObservation(
|
|
|
1938
2150
|
);
|
|
1939
2151
|
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
1940
2152
|
if (runtime.state !== "observed") {
|
|
1941
|
-
publishProducerState(path, state);
|
|
2153
|
+
publishProducerState(input.coordRoot, path, state);
|
|
1942
2154
|
return;
|
|
1943
2155
|
}
|
|
1944
2156
|
|
|
@@ -2205,7 +2417,7 @@ function reconcilePendingRuntimeContexts(
|
|
|
2205
2417
|
if (state.pending_runtime_contexts?.length === 0) {
|
|
2206
2418
|
state.pending_runtime_contexts = undefined;
|
|
2207
2419
|
}
|
|
2208
|
-
publishProducerState(path, state);
|
|
2420
|
+
publishProducerState(input.coordRoot, path, state);
|
|
2209
2421
|
}
|
|
2210
2422
|
|
|
2211
2423
|
function reconcilePendingRuntimeContextsBeforeApprovedEnd(
|
|
@@ -2983,7 +3195,7 @@ export function recordApprovedSessionEndV3(
|
|
|
2983
3195
|
const durability = writeEventV3(input.coordRoot, pending, input.writerOptions);
|
|
2984
3196
|
applyCommittedEvent(state, pending);
|
|
2985
3197
|
state.pending = undefined;
|
|
2986
|
-
publishProducerState(record.path, state);
|
|
3198
|
+
publishProducerState(input.coordRoot, record.path, state);
|
|
2987
3199
|
recovered = true;
|
|
2988
3200
|
if (pending.event_type === "session.ended") {
|
|
2989
3201
|
return { state: "recorded", event: pending, durability, recovered };
|
|
@@ -3080,11 +3292,11 @@ export function recordApprovedSessionEndV3(
|
|
|
3080
3292
|
assertEventV3(event);
|
|
3081
3293
|
|
|
3082
3294
|
state.pending = { event };
|
|
3083
|
-
publishProducerState(record.path, state);
|
|
3295
|
+
publishProducerState(input.coordRoot, record.path, state);
|
|
3084
3296
|
const durability = writeEventV3(input.coordRoot, event, input.writerOptions);
|
|
3085
3297
|
applyCommittedEvent(state, event);
|
|
3086
3298
|
state.pending = undefined;
|
|
3087
|
-
publishProducerState(record.path, state);
|
|
3299
|
+
publishProducerState(input.coordRoot, record.path, state);
|
|
3088
3300
|
return { state: "recorded", event, durability, recovered };
|
|
3089
3301
|
} finally {
|
|
3090
3302
|
lease.release();
|
|
@@ -3168,7 +3380,7 @@ export function salvageOpenSpansV3(input: SalvageOpenSpansV3Input): SalvageOpenS
|
|
|
3168
3380
|
writeEventV3(input.coordRoot, pendingEvent, input.writerOptions);
|
|
3169
3381
|
applyCommittedEvent(state, pendingEvent);
|
|
3170
3382
|
state.pending = undefined;
|
|
3171
|
-
publishProducerState(record.path, state);
|
|
3383
|
+
publishProducerState(input.coordRoot, record.path, state);
|
|
3172
3384
|
}
|
|
3173
3385
|
const allowed = new Set(input.allowed_span_ids);
|
|
3174
3386
|
const fingerprintContext = fingerprintContextV3(
|
|
@@ -3250,6 +3462,155 @@ export function listHookProducerStateRecordsV3(
|
|
|
3250
3462
|
);
|
|
3251
3463
|
}
|
|
3252
3464
|
|
|
3465
|
+
export interface ReanchorArchivedHookProducersV3Input {
|
|
3466
|
+
coordRoot: string;
|
|
3467
|
+
archivedEpoch: string;
|
|
3468
|
+
mode: EventV3WriteMode;
|
|
3469
|
+
build_id: `build_${string}`;
|
|
3470
|
+
platform: "linux" | "windows" | "macos" | "unknown";
|
|
3471
|
+
observed_at?: string;
|
|
3472
|
+
}
|
|
3473
|
+
|
|
3474
|
+
export interface ReanchorArchivedHookProducersV3Result {
|
|
3475
|
+
sessions: number;
|
|
3476
|
+
turns: number;
|
|
3477
|
+
}
|
|
3478
|
+
|
|
3479
|
+
/**
|
|
3480
|
+
* Re-anchor every live archived hook producer into a newly activated epoch.
|
|
3481
|
+
*
|
|
3482
|
+
* The archive rename is the rotation's atomic snapshot: it includes every
|
|
3483
|
+
* state published before the boundary without copying any old boot sequence
|
|
3484
|
+
* or causal link into the successor. Each live session gets a fresh
|
|
3485
|
+
* generation and attestation. Only a turn that was open at the boundary is
|
|
3486
|
+
* reopened, which makes command telemetry joinable before another adapter
|
|
3487
|
+
* hook fires while preserving the between-turn state for idle sessions.
|
|
3488
|
+
*/
|
|
3489
|
+
export function reanchorArchivedHookProducersV3(
|
|
3490
|
+
input: ReanchorArchivedHookProducersV3Input,
|
|
3491
|
+
): ReanchorArchivedHookProducersV3Result {
|
|
3492
|
+
const control = readEventV3ControlState(input.coordRoot);
|
|
3493
|
+
if (control.state !== input.mode) {
|
|
3494
|
+
throw new Error(`event_v3_rotation_reanchor_gate_closed:${control.state}`);
|
|
3495
|
+
}
|
|
3496
|
+
const rootId = control.genesis.event.scope.root_id as `root_${string}`;
|
|
3497
|
+
const epochId = control.genesis.profile.privacy_key_epoch;
|
|
3498
|
+
const genesisId = control.genesis.event.payload.genesis_id as `gex_${string}`;
|
|
3499
|
+
const boundaryEventId =
|
|
3500
|
+
control.state === "candidate"
|
|
3501
|
+
? control.genesis.event.event_id
|
|
3502
|
+
: control.activation.event.event_id;
|
|
3503
|
+
const observedAt = input.observed_at ?? new Date().toISOString();
|
|
3504
|
+
let sessions = 0;
|
|
3505
|
+
let turns = 0;
|
|
3506
|
+
|
|
3507
|
+
for (const archived of listArchivedHookProducerStatesV3(input.archivedEpoch)) {
|
|
3508
|
+
const previous = archived.state;
|
|
3509
|
+
if (previous.terminal || !previous.started_event_id) continue;
|
|
3510
|
+
const path = producerStatePath(input.coordRoot, previous.adapter, archived.sessionHash);
|
|
3511
|
+
const lease = acquireStateLeaseWithRetry(input.coordRoot, path, 40);
|
|
3512
|
+
if (!lease) {
|
|
3513
|
+
throw new Error(`event_v3_rotation_reanchor_busy:${previous.instance_id}`);
|
|
3514
|
+
}
|
|
3515
|
+
try {
|
|
3516
|
+
if (existsSync(path)) {
|
|
3517
|
+
const current = readProducerState(path);
|
|
3518
|
+
if (current.epoch_genesis_id === genesisId) continue;
|
|
3519
|
+
}
|
|
3520
|
+
const sourceEvent = `${previous.adapter}.epoch-rotation-reanchor`;
|
|
3521
|
+
const rotationInput: RecordHookSignalV3Input = {
|
|
3522
|
+
coordRoot: input.coordRoot,
|
|
3523
|
+
mode: input.mode,
|
|
3524
|
+
signal: "session-start",
|
|
3525
|
+
payload: {
|
|
3526
|
+
raw: {},
|
|
3527
|
+
...(previous.current_native_turn_id ? { turn_id: previous.current_native_turn_id } : {}),
|
|
3528
|
+
...(previous.adapter === "cursor" && previous.cursor_mode
|
|
3529
|
+
? { cursor_mode: previous.cursor_mode }
|
|
3530
|
+
: {}),
|
|
3531
|
+
},
|
|
3532
|
+
adapter: previous.adapter,
|
|
3533
|
+
instance_id: previous.instance_id,
|
|
3534
|
+
producer_id: "prd_agent-hook",
|
|
3535
|
+
build_id: input.build_id,
|
|
3536
|
+
platform: input.platform,
|
|
3537
|
+
observed_at: observedAt,
|
|
3538
|
+
writerOptions: { expectedGenesisId: genesisId },
|
|
3539
|
+
};
|
|
3540
|
+
const state = newProducerState(
|
|
3541
|
+
rotationInput,
|
|
3542
|
+
previous.session_id,
|
|
3543
|
+
epochId,
|
|
3544
|
+
boundaryEventId as `evt_${string}`,
|
|
3545
|
+
genesisId,
|
|
3546
|
+
);
|
|
3547
|
+
const sessionStart = buildMidFlightSessionStart(rotationInput, state, rootId);
|
|
3548
|
+
if (sessionStart.event_type !== "session.started") {
|
|
3549
|
+
throw new Error("rotation re-anchor session start could not be normalized");
|
|
3550
|
+
}
|
|
3551
|
+
sessionStart.provenance = {
|
|
3552
|
+
...sessionStart.provenance,
|
|
3553
|
+
source_event: sourceEvent,
|
|
3554
|
+
attestation: "derived",
|
|
3555
|
+
confidence: "high",
|
|
3556
|
+
attribution: {
|
|
3557
|
+
method: "session_env",
|
|
3558
|
+
state: "verified",
|
|
3559
|
+
subject_instance_id: state.instance_id,
|
|
3560
|
+
},
|
|
3561
|
+
};
|
|
3562
|
+
sessionStart.payload.resume = {
|
|
3563
|
+
state: "unknown",
|
|
3564
|
+
reason: "epoch_rotation_reanchor",
|
|
3565
|
+
};
|
|
3566
|
+
assertEventV3(sessionStart);
|
|
3567
|
+
commitEventLocked(rotationInput, state, path, sessionStart);
|
|
3568
|
+
sessions += 1;
|
|
3569
|
+
|
|
3570
|
+
if (previous.current_turn_id && previous.current_turn_span) {
|
|
3571
|
+
commitMidFlightTurnStart(rotationInput, state, path, rootId, {
|
|
3572
|
+
source_event: sourceEvent,
|
|
3573
|
+
confidence: "high",
|
|
3574
|
+
attribution_method: "session_env",
|
|
3575
|
+
});
|
|
3576
|
+
turns += 1;
|
|
3577
|
+
}
|
|
3578
|
+
} finally {
|
|
3579
|
+
lease.release();
|
|
3580
|
+
}
|
|
3581
|
+
}
|
|
3582
|
+
return { sessions, turns };
|
|
3583
|
+
}
|
|
3584
|
+
|
|
3585
|
+
function listArchivedHookProducerStatesV3(
|
|
3586
|
+
archivedEpoch: string,
|
|
3587
|
+
): Array<{ sessionHash: `hid_${string}`; state: HookProducerStateV3 }> {
|
|
3588
|
+
const producerRoot = join(resolve(archivedEpoch), "private-producers");
|
|
3589
|
+
if (!existsSync(producerRoot)) return [];
|
|
3590
|
+
const records: Array<{ sessionHash: `hid_${string}`; state: HookProducerStateV3 }> = [];
|
|
3591
|
+
for (const adapter of ["claude-code", "codex", "cursor"] as const) {
|
|
3592
|
+
const directory = join(producerRoot, adapter);
|
|
3593
|
+
if (!existsSync(directory)) continue;
|
|
3594
|
+
const metadata = lstatSync(directory);
|
|
3595
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink()) {
|
|
3596
|
+
throw new Error("V3 archived producer state directory is unsafe");
|
|
3597
|
+
}
|
|
3598
|
+
for (const name of readdirSync(directory).filter((entry) =>
|
|
3599
|
+
/^hid_[a-f0-9]{64}\.json$/.test(entry),
|
|
3600
|
+
)) {
|
|
3601
|
+
records.push({
|
|
3602
|
+
sessionHash: name.slice(0, -".json".length) as `hid_${string}`,
|
|
3603
|
+
state: readProducerState(join(directory, name)),
|
|
3604
|
+
});
|
|
3605
|
+
}
|
|
3606
|
+
}
|
|
3607
|
+
return records.sort(
|
|
3608
|
+
(left, right) =>
|
|
3609
|
+
left.state.generation_id.localeCompare(right.state.generation_id) ||
|
|
3610
|
+
left.sessionHash.localeCompare(right.sessionHash),
|
|
3611
|
+
);
|
|
3612
|
+
}
|
|
3613
|
+
|
|
3253
3614
|
function hookSignalCapability(signal: HookSignalV3): AdapterSignalV3 {
|
|
3254
3615
|
switch (signal) {
|
|
3255
3616
|
case "session-start":
|
|
@@ -3258,6 +3619,8 @@ function hookSignalCapability(signal: HookSignalV3): AdapterSignalV3 {
|
|
|
3258
3619
|
return "session_end";
|
|
3259
3620
|
case "user-prompt-submit":
|
|
3260
3621
|
return "prompt";
|
|
3622
|
+
case "after-agent-response":
|
|
3623
|
+
return "assistant_reply_text";
|
|
3261
3624
|
case "stop":
|
|
3262
3625
|
case "stop-failure":
|
|
3263
3626
|
return "turn_completion";
|
|
@@ -3515,6 +3878,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
|
|
|
3515
3878
|
if (event.event_type === "turn.started") {
|
|
3516
3879
|
const nextTurnId = (event.scope as { turn_id: `tid_${string}` }).turn_id;
|
|
3517
3880
|
state.current_turn_id = nextTurnId;
|
|
3881
|
+
state.cursor_response_ritual = undefined;
|
|
3518
3882
|
state.session_start_derivation = undefined;
|
|
3519
3883
|
if (state.tool_call_count_turn_id !== nextTurnId) {
|
|
3520
3884
|
state.tool_call_count = 0;
|
|
@@ -3600,6 +3964,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
|
|
|
3600
3964
|
}
|
|
3601
3965
|
state.current_turn_id = undefined;
|
|
3602
3966
|
state.current_native_turn_id = undefined;
|
|
3967
|
+
state.cursor_response_ritual = undefined;
|
|
3603
3968
|
state.current_turn_span = undefined;
|
|
3604
3969
|
state.tool_call_count = 0;
|
|
3605
3970
|
state.tool_call_count_turn_id = undefined;
|
|
@@ -3824,7 +4189,12 @@ function acquireStateLease(coordRoot: string, statePath: string) {
|
|
|
3824
4189
|
mkdirSync(directory, { recursive: true, mode: 0o700 });
|
|
3825
4190
|
chmodSync(producerRoot, 0o700);
|
|
3826
4191
|
chmodSync(directory, 0o700);
|
|
3827
|
-
|
|
4192
|
+
const acquiredControl = readEventV3ControlState(coordRoot);
|
|
4193
|
+
const acquiredGenesis =
|
|
4194
|
+
acquiredControl.state === "candidate" || acquiredControl.state === "active"
|
|
4195
|
+
? acquiredControl.genesis.event.payload.genesis_id
|
|
4196
|
+
: undefined;
|
|
4197
|
+
const lease = acquireNoClobberLease({
|
|
3828
4198
|
path: `${statePath}.lease`,
|
|
3829
4199
|
scope: "event-v3-hook-producer",
|
|
3830
4200
|
authoritySha256: createHash("sha256")
|
|
@@ -3835,9 +4205,32 @@ function acquireStateLease(coordRoot: string, statePath: string) {
|
|
|
3835
4205
|
staleAfterMs: 5_000,
|
|
3836
4206
|
validateStaleOwner: (owner) => owner.host === hostname() && !pidIsAlive(owner.pid),
|
|
3837
4207
|
});
|
|
4208
|
+
return {
|
|
4209
|
+
...lease,
|
|
4210
|
+
release() {
|
|
4211
|
+
try {
|
|
4212
|
+
lease.release();
|
|
4213
|
+
} catch (error) {
|
|
4214
|
+
const current = readEventV3ControlState(coordRoot);
|
|
4215
|
+
const epochReplaced =
|
|
4216
|
+
acquiredGenesis !== undefined &&
|
|
4217
|
+
(current.state === "candidate" || current.state === "active") &&
|
|
4218
|
+
current.genesis.event.payload.genesis_id !== acquiredGenesis;
|
|
4219
|
+
if ((error as NodeJS.ErrnoException).code === "ENOENT" && epochReplaced) return;
|
|
4220
|
+
throw error;
|
|
4221
|
+
}
|
|
4222
|
+
},
|
|
4223
|
+
};
|
|
3838
4224
|
}
|
|
3839
4225
|
|
|
3840
|
-
function publishProducerState(path: string, state: HookProducerStateV3): void {
|
|
4226
|
+
function publishProducerState(coordRoot: string, path: string, state: HookProducerStateV3): void {
|
|
4227
|
+
const control = readEventV3ControlState(coordRoot);
|
|
4228
|
+
if (
|
|
4229
|
+
(control.state === "candidate" || control.state === "active") &&
|
|
4230
|
+
state.epoch_genesis_id !== control.genesis.event.payload.genesis_id
|
|
4231
|
+
) {
|
|
4232
|
+
return;
|
|
4233
|
+
}
|
|
3841
4234
|
const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
3842
4235
|
let fd: number | undefined;
|
|
3843
4236
|
try {
|
|
@@ -3904,6 +4297,7 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
3904
4297
|
"current_native_turn_id",
|
|
3905
4298
|
"current_turn_span",
|
|
3906
4299
|
"cursor_mode",
|
|
4300
|
+
"cursor_response_ritual",
|
|
3907
4301
|
"delegations",
|
|
3908
4302
|
"epoch_genesis_id",
|
|
3909
4303
|
"format",
|
|
@@ -4021,6 +4415,15 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
4021
4415
|
(typeof state.current_native_turn_id !== "string" ||
|
|
4022
4416
|
state.current_native_turn_id.length === 0 ||
|
|
4023
4417
|
state.current_native_turn_id.length > 512)) ||
|
|
4418
|
+
(state.cursor_response_ritual !== undefined &&
|
|
4419
|
+
(!/^tid_[a-f0-9]{64}$/.test(state.cursor_response_ritual.turn_id) ||
|
|
4420
|
+
(state.cursor_response_ritual.native_turn_id !== undefined &&
|
|
4421
|
+
(typeof state.cursor_response_ritual.native_turn_id !== "string" ||
|
|
4422
|
+
state.cursor_response_ritual.native_turn_id.length === 0 ||
|
|
4423
|
+
state.cursor_response_ritual.native_turn_id.length > 512)) ||
|
|
4424
|
+
!Number.isFinite(Date.parse(state.cursor_response_ritual.observed_at)) ||
|
|
4425
|
+
typeof state.cursor_response_ritual.status_box_present !== "boolean" ||
|
|
4426
|
+
typeof state.cursor_response_ritual.status_box_present_strict !== "boolean")) ||
|
|
4024
4427
|
(state.last_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.last_event_id)) ||
|
|
4025
4428
|
(state.last_monotonic_ns !== undefined && !/^\d+$/.test(state.last_monotonic_ns)) ||
|
|
4026
4429
|
(state.last_observed_at !== undefined &&
|
|
@@ -31,10 +31,21 @@ export type SystemEvent =
|
|
|
31
31
|
| "PreToolUse"
|
|
32
32
|
| "PostToolUse";
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* Whether this adapter can actually receive injected context for an event.
|
|
36
|
+
* Cursor's beforeSubmitPrompt hook can allow or block a turn but cannot inject
|
|
37
|
+
* model context, so anything rendered for that event is discarded. A caller
|
|
38
|
+
* that consumes state to build the text (draining a mailbox, for instance)
|
|
39
|
+
* must check this first, or the state is spent on output nobody reads.
|
|
40
|
+
*/
|
|
41
|
+
export function canReceiveContext(adapter: Adapter, event: SystemEvent): boolean {
|
|
42
|
+
return !(adapter === "cursor" && event === "UserPromptSubmit");
|
|
43
|
+
}
|
|
44
|
+
|
|
34
45
|
/** Emit a context-injection (peer table, wiring check, council pending, …). */
|
|
35
46
|
export function emitContext(adapter: Adapter, event: SystemEvent, text: string): void {
|
|
36
47
|
if (!text || text.length === 0) return;
|
|
37
|
-
if (adapter
|
|
48
|
+
if (!canReceiveContext(adapter, event)) return;
|
|
38
49
|
const json = buildContextJson(adapter, event, text);
|
|
39
50
|
process.stdout.write(`${JSON.stringify(json)}\n`);
|
|
40
51
|
}
|