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
|
@@ -23,7 +23,13 @@ import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
|
|
|
23
23
|
import { acquireNoClobberLease } from "../../workflow/workspaces/leases.ts";
|
|
24
24
|
import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
|
|
25
25
|
import type { EventV3 } from "./contract.ts";
|
|
26
|
+
import { genesisIdFromManifestV3, liveGenesisIdV3 } from "./control.ts";
|
|
27
|
+
import { advanceControlWitnessV3, readAdvanceableControlWitnessV3 } from "./control-witness.ts";
|
|
26
28
|
import { EVENT_V3_SCHEMA_DIGEST } from "./generated.ts";
|
|
29
|
+
import {
|
|
30
|
+
type EventV3AppendValidationCheckpointV3,
|
|
31
|
+
readEventV3AppendValidationCheckpointV3,
|
|
32
|
+
} from "./reader.ts";
|
|
27
33
|
import { assertEventV3 } from "./validate.ts";
|
|
28
34
|
|
|
29
35
|
const MAX_LINE_BYTES = 16 * 1024;
|
|
@@ -34,7 +40,7 @@ export const EVENT_V3_LEDGER_RELATIVE_ROOT = ".harnery/ledgers/v3" as const;
|
|
|
34
40
|
export type EventV3DurabilityState = "committed" | "ready";
|
|
35
41
|
|
|
36
42
|
export interface WriteEventV3Result {
|
|
37
|
-
state: EventV3DurabilityState;
|
|
43
|
+
state: EventV3DurabilityState | "epoch_replaced";
|
|
38
44
|
event_id: string;
|
|
39
45
|
row_digest: `sha256:${string}`;
|
|
40
46
|
ready_path?: string;
|
|
@@ -50,6 +56,16 @@ export interface WriteEventV3Options {
|
|
|
50
56
|
* the option exists for matched harness-cost experiments.
|
|
51
57
|
*/
|
|
52
58
|
deferDrain?: boolean;
|
|
59
|
+
/**
|
|
60
|
+
* Epoch fence: the genesis id of the epoch this event was produced for.
|
|
61
|
+
* An event carries per-epoch authority (producer boot sequences start at 1
|
|
62
|
+
* and every causal link must resolve inside its own epoch), so committing
|
|
63
|
+
* it into a replaced epoch would poison the new authority. When set, the
|
|
64
|
+
* write refuses with `epoch_replaced` if the live genesis no longer
|
|
65
|
+
* matches, the spooled ready row is tagged with the id, and the drain
|
|
66
|
+
* quarantines any tagged row whose epoch has been replaced underneath it.
|
|
67
|
+
*/
|
|
68
|
+
expectedGenesisId?: `gex_${string}`;
|
|
53
69
|
now?: () => number;
|
|
54
70
|
onStep?: (step: EventV3WriteStep, eventId?: string) => void;
|
|
55
71
|
}
|
|
@@ -86,7 +102,11 @@ export function writeEventV3(
|
|
|
86
102
|
}
|
|
87
103
|
const paths = ensureEventV3Layout(coordRoot);
|
|
88
104
|
const rowDigest = sha256V3(row);
|
|
89
|
-
|
|
105
|
+
if (options.expectedGenesisId && liveGenesisIdV3(coordRoot) !== options.expectedGenesisId) {
|
|
106
|
+
return { state: "epoch_replaced", event_id: event.event_id, row_digest: rowDigest };
|
|
107
|
+
}
|
|
108
|
+
const epochTag = options.expectedGenesisId ? `-${options.expectedGenesisId}` : "";
|
|
109
|
+
const readyName = `${String(event.producer.sequence).padStart(16, "0")}-${event.event_id}-${rowDigest.slice(7)}${epochTag}.ready`;
|
|
90
110
|
const readyPath = join(paths.spool, readyName);
|
|
91
111
|
writeReadyRecord(paths.spool, readyPath, row, event.event_id, options.onStep);
|
|
92
112
|
|
|
@@ -110,14 +130,18 @@ export function writeEventV3(
|
|
|
110
130
|
diagnostic_code: "wal_drain_failed",
|
|
111
131
|
};
|
|
112
132
|
}
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
133
|
+
if (existsSync(readyPath)) {
|
|
134
|
+
return {
|
|
135
|
+
state: "ready",
|
|
136
|
+
event_id: event.event_id,
|
|
137
|
+
row_digest: rowDigest,
|
|
138
|
+
ready_path: readyPath,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
if (existsSync(`${readyPath.slice(0, -".ready".length)}.epoch-replaced`)) {
|
|
142
|
+
return { state: "epoch_replaced", event_id: event.event_id, row_digest: rowDigest };
|
|
143
|
+
}
|
|
144
|
+
return { state: "committed", event_id: event.event_id, row_digest: rowDigest };
|
|
121
145
|
}
|
|
122
146
|
|
|
123
147
|
/** Drain every durable ready record under the fenced append lease. */
|
|
@@ -158,16 +182,24 @@ export function drainReadyEventsUnderLeaseV3(
|
|
|
158
182
|
paths: ReturnType<typeof eventV3Paths>,
|
|
159
183
|
options: WriteEventV3Options = {},
|
|
160
184
|
): number {
|
|
185
|
+
let priorWitness = readAdvanceableControlWitnessV3(paths.coordRoot);
|
|
161
186
|
if (repairUnterminatedActiveFrame(paths.active)) {
|
|
162
187
|
options.onStep?.("active_tail_repaired");
|
|
188
|
+
// The repair can remove IDs that the old witness considered committed.
|
|
189
|
+
// Never use that stale checkpoint to release a dependent ready row.
|
|
190
|
+
priorWitness = undefined;
|
|
163
191
|
}
|
|
164
192
|
requeueCommittedReceipts(paths.spool);
|
|
165
193
|
const readyNames = readdirSync(paths.spool)
|
|
166
194
|
.filter((name) => name.endsWith(".ready"))
|
|
167
195
|
.sort();
|
|
168
196
|
if (readyNames.length === 0) return 0;
|
|
197
|
+
const drainableNames = quarantineReplacedEpochRows(paths, readyNames);
|
|
198
|
+
if (drainableNames.length === 0) return 0;
|
|
199
|
+
const checkpoint =
|
|
200
|
+
priorWitness?.checkpoint ?? readEventV3AppendValidationCheckpointV3(paths.coordRoot);
|
|
169
201
|
const readyRows = causallyOrderedReadyRows(
|
|
170
|
-
|
|
202
|
+
drainableNames.map((readyName) => {
|
|
171
203
|
const readyPath = join(paths.spool, readyName);
|
|
172
204
|
const row = readAndValidateReadyRow(readyPath);
|
|
173
205
|
return {
|
|
@@ -177,7 +209,9 @@ export function drainReadyEventsUnderLeaseV3(
|
|
|
177
209
|
event: JSON.parse(row) as EventV3,
|
|
178
210
|
};
|
|
179
211
|
}),
|
|
212
|
+
checkpoint?.genesis_id ? checkpoint : undefined,
|
|
180
213
|
);
|
|
214
|
+
if (readyRows.length === 0) return 0;
|
|
181
215
|
const activeFd = openSync(paths.active, "a", 0o600);
|
|
182
216
|
let committed = 0;
|
|
183
217
|
try {
|
|
@@ -199,6 +233,13 @@ export function drainReadyEventsUnderLeaseV3(
|
|
|
199
233
|
} finally {
|
|
200
234
|
closeSync(activeFd);
|
|
201
235
|
}
|
|
236
|
+
if (committed > 0 && priorWitness) {
|
|
237
|
+
advanceControlWitnessV3(
|
|
238
|
+
paths.coordRoot,
|
|
239
|
+
priorWitness,
|
|
240
|
+
genesisIdFromManifestV3(join(paths.root, "genesis.json")),
|
|
241
|
+
);
|
|
242
|
+
}
|
|
202
243
|
return committed;
|
|
203
244
|
}
|
|
204
245
|
|
|
@@ -210,11 +251,51 @@ interface ReadyEventRowV3 {
|
|
|
210
251
|
}
|
|
211
252
|
|
|
212
253
|
/**
|
|
213
|
-
* Keep the spool's deterministic filename order except where
|
|
214
|
-
*
|
|
215
|
-
*
|
|
254
|
+
* Keep the spool's deterministic filename order except where an event depends
|
|
255
|
+
* on an uncommitted cause or attestation declaration. The authenticated
|
|
256
|
+
* checkpoint proves what the active authority already contains; rows whose
|
|
257
|
+
* prerequisite has not reached either the authority or this ready batch stay
|
|
258
|
+
* in the WAL. This covers the cross-process window where a dependent row is
|
|
259
|
+
* published before the row that mints its attestation.
|
|
216
260
|
*/
|
|
217
|
-
function causallyOrderedReadyRows(
|
|
261
|
+
function causallyOrderedReadyRows(
|
|
262
|
+
rows: ReadyEventRowV3[],
|
|
263
|
+
checkpoint?: EventV3AppendValidationCheckpointV3,
|
|
264
|
+
): ReadyEventRowV3[] {
|
|
265
|
+
// Bare writer fixtures and pre-genesis bootstrap rows have no semantic
|
|
266
|
+
// authority to consult. Preserve the original within-batch causal ordering;
|
|
267
|
+
// once a genesis exists, the validated checkpoint becomes the writer fence.
|
|
268
|
+
if (!checkpoint) return causallyOrderedReadyRowsWithinBatch(rows);
|
|
269
|
+
|
|
270
|
+
const pending = new Map(rows.map((row) => [row.event.event_id, row]));
|
|
271
|
+
const ordered: ReadyEventRowV3[] = [];
|
|
272
|
+
const committedEventIds = new Set(checkpoint.seen_event_ids);
|
|
273
|
+
const committedAttestationIds = new Set(checkpoint.attestation_ids);
|
|
274
|
+
while (pending.size > 0) {
|
|
275
|
+
const next = rows.find(({ event }) => {
|
|
276
|
+
const causes = (event.links as { caused_by: string[] }).caused_by;
|
|
277
|
+
return (
|
|
278
|
+
pending.has(event.event_id) &&
|
|
279
|
+
causes.every((eventId) => committedEventIds.has(eventId)) &&
|
|
280
|
+
attestationPrerequisitesV3(event).every((attestationId) =>
|
|
281
|
+
committedAttestationIds.has(attestationId),
|
|
282
|
+
)
|
|
283
|
+
);
|
|
284
|
+
});
|
|
285
|
+
if (!next) break;
|
|
286
|
+
pending.delete(next.event.event_id);
|
|
287
|
+
ordered.push(next);
|
|
288
|
+
committedEventIds.add(next.event.event_id);
|
|
289
|
+
const minted = mintedAttestationV3(next.event);
|
|
290
|
+
if (minted) committedAttestationIds.add(minted);
|
|
291
|
+
}
|
|
292
|
+
if (pending.size > 0 && dependenciesResolveInsidePendingV3(pending, committedEventIds)) {
|
|
293
|
+
throw new Error("ready V3 events contain a causal dependency cycle");
|
|
294
|
+
}
|
|
295
|
+
return ordered;
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
function causallyOrderedReadyRowsWithinBatch(rows: ReadyEventRowV3[]): ReadyEventRowV3[] {
|
|
218
299
|
const pending = new Map(rows.map((row) => [row.event.event_id, row]));
|
|
219
300
|
const ordered: ReadyEventRowV3[] = [];
|
|
220
301
|
while (pending.size > 0) {
|
|
@@ -229,6 +310,42 @@ function causallyOrderedReadyRows(rows: ReadyEventRowV3[]): ReadyEventRowV3[] {
|
|
|
229
310
|
return ordered;
|
|
230
311
|
}
|
|
231
312
|
|
|
313
|
+
function mintedAttestationV3(event: EventV3): string | undefined {
|
|
314
|
+
return event.event_type === "session.started" ||
|
|
315
|
+
event.event_type === "session.attestation_changed"
|
|
316
|
+
? event.attestation_id
|
|
317
|
+
: undefined;
|
|
318
|
+
}
|
|
319
|
+
|
|
320
|
+
function attestationPrerequisitesV3(event: EventV3): string[] {
|
|
321
|
+
if (event.event_type === "session.started") return [];
|
|
322
|
+
if (event.event_type === "session.attestation_changed") {
|
|
323
|
+
return [event.payload.prior_attestation_id];
|
|
324
|
+
}
|
|
325
|
+
return event.attestation_id ? [event.attestation_id] : [];
|
|
326
|
+
}
|
|
327
|
+
|
|
328
|
+
function dependenciesResolveInsidePendingV3(
|
|
329
|
+
pending: Map<string, ReadyEventRowV3>,
|
|
330
|
+
committedEventIds: Set<string>,
|
|
331
|
+
): boolean {
|
|
332
|
+
const pendingAttestations = new Set(
|
|
333
|
+
[...pending.values()]
|
|
334
|
+
.map(({ event }) => mintedAttestationV3(event))
|
|
335
|
+
.filter((value): value is string => value !== undefined),
|
|
336
|
+
);
|
|
337
|
+
return [...pending.values()].every(({ event }) => {
|
|
338
|
+
const causes = (event.links as { caused_by: string[] }).caused_by;
|
|
339
|
+
const causesStayInside = causes.every(
|
|
340
|
+
(eventId) => committedEventIds.has(eventId) || pending.has(eventId),
|
|
341
|
+
);
|
|
342
|
+
const attestationsStayInside = attestationPrerequisitesV3(event).every((attestationId) =>
|
|
343
|
+
pendingAttestations.has(attestationId),
|
|
344
|
+
);
|
|
345
|
+
return causesStayInside && attestationsStayInside;
|
|
346
|
+
});
|
|
347
|
+
}
|
|
348
|
+
|
|
232
349
|
/**
|
|
233
350
|
* A `.committed` receipt is created only after the active row is flushed. If
|
|
234
351
|
* the process dies before unlinking it, replaying the exact canonical row is
|
|
@@ -255,8 +372,10 @@ function requeueCommittedReceipts(spool: string): void {
|
|
|
255
372
|
}
|
|
256
373
|
|
|
257
374
|
export function eventV3Paths(coordRoot: string) {
|
|
258
|
-
const
|
|
375
|
+
const resolvedCoordRoot = resolve(coordRoot);
|
|
376
|
+
const root = join(resolvedCoordRoot, EVENT_V3_LEDGER_RELATIVE_ROOT);
|
|
259
377
|
return {
|
|
378
|
+
coordRoot: resolvedCoordRoot,
|
|
260
379
|
root,
|
|
261
380
|
active: join(root, "active.ndjson"),
|
|
262
381
|
catalog: join(root, "catalog.json"),
|
|
@@ -378,6 +497,39 @@ function eventIdFromReadyName(name: string): string | undefined {
|
|
|
378
497
|
return match?.[1];
|
|
379
498
|
}
|
|
380
499
|
|
|
500
|
+
function epochTagFromReadyName(name: string): `gex_${string}` | undefined {
|
|
501
|
+
const match = name.match(/-(gex_[0-9a-f-]{36})\.ready$/);
|
|
502
|
+
return match ? (match[1] as `gex_${string}`) : undefined;
|
|
503
|
+
}
|
|
504
|
+
|
|
505
|
+
/**
|
|
506
|
+
* Move every ready row tagged with a replaced epoch out of the drainable
|
|
507
|
+
* spool. A tagged row was produced for exactly one epoch; committing it into
|
|
508
|
+
* a successor would break that epoch's boot-sequence and causal-link
|
|
509
|
+
* authority, so the row is preserved beside the spool as `.epoch-replaced`
|
|
510
|
+
* evidence instead of ever reaching the active file.
|
|
511
|
+
*/
|
|
512
|
+
function quarantineReplacedEpochRows(
|
|
513
|
+
paths: ReturnType<typeof eventV3Paths>,
|
|
514
|
+
readyNames: string[],
|
|
515
|
+
): string[] {
|
|
516
|
+
if (!readyNames.some((name) => epochTagFromReadyName(name) !== undefined)) return readyNames;
|
|
517
|
+
const liveGenesisId = genesisIdFromManifestV3(join(paths.root, "genesis.json"));
|
|
518
|
+
const drainable: string[] = [];
|
|
519
|
+
for (const name of readyNames) {
|
|
520
|
+
const tag = epochTagFromReadyName(name);
|
|
521
|
+
if (tag === undefined || tag === liveGenesisId) {
|
|
522
|
+
drainable.push(name);
|
|
523
|
+
continue;
|
|
524
|
+
}
|
|
525
|
+
const readyPath = join(paths.spool, name);
|
|
526
|
+
const quarantinePath = `${readyPath.slice(0, -".ready".length)}.epoch-replaced`;
|
|
527
|
+
renameSync(readyPath, quarantinePath);
|
|
528
|
+
fsyncParentDirectory(quarantinePath);
|
|
529
|
+
}
|
|
530
|
+
return drainable;
|
|
531
|
+
}
|
|
532
|
+
|
|
381
533
|
function readFileTail(fd: number, buffer: Buffer, position: number): number {
|
|
382
534
|
let read = 0;
|
|
383
535
|
while (read < buffer.length) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
2
|
import { existsSync, readdirSync, readFileSync, statSync } from "node:fs";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
|
+
import { readSegmentedJsonlFileSync } from "../storage/durable-history.ts";
|
|
4
5
|
import { readWorkItem } from "../work/read.ts";
|
|
5
6
|
import {
|
|
6
7
|
GOVERNOR_PLAN_SCHEMA_VERSION,
|
|
@@ -29,8 +30,6 @@ const PLAN_KEY = /^[a-z][a-z0-9-]{0,31}$/;
|
|
|
29
30
|
const TEMPLATE_ID = /^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$/;
|
|
30
31
|
const MAX_PLANS = 100;
|
|
31
32
|
const MAX_RECORD_BYTES = 256 * 1024;
|
|
32
|
-
const MAX_EVENTS_BYTES = 512 * 1024;
|
|
33
|
-
const MAX_EVENTS = 100;
|
|
34
33
|
const EVENT_TYPES = new Set<GovernorPlanEventType>([
|
|
35
34
|
"plan.awaiting_approval",
|
|
36
35
|
"plan.resumed",
|
|
@@ -232,22 +231,10 @@ function deriveStatus(
|
|
|
232
231
|
}
|
|
233
232
|
|
|
234
233
|
function readEvents(path: string, planId: string): GovernorPlanEvent[] {
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
if (body && !body.endsWith("\n")) throw new Error(`governor plan ${planId} has a partial event`);
|
|
240
|
-
const lines = body.split("\n").filter(Boolean);
|
|
241
|
-
if (lines.length > MAX_EVENTS) throw new Error(`governor plan exceeds ${MAX_EVENTS} events`);
|
|
242
|
-
return lines.map((line, index) => {
|
|
243
|
-
let event: GovernorPlanEvent;
|
|
244
|
-
try {
|
|
245
|
-
event = JSON.parse(line) as GovernorPlanEvent;
|
|
246
|
-
} catch (error) {
|
|
247
|
-
throw new Error(
|
|
248
|
-
`cannot parse governor plan ${planId} event ${index + 1}: ${(error as Error).message}`,
|
|
249
|
-
);
|
|
250
|
-
}
|
|
234
|
+
return readSegmentedJsonlFileSync<GovernorPlanEvent>(path, {
|
|
235
|
+
max_record_bytes: MAX_RECORD_BYTES,
|
|
236
|
+
max_records: 1_000_000,
|
|
237
|
+
}).map((event, index) => {
|
|
251
238
|
validateEvent(event, planId, index + 1);
|
|
252
239
|
return event;
|
|
253
240
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { createHash, randomBytes, randomUUID } from "node:crypto";
|
|
2
2
|
import {
|
|
3
|
-
appendFileSync,
|
|
4
3
|
chmodSync,
|
|
5
4
|
existsSync,
|
|
6
5
|
linkSync,
|
|
@@ -11,6 +10,7 @@ import {
|
|
|
11
10
|
writeFileSync,
|
|
12
11
|
} from "node:fs";
|
|
13
12
|
import { dirname, join, resolve } from "node:path";
|
|
13
|
+
import { appendSegmentedJsonlFile } from "../storage/durable-history.ts";
|
|
14
14
|
import { createWorkItem, readWorkItem } from "../work/index.ts";
|
|
15
15
|
import {
|
|
16
16
|
digestResult,
|
|
@@ -1573,13 +1573,10 @@ function appendPlanEvent(
|
|
|
1573
1573
|
actor: bounded(input.actor, "plan actor", 200),
|
|
1574
1574
|
reason: bounded(input.reason, "plan reason", MAX_REASON),
|
|
1575
1575
|
};
|
|
1576
|
-
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
1580
|
-
}
|
|
1581
|
-
appendFileSync(path, line, { encoding: "utf8", mode: 0o600 });
|
|
1582
|
-
chmodSync(path, 0o600);
|
|
1576
|
+
appendSegmentedJsonlFile(path, event, {
|
|
1577
|
+
max_record_bytes: MAX_RECORD_BYTES,
|
|
1578
|
+
max_segment_bytes: MAX_EVENTS_BYTES,
|
|
1579
|
+
});
|
|
1583
1580
|
}
|
|
1584
1581
|
|
|
1585
1582
|
function appendPlanEventIfMissing(
|
|
@@ -1,6 +1,12 @@
|
|
|
1
|
-
import { existsSync, readFileSync, statSync } from "node:fs";
|
|
1
|
+
import { closeSync, existsSync, openSync, readFileSync, readSync, statSync } from "node:fs";
|
|
2
2
|
import { hostname } from "node:os";
|
|
3
3
|
import { join, resolve } from "node:path";
|
|
4
|
+
import { gunzipSync } from "node:zlib";
|
|
5
|
+
import { coordEnv } from "../../lib/env.ts";
|
|
6
|
+
import { createStorageCatalog } from "../storage/catalog.ts";
|
|
7
|
+
import type { HarneryLogRecordV1 } from "../storage/jsonl.ts";
|
|
8
|
+
import { parseLogRecord } from "../storage/jsonl.ts";
|
|
9
|
+
import { familyLogDirectory, readSegmentManifest } from "../storage/segments.ts";
|
|
4
10
|
import type {
|
|
5
11
|
GovernorServiceConfig,
|
|
6
12
|
GovernorServiceRuntime,
|
|
@@ -9,6 +15,7 @@ import type {
|
|
|
9
15
|
} from "./service.ts";
|
|
10
16
|
|
|
11
17
|
const MAX_FILE_BYTES = 512 * 1024;
|
|
18
|
+
const MAX_LOG_RECORDS = 10_000;
|
|
12
19
|
const MAX_GOALS = 100;
|
|
13
20
|
const FOREIGN_STATUS_STALE_MS = 30_000;
|
|
14
21
|
|
|
@@ -81,7 +88,318 @@ export function readGovernorServiceStatus(coordRootRaw: string): GovernorService
|
|
|
81
88
|
}
|
|
82
89
|
|
|
83
90
|
export function governorServiceLogPath(coordRoot: string): string {
|
|
84
|
-
|
|
91
|
+
const root = resolve(coordRoot);
|
|
92
|
+
const legacy = join(serviceDir(root), "service.log");
|
|
93
|
+
if (coordEnv("SHARED_LOGS") === "0") return legacy;
|
|
94
|
+
try {
|
|
95
|
+
const family = createStorageCatalog({ coord_root: root }).require("governor-service-log");
|
|
96
|
+
const directory = familyLogDirectory(family);
|
|
97
|
+
readSegmentManifest(directory, family);
|
|
98
|
+
const active = join(directory, "active.jsonl");
|
|
99
|
+
return existsSync(active) || !existsSync(legacy) ? active : legacy;
|
|
100
|
+
} catch {
|
|
101
|
+
return legacy;
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface GovernorServiceLogReadOptions {
|
|
106
|
+
max_bytes?: number;
|
|
107
|
+
max_records?: number;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
export interface GovernorServiceLogReadResult {
|
|
111
|
+
lines: readonly string[];
|
|
112
|
+
bytes_read: number;
|
|
113
|
+
records_examined: number;
|
|
114
|
+
truncated: boolean;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
interface GovernorLogEntry {
|
|
118
|
+
identity: string;
|
|
119
|
+
line: string;
|
|
120
|
+
timestamp?: string;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
interface GovernorLogRead {
|
|
124
|
+
entries: GovernorLogEntry[];
|
|
125
|
+
bytes: number;
|
|
126
|
+
records: number;
|
|
127
|
+
truncated: boolean;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
/** Read shared generations plus untouched legacy history under one aggregate budget. */
|
|
131
|
+
export function readGovernorServiceLogs(
|
|
132
|
+
coordRootRaw: string,
|
|
133
|
+
options: GovernorServiceLogReadOptions = {},
|
|
134
|
+
): GovernorServiceLogReadResult {
|
|
135
|
+
const coordRoot = resolve(coordRootRaw);
|
|
136
|
+
const maxBytes = options.max_bytes ?? MAX_FILE_BYTES;
|
|
137
|
+
const maxRecords = options.max_records ?? MAX_LOG_RECORDS;
|
|
138
|
+
if (!Number.isSafeInteger(maxBytes) || maxBytes <= 0) {
|
|
139
|
+
throw new Error("governor service log byte budget must be a positive integer");
|
|
140
|
+
}
|
|
141
|
+
if (!Number.isSafeInteger(maxRecords) || maxRecords <= 0) {
|
|
142
|
+
throw new Error("governor service log record budget must be a positive integer");
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
let bytes = 0;
|
|
146
|
+
let records = 0;
|
|
147
|
+
let truncated = false;
|
|
148
|
+
const reads: GovernorLogEntry[][] = [];
|
|
149
|
+
if (coordEnv("SHARED_LOGS") !== "0") {
|
|
150
|
+
try {
|
|
151
|
+
const shared = readSharedGovernorLogs(coordRoot, maxBytes, maxRecords);
|
|
152
|
+
reads.push(shared.entries);
|
|
153
|
+
bytes += shared.bytes;
|
|
154
|
+
records += shared.records;
|
|
155
|
+
truncated ||= shared.truncated;
|
|
156
|
+
} catch {
|
|
157
|
+
// A corrupt or racing shared generation fails closed into bounded legacy history.
|
|
158
|
+
truncated = true;
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
for (const legacy of [
|
|
162
|
+
{ path: join(serviceDir(coordRoot), "events.jsonl"), structured: true },
|
|
163
|
+
{ path: join(serviceDir(coordRoot), "service.log"), structured: false },
|
|
164
|
+
]) {
|
|
165
|
+
const remainingBytes = maxBytes - bytes;
|
|
166
|
+
const remainingRecords = maxRecords - records;
|
|
167
|
+
if (remainingBytes <= 0 || remainingRecords <= 0) {
|
|
168
|
+
if (existsSync(legacy.path)) truncated = true;
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const read = readLegacyGovernorLog(
|
|
172
|
+
legacy.path,
|
|
173
|
+
legacy.structured,
|
|
174
|
+
remainingBytes,
|
|
175
|
+
remainingRecords,
|
|
176
|
+
);
|
|
177
|
+
reads.push(read.entries);
|
|
178
|
+
bytes += read.bytes;
|
|
179
|
+
records += read.records;
|
|
180
|
+
truncated ||= read.truncated;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
const merged = new Map<string, GovernorLogEntry>();
|
|
184
|
+
for (const entries of reads) {
|
|
185
|
+
for (const entry of entries) if (!merged.has(entry.identity)) merged.set(entry.identity, entry);
|
|
186
|
+
}
|
|
187
|
+
const lines = [...merged.values()]
|
|
188
|
+
.sort(
|
|
189
|
+
(left, right) =>
|
|
190
|
+
(left.timestamp ?? "").localeCompare(right.timestamp ?? "") ||
|
|
191
|
+
left.identity.localeCompare(right.identity),
|
|
192
|
+
)
|
|
193
|
+
.map(({ line }) => line);
|
|
194
|
+
return { lines, bytes_read: bytes, records_examined: records, truncated };
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
function readSharedGovernorLogs(
|
|
198
|
+
coordRoot: string,
|
|
199
|
+
maxBytes: number,
|
|
200
|
+
maxRecords: number,
|
|
201
|
+
): GovernorLogRead {
|
|
202
|
+
const family = createStorageCatalog({ coord_root: coordRoot }).require("governor-service-log");
|
|
203
|
+
const directory = familyLogDirectory(family);
|
|
204
|
+
let totalBytes = 0;
|
|
205
|
+
let totalRecords = 0;
|
|
206
|
+
let raced = false;
|
|
207
|
+
for (let attempt = 0; attempt < 2; attempt += 1) {
|
|
208
|
+
const remainingBytes = maxBytes - totalBytes;
|
|
209
|
+
const remainingRecords = maxRecords - totalRecords;
|
|
210
|
+
if (remainingBytes <= 0 || remainingRecords <= 0) break;
|
|
211
|
+
const manifest = readSegmentManifest(directory, family);
|
|
212
|
+
const generation = manifestGeneration(manifest);
|
|
213
|
+
const sources = [
|
|
214
|
+
...manifest.segments.map((segment) => ({ path: join(directory, segment.file), gzip: true })),
|
|
215
|
+
{ path: join(directory, "active.jsonl"), gzip: false },
|
|
216
|
+
];
|
|
217
|
+
const read = readSharedSources(sources, remainingBytes, remainingRecords);
|
|
218
|
+
totalBytes += read.bytes;
|
|
219
|
+
totalRecords += read.records;
|
|
220
|
+
const after = readSegmentManifest(directory, family);
|
|
221
|
+
if (manifestGeneration(after) === generation) {
|
|
222
|
+
return {
|
|
223
|
+
entries: read.entries,
|
|
224
|
+
bytes: totalBytes,
|
|
225
|
+
records: totalRecords,
|
|
226
|
+
truncated: raced || read.truncated,
|
|
227
|
+
};
|
|
228
|
+
}
|
|
229
|
+
raced = true;
|
|
230
|
+
}
|
|
231
|
+
return { entries: [], bytes: totalBytes, records: totalRecords, truncated: raced };
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
function readSharedSources(
|
|
235
|
+
sources: readonly { path: string; gzip: boolean }[],
|
|
236
|
+
maxBytes: number,
|
|
237
|
+
maxRecords: number,
|
|
238
|
+
): GovernorLogRead {
|
|
239
|
+
const entries: GovernorLogEntry[] = [];
|
|
240
|
+
let bytes = 0;
|
|
241
|
+
let records = 0;
|
|
242
|
+
let truncated = false;
|
|
243
|
+
for (const source of sources) {
|
|
244
|
+
if (!existsSync(source.path)) continue;
|
|
245
|
+
if (bytes >= maxBytes || records >= maxRecords) {
|
|
246
|
+
truncated = true;
|
|
247
|
+
break;
|
|
248
|
+
}
|
|
249
|
+
const body = readBoundedSource(source.path, source.gzip, maxBytes - bytes, false);
|
|
250
|
+
bytes += body.bytes;
|
|
251
|
+
truncated ||= body.truncated;
|
|
252
|
+
for (const line of completeLines(body.body, false)) {
|
|
253
|
+
if (records >= maxRecords) {
|
|
254
|
+
truncated = true;
|
|
255
|
+
break;
|
|
256
|
+
}
|
|
257
|
+
records += 1;
|
|
258
|
+
try {
|
|
259
|
+
entries.push(normalizeSharedGovernorRecord(parseLogRecord(line)));
|
|
260
|
+
} catch {
|
|
261
|
+
// Malformed rows count against the source budget but cannot poison the readable tail.
|
|
262
|
+
}
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return { entries, bytes, records, truncated };
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
function readLegacyGovernorLog(
|
|
269
|
+
path: string,
|
|
270
|
+
structured: boolean,
|
|
271
|
+
maxBytes: number,
|
|
272
|
+
maxRecords: number,
|
|
273
|
+
): GovernorLogRead {
|
|
274
|
+
if (!existsSync(path)) return { entries: [], bytes: 0, records: 0, truncated: false };
|
|
275
|
+
const source = readBoundedSource(path, false, maxBytes, true);
|
|
276
|
+
const entries: GovernorLogEntry[] = [];
|
|
277
|
+
let records = 0;
|
|
278
|
+
let truncated = source.truncated;
|
|
279
|
+
for (const line of completeLines(source.body, source.truncated)) {
|
|
280
|
+
if (records >= maxRecords) {
|
|
281
|
+
truncated = true;
|
|
282
|
+
break;
|
|
283
|
+
}
|
|
284
|
+
records += 1;
|
|
285
|
+
if (!structured) {
|
|
286
|
+
entries.push({ identity: `text:${line}`, line });
|
|
287
|
+
continue;
|
|
288
|
+
}
|
|
289
|
+
try {
|
|
290
|
+
const parsed = JSON.parse(line) as unknown;
|
|
291
|
+
if (isRecord(parsed)) entries.push(normalizeLegacyGovernorRecord(parsed));
|
|
292
|
+
} catch {
|
|
293
|
+
// Malformed legacy lines stay excluded while consuming their source budget.
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return { entries, bytes: source.bytes, records, truncated };
|
|
297
|
+
}
|
|
298
|
+
|
|
299
|
+
function readBoundedSource(
|
|
300
|
+
path: string,
|
|
301
|
+
gzip: boolean,
|
|
302
|
+
maxBytes: number,
|
|
303
|
+
tail: boolean,
|
|
304
|
+
): { body: string; bytes: number; truncated: boolean } {
|
|
305
|
+
if (maxBytes <= 0) return { body: "", bytes: 0, truncated: true };
|
|
306
|
+
const size = statSync(path).size;
|
|
307
|
+
if (size <= 0) return { body: "", bytes: 0, truncated: false };
|
|
308
|
+
if (gzip) {
|
|
309
|
+
if (size > maxBytes) return { body: "", bytes: maxBytes, truncated: true };
|
|
310
|
+
try {
|
|
311
|
+
const output = gunzipSync(readFileSync(path), { maxOutputLength: maxBytes });
|
|
312
|
+
return {
|
|
313
|
+
body: output.toString("utf8"),
|
|
314
|
+
bytes: Math.max(size, output.byteLength),
|
|
315
|
+
truncated: false,
|
|
316
|
+
};
|
|
317
|
+
} catch {
|
|
318
|
+
return { body: "", bytes: maxBytes, truncated: true };
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
const length = Math.min(size, maxBytes);
|
|
322
|
+
const buffer = Buffer.allocUnsafe(length);
|
|
323
|
+
const descriptor = openSync(path, "r");
|
|
324
|
+
try {
|
|
325
|
+
const bytes = readSync(descriptor, buffer, 0, length, tail ? size - length : 0);
|
|
326
|
+
return {
|
|
327
|
+
body: buffer.subarray(0, bytes).toString("utf8"),
|
|
328
|
+
bytes,
|
|
329
|
+
truncated: size > bytes,
|
|
330
|
+
};
|
|
331
|
+
} finally {
|
|
332
|
+
closeSync(descriptor);
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
function completeLines(body: string, truncatedPrefix: boolean): string[] {
|
|
337
|
+
const start = truncatedPrefix ? body.indexOf("\n") + 1 : 0;
|
|
338
|
+
const end = body.lastIndexOf("\n");
|
|
339
|
+
if (start < 0 || end < start) return [];
|
|
340
|
+
return body.slice(start, end).split("\n").filter(Boolean);
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
function normalizeSharedGovernorRecord(record: HarneryLogRecordV1): GovernorLogEntry {
|
|
344
|
+
if (record.family_id !== "governor-service-log") throw new Error("wrong governor log family");
|
|
345
|
+
const payload = {
|
|
346
|
+
...Object.fromEntries(
|
|
347
|
+
Object.entries(record.fields).map(([key, value]) => [key, parseJsonField(value)]),
|
|
348
|
+
),
|
|
349
|
+
ts: record.emitted_at,
|
|
350
|
+
event: record.event,
|
|
351
|
+
};
|
|
352
|
+
return normalizedGovernorEntry(payload);
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
function normalizeLegacyGovernorRecord(record: Record<string, unknown>): GovernorLogEntry {
|
|
356
|
+
const { schema_version: _schemaVersion, ...payload } = record;
|
|
357
|
+
return normalizedGovernorEntry(payload);
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
function normalizedGovernorEntry(payload: Record<string, unknown>): GovernorLogEntry {
|
|
361
|
+
const identity = stableJson(payload);
|
|
362
|
+
return {
|
|
363
|
+
identity,
|
|
364
|
+
line: JSON.stringify(payload),
|
|
365
|
+
...(typeof payload.ts === "string" ? { timestamp: payload.ts } : {}),
|
|
366
|
+
};
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
function parseJsonField(value: unknown): unknown {
|
|
370
|
+
if (typeof value !== "string" || (!value.startsWith("[") && !value.startsWith("{"))) {
|
|
371
|
+
return value;
|
|
372
|
+
}
|
|
373
|
+
try {
|
|
374
|
+
return JSON.parse(value) as unknown;
|
|
375
|
+
} catch {
|
|
376
|
+
return value;
|
|
377
|
+
}
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
function stableJson(value: unknown): string {
|
|
381
|
+
if (Array.isArray(value)) return `[${value.map(stableJson).join(",")}]`;
|
|
382
|
+
if (value && typeof value === "object") {
|
|
383
|
+
return `{${Object.entries(value as Record<string, unknown>)
|
|
384
|
+
.sort(([left], [right]) => left.localeCompare(right))
|
|
385
|
+
.map(([key, child]) => `${JSON.stringify(key)}:${stableJson(child)}`)
|
|
386
|
+
.join(",")}}`;
|
|
387
|
+
}
|
|
388
|
+
return JSON.stringify(value) ?? "null";
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
function manifestGeneration(manifest: {
|
|
392
|
+
next_sequence: number;
|
|
393
|
+
segments: readonly { file: string; sha256: string }[];
|
|
394
|
+
}): string {
|
|
395
|
+
return JSON.stringify([
|
|
396
|
+
manifest.next_sequence,
|
|
397
|
+
manifest.segments.map((segment) => [segment.file, segment.sha256]),
|
|
398
|
+
]);
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
function isRecord(value: unknown): value is Record<string, unknown> {
|
|
402
|
+
return typeof value === "object" && value !== null && !Array.isArray(value);
|
|
85
403
|
}
|
|
86
404
|
|
|
87
405
|
function readStatusRecord(coordRoot: string): GovernorServiceStatusRecord | undefined {
|