harnery 0.34.1 → 0.36.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/commander.d.ts +30 -5
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +124 -94
- package/dist/commands/agents.d.ts +37 -6
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +466 -371
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +10 -10
- package/dist/commands/browse-session.d.ts.map +1 -1
- package/dist/commands/browse-session.js +12 -0
- package/dist/commands/browse.d.ts +1 -1
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +31 -6
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +2 -2
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/events.d.ts.map +1 -1
- package/dist/commands/events.js +18 -1
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +22 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +113 -0
- package/dist/commands/governor.js +14 -12
- package/dist/commands/inbox.d.ts +5 -0
- package/dist/commands/inbox.d.ts.map +1 -0
- package/dist/commands/inbox.js +57 -0
- package/dist/commands/init.d.ts +4 -5
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +63 -13
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +347 -1
- package/dist/commands/logs.d.ts +4 -0
- package/dist/commands/logs.d.ts.map +1 -0
- package/dist/commands/logs.js +169 -0
- package/dist/commands/messages.d.ts +5 -0
- package/dist/commands/messages.d.ts.map +1 -0
- package/dist/commands/messages.js +45 -0
- package/dist/commands/outline.d.ts +1 -1
- package/dist/commands/outline.d.ts.map +1 -1
- package/dist/commands/outline.js +2 -2
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +2 -2
- package/dist/commands/read.d.ts +1 -1
- package/dist/commands/read.d.ts.map +1 -1
- package/dist/commands/read.js +2 -2
- package/dist/commands/semantic.d.ts +4 -0
- package/dist/commands/semantic.d.ts.map +1 -0
- package/dist/commands/semantic.js +199 -0
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/tunnel.d.ts +5 -1
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +44 -31
- package/dist/commands/web.d.ts +3 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +84 -7
- package/dist/commands/work.js +3 -3
- package/dist/commands/workflow.js +13 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -0
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +12 -0
- package/dist/core/agents/claim-path.d.ts +11 -0
- package/dist/core/agents/claim-path.d.ts.map +1 -0
- package/dist/core/agents/claim-path.js +22 -0
- package/dist/core/agents/cli.js +209 -39
- package/dist/core/agents/coord-client.d.ts +29 -3
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +88 -9
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +245 -13
- package/dist/core/agents/live-lifecycle-v3.js +9 -4
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +8 -3
- package/dist/core/agents/render/prompt-context.d.ts +9 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +36 -17
- package/dist/core/agents/rules/stop-hook.d.ts +2 -0
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +115 -22
- package/dist/core/agents/rules/verdict.d.ts +1 -0
- package/dist/core/agents/rules/verdict.d.ts.map +1 -1
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +4 -0
- package/dist/core/agents/session-finalization-state-v3.js +1 -1
- package/dist/core/agents/session-finalizer-v3.js +5 -1
- package/dist/core/agents/session-name-display.d.ts +1 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +8 -1
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-reader.d.ts +46 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -0
- package/dist/core/agents/state/heartbeat-reader.js +25 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts +9 -48
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +34 -34
- package/dist/core/agents/state/live-coordination-view.d.ts +6 -8
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +16 -67
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/agents/state/names.d.ts +9 -1
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +190 -182
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -5
- package/dist/core/artifacts/constants.d.ts +5 -0
- package/dist/core/artifacts/constants.d.ts.map +1 -0
- package/dist/core/artifacts/constants.js +4 -0
- package/dist/core/artifacts/index.d.ts +24 -3
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +96 -8
- package/dist/core/config.d.ts +62 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -4
- package/dist/core/conversations/archive.d.ts +49 -0
- package/dist/core/conversations/archive.d.ts.map +1 -0
- package/dist/core/conversations/archive.js +136 -0
- package/dist/core/conversations/catalog.d.ts +10 -0
- package/dist/core/conversations/catalog.d.ts.map +1 -0
- package/dist/core/conversations/catalog.js +72 -0
- package/dist/core/conversations/context-pack.d.ts +6 -0
- package/dist/core/conversations/context-pack.d.ts.map +1 -0
- package/dist/core/conversations/context-pack.js +60 -0
- package/dist/core/conversations/contract.d.ts +155 -0
- package/dist/core/conversations/contract.d.ts.map +1 -0
- package/dist/core/conversations/contract.js +1 -0
- package/dist/core/conversations/evaluation.d.ts +16 -0
- package/dist/core/conversations/evaluation.d.ts.map +1 -0
- package/dist/core/conversations/evaluation.js +9 -0
- package/dist/core/conversations/index.d.ts +10 -0
- package/dist/core/conversations/index.d.ts.map +1 -0
- package/dist/core/conversations/index.js +9 -0
- package/dist/core/conversations/lifecycle.d.ts +28 -0
- package/dist/core/conversations/lifecycle.d.ts.map +1 -0
- package/dist/core/conversations/lifecycle.js +29 -0
- package/dist/core/conversations/normalize.d.ts +14 -0
- package/dist/core/conversations/normalize.d.ts.map +1 -0
- package/dist/core/conversations/normalize.js +82 -0
- package/dist/core/conversations/query.d.ts +8 -0
- package/dist/core/conversations/query.d.ts.map +1 -0
- package/dist/core/conversations/query.js +280 -0
- package/dist/core/conversations/search-index.d.ts +9 -0
- package/dist/core/conversations/search-index.d.ts.map +1 -0
- package/dist/core/conversations/search-index.js +29 -0
- package/dist/core/events/legacy-storage/canary.d.ts +18 -0
- package/dist/core/events/legacy-storage/canary.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/canary.js +150 -0
- package/dist/core/events/legacy-storage/fence.d.ts +15 -0
- package/dist/core/events/legacy-storage/fence.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/fence.js +115 -0
- package/dist/core/events/legacy-storage/index.d.ts +6 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +5 -0
- package/dist/core/events/legacy-storage/inventory.d.ts +10 -0
- package/dist/core/events/legacy-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/inventory.js +40 -0
- package/dist/core/events/legacy-storage/manifest.d.ts +23 -0
- package/dist/core/events/legacy-storage/manifest.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/manifest.js +108 -0
- package/dist/core/events/legacy-storage/reader.d.ts +15 -0
- package/dist/core/events/legacy-storage/reader.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/reader.js +154 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +851 -16
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +50 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.d.ts +11 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +26 -3
- package/dist/core/events/v3/control-witness.d.ts +44 -0
- package/dist/core/events/v3/control-witness.d.ts.map +1 -0
- package/dist/core/events/v3/control-witness.js +233 -0
- package/dist/core/events/v3/control-writer.d.ts +4 -0
- package/dist/core/events/v3/control-writer.d.ts.map +1 -0
- package/dist/core/events/v3/control-writer.js +16 -0
- package/dist/core/events/v3/control.d.ts +8 -2
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +46 -18
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts +42 -0
- package/dist/core/events/v3/coordination-transaction-recovery.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-transaction-recovery.js +342 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +16 -1
- package/dist/core/events/v3/generated.d.ts +1 -1
- package/dist/core/events/v3/generated.js +1 -1
- package/dist/core/events/v3/index.d.ts +8 -5
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +7 -4
- package/dist/core/events/v3/latency.d.ts +31 -1
- package/dist/core/events/v3/latency.d.ts.map +1 -1
- package/dist/core/events/v3/latency.js +127 -3
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +42 -20
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +153 -41
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +10 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +90 -13
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +17 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +83 -2
- package/dist/core/events/v3/producers/intake.d.ts +13 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +36 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts +8 -0
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -0
- package/dist/core/events/v3/producers/producer-state-observer.js +45 -0
- package/dist/core/events/v3/producers/recorder.d.ts +117 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +992 -27
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +52 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +54 -0
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +21 -6
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +4 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +13 -5
- package/dist/core/hooks/adapter/parse.d.ts +3 -0
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +14 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +142 -0
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -0
- package/dist/core/hooks/adapter/runtime-telemetry.js +869 -0
- package/dist/core/hooks/cli.js +318 -61
- package/dist/core/hooks/effects/image-capture.d.ts +1 -1
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +4 -2
- package/dist/core/hooks/remediation-cap.d.ts +39 -0
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -0
- package/dist/core/hooks/remediation-cap.js +63 -0
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +33 -9
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +33 -10
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/semantic/adapters.d.ts +37 -0
- package/dist/core/semantic/adapters.d.ts.map +1 -0
- package/dist/core/semantic/adapters.js +360 -0
- package/dist/core/semantic/contract.d.ts +1072 -0
- package/dist/core/semantic/contract.d.ts.map +1 -0
- package/dist/core/semantic/contract.js +331 -0
- package/dist/core/semantic/evidence.d.ts +11 -0
- package/dist/core/semantic/evidence.d.ts.map +1 -0
- package/dist/core/semantic/evidence.js +262 -0
- package/dist/core/semantic/index.d.ts +14 -0
- package/dist/core/semantic/index.d.ts.map +1 -0
- package/dist/core/semantic/index.js +13 -0
- package/dist/core/semantic/once.d.ts +38 -0
- package/dist/core/semantic/once.d.ts.map +1 -0
- package/dist/core/semantic/once.js +364 -0
- package/dist/core/semantic/prompt.d.ts +12 -0
- package/dist/core/semantic/prompt.d.ts.map +1 -0
- package/dist/core/semantic/prompt.js +83 -0
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +27 -0
- package/dist/core/semantic/scheduler.d.ts.map +1 -0
- package/dist/core/semantic/scheduler.js +91 -0
- package/dist/core/semantic/service-status.d.ts +51 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -0
- package/dist/core/semantic/service-status.js +140 -0
- package/dist/core/semantic/service.d.ts +52 -0
- package/dist/core/semantic/service.d.ts.map +1 -0
- package/dist/core/semantic/service.js +559 -0
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +81 -0
- package/dist/core/semantic/storage.d.ts.map +1 -0
- package/dist/core/semantic/storage.js +180 -0
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +18 -0
- package/dist/core/semantic/validate.d.ts.map +1 -0
- package/dist/core/semantic/validate.js +207 -0
- package/dist/core/storage/buffer.d.ts +28 -0
- package/dist/core/storage/buffer.d.ts.map +1 -0
- package/dist/core/storage/buffer.js +101 -0
- package/dist/core/storage/builtins.d.ts +3 -0
- package/dist/core/storage/builtins.d.ts.map +1 -0
- package/dist/core/storage/builtins.js +683 -0
- package/dist/core/storage/catalog.d.ts +19 -0
- package/dist/core/storage/catalog.d.ts.map +1 -0
- package/dist/core/storage/catalog.js +365 -0
- package/dist/core/storage/config.d.ts +16 -0
- package/dist/core/storage/config.d.ts.map +1 -0
- package/dist/core/storage/config.js +311 -0
- package/dist/core/storage/contract.d.ts +275 -0
- package/dist/core/storage/contract.d.ts.map +1 -0
- package/dist/core/storage/contract.js +3 -0
- package/dist/core/storage/durable-history.d.ts +36 -0
- package/dist/core/storage/durable-history.d.ts.map +1 -0
- package/dist/core/storage/durable-history.js +606 -0
- package/dist/core/storage/health.d.ts +4 -0
- package/dist/core/storage/health.d.ts.map +1 -0
- package/dist/core/storage/health.js +65 -0
- package/dist/core/storage/index.d.ts +16 -0
- package/dist/core/storage/index.d.ts.map +1 -0
- package/dist/core/storage/index.js +15 -0
- package/dist/core/storage/inventory.d.ts +25 -0
- package/dist/core/storage/inventory.d.ts.map +1 -0
- package/dist/core/storage/inventory.js +666 -0
- package/dist/core/storage/jsonl.d.ts +52 -0
- package/dist/core/storage/jsonl.d.ts.map +1 -0
- package/dist/core/storage/jsonl.js +156 -0
- package/dist/core/storage/log-retention.d.ts +52 -0
- package/dist/core/storage/log-retention.d.ts.map +1 -0
- package/dist/core/storage/log-retention.js +419 -0
- package/dist/core/storage/logger.d.ts +82 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +411 -0
- package/dist/core/storage/maintenance-providers.d.ts +26 -0
- package/dist/core/storage/maintenance-providers.d.ts.map +1 -0
- package/dist/core/storage/maintenance-providers.js +141 -0
- package/dist/core/storage/maintenance.d.ts +125 -0
- package/dist/core/storage/maintenance.d.ts.map +1 -0
- package/dist/core/storage/maintenance.js +609 -0
- package/dist/core/storage/metrics.d.ts +60 -0
- package/dist/core/storage/metrics.d.ts.map +1 -0
- package/dist/core/storage/metrics.js +134 -0
- package/dist/core/storage/policy.d.ts +7 -0
- package/dist/core/storage/policy.d.ts.map +1 -0
- package/dist/core/storage/policy.js +110 -0
- package/dist/core/storage/process-log.d.ts +38 -0
- package/dist/core/storage/process-log.d.ts.map +1 -0
- package/dist/core/storage/process-log.js +165 -0
- package/dist/core/storage/query.d.ts +34 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +295 -0
- package/dist/core/storage/receipts.d.ts +23 -0
- package/dist/core/storage/receipts.d.ts.map +1 -0
- package/dist/core/storage/receipts.js +117 -0
- package/dist/core/storage/segments.d.ts +84 -0
- package/dist/core/storage/segments.d.ts.map +1 -0
- package/dist/core/storage/segments.js +542 -0
- package/dist/core/storage/sink-graph.d.ts +65 -0
- package/dist/core/storage/sink-graph.d.ts.map +1 -0
- package/dist/core/storage/sink-graph.js +213 -0
- package/dist/core/storage/storm-control.d.ts +23 -0
- package/dist/core/storage/storm-control.d.ts.map +1 -0
- package/dist/core/storage/storm-control.js +59 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -0
- package/dist/lazy-commands.d.ts +26 -0
- package/dist/lazy-commands.d.ts.map +1 -0
- package/dist/lazy-commands.js +210 -0
- package/dist/lib/browser/client.d.ts +11 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +13 -0
- package/dist/lib/browser/index.d.ts +1 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.d.ts +25 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -0
- package/dist/lib/browser/standalone-html.js +284 -0
- package/dist/lib/docs-lint.d.ts +2 -0
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +45 -80
- package/dist/lib/docs-metadata-audit.d.ts +3 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -1
- package/dist/lib/docs-metadata-audit.js +13 -23
- package/dist/lib/docs-metadata-sync.d.ts +1 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -1
- package/dist/lib/docs-metadata-sync.js +28 -10
- package/dist/lib/docs-repository-view.d.ts +22 -0
- package/dist/lib/docs-repository-view.d.ts.map +1 -0
- package/dist/lib/docs-repository-view.js +185 -0
- package/dist/lib/http/client.d.ts +11 -5
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +22 -4
- package/dist/lib/http/index.d.ts +1 -1
- package/dist/lib/http/index.d.ts.map +1 -1
- package/dist/lib/http/index.js +1 -1
- package/dist/lib/indexer-exclusions.d.ts +27 -0
- package/dist/lib/indexer-exclusions.d.ts.map +1 -0
- package/dist/lib/indexer-exclusions.js +176 -0
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +1 -0
- package/dist/lib/instructions/templates.d.ts +2 -0
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +149 -4
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +34 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +3073 -581
- package/src/commander.ts +462 -93
- package/src/commands/agents.ts +617 -355
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +31 -9
- package/src/commands/conversations.ts +279 -0
- package/src/commands/decision.ts +8 -2
- package/src/commands/deinit.ts +6 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/events.ts +21 -1
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +143 -0
- package/src/commands/governor.ts +13 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +421 -1
- package/src/commands/logs.ts +224 -0
- package/src/commands/messages.ts +61 -0
- package/src/commands/outline.ts +6 -2
- package/src/commands/presence.ts +7 -2
- package/src/commands/read.ts +6 -2
- package/src/commands/semantic.ts +244 -0
- package/src/commands/storage.ts +310 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +92 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +13 -13
- package/src/core/agents/canonical-emit.ts +15 -0
- package/src/core/agents/claim-path.ts +23 -0
- package/src/core/agents/cli.ts +259 -53
- package/src/core/agents/coord-client.ts +92 -8
- package/src/core/agents/live-authority-v3.ts +342 -14
- package/src/core/agents/live-lifecycle-v3.ts +14 -4
- package/src/core/agents/live-observation-v3.ts +13 -3
- package/src/core/agents/render/prompt-context.ts +40 -16
- package/src/core/agents/rules/stop-hook.ts +129 -25
- package/src/core/agents/rules/verdict.ts +1 -0
- package/src/core/agents/session-events.ts +4 -0
- package/src/core/agents/session-finalization-state-v3.ts +1 -1
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/session-name-display.ts +9 -1
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-reader.ts +69 -0
- package/src/core/agents/state/heartbeat-writer.ts +47 -84
- package/src/core/agents/state/live-coordination-view.ts +17 -81
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/agents/state/names.ts +190 -182
- package/src/core/agents/state/stale-sweep.ts +25 -5
- package/src/core/artifacts/constants.ts +4 -0
- package/src/core/artifacts/index.ts +113 -8
- package/src/core/config.ts +126 -5
- package/src/core/conversations/archive.ts +237 -0
- package/src/core/conversations/catalog.ts +79 -0
- package/src/core/conversations/context-pack.ts +72 -0
- package/src/core/conversations/contract.ts +178 -0
- package/src/core/conversations/evaluation.ts +30 -0
- package/src/core/conversations/index.ts +9 -0
- package/src/core/conversations/lifecycle.ts +63 -0
- package/src/core/conversations/normalize.ts +105 -0
- package/src/core/conversations/query.ts +318 -0
- package/src/core/conversations/search-index.ts +48 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +5 -0
- package/src/core/events/legacy-storage/inventory.ts +51 -0
- package/src/core/events/legacy-storage/manifest.ts +136 -0
- package/src/core/events/legacy-storage/reader.ts +178 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +56 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +37 -3
- package/src/core/events/v3/control-witness.ts +339 -0
- package/src/core/events/v3/control-writer.ts +16 -0
- package/src/core/events/v3/control.ts +54 -18
- package/src/core/events/v3/coordination-transaction-recovery.ts +477 -0
- package/src/core/events/v3/coordination-view.ts +17 -1
- package/src/core/events/v3/generated.ts +1 -1
- package/src/core/events/v3/index.ts +26 -2
- package/src/core/events/v3/latency.ts +213 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +182 -45
- package/src/core/events/v3/producers/command-recorder.ts +10 -1
- package/src/core/events/v3/producers/coordination-recorder.ts +112 -15
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +116 -2
- package/src/core/events/v3/producers/intake.ts +48 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +1403 -30
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +143 -0
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +66 -5
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +12 -5
- package/src/core/hooks/adapter/parse.ts +16 -0
- package/src/core/hooks/adapter/runtime-telemetry.ts +1200 -0
- package/src/core/hooks/cli.ts +342 -64
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/remediation-cap.ts +83 -0
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +55 -11
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/semantic/adapters.ts +452 -0
- package/src/core/semantic/contract.ts +430 -0
- package/src/core/semantic/evidence.ts +336 -0
- package/src/core/semantic/index.ts +201 -0
- package/src/core/semantic/once.ts +496 -0
- package/src/core/semantic/prompt.ts +96 -0
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +151 -0
- package/src/core/semantic/service-status.ts +212 -0
- package/src/core/semantic/service.ts +681 -0
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +300 -0
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +243 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +916 -0
- package/src/core/storage/catalog.ts +467 -0
- package/src/core/storage/config.ts +423 -0
- package/src/core/storage/contract.ts +342 -0
- package/src/core/storage/durable-history.ts +738 -0
- package/src/core/storage/health.ts +76 -0
- package/src/core/storage/index.ts +15 -0
- package/src/core/storage/inventory.ts +859 -0
- package/src/core/storage/jsonl.ts +213 -0
- package/src/core/storage/log-retention.ts +555 -0
- package/src/core/storage/logger.ts +546 -0
- package/src/core/storage/maintenance-providers.ts +200 -0
- package/src/core/storage/maintenance.ts +929 -0
- package/src/core/storage/metrics.ts +199 -0
- package/src/core/storage/policy.ts +141 -0
- package/src/core/storage/process-log.ts +203 -0
- package/src/core/storage/query.ts +360 -0
- package/src/core/storage/receipts.ts +162 -0
- package/src/core/storage/segments.ts +721 -0
- package/src/core/storage/sink-graph.ts +343 -0
- package/src/core/storage/storm-control.ts +91 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/browser/client.ts +21 -0
- package/src/lib/browser/index.ts +4 -0
- package/src/lib/browser/standalone-html.ts +312 -0
- package/src/lib/docs-lint.ts +58 -77
- package/src/lib/docs-metadata-audit.ts +26 -21
- package/src/lib/docs-metadata-sync.ts +32 -9
- package/src/lib/docs-repository-view.ts +220 -0
- package/src/lib/http/client.ts +44 -8
- package/src/lib/http/index.ts +6 -1
- package/src/lib/indexer-exclusions.ts +173 -0
- package/src/lib/instructions/apply.ts +1 -0
- package/src/lib/instructions/templates.ts +154 -4
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -3,11 +3,16 @@ import { join } from "node:path";
|
|
|
3
3
|
import { buildEventV3 } from "./builder.ts";
|
|
4
4
|
import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
|
|
5
5
|
import type { EventV3 } from "./contract.ts";
|
|
6
|
+
import { activeControlWitnessMatchesV3, publishActiveControlWitnessV3 } from "./control-witness.ts";
|
|
6
7
|
import { EVENT_V3_SCHEMA_DIGEST } from "./generated.ts";
|
|
7
8
|
import { activationIdV3, eventIdV3, genesisIdV3 } from "./ids.ts";
|
|
8
|
-
import {
|
|
9
|
+
import {
|
|
10
|
+
eventV3AuthorityStorageVersionV3,
|
|
11
|
+
type ReadLedgerV3Result,
|
|
12
|
+
readEventV3AppendValidationCheckpointV3,
|
|
13
|
+
readLedgerV3,
|
|
14
|
+
} from "./reader.ts";
|
|
9
15
|
import { validateEventV3 } from "./validate.ts";
|
|
10
|
-
import { writeEventV3 } from "./writer.ts";
|
|
11
16
|
|
|
12
17
|
export const EVENT_V3_GENESIS_MANIFEST = ".harnery/ledgers/v3/genesis.json" as const;
|
|
13
18
|
export const EVENT_V3_ACTIVATION_MANIFEST = ".harnery/ledgers/v3/activation.json" as const;
|
|
@@ -210,6 +215,26 @@ export function validateActivationManifestV3(
|
|
|
210
215
|
* Resolve the session/evidence gate from exact control-file and ledger-event pairs.
|
|
211
216
|
* This function never repairs or creates state. Any ambiguity keeps the gate closed.
|
|
212
217
|
*/
|
|
218
|
+
/**
|
|
219
|
+
* The live epoch's genesis id from the immutable manifest, or undefined when
|
|
220
|
+
* no valid genesis is published. This is the cheap epoch-identity read the
|
|
221
|
+
* writer fence uses: one small canonical file, never the event history.
|
|
222
|
+
*/
|
|
223
|
+
export function liveGenesisIdV3(coordRoot: string): `gex_${string}` | undefined {
|
|
224
|
+
return genesisIdFromManifestV3(join(coordRoot, EVENT_V3_GENESIS_MANIFEST));
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
/** Same read for a caller that already holds the manifest path (the writer's drain). */
|
|
228
|
+
export function genesisIdFromManifestV3(genesisPath: string): `gex_${string}` | undefined {
|
|
229
|
+
if (!existsSync(genesisPath)) return undefined;
|
|
230
|
+
const genesis = readGenesisManifest(genesisPath);
|
|
231
|
+
if (!genesis.ok) return undefined;
|
|
232
|
+
const genesisId = genesis.value.event.payload.genesis_id;
|
|
233
|
+
return typeof genesisId === "string" && genesisId.startsWith("gex_")
|
|
234
|
+
? (genesisId as `gex_${string}`)
|
|
235
|
+
: undefined;
|
|
236
|
+
}
|
|
237
|
+
|
|
213
238
|
export function readEventV3ControlState(coordRoot: string): EventV3ControlState {
|
|
214
239
|
const genesisPath = join(coordRoot, EVENT_V3_GENESIS_MANIFEST);
|
|
215
240
|
const activationPath = join(coordRoot, EVENT_V3_ACTIVATION_MANIFEST);
|
|
@@ -232,6 +257,25 @@ export function readEventV3ControlState(coordRoot: string): EventV3ControlState
|
|
|
232
257
|
if (!genesisResult.ok) return { state: "invalid", reason: genesisResult.reason };
|
|
233
258
|
const genesis = genesisResult.value;
|
|
234
259
|
const candidateDigest = candidateManifestDigestV3(genesis);
|
|
260
|
+
const activationForWitness = hasActivation
|
|
261
|
+
? readActivationManifest(activationPath, genesis, candidateDigest)
|
|
262
|
+
: undefined;
|
|
263
|
+
if (
|
|
264
|
+
activationForWitness?.ok &&
|
|
265
|
+
activeControlWitnessMatchesV3(coordRoot, {
|
|
266
|
+
genesis,
|
|
267
|
+
activation: activationForWitness.value,
|
|
268
|
+
candidate_manifest_digest: candidateDigest,
|
|
269
|
+
})
|
|
270
|
+
) {
|
|
271
|
+
return {
|
|
272
|
+
state: "active",
|
|
273
|
+
genesis,
|
|
274
|
+
activation: activationForWitness.value,
|
|
275
|
+
candidate_manifest_digest: candidateDigest,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
const storageBeforeValidation = eventV3AuthorityStorageVersionV3(coordRoot);
|
|
235
279
|
const ledger = readControlLedger(coordRoot);
|
|
236
280
|
if (!ledger.complete) {
|
|
237
281
|
return { state: "invalid", reason: "ledger_integrity_failure" };
|
|
@@ -253,7 +297,8 @@ export function readEventV3ControlState(coordRoot: string): EventV3ControlState
|
|
|
253
297
|
return { state: "candidate", genesis, candidate_manifest_digest: candidateDigest };
|
|
254
298
|
}
|
|
255
299
|
|
|
256
|
-
const activationResult =
|
|
300
|
+
const activationResult =
|
|
301
|
+
activationForWitness ?? readActivationManifest(activationPath, genesis, candidateDigest);
|
|
257
302
|
if (!activationResult.ok) return { state: "invalid", reason: activationResult.reason };
|
|
258
303
|
const activation = activationResult.value;
|
|
259
304
|
const activationPair = exactEventPair(
|
|
@@ -271,12 +316,17 @@ export function readEventV3ControlState(coordRoot: string): EventV3ControlState
|
|
|
271
316
|
activation,
|
|
272
317
|
};
|
|
273
318
|
}
|
|
274
|
-
|
|
319
|
+
const active: Extract<EventV3ControlState, { state: "active" }> = {
|
|
275
320
|
state: "active",
|
|
276
321
|
genesis,
|
|
277
322
|
activation,
|
|
278
323
|
candidate_manifest_digest: candidateDigest,
|
|
279
324
|
};
|
|
325
|
+
const checkpoint = readEventV3AppendValidationCheckpointV3(coordRoot);
|
|
326
|
+
if (checkpoint) {
|
|
327
|
+
publishActiveControlWitnessV3(coordRoot, active, storageBeforeValidation, checkpoint);
|
|
328
|
+
}
|
|
329
|
+
return active;
|
|
280
330
|
}
|
|
281
331
|
|
|
282
332
|
export function eventV3WriteGateOpen(coordRoot: string, mode: EventV3WriteMode): boolean {
|
|
@@ -284,20 +334,6 @@ export function eventV3WriteGateOpen(coordRoot: string, mode: EventV3WriteMode):
|
|
|
284
334
|
return mode === "candidate" ? control.state === "candidate" : control.state === "active";
|
|
285
335
|
}
|
|
286
336
|
|
|
287
|
-
/** Repair only a manifest-first crash by appending the exact pre-minted event. */
|
|
288
|
-
export function repairEventV3ControlPair(coordRoot: string): EventV3ControlState {
|
|
289
|
-
const control = readEventV3ControlState(coordRoot);
|
|
290
|
-
if (control.state !== "repairable") return control;
|
|
291
|
-
const event =
|
|
292
|
-
control.reason === "genesis_event_missing" ? control.genesis.event : control.activation?.event;
|
|
293
|
-
if (!event) return { state: "invalid", reason: "repair_event_unavailable" };
|
|
294
|
-
const result = writeEventV3(coordRoot, event);
|
|
295
|
-
if (result.state !== "committed") {
|
|
296
|
-
return { state: "invalid", reason: "control_event_repair_not_committed" };
|
|
297
|
-
}
|
|
298
|
-
return readEventV3ControlState(coordRoot);
|
|
299
|
-
}
|
|
300
|
-
|
|
301
337
|
export function candidateProfileDigestV3(profile: CandidateProfileV3): `sha256:${string}` {
|
|
302
338
|
return sha256V3(canonicalJsonV3(profile));
|
|
303
339
|
}
|
|
@@ -0,0 +1,477 @@
|
|
|
1
|
+
import { randomUUID } from "node:crypto";
|
|
2
|
+
import {
|
|
3
|
+
chmodSync,
|
|
4
|
+
closeSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
fsyncSync,
|
|
7
|
+
linkSync,
|
|
8
|
+
mkdirSync,
|
|
9
|
+
openSync,
|
|
10
|
+
readdirSync,
|
|
11
|
+
readFileSync,
|
|
12
|
+
unlinkSync,
|
|
13
|
+
writeFileSync,
|
|
14
|
+
} from "node:fs";
|
|
15
|
+
import { join } from "node:path";
|
|
16
|
+
import { fsyncParentDirectory } from "../../workflow/durable-record.ts";
|
|
17
|
+
import {
|
|
18
|
+
type AuthorityTransactionV3,
|
|
19
|
+
authorityRecoveryIntentPathV3,
|
|
20
|
+
readAuthorityTransactionV3,
|
|
21
|
+
} from "./authority-outbox.ts";
|
|
22
|
+
import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
|
|
23
|
+
import {
|
|
24
|
+
findPendingCoordinationTransactionV3,
|
|
25
|
+
withPendingCoordinationTransactionRecoveryV3,
|
|
26
|
+
} from "./producers/coordination-recorder.ts";
|
|
27
|
+
import { readLedgerV3 } from "./reader.ts";
|
|
28
|
+
import { ensureEventV3Layout } from "./writer.ts";
|
|
29
|
+
|
|
30
|
+
const SHA256_PATTERN = /^sha256:[a-f0-9]{64}$/;
|
|
31
|
+
const TX_PATTERN = /^txn_[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/;
|
|
32
|
+
const INSTANCE_PATTERN = /^inst_[a-zA-Z0-9._-]{1,128}$/;
|
|
33
|
+
const PRODUCER_STATE_PATTERN = /^hid_[a-f0-9]{64}\.json$/;
|
|
34
|
+
const APPROVAL_PATTERN = /^[a-zA-Z0-9][a-zA-Z0-9._:/-]{0,199}$/;
|
|
35
|
+
|
|
36
|
+
export type CoordinationTransactionRecoveryStep =
|
|
37
|
+
| "intent_published"
|
|
38
|
+
| "transaction_quarantined"
|
|
39
|
+
| "producer_pending_cleared"
|
|
40
|
+
| "outbox_ready_removed"
|
|
41
|
+
| "receipt_committed";
|
|
42
|
+
|
|
43
|
+
interface CoordinationTransactionQuarantineCommonV3 {
|
|
44
|
+
transaction_id: `txn_${string}`;
|
|
45
|
+
transaction_digest: `sha256:${string}`;
|
|
46
|
+
event_id: string;
|
|
47
|
+
event_row_digest: `sha256:${string}`;
|
|
48
|
+
actor_instance_id: string;
|
|
49
|
+
subject_instance_id: string;
|
|
50
|
+
mutation_kind: string;
|
|
51
|
+
expected_prior_state_digest: `sha256:${string}`;
|
|
52
|
+
desired_state_digest: `sha256:${string}`;
|
|
53
|
+
observed_current_state_digest: `sha256:${string}`;
|
|
54
|
+
approval_record_id: string;
|
|
55
|
+
producer_state_file: string;
|
|
56
|
+
reason: "current_state_conflict";
|
|
57
|
+
created_at: string;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface CoordinationTransactionQuarantineIntentV3
|
|
61
|
+
extends CoordinationTransactionQuarantineCommonV3 {
|
|
62
|
+
format: "harnery-v3-coordination-transaction-quarantine-intent";
|
|
63
|
+
format_version: 1;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export interface CoordinationTransactionQuarantineReceiptV3
|
|
67
|
+
extends CoordinationTransactionQuarantineCommonV3 {
|
|
68
|
+
format: "harnery-v3-coordination-transaction-quarantine-receipt";
|
|
69
|
+
format_version: 1;
|
|
70
|
+
completed_at: string;
|
|
71
|
+
quarantine_file: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
export interface QuarantineConflictingCoordinationTransactionV3Input {
|
|
75
|
+
transaction_id: string;
|
|
76
|
+
actor_instance_id: string;
|
|
77
|
+
observed_current_state_digest: `sha256:${string}`;
|
|
78
|
+
approval_record_id: string;
|
|
79
|
+
now?: () => Date;
|
|
80
|
+
onStep?: (step: CoordinationTransactionRecoveryStep) => void;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
/**
|
|
84
|
+
* Abandon one authority transaction only after proving that normal recovery is
|
|
85
|
+
* impossible and that its event never entered the ledger or ready spool.
|
|
86
|
+
*/
|
|
87
|
+
export function quarantineConflictingCoordinationTransactionV3(
|
|
88
|
+
coordRoot: string,
|
|
89
|
+
input: QuarantineConflictingCoordinationTransactionV3Input,
|
|
90
|
+
): CoordinationTransactionQuarantineReceiptV3 {
|
|
91
|
+
assertTransactionId(input.transaction_id);
|
|
92
|
+
assertInstanceId(input.actor_instance_id);
|
|
93
|
+
assertDigest(input.observed_current_state_digest, "observed current state digest");
|
|
94
|
+
assertApprovalRecordId(input.approval_record_id);
|
|
95
|
+
const paths = recoveryPaths(coordRoot, input.transaction_id);
|
|
96
|
+
ensureRecoveryLayout(paths);
|
|
97
|
+
|
|
98
|
+
if (existsSync(paths.receipt)) {
|
|
99
|
+
const receipt = readReceipt(paths.receipt);
|
|
100
|
+
assertRecoveryBinding(receipt, input);
|
|
101
|
+
removeIfExists(paths.intent);
|
|
102
|
+
return receipt;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
let intent: CoordinationTransactionQuarantineIntentV3;
|
|
106
|
+
let transaction: AuthorityTransactionV3;
|
|
107
|
+
let serializedTransaction: string;
|
|
108
|
+
const recoveryAlreadyStarted = existsSync(paths.intent);
|
|
109
|
+
if (recoveryAlreadyStarted) {
|
|
110
|
+
intent = readIntent(paths.intent);
|
|
111
|
+
assertRecoveryBinding(intent, input);
|
|
112
|
+
({ transaction, serialized: serializedTransaction } = readQuarantinedOrReadyTransaction(paths));
|
|
113
|
+
assertTransactionMatchesIntent(transaction, serializedTransaction, intent);
|
|
114
|
+
} else {
|
|
115
|
+
if (!existsSync(paths.ready)) {
|
|
116
|
+
throw new Error("authority transaction is not ready for recovery");
|
|
117
|
+
}
|
|
118
|
+
transaction = readAuthorityTransactionV3(paths.ready);
|
|
119
|
+
serializedTransaction = readFileSync(paths.ready, "utf8");
|
|
120
|
+
if (transaction.actor_instance_id !== input.actor_instance_id) {
|
|
121
|
+
throw new Error("authority transaction actor does not match the recovery target");
|
|
122
|
+
}
|
|
123
|
+
if (
|
|
124
|
+
input.observed_current_state_digest === transaction.expected_prior_state_digest ||
|
|
125
|
+
input.observed_current_state_digest === transaction.desired_state_digest
|
|
126
|
+
) {
|
|
127
|
+
throw new Error("authority transaction is still reconcilable and cannot be quarantined");
|
|
128
|
+
}
|
|
129
|
+
assertEventNeverCommitted(coordRoot, transaction.event_id, paths.committed);
|
|
130
|
+
const pending = findPendingCoordinationTransactionV3(coordRoot, transaction.transaction_id);
|
|
131
|
+
if (!pending) throw new Error("authority transaction has no matching pending producer state");
|
|
132
|
+
if (canonicalJsonV3(pending.transaction) !== canonicalJsonV3(transaction)) {
|
|
133
|
+
throw new Error("authority outbox and producer state transactions do not match");
|
|
134
|
+
}
|
|
135
|
+
const createdAt = (input.now ?? (() => new Date()))().toISOString();
|
|
136
|
+
intent = {
|
|
137
|
+
format: "harnery-v3-coordination-transaction-quarantine-intent",
|
|
138
|
+
format_version: 1,
|
|
139
|
+
...transactionFacts(transaction, serializedTransaction),
|
|
140
|
+
observed_current_state_digest: input.observed_current_state_digest,
|
|
141
|
+
approval_record_id: input.approval_record_id,
|
|
142
|
+
producer_state_file: pending.producer_state_file,
|
|
143
|
+
reason: "current_state_conflict",
|
|
144
|
+
created_at: createdAt,
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
return withPendingCoordinationTransactionRecoveryV3(
|
|
149
|
+
coordRoot,
|
|
150
|
+
intent.producer_state_file,
|
|
151
|
+
transaction,
|
|
152
|
+
recoveryAlreadyStarted,
|
|
153
|
+
({ clearPending }) => {
|
|
154
|
+
assertEventNeverCommitted(coordRoot, transaction.event_id, paths.committed);
|
|
155
|
+
publishCanonicalExclusive(paths.intent, intent);
|
|
156
|
+
input.onStep?.("intent_published");
|
|
157
|
+
|
|
158
|
+
publishSerializedExclusive(paths.quarantine, serializedTransaction);
|
|
159
|
+
input.onStep?.("transaction_quarantined");
|
|
160
|
+
|
|
161
|
+
clearPending();
|
|
162
|
+
input.onStep?.("producer_pending_cleared");
|
|
163
|
+
|
|
164
|
+
if (existsSync(paths.ready)) {
|
|
165
|
+
if (readFileSync(paths.ready, "utf8") !== serializedTransaction) {
|
|
166
|
+
throw new Error("authority ready transaction changed during recovery");
|
|
167
|
+
}
|
|
168
|
+
unlinkSync(paths.ready);
|
|
169
|
+
fsyncParentDirectory(paths.ready);
|
|
170
|
+
}
|
|
171
|
+
input.onStep?.("outbox_ready_removed");
|
|
172
|
+
|
|
173
|
+
const receipt: CoordinationTransactionQuarantineReceiptV3 = {
|
|
174
|
+
format: "harnery-v3-coordination-transaction-quarantine-receipt",
|
|
175
|
+
format_version: 1,
|
|
176
|
+
...commonIntentFields(intent),
|
|
177
|
+
completed_at: (input.now ?? (() => new Date()))().toISOString(),
|
|
178
|
+
quarantine_file: `quarantine/${input.transaction_id}.json`,
|
|
179
|
+
};
|
|
180
|
+
if (Date.parse(receipt.completed_at) < Date.parse(receipt.created_at)) {
|
|
181
|
+
throw new Error("authority transaction recovery clock moved backwards");
|
|
182
|
+
}
|
|
183
|
+
publishCanonicalExclusive(paths.receipt, receipt);
|
|
184
|
+
input.onStep?.("receipt_committed");
|
|
185
|
+
removeIfExists(paths.intent);
|
|
186
|
+
return receipt;
|
|
187
|
+
},
|
|
188
|
+
);
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
function transactionFacts(
|
|
192
|
+
transaction: AuthorityTransactionV3,
|
|
193
|
+
serialized: string,
|
|
194
|
+
): Pick<
|
|
195
|
+
CoordinationTransactionQuarantineCommonV3,
|
|
196
|
+
| "transaction_id"
|
|
197
|
+
| "transaction_digest"
|
|
198
|
+
| "event_id"
|
|
199
|
+
| "event_row_digest"
|
|
200
|
+
| "actor_instance_id"
|
|
201
|
+
| "subject_instance_id"
|
|
202
|
+
| "mutation_kind"
|
|
203
|
+
| "expected_prior_state_digest"
|
|
204
|
+
| "desired_state_digest"
|
|
205
|
+
> {
|
|
206
|
+
return {
|
|
207
|
+
transaction_id: transaction.transaction_id,
|
|
208
|
+
transaction_digest: sha256V3(serialized),
|
|
209
|
+
event_id: transaction.event_id,
|
|
210
|
+
event_row_digest: sha256V3(transaction.event_row),
|
|
211
|
+
actor_instance_id: transaction.actor_instance_id,
|
|
212
|
+
subject_instance_id: transaction.subject_instance_id,
|
|
213
|
+
mutation_kind: transaction.mutation.kind,
|
|
214
|
+
expected_prior_state_digest: transaction.expected_prior_state_digest,
|
|
215
|
+
desired_state_digest: transaction.desired_state_digest,
|
|
216
|
+
};
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
function commonIntentFields(
|
|
220
|
+
intent: CoordinationTransactionQuarantineIntentV3,
|
|
221
|
+
): CoordinationTransactionQuarantineCommonV3 {
|
|
222
|
+
const { format: _format, format_version: _formatVersion, ...common } = intent;
|
|
223
|
+
return common;
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
function assertEventNeverCommitted(
|
|
227
|
+
coordRoot: string,
|
|
228
|
+
eventId: string,
|
|
229
|
+
committedReceiptPath: string,
|
|
230
|
+
): void {
|
|
231
|
+
if (existsSync(committedReceiptPath)) {
|
|
232
|
+
throw new Error("authority transaction already has a committed receipt");
|
|
233
|
+
}
|
|
234
|
+
if (readLedgerV3(coordRoot).events.some(({ event }) => event.event_id === eventId)) {
|
|
235
|
+
throw new Error("authority transaction event is already present in the ledger");
|
|
236
|
+
}
|
|
237
|
+
const spool = ensureEventV3Layout(coordRoot).spool;
|
|
238
|
+
for (const name of readdirSync(spool)
|
|
239
|
+
.filter((entry) => entry.endsWith(".ready"))
|
|
240
|
+
.sort()) {
|
|
241
|
+
let event: unknown;
|
|
242
|
+
try {
|
|
243
|
+
event = JSON.parse(readFileSync(join(spool, name), "utf8"));
|
|
244
|
+
} catch {
|
|
245
|
+
throw new Error("V3 ready spool is unreadable during authority recovery");
|
|
246
|
+
}
|
|
247
|
+
if (
|
|
248
|
+
event &&
|
|
249
|
+
typeof event === "object" &&
|
|
250
|
+
!Array.isArray(event) &&
|
|
251
|
+
(event as Record<string, unknown>).event_id === eventId
|
|
252
|
+
) {
|
|
253
|
+
throw new Error("authority transaction event is already present in the ready spool");
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
function readQuarantinedOrReadyTransaction(paths: ReturnType<typeof recoveryPaths>): {
|
|
259
|
+
transaction: AuthorityTransactionV3;
|
|
260
|
+
serialized: string;
|
|
261
|
+
} {
|
|
262
|
+
const path = existsSync(paths.quarantine) ? paths.quarantine : paths.ready;
|
|
263
|
+
if (!existsSync(path)) throw new Error("authority transaction recovery lost its durable record");
|
|
264
|
+
return { transaction: readAuthorityTransactionV3(path), serialized: readFileSync(path, "utf8") };
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
function assertTransactionMatchesIntent(
|
|
268
|
+
transaction: AuthorityTransactionV3,
|
|
269
|
+
serialized: string,
|
|
270
|
+
intent: CoordinationTransactionQuarantineIntentV3,
|
|
271
|
+
): void {
|
|
272
|
+
const facts = transactionFacts(transaction, serialized);
|
|
273
|
+
for (const [key, value] of Object.entries(facts)) {
|
|
274
|
+
if (intent[key as keyof typeof intent] !== value) {
|
|
275
|
+
throw new Error("authority transaction recovery intent no longer matches its transaction");
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
function assertRecoveryBinding(
|
|
281
|
+
record: CoordinationTransactionQuarantineIntentV3 | CoordinationTransactionQuarantineReceiptV3,
|
|
282
|
+
input: QuarantineConflictingCoordinationTransactionV3Input,
|
|
283
|
+
): void {
|
|
284
|
+
if (
|
|
285
|
+
record.transaction_id !== input.transaction_id ||
|
|
286
|
+
record.actor_instance_id !== input.actor_instance_id ||
|
|
287
|
+
record.approval_record_id !== input.approval_record_id
|
|
288
|
+
) {
|
|
289
|
+
throw new Error("authority transaction recovery record does not match this request");
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function recoveryPaths(coordRoot: string, transactionId: string) {
|
|
294
|
+
const ledger = ensureEventV3Layout(coordRoot);
|
|
295
|
+
const root = join(ledger.root, "authority-recoveries");
|
|
296
|
+
return {
|
|
297
|
+
root,
|
|
298
|
+
quarantineRoot: join(root, "quarantine"),
|
|
299
|
+
intent: authorityRecoveryIntentPathV3(coordRoot, transactionId),
|
|
300
|
+
receipt: join(root, `${transactionId}.committed.json`),
|
|
301
|
+
quarantine: join(root, "quarantine", `${transactionId}.json`),
|
|
302
|
+
ready: join(ledger.authorityOutbox, `${transactionId}.ready.json`),
|
|
303
|
+
committed: join(ledger.authorityOutbox, `${transactionId}.committed.json`),
|
|
304
|
+
};
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
function ensureRecoveryLayout(paths: ReturnType<typeof recoveryPaths>): void {
|
|
308
|
+
for (const path of [paths.root, paths.quarantineRoot]) {
|
|
309
|
+
mkdirSync(path, { recursive: true, mode: 0o700 });
|
|
310
|
+
chmodSync(path, 0o700);
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
|
|
314
|
+
function publishCanonicalExclusive(path: string, value: unknown): void {
|
|
315
|
+
publishSerializedExclusive(path, `${canonicalJsonV3(value)}\n`);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
function publishSerializedExclusive(path: string, serialized: string): void {
|
|
319
|
+
if (existsSync(path)) {
|
|
320
|
+
if (readFileSync(path, "utf8") !== serialized) {
|
|
321
|
+
throw new Error("authority transaction recovery record conflicts with an existing record");
|
|
322
|
+
}
|
|
323
|
+
return;
|
|
324
|
+
}
|
|
325
|
+
const temporary = `${path}.tmp-${process.pid}-${randomUUID()}`;
|
|
326
|
+
let fd: number | undefined;
|
|
327
|
+
try {
|
|
328
|
+
fd = openSync(temporary, "wx", 0o600);
|
|
329
|
+
writeFileSync(fd, serialized, "utf8");
|
|
330
|
+
fsyncSync(fd);
|
|
331
|
+
closeSync(fd);
|
|
332
|
+
fd = undefined;
|
|
333
|
+
linkSync(temporary, path);
|
|
334
|
+
fsyncParentDirectory(path);
|
|
335
|
+
unlinkSync(temporary);
|
|
336
|
+
} finally {
|
|
337
|
+
if (fd !== undefined) closeSync(fd);
|
|
338
|
+
if (existsSync(temporary)) unlinkSync(temporary);
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
function readIntent(path: string): CoordinationTransactionQuarantineIntentV3 {
|
|
343
|
+
return readCanonicalRecord(path, validateIntent);
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
function readReceipt(path: string): CoordinationTransactionQuarantineReceiptV3 {
|
|
347
|
+
return readCanonicalRecord(path, validateReceipt);
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
function readCanonicalRecord<T>(path: string, validate: (value: unknown) => T): T {
|
|
351
|
+
let text: string;
|
|
352
|
+
let parsed: unknown;
|
|
353
|
+
try {
|
|
354
|
+
text = readFileSync(path, "utf8");
|
|
355
|
+
parsed = JSON.parse(text);
|
|
356
|
+
} catch {
|
|
357
|
+
throw new Error("authority transaction recovery record is malformed");
|
|
358
|
+
}
|
|
359
|
+
const value = validate(parsed);
|
|
360
|
+
if (text !== `${canonicalJsonV3(value)}\n`) {
|
|
361
|
+
throw new Error("authority transaction recovery record is not canonical");
|
|
362
|
+
}
|
|
363
|
+
return value;
|
|
364
|
+
}
|
|
365
|
+
|
|
366
|
+
function validateIntent(value: unknown): CoordinationTransactionQuarantineIntentV3 {
|
|
367
|
+
const record = validateCommon(value, ["format", "format_version"]);
|
|
368
|
+
if (
|
|
369
|
+
record.format !== "harnery-v3-coordination-transaction-quarantine-intent" ||
|
|
370
|
+
record.format_version !== 1
|
|
371
|
+
) {
|
|
372
|
+
throw new Error("authority transaction recovery intent is invalid");
|
|
373
|
+
}
|
|
374
|
+
return record as unknown as CoordinationTransactionQuarantineIntentV3;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
function validateReceipt(value: unknown): CoordinationTransactionQuarantineReceiptV3 {
|
|
378
|
+
const record = validateCommon(value, [
|
|
379
|
+
"completed_at",
|
|
380
|
+
"format",
|
|
381
|
+
"format_version",
|
|
382
|
+
"quarantine_file",
|
|
383
|
+
]);
|
|
384
|
+
if (
|
|
385
|
+
record.format !== "harnery-v3-coordination-transaction-quarantine-receipt" ||
|
|
386
|
+
record.format_version !== 1 ||
|
|
387
|
+
!timestamp(record.completed_at) ||
|
|
388
|
+
Date.parse(String(record.completed_at)) < Date.parse(String(record.created_at)) ||
|
|
389
|
+
record.quarantine_file !== `quarantine/${record.transaction_id}.json`
|
|
390
|
+
) {
|
|
391
|
+
throw new Error("authority transaction recovery receipt is invalid");
|
|
392
|
+
}
|
|
393
|
+
return record as unknown as CoordinationTransactionQuarantineReceiptV3;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
function validateCommon(value: unknown, extraKeys: string[]): Record<string, unknown> {
|
|
397
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
398
|
+
throw new Error("authority transaction recovery record is invalid");
|
|
399
|
+
}
|
|
400
|
+
const record = value as Record<string, unknown>;
|
|
401
|
+
const commonKeys = [
|
|
402
|
+
"actor_instance_id",
|
|
403
|
+
"approval_record_id",
|
|
404
|
+
"created_at",
|
|
405
|
+
"desired_state_digest",
|
|
406
|
+
"event_id",
|
|
407
|
+
"event_row_digest",
|
|
408
|
+
"expected_prior_state_digest",
|
|
409
|
+
"mutation_kind",
|
|
410
|
+
"observed_current_state_digest",
|
|
411
|
+
"producer_state_file",
|
|
412
|
+
"reason",
|
|
413
|
+
"subject_instance_id",
|
|
414
|
+
"transaction_digest",
|
|
415
|
+
"transaction_id",
|
|
416
|
+
];
|
|
417
|
+
if (Object.keys(record).sort().join("\0") !== [...commonKeys, ...extraKeys].sort().join("\0")) {
|
|
418
|
+
throw new Error("authority transaction recovery record has unsupported fields");
|
|
419
|
+
}
|
|
420
|
+
if (
|
|
421
|
+
typeof record.transaction_id !== "string" ||
|
|
422
|
+
!TX_PATTERN.test(record.transaction_id) ||
|
|
423
|
+
typeof record.transaction_digest !== "string" ||
|
|
424
|
+
!SHA256_PATTERN.test(record.transaction_digest) ||
|
|
425
|
+
typeof record.event_id !== "string" ||
|
|
426
|
+
record.event_id.length === 0 ||
|
|
427
|
+
typeof record.event_row_digest !== "string" ||
|
|
428
|
+
!SHA256_PATTERN.test(record.event_row_digest) ||
|
|
429
|
+
typeof record.actor_instance_id !== "string" ||
|
|
430
|
+
!INSTANCE_PATTERN.test(record.actor_instance_id) ||
|
|
431
|
+
typeof record.subject_instance_id !== "string" ||
|
|
432
|
+
!INSTANCE_PATTERN.test(record.subject_instance_id) ||
|
|
433
|
+
typeof record.mutation_kind !== "string" ||
|
|
434
|
+
record.mutation_kind.length === 0 ||
|
|
435
|
+
typeof record.expected_prior_state_digest !== "string" ||
|
|
436
|
+
!SHA256_PATTERN.test(record.expected_prior_state_digest) ||
|
|
437
|
+
typeof record.desired_state_digest !== "string" ||
|
|
438
|
+
!SHA256_PATTERN.test(record.desired_state_digest) ||
|
|
439
|
+
typeof record.observed_current_state_digest !== "string" ||
|
|
440
|
+
!SHA256_PATTERN.test(record.observed_current_state_digest) ||
|
|
441
|
+
typeof record.approval_record_id !== "string" ||
|
|
442
|
+
!APPROVAL_PATTERN.test(record.approval_record_id) ||
|
|
443
|
+
typeof record.producer_state_file !== "string" ||
|
|
444
|
+
!PRODUCER_STATE_PATTERN.test(record.producer_state_file) ||
|
|
445
|
+
record.reason !== "current_state_conflict" ||
|
|
446
|
+
!timestamp(record.created_at)
|
|
447
|
+
) {
|
|
448
|
+
throw new Error("authority transaction recovery record values are invalid");
|
|
449
|
+
}
|
|
450
|
+
return record;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
function assertTransactionId(value: string): asserts value is `txn_${string}` {
|
|
454
|
+
if (!TX_PATTERN.test(value)) throw new Error("authority transaction ID is invalid");
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
function assertInstanceId(value: string): void {
|
|
458
|
+
if (!INSTANCE_PATTERN.test(value)) throw new Error("authority recovery actor is invalid");
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
function assertDigest(value: string, label: string): void {
|
|
462
|
+
if (!SHA256_PATTERN.test(value)) throw new Error(`${label} is invalid`);
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
function assertApprovalRecordId(value: string): void {
|
|
466
|
+
if (!APPROVAL_PATTERN.test(value)) throw new Error("approval record ID is invalid");
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function timestamp(value: unknown): boolean {
|
|
470
|
+
return typeof value === "string" && Number.isFinite(Date.parse(value));
|
|
471
|
+
}
|
|
472
|
+
|
|
473
|
+
function removeIfExists(path: string): void {
|
|
474
|
+
if (!existsSync(path)) return;
|
|
475
|
+
unlinkSync(path);
|
|
476
|
+
fsyncParentDirectory(path);
|
|
477
|
+
}
|
|
@@ -68,6 +68,17 @@ export class CoordinationViewV3Error extends Error {
|
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
|
|
71
|
+
/**
|
|
72
|
+
* A canonical ledger read is immutable and readLedgerV3 returns the same result
|
|
73
|
+
* object until the authority changes. Several web helpers derive the
|
|
74
|
+
* coordination view independently during one server render; without this
|
|
75
|
+
* cache each helper reduces the complete append-only history again.
|
|
76
|
+
*
|
|
77
|
+
* Weak keys bind the projection lifetime to the reader snapshot. A newly
|
|
78
|
+
* appended event produces a new ReadLedgerV3Result and therefore a fresh view.
|
|
79
|
+
*/
|
|
80
|
+
const coordinationViewCacheV3 = new WeakMap<ReadLedgerV3Result, CoordinationViewV3>();
|
|
81
|
+
|
|
71
82
|
/** Read the complete V3 catalog and derive the disposable coordination view. */
|
|
72
83
|
export function readCoordinationViewV3(coordRoot: string): CoordinationViewV3 {
|
|
73
84
|
return projectCoordinationViewV3(readLedgerV3(coordRoot));
|
|
@@ -78,6 +89,9 @@ export function readCoordinationViewV3(coordRoot: string): CoordinationViewV3 {
|
|
|
78
89
|
* finalization, web, and Codec adapters. This function performs no writes.
|
|
79
90
|
*/
|
|
80
91
|
export function projectCoordinationViewV3(read: ReadLedgerV3Result): CoordinationViewV3 {
|
|
92
|
+
const cached = coordinationViewCacheV3.get(read);
|
|
93
|
+
if (cached) return cached;
|
|
94
|
+
|
|
81
95
|
const safety = reduceSafetyProjectionV3(read);
|
|
82
96
|
const starts = new Map<string, Extract<EventV3, { event_type: "session.started" }>>();
|
|
83
97
|
const eventGeneration = new Map<string, string>();
|
|
@@ -169,7 +183,7 @@ export function projectCoordinationViewV3(read: ReadLedgerV3Result): Coordinatio
|
|
|
169
183
|
}
|
|
170
184
|
}
|
|
171
185
|
|
|
172
|
-
|
|
186
|
+
const view: CoordinationViewV3 = {
|
|
173
187
|
projection_version: EVENT_V3_COORDINATION_VIEW_VERSION,
|
|
174
188
|
contract_major: 2,
|
|
175
189
|
reducer_build_id: EVENT_V3_SAFETY_REDUCER_BUILD,
|
|
@@ -182,6 +196,8 @@ export function projectCoordinationViewV3(read: ReadLedgerV3Result): Coordinatio
|
|
|
182
196
|
decisions: safety.decisions,
|
|
183
197
|
health: safety.health,
|
|
184
198
|
};
|
|
199
|
+
coordinationViewCacheV3.set(read, view);
|
|
200
|
+
return view;
|
|
185
201
|
}
|
|
186
202
|
|
|
187
203
|
/** Refuse authority decisions while still allowing callers to render diagnostics. */
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/** Generated by scripts/generate-event-v3-contract.ts. Do not edit. */
|
|
2
2
|
export const EVENT_V3_SCHEMA_DIGEST =
|
|
3
|
-
"sha256:
|
|
3
|
+
"sha256:bdcee8d7839add0c786740ba9d5cfd0b6573f0ad4974bf53272737468734aa36" as const;
|
|
4
4
|
export const EVENT_V3_GENERATED_CORE_TYPES = [
|
|
5
5
|
"ledger.genesis",
|
|
6
6
|
"ledger.activated",
|