harnery 0.38.0 → 0.40.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/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +32 -8
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +97 -6
- package/dist/commands/backup.d.ts +16 -0
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +239 -33
- package/dist/commands/browse.d.ts +8 -0
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +466 -231
- package/dist/commands/diagnostics.d.ts.map +1 -1
- package/dist/commands/diagnostics.js +6 -3
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +20 -4
- package/dist/commands/qa-run.d.ts.map +1 -1
- package/dist/commands/qa-run.js +26 -3
- package/dist/commands/qa-status.d.ts.map +1 -1
- package/dist/commands/qa-status.js +7 -2
- package/dist/commands/resources.d.ts.map +1 -1
- package/dist/commands/resources.js +23 -3
- package/dist/commands/review-pack.d.ts.map +1 -1
- package/dist/commands/review-pack.js +98 -23
- package/dist/commands/tunnel.d.ts.map +1 -1
- package/dist/commands/tunnel.js +2 -2
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/canonical-emit.d.ts +3 -2
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +2 -0
- package/dist/core/agents/cli.js +13 -6
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +5 -3
- package/dist/core/agents/live-lifecycle-v3.d.ts +2 -2
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.d.ts +7 -5
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +63 -8
- package/dist/core/agents/session-finalizer-v3.d.ts +2 -2
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.d.ts +3 -3
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +2 -1
- package/dist/core/agents/state/names.d.ts +35 -2
- package/dist/core/agents/state/names.d.ts.map +1 -1
- package/dist/core/agents/state/names.js +80 -5
- package/dist/core/agents/state/stale-sweep.d.ts +2 -1
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +23 -6
- package/dist/core/agents/turn-elapsed.d.ts +51 -0
- package/dist/core/agents/turn-elapsed.d.ts.map +1 -0
- package/dist/core/agents/turn-elapsed.js +91 -0
- package/dist/core/artifacts/activity.d.ts +14 -0
- package/dist/core/artifacts/activity.d.ts.map +1 -0
- package/dist/core/artifacts/activity.js +52 -0
- package/dist/core/artifacts/delivery-card.d.ts +39 -0
- package/dist/core/artifacts/delivery-card.d.ts.map +1 -0
- package/dist/core/artifacts/delivery-card.js +282 -0
- package/dist/core/artifacts/index.d.ts +42 -7
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +288 -76
- package/dist/core/artifacts/mutation-lock.d.ts +2 -0
- package/dist/core/artifacts/mutation-lock.d.ts.map +1 -0
- package/dist/core/artifacts/mutation-lock.js +91 -0
- package/dist/core/backup/host-snapshot.d.ts +18 -0
- package/dist/core/backup/host-snapshot.d.ts.map +1 -0
- package/dist/core/backup/host-snapshot.js +64 -0
- package/dist/core/config.d.ts +20 -5
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +44 -10
- package/dist/core/diagnostics/advice.d.ts +38 -3
- package/dist/core/diagnostics/advice.d.ts.map +1 -1
- package/dist/core/diagnostics/advice.js +103 -99
- package/dist/core/diagnostics/bundle.d.ts.map +1 -1
- package/dist/core/diagnostics/bundle.js +111 -47
- package/dist/core/diagnostics/comparison.d.ts.map +1 -1
- package/dist/core/diagnostics/comparison.js +3 -2
- package/dist/core/diagnostics/contract.d.ts +15 -31
- package/dist/core/diagnostics/contract.d.ts.map +1 -1
- package/dist/core/diagnostics/contract.js +2 -5
- package/dist/core/diagnostics/index.d.ts +2 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -1
- package/dist/core/diagnostics/index.js +2 -0
- package/dist/core/diagnostics/pressure-contract.d.ts +260 -0
- package/dist/core/diagnostics/pressure-contract.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure-contract.js +70 -0
- package/dist/core/diagnostics/pressure.d.ts +25 -0
- package/dist/core/diagnostics/pressure.d.ts.map +1 -0
- package/dist/core/diagnostics/pressure.js +1138 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -1
- package/dist/core/diagnostics/replay.js +90 -10
- package/dist/core/events/v3/adapter-id.d.ts +6 -0
- package/dist/core/events/v3/adapter-id.d.ts.map +1 -0
- package/dist/core/events/v3/adapter-id.js +7 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -1
- package/dist/core/events/v3/archive-retention.js +3 -2
- package/dist/core/events/v3/bootstrap.d.ts +41 -4
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +120 -17
- package/dist/core/events/v3/capabilities.d.ts +16 -9
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +37 -2
- package/dist/core/events/v3/capability-drift.d.ts +2 -2
- package/dist/core/events/v3/capability-drift.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.d.ts +48 -5
- package/dist/core/events/v3/control-witness.d.ts.map +1 -1
- package/dist/core/events/v3/control-witness.js +91 -36
- package/dist/core/events/v3/control.d.ts.map +1 -1
- package/dist/core/events/v3/control.js +22 -2
- package/dist/core/events/v3/index.d.ts +2 -1
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +2 -1
- package/dist/core/events/v3/live-feed.d.ts +7 -1
- package/dist/core/events/v3/live-feed.d.ts.map +1 -1
- package/dist/core/events/v3/live-feed.js +21 -3
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +10 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/command-recorder.js +2 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +2 -2
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +2 -1
- package/dist/core/events/v3/producers/hook-base.d.ts +2 -2
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +15 -5
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook.js +17 -4
- package/dist/core/events/v3/producers/intake.d.ts +4 -4
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +3 -2
- package/dist/core/events/v3/producers/producer-state-observer.d.ts.map +1 -1
- package/dist/core/events/v3/producers/producer-state-observer.js +2 -1
- package/dist/core/events/v3/producers/recorder.d.ts +16 -5
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +31 -9
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +10 -13
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-build.js +3 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +2 -2
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.d.ts +2 -2
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.d.ts +16 -14
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +36 -38
- package/dist/core/hooks/backup-schedule.d.ts +34 -0
- package/dist/core/hooks/backup-schedule.d.ts.map +1 -0
- package/dist/core/hooks/backup-schedule.js +114 -0
- package/dist/core/hooks/cli.js +61 -18
- package/dist/core/hooks/codex-wsl-bridge.d.ts +2 -0
- package/dist/core/hooks/codex-wsl-bridge.d.ts.map +1 -1
- package/dist/core/hooks/codex-wsl-bridge.js +18 -4
- package/dist/core/hooks/index.d.ts +1 -0
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +1 -0
- package/dist/core/hooks/prompt-context/contract.d.ts +61 -0
- package/dist/core/hooks/prompt-context/contract.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/contract.js +102 -0
- package/dist/core/hooks/prompt-context/index.d.ts +5 -0
- package/dist/core/hooks/prompt-context/index.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/index.js +2 -0
- package/dist/core/hooks/prompt-context/runner.d.ts +24 -0
- package/dist/core/hooks/prompt-context/runner.d.ts.map +1 -0
- package/dist/core/hooks/prompt-context/runner.js +249 -0
- package/dist/core/qa-artifacts.d.ts +3 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -1
- package/dist/core/qa-artifacts.js +25 -3
- package/dist/core/resources/contract.d.ts +69 -3
- package/dist/core/resources/contract.d.ts.map +1 -1
- package/dist/core/resources/contract.js +1 -1
- package/dist/core/resources/index.d.ts +1 -0
- package/dist/core/resources/index.d.ts.map +1 -1
- package/dist/core/resources/index.js +1 -0
- package/dist/core/resources/native.d.ts +36 -0
- package/dist/core/resources/native.d.ts.map +1 -0
- package/dist/core/resources/native.js +418 -0
- package/dist/core/resources/sampler.d.ts +2 -0
- package/dist/core/resources/sampler.d.ts.map +1 -1
- package/dist/core/resources/sampler.js +31 -1
- package/dist/core/resources/status.d.ts +61 -0
- package/dist/core/resources/status.d.ts.map +1 -0
- package/dist/core/resources/status.js +536 -0
- package/dist/core/resources/system.d.ts +27 -0
- package/dist/core/resources/system.d.ts.map +1 -0
- package/dist/core/resources/system.js +439 -0
- package/dist/core/semantic/contract.d.ts +13 -13
- package/dist/core/semantic/service.d.ts +2 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +27 -4
- package/dist/core/storage/builtins.js +41 -0
- package/dist/core/supervisor/contract.d.ts +41 -3
- package/dist/core/supervisor/contract.d.ts.map +1 -1
- package/dist/core/supervisor/contract.js +3 -2
- package/dist/core/supervisor/findings.d.ts +3 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -1
- package/dist/core/supervisor/findings.js +88 -0
- package/dist/core/supervisor/history.d.ts.map +1 -1
- package/dist/core/supervisor/history.js +14 -0
- package/dist/core/supervisor/ledger-state.d.ts +55 -0
- package/dist/core/supervisor/ledger-state.d.ts.map +1 -0
- package/dist/core/supervisor/ledger-state.js +0 -0
- package/dist/core/supervisor/service.d.ts.map +1 -1
- package/dist/core/supervisor/service.js +120 -7
- package/dist/core/supervisor/storage.d.ts +3 -1
- package/dist/core/supervisor/storage.d.ts.map +1 -1
- package/dist/core/supervisor/storage.js +4 -0
- package/dist/core/workflow/admission.d.ts +3 -0
- package/dist/core/workflow/admission.d.ts.map +1 -1
- package/dist/core/workflow/admission.js +28 -16
- package/dist/core/workflow/engine.js +2 -2
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +6 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +4 -3
- package/dist/lib/browser/capture-fidelity.d.ts +7 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -1
- package/dist/lib/browser/capture-fidelity.js +17 -0
- package/dist/lib/browser/client.d.ts +9 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +85 -37
- package/dist/lib/browser/index.d.ts +3 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -1
- package/dist/lib/browser/page-review-budget.d.ts +13 -0
- package/dist/lib/browser/page-review-budget.d.ts.map +1 -0
- package/dist/lib/browser/page-review-budget.js +251 -0
- package/dist/lib/browser/page-review-contracts.d.ts +127 -0
- package/dist/lib/browser/page-review-contracts.d.ts.map +1 -0
- package/dist/lib/browser/page-review-contracts.js +5 -0
- package/dist/lib/browser/page-review-evidence.d.ts +48 -0
- package/dist/lib/browser/page-review-evidence.d.ts.map +1 -0
- package/dist/lib/browser/page-review-evidence.js +340 -0
- package/dist/lib/browser/page-review-judge.d.ts +1 -1
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -1
- package/dist/lib/browser/page-review-judge.js +46 -38
- package/dist/lib/browser/page-review-pack.d.ts +44 -22
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -1
- package/dist/lib/browser/page-review-pack.js +116 -36
- package/dist/lib/browser/page-review-source.d.ts +12 -0
- package/dist/lib/browser/page-review-source.d.ts.map +1 -0
- package/dist/lib/browser/page-review-source.js +22 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +35 -9
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -1
- package/dist/lib/browser/qa-run-contracts.js +48 -14
- package/dist/lib/browser/qa-run.d.ts.map +1 -1
- package/dist/lib/browser/qa-run.js +215 -68
- package/dist/lib/browser/qa-snapshot.d.ts +6 -0
- package/dist/lib/browser/qa-snapshot.d.ts.map +1 -1
- package/dist/lib/browser/qa-snapshot.js +259 -48
- package/dist/lib/browser/review-capture-transaction.d.ts +13 -0
- package/dist/lib/browser/review-capture-transaction.d.ts.map +1 -0
- package/dist/lib/browser/review-capture-transaction.js +79 -0
- package/dist/lib/browser/standalone-html.d.ts.map +1 -1
- package/dist/lib/browser/standalone-html.js +4 -2
- package/dist/lib/browser/thumbnail-association.d.ts +34 -0
- package/dist/lib/browser/thumbnail-association.d.ts.map +1 -0
- package/dist/lib/browser/thumbnail-association.js +158 -0
- package/dist/lib/browser/tiling.d.ts +30 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +38 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -1
- package/dist/lib/docs-metadata-managed.js +4 -1
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +7 -1
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +1 -0
- package/dist/lib/local-file-url.d.ts +12 -0
- package/dist/lib/local-file-url.d.ts.map +1 -1
- package/dist/lib/local-file-url.js +16 -2
- package/dist/lib/tunnel/state.d.ts +19 -4
- package/dist/lib/tunnel/state.d.ts.map +1 -1
- package/dist/lib/tunnel/state.js +53 -13
- package/package.json +7 -4
- package/schemas/config.schema.json +69 -2
- package/src/commands/agents.ts +42 -9
- package/src/commands/artifacts.ts +130 -6
- package/src/commands/backup.ts +287 -34
- package/src/commands/browse.ts +564 -267
- package/src/commands/diagnostics.ts +6 -3
- package/src/commands/ledger-v3.ts +20 -3
- package/src/commands/qa-run.ts +37 -3
- package/src/commands/qa-status.ts +11 -2
- package/src/commands/resources.ts +23 -3
- package/src/commands/review-pack.ts +165 -62
- package/src/commands/tunnel.ts +2 -1
- package/src/core/agents/canonical-emit.ts +4 -2
- package/src/core/agents/cli.ts +14 -6
- package/src/core/agents/live-authority-v3.ts +7 -3
- package/src/core/agents/live-lifecycle-v3.ts +2 -2
- package/src/core/agents/render/prompt-context.ts +68 -14
- package/src/core/agents/session-finalizer-v3.ts +2 -2
- package/src/core/agents/state/live-coordination-view.ts +4 -4
- package/src/core/agents/state/names.ts +92 -7
- package/src/core/agents/state/stale-sweep.ts +22 -8
- package/src/core/agents/turn-elapsed.ts +135 -0
- package/src/core/artifacts/activity.ts +71 -0
- package/src/core/artifacts/delivery-card.ts +375 -0
- package/src/core/artifacts/index.ts +385 -91
- package/src/core/artifacts/mutation-lock.ts +106 -0
- package/src/core/backup/host-snapshot.ts +76 -0
- package/src/core/config.ts +66 -13
- package/src/core/diagnostics/advice.ts +148 -120
- package/src/core/diagnostics/bundle.ts +138 -52
- package/src/core/diagnostics/comparison.ts +6 -2
- package/src/core/diagnostics/contract.ts +39 -42
- package/src/core/diagnostics/index.ts +2 -0
- package/src/core/diagnostics/pressure-contract.ts +294 -0
- package/src/core/diagnostics/pressure.ts +1361 -0
- package/src/core/diagnostics/replay.ts +116 -11
- package/src/core/events/v3/adapter-id.ts +12 -0
- package/src/core/events/v3/archive-retention.ts +3 -6
- package/src/core/events/v3/bootstrap.ts +163 -16
- package/src/core/events/v3/capabilities.ts +75 -25
- package/src/core/events/v3/capability-drift.ts +2 -2
- package/src/core/events/v3/control-witness.ts +172 -41
- package/src/core/events/v3/control.ts +34 -2
- package/src/core/events/v3/index.ts +3 -0
- package/src/core/events/v3/live-feed.ts +23 -5
- package/src/core/events/v3/live-routing.ts +14 -2
- package/src/core/events/v3/producers/command-recorder.ts +4 -4
- package/src/core/events/v3/producers/coordination-recorder.ts +4 -4
- package/src/core/events/v3/producers/hook-base.ts +21 -16
- package/src/core/events/v3/producers/hook.ts +21 -4
- package/src/core/events/v3/producers/intake.ts +6 -6
- package/src/core/events/v3/producers/producer-state-observer.ts +2 -1
- package/src/core/events/v3/producers/recorder.ts +50 -21
- package/src/core/events/v3/reader.ts +14 -13
- package/src/core/events/v3/runtime-build.ts +3 -2
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +3 -3
- package/src/core/events/v3/turn-telemetry.ts +4 -4
- package/src/core/hooks/adapter/output.ts +50 -36
- package/src/core/hooks/backup-schedule.ts +147 -0
- package/src/core/hooks/cli.ts +65 -14
- package/src/core/hooks/codex-wsl-bridge.ts +21 -5
- package/src/core/hooks/index.ts +1 -0
- package/src/core/hooks/prompt-context/contract.ts +177 -0
- package/src/core/hooks/prompt-context/index.ts +22 -0
- package/src/core/hooks/prompt-context/runner.ts +303 -0
- package/src/core/qa-artifacts.ts +29 -3
- package/src/core/resources/contract.ts +76 -3
- package/src/core/resources/index.ts +1 -0
- package/src/core/resources/native.ts +481 -0
- package/src/core/resources/sampler.ts +46 -1
- package/src/core/resources/status.ts +717 -0
- package/src/core/resources/system.ts +530 -0
- package/src/core/semantic/service.ts +37 -3
- package/src/core/storage/builtins.ts +41 -0
- package/src/core/supervisor/contract.ts +45 -3
- package/src/core/supervisor/findings.ts +159 -0
- package/src/core/supervisor/history.ts +15 -0
- package/src/core/supervisor/ledger-state.ts +0 -0
- package/src/core/supervisor/service.ts +133 -5
- package/src/core/supervisor/storage.ts +7 -0
- package/src/core/workflow/admission.ts +33 -17
- package/src/core/workflow/engine.ts +2 -2
- package/src/core/workflow/live-session-v3.ts +6 -8
- package/src/core/workflow/proof.ts +4 -3
- package/src/lib/browser/capture-fidelity.ts +23 -0
- package/src/lib/browser/client.ts +96 -44
- package/src/lib/browser/index.ts +15 -1
- package/src/lib/browser/page-review-budget.ts +309 -0
- package/src/lib/browser/page-review-contracts.ts +129 -0
- package/src/lib/browser/page-review-evidence.ts +465 -0
- package/src/lib/browser/page-review-judge.ts +56 -40
- package/src/lib/browser/page-review-pack.ts +181 -43
- package/src/lib/browser/page-review-source.ts +30 -0
- package/src/lib/browser/qa-run-contracts.ts +62 -18
- package/src/lib/browser/qa-run.ts +259 -71
- package/src/lib/browser/qa-snapshot.ts +289 -48
- package/src/lib/browser/review-capture-transaction.ts +106 -0
- package/src/lib/browser/standalone-html.ts +4 -2
- package/src/lib/browser/thumbnail-association.ts +190 -0
- package/src/lib/browser/tiling.ts +63 -0
- package/src/lib/docs-metadata-managed.ts +4 -1
- package/src/lib/identities/assume.ts +12 -4
- package/src/lib/instructions/templates.ts +1 -0
- package/src/lib/local-file-url.ts +17 -2
- package/src/lib/tunnel/state.ts +70 -13
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EventAdapterIdV3 } from "./adapter-id.ts";
|
|
2
2
|
import { canonicalJsonV3, sha256V3 } from "./canonical.ts";
|
|
3
3
|
|
|
4
4
|
export type CapabilitySupportV3 = "native" | "derived" | "conditional" | "unsupported";
|
|
5
5
|
|
|
6
|
+
export type AdapterDurationCapabilityV3 = "turn_duration" | "tool_duration";
|
|
7
|
+
|
|
6
8
|
export type CursorExecutionModeV3 = "local" | "cloud" | "unknown";
|
|
7
9
|
|
|
8
10
|
export type AdapterWaitKindV3 =
|
|
@@ -59,7 +61,7 @@ export type AdapterSignalV3 =
|
|
|
59
61
|
export interface AdapterCapabilityProfileV3 {
|
|
60
62
|
format: "harnery-v3-adapter-capabilities";
|
|
61
63
|
format_version: 1;
|
|
62
|
-
adapter:
|
|
64
|
+
adapter: EventAdapterIdV3;
|
|
63
65
|
signals: Record<AdapterSignalV3, CapabilitySupportV3>;
|
|
64
66
|
}
|
|
65
67
|
|
|
@@ -79,7 +81,10 @@ const SHARED_SIGNAL_SUPPORT = {
|
|
|
79
81
|
model_identity: "conditional",
|
|
80
82
|
} as const;
|
|
81
83
|
|
|
82
|
-
const BASE_SIGNAL_SUPPORT: Record<
|
|
84
|
+
const BASE_SIGNAL_SUPPORT: Record<
|
|
85
|
+
EventAdapterIdV3,
|
|
86
|
+
Record<BaseAdapterSignalV3, CapabilitySupportV3>
|
|
87
|
+
> = {
|
|
83
88
|
"claude-code": {
|
|
84
89
|
...SHARED_SIGNAL_SUPPORT,
|
|
85
90
|
session_end: "native",
|
|
@@ -110,11 +115,32 @@ const BASE_SIGNAL_SUPPORT: Record<Adapter, Record<BaseAdapterSignalV3, Capabilit
|
|
|
110
115
|
post_compaction: "unsupported",
|
|
111
116
|
context_usage: "conditional",
|
|
112
117
|
},
|
|
118
|
+
openclaw: {
|
|
119
|
+
session_start: "conditional",
|
|
120
|
+
session_end: "native",
|
|
121
|
+
prompt: "native",
|
|
122
|
+
turn_id: "native",
|
|
123
|
+
turn_completion: "native",
|
|
124
|
+
assistant_reply_text: "unsupported",
|
|
125
|
+
tool_request: "native",
|
|
126
|
+
tool_result: "native",
|
|
127
|
+
tool_failure: "conditional",
|
|
128
|
+
tool_call_id: "native",
|
|
129
|
+
tool_duration: "unsupported",
|
|
130
|
+
permission: "unsupported",
|
|
131
|
+
subagent: "unsupported",
|
|
132
|
+
shell: "native",
|
|
133
|
+
pre_compaction: "unsupported",
|
|
134
|
+
post_compaction: "unsupported",
|
|
135
|
+
context_usage: "unsupported",
|
|
136
|
+
model_identity: "unsupported",
|
|
137
|
+
},
|
|
113
138
|
};
|
|
114
139
|
|
|
115
140
|
function profile(
|
|
116
|
-
adapter:
|
|
141
|
+
adapter: EventAdapterIdV3,
|
|
117
142
|
economics: Pick<Record<AdapterSignalV3, CapabilitySupportV3>, "model_usage" | "inference_timing">,
|
|
143
|
+
harnessTiming: CapabilitySupportV3 = "derived",
|
|
118
144
|
): AdapterCapabilityProfileV3 {
|
|
119
145
|
return {
|
|
120
146
|
format: "harnery-v3-adapter-capabilities",
|
|
@@ -123,56 +149,80 @@ function profile(
|
|
|
123
149
|
signals: {
|
|
124
150
|
...BASE_SIGNAL_SUPPORT[adapter],
|
|
125
151
|
...economics,
|
|
126
|
-
harness_timing:
|
|
152
|
+
harness_timing: harnessTiming,
|
|
127
153
|
capability_drift: "derived",
|
|
128
154
|
},
|
|
129
155
|
};
|
|
130
156
|
}
|
|
131
157
|
|
|
132
|
-
export const ADAPTER_CAPABILITY_PROFILES_V3: Record<
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
158
|
+
export const ADAPTER_CAPABILITY_PROFILES_V3: Record<EventAdapterIdV3, AdapterCapabilityProfileV3> =
|
|
159
|
+
{
|
|
160
|
+
"claude-code": profile("claude-code", {
|
|
161
|
+
model_usage: "conditional",
|
|
162
|
+
inference_timing: "unsupported",
|
|
163
|
+
}),
|
|
164
|
+
codex: profile("codex", {
|
|
165
|
+
model_usage: "conditional",
|
|
166
|
+
inference_timing: "unsupported",
|
|
167
|
+
}),
|
|
168
|
+
cursor: profile("cursor", {
|
|
169
|
+
model_usage: "unsupported",
|
|
170
|
+
inference_timing: "unsupported",
|
|
171
|
+
}),
|
|
172
|
+
openclaw: profile(
|
|
173
|
+
"openclaw",
|
|
174
|
+
{
|
|
175
|
+
model_usage: "unsupported",
|
|
176
|
+
inference_timing: "unsupported",
|
|
177
|
+
},
|
|
178
|
+
"unsupported",
|
|
179
|
+
),
|
|
180
|
+
};
|
|
146
181
|
|
|
147
|
-
export function adapterCapabilityProfileV3(adapter:
|
|
182
|
+
export function adapterCapabilityProfileV3(adapter: EventAdapterIdV3): AdapterCapabilityProfileV3 {
|
|
148
183
|
return ADAPTER_CAPABILITY_PROFILES_V3[adapter];
|
|
149
184
|
}
|
|
150
185
|
|
|
151
|
-
export function adapterCapabilityProfileDigestV3(adapter:
|
|
186
|
+
export function adapterCapabilityProfileDigestV3(adapter: EventAdapterIdV3): `cap_${string}` {
|
|
152
187
|
return `cap_${sha256V3(canonicalJsonV3(adapterCapabilityProfileV3(adapter))).slice(7)}`;
|
|
153
188
|
}
|
|
154
189
|
|
|
155
190
|
export function adapterSignalSupportV3(
|
|
156
|
-
adapter:
|
|
191
|
+
adapter: EventAdapterIdV3,
|
|
157
192
|
signal: AdapterSignalV3,
|
|
158
193
|
): CapabilitySupportV3 {
|
|
159
194
|
return adapterCapabilityProfileV3(adapter).signals[signal];
|
|
160
195
|
}
|
|
161
196
|
|
|
197
|
+
/**
|
|
198
|
+
* Duration support for terminal spans. Tool duration is part of the digested
|
|
199
|
+
* adapter profile. Turn duration predates that profile dimension, so keep its
|
|
200
|
+
* compatibility-preserving classification here until the next contract major.
|
|
201
|
+
*/
|
|
202
|
+
export function adapterDurationSupportV3(
|
|
203
|
+
adapter: EventAdapterIdV3,
|
|
204
|
+
capability: AdapterDurationCapabilityV3,
|
|
205
|
+
): CapabilitySupportV3 {
|
|
206
|
+
if (capability === "tool_duration") {
|
|
207
|
+
return adapterSignalSupportV3(adapter, "tool_duration");
|
|
208
|
+
}
|
|
209
|
+
return adapter === "openclaw" ? "unsupported" : "derived";
|
|
210
|
+
}
|
|
211
|
+
|
|
162
212
|
/**
|
|
163
213
|
* Adapter hooks only expose permission waits today. Other wait kinds can be
|
|
164
214
|
* authored by coordination producers, but they are not observable from an
|
|
165
215
|
* adapter's native turn channel.
|
|
166
216
|
*/
|
|
167
217
|
export function adapterWaitKindSupportV3(
|
|
168
|
-
adapter:
|
|
218
|
+
adapter: EventAdapterIdV3,
|
|
169
219
|
kind: AdapterWaitKindV3,
|
|
170
220
|
): CapabilitySupportV3 {
|
|
171
221
|
return kind === "permission" ? adapterSignalSupportV3(adapter, "permission") : "unsupported";
|
|
172
222
|
}
|
|
173
223
|
|
|
174
224
|
/** No current adapter supplies an independent completed-turn wait aggregate. */
|
|
175
|
-
export function adapterTurnWaitCountSupportV3(_adapter:
|
|
225
|
+
export function adapterTurnWaitCountSupportV3(_adapter: EventAdapterIdV3): CapabilitySupportV3 {
|
|
176
226
|
return "unsupported";
|
|
177
227
|
}
|
|
178
228
|
|
|
@@ -182,7 +232,7 @@ export function adapterTurnWaitCountSupportV3(_adapter: Adapter): CapabilitySupp
|
|
|
182
232
|
* never proves that an absent span means zero.
|
|
183
233
|
*/
|
|
184
234
|
export function adapterWaitCoverageMatrixV3(
|
|
185
|
-
adapter:
|
|
235
|
+
adapter: EventAdapterIdV3,
|
|
186
236
|
): Record<AdapterWaitKindV3, WaitKindCapabilityV3> {
|
|
187
237
|
return Object.fromEntries(
|
|
188
238
|
ADAPTER_WAIT_KINDS_V3.map((kind) => [
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type { EventAdapterIdV3 } from "./adapter-id.ts";
|
|
2
2
|
import {
|
|
3
3
|
type AdapterSignalV3,
|
|
4
4
|
adapterSignalSupportV3,
|
|
@@ -23,7 +23,7 @@ export type CapabilityDriftPayloadV3 = EventPayloadV3<"health.capability_drift">
|
|
|
23
23
|
* failures.
|
|
24
24
|
*/
|
|
25
25
|
export function capabilityDriftPayloadsV3(
|
|
26
|
-
adapter:
|
|
26
|
+
adapter: EventAdapterIdV3,
|
|
27
27
|
events: readonly EventV3[],
|
|
28
28
|
options: { generation_ended?: boolean } = {},
|
|
29
29
|
): CapabilityDriftPayloadV3[] {
|
|
@@ -28,15 +28,23 @@ import {
|
|
|
28
28
|
|
|
29
29
|
export { EVENT_V3_CONTROL_CHECKPOINT_RELATIVE_PATH, EVENT_V3_CONTROL_WITNESS_RELATIVE_PATH };
|
|
30
30
|
|
|
31
|
-
|
|
31
|
+
/**
|
|
32
|
+
* A witness answers one question cheaply: does an authenticated record already
|
|
33
|
+
* name this exact control pair over this exact storage? Both control states get
|
|
34
|
+
* one, because a hook must never pay a whole-history parse for either.
|
|
35
|
+
*
|
|
36
|
+
* `control_state` is the discriminator, and it is authenticated with the rest of
|
|
37
|
+
* the payload. A candidate witness therefore cannot be replayed as an active
|
|
38
|
+
* one, and an active witness cannot survive its activation being removed.
|
|
39
|
+
*/
|
|
40
|
+
export type EventV3ControlWitnessControlStateV3 = "active" | "candidate";
|
|
41
|
+
|
|
42
|
+
interface EventV3ControlWitnessPayloadCommonV3 {
|
|
32
43
|
format: "harnery-event-v3-control-witness";
|
|
33
|
-
format_version:
|
|
44
|
+
format_version: 2;
|
|
34
45
|
genesis_id: `gex_${string}`;
|
|
35
|
-
activation_id: `act_${string}`;
|
|
36
46
|
genesis_event_id: `evt_${string}`;
|
|
37
|
-
activation_event_id: `evt_${string}`;
|
|
38
47
|
genesis_manifest_digest: `sha256:${string}`;
|
|
39
|
-
activation_manifest_digest: `sha256:${string}`;
|
|
40
48
|
candidate_manifest_digest: `sha256:${string}`;
|
|
41
49
|
privacy_key_epoch: `pep_${string}`;
|
|
42
50
|
root_id: `root_${string}`;
|
|
@@ -44,6 +52,21 @@ interface EventV3ControlWitnessPayload {
|
|
|
44
52
|
checkpoint_digest: `sha256:${string}`;
|
|
45
53
|
}
|
|
46
54
|
|
|
55
|
+
interface EventV3ActiveControlWitnessPayloadV3 extends EventV3ControlWitnessPayloadCommonV3 {
|
|
56
|
+
control_state: "active";
|
|
57
|
+
activation_id: `act_${string}`;
|
|
58
|
+
activation_event_id: `evt_${string}`;
|
|
59
|
+
activation_manifest_digest: `sha256:${string}`;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
interface EventV3CandidateControlWitnessPayloadV3 extends EventV3ControlWitnessPayloadCommonV3 {
|
|
63
|
+
control_state: "candidate";
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
type EventV3ControlWitnessPayload =
|
|
67
|
+
| EventV3ActiveControlWitnessPayloadV3
|
|
68
|
+
| EventV3CandidateControlWitnessPayloadV3;
|
|
69
|
+
|
|
47
70
|
interface EventV3ControlWitness {
|
|
48
71
|
payload: EventV3ControlWitnessPayload;
|
|
49
72
|
authentication: FingerprintV3;
|
|
@@ -55,22 +78,43 @@ export interface ActiveControlWitnessBindingV3 {
|
|
|
55
78
|
candidate_manifest_digest: `sha256:${string}`;
|
|
56
79
|
}
|
|
57
80
|
|
|
81
|
+
/** The candidate equivalent: a validated genesis with no activation yet. */
|
|
82
|
+
export interface CandidateControlWitnessBindingV3 {
|
|
83
|
+
genesis: CandidateGenesisManifestV3;
|
|
84
|
+
candidate_manifest_digest: `sha256:${string}`;
|
|
85
|
+
}
|
|
86
|
+
|
|
58
87
|
/** True only when one authenticated witness names this exact active control pair and storage. */
|
|
59
88
|
export function activeControlWitnessMatchesV3(
|
|
60
89
|
coordRoot: string,
|
|
61
90
|
binding: ActiveControlWitnessBindingV3,
|
|
62
91
|
): boolean {
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
92
|
+
return witnessMatchesV3(coordRoot, "active", (storage, checkpointDigest) =>
|
|
93
|
+
activeWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
94
|
+
);
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* True only when one authenticated witness names this exact candidate control
|
|
99
|
+
* pair and storage.
|
|
100
|
+
*
|
|
101
|
+
* A candidate epoch is not a degraded active one: its gate is narrower, but a
|
|
102
|
+
* hook still has to resolve it, and paying a whole-history parse for that
|
|
103
|
+
* answer is what made a stranded epoch cost seconds and hundreds of megabytes
|
|
104
|
+
* per process. The tamper coverage is the active witness's, unchanged: the
|
|
105
|
+
* authenticated payload names the storage version, so a corrupt append, a
|
|
106
|
+
* same-size rewrite, a changed sealed segment, and a replaced inode all miss
|
|
107
|
+
* and fall back to canonical validation. Because `control_state` is inside the
|
|
108
|
+
* authenticated payload, an active witness can never answer here and a
|
|
109
|
+
* candidate witness can never answer the active gate.
|
|
110
|
+
*/
|
|
111
|
+
export function candidateControlWitnessMatchesV3(
|
|
112
|
+
coordRoot: string,
|
|
113
|
+
binding: CandidateControlWitnessBindingV3,
|
|
114
|
+
): boolean {
|
|
115
|
+
return witnessMatchesV3(coordRoot, "candidate", (storage, checkpointDigest) =>
|
|
116
|
+
candidateWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
117
|
+
);
|
|
74
118
|
}
|
|
75
119
|
|
|
76
120
|
/**
|
|
@@ -83,17 +127,31 @@ export function publishActiveControlWitnessV3(
|
|
|
83
127
|
validatedStorage: EventV3AuthorityStorageVersionV3,
|
|
84
128
|
checkpoint: EventV3AppendValidationCheckpointV3,
|
|
85
129
|
): boolean {
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
130
|
+
return publishControlWitnessV3(
|
|
131
|
+
coordRoot,
|
|
132
|
+
validatedStorage,
|
|
133
|
+
checkpoint,
|
|
134
|
+
(storage, checkpointDigest) => activeWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
135
|
+
);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The candidate equivalent, published on the same terms: only when the storage
|
|
140
|
+
* the caller validated is still current, and silently skipped otherwise so the
|
|
141
|
+
* next read keeps the canonical full-scan fallback.
|
|
142
|
+
*/
|
|
143
|
+
export function publishCandidateControlWitnessV3(
|
|
144
|
+
coordRoot: string,
|
|
145
|
+
binding: CandidateControlWitnessBindingV3,
|
|
146
|
+
validatedStorage: EventV3AuthorityStorageVersionV3,
|
|
147
|
+
checkpoint: EventV3AppendValidationCheckpointV3,
|
|
148
|
+
): boolean {
|
|
149
|
+
return publishControlWitnessV3(
|
|
150
|
+
coordRoot,
|
|
151
|
+
validatedStorage,
|
|
152
|
+
checkpoint,
|
|
153
|
+
(storage, checkpointDigest) => candidateWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
154
|
+
);
|
|
97
155
|
}
|
|
98
156
|
|
|
99
157
|
/**
|
|
@@ -155,21 +213,87 @@ export function advanceControlWitnessV3(
|
|
|
155
213
|
}
|
|
156
214
|
}
|
|
157
215
|
|
|
158
|
-
|
|
216
|
+
type WitnessPayloadBuilderV3 = (
|
|
217
|
+
storage: EventV3AuthorityStorageVersionV3,
|
|
218
|
+
checkpointDigest: `sha256:${string}`,
|
|
219
|
+
) => EventV3ControlWitnessPayload;
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* One matcher for both control states. The witness on disk must authenticate,
|
|
223
|
+
* carry the requested `control_state`, and canonicalize identically to the
|
|
224
|
+
* payload this exact binding would produce over the storage observed both
|
|
225
|
+
* before and after the read.
|
|
226
|
+
*/
|
|
227
|
+
function witnessMatchesV3(
|
|
228
|
+
coordRoot: string,
|
|
229
|
+
controlState: EventV3ControlWitnessControlStateV3,
|
|
230
|
+
build: WitnessPayloadBuilderV3,
|
|
231
|
+
): boolean {
|
|
232
|
+
try {
|
|
233
|
+
const before = eventV3AuthorityStorageVersionV3(coordRoot);
|
|
234
|
+
const witness = readAuthenticatedWitnessV3(coordRoot);
|
|
235
|
+
if (!witness || witness.payload.control_state !== controlState) return false;
|
|
236
|
+
const expected = build(before, witness.payload.checkpoint_digest);
|
|
237
|
+
if (canonicalJsonV3(witness.payload) !== canonicalJsonV3(expected)) return false;
|
|
238
|
+
const after = eventV3AuthorityStorageVersionV3(coordRoot);
|
|
239
|
+
return sameStorageVersion(before, after);
|
|
240
|
+
} catch {
|
|
241
|
+
return false;
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
function publishControlWitnessV3(
|
|
246
|
+
coordRoot: string,
|
|
247
|
+
validatedStorage: EventV3AuthorityStorageVersionV3,
|
|
248
|
+
checkpoint: EventV3AppendValidationCheckpointV3,
|
|
249
|
+
build: WitnessPayloadBuilderV3,
|
|
250
|
+
): boolean {
|
|
251
|
+
try {
|
|
252
|
+
const current = eventV3AuthorityStorageVersionV3(coordRoot);
|
|
253
|
+
if (!sameStorageVersion(validatedStorage, current)) return false;
|
|
254
|
+
return publishWitnessV3(coordRoot, build(current, checkpointDigestV3(checkpoint)), checkpoint);
|
|
255
|
+
} catch {
|
|
256
|
+
return false;
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function activeWitnessPayloadV3(
|
|
159
261
|
binding: ActiveControlWitnessBindingV3,
|
|
160
262
|
storage: EventV3AuthorityStorageVersionV3,
|
|
161
263
|
checkpointDigest: `sha256:${string}`,
|
|
162
|
-
):
|
|
264
|
+
): EventV3ActiveControlWitnessPayloadV3 {
|
|
265
|
+
return {
|
|
266
|
+
...commonWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
267
|
+
control_state: "active",
|
|
268
|
+
activation_id: binding.activation.activation_id,
|
|
269
|
+
activation_event_id: binding.activation.event.event_id as `evt_${string}`,
|
|
270
|
+
activation_manifest_digest: sha256V3(canonicalJsonV3(binding.activation)),
|
|
271
|
+
};
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
function candidateWitnessPayloadV3(
|
|
275
|
+
binding: CandidateControlWitnessBindingV3,
|
|
276
|
+
storage: EventV3AuthorityStorageVersionV3,
|
|
277
|
+
checkpointDigest: `sha256:${string}`,
|
|
278
|
+
): EventV3CandidateControlWitnessPayloadV3 {
|
|
279
|
+
return {
|
|
280
|
+
...commonWitnessPayloadV3(binding, storage, checkpointDigest),
|
|
281
|
+
control_state: "candidate",
|
|
282
|
+
};
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function commonWitnessPayloadV3(
|
|
286
|
+
binding: CandidateControlWitnessBindingV3,
|
|
287
|
+
storage: EventV3AuthorityStorageVersionV3,
|
|
288
|
+
checkpointDigest: `sha256:${string}`,
|
|
289
|
+
): EventV3ControlWitnessPayloadCommonV3 {
|
|
163
290
|
const scope = binding.genesis.event.scope as { root_id: `root_${string}` };
|
|
164
291
|
return {
|
|
165
292
|
format: "harnery-event-v3-control-witness",
|
|
166
|
-
format_version:
|
|
293
|
+
format_version: 2,
|
|
167
294
|
genesis_id: binding.genesis.event.payload.genesis_id as `gex_${string}`,
|
|
168
|
-
activation_id: binding.activation.activation_id,
|
|
169
295
|
genesis_event_id: binding.genesis.event.event_id as `evt_${string}`,
|
|
170
|
-
activation_event_id: binding.activation.event.event_id as `evt_${string}`,
|
|
171
296
|
genesis_manifest_digest: sha256V3(canonicalJsonV3(binding.genesis)),
|
|
172
|
-
activation_manifest_digest: sha256V3(canonicalJsonV3(binding.activation)),
|
|
173
297
|
candidate_manifest_digest: binding.candidate_manifest_digest,
|
|
174
298
|
privacy_key_epoch: binding.genesis.profile.privacy_key_epoch,
|
|
175
299
|
root_id: scope.root_id,
|
|
@@ -265,12 +389,14 @@ function parseWitnessV3(value: unknown): EventV3ControlWitness {
|
|
|
265
389
|
throw new Error("control witness envelope is invalid");
|
|
266
390
|
}
|
|
267
391
|
const payload = object(envelope.payload);
|
|
268
|
-
const
|
|
269
|
-
|
|
270
|
-
"
|
|
271
|
-
|
|
392
|
+
const controlState = payload.control_state;
|
|
393
|
+
if (controlState !== "active" && controlState !== "candidate") {
|
|
394
|
+
throw new Error("control witness control state is invalid");
|
|
395
|
+
}
|
|
396
|
+
const commonPayloadKeys = [
|
|
272
397
|
"candidate_manifest_digest",
|
|
273
398
|
"checkpoint_digest",
|
|
399
|
+
"control_state",
|
|
274
400
|
"format",
|
|
275
401
|
"format_version",
|
|
276
402
|
"genesis_event_id",
|
|
@@ -280,6 +406,10 @@ function parseWitnessV3(value: unknown): EventV3ControlWitness {
|
|
|
280
406
|
"root_id",
|
|
281
407
|
"storage",
|
|
282
408
|
];
|
|
409
|
+
const expectedPayloadKeys =
|
|
410
|
+
controlState === "active"
|
|
411
|
+
? [...commonPayloadKeys, "activation_event_id", "activation_id", "activation_manifest_digest"]
|
|
412
|
+
: commonPayloadKeys;
|
|
283
413
|
if (Object.keys(payload).sort().join("\0") !== expectedPayloadKeys.sort().join("\0")) {
|
|
284
414
|
throw new Error("control witness payload shape is invalid");
|
|
285
415
|
}
|
|
@@ -289,13 +419,14 @@ function parseWitnessV3(value: unknown): EventV3ControlWitness {
|
|
|
289
419
|
}
|
|
290
420
|
if (
|
|
291
421
|
payload.format !== "harnery-event-v3-control-witness" ||
|
|
292
|
-
payload.format_version !==
|
|
422
|
+
payload.format_version !== 2 ||
|
|
293
423
|
!token(payload.genesis_id, "gex_") ||
|
|
294
|
-
!token(payload.activation_id, "act_") ||
|
|
295
424
|
!token(payload.genesis_event_id, "evt_") ||
|
|
296
|
-
|
|
425
|
+
(controlState === "active" &&
|
|
426
|
+
(!token(payload.activation_id, "act_") ||
|
|
427
|
+
!token(payload.activation_event_id, "evt_") ||
|
|
428
|
+
!digest(payload.activation_manifest_digest))) ||
|
|
297
429
|
!digest(payload.genesis_manifest_digest) ||
|
|
298
|
-
!digest(payload.activation_manifest_digest) ||
|
|
299
430
|
!digest(payload.candidate_manifest_digest) ||
|
|
300
431
|
!digest(payload.checkpoint_digest) ||
|
|
301
432
|
!token(payload.privacy_key_epoch, "pep_") ||
|
|
@@ -3,7 +3,12 @@ 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 {
|
|
6
|
+
import {
|
|
7
|
+
activeControlWitnessMatchesV3,
|
|
8
|
+
candidateControlWitnessMatchesV3,
|
|
9
|
+
publishActiveControlWitnessV3,
|
|
10
|
+
publishCandidateControlWitnessV3,
|
|
11
|
+
} from "./control-witness.ts";
|
|
7
12
|
import { EVENT_V3_SCHEMA_DIGEST } from "./generated.ts";
|
|
8
13
|
import { activationIdV3, eventIdV3, genesisIdV3 } from "./ids.ts";
|
|
9
14
|
import {
|
|
@@ -275,6 +280,19 @@ export function readEventV3ControlState(coordRoot: string): EventV3ControlState
|
|
|
275
280
|
candidate_manifest_digest: candidateDigest,
|
|
276
281
|
};
|
|
277
282
|
}
|
|
283
|
+
// A candidate epoch answers from its own witness on the same terms. The
|
|
284
|
+
// absent activation manifest is part of the question, so the fast path is
|
|
285
|
+
// only taken when none is published: the moment one appears, this read goes
|
|
286
|
+
// back through canonical validation and can report the repairable window.
|
|
287
|
+
if (
|
|
288
|
+
!hasActivation &&
|
|
289
|
+
candidateControlWitnessMatchesV3(coordRoot, {
|
|
290
|
+
genesis,
|
|
291
|
+
candidate_manifest_digest: candidateDigest,
|
|
292
|
+
})
|
|
293
|
+
) {
|
|
294
|
+
return { state: "candidate", genesis, candidate_manifest_digest: candidateDigest };
|
|
295
|
+
}
|
|
278
296
|
const storageBeforeValidation = eventV3AuthorityStorageVersionV3(coordRoot);
|
|
279
297
|
const ledger = readControlLedger(coordRoot);
|
|
280
298
|
if (!ledger.complete) {
|
|
@@ -294,7 +312,21 @@ export function readEventV3ControlState(coordRoot: string): EventV3ControlState
|
|
|
294
312
|
if (ledger.events.some(({ event }) => event.event_type === "ledger.activated")) {
|
|
295
313
|
return { state: "invalid", reason: "activation_event_without_manifest" };
|
|
296
314
|
}
|
|
297
|
-
|
|
315
|
+
const candidate: Extract<EventV3ControlState, { state: "candidate" }> = {
|
|
316
|
+
state: "candidate",
|
|
317
|
+
genesis,
|
|
318
|
+
candidate_manifest_digest: candidateDigest,
|
|
319
|
+
};
|
|
320
|
+
const candidateCheckpoint = readEventV3AppendValidationCheckpointV3(coordRoot);
|
|
321
|
+
if (candidateCheckpoint) {
|
|
322
|
+
publishCandidateControlWitnessV3(
|
|
323
|
+
coordRoot,
|
|
324
|
+
candidate,
|
|
325
|
+
storageBeforeValidation,
|
|
326
|
+
candidateCheckpoint,
|
|
327
|
+
);
|
|
328
|
+
}
|
|
329
|
+
return candidate;
|
|
298
330
|
}
|
|
299
331
|
|
|
300
332
|
const activationResult =
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
export { EVENT_ADAPTER_IDS_V3, type EventAdapterIdV3 } from "./adapter-id.ts";
|
|
1
2
|
export {
|
|
2
3
|
type SchemaAdvanceEligibilityV3,
|
|
3
4
|
validateAdditiveSchemaAdvanceV3,
|
|
@@ -45,10 +46,12 @@ export {
|
|
|
45
46
|
ADAPTER_CAPABILITY_PROFILES_V3,
|
|
46
47
|
ADAPTER_WAIT_KINDS_V3,
|
|
47
48
|
type AdapterCapabilityProfileV3,
|
|
49
|
+
type AdapterDurationCapabilityV3,
|
|
48
50
|
type AdapterSignalV3,
|
|
49
51
|
type AdapterWaitKindV3,
|
|
50
52
|
adapterCapabilityProfileDigestV3,
|
|
51
53
|
adapterCapabilityProfileV3,
|
|
54
|
+
adapterDurationSupportV3,
|
|
52
55
|
adapterSignalSupportV3,
|
|
53
56
|
adapterWaitCoverageMatrixV3,
|
|
54
57
|
adapterWaitKindSupportV3,
|
|
@@ -121,23 +121,40 @@ export function tryWriteLiveDisplayV3(
|
|
|
121
121
|
}
|
|
122
122
|
}
|
|
123
123
|
|
|
124
|
-
/**
|
|
124
|
+
/**
|
|
125
|
+
* Return every unexpired live-display row across generations.
|
|
126
|
+
*
|
|
127
|
+
* A generation file whose last write is older than the hard TTL cannot hold a
|
|
128
|
+
* live row, so it is skipped on the stat alone. Without that guard a directory
|
|
129
|
+
* that has not been swept turns every read into a parse of days of residue.
|
|
130
|
+
*/
|
|
125
131
|
export function listLiveDisplayV3(
|
|
126
132
|
coordRoot: string,
|
|
127
133
|
now: () => Date = () => new Date(),
|
|
128
134
|
): LiveDisplayRowV3[] {
|
|
129
135
|
const root = liveRoot(coordRoot);
|
|
130
136
|
if (!existsSync(root)) return [];
|
|
137
|
+
const nowMs = now().getTime();
|
|
131
138
|
const rows: LiveDisplayRowV3[] = [];
|
|
132
139
|
for (const name of readdirSync(root)) {
|
|
133
140
|
if (!name.endsWith(".ndjson")) continue;
|
|
134
141
|
const generationId = name.slice(0, -".ndjson".length);
|
|
135
142
|
if (!GENERATION_PATTERN.test(generationId)) continue;
|
|
143
|
+
if (fileHardExpiredV3(join(root, name), nowMs)) continue;
|
|
136
144
|
rows.push(...readLiveDisplayV3(coordRoot, generationId, now));
|
|
137
145
|
}
|
|
138
146
|
return rows;
|
|
139
147
|
}
|
|
140
148
|
|
|
149
|
+
/** True when the file's last write predates the hard TTL; a missing file counts as expired. */
|
|
150
|
+
function fileHardExpiredV3(path: string, nowMs: number): boolean {
|
|
151
|
+
try {
|
|
152
|
+
return statSync(path).mtimeMs + HARD_MAX_TTL_MS <= nowMs;
|
|
153
|
+
} catch {
|
|
154
|
+
return true;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
141
158
|
/** Return only unexpired, structurally valid rows. Expiry is enforced before cleanup. */
|
|
142
159
|
export function readLiveDisplayV3(
|
|
143
160
|
coordRoot: string,
|
|
@@ -180,10 +197,11 @@ export function janitorLiveDisplayV3(
|
|
|
180
197
|
if (!name.endsWith(".ndjson")) continue;
|
|
181
198
|
scanned += 1;
|
|
182
199
|
const path = join(root, basename(name));
|
|
183
|
-
const
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
200
|
+
const hardExpired = fileHardExpiredV3(path, nowMs);
|
|
201
|
+
const visible =
|
|
202
|
+
!hardExpired && GENERATION_PATTERN.test(name.slice(0, -".ndjson".length))
|
|
203
|
+
? readLiveDisplayV3(coordRoot, name.slice(0, -".ndjson".length), now)
|
|
204
|
+
: [];
|
|
187
205
|
if (visible.length === 0 || hardExpired) {
|
|
188
206
|
rmSync(path, { force: true });
|
|
189
207
|
removed += 1;
|
|
@@ -1,6 +1,10 @@
|
|
|
1
1
|
import type { Adapter } from "../../adapter.ts";
|
|
2
2
|
import type { ParsedPayload } from "../../hooks/adapter/parse.ts";
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
refreshIncompatibleEventLedgerV3,
|
|
5
|
+
repairStrandedEventLedgerV3Candidate,
|
|
6
|
+
rotateOversizedEventLedgerV3,
|
|
7
|
+
} from "./bootstrap.ts";
|
|
4
8
|
import type { EventV3 } from "./contract.ts";
|
|
5
9
|
import { readEventV3ControlState } from "./control.ts";
|
|
6
10
|
import { repairEventV3ControlPair } from "./control-writer.ts";
|
|
@@ -54,7 +58,15 @@ export function resolveLiveEventLedgerRouteV3(coordRoot: string): LiveEventLedge
|
|
|
54
58
|
};
|
|
55
59
|
}
|
|
56
60
|
}
|
|
57
|
-
if (control.state === "
|
|
61
|
+
if (control.state === "candidate") {
|
|
62
|
+
// An epoch is created and activated as one locked step, so a candidate on
|
|
63
|
+
// this boundary is a stranded epoch: a crashed or failed activation that
|
|
64
|
+
// every later hook would otherwise keep serving with a candidate-only
|
|
65
|
+
// write gate. Finish it here. A live bootstrap lease or any other refusal
|
|
66
|
+
// leaves the candidate serving and the next boundary retries.
|
|
67
|
+
control = repairStrandedEventLedgerV3Candidate(coordRoot).control;
|
|
68
|
+
}
|
|
69
|
+
if (control.state === "active" || control.state === "candidate") {
|
|
58
70
|
// Bound the epoch every producer must re-validate: an oversized active
|
|
59
71
|
// segment rotates into the archive here, on the shared route boundary.
|
|
60
72
|
// Rotation failure never blocks recording; the current epoch stays live.
|