harnery 0.35.0 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -96
- package/dist/commands/agents.d.ts +23 -3
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +379 -198
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +5 -4
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts.map +1 -1
- package/dist/commands/semantic.js +54 -2
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +67 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +244 -10
- package/dist/core/agents/live-lifecycle-v3.js +6 -1
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +6 -1
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +24 -7
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +94 -13
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +18 -0
- package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +15 -90
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/artifacts/index.d.ts +21 -0
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +46 -1
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +81 -41
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +17 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.js +3 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +4 -2
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +3 -1
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +13 -21
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +45 -41
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.js +1 -1
- package/dist/core/events/v3/producers/intake.d.ts +7 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +25 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +55 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +353 -24
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
- package/dist/core/hooks/cli.js +212 -30
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +8 -3
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
- package/dist/core/hooks/remediation-cap.js +3 -11
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +8 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +11 -0
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +11 -8
- package/dist/core/semantic/adapters.d.ts.map +1 -1
- package/dist/core/semantic/adapters.js +169 -31
- package/dist/core/semantic/contract.d.ts +532 -48
- package/dist/core/semantic/contract.d.ts.map +1 -1
- package/dist/core/semantic/contract.js +104 -3
- package/dist/core/semantic/index.d.ts +7 -3
- package/dist/core/semantic/index.d.ts.map +1 -1
- package/dist/core/semantic/index.js +7 -3
- package/dist/core/semantic/once.d.ts +6 -1
- package/dist/core/semantic/once.d.ts.map +1 -1
- package/dist/core/semantic/once.js +80 -9
- package/dist/core/semantic/prompt.d.ts.map +1 -1
- package/dist/core/semantic/prompt.js +14 -1
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +14 -3
- package/dist/core/semantic/scheduler.d.ts.map +1 -1
- package/dist/core/semantic/scheduler.js +30 -6
- package/dist/core/semantic/service-status.d.ts +20 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -1
- package/dist/core/semantic/service-status.js +60 -4
- package/dist/core/semantic/service.d.ts +1 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +104 -15
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +11 -1
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +4 -3
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +3 -1
- package/dist/core/semantic/validate.d.ts.map +1 -1
- package/dist/core/semantic/validate.js +34 -1
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +5 -0
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +29 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +324 -112
- package/src/commander.ts +462 -95
- package/src/commands/agents.ts +517 -190
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +6 -7
- package/src/commands/conversations.ts +279 -0
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +66 -1
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +77 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/live-authority-v3.ts +341 -10
- package/src/core/agents/live-lifecycle-v3.ts +6 -1
- package/src/core/agents/live-observation-v3.ts +6 -1
- package/src/core/agents/render/prompt-context.ts +27 -6
- package/src/core/agents/rules/stop-hook.ts +107 -16
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-writer.ts +27 -0
- package/src/core/agents/state/live-coordination-view.ts +16 -105
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/artifacts/index.ts +64 -1
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +17 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +3 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +5 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +64 -46
- package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +1 -1
- package/src/core/events/v3/producers/intake.ts +30 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +571 -33
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +58 -7
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
- package/src/core/hooks/cli.ts +226 -32
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +12 -6
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +18 -0
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +200 -41
- package/src/core/semantic/contract.ts +135 -3
- package/src/core/semantic/index.ts +76 -2
- package/src/core/semantic/once.ts +93 -7
- package/src/core/semantic/prompt.ts +13 -1
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +49 -5
- package/src/core/semantic/service-status.ts +99 -5
- package/src/core/semantic/service.ts +116 -15
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +20 -6
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +31 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/templates.ts +5 -0
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -0,0 +1,499 @@
|
|
|
1
|
+
import { createHash, randomUUID } from "node:crypto";
|
|
2
|
+
import { appendFileSync, chmodSync, closeSync, existsSync, fsyncSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, renameSync, rmdirSync, statSync, unlinkSync, writeFileSync, } from "node:fs";
|
|
3
|
+
import { hostname } from "node:os";
|
|
4
|
+
import { join, resolve } from "node:path";
|
|
5
|
+
import { coordEnv } from "../../../../lib/env.js";
|
|
6
|
+
import { fsyncParentDirectory } from "../../../workflow/durable-record.js";
|
|
7
|
+
import { acquireNoClobberLease } from "../../../workflow/workspaces/leases.js";
|
|
8
|
+
import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../writer.js";
|
|
9
|
+
/**
|
|
10
|
+
* Producer-side bound on duplicate diagnostic file creation.
|
|
11
|
+
*
|
|
12
|
+
* A producer fault can emit the same diagnostic thousands of times per day,
|
|
13
|
+
* and every emission used to become one loose file in the diagnostics spool.
|
|
14
|
+
* This module keeps the first bounded loose exemplars per
|
|
15
|
+
* (category, reason, instance) key and UTC day unchanged, then coalesces
|
|
16
|
+
* further identical emissions into one deterministic summary file per key and
|
|
17
|
+
* window, preserving the exact logical count, first and last times,
|
|
18
|
+
* represented bytes, hourly rate buckets, and bounded exemplar digests.
|
|
19
|
+
*
|
|
20
|
+
* Below the bound the gate creates no state at all: admitted loose filenames
|
|
21
|
+
* carry the key digest as a suffix, and the gate counts a key's emissions for
|
|
22
|
+
* the window from those filenames alone. A summary file and its short-lived
|
|
23
|
+
* per-key lease exist only for a key that actually crossed the bound, so a
|
|
24
|
+
* healthy spool gains zero files and zero directories from this mitigation.
|
|
25
|
+
*
|
|
26
|
+
* The mitigation is fail-open: any count, lease, read, or publish failure
|
|
27
|
+
* admits the loose diagnostic exactly as before and appends to a lock-free,
|
|
28
|
+
* size-capped emergency log. It never deletes, moves, or rewrites an existing
|
|
29
|
+
* loose diagnostic, and it never calls back into the diagnostic writer.
|
|
30
|
+
*/
|
|
31
|
+
export const DIAGNOSTIC_SUMMARY_FORMAT = "harnery-v3-diagnostic-summary";
|
|
32
|
+
export const DIAGNOSTIC_SUMMARY_VERSION = 1;
|
|
33
|
+
/**
|
|
34
|
+
* Loose exemplars admitted per (category, reason, instance) key per UTC day
|
|
35
|
+
* before identical emissions coalesce into the key's summary. Frozen from a
|
|
36
|
+
* whole-history measurement: healthy categories peak well under this value
|
|
37
|
+
* per day across ALL keys combined, while a producer fault exceeds it within
|
|
38
|
+
* minutes. The bound is enforced from filename counts without cross-process
|
|
39
|
+
* locking, so simultaneous writers straddling the crossing can admit a few
|
|
40
|
+
* extra exemplars; the bound is a flood stop, not an exact quota.
|
|
41
|
+
*/
|
|
42
|
+
export const DIAGNOSTIC_LOOSE_EXEMPLAR_LIMIT = 32;
|
|
43
|
+
/** Bounded exemplar digests retained inside one summary. */
|
|
44
|
+
const SUMMARY_EXEMPLAR_LIMIT = 4;
|
|
45
|
+
/**
|
|
46
|
+
* Hourly rate buckets retained inside one summary. One summary covers one UTC
|
|
47
|
+
* day, so at most 24 buckets are reachable; the margin absorbs clock skew.
|
|
48
|
+
* Consumer windows wider than a day (doctor reads 48h) span multiple
|
|
49
|
+
* day-scoped summary files, not more buckets in one file.
|
|
50
|
+
*/
|
|
51
|
+
const SUMMARY_HOUR_BUCKET_LIMIT = 26;
|
|
52
|
+
/** Refuse to publish a summary larger than this; falls open to loose writes. */
|
|
53
|
+
const SUMMARY_MAX_BYTES = 128 * 1024;
|
|
54
|
+
/** Coalesce updates fsync only every Nth increment; a crash between durable
|
|
55
|
+
* points can lose at most this many recent increments from the summary. */
|
|
56
|
+
const SUMMARY_DURABLE_EVERY = 32;
|
|
57
|
+
/** Stop appending to the emergency fail-open log past this size. */
|
|
58
|
+
const MITIGATION_HEALTH_MAX_BYTES = 256 * 1024;
|
|
59
|
+
export const DIAGNOSTIC_MITIGATION_HEALTH_FILE = "mitigation-health.ndjson";
|
|
60
|
+
const LEASE_STALE_AFTER_MS = 5_000;
|
|
61
|
+
const LEASE_RETRIES = 4;
|
|
62
|
+
const LEASE_RETRY_MS = 10;
|
|
63
|
+
const METADATA_KEY_LIMIT = 16;
|
|
64
|
+
const METADATA_VALUE_LIMIT = 256;
|
|
65
|
+
/** Extracts the 15-digit epoch-ms segment of a loose diagnostic order key. */
|
|
66
|
+
const LOOSE_ORDER_KEY_TIMESTAMP = /-(\d{15})-\d{20}-/;
|
|
67
|
+
const sleepCell = new Int32Array(new SharedArrayBuffer(4));
|
|
68
|
+
export function diagnosticSummariesRootV3(coordRoot) {
|
|
69
|
+
return join(resolve(coordRoot), EVENT_V3_LEDGER_RELATIVE_ROOT, "diagnostic-summaries");
|
|
70
|
+
}
|
|
71
|
+
function looseDiagnosticsRootV3(coordRoot) {
|
|
72
|
+
return join(resolve(coordRoot), EVENT_V3_LEDGER_RELATIVE_ROOT, "diagnostics");
|
|
73
|
+
}
|
|
74
|
+
export function diagnosticSummariesEnabledV3() {
|
|
75
|
+
return coordEnv("V3_DIAGNOSTIC_SUMMARIES") !== "0";
|
|
76
|
+
}
|
|
77
|
+
function sanitizeComponent(value, fallback) {
|
|
78
|
+
if (typeof value !== "string" || value.length === 0)
|
|
79
|
+
return fallback;
|
|
80
|
+
const safe = value.replace(/[^a-zA-Z0-9._-]/g, "_").slice(0, 128);
|
|
81
|
+
return safe.length > 0 ? safe : fallback;
|
|
82
|
+
}
|
|
83
|
+
function keyDigest(category, reason, instanceId) {
|
|
84
|
+
return createHash("sha256")
|
|
85
|
+
.update(`${category}\n${reason}\n${instanceId}`)
|
|
86
|
+
.digest("hex")
|
|
87
|
+
.slice(0, 16);
|
|
88
|
+
}
|
|
89
|
+
function utcDay(nowMs) {
|
|
90
|
+
return new Date(nowMs).toISOString().slice(0, 10);
|
|
91
|
+
}
|
|
92
|
+
function utcHour(nowMs) {
|
|
93
|
+
return new Date(nowMs).toISOString().slice(0, 13);
|
|
94
|
+
}
|
|
95
|
+
function summaryPath(root, category, window, digest) {
|
|
96
|
+
return join(root, `${category}-${window.replaceAll("-", "")}-${digest}.json`);
|
|
97
|
+
}
|
|
98
|
+
function ensureOwnerOnlyDirectory(path) {
|
|
99
|
+
mkdirSync(path, { recursive: true, mode: 0o700 });
|
|
100
|
+
chmodSync(path, 0o700);
|
|
101
|
+
}
|
|
102
|
+
function publishOwnerOnlyJson(path, value, durable) {
|
|
103
|
+
const contents = `${JSON.stringify(value)}\n`;
|
|
104
|
+
if (Buffer.byteLength(contents, "utf8") > SUMMARY_MAX_BYTES) {
|
|
105
|
+
throw new Error("diagnostic summary exceeds its size bound");
|
|
106
|
+
}
|
|
107
|
+
const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
108
|
+
let fd;
|
|
109
|
+
try {
|
|
110
|
+
fd = openSync(temporary, "wx", 0o600);
|
|
111
|
+
writeFileSync(fd, contents, "utf8");
|
|
112
|
+
if (durable)
|
|
113
|
+
fsyncSync(fd);
|
|
114
|
+
closeSync(fd);
|
|
115
|
+
fd = undefined;
|
|
116
|
+
renameSync(temporary, path);
|
|
117
|
+
if (durable)
|
|
118
|
+
fsyncParentDirectory(path);
|
|
119
|
+
}
|
|
120
|
+
finally {
|
|
121
|
+
if (fd !== undefined)
|
|
122
|
+
closeSync(fd);
|
|
123
|
+
if (existsSync(temporary))
|
|
124
|
+
unlinkSync(temporary);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
function pidIsAlive(pid) {
|
|
128
|
+
if (!Number.isSafeInteger(pid) || pid < 1)
|
|
129
|
+
return false;
|
|
130
|
+
try {
|
|
131
|
+
process.kill(pid, 0);
|
|
132
|
+
return true;
|
|
133
|
+
}
|
|
134
|
+
catch (error) {
|
|
135
|
+
return error.code !== "ESRCH";
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
function withKeyLease(root, digest, operation) {
|
|
139
|
+
const leasesDir = join(root, "leases");
|
|
140
|
+
ensureOwnerOnlyDirectory(leasesDir);
|
|
141
|
+
const leaseDir = join(leasesDir, digest);
|
|
142
|
+
const authority = createHash("sha256").update(resolve(root)).digest("hex");
|
|
143
|
+
let lease;
|
|
144
|
+
for (let attempt = 0; attempt < LEASE_RETRIES; attempt += 1) {
|
|
145
|
+
try {
|
|
146
|
+
lease = acquireNoClobberLease({
|
|
147
|
+
path: leaseDir,
|
|
148
|
+
scope: "event-v3-diagnostic-summary",
|
|
149
|
+
authoritySha256: authority,
|
|
150
|
+
staleAfterMs: LEASE_STALE_AFTER_MS,
|
|
151
|
+
validateStaleOwner: (owner) => owner.host === hostname() && !pidIsAlive(owner.pid),
|
|
152
|
+
});
|
|
153
|
+
break;
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (attempt === LEASE_RETRIES - 1)
|
|
157
|
+
throw error;
|
|
158
|
+
Atomics.wait(sleepCell, 0, 0, LEASE_RETRY_MS);
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
if (!lease)
|
|
162
|
+
throw new Error("diagnostic summary lease is busy");
|
|
163
|
+
try {
|
|
164
|
+
return operation();
|
|
165
|
+
}
|
|
166
|
+
finally {
|
|
167
|
+
// A durably published result must survive release-time faults (an epoch
|
|
168
|
+
// rotation can remove the lease state mid-operation); stale takeover
|
|
169
|
+
// recovers any residue. The empty lease directory is removed so per-key
|
|
170
|
+
// lease state never outlives the contention that needed it.
|
|
171
|
+
try {
|
|
172
|
+
lease.release();
|
|
173
|
+
}
|
|
174
|
+
catch {
|
|
175
|
+
// Swallowed: the operation's outcome already stands.
|
|
176
|
+
}
|
|
177
|
+
try {
|
|
178
|
+
rmdirSync(leaseDir);
|
|
179
|
+
}
|
|
180
|
+
catch {
|
|
181
|
+
// A concurrent acquirer repopulated it, or release left residue.
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
/**
|
|
186
|
+
* Count the key's admitted loose exemplars for a UTC-day window from their
|
|
187
|
+
* digest-suffixed filenames. Files written before this mitigation carry no
|
|
188
|
+
* suffix and are not counted, so a pre-existing flood does not consume the
|
|
189
|
+
* window's exemplar budget.
|
|
190
|
+
*/
|
|
191
|
+
function countLooseExemplars(coordRoot, digest, window) {
|
|
192
|
+
const directory = looseDiagnosticsRootV3(coordRoot);
|
|
193
|
+
if (!existsSync(directory))
|
|
194
|
+
return 0;
|
|
195
|
+
const windowStartMs = Date.parse(`${window}T00:00:00.000Z`);
|
|
196
|
+
const windowEndMs = windowStartMs + 24 * 60 * 60 * 1000;
|
|
197
|
+
const suffix = `-${digest}.json`;
|
|
198
|
+
let count = 0;
|
|
199
|
+
for (const name of readdirSync(directory)) {
|
|
200
|
+
if (!name.endsWith(suffix))
|
|
201
|
+
continue;
|
|
202
|
+
const epochMs = Number(LOOSE_ORDER_KEY_TIMESTAMP.exec(name)?.[1]);
|
|
203
|
+
if (Number.isFinite(epochMs) && epochMs >= windowStartMs && epochMs < windowEndMs) {
|
|
204
|
+
count += 1;
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
return count;
|
|
208
|
+
}
|
|
209
|
+
function boundedMetadata(metadata) {
|
|
210
|
+
const bounded = {};
|
|
211
|
+
let kept = 0;
|
|
212
|
+
for (const [key, value] of Object.entries(metadata)) {
|
|
213
|
+
if (kept >= METADATA_KEY_LIMIT)
|
|
214
|
+
break;
|
|
215
|
+
if (typeof value === "string" && value.length > METADATA_VALUE_LIMIT)
|
|
216
|
+
continue;
|
|
217
|
+
bounded[key] = value;
|
|
218
|
+
kept += 1;
|
|
219
|
+
}
|
|
220
|
+
return bounded;
|
|
221
|
+
}
|
|
222
|
+
function pruneHourBuckets(buckets, nowMs) {
|
|
223
|
+
const keys = Object.keys(buckets).sort();
|
|
224
|
+
const horizon = utcHour(nowMs - SUMMARY_HOUR_BUCKET_LIMIT * 60 * 60 * 1000);
|
|
225
|
+
const pruned = {};
|
|
226
|
+
for (const key of keys) {
|
|
227
|
+
if (key >= horizon)
|
|
228
|
+
pruned[key] = buckets[key];
|
|
229
|
+
}
|
|
230
|
+
// A pathological clock can still grow the map; hard-cap by newest keys.
|
|
231
|
+
const capped = Object.keys(pruned).sort().slice(-SUMMARY_HOUR_BUCKET_LIMIT);
|
|
232
|
+
const result = {};
|
|
233
|
+
for (const key of capped)
|
|
234
|
+
result[key] = pruned[key];
|
|
235
|
+
return result;
|
|
236
|
+
}
|
|
237
|
+
function freshSummary(category, reason, instanceId, window) {
|
|
238
|
+
return {
|
|
239
|
+
format: DIAGNOSTIC_SUMMARY_FORMAT,
|
|
240
|
+
format_version: DIAGNOSTIC_SUMMARY_VERSION,
|
|
241
|
+
category,
|
|
242
|
+
reason,
|
|
243
|
+
instance_id: instanceId,
|
|
244
|
+
window,
|
|
245
|
+
loose_count: 0,
|
|
246
|
+
summarized_count: 0,
|
|
247
|
+
first_summarized_at: null,
|
|
248
|
+
last_summarized_at: null,
|
|
249
|
+
represented_bytes: 0,
|
|
250
|
+
exemplars: [],
|
|
251
|
+
metadata: {},
|
|
252
|
+
recent_hours: {},
|
|
253
|
+
};
|
|
254
|
+
}
|
|
255
|
+
function readSummaryFile(path) {
|
|
256
|
+
let parsed;
|
|
257
|
+
try {
|
|
258
|
+
const metadata = lstatSync(path);
|
|
259
|
+
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
260
|
+
return undefined;
|
|
261
|
+
parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
262
|
+
}
|
|
263
|
+
catch {
|
|
264
|
+
return undefined;
|
|
265
|
+
}
|
|
266
|
+
if (!parsed || typeof parsed !== "object" || Array.isArray(parsed))
|
|
267
|
+
return undefined;
|
|
268
|
+
const summary = parsed;
|
|
269
|
+
if (summary.format !== DIAGNOSTIC_SUMMARY_FORMAT ||
|
|
270
|
+
summary.format_version !== DIAGNOSTIC_SUMMARY_VERSION ||
|
|
271
|
+
typeof summary.category !== "string" ||
|
|
272
|
+
typeof summary.reason !== "string" ||
|
|
273
|
+
typeof summary.instance_id !== "string" ||
|
|
274
|
+
!/^\d{4}-\d{2}-\d{2}$/.test(summary.window) ||
|
|
275
|
+
!Number.isSafeInteger(summary.loose_count) ||
|
|
276
|
+
summary.loose_count < 0 ||
|
|
277
|
+
!Number.isSafeInteger(summary.summarized_count) ||
|
|
278
|
+
summary.summarized_count < 0 ||
|
|
279
|
+
!Number.isSafeInteger(summary.represented_bytes) ||
|
|
280
|
+
summary.represented_bytes < 0 ||
|
|
281
|
+
!Array.isArray(summary.exemplars) ||
|
|
282
|
+
!summary.recent_hours ||
|
|
283
|
+
typeof summary.recent_hours !== "object" ||
|
|
284
|
+
Array.isArray(summary.recent_hours)) {
|
|
285
|
+
return undefined;
|
|
286
|
+
}
|
|
287
|
+
// Drop malformed rate buckets so a corrupt value can neither poison later
|
|
288
|
+
// increments nor silently diverge windowed counts from the total.
|
|
289
|
+
const hours = {};
|
|
290
|
+
for (const [key, value] of Object.entries(summary.recent_hours)) {
|
|
291
|
+
if (/^\d{4}-\d{2}-\d{2}T\d{2}$/.test(key) && Number.isSafeInteger(value) && value >= 0) {
|
|
292
|
+
hours[key] = value;
|
|
293
|
+
}
|
|
294
|
+
}
|
|
295
|
+
summary.recent_hours = hours;
|
|
296
|
+
return summary;
|
|
297
|
+
}
|
|
298
|
+
/**
|
|
299
|
+
* Append one line to the emergency fail-open log. Lock-free by design: an
|
|
300
|
+
* O_APPEND write of one small line is atomic, so concurrent fail-opens never
|
|
301
|
+
* serialize on shared state. Best-effort, size-capped, and nonrecursive: a
|
|
302
|
+
* failure here is swallowed, never diagnosed, and never blocks the loose
|
|
303
|
+
* fallback write.
|
|
304
|
+
*/
|
|
305
|
+
function recordFailOpen(root, stage, nowMs) {
|
|
306
|
+
try {
|
|
307
|
+
ensureOwnerOnlyDirectory(root);
|
|
308
|
+
const path = join(root, DIAGNOSTIC_MITIGATION_HEALTH_FILE);
|
|
309
|
+
try {
|
|
310
|
+
if (statSync(path).size >= MITIGATION_HEALTH_MAX_BYTES)
|
|
311
|
+
return;
|
|
312
|
+
}
|
|
313
|
+
catch {
|
|
314
|
+
// Missing log starts fresh.
|
|
315
|
+
}
|
|
316
|
+
const line = JSON.stringify({ at: new Date(nowMs).toISOString(), stage, pid: process.pid });
|
|
317
|
+
appendFileSync(path, `${line}\n`, { mode: 0o600 });
|
|
318
|
+
}
|
|
319
|
+
catch {
|
|
320
|
+
// The emergency log may undercount when storage is unavailable; it is a
|
|
321
|
+
// signal, not accounting, and must never throw into the producer path.
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
function readMitigationHealth(path) {
|
|
325
|
+
let contents;
|
|
326
|
+
let size = 0;
|
|
327
|
+
try {
|
|
328
|
+
const metadata = lstatSync(path);
|
|
329
|
+
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
330
|
+
return null;
|
|
331
|
+
size = metadata.size;
|
|
332
|
+
contents = readFileSync(path, "utf8");
|
|
333
|
+
}
|
|
334
|
+
catch {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const health = {
|
|
338
|
+
fail_open_count: 0,
|
|
339
|
+
last_fail_open_at: null,
|
|
340
|
+
by_stage: {},
|
|
341
|
+
truncated: size >= MITIGATION_HEALTH_MAX_BYTES,
|
|
342
|
+
};
|
|
343
|
+
for (const line of contents.split("\n")) {
|
|
344
|
+
if (line.trim().length === 0)
|
|
345
|
+
continue;
|
|
346
|
+
// Every non-empty line was one fail-open, even a torn one.
|
|
347
|
+
health.fail_open_count += 1;
|
|
348
|
+
try {
|
|
349
|
+
const row = JSON.parse(line);
|
|
350
|
+
if (typeof row.at === "string")
|
|
351
|
+
health.last_fail_open_at = row.at;
|
|
352
|
+
if (typeof row.stage === "string" && row.stage.length <= 32) {
|
|
353
|
+
if (Object.keys(health.by_stage).length < 16 || health.by_stage[row.stage] !== undefined) {
|
|
354
|
+
health.by_stage[row.stage] = (health.by_stage[row.stage] ?? 0) + 1;
|
|
355
|
+
}
|
|
356
|
+
}
|
|
357
|
+
}
|
|
358
|
+
catch {
|
|
359
|
+
// A torn tail line still counts above.
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
return health;
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* Decide whether one diagnostic emission may become a loose file.
|
|
366
|
+
*
|
|
367
|
+
* Below the per-key bound (counted from digest-suffixed loose filenames) the
|
|
368
|
+
* emission is admitted with the suffix to append, and no summary or lease
|
|
369
|
+
* state is created. At or past the bound the emission is durably coalesced
|
|
370
|
+
* into the key's summary under a short per-key lease and `admit: false` is
|
|
371
|
+
* returned with the summary path. Any mitigation failure, and the disabled
|
|
372
|
+
* gate, admit the loose write exactly as before.
|
|
373
|
+
*/
|
|
374
|
+
export function gateProducerDiagnosticV3(coordRoot, input, nowMs = Date.now()) {
|
|
375
|
+
if (!diagnosticSummariesEnabledV3())
|
|
376
|
+
return { admit: true, loose_name_suffix: "" };
|
|
377
|
+
const at = Number.isFinite(nowMs) ? nowMs : Date.now();
|
|
378
|
+
const category = sanitizeComponent(input.category, "unknown");
|
|
379
|
+
const reason = sanitizeComponent(input.reason, "none");
|
|
380
|
+
const instanceId = sanitizeComponent(input.instanceId, "unknown");
|
|
381
|
+
const window = utcDay(at);
|
|
382
|
+
const digest = keyDigest(category, reason, instanceId);
|
|
383
|
+
const admitLoose = { admit: true, loose_name_suffix: `-${digest}` };
|
|
384
|
+
const root = diagnosticSummariesRootV3(coordRoot);
|
|
385
|
+
let stage = "peek";
|
|
386
|
+
try {
|
|
387
|
+
const path = summaryPath(root, category, window, digest);
|
|
388
|
+
if (!readSummaryFile(path)) {
|
|
389
|
+
stage = "count";
|
|
390
|
+
if (countLooseExemplars(coordRoot, digest, window) < DIAGNOSTIC_LOOSE_EXEMPLAR_LIMIT) {
|
|
391
|
+
return admitLoose;
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
stage = "coalesce";
|
|
395
|
+
ensureOwnerOnlyDirectory(root);
|
|
396
|
+
return withKeyLease(root, digest, () => {
|
|
397
|
+
const existing = readSummaryFile(path);
|
|
398
|
+
const state = existing ?? freshSummary(category, reason, instanceId, window);
|
|
399
|
+
if (!existing)
|
|
400
|
+
state.loose_count = countLooseExemplars(coordRoot, digest, window);
|
|
401
|
+
const atIso = new Date(at).toISOString();
|
|
402
|
+
state.summarized_count += 1;
|
|
403
|
+
state.first_summarized_at ??= atIso;
|
|
404
|
+
state.last_summarized_at = atIso;
|
|
405
|
+
if (Number.isSafeInteger(input.fingerprint?.bytes) && input.fingerprint.bytes >= 0) {
|
|
406
|
+
state.represented_bytes += input.fingerprint.bytes;
|
|
407
|
+
}
|
|
408
|
+
if (state.exemplars.length < SUMMARY_EXEMPLAR_LIMIT && input.fingerprint) {
|
|
409
|
+
state.exemplars.push({
|
|
410
|
+
bytes: input.fingerprint.bytes,
|
|
411
|
+
sha256: input.fingerprint.sha256,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
if (Object.keys(state.metadata).length === 0) {
|
|
415
|
+
state.metadata = boundedMetadata(input.metadata ?? {});
|
|
416
|
+
}
|
|
417
|
+
const hour = utcHour(at);
|
|
418
|
+
state.recent_hours[hour] = (state.recent_hours[hour] ?? 0) + 1;
|
|
419
|
+
state.recent_hours = pruneHourBuckets(state.recent_hours, at);
|
|
420
|
+
const durable = !existing || state.summarized_count % SUMMARY_DURABLE_EVERY === 0;
|
|
421
|
+
publishOwnerOnlyJson(path, state, durable);
|
|
422
|
+
return { admit: false, summary_path: path };
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
catch {
|
|
426
|
+
recordFailOpen(root, stage, at);
|
|
427
|
+
return admitLoose;
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Read every summary in the active epoch's `diagnostic-summaries/` subtree.
|
|
432
|
+
* Skips lease state, temp files, and the mitigation health log (which is
|
|
433
|
+
* aggregated into `mitigation_health` instead). Never throws; a missing
|
|
434
|
+
* subtree returns an empty listing.
|
|
435
|
+
*/
|
|
436
|
+
export function listDiagnosticSummariesV3(coordRoot) {
|
|
437
|
+
const root = diagnosticSummariesRootV3(coordRoot);
|
|
438
|
+
const listing = {
|
|
439
|
+
summaries: [],
|
|
440
|
+
file_count: 0,
|
|
441
|
+
unreadable_count: 0,
|
|
442
|
+
mitigation_health: null,
|
|
443
|
+
};
|
|
444
|
+
let names;
|
|
445
|
+
try {
|
|
446
|
+
const metadata = lstatSync(root);
|
|
447
|
+
if (!metadata.isDirectory() || metadata.isSymbolicLink())
|
|
448
|
+
return listing;
|
|
449
|
+
names = readdirSync(root);
|
|
450
|
+
}
|
|
451
|
+
catch {
|
|
452
|
+
return listing;
|
|
453
|
+
}
|
|
454
|
+
for (const name of names.sort()) {
|
|
455
|
+
if (name === "leases" || name.includes(".tmp-"))
|
|
456
|
+
continue;
|
|
457
|
+
if (name.startsWith("mitigation-health")) {
|
|
458
|
+
if (name === DIAGNOSTIC_MITIGATION_HEALTH_FILE) {
|
|
459
|
+
listing.mitigation_health = readMitigationHealth(join(root, name));
|
|
460
|
+
}
|
|
461
|
+
continue;
|
|
462
|
+
}
|
|
463
|
+
if (!name.endsWith(".json"))
|
|
464
|
+
continue;
|
|
465
|
+
listing.file_count += 1;
|
|
466
|
+
const summary = readSummaryFile(join(root, name));
|
|
467
|
+
if (summary)
|
|
468
|
+
listing.summaries.push(summary);
|
|
469
|
+
else
|
|
470
|
+
listing.unreadable_count += 1;
|
|
471
|
+
}
|
|
472
|
+
return listing;
|
|
473
|
+
}
|
|
474
|
+
/**
|
|
475
|
+
* Sum summarized-only occurrences inside a lookback window, from hour
|
|
476
|
+
* buckets. Hour-granular and conservative: a bucket is counted only when its
|
|
477
|
+
* whole hour lies inside `[sinceMs, nowMs]`, so a boundary bucket is excluded
|
|
478
|
+
* (up to 59 minutes undercounted) rather than fully included (up to 59
|
|
479
|
+
* minutes overcounted), and a future-dated bucket from clock skew never
|
|
480
|
+
* inflates a window.
|
|
481
|
+
*/
|
|
482
|
+
export function countSummarizedSinceV3(summaries, sinceMs, filter, nowMs = Date.now()) {
|
|
483
|
+
let count = 0;
|
|
484
|
+
for (const summary of summaries) {
|
|
485
|
+
if (filter && !filter(summary))
|
|
486
|
+
continue;
|
|
487
|
+
for (const [hour, value] of Object.entries(summary.recent_hours)) {
|
|
488
|
+
const hourStartMs = Date.parse(`${hour}:00:00.000Z`);
|
|
489
|
+
if (Number.isFinite(hourStartMs) &&
|
|
490
|
+
hourStartMs >= sinceMs &&
|
|
491
|
+
hourStartMs <= nowMs &&
|
|
492
|
+
Number.isSafeInteger(value) &&
|
|
493
|
+
value > 0) {
|
|
494
|
+
count += value;
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
return count;
|
|
499
|
+
}
|
|
@@ -320,7 +320,7 @@ function turnRitualObservation(adapter, evidence) {
|
|
|
320
320
|
function inputContextMeasurement(payload, phase) {
|
|
321
321
|
const metadata = plainRecord(payload.raw.compact_metadata);
|
|
322
322
|
const usedKeys = phase === "before"
|
|
323
|
-
? ["pre_tokens", "pre_compact_tokens", "used_tokens"]
|
|
323
|
+
? ["pre_tokens", "pre_compact_tokens", "used_tokens", "context_tokens"]
|
|
324
324
|
: ["post_tokens", "post_compact_tokens", "used_tokens"];
|
|
325
325
|
const limitKeys = [
|
|
326
326
|
"context_window_size",
|
|
@@ -65,6 +65,13 @@ export declare function removeIntakeRecordV3(path: string): void;
|
|
|
65
65
|
* are reduced to byte counts and digests so the diagnostics spool never holds
|
|
66
66
|
* prompt, tool input, or tool output bodies (invariant: delivered evidence is
|
|
67
67
|
* never silently destroyed, and never re-exposed either).
|
|
68
|
+
*
|
|
69
|
+
* Identical emissions are bounded per (category, reason, instance) key and
|
|
70
|
+
* UTC day: past the loose-exemplar limit the emission is coalesced into the
|
|
71
|
+
* key's summary file. Returns the path of the durable record either way (the
|
|
72
|
+
* loose file when admitted, the summary file when coalesced); `undefined`
|
|
73
|
+
* means nothing durable was written. The gate is fail-open, so a mitigation
|
|
74
|
+
* failure still produces the loose file.
|
|
68
75
|
*/
|
|
69
76
|
export declare function writeProducerDiagnosticV3(coordRoot: string, category: string, record: Record<string, unknown>): string | undefined;
|
|
70
77
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/producers/intake.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"intake.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/producers/intake.ts"],"names":[],"mappings":"AAeA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,qBAAqB,CAAC;AACnD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;AAErE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AAMtD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAC;AAC9C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,gBAAgB,CAAC;AAE3D;;;;;;;;;;;GAWG;AAEH,QAAA,MAAM,aAAa,EAAG,wBAAiC,CAAC;AACxD,QAAA,MAAM,cAAc,EAAG,CAAU,CAAC;AA4ClC,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,OAAO,aAAa,CAAC;IAC7B,cAAc,EAAE,OAAO,cAAc,CAAC;IACtC,IAAI,EAAE,gBAAgB,CAAC;IACvB,MAAM,EAAE,YAAY,CAAC;IACrB,OAAO,EAAE,aAAa,CAAC;IACvB,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,QAAQ,MAAM,EAAE,CAAC;IAC9B,WAAW,EAAE,OAAO,MAAM,EAAE,CAAC;IAC7B,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAC;IAC5B,QAAQ,EAAE,OAAO,GAAG,SAAS,GAAG,OAAO,GAAG,SAAS,CAAC;IACpD,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,gBAAgB,CAAC,EAAE,OAAO,CAAC;IAC3B,WAAW,CAAC,EAAE,oBAAoB,CAAC;IACnC,eAAe,CAAC,EAAE;QAChB,aAAa,EAAE,OAAO,MAAM,EAAE,CAAC;QAC/B,oBAAoB,EAAE,OAAO,MAAM,EAAE,CAAC;QACtC,aAAa,EAAE,OAAO,MAAM,EAAE,CAAC;QAC/B,kBAAkB,EAAE,OAAO,MAAM,EAAE,CAAC;KACrC,CAAC;CACH;AAED,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;IACjB,YAAY,EAAE,OAAO,MAAM,EAAE,CAAC;IAC9B,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,MAAM,EAAE,kBAAkB,GAAG,SAAS,CAAC;CACxC;AAUD,wBAAgB,oBAAoB,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,OAAO,MAAM,EAAE,GAC3B,MAAM,CAER;AA+BD,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,WAAW,EAAE,OAAO,MAAM,EAAE,EAC5B,MAAM,EAAE,kBAAkB,GACzB,MAAM,CAOR;AAED,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAsB7E;AAED,wBAAgB,uBAAuB,CAAC,SAAS,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAc9E;AAED,wBAAgB,oBAAoB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAGvD;AAkED;;;;;;;;;;;;GAYG;AACH,wBAAgB,yBAAyB,CACvC,SAAS,EAAE,MAAM,EACjB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC9B,MAAM,GAAG,SAAS,CA8BpB"}
|
|
@@ -3,6 +3,7 @@ import { chmodSync, closeSync, existsSync, fsyncSync, lstatSync, mkdirSync, open
|
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
4
|
import { fsyncParentDirectory } from "../../../workflow/durable-record.js";
|
|
5
5
|
import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../writer.js";
|
|
6
|
+
import { gateProducerDiagnosticV3, } from "./diagnostic-summaries.js";
|
|
6
7
|
/**
|
|
7
8
|
* Durable intake spool for hook signals, plus the producer diagnostics spool.
|
|
8
9
|
*
|
|
@@ -54,6 +55,10 @@ const DIAGNOSTIC_METADATA_KEYS = new Set([
|
|
|
54
55
|
"sequence",
|
|
55
56
|
"expected",
|
|
56
57
|
"actual",
|
|
58
|
+
"thread_id_present",
|
|
59
|
+
"wslenv_present",
|
|
60
|
+
"wslenv_names",
|
|
61
|
+
"identity_recovery_source",
|
|
57
62
|
]);
|
|
58
63
|
function intakeRoot(coordRoot) {
|
|
59
64
|
return join(resolve(coordRoot), EVENT_V3_LEDGER_RELATIVE_ROOT, "intake", "hook");
|
|
@@ -212,17 +217,35 @@ function validTurnRitual(value) {
|
|
|
212
217
|
* are reduced to byte counts and digests so the diagnostics spool never holds
|
|
213
218
|
* prompt, tool input, or tool output bodies (invariant: delivered evidence is
|
|
214
219
|
* never silently destroyed, and never re-exposed either).
|
|
220
|
+
*
|
|
221
|
+
* Identical emissions are bounded per (category, reason, instance) key and
|
|
222
|
+
* UTC day: past the loose-exemplar limit the emission is coalesced into the
|
|
223
|
+
* key's summary file. Returns the path of the durable record either way (the
|
|
224
|
+
* loose file when admitted, the summary file when coalesced); `undefined`
|
|
225
|
+
* means nothing durable was written. The gate is fail-open, so a mitigation
|
|
226
|
+
* failure still produces the loose file.
|
|
215
227
|
*/
|
|
216
228
|
export function writeProducerDiagnosticV3(coordRoot, category, record) {
|
|
217
229
|
try {
|
|
218
230
|
const safeCategory = category.replace(/[^a-z0-9_-]/gi, "_").slice(0, 64);
|
|
231
|
+
const redacted = redactDiagnosticRecord(record);
|
|
232
|
+
const { content_fingerprint: fingerprint, ...metadata } = redacted;
|
|
233
|
+
const decision = gateProducerDiagnosticV3(coordRoot, {
|
|
234
|
+
category: safeCategory,
|
|
235
|
+
reason: typeof record.reason === "string" ? record.reason : undefined,
|
|
236
|
+
instanceId: typeof record.instance_id === "string" ? record.instance_id : undefined,
|
|
237
|
+
fingerprint: fingerprint,
|
|
238
|
+
metadata: metadata,
|
|
239
|
+
});
|
|
240
|
+
if (!decision.admit)
|
|
241
|
+
return decision.summary_path;
|
|
219
242
|
const root = diagnosticsRoot(coordRoot);
|
|
220
243
|
ensureOwnerOnlyDirectory(root);
|
|
221
|
-
const path = join(root, `${safeCategory}-${intakeOrderKey()}.json`);
|
|
244
|
+
const path = join(root, `${safeCategory}-${intakeOrderKey()}${decision.loose_name_suffix}.json`);
|
|
222
245
|
const contents = `${JSON.stringify({
|
|
223
246
|
recorded_at: new Date().toISOString(),
|
|
224
247
|
category: safeCategory,
|
|
225
|
-
...
|
|
248
|
+
...redacted,
|
|
226
249
|
})}\n`;
|
|
227
250
|
writeOwnerOnlyFileDurably(path, contents);
|
|
228
251
|
return path;
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
export interface HookProducerStateSummaryV3 {
|
|
2
|
+
generation_id: `gen_${string}`;
|
|
3
|
+
open_span_count: number;
|
|
4
|
+
turn_open: boolean;
|
|
5
|
+
}
|
|
6
|
+
/** Read the narrow producer-state facts needed by passive coordination views. */
|
|
7
|
+
export declare function listHookProducerStateSummariesV3(coordRoot: string): HookProducerStateSummaryV3[];
|
|
8
|
+
//# sourceMappingURL=producer-state-observer.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"producer-state-observer.d.ts","sourceRoot":"","sources":["../../../../../src/core/events/v3/producers/producer-state-observer.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,OAAO,MAAM,EAAE,CAAC;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,SAAS,EAAE,OAAO,CAAC;CACpB;AAED,iFAAiF;AACjF,wBAAgB,gCAAgC,CAAC,SAAS,EAAE,MAAM,GAAG,0BAA0B,EAAE,CAuChG"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { existsSync, lstatSync, readdirSync, readFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { readEventV3ControlState } from "../control.js";
|
|
4
|
+
import { EVENT_V3_LEDGER_RELATIVE_ROOT } from "../reader.js";
|
|
5
|
+
/** Read the narrow producer-state facts needed by passive coordination views. */
|
|
6
|
+
export function listHookProducerStateSummariesV3(coordRoot) {
|
|
7
|
+
const control = readEventV3ControlState(coordRoot);
|
|
8
|
+
if (control.state !== "candidate" && control.state !== "active")
|
|
9
|
+
return [];
|
|
10
|
+
const producerRoot = join(resolve(coordRoot), EVENT_V3_LEDGER_RELATIVE_ROOT, "private-producers");
|
|
11
|
+
if (!existsSync(producerRoot))
|
|
12
|
+
return [];
|
|
13
|
+
const summaries = [];
|
|
14
|
+
for (const adapter of ["claude-code", "codex", "cursor"]) {
|
|
15
|
+
const directory = join(producerRoot, adapter);
|
|
16
|
+
if (!existsSync(directory))
|
|
17
|
+
continue;
|
|
18
|
+
const directoryMetadata = lstatSync(directory);
|
|
19
|
+
if (!directoryMetadata.isDirectory() || directoryMetadata.isSymbolicLink()) {
|
|
20
|
+
throw new Error("V3 producer state directory is unsafe");
|
|
21
|
+
}
|
|
22
|
+
for (const name of readdirSync(directory).filter((entry) => /^hid_[a-f0-9]{64}\.json$/.test(entry))) {
|
|
23
|
+
const file = join(directory, name);
|
|
24
|
+
const metadata = lstatSync(file);
|
|
25
|
+
if (!metadata.isFile() || metadata.isSymbolicLink())
|
|
26
|
+
continue;
|
|
27
|
+
const value = JSON.parse(readFileSync(file, "utf8"));
|
|
28
|
+
if (value.format !== "harnery-v3-hook-producer" ||
|
|
29
|
+
value.format_version !== 3 ||
|
|
30
|
+
value.adapter !== adapter ||
|
|
31
|
+
value.terminal === true ||
|
|
32
|
+
typeof value.generation_id !== "string" ||
|
|
33
|
+
!/^gen_[a-zA-Z0-9._-]+$/.test(value.generation_id) ||
|
|
34
|
+
!Array.isArray(value.spans)) {
|
|
35
|
+
continue;
|
|
36
|
+
}
|
|
37
|
+
summaries.push({
|
|
38
|
+
generation_id: value.generation_id,
|
|
39
|
+
open_span_count: value.spans.length,
|
|
40
|
+
turn_open: typeof value.current_turn_id === "string",
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
return summaries.sort((left, right) => left.generation_id.localeCompare(right.generation_id));
|
|
45
|
+
}
|