harnery 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -94
- package/dist/commands/agents.d.ts +37 -6
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +466 -371
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +31 -6
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +2 -2
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/commands/events.js +18 -1
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts +4 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +199 -0
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +84 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +12 -0
- package/dist/core/agents/claim-path.d.ts +11 -0
- package/dist/core/agents/claim-path.d.ts.map +1 -0
- package/dist/core/agents/claim-path.js +22 -0
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/coord-client.d.ts +29 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +88 -9
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +245 -13
- package/dist/core/agents/live-lifecycle-v3.js +9 -4
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +8 -3
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +36 -17
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +115 -22
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/session-name-display.d.ts +1 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +8 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-reader.js +25 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +9 -48
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +34 -34
- package/dist/core/agents/state/live-coordination-view.d.ts +6 -8
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +16 -67
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/agents/state/names.d.ts +9 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +190 -182
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -5
- package/dist/core/artifacts/constants.d.ts +5 -0
- package/dist/core/artifacts/constants.d.ts.map +1 -0
- package/dist/core/artifacts/constants.js +4 -0
- package/dist/core/artifacts/index.d.ts +24 -3
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +96 -8
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +851 -16
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +50 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.d.ts +11 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +26 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +8 -5
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +7 -4
- package/dist/core/events/v3/latency.d.ts +31 -1
- package/dist/core/events/v3/latency.d.ts.map +1 -1
- package/dist/core/events/v3/latency.js +127 -3
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +42 -20
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +153 -41
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +10 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +90 -13
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +83 -2
- package/dist/core/events/v3/producers/intake.d.ts +13 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +36 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +117 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +992 -27
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +52 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +21 -6
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/parse.d.ts +3 -0
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +14 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +142 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +869 -0
- package/dist/core/hooks/cli.js +318 -61
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +39 -0
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
- package/dist/core/hooks/remediation-cap.js +63 -0
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +33 -9
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +33 -10
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +37 -0
- package/dist/core/semantic/adapters.d.ts.map +1 -0
- package/dist/core/semantic/adapters.js +360 -0
- package/dist/core/semantic/contract.d.ts +1072 -0
- package/dist/core/semantic/contract.d.ts.map +1 -0
- package/dist/core/semantic/contract.js +331 -0
- package/dist/core/semantic/evidence.d.ts +11 -0
- package/dist/core/semantic/evidence.d.ts.map +1 -0
- package/dist/core/semantic/evidence.js +262 -0
- package/dist/core/semantic/index.d.ts +14 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +13 -0
- package/dist/core/semantic/once.d.ts +38 -0
- package/dist/core/semantic/once.d.ts.map +1 -0
- package/dist/core/semantic/once.js +364 -0
- package/dist/core/semantic/prompt.d.ts +12 -0
- package/dist/core/semantic/prompt.d.ts.map +1 -0
- package/dist/core/semantic/prompt.js +83 -0
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +27 -0
- package/dist/core/semantic/scheduler.d.ts.map +1 -0
- package/dist/core/semantic/scheduler.js +91 -0
- package/dist/core/semantic/service-status.d.ts +51 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -0
- package/dist/core/semantic/service-status.js +140 -0
- package/dist/core/semantic/service.d.ts +52 -0
- package/dist/core/semantic/service.d.ts.map +1 -0
- package/dist/core/semantic/service.js +559 -0
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +81 -0
- package/dist/core/semantic/storage.d.ts.map +1 -0
- package/dist/core/semantic/storage.js +180 -0
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +18 -0
- package/dist/core/semantic/validate.d.ts.map +1 -0
- package/dist/core/semantic/validate.js +207 -0
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/browser/client.d.ts +11 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +13 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.d.ts +25 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -0
- package/dist/lib/browser/standalone-html.js +284 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +1 -0
- package/dist/lib/instructions/templates.d.ts +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +149 -4
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +34 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +3073 -581
- package/src/commander.ts +462 -93
- package/src/commands/agents.ts +617 -355
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +31 -9
- package/src/commands/conversations.ts +279 -0
- package/src/commands/decision.ts +8 -2
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/events.ts +21 -1
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/presence.ts +7 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +244 -0
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +92 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/canonical-emit.ts +15 -0
- package/src/core/agents/claim-path.ts +23 -0
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/coord-client.ts +92 -8
- package/src/core/agents/live-authority-v3.ts +342 -14
- package/src/core/agents/live-lifecycle-v3.ts +14 -4
- package/src/core/agents/live-observation-v3.ts +13 -3
- package/src/core/agents/render/prompt-context.ts +40 -16
- package/src/core/agents/rules/stop-hook.ts +129 -25
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/session-name-display.ts +9 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-reader.ts +69 -0
- package/src/core/agents/state/heartbeat-writer.ts +47 -84
- package/src/core/agents/state/live-coordination-view.ts +17 -81
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/agents/state/names.ts +190 -182
- package/src/core/agents/state/stale-sweep.ts +25 -5
- package/src/core/artifacts/constants.ts +4 -0
- package/src/core/artifacts/index.ts +113 -8
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +56 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +37 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +26 -2
- package/src/core/events/v3/latency.ts +213 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +182 -45
- package/src/core/events/v3/producers/command-recorder.ts +10 -1
- package/src/core/events/v3/producers/coordination-recorder.ts +112 -15
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +116 -2
- package/src/core/events/v3/producers/intake.ts +48 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +1403 -30
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +143 -0
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +66 -5
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/parse.ts +16 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +1200 -0
- package/src/core/hooks/cli.ts +342 -64
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +83 -0
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +55 -11
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +452 -0
- package/src/core/semantic/contract.ts +430 -0
- package/src/core/semantic/evidence.ts +336 -0
- package/src/core/semantic/index.ts +201 -0
- package/src/core/semantic/once.ts +496 -0
- package/src/core/semantic/prompt.ts +96 -0
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +151 -0
- package/src/core/semantic/service-status.ts +212 -0
- package/src/core/semantic/service.ts +681 -0
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +300 -0
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +243 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/browser/client.ts +21 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/standalone-html.ts +312 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/apply.ts +1 -0
- package/src/lib/instructions/templates.ts +154 -4
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -17,10 +17,18 @@ import { hostname } from "node:os";
|
|
|
17
17
|
import { basename, join, resolve } from "node:path";
|
|
18
18
|
import type { Adapter } from "../../../adapter.ts";
|
|
19
19
|
import { extractBashCommand, type ParsedPayload } from "../../../hooks/adapter/parse.ts";
|
|
20
|
+
import {
|
|
21
|
+
discoverCodexSessionTranscript,
|
|
22
|
+
type RuntimeContextTelemetry,
|
|
23
|
+
type RuntimeTelemetryOptions,
|
|
24
|
+
readRuntimeContextTelemetry,
|
|
25
|
+
readRuntimeTuning,
|
|
26
|
+
} from "../../../hooks/adapter/runtime-telemetry.ts";
|
|
20
27
|
import { fsyncParentDirectory } from "../../../workflow/durable-record.ts";
|
|
21
28
|
import { acquireNoClobberLease } from "../../../workflow/workspaces/leases.ts";
|
|
29
|
+
import type { RuntimeAttestationV3Base } from "../base-contract.ts";
|
|
22
30
|
import { buildEventV3 } from "../builder.ts";
|
|
23
|
-
import { fingerprintV3, normalizeNativeIdV3 } from "../canonical.ts";
|
|
31
|
+
import { canonicalJsonV3, fingerprintV3, normalizeNativeIdV3 } from "../canonical.ts";
|
|
24
32
|
import {
|
|
25
33
|
type AdapterSignalV3,
|
|
26
34
|
adapterCapabilityProfileDigestV3,
|
|
@@ -33,8 +41,19 @@ import { markObservedClockRegressionV3 } from "../clock-order.ts";
|
|
|
33
41
|
import type { EventV3 } from "../contract.ts";
|
|
34
42
|
import { type EventV3WriteMode, readEventV3ControlState } from "../control.ts";
|
|
35
43
|
import { fingerprintContextV3 } from "../fingerprint-keys.ts";
|
|
36
|
-
import {
|
|
44
|
+
import {
|
|
45
|
+
attestationIdV3,
|
|
46
|
+
clockIdV3,
|
|
47
|
+
delegationIdV3,
|
|
48
|
+
eventIdV3,
|
|
49
|
+
generationIdV3,
|
|
50
|
+
spanIdV3,
|
|
51
|
+
} from "../ids.ts";
|
|
37
52
|
import { readLedgerV3 } from "../reader.ts";
|
|
53
|
+
import {
|
|
54
|
+
effectiveRuntimeTelemetryCapabilitiesV3,
|
|
55
|
+
type RuntimeTelemetryCapabilitiesV3,
|
|
56
|
+
} from "../runtime-telemetry-capabilities.ts";
|
|
38
57
|
import {
|
|
39
58
|
closeSpanStateV3,
|
|
40
59
|
type OpenSpanStateV3,
|
|
@@ -44,8 +63,10 @@ import {
|
|
|
44
63
|
} from "../span-state.ts";
|
|
45
64
|
import {
|
|
46
65
|
type ContextMeasurementV3,
|
|
66
|
+
type ContextTelemetryProvenanceV3,
|
|
47
67
|
extractTurnTelemetryV3,
|
|
48
68
|
type TelemetryObservationV3,
|
|
69
|
+
type TurnTelemetryV3,
|
|
49
70
|
} from "../turn-telemetry.ts";
|
|
50
71
|
import { assertEventV3, validateEventV3 } from "../validate.ts";
|
|
51
72
|
import {
|
|
@@ -74,6 +95,14 @@ const CLOSED_SPAN_TURN_RETENTION = 2;
|
|
|
74
95
|
const CLOSED_SPAN_MEMORY_CAP = 512;
|
|
75
96
|
const CLOSED_TURN_MEMORY_CAP = 16;
|
|
76
97
|
const SPAN_SOFT_WATERMARK = 128;
|
|
98
|
+
const PENDING_RUNTIME_CONTEXT_CAP = 4;
|
|
99
|
+
const RUNTIME_CONTEXT_RETRY_LIMIT = 2;
|
|
100
|
+
/** Active turns pay for at most one bounded adapter telemetry read per interval. */
|
|
101
|
+
const ACTIVE_RUNTIME_CONTEXT_PROBE_INTERVAL_MS = 15_000;
|
|
102
|
+
/** Codex can flush the terminal row just after Stop; keep this grace bounded and off other hooks. */
|
|
103
|
+
const STOP_RUNTIME_CONTEXT_RETRY_DELAYS_MS = [75, 175] as const;
|
|
104
|
+
/** Finalization is off the interactive hook path; briefly cover Codex's delayed transcript flush. */
|
|
105
|
+
const APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS = [0, 250, 250] as const;
|
|
77
106
|
/**
|
|
78
107
|
* Adapters whose turn-boundary recovery and mid-flight onboarding are enabled.
|
|
79
108
|
* Kept in code, outside the digested capability profiles, so tuning recovery
|
|
@@ -117,6 +146,29 @@ interface PendingEventV3 {
|
|
|
117
146
|
event: EventV3;
|
|
118
147
|
}
|
|
119
148
|
|
|
149
|
+
interface TurnContextTargetV3 {
|
|
150
|
+
terminal_event_id: `evt_${string}`;
|
|
151
|
+
terminal_observed_at: string;
|
|
152
|
+
turn_id: `tid_${string}`;
|
|
153
|
+
run_id?: `run_${string}`;
|
|
154
|
+
workflow_id?: `wf_${string}`;
|
|
155
|
+
workflow_agent_id?: string;
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
interface PendingRuntimeContextV3 extends TurnContextTargetV3 {
|
|
159
|
+
native_session_id: string;
|
|
160
|
+
native_turn_id: string;
|
|
161
|
+
transcript_path?: string;
|
|
162
|
+
runtime_version?: string;
|
|
163
|
+
attempts: number;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
interface ActiveRuntimeContextProbeV3 {
|
|
167
|
+
turn_id: `tid_${string}`;
|
|
168
|
+
attempted_at: string;
|
|
169
|
+
boundary?: "tool_completed";
|
|
170
|
+
}
|
|
171
|
+
|
|
120
172
|
interface DelegationStateV3 extends OpenSpanStateV3 {
|
|
121
173
|
source_id: `hid_${string}`;
|
|
122
174
|
delegation_id: `del_${string}`;
|
|
@@ -135,16 +187,29 @@ export interface HookProducerStateV3 {
|
|
|
135
187
|
capability_profile: `cap_${string}`;
|
|
136
188
|
cursor_mode?: CursorExecutionModeV3;
|
|
137
189
|
privacy_epoch_id: `pep_${string}`;
|
|
190
|
+
/**
|
|
191
|
+
* Genesis id of the ledger epoch this producer's boot chain lives in. The
|
|
192
|
+
* fingerprint key epoch survives ledger rotation, so this is the field that
|
|
193
|
+
* keeps a state file from being adopted across an epoch boundary (its
|
|
194
|
+
* sequences and causal links only validate inside their own epoch). A state
|
|
195
|
+
* without it predates the field and is never adopted.
|
|
196
|
+
*/
|
|
197
|
+
epoch_genesis_id?: `gex_${string}`;
|
|
138
198
|
boot_id: `boot_${string}`;
|
|
139
199
|
clock_id: `clk_${string}`;
|
|
140
200
|
next_sequence: number;
|
|
141
201
|
current_turn_id?: `tid_${string}`;
|
|
202
|
+
/** Native turn identity retained owner-only for transcript attribution. */
|
|
203
|
+
current_native_turn_id?: string;
|
|
142
204
|
tool_call_count: number;
|
|
143
205
|
tool_call_count_turn_id?: `tid_${string}`;
|
|
144
206
|
last_event_id?: `evt_${string}`;
|
|
145
207
|
last_monotonic_ns?: string;
|
|
146
208
|
last_observed_at?: string;
|
|
147
209
|
started_event_id?: `evt_${string}`;
|
|
210
|
+
/** A derived lifecycle reopen is allowed to exist before the adapter's next
|
|
211
|
+
* native prompt. Retained owner-only until that prompt starts a real turn. */
|
|
212
|
+
session_start_derivation?: "approved_lifecycle_reopen" | "validated_current_session_heal";
|
|
148
213
|
session_span: OpenSpanStateV3;
|
|
149
214
|
current_turn_span?: OpenSpanStateV3;
|
|
150
215
|
terminal: boolean;
|
|
@@ -156,6 +221,29 @@ export interface HookProducerStateV3 {
|
|
|
156
221
|
turn_harness: TurnHarnessTimingV3;
|
|
157
222
|
turn_ordinal: number;
|
|
158
223
|
pending?: PendingEventV3;
|
|
224
|
+
pending_runtime_contexts?: PendingRuntimeContextV3[];
|
|
225
|
+
/** Last bounded active-turn probe; owner-only and used only for cadence. */
|
|
226
|
+
active_runtime_context_probe?: ActiveRuntimeContextProbeV3;
|
|
227
|
+
/** Last emitted runtime source witness; owner-only measurement deduplication. */
|
|
228
|
+
last_context_source_witness?: string;
|
|
229
|
+
/** Verified adapter-native transcript path retained only in owner-only state. */
|
|
230
|
+
runtime_transcript_path?: string;
|
|
231
|
+
/** Tuning carried by the current attestation; {} means attested-none.
|
|
232
|
+
* Absent on pre-upgrade state files, which seed silently on first sight. */
|
|
233
|
+
last_attested_tuning?: { effort?: string; speed?: string };
|
|
234
|
+
/** Model observation carried forward into a refreshed attestation when the
|
|
235
|
+
* change-time transcript read does not pair a model with the new tuning. */
|
|
236
|
+
last_attested_model?: { provider: string; id: string };
|
|
237
|
+
/** Telemetry evidence carried forward verbatim: a tuning change does not
|
|
238
|
+
* alter what telemetry the runtime proved it can deliver. */
|
|
239
|
+
last_attested_telemetry?: RuntimeTelemetryCapabilitiesV3;
|
|
240
|
+
/** Full observations preserve missing and unsupported states when a
|
|
241
|
+
* different attestation channel changes. */
|
|
242
|
+
last_attested_model_observation?: RuntimeAttestationV3Base["model"];
|
|
243
|
+
last_attested_tuning_observation?: RuntimeAttestationV3Base["tuning"];
|
|
244
|
+
/** Turn already probed for Codex tuning while effort is unknown; bounds the
|
|
245
|
+
* rollout forward-scan to one attempt per turn. */
|
|
246
|
+
tuning_probe_turn_id?: `tid_${string}`;
|
|
159
247
|
}
|
|
160
248
|
|
|
161
249
|
export interface RecordHookSignalV3Input {
|
|
@@ -180,7 +268,15 @@ export interface RecordHookSignalV3Input {
|
|
|
180
268
|
hook_duration_ms?: number;
|
|
181
269
|
stop_remediation?: boolean;
|
|
182
270
|
turn_ritual?: TurnRitualEvidenceV3;
|
|
183
|
-
session_start_derivation?: "approved_lifecycle_reopen";
|
|
271
|
+
session_start_derivation?: "approved_lifecycle_reopen" | "validated_current_session_heal";
|
|
272
|
+
delegated_child?: {
|
|
273
|
+
generation_id: `gen_${string}`;
|
|
274
|
+
parent_generation_id: `gen_${string}`;
|
|
275
|
+
delegation_id: `del_${string}`;
|
|
276
|
+
caused_by_event_id: `evt_${string}`;
|
|
277
|
+
};
|
|
278
|
+
/** Optional roots and read budgets for runtime telemetry adapters. */
|
|
279
|
+
runtimeTelemetryOptions?: RuntimeTelemetryOptions;
|
|
184
280
|
writerOptions?: WriteEventV3Options;
|
|
185
281
|
}
|
|
186
282
|
|
|
@@ -310,11 +406,21 @@ function hookSignalGate(
|
|
|
310
406
|
}
|
|
311
407
|
|
|
312
408
|
function sessionHashForSignal(
|
|
313
|
-
input: Pick<
|
|
409
|
+
input: Pick<
|
|
410
|
+
RecordHookSignalV3Input,
|
|
411
|
+
"coordRoot" | "payload" | "adapter" | "instance_id" | "signal"
|
|
412
|
+
>,
|
|
314
413
|
context: ReturnType<typeof fingerprintContextV3>,
|
|
315
414
|
): `hid_${string}` {
|
|
316
|
-
const
|
|
317
|
-
|
|
415
|
+
const nativeChild = input.payload.subagent_id ?? input.payload.agent_id;
|
|
416
|
+
const childOwnsSignal =
|
|
417
|
+
input.signal !== "sub-agent-start" &&
|
|
418
|
+
input.signal !== "sub-agent-stop" &&
|
|
419
|
+
nativeChild !== undefined &&
|
|
420
|
+
input.instance_id === asLiveInstanceId(nativeChild);
|
|
421
|
+
const nativeSession = childOwnsSignal
|
|
422
|
+
? nativeChild
|
|
423
|
+
: (input.payload.session_id ?? input.payload.conversation_id ?? input.payload.agent_id);
|
|
318
424
|
if (nativeSession !== undefined) {
|
|
319
425
|
return normalizeNativeIdV3(context, `${input.adapter}.session`, nativeSession);
|
|
320
426
|
}
|
|
@@ -360,6 +466,7 @@ function intakeRecord(input: RecordHookSignalV3Input): HookIntakeRecordV3 {
|
|
|
360
466
|
: {}),
|
|
361
467
|
...(input.stop_remediation !== undefined ? { stop_remediation: input.stop_remediation } : {}),
|
|
362
468
|
...(input.turn_ritual ? { turn_ritual: input.turn_ritual } : {}),
|
|
469
|
+
...(input.delegated_child ? { delegated_child: input.delegated_child } : {}),
|
|
363
470
|
};
|
|
364
471
|
}
|
|
365
472
|
|
|
@@ -386,6 +493,7 @@ function inputForIntakeRecord(
|
|
|
386
493
|
...(record.hook_duration_ms !== undefined ? { hook_duration_ms: record.hook_duration_ms } : {}),
|
|
387
494
|
...(record.stop_remediation !== undefined ? { stop_remediation: record.stop_remediation } : {}),
|
|
388
495
|
...(record.turn_ritual ? { turn_ritual: record.turn_ritual } : {}),
|
|
496
|
+
...(record.delegated_child ? { delegated_child: record.delegated_child } : {}),
|
|
389
497
|
};
|
|
390
498
|
}
|
|
391
499
|
|
|
@@ -524,8 +632,23 @@ function processHookSignalLocked(
|
|
|
524
632
|
: control.activation.event.event_id;
|
|
525
633
|
const rootFingerprintContext = fingerprintContextV3(input.coordRoot, rootId, undefined, epochId);
|
|
526
634
|
const sessionId = `sid_${sessionHash.slice(4)}` as `sid_${string}`;
|
|
635
|
+
const genesisId = control.genesis.event.payload.genesis_id as `gex_${string}`;
|
|
636
|
+
// Every write below carries the epoch fence: an event produced for this
|
|
637
|
+
// epoch is refused (or quarantined from the spool) once the epoch has been
|
|
638
|
+
// replaced, instead of poisoning the successor's authority.
|
|
639
|
+
input = {
|
|
640
|
+
...input,
|
|
641
|
+
writerOptions: { ...input.writerOptions, expectedGenesisId: genesisId },
|
|
642
|
+
};
|
|
527
643
|
try {
|
|
528
644
|
let state = existsSync(path) ? readProducerState(path) : undefined;
|
|
645
|
+
if (state && state.epoch_genesis_id !== genesisId) {
|
|
646
|
+
// A producer state from a replaced epoch (or one that predates the
|
|
647
|
+
// field) is never adopted: its boot sequences and causal links only
|
|
648
|
+
// validate inside the epoch that recorded them. The session re-onboards
|
|
649
|
+
// below exactly as it does after an automatic epoch refresh.
|
|
650
|
+
state = undefined;
|
|
651
|
+
}
|
|
529
652
|
if (
|
|
530
653
|
state &&
|
|
531
654
|
(state.adapter !== input.adapter ||
|
|
@@ -551,7 +674,7 @@ function processHookSignalLocked(
|
|
|
551
674
|
const pendingSource = state.pending.source_id;
|
|
552
675
|
const incomingSource = sourceIdForSignal(input, rootFingerprintContext);
|
|
553
676
|
const pendingEvent = state.pending.event;
|
|
554
|
-
const durability = writeEventV3(input.coordRoot, pendingEvent);
|
|
677
|
+
const durability = writeEventV3(input.coordRoot, pendingEvent, input.writerOptions);
|
|
555
678
|
applyCommittedEvent(state, pendingEvent);
|
|
556
679
|
state.pending = undefined;
|
|
557
680
|
publishProducerState(path, state);
|
|
@@ -565,10 +688,19 @@ function processHookSignalLocked(
|
|
|
565
688
|
if (state && !state.terminal && state.started_event_id) {
|
|
566
689
|
return { state: "already_started", event_id: state.started_event_id };
|
|
567
690
|
}
|
|
568
|
-
if (
|
|
691
|
+
if (
|
|
692
|
+
(input.session_start_derivation === "approved_lifecycle_reopen" && !state?.terminal) ||
|
|
693
|
+
(input.session_start_derivation === "validated_current_session_heal" && state?.terminal)
|
|
694
|
+
) {
|
|
569
695
|
return { state: "missing_session_start" };
|
|
570
696
|
}
|
|
571
|
-
state = newProducerState(
|
|
697
|
+
state = newProducerState(
|
|
698
|
+
input,
|
|
699
|
+
sessionId,
|
|
700
|
+
epochId,
|
|
701
|
+
boundaryEventId as `evt_${string}`,
|
|
702
|
+
genesisId,
|
|
703
|
+
);
|
|
572
704
|
} else if (!state || state.terminal) {
|
|
573
705
|
// Mid-flight onboarding (ADR 0078): a live session with no producer
|
|
574
706
|
// state in this epoch (fresh epoch, lost session-start hook) opens a
|
|
@@ -595,7 +727,13 @@ function processHookSignalLocked(
|
|
|
595
727
|
});
|
|
596
728
|
return { state: "missing_session_start" };
|
|
597
729
|
}
|
|
598
|
-
state = newProducerState(
|
|
730
|
+
state = newProducerState(
|
|
731
|
+
input,
|
|
732
|
+
sessionId,
|
|
733
|
+
epochId,
|
|
734
|
+
boundaryEventId as `evt_${string}`,
|
|
735
|
+
genesisId,
|
|
736
|
+
);
|
|
599
737
|
const cursorPromptBootstrap = isCursorPromptBootstrap(input);
|
|
600
738
|
const onboarding = buildMidFlightSessionStart(input, state, rootId, cursorPromptBootstrap);
|
|
601
739
|
commitEventLocked(input, state, path, onboarding);
|
|
@@ -605,6 +743,7 @@ function processHookSignalLocked(
|
|
|
605
743
|
instance_id: input.instance_id,
|
|
606
744
|
signal: input.signal,
|
|
607
745
|
session_hash: sessionHash,
|
|
746
|
+
...(input.adapter === "codex" ? codexMidFlightDiagnosticContext(input.payload) : {}),
|
|
608
747
|
});
|
|
609
748
|
}
|
|
610
749
|
}
|
|
@@ -669,6 +808,9 @@ function processHookSignalLocked(
|
|
|
669
808
|
(nativeTid !== undefined && state.current_turn_id === nativeTid));
|
|
670
809
|
|
|
671
810
|
recordTurnHarnessTiming(state, input, !duplicateOpenTurnStart);
|
|
811
|
+
reconcilePendingRuntimeContexts(input, state, path, rootId, fingerprintContext, {
|
|
812
|
+
finalAttempt: input.signal === "session-end",
|
|
813
|
+
});
|
|
672
814
|
|
|
673
815
|
closeResolvedWaits(input, state, path, rootId, fingerprintContext, nativeTid);
|
|
674
816
|
if (input.signal === "permission-request") {
|
|
@@ -736,6 +878,7 @@ function processHookSignalLocked(
|
|
|
736
878
|
boot_id: state.boot_id,
|
|
737
879
|
clock: eventClock,
|
|
738
880
|
});
|
|
881
|
+
state.current_native_turn_id = input.payload.turn_id;
|
|
739
882
|
}
|
|
740
883
|
|
|
741
884
|
let sourceId = sourceIdForSignal(input, rootFingerprintContext);
|
|
@@ -933,7 +1076,7 @@ function processHookSignalLocked(
|
|
|
933
1076
|
|
|
934
1077
|
const turnTelemetry =
|
|
935
1078
|
input.signal === "stop" || input.signal === "stop-failure"
|
|
936
|
-
?
|
|
1079
|
+
? turnTelemetryForTerminal(input, state, eventClock.observed_at)
|
|
937
1080
|
: undefined;
|
|
938
1081
|
const cursorToolChannelSupport =
|
|
939
1082
|
input.adapter === "cursor"
|
|
@@ -950,6 +1093,9 @@ function processHookSignalLocked(
|
|
|
950
1093
|
const toolCallCountScopeMismatch =
|
|
951
1094
|
(input.signal === "stop" || input.signal === "stop-failure") &&
|
|
952
1095
|
(!state.current_turn_id || state.tool_call_count_turn_id !== state.current_turn_id);
|
|
1096
|
+
// Before the signal's own event: the tool call or turn that carries the
|
|
1097
|
+
// new effort already ran under it, so it must ride the new attestation.
|
|
1098
|
+
maybeAttestTuningChange(input, state, path, rootId);
|
|
953
1099
|
const event = normalizeHookEventV3(input.signal, eventInput.payload, {
|
|
954
1100
|
coordRoot: input.coordRoot,
|
|
955
1101
|
adapter: input.adapter,
|
|
@@ -973,6 +1119,7 @@ function processHookSignalLocked(
|
|
|
973
1119
|
platform: input.platform,
|
|
974
1120
|
bridge: input.bridge,
|
|
975
1121
|
capability_profile: state.capability_profile,
|
|
1122
|
+
cursor_mode: state.cursor_mode,
|
|
976
1123
|
fingerprintContext,
|
|
977
1124
|
turn_id: state.current_turn_id,
|
|
978
1125
|
span_id: openingSpan?.span_id ?? closingSpan?.span_id,
|
|
@@ -1012,12 +1159,58 @@ function processHookSignalLocked(
|
|
|
1012
1159
|
if (!event) return { state: "ignored" };
|
|
1013
1160
|
if (
|
|
1014
1161
|
input.signal === "session-start" &&
|
|
1015
|
-
input.
|
|
1162
|
+
input.delegated_child &&
|
|
1163
|
+
event.event_type === "session.started"
|
|
1164
|
+
) {
|
|
1165
|
+
event.links = {
|
|
1166
|
+
caused_by: [input.delegated_child.caused_by_event_id],
|
|
1167
|
+
parent_generation_id: input.delegated_child.parent_generation_id,
|
|
1168
|
+
delegation_id: input.delegated_child.delegation_id,
|
|
1169
|
+
};
|
|
1170
|
+
event.provenance = {
|
|
1171
|
+
...event.provenance,
|
|
1172
|
+
source_event: `${input.adapter}.subagent-start.child-generation`,
|
|
1173
|
+
attestation: "derived",
|
|
1174
|
+
confidence: "high",
|
|
1175
|
+
attribution: {
|
|
1176
|
+
method: "native_payload",
|
|
1177
|
+
state: "verified",
|
|
1178
|
+
subject_instance_id: state.instance_id,
|
|
1179
|
+
},
|
|
1180
|
+
};
|
|
1181
|
+
assertEventV3(event);
|
|
1182
|
+
}
|
|
1183
|
+
if (
|
|
1184
|
+
input.signal === "user-prompt-submit" &&
|
|
1185
|
+
input.delegated_child &&
|
|
1186
|
+
event.event_type === "turn.started"
|
|
1187
|
+
) {
|
|
1188
|
+
event.links = { caused_by: [input.delegated_child.caused_by_event_id] };
|
|
1189
|
+
event.provenance = {
|
|
1190
|
+
...event.provenance,
|
|
1191
|
+
source_event: `${input.adapter}.subagent-start.child-turn`,
|
|
1192
|
+
attestation: "derived",
|
|
1193
|
+
confidence: "high",
|
|
1194
|
+
attribution: {
|
|
1195
|
+
method: "native_payload",
|
|
1196
|
+
state: "verified",
|
|
1197
|
+
subject_instance_id: state.instance_id,
|
|
1198
|
+
},
|
|
1199
|
+
};
|
|
1200
|
+
assertEventV3(event);
|
|
1201
|
+
}
|
|
1202
|
+
if (
|
|
1203
|
+
input.signal === "session-start" &&
|
|
1204
|
+
input.session_start_derivation &&
|
|
1016
1205
|
event.event_type === "session.started"
|
|
1017
1206
|
) {
|
|
1207
|
+
const lifecycleReopen = input.session_start_derivation === "approved_lifecycle_reopen";
|
|
1208
|
+
const reason = lifecycleReopen
|
|
1209
|
+
? "approved_lifecycle_reopen"
|
|
1210
|
+
: "validated_current_session_heal";
|
|
1018
1211
|
event.provenance = {
|
|
1019
1212
|
...event.provenance,
|
|
1020
|
-
source_event: `${input.adapter}.
|
|
1213
|
+
source_event: `${input.adapter}.${reason.replaceAll("_", "-")}`,
|
|
1021
1214
|
attestation: "derived",
|
|
1022
1215
|
confidence: "high",
|
|
1023
1216
|
attribution: {
|
|
@@ -1028,7 +1221,7 @@ function processHookSignalLocked(
|
|
|
1028
1221
|
};
|
|
1029
1222
|
event.payload.resume = {
|
|
1030
1223
|
state: "unknown",
|
|
1031
|
-
reason
|
|
1224
|
+
reason,
|
|
1032
1225
|
};
|
|
1033
1226
|
assertEventV3(event);
|
|
1034
1227
|
}
|
|
@@ -1037,7 +1230,20 @@ function processHookSignalLocked(
|
|
|
1037
1230
|
span.open_event_id = event.event_id as `evt_${string}`;
|
|
1038
1231
|
stampSpanTurn(span, event, eventInput, state);
|
|
1039
1232
|
}
|
|
1233
|
+
// A turn terminal clears current_native_turn_id when it commits. Retain the
|
|
1234
|
+
// native identity long enough to seed a delayed context retry afterward.
|
|
1235
|
+
const nativeTurnIdForContext = input.payload.turn_id ?? state.current_native_turn_id;
|
|
1040
1236
|
const durability = commitEventLocked(input, state, path, event, sourceId);
|
|
1237
|
+
if (event.event_type === "context.compaction_started" && input.signal === "pre-compact") {
|
|
1238
|
+
maybeCommitNativeHookContextObservation(
|
|
1239
|
+
input,
|
|
1240
|
+
state,
|
|
1241
|
+
path,
|
|
1242
|
+
rootId,
|
|
1243
|
+
fingerprintContext,
|
|
1244
|
+
event,
|
|
1245
|
+
);
|
|
1246
|
+
}
|
|
1041
1247
|
if (event.event_type === "tool.requested" && sourceId) {
|
|
1042
1248
|
const explicitWait = explicitNativeWait(input);
|
|
1043
1249
|
if (explicitWait) {
|
|
@@ -1050,8 +1256,35 @@ function processHookSignalLocked(
|
|
|
1050
1256
|
if (progressKind) {
|
|
1051
1257
|
commitProgressObservation(input, state, path, rootId, event, progressKind);
|
|
1052
1258
|
}
|
|
1259
|
+
if (event.event_type === "tool.completed" && input.signal === "post-tool-use") {
|
|
1260
|
+
maybeCommitActiveRuntimeContextObservation(
|
|
1261
|
+
input,
|
|
1262
|
+
state,
|
|
1263
|
+
path,
|
|
1264
|
+
rootId,
|
|
1265
|
+
fingerprintContext,
|
|
1266
|
+
event,
|
|
1267
|
+
);
|
|
1268
|
+
}
|
|
1053
1269
|
if (turnTelemetry) {
|
|
1054
|
-
|
|
1270
|
+
const contextTarget = turnContextTarget(event);
|
|
1271
|
+
queuePendingRuntimeContext(
|
|
1272
|
+
input,
|
|
1273
|
+
state,
|
|
1274
|
+
contextTarget,
|
|
1275
|
+
turnTelemetry.context,
|
|
1276
|
+
nativeTurnIdForContext,
|
|
1277
|
+
);
|
|
1278
|
+
commitTurnContextObservation(
|
|
1279
|
+
input,
|
|
1280
|
+
state,
|
|
1281
|
+
path,
|
|
1282
|
+
rootId,
|
|
1283
|
+
fingerprintContext,
|
|
1284
|
+
contextTarget,
|
|
1285
|
+
turnTelemetry.context,
|
|
1286
|
+
turnTelemetry.context_provenance,
|
|
1287
|
+
);
|
|
1055
1288
|
}
|
|
1056
1289
|
if (event.event_type === "session.ended") {
|
|
1057
1290
|
commitCapabilityDriftEvents(input, state, path, rootId);
|
|
@@ -1501,10 +1734,60 @@ function commitTurnContextObservation(
|
|
|
1501
1734
|
state: HookProducerStateV3,
|
|
1502
1735
|
path: string,
|
|
1503
1736
|
rootId: `root_${string}`,
|
|
1504
|
-
|
|
1737
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
1738
|
+
target: TurnContextTargetV3 | undefined,
|
|
1739
|
+
measurement: TelemetryObservationV3<ContextMeasurementV3>,
|
|
1740
|
+
contextProvenance?: ContextTelemetryProvenanceV3,
|
|
1741
|
+
observedAt?: string,
|
|
1742
|
+
): void {
|
|
1743
|
+
if (!target) return;
|
|
1744
|
+
commitContextObservation(
|
|
1745
|
+
input,
|
|
1746
|
+
state,
|
|
1747
|
+
path,
|
|
1748
|
+
rootId,
|
|
1749
|
+
fingerprintContext,
|
|
1750
|
+
{
|
|
1751
|
+
caused_by_event_id: target.terminal_event_id,
|
|
1752
|
+
observed_at: observedAt ?? target.terminal_observed_at,
|
|
1753
|
+
turn_id: target.turn_id,
|
|
1754
|
+
...(target.run_id ? { run_id: target.run_id } : {}),
|
|
1755
|
+
...(target.workflow_id ? { workflow_id: target.workflow_id } : {}),
|
|
1756
|
+
...(target.workflow_agent_id ? { workflow_agent_id: target.workflow_agent_id } : {}),
|
|
1757
|
+
},
|
|
1758
|
+
measurement,
|
|
1759
|
+
contextProvenance,
|
|
1760
|
+
);
|
|
1761
|
+
}
|
|
1762
|
+
|
|
1763
|
+
function commitContextObservation(
|
|
1764
|
+
input: RecordHookSignalV3Input,
|
|
1765
|
+
state: HookProducerStateV3,
|
|
1766
|
+
path: string,
|
|
1767
|
+
rootId: `root_${string}`,
|
|
1768
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
1769
|
+
target: {
|
|
1770
|
+
caused_by_event_id: `evt_${string}`;
|
|
1771
|
+
observed_at: string;
|
|
1772
|
+
turn_id: `tid_${string}`;
|
|
1773
|
+
run_id?: `run_${string}`;
|
|
1774
|
+
workflow_id?: `wf_${string}`;
|
|
1775
|
+
workflow_agent_id?: string;
|
|
1776
|
+
},
|
|
1505
1777
|
measurement: TelemetryObservationV3<ContextMeasurementV3>,
|
|
1778
|
+
contextProvenance?: ContextTelemetryProvenanceV3,
|
|
1506
1779
|
): void {
|
|
1507
|
-
if (
|
|
1780
|
+
if (
|
|
1781
|
+
measurement.state === "observed" &&
|
|
1782
|
+
contextProvenance?.source_witness &&
|
|
1783
|
+
state.last_context_source_witness === contextProvenance.source_witness
|
|
1784
|
+
) {
|
|
1785
|
+
publishProducerState(path, state);
|
|
1786
|
+
return;
|
|
1787
|
+
}
|
|
1788
|
+
if (measurement.state === "observed" && contextProvenance?.source_witness) {
|
|
1789
|
+
state.last_context_source_witness = contextProvenance.source_witness;
|
|
1790
|
+
}
|
|
1508
1791
|
const event = buildEventV3("context.observed", {
|
|
1509
1792
|
producer: {
|
|
1510
1793
|
producer_id: input.producer_id,
|
|
@@ -1520,36 +1803,859 @@ function commitTurnContextObservation(
|
|
|
1520
1803
|
instance_id: state.instance_id,
|
|
1521
1804
|
session_id: state.session_id,
|
|
1522
1805
|
generation_id: state.generation_id,
|
|
1523
|
-
turn_id:
|
|
1524
|
-
...(
|
|
1525
|
-
...(
|
|
1526
|
-
...(
|
|
1806
|
+
turn_id: target.turn_id,
|
|
1807
|
+
...(target.run_id ? { run_id: target.run_id } : {}),
|
|
1808
|
+
...(target.workflow_id ? { workflow_id: target.workflow_id } : {}),
|
|
1809
|
+
...(target.workflow_agent_id ? { workflow_agent_id: target.workflow_agent_id } : {}),
|
|
1527
1810
|
},
|
|
1528
1811
|
attestation_id: state.attestation_id,
|
|
1529
|
-
links: { caused_by: [
|
|
1812
|
+
links: { caused_by: [target.caused_by_event_id] },
|
|
1530
1813
|
provenance: {
|
|
1531
|
-
source_event:
|
|
1814
|
+
source_event: safeRole(
|
|
1815
|
+
[
|
|
1816
|
+
contextProvenance?.source_event ?? `${input.adapter}.turn-context`,
|
|
1817
|
+
contextProvenance?.runtime_version,
|
|
1818
|
+
]
|
|
1819
|
+
.filter(Boolean)
|
|
1820
|
+
.join("."),
|
|
1821
|
+
),
|
|
1822
|
+
attestation: contextProvenance?.attestation ?? "native",
|
|
1823
|
+
confidence: contextProvenance?.confidence ?? "exact",
|
|
1824
|
+
...(contextProvenance?.source_witness
|
|
1825
|
+
? {
|
|
1826
|
+
source_record_id: normalizeNativeIdV3(
|
|
1827
|
+
fingerprintContext,
|
|
1828
|
+
`${input.adapter}.runtime-context`,
|
|
1829
|
+
contextProvenance.source_witness,
|
|
1830
|
+
),
|
|
1831
|
+
}
|
|
1832
|
+
: {}),
|
|
1833
|
+
attribution: {
|
|
1834
|
+
method: "native_payload",
|
|
1835
|
+
state: "verified",
|
|
1836
|
+
subject_instance_id: state.instance_id,
|
|
1837
|
+
},
|
|
1838
|
+
},
|
|
1839
|
+
// The source sample may precede the hook boundary that admits it.
|
|
1840
|
+
// measurement.measured_at preserves the sample clock without creating a
|
|
1841
|
+
// causal wall-clock regression in the producer event chain.
|
|
1842
|
+
observed_at: target.observed_at,
|
|
1843
|
+
monotonic_ns: orderedEventMonotonic(state, input.monotonic_ns),
|
|
1844
|
+
clock_id: state.clock_id,
|
|
1845
|
+
payload: {
|
|
1846
|
+
measurement,
|
|
1847
|
+
},
|
|
1848
|
+
}) as EventV3;
|
|
1849
|
+
commitEventLocked(input, state, path, event);
|
|
1850
|
+
maybeAttestContextCapabilityChange(input, state, path, rootId, measurement, contextProvenance);
|
|
1851
|
+
}
|
|
1852
|
+
|
|
1853
|
+
/**
|
|
1854
|
+
* Admit fresh adapter-native or bounded runtime context while a turn is open.
|
|
1855
|
+
* Tool completions are safe sampling boundaries. Persistent owner-only cadence
|
|
1856
|
+
* state prevents short-lived hook processes from reading on every request,
|
|
1857
|
+
* and the source witness prevents duplicate public events.
|
|
1858
|
+
*/
|
|
1859
|
+
function maybeCommitActiveRuntimeContextObservation(
|
|
1860
|
+
input: RecordHookSignalV3Input,
|
|
1861
|
+
state: HookProducerStateV3,
|
|
1862
|
+
path: string,
|
|
1863
|
+
rootId: `root_${string}`,
|
|
1864
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
1865
|
+
sourceEvent: EventV3,
|
|
1866
|
+
): void {
|
|
1867
|
+
if (input.signal !== "post-tool-use" || state.terminal || !state.current_turn_id) {
|
|
1868
|
+
return;
|
|
1869
|
+
}
|
|
1870
|
+
const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
|
|
1871
|
+
const nativeTurnId = input.payload.turn_id ?? state.current_native_turn_id;
|
|
1872
|
+
if (!nativeSessionId || (!nativeTurnId && input.adapter !== "cursor")) return;
|
|
1873
|
+
|
|
1874
|
+
const now = Date.now();
|
|
1875
|
+
const configuredInterval = input.runtimeTelemetryOptions?.activeContextProbeIntervalMs;
|
|
1876
|
+
const intervalMs =
|
|
1877
|
+
configuredInterval !== undefined && Number.isFinite(configuredInterval)
|
|
1878
|
+
? Math.max(0, Math.floor(configuredInterval))
|
|
1879
|
+
: ACTIVE_RUNTIME_CONTEXT_PROBE_INTERVAL_MS;
|
|
1880
|
+
const prior = state.active_runtime_context_probe;
|
|
1881
|
+
const priorAttempt = prior ? Date.parse(prior.attempted_at) : Number.NaN;
|
|
1882
|
+
if (
|
|
1883
|
+
prior?.turn_id === state.current_turn_id &&
|
|
1884
|
+
prior.boundary === "tool_completed" &&
|
|
1885
|
+
Number.isFinite(priorAttempt) &&
|
|
1886
|
+
now - priorAttempt >= 0 &&
|
|
1887
|
+
now - priorAttempt < intervalMs
|
|
1888
|
+
) {
|
|
1889
|
+
return;
|
|
1890
|
+
}
|
|
1891
|
+
state.active_runtime_context_probe = {
|
|
1892
|
+
turn_id: state.current_turn_id,
|
|
1893
|
+
attempted_at: new Date(now).toISOString(),
|
|
1894
|
+
boundary: "tool_completed",
|
|
1895
|
+
};
|
|
1896
|
+
|
|
1897
|
+
const native = extractTurnTelemetryV3(
|
|
1898
|
+
input.adapter,
|
|
1899
|
+
input.payload.raw,
|
|
1900
|
+
sourceEvent.time.observed_at,
|
|
1901
|
+
).context;
|
|
1902
|
+
if (native.state === "observed") {
|
|
1903
|
+
commitActiveContextObservation(
|
|
1904
|
+
input,
|
|
1905
|
+
state,
|
|
1906
|
+
path,
|
|
1907
|
+
rootId,
|
|
1908
|
+
fingerprintContext,
|
|
1909
|
+
sourceEvent,
|
|
1910
|
+
native,
|
|
1911
|
+
nativeContextProvenance(input, state, native),
|
|
1912
|
+
);
|
|
1913
|
+
return;
|
|
1914
|
+
}
|
|
1915
|
+
if (input.adapter === "cursor" && state.cursor_mode === "cloud") {
|
|
1916
|
+
publishProducerState(path, state);
|
|
1917
|
+
return;
|
|
1918
|
+
}
|
|
1919
|
+
|
|
1920
|
+
const transcriptPath = runtimeTranscriptPath(input, state);
|
|
1921
|
+
if (!transcriptPath && input.adapter !== "cursor") {
|
|
1922
|
+
publishProducerState(path, state);
|
|
1923
|
+
return;
|
|
1924
|
+
}
|
|
1925
|
+
const runtime = readRuntimeContextTelemetry(
|
|
1926
|
+
{
|
|
1927
|
+
adapter: input.adapter,
|
|
1928
|
+
session_id: nativeSessionId,
|
|
1929
|
+
...(nativeTurnId ? { turn_id: nativeTurnId } : {}),
|
|
1930
|
+
...(state.current_turn_span?.opened_at
|
|
1931
|
+
? { turn_started_at: state.current_turn_span.opened_at }
|
|
1932
|
+
: {}),
|
|
1933
|
+
transcript_path: transcriptPath,
|
|
1934
|
+
observed_at: sourceEvent.time.observed_at,
|
|
1935
|
+
mode: "active_turn",
|
|
1936
|
+
},
|
|
1937
|
+
input.runtimeTelemetryOptions,
|
|
1938
|
+
);
|
|
1939
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
1940
|
+
if (runtime.state !== "observed") {
|
|
1941
|
+
publishProducerState(path, state);
|
|
1942
|
+
return;
|
|
1943
|
+
}
|
|
1944
|
+
|
|
1945
|
+
commitActiveContextObservation(
|
|
1946
|
+
input,
|
|
1947
|
+
state,
|
|
1948
|
+
path,
|
|
1949
|
+
rootId,
|
|
1950
|
+
fingerprintContext,
|
|
1951
|
+
sourceEvent,
|
|
1952
|
+
runtimeContextObservation(runtime),
|
|
1953
|
+
{
|
|
1954
|
+
source_event: runtime.source_event,
|
|
1955
|
+
source_witness: runtime.source_witness,
|
|
1956
|
+
...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
|
|
1957
|
+
attestation: runtime.attestation,
|
|
1958
|
+
confidence: runtime.confidence,
|
|
1959
|
+
},
|
|
1960
|
+
);
|
|
1961
|
+
}
|
|
1962
|
+
|
|
1963
|
+
function commitActiveContextObservation(
|
|
1964
|
+
input: RecordHookSignalV3Input,
|
|
1965
|
+
state: HookProducerStateV3,
|
|
1966
|
+
path: string,
|
|
1967
|
+
rootId: `root_${string}`,
|
|
1968
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
1969
|
+
sourceEvent: EventV3,
|
|
1970
|
+
measurement: TelemetryObservationV3<ContextMeasurementV3>,
|
|
1971
|
+
provenance: ContextTelemetryProvenanceV3,
|
|
1972
|
+
): void {
|
|
1973
|
+
if (!state.current_turn_id) return;
|
|
1974
|
+
const scope = sourceEvent.scope as {
|
|
1975
|
+
run_id?: `run_${string}`;
|
|
1976
|
+
workflow_id?: `wf_${string}`;
|
|
1977
|
+
workflow_agent_id?: string;
|
|
1978
|
+
};
|
|
1979
|
+
commitContextObservation(
|
|
1980
|
+
input,
|
|
1981
|
+
state,
|
|
1982
|
+
path,
|
|
1983
|
+
rootId,
|
|
1984
|
+
fingerprintContext,
|
|
1985
|
+
{
|
|
1986
|
+
caused_by_event_id: sourceEvent.event_id as `evt_${string}`,
|
|
1987
|
+
observed_at: sourceEvent.time.observed_at,
|
|
1988
|
+
turn_id: state.current_turn_id,
|
|
1989
|
+
...(scope.run_id ? { run_id: scope.run_id } : {}),
|
|
1990
|
+
...(scope.workflow_id ? { workflow_id: scope.workflow_id } : {}),
|
|
1991
|
+
...(scope.workflow_agent_id ? { workflow_agent_id: scope.workflow_agent_id } : {}),
|
|
1992
|
+
},
|
|
1993
|
+
measurement,
|
|
1994
|
+
provenance,
|
|
1995
|
+
);
|
|
1996
|
+
}
|
|
1997
|
+
|
|
1998
|
+
function nativeContextProvenance(
|
|
1999
|
+
input: RecordHookSignalV3Input,
|
|
2000
|
+
state: HookProducerStateV3,
|
|
2001
|
+
measurement: Extract<TelemetryObservationV3<ContextMeasurementV3>, { state: "observed" }>,
|
|
2002
|
+
): ContextTelemetryProvenanceV3 {
|
|
2003
|
+
const { measured_at: _measuredAt, ...stableValue } = measurement.value;
|
|
2004
|
+
const witness = canonicalJsonV3({
|
|
2005
|
+
adapter: input.adapter,
|
|
2006
|
+
session_id: state.session_id,
|
|
2007
|
+
turn_id: state.current_turn_id,
|
|
2008
|
+
value: stableValue,
|
|
2009
|
+
});
|
|
2010
|
+
return {
|
|
2011
|
+
source_event: `${input.adapter}.native_context`,
|
|
2012
|
+
source_witness: createHash("sha256").update(witness).digest("hex"),
|
|
2013
|
+
...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
|
|
2014
|
+
attestation: measurement.attestation,
|
|
2015
|
+
confidence: measurement.confidence,
|
|
2016
|
+
};
|
|
2017
|
+
}
|
|
2018
|
+
|
|
2019
|
+
function maybeCommitNativeHookContextObservation(
|
|
2020
|
+
input: RecordHookSignalV3Input,
|
|
2021
|
+
state: HookProducerStateV3,
|
|
2022
|
+
path: string,
|
|
2023
|
+
rootId: `root_${string}`,
|
|
2024
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
2025
|
+
sourceEvent: EventV3,
|
|
2026
|
+
): void {
|
|
2027
|
+
const measurement = extractTurnTelemetryV3(
|
|
2028
|
+
input.adapter,
|
|
2029
|
+
input.payload.raw,
|
|
2030
|
+
sourceEvent.time.observed_at,
|
|
2031
|
+
).context;
|
|
2032
|
+
if (measurement.state !== "observed") return;
|
|
2033
|
+
commitActiveContextObservation(
|
|
2034
|
+
input,
|
|
2035
|
+
state,
|
|
2036
|
+
path,
|
|
2037
|
+
rootId,
|
|
2038
|
+
fingerprintContext,
|
|
2039
|
+
sourceEvent,
|
|
2040
|
+
measurement,
|
|
2041
|
+
nativeContextProvenance(input, state, measurement),
|
|
2042
|
+
);
|
|
2043
|
+
}
|
|
2044
|
+
|
|
2045
|
+
function maybeAttestContextCapabilityChange(
|
|
2046
|
+
input: RecordHookSignalV3Input,
|
|
2047
|
+
state: HookProducerStateV3,
|
|
2048
|
+
path: string,
|
|
2049
|
+
rootId: `root_${string}`,
|
|
2050
|
+
measurement: TelemetryObservationV3<ContextMeasurementV3>,
|
|
2051
|
+
provenance?: ContextTelemetryProvenanceV3,
|
|
2052
|
+
): void {
|
|
2053
|
+
const context =
|
|
2054
|
+
measurement.state === "observed"
|
|
2055
|
+
? {
|
|
2056
|
+
state: "observed" as const,
|
|
2057
|
+
source: provenance?.source_event ?? `${input.adapter}.turn_context`,
|
|
2058
|
+
attestation: provenance?.attestation ?? measurement.attestation,
|
|
2059
|
+
confidence: provenance?.confidence ?? measurement.confidence,
|
|
2060
|
+
completeness:
|
|
2061
|
+
"used_percent" in measurement.value
|
|
2062
|
+
? ("percentage_only" as const)
|
|
2063
|
+
: (provenance?.attestation ?? measurement.attestation) === "inferred"
|
|
2064
|
+
? ("inferred" as const)
|
|
2065
|
+
: ("exact" as const),
|
|
2066
|
+
}
|
|
2067
|
+
: measurement.state === "expected_but_missing"
|
|
2068
|
+
? { state: "partial" as const, reason: measurement.reason }
|
|
2069
|
+
: { state: "unsupported" as const };
|
|
2070
|
+
const telemetry = effectiveRuntimeTelemetryCapabilitiesV3({
|
|
2071
|
+
adapter: input.adapter,
|
|
2072
|
+
...(state.cursor_mode ? { cursor_mode: state.cursor_mode } : {}),
|
|
2073
|
+
context,
|
|
2074
|
+
canonical_turn_boundaries: true,
|
|
2075
|
+
});
|
|
2076
|
+
if (!state.last_attested_telemetry) return;
|
|
2077
|
+
if (canonicalJsonV3(telemetry) === canonicalJsonV3(state.last_attested_telemetry)) return;
|
|
2078
|
+
if (!state.last_attested_model_observation || !state.last_attested_tuning_observation) return;
|
|
2079
|
+
|
|
2080
|
+
commitRuntimeAttestationChange(input, state, path, rootId, {
|
|
2081
|
+
model: state.last_attested_model_observation,
|
|
2082
|
+
tuning: state.last_attested_tuning_observation,
|
|
2083
|
+
telemetry,
|
|
2084
|
+
reason: "runtime_telemetry_changed",
|
|
2085
|
+
source_event: provenance?.source_event ?? `${input.adapter}.turn_context`,
|
|
2086
|
+
attestation: provenance?.attestation ?? "derived",
|
|
2087
|
+
confidence: provenance?.confidence ?? (measurement.state === "observed" ? "exact" : "high"),
|
|
2088
|
+
});
|
|
2089
|
+
}
|
|
2090
|
+
|
|
2091
|
+
function turnContextTarget(turnTerminal: EventV3): TurnContextTargetV3 | undefined {
|
|
2092
|
+
if (turnTerminal.event_type !== "turn.completed") return undefined;
|
|
2093
|
+
const scope = turnTerminal.scope as {
|
|
2094
|
+
turn_id: `tid_${string}`;
|
|
2095
|
+
run_id?: `run_${string}`;
|
|
2096
|
+
workflow_id?: `wf_${string}`;
|
|
2097
|
+
workflow_agent_id?: string;
|
|
2098
|
+
};
|
|
2099
|
+
return {
|
|
2100
|
+
terminal_event_id: turnTerminal.event_id as `evt_${string}`,
|
|
2101
|
+
terminal_observed_at: turnTerminal.time.observed_at,
|
|
2102
|
+
turn_id: scope.turn_id,
|
|
2103
|
+
...(scope.run_id ? { run_id: scope.run_id } : {}),
|
|
2104
|
+
...(scope.workflow_id ? { workflow_id: scope.workflow_id } : {}),
|
|
2105
|
+
...(scope.workflow_agent_id ? { workflow_agent_id: scope.workflow_agent_id } : {}),
|
|
2106
|
+
};
|
|
2107
|
+
}
|
|
2108
|
+
|
|
2109
|
+
function queuePendingRuntimeContext(
|
|
2110
|
+
input: RecordHookSignalV3Input,
|
|
2111
|
+
state: HookProducerStateV3,
|
|
2112
|
+
target: TurnContextTargetV3 | undefined,
|
|
2113
|
+
measurement: TelemetryObservationV3<ContextMeasurementV3>,
|
|
2114
|
+
nativeTurnId: string | undefined,
|
|
2115
|
+
): void {
|
|
2116
|
+
if (
|
|
2117
|
+
input.adapter !== "codex" ||
|
|
2118
|
+
!target ||
|
|
2119
|
+
measurement.state !== "expected_but_missing" ||
|
|
2120
|
+
!retryableRuntimeContextReason(measurement.reason)
|
|
2121
|
+
) {
|
|
2122
|
+
return;
|
|
2123
|
+
}
|
|
2124
|
+
const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
|
|
2125
|
+
if (!nativeSessionId || !nativeTurnId) return;
|
|
2126
|
+
const pending: PendingRuntimeContextV3 = {
|
|
2127
|
+
...target,
|
|
2128
|
+
native_session_id: nativeSessionId,
|
|
2129
|
+
native_turn_id: nativeTurnId,
|
|
2130
|
+
...((input.payload.transcript_path ?? state.runtime_transcript_path)
|
|
2131
|
+
? { transcript_path: input.payload.transcript_path ?? state.runtime_transcript_path }
|
|
2132
|
+
: {}),
|
|
2133
|
+
...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
|
|
2134
|
+
attempts: 0,
|
|
2135
|
+
};
|
|
2136
|
+
state.pending_runtime_contexts = [
|
|
2137
|
+
...(state.pending_runtime_contexts ?? []).filter(
|
|
2138
|
+
(candidate) => candidate.turn_id !== target.turn_id,
|
|
2139
|
+
),
|
|
2140
|
+
pending,
|
|
2141
|
+
].slice(-PENDING_RUNTIME_CONTEXT_CAP);
|
|
2142
|
+
}
|
|
2143
|
+
|
|
2144
|
+
function reconcilePendingRuntimeContexts(
|
|
2145
|
+
input: RecordHookSignalV3Input,
|
|
2146
|
+
state: HookProducerStateV3,
|
|
2147
|
+
path: string,
|
|
2148
|
+
rootId: `root_${string}`,
|
|
2149
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
2150
|
+
options: { deferRetryLimit?: boolean; finalAttempt?: boolean } = {},
|
|
2151
|
+
): void {
|
|
2152
|
+
if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) return;
|
|
2153
|
+
for (const pending of [...state.pending_runtime_contexts]) {
|
|
2154
|
+
const runtime = readRuntimeContextTelemetry(
|
|
2155
|
+
{
|
|
2156
|
+
adapter: "codex",
|
|
2157
|
+
session_id: pending.native_session_id,
|
|
2158
|
+
turn_id: pending.native_turn_id,
|
|
2159
|
+
transcript_path: pending.transcript_path,
|
|
2160
|
+
mode: "turn",
|
|
2161
|
+
},
|
|
2162
|
+
input.runtimeTelemetryOptions,
|
|
2163
|
+
);
|
|
2164
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
2165
|
+
const queue = state.pending_runtime_contexts;
|
|
2166
|
+
if (!queue) break;
|
|
2167
|
+
const index = queue.findIndex((candidate) => candidate.turn_id === pending.turn_id);
|
|
2168
|
+
if (index < 0) continue;
|
|
2169
|
+
if (runtime.state === "observed") {
|
|
2170
|
+
queue.splice(index, 1);
|
|
2171
|
+
if (queue.length === 0) {
|
|
2172
|
+
state.pending_runtime_contexts = undefined;
|
|
2173
|
+
}
|
|
2174
|
+
commitTurnContextObservation(
|
|
2175
|
+
input,
|
|
2176
|
+
state,
|
|
2177
|
+
path,
|
|
2178
|
+
rootId,
|
|
2179
|
+
fingerprintContext,
|
|
2180
|
+
pending,
|
|
2181
|
+
runtimeContextObservation(runtime),
|
|
2182
|
+
{
|
|
2183
|
+
source_event: runtime.source_event,
|
|
2184
|
+
source_witness: runtime.source_witness,
|
|
2185
|
+
...(pending.runtime_version ? { runtime_version: pending.runtime_version } : {}),
|
|
2186
|
+
attestation: "derived",
|
|
2187
|
+
confidence: "exact",
|
|
2188
|
+
},
|
|
2189
|
+
signalClock(input).observed_at,
|
|
2190
|
+
);
|
|
2191
|
+
continue;
|
|
2192
|
+
}
|
|
2193
|
+
const attempts = pending.attempts + 1;
|
|
2194
|
+
if (
|
|
2195
|
+
options.finalAttempt ||
|
|
2196
|
+
runtime.state === "unsupported" ||
|
|
2197
|
+
!retryableRuntimeContextReason(runtime.reason) ||
|
|
2198
|
+
(!options.deferRetryLimit && attempts >= RUNTIME_CONTEXT_RETRY_LIMIT)
|
|
2199
|
+
) {
|
|
2200
|
+
queue.splice(index, 1);
|
|
2201
|
+
} else {
|
|
2202
|
+
queue[index] = { ...pending, attempts };
|
|
2203
|
+
}
|
|
2204
|
+
}
|
|
2205
|
+
if (state.pending_runtime_contexts?.length === 0) {
|
|
2206
|
+
state.pending_runtime_contexts = undefined;
|
|
2207
|
+
}
|
|
2208
|
+
publishProducerState(path, state);
|
|
2209
|
+
}
|
|
2210
|
+
|
|
2211
|
+
function reconcilePendingRuntimeContextsBeforeApprovedEnd(
|
|
2212
|
+
input: RecordApprovedSessionEndV3Input,
|
|
2213
|
+
state: HookProducerStateV3,
|
|
2214
|
+
path: string,
|
|
2215
|
+
rootId: `root_${string}`,
|
|
2216
|
+
fingerprintContext: ReturnType<typeof fingerprintContextV3>,
|
|
2217
|
+
): void {
|
|
2218
|
+
if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) return;
|
|
2219
|
+
for (const [index, delayMs] of APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS.entries()) {
|
|
2220
|
+
if (delayMs > 0) sleepSync(delayMs);
|
|
2221
|
+
reconcilePendingRuntimeContexts(
|
|
2222
|
+
{
|
|
2223
|
+
coordRoot: input.coordRoot,
|
|
2224
|
+
mode: input.mode,
|
|
2225
|
+
signal: "session-end",
|
|
2226
|
+
payload: { raw: {} },
|
|
2227
|
+
adapter: state.adapter,
|
|
2228
|
+
instance_id: state.instance_id,
|
|
2229
|
+
producer_id: "prd_agent-finalizer",
|
|
2230
|
+
build_id: input.build_id,
|
|
2231
|
+
platform: input.platform,
|
|
2232
|
+
observed_at: new Date().toISOString(),
|
|
2233
|
+
writerOptions: input.writerOptions,
|
|
2234
|
+
},
|
|
2235
|
+
state,
|
|
2236
|
+
path,
|
|
2237
|
+
rootId,
|
|
2238
|
+
fingerprintContext,
|
|
2239
|
+
{
|
|
2240
|
+
deferRetryLimit: true,
|
|
2241
|
+
finalAttempt: index === APPROVED_END_RUNTIME_CONTEXT_RETRY_DELAYS_MS.length - 1,
|
|
2242
|
+
},
|
|
2243
|
+
);
|
|
2244
|
+
if (!state.pending_runtime_contexts?.length) return;
|
|
2245
|
+
}
|
|
2246
|
+
}
|
|
2247
|
+
|
|
2248
|
+
function retryableRuntimeContextReason(reason: string | undefined): boolean {
|
|
2249
|
+
return (
|
|
2250
|
+
reason === "codex_transcript_turn_not_found" ||
|
|
2251
|
+
reason === "codex_transcript_turn_not_terminal" ||
|
|
2252
|
+
reason === "codex_transcript_token_count_missing"
|
|
2253
|
+
);
|
|
2254
|
+
}
|
|
2255
|
+
|
|
2256
|
+
function turnTelemetryForTerminal(
|
|
2257
|
+
input: RecordHookSignalV3Input,
|
|
2258
|
+
state: HookProducerStateV3,
|
|
2259
|
+
observedAt: string,
|
|
2260
|
+
): TurnTelemetryV3 {
|
|
2261
|
+
const native = extractTurnTelemetryV3(input.adapter, input.payload.raw, observedAt);
|
|
2262
|
+
if (native.context.state === "observed") return native;
|
|
2263
|
+
if (input.adapter === "cursor" && state.cursor_mode === "cloud") {
|
|
2264
|
+
return {
|
|
2265
|
+
...native,
|
|
2266
|
+
context: { state: "unsupported", capability: "context_usage" },
|
|
2267
|
+
};
|
|
2268
|
+
}
|
|
2269
|
+
|
|
2270
|
+
const request = {
|
|
2271
|
+
adapter: input.adapter,
|
|
2272
|
+
session_id: input.payload.session_id ?? input.payload.conversation_id,
|
|
2273
|
+
turn_id: input.payload.turn_id ?? state.current_native_turn_id,
|
|
2274
|
+
transcript_path: runtimeTranscriptPath(input, state),
|
|
2275
|
+
observed_at: observedAt,
|
|
2276
|
+
mode: "turn" as const,
|
|
2277
|
+
};
|
|
2278
|
+
let runtime = readRuntimeContextTelemetry(request, input.runtimeTelemetryOptions);
|
|
2279
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
2280
|
+
if (
|
|
2281
|
+
input.adapter === "codex" &&
|
|
2282
|
+
runtime.state === "partial" &&
|
|
2283
|
+
retryableRuntimeContextReason(runtime.reason)
|
|
2284
|
+
) {
|
|
2285
|
+
for (const delayMs of STOP_RUNTIME_CONTEXT_RETRY_DELAYS_MS) {
|
|
2286
|
+
sleepSync(delayMs);
|
|
2287
|
+
runtime = readRuntimeContextTelemetry(request, input.runtimeTelemetryOptions);
|
|
2288
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
2289
|
+
if (runtime.state !== "partial" || !retryableRuntimeContextReason(runtime.reason)) break;
|
|
2290
|
+
}
|
|
2291
|
+
}
|
|
2292
|
+
if (runtime.state === "unsupported") return native;
|
|
2293
|
+
return {
|
|
2294
|
+
...native,
|
|
2295
|
+
context: runtimeContextObservation(runtime),
|
|
2296
|
+
context_provenance: {
|
|
2297
|
+
source_event:
|
|
2298
|
+
runtime.state === "observed" ? runtime.source_event : `${input.adapter}.runtime_context`,
|
|
2299
|
+
...(runtime.state === "observed" ? { source_witness: runtime.source_witness } : {}),
|
|
2300
|
+
...(input.adapterVersion ? { runtime_version: input.adapterVersion } : {}),
|
|
2301
|
+
attestation: runtime.state === "observed" ? runtime.attestation : "derived",
|
|
2302
|
+
confidence: runtime.state === "observed" ? runtime.confidence : "high",
|
|
2303
|
+
},
|
|
2304
|
+
};
|
|
2305
|
+
}
|
|
2306
|
+
|
|
2307
|
+
/**
|
|
2308
|
+
* Resolve Codex's rollout once, retain it in owner-only producer state, and
|
|
2309
|
+
* verify the cached path against the native session before every reuse. Public
|
|
2310
|
+
* events receive only numeric telemetry and an opaque source witness.
|
|
2311
|
+
*/
|
|
2312
|
+
function runtimeTranscriptPath(
|
|
2313
|
+
input: RecordHookSignalV3Input,
|
|
2314
|
+
state: HookProducerStateV3,
|
|
2315
|
+
): string | undefined {
|
|
2316
|
+
if (input.adapter !== "codex") return input.payload.transcript_path;
|
|
2317
|
+
const nativeSessionId = input.payload.session_id ?? input.payload.conversation_id;
|
|
2318
|
+
if (!nativeSessionId) return input.payload.transcript_path;
|
|
2319
|
+
|
|
2320
|
+
const supplied = input.payload.transcript_path;
|
|
2321
|
+
if (supplied) {
|
|
2322
|
+
const verified = discoverCodexSessionTranscript(
|
|
2323
|
+
nativeSessionId,
|
|
2324
|
+
supplied,
|
|
2325
|
+
input.runtimeTelemetryOptions,
|
|
2326
|
+
);
|
|
2327
|
+
if (verified) state.runtime_transcript_path = verified;
|
|
2328
|
+
// Preserve a supplied mismatch so the typed reader reports it honestly.
|
|
2329
|
+
return verified ?? supplied;
|
|
2330
|
+
}
|
|
2331
|
+
|
|
2332
|
+
if (state.runtime_transcript_path) {
|
|
2333
|
+
const verified = discoverCodexSessionTranscript(
|
|
2334
|
+
nativeSessionId,
|
|
2335
|
+
state.runtime_transcript_path,
|
|
2336
|
+
input.runtimeTelemetryOptions,
|
|
2337
|
+
);
|
|
2338
|
+
if (verified) return verified;
|
|
2339
|
+
state.runtime_transcript_path = undefined;
|
|
2340
|
+
}
|
|
2341
|
+
|
|
2342
|
+
const discovered = discoverCodexSessionTranscript(
|
|
2343
|
+
nativeSessionId,
|
|
2344
|
+
undefined,
|
|
2345
|
+
input.runtimeTelemetryOptions,
|
|
2346
|
+
);
|
|
2347
|
+
if (discovered) state.runtime_transcript_path = discovered;
|
|
2348
|
+
return discovered;
|
|
2349
|
+
}
|
|
2350
|
+
|
|
2351
|
+
function runtimeContextObservation(
|
|
2352
|
+
runtime: RuntimeContextTelemetry,
|
|
2353
|
+
): TelemetryObservationV3<ContextMeasurementV3> {
|
|
2354
|
+
if (runtime.state === "observed") {
|
|
2355
|
+
if ("used_percent" in runtime) {
|
|
2356
|
+
return {
|
|
2357
|
+
state: "observed",
|
|
2358
|
+
value: {
|
|
2359
|
+
used_percent: runtime.used_percent,
|
|
2360
|
+
remaining_percent: Math.max(0, 100 - runtime.used_percent),
|
|
2361
|
+
measured_at: runtime.measured_at,
|
|
2362
|
+
method: runtime.method,
|
|
2363
|
+
},
|
|
2364
|
+
attestation: runtime.attestation,
|
|
2365
|
+
confidence: runtime.confidence,
|
|
2366
|
+
};
|
|
2367
|
+
}
|
|
2368
|
+
return {
|
|
2369
|
+
state: "observed",
|
|
2370
|
+
value: {
|
|
2371
|
+
used_tokens: runtime.used_tokens,
|
|
2372
|
+
limit_tokens: runtime.limit_tokens,
|
|
2373
|
+
remaining_tokens: Math.max(0, runtime.limit_tokens - runtime.used_tokens),
|
|
2374
|
+
measured_at: runtime.measured_at,
|
|
2375
|
+
method: runtime.method,
|
|
2376
|
+
},
|
|
2377
|
+
attestation: runtime.attestation,
|
|
2378
|
+
confidence: runtime.confidence,
|
|
2379
|
+
};
|
|
2380
|
+
}
|
|
2381
|
+
return {
|
|
2382
|
+
state: "expected_but_missing",
|
|
2383
|
+
capability: "context_usage",
|
|
2384
|
+
reason: runtime.reason,
|
|
2385
|
+
};
|
|
2386
|
+
}
|
|
2387
|
+
|
|
2388
|
+
/** Seed the change-detection baseline from a committed session.started. */
|
|
2389
|
+
function seedAttestedTuning(state: HookProducerStateV3, event: { payload: unknown }): void {
|
|
2390
|
+
const attestation = (event.payload as { runtime_attestation?: RuntimeAttestationV3Base })
|
|
2391
|
+
.runtime_attestation;
|
|
2392
|
+
if (!attestation) return;
|
|
2393
|
+
const tuning = attestation.tuning;
|
|
2394
|
+
state.last_attested_tuning =
|
|
2395
|
+
tuning?.state === "observed"
|
|
2396
|
+
? {
|
|
2397
|
+
...(tuning.value?.effort ? { effort: tuning.value.effort } : {}),
|
|
2398
|
+
...(tuning.value?.speed ? { speed: tuning.value.speed } : {}),
|
|
2399
|
+
}
|
|
2400
|
+
: {};
|
|
2401
|
+
const model = attestation.model;
|
|
2402
|
+
if (model.state === "observed") {
|
|
2403
|
+
state.last_attested_model = { provider: model.value.provider, id: model.value.id };
|
|
2404
|
+
}
|
|
2405
|
+
state.last_attested_model_observation = model;
|
|
2406
|
+
state.last_attested_tuning_observation = tuning;
|
|
2407
|
+
state.last_attested_telemetry = attestation.telemetry as RuntimeTelemetryCapabilitiesV3;
|
|
2408
|
+
}
|
|
2409
|
+
|
|
2410
|
+
/**
|
|
2411
|
+
* Emit `session.attestation_changed` when the observed tuning moves.
|
|
2412
|
+
*
|
|
2413
|
+
* Detection channels are deliberately cheap: CC stamps `effort.level` on
|
|
2414
|
+
* every tool hook and Stop (zero I/O), and Codex tuning is read from the
|
|
2415
|
+
* rollout only at turn terminals, where the context enrichment already pays
|
|
2416
|
+
* for a bounded tail read. A pre-upgrade state file (no baseline) seeds
|
|
2417
|
+
* silently so existing sessions do not fire a spurious change on their next
|
|
2418
|
+
* tool event; a fresh session's baseline comes from its session.started.
|
|
2419
|
+
*/
|
|
2420
|
+
function maybeAttestTuningChange(
|
|
2421
|
+
input: RecordHookSignalV3Input,
|
|
2422
|
+
state: HookProducerStateV3,
|
|
2423
|
+
path: string,
|
|
2424
|
+
rootId: `root_${string}`,
|
|
2425
|
+
): void {
|
|
2426
|
+
if (
|
|
2427
|
+
input.signal !== "pre-tool-use" &&
|
|
2428
|
+
input.signal !== "post-tool-use" &&
|
|
2429
|
+
input.signal !== "stop"
|
|
2430
|
+
) {
|
|
2431
|
+
return;
|
|
2432
|
+
}
|
|
2433
|
+
if (state.terminal) return;
|
|
2434
|
+
|
|
2435
|
+
let candidate: { effort?: string; speed?: string; model?: string } | undefined;
|
|
2436
|
+
let attestationSource: "native" | "derived" = "native";
|
|
2437
|
+
let sourceEvent = `${input.adapter}.effort-payload`;
|
|
2438
|
+
if (input.adapter === "claude-code" || input.adapter === "cursor") {
|
|
2439
|
+
if (!input.payload.effort) return;
|
|
2440
|
+
candidate = { effort: input.payload.effort };
|
|
2441
|
+
} else if (
|
|
2442
|
+
input.adapter === "codex" &&
|
|
2443
|
+
(input.signal === "stop" ||
|
|
2444
|
+
// Early probe: without it, a Codex card shows no effort until the first
|
|
2445
|
+
// turn terminal. One rollout read per turn while effort is unknown.
|
|
2446
|
+
(input.signal === "post-tool-use" &&
|
|
2447
|
+
!state.last_attested_tuning?.effort &&
|
|
2448
|
+
state.current_turn_id !== undefined &&
|
|
2449
|
+
state.tuning_probe_turn_id !== state.current_turn_id))
|
|
2450
|
+
) {
|
|
2451
|
+
if (input.signal === "post-tool-use") state.tuning_probe_turn_id = state.current_turn_id;
|
|
2452
|
+
const runtime = readRuntimeTuning(
|
|
2453
|
+
{
|
|
2454
|
+
adapter: "codex",
|
|
2455
|
+
session_id: input.payload.session_id ?? input.payload.conversation_id,
|
|
2456
|
+
transcript_path: runtimeTranscriptPath(input, state),
|
|
2457
|
+
},
|
|
2458
|
+
input.runtimeTelemetryOptions,
|
|
2459
|
+
);
|
|
2460
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
2461
|
+
if (runtime.state !== "observed") return;
|
|
2462
|
+
candidate = {
|
|
2463
|
+
...(runtime.effort ? { effort: runtime.effort } : {}),
|
|
2464
|
+
...(runtime.speed ? { speed: runtime.speed } : {}),
|
|
2465
|
+
...(runtime.model ? { model: runtime.model } : {}),
|
|
2466
|
+
};
|
|
2467
|
+
attestationSource = "derived";
|
|
2468
|
+
sourceEvent = runtime.source_event;
|
|
2469
|
+
} else {
|
|
2470
|
+
return;
|
|
2471
|
+
}
|
|
2472
|
+
|
|
2473
|
+
const baseline = state.last_attested_tuning;
|
|
2474
|
+
const next = { effort: candidate.effort, speed: candidate.speed ?? baseline?.speed };
|
|
2475
|
+
if (baseline === undefined || state.last_attested_telemetry === undefined) {
|
|
2476
|
+
// Pre-upgrade state: adopt without emitting; there is no attested prior.
|
|
2477
|
+
state.last_attested_tuning = { ...(next.effort ? { effort: next.effort } : {}) };
|
|
2478
|
+
if (next.speed) state.last_attested_tuning.speed = next.speed;
|
|
2479
|
+
return;
|
|
2480
|
+
}
|
|
2481
|
+
if (baseline.effort === next.effort && (candidate.speed ?? baseline.speed) === baseline.speed) {
|
|
2482
|
+
return;
|
|
2483
|
+
}
|
|
2484
|
+
|
|
2485
|
+
// CC change detection rides the payload; the paired transcript row also
|
|
2486
|
+
// carries speed and the (possibly swapped) model, so refresh from it.
|
|
2487
|
+
if (input.adapter === "claude-code") {
|
|
2488
|
+
const runtime = readRuntimeTuning({
|
|
2489
|
+
adapter: "claude-code",
|
|
2490
|
+
transcript_path: input.payload.transcript_path,
|
|
2491
|
+
});
|
|
2492
|
+
if (runtime.bytes_read > 0) recordRuntimeTelemetryTiming(state, runtime.io_duration_ms);
|
|
2493
|
+
if (runtime.state === "observed" && runtime.effort === candidate.effort) {
|
|
2494
|
+
if (runtime.speed) candidate.speed = runtime.speed;
|
|
2495
|
+
if (runtime.model) candidate.model = runtime.model;
|
|
2496
|
+
}
|
|
2497
|
+
}
|
|
2498
|
+
|
|
2499
|
+
const model: RuntimeAttestationV3Base["model"] = candidate.model
|
|
2500
|
+
? {
|
|
2501
|
+
state: "observed",
|
|
2502
|
+
value: { provider: modelProviderFor(input.adapter), id: safeRole(candidate.model) },
|
|
2503
|
+
attestation: "derived",
|
|
2504
|
+
confidence: "high",
|
|
2505
|
+
}
|
|
2506
|
+
: state.last_attested_model
|
|
2507
|
+
? {
|
|
2508
|
+
state: "observed",
|
|
2509
|
+
value: state.last_attested_model,
|
|
2510
|
+
attestation: "derived",
|
|
2511
|
+
confidence: "high",
|
|
2512
|
+
}
|
|
2513
|
+
: { state: "expected_but_missing", capability: "model_identity", reason: "not_reported" };
|
|
2514
|
+
const tuning: RuntimeAttestationV3Base["tuning"] =
|
|
2515
|
+
candidate.effort || candidate.speed
|
|
2516
|
+
? {
|
|
2517
|
+
state: "observed",
|
|
2518
|
+
value: {
|
|
2519
|
+
...(candidate.effort ? { effort: candidate.effort } : {}),
|
|
2520
|
+
...(candidate.speed ? { speed: candidate.speed } : {}),
|
|
2521
|
+
},
|
|
2522
|
+
attestation: attestationSource,
|
|
2523
|
+
confidence: "exact",
|
|
2524
|
+
}
|
|
2525
|
+
: { state: "unsupported", capability: "effort_selection" };
|
|
2526
|
+
commitRuntimeAttestationChange(input, state, path, rootId, {
|
|
2527
|
+
model,
|
|
2528
|
+
tuning,
|
|
2529
|
+
telemetry: state.last_attested_telemetry,
|
|
2530
|
+
reason: "runtime_tuning_changed",
|
|
2531
|
+
source_event: sourceEvent,
|
|
2532
|
+
attestation: attestationSource,
|
|
2533
|
+
confidence: attestationSource === "native" ? "exact" : "high",
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
|
|
2537
|
+
interface RuntimeAttestationChangeV3 {
|
|
2538
|
+
model: RuntimeAttestationV3Base["model"];
|
|
2539
|
+
tuning: RuntimeAttestationV3Base["tuning"];
|
|
2540
|
+
telemetry: RuntimeTelemetryCapabilitiesV3;
|
|
2541
|
+
reason: string;
|
|
2542
|
+
source_event: string;
|
|
2543
|
+
attestation: "native" | "derived" | "inferred";
|
|
2544
|
+
confidence: "exact" | "high" | "medium" | "low";
|
|
2545
|
+
}
|
|
2546
|
+
|
|
2547
|
+
function commitRuntimeAttestationChange(
|
|
2548
|
+
input: RecordHookSignalV3Input,
|
|
2549
|
+
state: HookProducerStateV3,
|
|
2550
|
+
path: string,
|
|
2551
|
+
rootId: `root_${string}`,
|
|
2552
|
+
change: RuntimeAttestationChangeV3,
|
|
2553
|
+
): void {
|
|
2554
|
+
const priorAttestationId = state.attestation_id;
|
|
2555
|
+
const nextAttestationId = attestationIdV3();
|
|
2556
|
+
const eventId = eventIdV3();
|
|
2557
|
+
const runtimeAttestation: RuntimeAttestationV3Base = {
|
|
2558
|
+
attestation_id: nextAttestationId,
|
|
2559
|
+
generation_id: state.generation_id,
|
|
2560
|
+
adapter: {
|
|
2561
|
+
state: "observed",
|
|
2562
|
+
value: {
|
|
2563
|
+
id: input.adapter,
|
|
2564
|
+
...(input.adapterVersion ? { version: input.adapterVersion } : {}),
|
|
2565
|
+
},
|
|
1532
2566
|
attestation: "native",
|
|
1533
2567
|
confidence: "exact",
|
|
2568
|
+
},
|
|
2569
|
+
harness: {
|
|
2570
|
+
state: "observed",
|
|
2571
|
+
value: {
|
|
2572
|
+
id: input.adapter,
|
|
2573
|
+
...(input.harnessVersion ? { version: input.harnessVersion } : {}),
|
|
2574
|
+
},
|
|
2575
|
+
attestation: "native",
|
|
2576
|
+
confidence: "exact",
|
|
2577
|
+
},
|
|
2578
|
+
model: change.model,
|
|
2579
|
+
tuning: change.tuning,
|
|
2580
|
+
telemetry: change.telemetry,
|
|
2581
|
+
capability_profile: state.capability_profile,
|
|
2582
|
+
declared_by_event_id: eventId,
|
|
2583
|
+
};
|
|
2584
|
+
const event = buildEventV3("session.attestation_changed", {
|
|
2585
|
+
event_id: eventId,
|
|
2586
|
+
producer: {
|
|
2587
|
+
producer_id: input.producer_id,
|
|
2588
|
+
boot_id: state.boot_id,
|
|
2589
|
+
sequence: state.next_sequence,
|
|
2590
|
+
component: "agent-hook",
|
|
2591
|
+
build_id: input.build_id,
|
|
2592
|
+
platform: input.platform,
|
|
2593
|
+
...(input.bridge ? { bridge: input.bridge } : {}),
|
|
2594
|
+
},
|
|
2595
|
+
scope: {
|
|
2596
|
+
root_id: rootId,
|
|
2597
|
+
instance_id: state.instance_id,
|
|
2598
|
+
session_id: state.session_id,
|
|
2599
|
+
generation_id: state.generation_id,
|
|
2600
|
+
...(input.run_id ? { run_id: input.run_id } : {}),
|
|
2601
|
+
...(input.workflow_id ? { workflow_id: input.workflow_id } : {}),
|
|
2602
|
+
...(input.workflow_agent_id ? { workflow_agent_id: input.workflow_agent_id } : {}),
|
|
2603
|
+
},
|
|
2604
|
+
attestation_id: nextAttestationId,
|
|
2605
|
+
links: { caused_by: state.last_event_id ? [state.last_event_id] : [] },
|
|
2606
|
+
provenance: {
|
|
2607
|
+
source_event: safeRole(change.source_event),
|
|
2608
|
+
attestation: change.attestation,
|
|
2609
|
+
confidence: change.confidence,
|
|
1534
2610
|
attribution: {
|
|
1535
2611
|
method: "native_payload",
|
|
1536
2612
|
state: "verified",
|
|
1537
2613
|
subject_instance_id: state.instance_id,
|
|
1538
2614
|
},
|
|
1539
2615
|
},
|
|
1540
|
-
observed_at:
|
|
1541
|
-
measurement.state === "observed"
|
|
1542
|
-
? measurement.value.measured_at
|
|
1543
|
-
: turnTerminal.time.observed_at,
|
|
2616
|
+
observed_at: input.observed_at ?? new Date().toISOString(),
|
|
1544
2617
|
monotonic_ns: orderedEventMonotonic(state, input.monotonic_ns),
|
|
1545
2618
|
clock_id: state.clock_id,
|
|
1546
2619
|
payload: {
|
|
1547
|
-
|
|
2620
|
+
prior_attestation_id: priorAttestationId,
|
|
2621
|
+
runtime_attestation: runtimeAttestation,
|
|
2622
|
+
reason: change.reason,
|
|
1548
2623
|
},
|
|
1549
2624
|
}) as EventV3;
|
|
2625
|
+
// Mutate BEFORE the commit: commitEventLocked publishes the state file, so
|
|
2626
|
+
// post-commit mutations would be dropped by the next signal's fresh read.
|
|
2627
|
+
// A crash between publishes replays the pending event against a state that
|
|
2628
|
+
// already carries the new attestation id, which is the id the event declares.
|
|
2629
|
+
state.attestation_id = nextAttestationId;
|
|
2630
|
+
state.last_attested_model_observation = change.model;
|
|
2631
|
+
state.last_attested_tuning_observation = change.tuning;
|
|
2632
|
+
state.last_attested_telemetry = change.telemetry;
|
|
2633
|
+
state.last_attested_model =
|
|
2634
|
+
change.model.state === "observed" ? { ...change.model.value } : undefined;
|
|
2635
|
+
state.last_attested_tuning = change.tuning.state === "observed" ? { ...change.tuning.value } : {};
|
|
1550
2636
|
commitEventLocked(input, state, path, event);
|
|
1551
2637
|
}
|
|
1552
2638
|
|
|
2639
|
+
function modelProviderFor(adapter: Adapter): string {
|
|
2640
|
+
if (adapter === "claude-code") return "anthropic";
|
|
2641
|
+
if (adapter === "codex") return "openai";
|
|
2642
|
+
return "cursor";
|
|
2643
|
+
}
|
|
2644
|
+
|
|
2645
|
+
function recordRuntimeTelemetryTiming(state: HookProducerStateV3, durationMs: number): void {
|
|
2646
|
+
const duration = Math.max(0, Math.ceil(durationMs));
|
|
2647
|
+
if (!Number.isSafeInteger(duration)) return;
|
|
2648
|
+
state.turn_harness = {
|
|
2649
|
+
hook_time_ms: state.turn_harness.hook_time_ms + duration,
|
|
2650
|
+
hook_count: state.turn_harness.hook_count + 1,
|
|
2651
|
+
slowest_hook:
|
|
2652
|
+
duration >= state.turn_harness.slowest_hook_ms
|
|
2653
|
+
? "runtime-context"
|
|
2654
|
+
: state.turn_harness.slowest_hook,
|
|
2655
|
+
slowest_hook_ms: Math.max(duration, state.turn_harness.slowest_hook_ms),
|
|
2656
|
+
};
|
|
2657
|
+
}
|
|
2658
|
+
|
|
1553
2659
|
function commitCapabilityDriftEvents(
|
|
1554
2660
|
input: RecordHookSignalV3Input,
|
|
1555
2661
|
state: HookProducerStateV3,
|
|
@@ -1785,6 +2891,40 @@ function isCursorPromptBootstrap(input: RecordHookSignalV3Input): boolean {
|
|
|
1785
2891
|
);
|
|
1786
2892
|
}
|
|
1787
2893
|
|
|
2894
|
+
/** Privacy-safe environment and recovery provenance for Codex mid-flight
|
|
2895
|
+
* onboarding. WSLENV values are never recorded, only normalized variable
|
|
2896
|
+
* names, and the native session identifier itself remains fingerprinted. */
|
|
2897
|
+
export function codexMidFlightDiagnosticContext(
|
|
2898
|
+
payload: ParsedPayload,
|
|
2899
|
+
env: NodeJS.ProcessEnv = process.env,
|
|
2900
|
+
): Record<string, string | boolean> {
|
|
2901
|
+
const wslenv = env.WSLENV?.trim() ?? "";
|
|
2902
|
+
const wslenvNames = [
|
|
2903
|
+
...new Set(
|
|
2904
|
+
wslenv
|
|
2905
|
+
.split(":")
|
|
2906
|
+
.map((entry) => entry.split("/", 1)[0]?.trim() ?? "")
|
|
2907
|
+
.filter((name) => /^[A-Za-z_][A-Za-z0-9_]*$/.test(name)),
|
|
2908
|
+
),
|
|
2909
|
+
]
|
|
2910
|
+
.sort()
|
|
2911
|
+
.join(":")
|
|
2912
|
+
.slice(0, 512);
|
|
2913
|
+
const identityRecoverySource = payload.session_id
|
|
2914
|
+
? "native_session_id"
|
|
2915
|
+
: payload.conversation_id
|
|
2916
|
+
? "native_conversation_id"
|
|
2917
|
+
: payload.agent_id
|
|
2918
|
+
? "native_agent_id"
|
|
2919
|
+
: "unavailable";
|
|
2920
|
+
return {
|
|
2921
|
+
thread_id_present: Boolean(env.CODEX_THREAD_ID?.trim()),
|
|
2922
|
+
wslenv_present: wslenv.length > 0,
|
|
2923
|
+
wslenv_names: wslenvNames,
|
|
2924
|
+
identity_recovery_source: identityRecoverySource,
|
|
2925
|
+
};
|
|
2926
|
+
}
|
|
2927
|
+
|
|
1788
2928
|
function suppressClosedSpanSignal(
|
|
1789
2929
|
input: RecordHookSignalV3Input,
|
|
1790
2930
|
sessionHash: `hid_${string}`,
|
|
@@ -1813,6 +2953,13 @@ export function recordApprovedSessionEndV3(
|
|
|
1813
2953
|
if (control.state !== input.mode) {
|
|
1814
2954
|
return { state: "gate_closed", reason: control.state };
|
|
1815
2955
|
}
|
|
2956
|
+
input = {
|
|
2957
|
+
...input,
|
|
2958
|
+
writerOptions: {
|
|
2959
|
+
...input.writerOptions,
|
|
2960
|
+
expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
|
|
2961
|
+
},
|
|
2962
|
+
};
|
|
1816
2963
|
const matches = listHookProducerStateRecordsV3(input.coordRoot, { includeTerminal: true }).filter(
|
|
1817
2964
|
({ state }) =>
|
|
1818
2965
|
state.instance_id === input.instance_id && state.generation_id === input.generation_id,
|
|
@@ -1854,6 +3001,7 @@ export function recordApprovedSessionEndV3(
|
|
|
1854
3001
|
state.generation_id,
|
|
1855
3002
|
state.privacy_epoch_id,
|
|
1856
3003
|
);
|
|
3004
|
+
reconcilePendingRuntimeContextsBeforeApprovedEnd(input, state, record.path, rootId, context);
|
|
1857
3005
|
const expected = [
|
|
1858
3006
|
"session_started",
|
|
1859
3007
|
"turn_closed",
|
|
@@ -1973,6 +3121,13 @@ export function salvageOpenSpansV3(input: SalvageOpenSpansV3Input): SalvageOpenS
|
|
|
1973
3121
|
if (control.state !== input.mode) {
|
|
1974
3122
|
return { state: "gate_closed", reason: control.state };
|
|
1975
3123
|
}
|
|
3124
|
+
input = {
|
|
3125
|
+
...input,
|
|
3126
|
+
writerOptions: {
|
|
3127
|
+
...input.writerOptions,
|
|
3128
|
+
expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
|
|
3129
|
+
},
|
|
3130
|
+
};
|
|
1976
3131
|
const matches = listHookProducerStateRecordsV3(input.coordRoot).filter(
|
|
1977
3132
|
({ state }) =>
|
|
1978
3133
|
state.instance_id === input.instance_id && state.generation_id === input.generation_id,
|
|
@@ -2081,6 +3236,9 @@ export function listHookProducerStateRecordsV3(
|
|
|
2081
3236
|
)) {
|
|
2082
3237
|
const path = join(directory, name);
|
|
2083
3238
|
const state = readProducerState(path);
|
|
3239
|
+
// Skip authorities left behind by a replaced epoch: their sequences and
|
|
3240
|
+
// causal links belong to the archived ledger, not this one.
|
|
3241
|
+
if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) continue;
|
|
2084
3242
|
if (!options.includeTerminal && state.terminal) continue;
|
|
2085
3243
|
records.push({ path, modified_at_ms: lstatSync(path).mtimeMs, state });
|
|
2086
3244
|
}
|
|
@@ -2137,7 +3295,101 @@ export function readHookProducerStateV3(
|
|
|
2137
3295
|
);
|
|
2138
3296
|
const sessionHash = normalizeNativeIdV3(context, `${adapter}.session`, nativeSessionId);
|
|
2139
3297
|
const path = producerStatePath(coordRoot, adapter, sessionHash);
|
|
2140
|
-
|
|
3298
|
+
if (!existsSync(path)) return undefined;
|
|
3299
|
+
const state = readProducerState(path);
|
|
3300
|
+
// A state left behind by a replaced epoch is not this epoch's authority.
|
|
3301
|
+
return state.epoch_genesis_id === control.genesis.event.payload.genesis_id ? state : undefined;
|
|
3302
|
+
}
|
|
3303
|
+
|
|
3304
|
+
export interface ReconcilePendingRuntimeContextV3Input {
|
|
3305
|
+
coordRoot: string;
|
|
3306
|
+
mode: EventV3WriteMode;
|
|
3307
|
+
nativeSessionId: string;
|
|
3308
|
+
producer_id: `prd_${string}`;
|
|
3309
|
+
build_id: `build_${string}`;
|
|
3310
|
+
platform: "linux" | "windows" | "macos" | "unknown";
|
|
3311
|
+
finalAttempt?: boolean;
|
|
3312
|
+
runtimeTelemetryOptions?: RuntimeTelemetryOptions;
|
|
3313
|
+
writerOptions?: WriteEventV3Options;
|
|
3314
|
+
}
|
|
3315
|
+
|
|
3316
|
+
export type ReconcilePendingRuntimeContextV3Result =
|
|
3317
|
+
| { state: "gate_closed" }
|
|
3318
|
+
| { state: "missing" }
|
|
3319
|
+
| { state: "busy" }
|
|
3320
|
+
| { state: "not_pending" }
|
|
3321
|
+
| { state: "pending" }
|
|
3322
|
+
| { state: "settled" };
|
|
3323
|
+
|
|
3324
|
+
/**
|
|
3325
|
+
* Retry one Codex session's owner-only context join without replaying its Stop
|
|
3326
|
+
* signal. Codex appends `task_complete` only after the synchronous Stop hook
|
|
3327
|
+
* exits, so this is invoked by a bounded detached worker after that exit.
|
|
3328
|
+
*/
|
|
3329
|
+
export function reconcilePendingRuntimeContextV3(
|
|
3330
|
+
input: ReconcilePendingRuntimeContextV3Input,
|
|
3331
|
+
): ReconcilePendingRuntimeContextV3Result {
|
|
3332
|
+
const control = readEventV3ControlState(input.coordRoot);
|
|
3333
|
+
if (control.state !== input.mode) return { state: "gate_closed" };
|
|
3334
|
+
if (control.state !== "candidate" && control.state !== "active") {
|
|
3335
|
+
return { state: "gate_closed" };
|
|
3336
|
+
}
|
|
3337
|
+
const rootId = control.genesis.event.scope.root_id as `root_${string}`;
|
|
3338
|
+
const rootContext = fingerprintContextV3(
|
|
3339
|
+
input.coordRoot,
|
|
3340
|
+
rootId,
|
|
3341
|
+
undefined,
|
|
3342
|
+
control.genesis.profile.privacy_key_epoch,
|
|
3343
|
+
);
|
|
3344
|
+
const sessionHash = normalizeNativeIdV3(rootContext, "codex.session", input.nativeSessionId);
|
|
3345
|
+
const path = producerStatePath(input.coordRoot, "codex", sessionHash);
|
|
3346
|
+
if (!existsSync(path)) return { state: "missing" };
|
|
3347
|
+
const lease = acquireStateLeaseWithRetry(input.coordRoot, path, STATE_LEASE_RETRY_ATTEMPTS);
|
|
3348
|
+
if (!lease) return { state: "busy" };
|
|
3349
|
+
try {
|
|
3350
|
+
const state = readProducerState(path);
|
|
3351
|
+
if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) {
|
|
3352
|
+
// The pending contexts belong to a replaced epoch; its archive already
|
|
3353
|
+
// holds everything this producer durably recorded.
|
|
3354
|
+
return { state: "missing" };
|
|
3355
|
+
}
|
|
3356
|
+
if (state.adapter !== "codex" || !state.pending_runtime_contexts?.length) {
|
|
3357
|
+
return { state: "not_pending" };
|
|
3358
|
+
}
|
|
3359
|
+
const context = fingerprintContextV3(
|
|
3360
|
+
input.coordRoot,
|
|
3361
|
+
rootId,
|
|
3362
|
+
state.generation_id,
|
|
3363
|
+
state.privacy_epoch_id,
|
|
3364
|
+
);
|
|
3365
|
+
reconcilePendingRuntimeContexts(
|
|
3366
|
+
{
|
|
3367
|
+
coordRoot: input.coordRoot,
|
|
3368
|
+
mode: input.mode,
|
|
3369
|
+
signal: "stop",
|
|
3370
|
+
payload: { raw: {}, session_id: input.nativeSessionId },
|
|
3371
|
+
adapter: "codex",
|
|
3372
|
+
instance_id: state.instance_id,
|
|
3373
|
+
producer_id: input.producer_id,
|
|
3374
|
+
build_id: input.build_id,
|
|
3375
|
+
platform: input.platform,
|
|
3376
|
+
observed_at: new Date().toISOString(),
|
|
3377
|
+
runtimeTelemetryOptions: input.runtimeTelemetryOptions,
|
|
3378
|
+
writerOptions: {
|
|
3379
|
+
...input.writerOptions,
|
|
3380
|
+
expectedGenesisId: control.genesis.event.payload.genesis_id as `gex_${string}`,
|
|
3381
|
+
},
|
|
3382
|
+
},
|
|
3383
|
+
state,
|
|
3384
|
+
path,
|
|
3385
|
+
rootId,
|
|
3386
|
+
context,
|
|
3387
|
+
{ deferRetryLimit: true, finalAttempt: input.finalAttempt },
|
|
3388
|
+
);
|
|
3389
|
+
return state.pending_runtime_contexts?.length ? { state: "pending" } : { state: "settled" };
|
|
3390
|
+
} finally {
|
|
3391
|
+
lease.release();
|
|
3392
|
+
}
|
|
2141
3393
|
}
|
|
2142
3394
|
|
|
2143
3395
|
/** Resolve one terminal producer only when native session and instance identity agree. */
|
|
@@ -2175,17 +3427,39 @@ export function readHookProducerStateByInstanceV3(
|
|
|
2175
3427
|
/^hid_[a-f0-9]{64}\.json$/.test(entry),
|
|
2176
3428
|
)) {
|
|
2177
3429
|
const state = readProducerState(join(directory, name));
|
|
3430
|
+
if (state.epoch_genesis_id !== control.genesis.event.payload.genesis_id) continue;
|
|
2178
3431
|
if (state.instance_id === instanceId && !state.terminal) matches.push(state);
|
|
2179
3432
|
}
|
|
2180
3433
|
}
|
|
2181
3434
|
return matches.length === 1 ? matches[0] : undefined;
|
|
2182
3435
|
}
|
|
2183
3436
|
|
|
3437
|
+
/**
|
|
3438
|
+
* Join a coordination actor to its hook producer.
|
|
3439
|
+
*
|
|
3440
|
+
* Native subagent commands can retain the parent's session id even after the
|
|
3441
|
+
* child has its own canonical generation. Prefer the native session join, but
|
|
3442
|
+
* when that points at a different instance accept only one exact live
|
|
3443
|
+
* instance match for the same adapter.
|
|
3444
|
+
*/
|
|
3445
|
+
export function readJoinableHookProducerStateV3(
|
|
3446
|
+
coordRoot: string,
|
|
3447
|
+
adapter: Adapter,
|
|
3448
|
+
nativeSessionId: string,
|
|
3449
|
+
instanceId: `inst_${string}`,
|
|
3450
|
+
): HookProducerStateV3 | undefined {
|
|
3451
|
+
const direct = readHookProducerStateV3(coordRoot, adapter, nativeSessionId);
|
|
3452
|
+
if (direct?.instance_id === instanceId && !direct.terminal) return direct;
|
|
3453
|
+
const byInstance = readHookProducerStateByInstanceV3(coordRoot, instanceId);
|
|
3454
|
+
return byInstance?.adapter === adapter && !byInstance.terminal ? byInstance : undefined;
|
|
3455
|
+
}
|
|
3456
|
+
|
|
2184
3457
|
function newProducerState(
|
|
2185
3458
|
input: RecordHookSignalV3Input,
|
|
2186
3459
|
sessionId: `sid_${string}`,
|
|
2187
3460
|
epochId: `pep_${string}`,
|
|
2188
3461
|
boundaryEventId: `evt_${string}`,
|
|
3462
|
+
genesisId: `gex_${string}`,
|
|
2189
3463
|
): HookProducerStateV3 {
|
|
2190
3464
|
const bootId = `boot_${randomUUID()}` as const;
|
|
2191
3465
|
return {
|
|
@@ -2194,11 +3468,12 @@ function newProducerState(
|
|
|
2194
3468
|
adapter: input.adapter,
|
|
2195
3469
|
instance_id: input.instance_id,
|
|
2196
3470
|
session_id: sessionId,
|
|
2197
|
-
generation_id: generationIdV3(),
|
|
3471
|
+
generation_id: input.delegated_child?.generation_id ?? generationIdV3(),
|
|
2198
3472
|
attestation_id: attestationIdV3(),
|
|
2199
3473
|
capability_profile: adapterCapabilityProfileDigestV3(input.adapter),
|
|
2200
3474
|
cursor_mode: input.adapter === "cursor" ? (input.payload.cursor_mode ?? "unknown") : undefined,
|
|
2201
3475
|
privacy_epoch_id: epochId,
|
|
3476
|
+
epoch_genesis_id: genesisId,
|
|
2202
3477
|
boot_id: bootId,
|
|
2203
3478
|
clock_id: clockIdV3(),
|
|
2204
3479
|
next_sequence: 1,
|
|
@@ -2209,6 +3484,7 @@ function newProducerState(
|
|
|
2209
3484
|
boot_id: bootId,
|
|
2210
3485
|
clock: signalClock(input),
|
|
2211
3486
|
}),
|
|
3487
|
+
session_start_derivation: input.session_start_derivation,
|
|
2212
3488
|
terminal: false,
|
|
2213
3489
|
spans: [],
|
|
2214
3490
|
delegations: [],
|
|
@@ -2234,10 +3510,12 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
|
|
|
2234
3510
|
if (event.event_type === "session.started") {
|
|
2235
3511
|
state.started_event_id = event.event_id as `evt_${string}`;
|
|
2236
3512
|
state.session_span.open_event_id = event.event_id as `evt_${string}`;
|
|
3513
|
+
seedAttestedTuning(state, event);
|
|
2237
3514
|
}
|
|
2238
3515
|
if (event.event_type === "turn.started") {
|
|
2239
3516
|
const nextTurnId = (event.scope as { turn_id: `tid_${string}` }).turn_id;
|
|
2240
3517
|
state.current_turn_id = nextTurnId;
|
|
3518
|
+
state.session_start_derivation = undefined;
|
|
2241
3519
|
if (state.tool_call_count_turn_id !== nextTurnId) {
|
|
2242
3520
|
state.tool_call_count = 0;
|
|
2243
3521
|
state.tool_call_count_turn_id = nextTurnId;
|
|
@@ -2321,6 +3599,7 @@ function applyCommittedEvent(state: HookProducerStateV3, event: EventV3): void {
|
|
|
2321
3599
|
}
|
|
2322
3600
|
}
|
|
2323
3601
|
state.current_turn_id = undefined;
|
|
3602
|
+
state.current_native_turn_id = undefined;
|
|
2324
3603
|
state.current_turn_span = undefined;
|
|
2325
3604
|
state.tool_call_count = 0;
|
|
2326
3605
|
state.tool_call_count_turn_id = undefined;
|
|
@@ -2511,6 +3790,14 @@ function safeRole(value: unknown): string {
|
|
|
2511
3790
|
return /^[a-zA-Z0-9]/.test(normalized) ? normalized : "agent";
|
|
2512
3791
|
}
|
|
2513
3792
|
|
|
3793
|
+
function asLiveInstanceId(nativeInstanceId: string): `inst_${string}` {
|
|
3794
|
+
if (/^inst_[a-zA-Z0-9._-]{1,128}$/.test(nativeInstanceId)) {
|
|
3795
|
+
return nativeInstanceId as `inst_${string}`;
|
|
3796
|
+
}
|
|
3797
|
+
if (/^[a-zA-Z0-9._-]{1,128}$/.test(nativeInstanceId)) return `inst_${nativeInstanceId}`;
|
|
3798
|
+
return `inst_${createHash("sha256").update(nativeInstanceId.normalize("NFC")).digest("hex")}`;
|
|
3799
|
+
}
|
|
3800
|
+
|
|
2514
3801
|
function safeTokenOrUndefined(value: unknown): string | undefined {
|
|
2515
3802
|
if (typeof value !== "string") return undefined;
|
|
2516
3803
|
const normalized = value.normalize("NFC");
|
|
@@ -2597,8 +3884,15 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
2597
3884
|
state.waits ??= [];
|
|
2598
3885
|
state.closed_turn_ids ??= [];
|
|
2599
3886
|
state.turn_harness ??= emptyTurnHarnessTiming();
|
|
3887
|
+
if (
|
|
3888
|
+
Array.isArray(state.pending_runtime_contexts) &&
|
|
3889
|
+
state.pending_runtime_contexts.length === 0
|
|
3890
|
+
) {
|
|
3891
|
+
state.pending_runtime_contexts = undefined;
|
|
3892
|
+
}
|
|
2600
3893
|
if (state.adapter === "cursor") state.cursor_mode ??= "unknown";
|
|
2601
3894
|
const allowedKeys = new Set([
|
|
3895
|
+
"active_runtime_context_probe",
|
|
2602
3896
|
"adapter",
|
|
2603
3897
|
"attestation_id",
|
|
2604
3898
|
"boot_id",
|
|
@@ -2607,20 +3901,32 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
2607
3901
|
"closed_spans",
|
|
2608
3902
|
"closed_turn_ids",
|
|
2609
3903
|
"current_turn_id",
|
|
3904
|
+
"current_native_turn_id",
|
|
2610
3905
|
"current_turn_span",
|
|
2611
3906
|
"cursor_mode",
|
|
2612
3907
|
"delegations",
|
|
3908
|
+
"epoch_genesis_id",
|
|
2613
3909
|
"format",
|
|
2614
3910
|
"format_version",
|
|
2615
3911
|
"generation_id",
|
|
2616
3912
|
"instance_id",
|
|
3913
|
+
"last_attested_model",
|
|
3914
|
+
"last_attested_model_observation",
|
|
3915
|
+
"last_attested_telemetry",
|
|
3916
|
+
"last_attested_tuning",
|
|
3917
|
+
"last_attested_tuning_observation",
|
|
3918
|
+
"last_context_source_witness",
|
|
3919
|
+
"tuning_probe_turn_id",
|
|
2617
3920
|
"last_event_id",
|
|
2618
3921
|
"last_monotonic_ns",
|
|
2619
3922
|
"last_observed_at",
|
|
2620
3923
|
"next_sequence",
|
|
2621
3924
|
"pending",
|
|
3925
|
+
"pending_runtime_contexts",
|
|
3926
|
+
"runtime_transcript_path",
|
|
2622
3927
|
"privacy_epoch_id",
|
|
2623
3928
|
"session_id",
|
|
3929
|
+
"session_start_derivation",
|
|
2624
3930
|
"session_span",
|
|
2625
3931
|
"spans",
|
|
2626
3932
|
"started_event_id",
|
|
@@ -2644,6 +3950,7 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
2644
3950
|
!/^att_[0-9a-f-]{36}$/.test(state.attestation_id) ||
|
|
2645
3951
|
!/^cap_[a-f0-9]{64}$/.test(state.capability_profile) ||
|
|
2646
3952
|
!/^pep_[a-zA-Z0-9._-]+$/.test(state.privacy_epoch_id) ||
|
|
3953
|
+
(state.epoch_genesis_id !== undefined && !/^gex_[0-9a-f-]{36}$/.test(state.epoch_genesis_id)) ||
|
|
2647
3954
|
!/^boot_[a-zA-Z0-9._-]+$/.test(state.boot_id) ||
|
|
2648
3955
|
!/^clk_[0-9a-f-]{36}$/.test(state.clock_id) ||
|
|
2649
3956
|
!Number.isSafeInteger(state.next_sequence) ||
|
|
@@ -2710,11 +4017,32 @@ function readProducerState(path: string): HookProducerStateV3 {
|
|
|
2710
4017
|
!Number.isSafeInteger(state.turn_ordinal) ||
|
|
2711
4018
|
state.turn_ordinal < 0 ||
|
|
2712
4019
|
(state.current_turn_id !== undefined && !/^tid_[a-f0-9]{64}$/.test(state.current_turn_id)) ||
|
|
4020
|
+
(state.current_native_turn_id !== undefined &&
|
|
4021
|
+
(typeof state.current_native_turn_id !== "string" ||
|
|
4022
|
+
state.current_native_turn_id.length === 0 ||
|
|
4023
|
+
state.current_native_turn_id.length > 512)) ||
|
|
2713
4024
|
(state.last_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.last_event_id)) ||
|
|
2714
4025
|
(state.last_monotonic_ns !== undefined && !/^\d+$/.test(state.last_monotonic_ns)) ||
|
|
2715
4026
|
(state.last_observed_at !== undefined &&
|
|
2716
4027
|
!Number.isFinite(Date.parse(state.last_observed_at))) ||
|
|
2717
4028
|
(state.started_event_id !== undefined && !/^evt_[0-9a-f-]{36}$/.test(state.started_event_id)) ||
|
|
4029
|
+
(state.session_start_derivation !== undefined &&
|
|
4030
|
+
state.session_start_derivation !== "approved_lifecycle_reopen" &&
|
|
4031
|
+
state.session_start_derivation !== "validated_current_session_heal") ||
|
|
4032
|
+
(state.pending_runtime_contexts !== undefined &&
|
|
4033
|
+
(!Array.isArray(state.pending_runtime_contexts) ||
|
|
4034
|
+
state.pending_runtime_contexts.length === 0 ||
|
|
4035
|
+
state.pending_runtime_contexts.length > PENDING_RUNTIME_CONTEXT_CAP ||
|
|
4036
|
+
state.pending_runtime_contexts.some((pending) => !validPendingRuntimeContext(pending)))) ||
|
|
4037
|
+
(state.active_runtime_context_probe !== undefined &&
|
|
4038
|
+
!validActiveRuntimeContextProbe(state.active_runtime_context_probe)) ||
|
|
4039
|
+
(state.last_context_source_witness !== undefined &&
|
|
4040
|
+
!/^[a-f0-9]{64}$/.test(state.last_context_source_witness)) ||
|
|
4041
|
+
(state.runtime_transcript_path !== undefined &&
|
|
4042
|
+
(typeof state.runtime_transcript_path !== "string" ||
|
|
4043
|
+
state.runtime_transcript_path.length === 0 ||
|
|
4044
|
+
state.runtime_transcript_path.length > 4096 ||
|
|
4045
|
+
state.runtime_transcript_path.includes("\0"))) ||
|
|
2718
4046
|
(state.pending?.source_id !== undefined &&
|
|
2719
4047
|
!/^hid_[a-f0-9]{64}$/.test(state.pending.source_id)) ||
|
|
2720
4048
|
(state.pending && !validateEventV3(state.pending.event).ok)
|
|
@@ -2794,6 +4122,51 @@ function validTurnHarnessTiming(value: TurnHarnessTimingV3): boolean {
|
|
|
2794
4122
|
);
|
|
2795
4123
|
}
|
|
2796
4124
|
|
|
4125
|
+
function validPendingRuntimeContext(value: unknown): value is PendingRuntimeContextV3 {
|
|
4126
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
4127
|
+
const pending = value as PendingRuntimeContextV3;
|
|
4128
|
+
return (
|
|
4129
|
+
typeof pending.terminal_event_id === "string" &&
|
|
4130
|
+
/^evt_[0-9a-f-]{36}$/.test(pending.terminal_event_id) &&
|
|
4131
|
+
typeof pending.terminal_observed_at === "string" &&
|
|
4132
|
+
Number.isFinite(Date.parse(pending.terminal_observed_at)) &&
|
|
4133
|
+
typeof pending.turn_id === "string" &&
|
|
4134
|
+
/^tid_[a-f0-9]{64}$/.test(pending.turn_id) &&
|
|
4135
|
+
(pending.run_id === undefined || /^run_[0-9a-f-]{36}$/.test(pending.run_id)) &&
|
|
4136
|
+
(pending.workflow_id === undefined || /^wf_[0-9a-f-]{36}$/.test(pending.workflow_id)) &&
|
|
4137
|
+
(pending.workflow_agent_id === undefined ||
|
|
4138
|
+
/^[a-zA-Z0-9][a-zA-Z0-9._:/+-]{0,127}$/.test(pending.workflow_agent_id)) &&
|
|
4139
|
+
typeof pending.native_session_id === "string" &&
|
|
4140
|
+
pending.native_session_id.length > 0 &&
|
|
4141
|
+
pending.native_session_id.length <= 512 &&
|
|
4142
|
+
typeof pending.native_turn_id === "string" &&
|
|
4143
|
+
pending.native_turn_id.length > 0 &&
|
|
4144
|
+
pending.native_turn_id.length <= 512 &&
|
|
4145
|
+
(pending.transcript_path === undefined ||
|
|
4146
|
+
(typeof pending.transcript_path === "string" &&
|
|
4147
|
+
pending.transcript_path.length > 0 &&
|
|
4148
|
+
pending.transcript_path.length <= 4096)) &&
|
|
4149
|
+
(pending.runtime_version === undefined ||
|
|
4150
|
+
(typeof pending.runtime_version === "string" &&
|
|
4151
|
+
/^[a-zA-Z0-9][a-zA-Z0-9._:/+-]{0,127}$/.test(pending.runtime_version))) &&
|
|
4152
|
+
Number.isSafeInteger(pending.attempts) &&
|
|
4153
|
+
pending.attempts >= 0 &&
|
|
4154
|
+
pending.attempts < RUNTIME_CONTEXT_RETRY_LIMIT
|
|
4155
|
+
);
|
|
4156
|
+
}
|
|
4157
|
+
|
|
4158
|
+
function validActiveRuntimeContextProbe(value: unknown): value is ActiveRuntimeContextProbeV3 {
|
|
4159
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) return false;
|
|
4160
|
+
const probe = value as ActiveRuntimeContextProbeV3;
|
|
4161
|
+
return (
|
|
4162
|
+
typeof probe.turn_id === "string" &&
|
|
4163
|
+
/^tid_[a-f0-9]{64}$/.test(probe.turn_id) &&
|
|
4164
|
+
typeof probe.attempted_at === "string" &&
|
|
4165
|
+
Number.isFinite(Date.parse(probe.attempted_at)) &&
|
|
4166
|
+
(probe.boundary === undefined || probe.boundary === "tool_completed")
|
|
4167
|
+
);
|
|
4168
|
+
}
|
|
4169
|
+
|
|
2797
4170
|
function pidIsAlive(pid: number): boolean {
|
|
2798
4171
|
if (!Number.isSafeInteger(pid) || pid < 1) return false;
|
|
2799
4172
|
try {
|