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
|
@@ -12,10 +12,9 @@ import { randomUUID } from "node:crypto";
|
|
|
12
12
|
import { existsSync, lstatSync, mkdirSync, readdirSync, readFileSync, renameSync, rmSync, writeFileSync, } from "node:fs";
|
|
13
13
|
import { basename, dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
|
|
14
14
|
import { readLiveCoordinationRow } from "../agents/state/live-coordination-view.js";
|
|
15
|
-
import { artifactDefaultRetentionDays } from "../config.js";
|
|
16
|
-
|
|
17
|
-
export
|
|
18
|
-
export const ARTIFACT_SCHEMA_VERSION = 1;
|
|
15
|
+
import { artifactAutoCleanEnabled, artifactAutoCleanIntervalHours, artifactDefaultRetentionDays, } from "../config.js";
|
|
16
|
+
import { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.js";
|
|
17
|
+
export { ARTIFACT_MANIFEST, ARTIFACT_SCHEMA_VERSION, ARTIFACTS_DIR } from "./constants.js";
|
|
19
18
|
export function artifactsRoot(repoRoot) {
|
|
20
19
|
return join(resolve(repoRoot), ARTIFACTS_DIR);
|
|
21
20
|
}
|
|
@@ -160,6 +159,51 @@ export function cleanArtifacts(repoRoot, opts = {}) {
|
|
|
160
159
|
}
|
|
161
160
|
});
|
|
162
161
|
}
|
|
162
|
+
/** Sibling of the artifacts root so the stamp never appears in the inventory scan. */
|
|
163
|
+
const AUTO_CLEAN_STAMP = ".harnery/artifacts-auto-clean.json";
|
|
164
|
+
/**
|
|
165
|
+
* Throttled expired-artifact sweep, fired as a SessionStart effect.
|
|
166
|
+
*
|
|
167
|
+
* Retention was previously enforced only when someone remembered to run
|
|
168
|
+
* `artifacts clean --yes`, so expired workspaces accumulated indefinitely on
|
|
169
|
+
* busy hosts. This runs the exact same guarded deletion (only
|
|
170
|
+
* `managed-expired` entries, each re-classified immediately before removal;
|
|
171
|
+
* unmanaged and legacy directories are never touched) at most once per
|
|
172
|
+
* interval (default 24h), claim-first via a stamp file so concurrent session
|
|
173
|
+
* starts do not double-sweep. Disable with `artifacts.auto_clean: false` or
|
|
174
|
+
* `HARNERY_ARTIFACT_AUTO_CLEAN=0`.
|
|
175
|
+
*/
|
|
176
|
+
export function autoCleanArtifacts(repoRoot, opts = {}) {
|
|
177
|
+
const now = opts.now ?? new Date();
|
|
178
|
+
assertValidDate(now, "now");
|
|
179
|
+
if (!existsSync(artifactsRoot(repoRoot))) {
|
|
180
|
+
return { ran: false, reason: "no-root", deleted: 0, bytes: 0 };
|
|
181
|
+
}
|
|
182
|
+
if (!artifactAutoCleanEnabled(repoRoot)) {
|
|
183
|
+
return { ran: false, reason: "disabled", deleted: 0, bytes: 0 };
|
|
184
|
+
}
|
|
185
|
+
const stampPath = join(resolve(repoRoot), AUTO_CLEAN_STAMP);
|
|
186
|
+
const intervalMs = artifactAutoCleanIntervalHours() * 60 * 60 * 1000;
|
|
187
|
+
try {
|
|
188
|
+
const stamp = JSON.parse(readFileSync(stampPath, "utf8"));
|
|
189
|
+
const last = Date.parse(stamp.last_run_at ?? "");
|
|
190
|
+
if (Number.isFinite(last) && now.getTime() - last < intervalMs) {
|
|
191
|
+
return { ran: false, reason: "fresh", deleted: 0, bytes: 0 };
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch {
|
|
195
|
+
// Missing or unreadable stamp: sweep now and write a fresh one.
|
|
196
|
+
}
|
|
197
|
+
// Claim first: a crash mid-sweep costs one skipped interval, while claiming
|
|
198
|
+
// after would let two concurrent session starts both walk the store.
|
|
199
|
+
writeFileSync(stampPath, `${JSON.stringify({ last_run_at: now.toISOString() }, null, 2)}\n`);
|
|
200
|
+
const rows = cleanArtifacts(repoRoot, { yes: true, now });
|
|
201
|
+
const deletedRows = rows.filter((row) => row.action === "deleted");
|
|
202
|
+
const deleted = deletedRows.length;
|
|
203
|
+
const bytes = deletedRows.reduce((sum, row) => sum + (row.bytes ?? 0), 0);
|
|
204
|
+
writeFileSync(stampPath, `${JSON.stringify({ last_run_at: now.toISOString(), deleted, bytes }, null, 2)}\n`);
|
|
205
|
+
return { ran: true, reason: "swept", deleted, bytes };
|
|
206
|
+
}
|
|
163
207
|
export function resolveArtifactRef(repoRoot, ref) {
|
|
164
208
|
const root = artifactsRoot(repoRoot);
|
|
165
209
|
const candidate = isAbsolute(ref) ? resolve(ref) : resolve(root, ref);
|
|
@@ -207,15 +251,21 @@ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
|
|
|
207
251
|
}
|
|
208
252
|
const manifest = parsed.manifest;
|
|
209
253
|
const bytes = safeTreeSize(path);
|
|
254
|
+
const lastModifiedMs = safeTreeLastModified(path, now);
|
|
255
|
+
const retentionAnchorMs = Date.parse(manifest.retention.renewed_at ?? manifest.created_at);
|
|
256
|
+
const retentionWindowMs = Date.parse(manifest.retention.expires_at) - retentionAnchorMs;
|
|
257
|
+
const effectiveLastModifiedMs = Math.max(retentionAnchorMs, lastModifiedMs ?? 0);
|
|
258
|
+
const effectiveExpiresAt = new Date(effectiveLastModifiedMs + retentionWindowMs).toISOString();
|
|
210
259
|
const base = rowFor(path, name, repoRoot, "managed-current", "retention has not expired", bytes);
|
|
211
260
|
Object.assign(base, {
|
|
212
261
|
artifact_id: manifest.artifact_id,
|
|
213
262
|
slug: manifest.slug,
|
|
214
263
|
created_at: manifest.created_at,
|
|
215
|
-
|
|
264
|
+
last_modified_at: new Date(effectiveLastModifiedMs).toISOString(),
|
|
265
|
+
expires_at: effectiveExpiresAt,
|
|
216
266
|
owner_instance_id: manifest.created_by?.instance_id ?? null,
|
|
217
267
|
});
|
|
218
|
-
if (base.bytes === null) {
|
|
268
|
+
if (base.bytes === null || lastModifiedMs === null) {
|
|
219
269
|
return {
|
|
220
270
|
...base,
|
|
221
271
|
classification: "unknown",
|
|
@@ -250,12 +300,12 @@ function classifyArtifactPath(repoRoot, path, now, freshnessSeconds) {
|
|
|
250
300
|
};
|
|
251
301
|
}
|
|
252
302
|
}
|
|
253
|
-
if (Date.parse(
|
|
303
|
+
if (Date.parse(effectiveExpiresAt) > now.getTime())
|
|
254
304
|
return base;
|
|
255
305
|
return {
|
|
256
306
|
...base,
|
|
257
307
|
classification: "managed-expired",
|
|
258
|
-
reason: `retention expired at ${
|
|
308
|
+
reason: `retention expired at ${effectiveExpiresAt}`,
|
|
259
309
|
action: "would-delete",
|
|
260
310
|
};
|
|
261
311
|
}
|
|
@@ -291,6 +341,13 @@ function readManifest(path) {
|
|
|
291
341
|
if (!m.retention || typeof m.retention !== "object" || !validIso(m.retention.expires_at)) {
|
|
292
342
|
return { ok: false, reason: "invalid retention.expires_at" };
|
|
293
343
|
}
|
|
344
|
+
if (m.retention.renewed_at !== undefined && !validIso(m.retention.renewed_at)) {
|
|
345
|
+
return { ok: false, reason: "invalid retention.renewed_at" };
|
|
346
|
+
}
|
|
347
|
+
const retentionAnchor = Date.parse(m.retention.renewed_at ?? m.created_at);
|
|
348
|
+
if (Date.parse(m.retention.expires_at) <= retentionAnchor) {
|
|
349
|
+
return { ok: false, reason: "retention.expires_at must follow its retention anchor" };
|
|
350
|
+
}
|
|
294
351
|
if (m.released_at !== undefined && !validIso(m.released_at)) {
|
|
295
352
|
return { ok: false, reason: "invalid released_at" };
|
|
296
353
|
}
|
|
@@ -358,6 +415,36 @@ function safeTreeSize(path) {
|
|
|
358
415
|
return null;
|
|
359
416
|
}
|
|
360
417
|
}
|
|
418
|
+
/**
|
|
419
|
+
* Return the newest filesystem change in a managed tree without following
|
|
420
|
+
* symlinks. A small future tolerance protects a write racing the inventory
|
|
421
|
+
* scan; timestamps farther ahead are ignored as clock-skewed metadata.
|
|
422
|
+
*/
|
|
423
|
+
function safeTreeLastModified(path, now) {
|
|
424
|
+
const nowMs = now.getTime();
|
|
425
|
+
const futureToleranceMs = 5 * 60 * 1000;
|
|
426
|
+
try {
|
|
427
|
+
const st = lstatSync(path);
|
|
428
|
+
let latest = 0;
|
|
429
|
+
for (const timestamp of [st.mtimeMs, st.ctimeMs]) {
|
|
430
|
+
if (Number.isFinite(timestamp) && timestamp <= nowMs + futureToleranceMs) {
|
|
431
|
+
latest = Math.max(latest, Math.min(timestamp, nowMs));
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
if (st.isSymbolicLink() || !st.isDirectory())
|
|
435
|
+
return latest;
|
|
436
|
+
for (const child of readdirSync(path)) {
|
|
437
|
+
const childLatest = safeTreeLastModified(join(path, child), now);
|
|
438
|
+
if (childLatest === null)
|
|
439
|
+
return null;
|
|
440
|
+
latest = Math.max(latest, childLatest);
|
|
441
|
+
}
|
|
442
|
+
return latest;
|
|
443
|
+
}
|
|
444
|
+
catch {
|
|
445
|
+
return null;
|
|
446
|
+
}
|
|
447
|
+
}
|
|
361
448
|
function rowFor(path, name, repoRoot, classification, reason, bytes = safeTreeSize(path)) {
|
|
362
449
|
return {
|
|
363
450
|
name,
|
|
@@ -370,6 +457,7 @@ function rowFor(path, name, repoRoot, classification, reason, bytes = safeTreeSi
|
|
|
370
457
|
artifact_id: null,
|
|
371
458
|
slug: null,
|
|
372
459
|
created_at: null,
|
|
460
|
+
last_modified_at: null,
|
|
373
461
|
expires_at: null,
|
|
374
462
|
owner_instance_id: null,
|
|
375
463
|
};
|
package/dist/core/config.d.ts
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* 2. `<project-root>/.harnery/config.jsonc` — project override (authoritative)
|
|
8
8
|
*
|
|
9
9
|
* Fields owned here: `binName` (host CLI name for agent-facing strings),
|
|
10
|
-
* `hooksSetupHint`, `agents`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
|
|
11
|
-
* `coord` (heartbeat freshness), `
|
|
10
|
+
* `hooksSetupHint`, `agents`, `instructions`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
|
|
11
|
+
* `coord` (heartbeat freshness), `logs` (structured-log storage budgets),
|
|
12
|
+
* `artifacts` (working-file retention),
|
|
12
13
|
* `backup` (restic repo/password/prune policy), `sync` (rclone
|
|
13
14
|
* remote/prefix), and `web` (dashboard port) sections. The `files` deny/override section
|
|
14
15
|
* is parsed separately by `web/lib/files.ts`.
|
|
@@ -17,12 +18,14 @@
|
|
|
17
18
|
* documents its own precedence). Dependency-free (no jsonc npm dep) so it runs on
|
|
18
19
|
* both Bun and Node, and so the ADR-009 vendored copies stay portable.
|
|
19
20
|
*/
|
|
21
|
+
export { DEFAULT_WEB_PORT } from "../lib/local-file-url.js";
|
|
22
|
+
export { DEFAULT_EVENT_LEDGER_ROTATE_ACTIVE_BYTES } from "./events/v3/rotation-config.js";
|
|
20
23
|
/** The standalone CLI's bin name: the resolution floor when nothing else is set. */
|
|
21
24
|
export declare const DEFAULT_BIN_NAME = "harn";
|
|
22
25
|
/** Heartbeat-freshness default (seconds): the sweep window when nothing overrides it. */
|
|
23
26
|
export declare const DEFAULT_FRESHNESS_SECS = 600;
|
|
24
|
-
/**
|
|
25
|
-
export declare const
|
|
27
|
+
/** Keep a fresh host reminder bounded to one short prompt-context line. */
|
|
28
|
+
export declare const MAX_HOST_PROMPT_REMINDER_CHARS = 500;
|
|
26
29
|
export interface SessionFinalizationConfig {
|
|
27
30
|
archiveGraceSeconds: number;
|
|
28
31
|
idleObserveSeconds: number;
|
|
@@ -44,6 +47,24 @@ export interface CoordRunQualityConfigSource {
|
|
|
44
47
|
/** Stable digest seed that contains no config values when parsing failed. */
|
|
45
48
|
digest_seed: unknown;
|
|
46
49
|
}
|
|
50
|
+
export interface LogStorageConfigLayerSource {
|
|
51
|
+
layer: "user" | "project";
|
|
52
|
+
value: unknown;
|
|
53
|
+
invalid: boolean;
|
|
54
|
+
/** Stable file signature for bounded diagnostics without retaining values. */
|
|
55
|
+
signature: string | null;
|
|
56
|
+
}
|
|
57
|
+
export interface LogStorageConfigSource {
|
|
58
|
+
layers: readonly [LogStorageConfigLayerSource, LogStorageConfigLayerSource];
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Raw user and project `logs.storage` layers with their origin intact.
|
|
62
|
+
*
|
|
63
|
+
* Storage retention validates these as one fail-closed unit. It cannot use the
|
|
64
|
+
* ordinary merged reader because commands must explain whether each effective
|
|
65
|
+
* scalar came from a user class, user family, project class, or project family.
|
|
66
|
+
*/
|
|
67
|
+
export declare function logStorageConfigSource(root: string): LogStorageConfigSource;
|
|
47
68
|
/**
|
|
48
69
|
* Effective user-plus-project `coord.run_quality` value with parse diagnostics.
|
|
49
70
|
* The ordinary config reader stays fail-soft; this one lets the guard visibly
|
|
@@ -76,6 +97,17 @@ export declare function pinnedBinName(projectRoot: string): string | null;
|
|
|
76
97
|
* `coordRoot` is resolved via `findCoordRoot()` when not passed.
|
|
77
98
|
*/
|
|
78
99
|
export declare function resolveHooksSetupHint(coordRoot?: string | null): string | null;
|
|
100
|
+
/**
|
|
101
|
+
* One project-owned reminder that a supported prompt hook can place immediately
|
|
102
|
+
* before a model response. The value is deliberately project-only: host policy
|
|
103
|
+
* must not follow the user-global config into unrelated repositories. It is
|
|
104
|
+
* emitted directly from config and never copied into coordination state.
|
|
105
|
+
*
|
|
106
|
+
* The reminder must be one non-empty line of at most 500 characters. Invalid
|
|
107
|
+
* values fail closed to no reminder so a malformed optional setting cannot
|
|
108
|
+
* break the prompt hook.
|
|
109
|
+
*/
|
|
110
|
+
export declare function hostPromptReminder(coordRoot?: string | null): string | null;
|
|
79
111
|
/**
|
|
80
112
|
* Whether the host requires the guarded Git check at the end of tool-using
|
|
81
113
|
* turns. Default false: Harnery exposes `agents status --end-turn` as a capability
|
|
@@ -142,6 +174,17 @@ export declare function presenceRelayUrl(coordRoot?: string | null): string | nu
|
|
|
142
174
|
* `coordRoot` is resolved via `findCoordRoot()` when not passed.
|
|
143
175
|
*/
|
|
144
176
|
export declare function coordFreshnessSeconds(coordRoot?: string | null): number;
|
|
177
|
+
/**
|
|
178
|
+
* Active-segment byte size at which the V3 event ledger rotates to a fresh
|
|
179
|
+
* epoch. Every reader validates the complete epoch, so an unbounded active
|
|
180
|
+
* segment makes each cold read (one per hook process) scale with all history.
|
|
181
|
+
* Precedence:
|
|
182
|
+
* 1. `HARNERY_EVENT_V3_ROTATE_ACTIVE_BYTES` env
|
|
183
|
+
* 2. `.harnery/config.jsonc` `events.rotate_active_bytes`
|
|
184
|
+
* 3. 33554432 (32 MiB)
|
|
185
|
+
* `0` (or a negative value) disables automatic rotation.
|
|
186
|
+
*/
|
|
187
|
+
export declare function eventLedgerRotateActiveBytes(coordRoot?: string | null): number;
|
|
145
188
|
/**
|
|
146
189
|
* Resolve the standalone dashboard port.
|
|
147
190
|
*
|
|
@@ -157,6 +200,21 @@ export declare function sessionFinalizationConfig(coordRoot?: string | null): Se
|
|
|
157
200
|
* `artifacts.default_retention_days` -> 3 days.
|
|
158
201
|
*/
|
|
159
202
|
export declare function artifactDefaultRetentionDays(coordRoot?: string | null): number;
|
|
203
|
+
/**
|
|
204
|
+
* Whether the daily SessionStart sweep of expired artifact workspaces runs.
|
|
205
|
+
* Precedence: `HARNERY_ARTIFACT_AUTO_CLEAN` (0/false disables) ->
|
|
206
|
+
* `artifacts.auto_clean` -> enabled. The sweep only ever deletes
|
|
207
|
+
* `managed-expired` entries via the same guarded classifier as
|
|
208
|
+
* `artifacts clean --yes`.
|
|
209
|
+
*/
|
|
210
|
+
export declare function artifactAutoCleanEnabled(coordRoot?: string | null): boolean;
|
|
211
|
+
/**
|
|
212
|
+
* Sweep cadence in hours. Env-only (`HARNERY_ARTIFACT_AUTO_CLEAN_INTERVAL_HOURS`,
|
|
213
|
+
* mainly for tests): the cadence is an implementation detail, not policy, and
|
|
214
|
+
* retention itself is quantized in whole days, so the 24h default is not a
|
|
215
|
+
* config surface.
|
|
216
|
+
*/
|
|
217
|
+
export declare function artifactAutoCleanIntervalHours(): number;
|
|
160
218
|
/** Resolved `harn backup` defaults (restic repo/password + prune policy). */
|
|
161
219
|
export interface BackupConfig {
|
|
162
220
|
repo: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/core/config.ts"],"names":[],"mappings":"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"}
|
package/dist/core/config.js
CHANGED
|
@@ -7,8 +7,9 @@
|
|
|
7
7
|
* 2. `<project-root>/.harnery/config.jsonc` — project override (authoritative)
|
|
8
8
|
*
|
|
9
9
|
* Fields owned here: `binName` (host CLI name for agent-facing strings),
|
|
10
|
-
* `hooksSetupHint`, `agents`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
|
|
11
|
-
* `coord` (heartbeat freshness), `
|
|
10
|
+
* `hooksSetupHint`, `agents`, `instructions`, `tools`, `workflow`, `skills`, `presence`, plus the tunable
|
|
11
|
+
* `coord` (heartbeat freshness), `logs` (structured-log storage budgets),
|
|
12
|
+
* `artifacts` (working-file retention),
|
|
12
13
|
* `backup` (restic repo/password/prune policy), `sync` (rclone
|
|
13
14
|
* remote/prefix), and `web` (dashboard port) sections. The `files` deny/override section
|
|
14
15
|
* is parsed separately by `web/lib/files.ts`.
|
|
@@ -21,13 +22,17 @@ import { readFileSync, statSync } from "node:fs";
|
|
|
21
22
|
import { homedir } from "node:os";
|
|
22
23
|
import { join } from "node:path";
|
|
23
24
|
import { coordEnv } from "../lib/env.js";
|
|
25
|
+
import { DEFAULT_WEB_PORT } from "../lib/local-file-url.js";
|
|
26
|
+
import { resolveEventLedgerRotateActiveBytesV3 } from "./events/v3/rotation-config.js";
|
|
24
27
|
import { findCoordRoot } from "./hooks/resolve/coord-root.js";
|
|
28
|
+
export { DEFAULT_WEB_PORT } from "../lib/local-file-url.js";
|
|
29
|
+
export { DEFAULT_EVENT_LEDGER_ROTATE_ACTIVE_BYTES } from "./events/v3/rotation-config.js";
|
|
25
30
|
/** The standalone CLI's bin name: the resolution floor when nothing else is set. */
|
|
26
31
|
export const DEFAULT_BIN_NAME = "harn";
|
|
27
32
|
/** Heartbeat-freshness default (seconds): the sweep window when nothing overrides it. */
|
|
28
33
|
export const DEFAULT_FRESHNESS_SECS = 600;
|
|
29
|
-
/**
|
|
30
|
-
export const
|
|
34
|
+
/** Keep a fresh host reminder bounded to one short prompt-context line. */
|
|
35
|
+
export const MAX_HOST_PROMPT_REMINDER_CHARS = 500;
|
|
31
36
|
export const DEFAULT_SESSION_FINALIZATION_CONFIG = {
|
|
32
37
|
archiveGraceSeconds: 600,
|
|
33
38
|
idleObserveSeconds: 3 * 24 * 60 * 60,
|
|
@@ -117,6 +122,27 @@ function parseConfigFile(p) {
|
|
|
117
122
|
}
|
|
118
123
|
return {};
|
|
119
124
|
}
|
|
125
|
+
/**
|
|
126
|
+
* Raw user and project `logs.storage` layers with their origin intact.
|
|
127
|
+
*
|
|
128
|
+
* Storage retention validates these as one fail-closed unit. It cannot use the
|
|
129
|
+
* ordinary merged reader because commands must explain whether each effective
|
|
130
|
+
* scalar came from a user class, user family, project class, or project family.
|
|
131
|
+
*/
|
|
132
|
+
export function logStorageConfigSource(root) {
|
|
133
|
+
const projectPath = join(root, ".harnery", "config.jsonc");
|
|
134
|
+
const user = parseConfigLayer(userConfigPath());
|
|
135
|
+
const project = parseConfigLayer(projectPath);
|
|
136
|
+
const layer = (source) => ({
|
|
137
|
+
layer: source.path_kind,
|
|
138
|
+
value: source.config.logs?.storage,
|
|
139
|
+
invalid: source.invalid,
|
|
140
|
+
signature: source.signature,
|
|
141
|
+
});
|
|
142
|
+
return {
|
|
143
|
+
layers: [layer(user), layer(project)],
|
|
144
|
+
};
|
|
145
|
+
}
|
|
120
146
|
/**
|
|
121
147
|
* Effective user-plus-project `coord.run_quality` value with parse diagnostics.
|
|
122
148
|
* The ordinary config reader stays fail-soft; this one lets the guard visibly
|
|
@@ -255,6 +281,29 @@ export function resolveHooksSetupHint(coordRoot) {
|
|
|
255
281
|
const hint = readConfig(root).hooksSetupHint;
|
|
256
282
|
return typeof hint === "string" && hint.trim() ? hint.trim() : null;
|
|
257
283
|
}
|
|
284
|
+
/**
|
|
285
|
+
* One project-owned reminder that a supported prompt hook can place immediately
|
|
286
|
+
* before a model response. The value is deliberately project-only: host policy
|
|
287
|
+
* must not follow the user-global config into unrelated repositories. It is
|
|
288
|
+
* emitted directly from config and never copied into coordination state.
|
|
289
|
+
*
|
|
290
|
+
* The reminder must be one non-empty line of at most 500 characters. Invalid
|
|
291
|
+
* values fail closed to no reminder so a malformed optional setting cannot
|
|
292
|
+
* break the prompt hook.
|
|
293
|
+
*/
|
|
294
|
+
export function hostPromptReminder(coordRoot) {
|
|
295
|
+
const root = coordRoot ?? findCoordRoot();
|
|
296
|
+
if (!root)
|
|
297
|
+
return null;
|
|
298
|
+
const value = readProjectConfig(root).instructions?.promptReminder;
|
|
299
|
+
if (typeof value !== "string")
|
|
300
|
+
return null;
|
|
301
|
+
const reminder = value.trim();
|
|
302
|
+
if (!reminder || reminder.length > MAX_HOST_PROMPT_REMINDER_CHARS || /[\r\n]/.test(reminder)) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
return reminder;
|
|
306
|
+
}
|
|
258
307
|
/**
|
|
259
308
|
* Whether the host requires the guarded Git check at the end of tool-using
|
|
260
309
|
* turns. Default false: Harnery exposes `agents status --end-turn` as a capability
|
|
@@ -410,6 +459,20 @@ export function coordFreshnessSeconds(coordRoot) {
|
|
|
410
459
|
return posIntOr(readConfig(root).coord?.freshness_seconds, DEFAULT_FRESHNESS_SECS);
|
|
411
460
|
return DEFAULT_FRESHNESS_SECS;
|
|
412
461
|
}
|
|
462
|
+
/**
|
|
463
|
+
* Active-segment byte size at which the V3 event ledger rotates to a fresh
|
|
464
|
+
* epoch. Every reader validates the complete epoch, so an unbounded active
|
|
465
|
+
* segment makes each cold read (one per hook process) scale with all history.
|
|
466
|
+
* Precedence:
|
|
467
|
+
* 1. `HARNERY_EVENT_V3_ROTATE_ACTIVE_BYTES` env
|
|
468
|
+
* 2. `.harnery/config.jsonc` `events.rotate_active_bytes`
|
|
469
|
+
* 3. 33554432 (32 MiB)
|
|
470
|
+
* `0` (or a negative value) disables automatic rotation.
|
|
471
|
+
*/
|
|
472
|
+
export function eventLedgerRotateActiveBytes(coordRoot) {
|
|
473
|
+
const root = coordRoot ?? findCoordRoot();
|
|
474
|
+
return resolveEventLedgerRotateActiveBytesV3(root);
|
|
475
|
+
}
|
|
413
476
|
function parseWebPort(value, source) {
|
|
414
477
|
const port = typeof value === "number" ? value : Number(value);
|
|
415
478
|
if (!Number.isInteger(port) || port < 1024 || port > 65535) {
|
|
@@ -477,6 +540,37 @@ export function artifactDefaultRetentionDays(coordRoot) {
|
|
|
477
540
|
? configured
|
|
478
541
|
: 3;
|
|
479
542
|
}
|
|
543
|
+
/**
|
|
544
|
+
* Whether the daily SessionStart sweep of expired artifact workspaces runs.
|
|
545
|
+
* Precedence: `HARNERY_ARTIFACT_AUTO_CLEAN` (0/false disables) ->
|
|
546
|
+
* `artifacts.auto_clean` -> enabled. The sweep only ever deletes
|
|
547
|
+
* `managed-expired` entries via the same guarded classifier as
|
|
548
|
+
* `artifacts clean --yes`.
|
|
549
|
+
*/
|
|
550
|
+
export function artifactAutoCleanEnabled(coordRoot) {
|
|
551
|
+
const env = coordEnv("ARTIFACT_AUTO_CLEAN");
|
|
552
|
+
if (env !== undefined)
|
|
553
|
+
return !(env === "0" || env.toLowerCase() === "false");
|
|
554
|
+
const root = coordRoot ?? findCoordRoot();
|
|
555
|
+
if (!root)
|
|
556
|
+
return true;
|
|
557
|
+
return readConfig(root).artifacts?.auto_clean !== false;
|
|
558
|
+
}
|
|
559
|
+
/**
|
|
560
|
+
* Sweep cadence in hours. Env-only (`HARNERY_ARTIFACT_AUTO_CLEAN_INTERVAL_HOURS`,
|
|
561
|
+
* mainly for tests): the cadence is an implementation detail, not policy, and
|
|
562
|
+
* retention itself is quantized in whole days, so the 24h default is not a
|
|
563
|
+
* config surface.
|
|
564
|
+
*/
|
|
565
|
+
export function artifactAutoCleanIntervalHours() {
|
|
566
|
+
const env = coordEnv("ARTIFACT_AUTO_CLEAN_INTERVAL_HOURS");
|
|
567
|
+
if (env !== undefined) {
|
|
568
|
+
const n = Number(env);
|
|
569
|
+
if (Number.isFinite(n) && n > 0 && n <= 24 * 365)
|
|
570
|
+
return n;
|
|
571
|
+
}
|
|
572
|
+
return 24;
|
|
573
|
+
}
|
|
480
574
|
/**
|
|
481
575
|
* `harn backup` (restic) defaults. Per field, precedence is env → config → built-in:
|
|
482
576
|
* repo: `HARNERY_RESTIC_REPO` → `backup.repo` → `~/.cache/harnery/restic-repo`
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import { type DurableHistoryFaultBoundary } from "../storage/durable-history.js";
|
|
2
|
+
import type { HarneryConversationAccessMode, HarneryConversationArchiveAuthorityMode, HarneryConversationProvider, HarneryConversationRecordV1, HarneryConversationSourceSnapshot } from "./contract.js";
|
|
3
|
+
export declare const HARNERY_CONVERSATION_MANIFEST_SCHEMA: "harnery.conversation-manifest/v1";
|
|
4
|
+
export interface HarneryConversationArchiveManifest {
|
|
5
|
+
schema: typeof HARNERY_CONVERSATION_MANIFEST_SCHEMA;
|
|
6
|
+
policy_version: "conversation-archive-v1";
|
|
7
|
+
provider_id: string;
|
|
8
|
+
project_scope_id: string;
|
|
9
|
+
conversation_id: string;
|
|
10
|
+
source_snapshot_id: string;
|
|
11
|
+
completeness: HarneryConversationSourceSnapshot["completeness"];
|
|
12
|
+
omissions: readonly string[];
|
|
13
|
+
record_count: number;
|
|
14
|
+
logical_bytes: number;
|
|
15
|
+
first_occurred_at?: string;
|
|
16
|
+
last_occurred_at?: string;
|
|
17
|
+
record_set_digest: `sha256:${string}`;
|
|
18
|
+
authority_mode: HarneryConversationArchiveAuthorityMode;
|
|
19
|
+
updated_at: string;
|
|
20
|
+
}
|
|
21
|
+
export interface CaptureConversationOptions {
|
|
22
|
+
coord_root: string;
|
|
23
|
+
project_scope_id: string;
|
|
24
|
+
conversation_id: string;
|
|
25
|
+
access_mode: HarneryConversationAccessMode;
|
|
26
|
+
authority_mode: HarneryConversationArchiveAuthorityMode;
|
|
27
|
+
now?: () => Date;
|
|
28
|
+
fault?: (boundary: DurableHistoryFaultBoundary | "after_record_append" | "before_manifest_publish" | "after_manifest_publish") => void;
|
|
29
|
+
}
|
|
30
|
+
export interface CaptureConversationResult {
|
|
31
|
+
state: "disabled" | "source-only" | "captured";
|
|
32
|
+
accepted: number;
|
|
33
|
+
duplicates: number;
|
|
34
|
+
omissions: readonly string[];
|
|
35
|
+
manifest?: HarneryConversationArchiveManifest;
|
|
36
|
+
}
|
|
37
|
+
export declare function captureProviderConversation(provider: HarneryConversationProvider, options: CaptureConversationOptions): Promise<CaptureConversationResult>;
|
|
38
|
+
export declare function readConversationArchive(objectDirOrCoordRoot: string, providerId?: string, conversationId?: string): HarneryConversationRecordV1[];
|
|
39
|
+
export declare function reconcileConversationArchive(input: {
|
|
40
|
+
coord_root: string;
|
|
41
|
+
provider_id: string;
|
|
42
|
+
conversation_id: string;
|
|
43
|
+
snapshot: HarneryConversationSourceSnapshot;
|
|
44
|
+
authority_mode: HarneryConversationArchiveAuthorityMode;
|
|
45
|
+
now: Date;
|
|
46
|
+
}): HarneryConversationArchiveManifest;
|
|
47
|
+
export declare function loadConversationManifest(coordRoot: string, providerId: string, conversationId: string): HarneryConversationArchiveManifest | undefined;
|
|
48
|
+
export declare function conversationArchiveDir(coordRoot: string, providerId: string, conversationId: string): string;
|
|
49
|
+
//# sourceMappingURL=archive.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"archive.d.ts","sourceRoot":"","sources":["../../../src/core/conversations/archive.ts"],"names":[],"mappings":"AAEA,OAAO,EAEL,KAAK,2BAA2B,EAEjC,MAAM,+BAA+B,CAAC;AACvC,OAAO,KAAK,EACV,6BAA6B,EAC7B,uCAAuC,EACvC,2BAA2B,EAC3B,2BAA2B,EAC3B,iCAAiC,EAClC,MAAM,eAAe,CAAC;AAGvB,eAAO,MAAM,oCAAoC,EAAG,kCAA2C,CAAC;AAEhG,MAAM,WAAW,kCAAkC;IACjD,MAAM,EAAE,OAAO,oCAAoC,CAAC;IACpD,cAAc,EAAE,yBAAyB,CAAC;IAC1C,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,MAAM,CAAC;IAC3B,YAAY,EAAE,iCAAiC,CAAC,cAAc,CAAC,CAAC;IAChE,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,YAAY,EAAE,MAAM,CAAC;IACrB,aAAa,EAAE,MAAM,CAAC;IACtB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,iBAAiB,EAAE,UAAU,MAAM,EAAE,CAAC;IACtC,cAAc,EAAE,uCAAuC,CAAC;IACxD,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,UAAU,EAAE,MAAM,CAAC;IACnB,gBAAgB,EAAE,MAAM,CAAC;IACzB,eAAe,EAAE,MAAM,CAAC;IACxB,WAAW,EAAE,6BAA6B,CAAC;IAC3C,cAAc,EAAE,uCAAuC,CAAC;IACxD,GAAG,CAAC,EAAE,MAAM,IAAI,CAAC;IACjB,KAAK,CAAC,EAAE,CACN,QAAQ,EACJ,2BAA2B,GAC3B,qBAAqB,GACrB,yBAAyB,GACzB,wBAAwB,KACzB,IAAI,CAAC;CACX;AAED,MAAM,WAAW,yBAAyB;IACxC,KAAK,EAAE,UAAU,GAAG,aAAa,GAAG,UAAU,CAAC;IAC/C,QAAQ,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,EAAE,SAAS,MAAM,EAAE,CAAC;IAC7B,QAAQ,CAAC,EAAE,kCAAkC,CAAC;CAC/C;AAED,wBAAsB,2BAA2B,CAC/C,QAAQ,EAAE,2BAA2B,EACrC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CAoEpC;AAED,wBAAgB,uBAAuB,CACrC,oBAAoB,EAAE,MAAM,EAC5B,UAAU,CAAC,EAAE,MAAM,EACnB,cAAc,CAAC,EAAE,MAAM,GACtB,2BAA2B,EAAE,CAS/B;AAED,wBAAgB,4BAA4B,CAAC,KAAK,EAAE;IAClD,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,eAAe,EAAE,MAAM,CAAC;IACxB,QAAQ,EAAE,iCAAiC,CAAC;IAC5C,cAAc,EAAE,uCAAuC,CAAC;IACxD,GAAG,EAAE,IAAI,CAAC;CACX,GAAG,kCAAkC,CAcrC;AAED,wBAAgB,wBAAwB,CACtC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,kCAAkC,GAAG,SAAS,CAUhD;AAED,wBAAgB,sBAAsB,CACpC,SAAS,EAAE,MAAM,EACjB,UAAU,EAAE,MAAM,EAClB,cAAc,EAAE,MAAM,GACrB,MAAM,CAIR"}
|
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
import { mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from "node:fs";
|
|
2
|
+
import { join, resolve } from "node:path";
|
|
3
|
+
import { appendDurableHistoryRecord, readDurableHistorySync, } from "../storage/durable-history.js";
|
|
4
|
+
import { digest, normalizeConversationRecord } from "./normalize.js";
|
|
5
|
+
export const HARNERY_CONVERSATION_MANIFEST_SCHEMA = "harnery.conversation-manifest/v1";
|
|
6
|
+
export async function captureProviderConversation(provider, options) {
|
|
7
|
+
if (options.access_mode === "off")
|
|
8
|
+
return result("disabled");
|
|
9
|
+
if (options.access_mode === "source")
|
|
10
|
+
return result("source-only");
|
|
11
|
+
const objectDir = conversationArchiveDir(options.coord_root, provider.capabilities.provider_id, options.conversation_id);
|
|
12
|
+
mkdirSync(objectDir, { recursive: true, mode: 0o700 });
|
|
13
|
+
const lease = join(objectDir, ".capture.lease");
|
|
14
|
+
try {
|
|
15
|
+
mkdirSync(lease, { mode: 0o700 });
|
|
16
|
+
}
|
|
17
|
+
catch {
|
|
18
|
+
throw new Error(`conversation capture lease busy: ${options.conversation_id}`);
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const snapshot = await provider.snapshot(options.project_scope_id, options.conversation_id);
|
|
22
|
+
const existing = readConversationArchive(objectDir);
|
|
23
|
+
const seen = new Map(existing.map((record) => [record.record_id, record.content_digest]));
|
|
24
|
+
let accepted = 0;
|
|
25
|
+
let duplicates = 0;
|
|
26
|
+
const omissions = new Set(snapshot.omissions);
|
|
27
|
+
let sequence = existing.at(-1)?.sequence ?? 0;
|
|
28
|
+
for await (const native of provider.stream(options.project_scope_id, options.conversation_id)) {
|
|
29
|
+
const normalized = normalizeConversationRecord({
|
|
30
|
+
capabilities: provider.capabilities,
|
|
31
|
+
snapshot,
|
|
32
|
+
native,
|
|
33
|
+
captured_at: (options.now?.() ?? new Date()).toISOString(),
|
|
34
|
+
sequence: sequence + 1,
|
|
35
|
+
});
|
|
36
|
+
if (!normalized.record) {
|
|
37
|
+
omissions.add(normalized.omission ?? "record_excluded");
|
|
38
|
+
continue;
|
|
39
|
+
}
|
|
40
|
+
const prior = seen.get(normalized.record.record_id);
|
|
41
|
+
if (prior) {
|
|
42
|
+
if (prior !== normalized.record.content_digest) {
|
|
43
|
+
throw new Error(`conversation record collision: ${normalized.record.record_id}`);
|
|
44
|
+
}
|
|
45
|
+
duplicates += 1;
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
48
|
+
sequence += 1;
|
|
49
|
+
normalized.record.sequence = sequence;
|
|
50
|
+
appendDurableHistoryRecord(objectDir, normalized.record, {
|
|
51
|
+
max_record_bytes: 1_048_576,
|
|
52
|
+
max_segment_bytes: 8_388_608,
|
|
53
|
+
fault: options.fault,
|
|
54
|
+
});
|
|
55
|
+
options.fault?.("after_record_append");
|
|
56
|
+
seen.set(normalized.record.record_id, normalized.record.content_digest);
|
|
57
|
+
accepted += 1;
|
|
58
|
+
}
|
|
59
|
+
const records = readConversationArchive(objectDir);
|
|
60
|
+
const manifest = manifestFor(records, { ...snapshot, omissions: [...omissions].sort() }, options.authority_mode, options.now?.() ?? new Date());
|
|
61
|
+
options.fault?.("before_manifest_publish");
|
|
62
|
+
publishManifest(objectDir, manifest);
|
|
63
|
+
options.fault?.("after_manifest_publish");
|
|
64
|
+
return { state: "captured", accepted, duplicates, omissions: [...omissions].sort(), manifest };
|
|
65
|
+
}
|
|
66
|
+
finally {
|
|
67
|
+
rmSync(lease, { recursive: true, force: true });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
export function readConversationArchive(objectDirOrCoordRoot, providerId, conversationId) {
|
|
71
|
+
const objectDir = providerId && conversationId
|
|
72
|
+
? conversationArchiveDir(objectDirOrCoordRoot, providerId, conversationId)
|
|
73
|
+
: objectDirOrCoordRoot;
|
|
74
|
+
return readDurableHistorySync(objectDir, {
|
|
75
|
+
max_record_bytes: 1_048_576,
|
|
76
|
+
max_records: 1_000_000,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
export function reconcileConversationArchive(input) {
|
|
80
|
+
const objectDir = conversationArchiveDir(input.coord_root, input.provider_id, input.conversation_id);
|
|
81
|
+
const manifest = manifestFor(readConversationArchive(objectDir), input.snapshot, input.authority_mode, input.now);
|
|
82
|
+
publishManifest(objectDir, manifest);
|
|
83
|
+
return manifest;
|
|
84
|
+
}
|
|
85
|
+
export function loadConversationManifest(coordRoot, providerId, conversationId) {
|
|
86
|
+
const path = join(conversationArchiveDir(coordRoot, providerId, conversationId), "manifest.json");
|
|
87
|
+
try {
|
|
88
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
89
|
+
if (parsed.schema !== HARNERY_CONVERSATION_MANIFEST_SCHEMA)
|
|
90
|
+
throw new Error("unknown schema");
|
|
91
|
+
return parsed;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (error.code === "ENOENT")
|
|
95
|
+
return undefined;
|
|
96
|
+
throw new Error(`conversation manifest invalid: ${error.message}`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
export function conversationArchiveDir(coordRoot, providerId, conversationId) {
|
|
100
|
+
const provider = opaque(providerId);
|
|
101
|
+
const conversation = digest(`${providerId}\0${conversationId}`).slice("sha256:".length, 38);
|
|
102
|
+
return join(resolve(coordRoot), ".harnery", "conversations", provider, conversation);
|
|
103
|
+
}
|
|
104
|
+
function manifestFor(records, snapshot, authorityMode, now) {
|
|
105
|
+
return {
|
|
106
|
+
schema: HARNERY_CONVERSATION_MANIFEST_SCHEMA,
|
|
107
|
+
policy_version: "conversation-archive-v1",
|
|
108
|
+
provider_id: snapshot.provider_id,
|
|
109
|
+
project_scope_id: snapshot.project_scope_id,
|
|
110
|
+
conversation_id: snapshot.conversation_id,
|
|
111
|
+
source_snapshot_id: snapshot.snapshot_id,
|
|
112
|
+
completeness: snapshot.completeness,
|
|
113
|
+
omissions: [...snapshot.omissions],
|
|
114
|
+
record_count: records.length,
|
|
115
|
+
logical_bytes: records.reduce((sum, record) => sum + record.content_bytes, 0),
|
|
116
|
+
...(records[0] ? { first_occurred_at: records[0].occurred_at } : {}),
|
|
117
|
+
...(records.at(-1) ? { last_occurred_at: records.at(-1).occurred_at } : {}),
|
|
118
|
+
record_set_digest: digest(records.map((record) => record.record_id).join("\n")),
|
|
119
|
+
authority_mode: authorityMode,
|
|
120
|
+
updated_at: now.toISOString(),
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
function publishManifest(objectDir, manifest) {
|
|
124
|
+
const path = join(objectDir, "manifest.json");
|
|
125
|
+
const temp = `${path}.tmp-${process.pid}`;
|
|
126
|
+
writeFileSync(temp, `${JSON.stringify(manifest, null, 2)}\n`, { mode: 0o600 });
|
|
127
|
+
renameSync(temp, path);
|
|
128
|
+
}
|
|
129
|
+
function opaque(value) {
|
|
130
|
+
if (!/^[a-z][a-z0-9-]{1,63}$/.test(value))
|
|
131
|
+
throw new Error(`invalid provider id: ${value}`);
|
|
132
|
+
return value;
|
|
133
|
+
}
|
|
134
|
+
function result(state) {
|
|
135
|
+
return { state, accepted: 0, duplicates: 0, omissions: [] };
|
|
136
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { HarneryConversationProvider } from "./contract.js";
|
|
2
|
+
export declare class HarneryConversationCatalog {
|
|
3
|
+
#private;
|
|
4
|
+
constructor(providers: readonly HarneryConversationProvider[]);
|
|
5
|
+
get(id: string): HarneryConversationProvider | undefined;
|
|
6
|
+
require(id: string): HarneryConversationProvider;
|
|
7
|
+
list(): readonly HarneryConversationProvider[];
|
|
8
|
+
}
|
|
9
|
+
export declare function unavailableAdapterProviders(): readonly HarneryConversationProvider[];
|
|
10
|
+
//# sourceMappingURL=catalog.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"catalog.d.ts","sourceRoot":"","sources":["../../../src/core/conversations/catalog.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,eAAe,CAAC;AAEjE,qBAAa,0BAA0B;;gBAGzB,SAAS,EAAE,SAAS,2BAA2B,EAAE;IAe7D,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,2BAA2B,GAAG,SAAS;IAIxD,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,2BAA2B;IAMhD,IAAI,IAAI,SAAS,2BAA2B,EAAE;CAK/C;AAED,wBAAgB,2BAA2B,IAAI,SAAS,2BAA2B,EAAE,CAyCpF"}
|