harnery 0.35.0 → 0.37.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 +128 -96
- package/dist/commands/agents.d.ts +23 -3
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +464 -242
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +26 -1
- 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 +16 -4
- package/dist/commands/conversations.d.ts +10 -0
- package/dist/commands/conversations.d.ts.map +1 -0
- package/dist/commands/conversations.js +201 -0
- package/dist/commands/deinit.d.ts.map +1 -1
- package/dist/commands/deinit.js +5 -0
- package/dist/commands/diagnostics.d.ts +4 -0
- package/dist/commands/diagnostics.d.ts.map +1 -0
- package/dist/commands/diagnostics.js +229 -0
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +13 -2
- package/dist/commands/doctor.d.ts +5 -0
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +51 -7
- package/dist/commands/fetch.js +6 -5
- package/dist/commands/files.d.ts +34 -0
- package/dist/commands/files.d.ts.map +1 -0
- package/dist/commands/files.js +166 -0
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +18 -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 +417 -2
- 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/qa-run.d.ts +4 -0
- package/dist/commands/qa-run.d.ts.map +1 -0
- package/dist/commands/qa-run.js +141 -0
- 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/resources.d.ts +4 -0
- package/dist/commands/resources.d.ts.map +1 -0
- package/dist/commands/resources.js +29 -0
- package/dist/commands/semantic.d.ts.map +1 -1
- package/dist/commands/semantic.js +54 -2
- package/dist/commands/storage.d.ts +4 -0
- package/dist/commands/storage.d.ts.map +1 -0
- package/dist/commands/storage.js +238 -0
- package/dist/commands/supervisor.d.ts +4 -0
- package/dist/commands/supervisor.d.ts.map +1 -0
- package/dist/commands/supervisor.js +101 -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.d.ts.map +1 -1
- package/dist/commands/workflow.js +17 -13
- package/dist/core/adapters/profiles.d.ts +1 -1
- package/dist/core/agents/cli.js +215 -41
- package/dist/core/agents/health.d.ts +17 -0
- package/dist/core/agents/health.d.ts.map +1 -0
- package/dist/core/agents/health.js +109 -0
- package/dist/core/agents/live-authority-v3.d.ts +47 -1
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -1
- package/dist/core/agents/live-authority-v3.js +244 -10
- package/dist/core/agents/live-lifecycle-v3.js +6 -1
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -1
- package/dist/core/agents/live-observation-v3.js +6 -1
- package/dist/core/agents/mailbox.d.ts +92 -0
- package/dist/core/agents/mailbox.d.ts.map +1 -0
- package/dist/core/agents/mailbox.js +325 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts +44 -0
- package/dist/core/agents/reconcile-coordination-v3.d.ts.map +1 -0
- package/dist/core/agents/reconcile-coordination-v3.js +58 -0
- package/dist/core/agents/render/prompt-context.d.ts +14 -3
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +54 -16
- package/dist/core/agents/render/session-context.d.ts +8 -0
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +34 -3
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +50 -1
- 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 +93 -16
- 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 +9 -2
- package/dist/core/agents/state/activity-log.d.ts +3 -0
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +6 -3
- package/dist/core/agents/state/heartbeat-writer.d.ts +6 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +18 -0
- package/dist/core/agents/state/live-coordination-view.d.ts +5 -7
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +15 -90
- package/dist/core/agents/state/live-coordination-writer.d.ts +12 -0
- package/dist/core/agents/state/live-coordination-writer.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +92 -0
- package/dist/core/artifacts/index.d.ts +47 -1
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +191 -6
- package/dist/core/config.d.ts +74 -4
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +141 -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/diagnostics/advice.d.ts +9 -0
- package/dist/core/diagnostics/advice.d.ts.map +1 -0
- package/dist/core/diagnostics/advice.js +112 -0
- package/dist/core/diagnostics/bundle.d.ts +35 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -0
- package/dist/core/diagnostics/bundle.js +874 -0
- package/dist/core/diagnostics/comparison.d.ts +5 -0
- package/dist/core/diagnostics/comparison.d.ts.map +1 -0
- package/dist/core/diagnostics/comparison.js +444 -0
- package/dist/core/diagnostics/contract.d.ts +245 -0
- package/dist/core/diagnostics/contract.d.ts.map +1 -0
- package/dist/core/diagnostics/contract.js +18 -0
- package/dist/core/diagnostics/identity.d.ts +3 -0
- package/dist/core/diagnostics/identity.d.ts.map +1 -0
- package/dist/core/diagnostics/identity.js +10 -0
- package/dist/core/diagnostics/index.d.ts +8 -0
- package/dist/core/diagnostics/index.d.ts.map +1 -0
- package/dist/core/diagnostics/index.js +7 -0
- package/dist/core/diagnostics/replay.d.ts +8 -0
- package/dist/core/diagnostics/replay.d.ts.map +1 -0
- package/dist/core/diagnostics/replay.js +213 -0
- package/dist/core/diagnostics/sanitize.d.ts +9 -0
- package/dist/core/diagnostics/sanitize.d.ts.map +1 -0
- package/dist/core/diagnostics/sanitize.js +84 -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/compression.d.ts +13 -0
- package/dist/core/events/legacy-storage/compression.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/compression.js +107 -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 +7 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -0
- package/dist/core/events/legacy-storage/index.js +6 -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/archive-retention.d.ts +33 -0
- package/dist/core/events/v3/archive-retention.d.ts.map +1 -0
- package/dist/core/events/v3/archive-retention.js +195 -0
- package/dist/core/events/v3/authority-outbox.d.ts +7 -2
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -1
- package/dist/core/events/v3/authority-outbox.js +16 -3
- package/dist/core/events/v3/base-contract.d.ts +81 -41
- package/dist/core/events/v3/base-contract.d.ts.map +1 -1
- package/dist/core/events/v3/base-contract.js +17 -7
- package/dist/core/events/v3/bootstrap.d.ts +39 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +167 -3
- package/dist/core/events/v3/capabilities.d.ts +1 -1
- package/dist/core/events/v3/capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/capabilities.js +4 -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 +5 -2
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +4 -1
- package/dist/core/events/v3/live-route-observer.d.ts +31 -0
- package/dist/core/events/v3/live-route-observer.d.ts.map +1 -0
- package/dist/core/events/v3/live-route-observer.js +58 -0
- package/dist/core/events/v3/live-routing.d.ts +13 -21
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +46 -41
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +11 -1
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/coordination-recorder.js +76 -10
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts +129 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.d.ts.map +1 -0
- package/dist/core/events/v3/producers/diagnostic-summaries.js +499 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +1 -1
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -1
- package/dist/core/events/v3/producers/hook-base.js +14 -3
- package/dist/core/events/v3/producers/intake.d.ts +7 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +26 -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 +71 -1
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +441 -25
- package/dist/core/events/v3/reader.d.ts +51 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -1
- package/dist/core/events/v3/reader.js +181 -1
- package/dist/core/events/v3/rotation-config.d.ts +9 -0
- package/dist/core/events/v3/rotation-config.d.ts.map +1 -0
- package/dist/core/events/v3/rotation-config.js +91 -0
- package/dist/core/events/v3/runtime-build.d.ts +11 -0
- package/dist/core/events/v3/runtime-build.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-build.js +39 -0
- package/dist/core/events/v3/runtime-identity.d.ts +5 -0
- package/dist/core/events/v3/runtime-identity.d.ts.map +1 -0
- package/dist/core/events/v3/runtime-identity.js +18 -0
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts +6 -5
- package/dist/core/events/v3/runtime-telemetry-capabilities.d.ts.map +1 -1
- package/dist/core/events/v3/runtime-telemetry-capabilities.js +1 -1
- package/dist/core/events/v3/support-storage/classify.d.ts +46 -0
- package/dist/core/events/v3/support-storage/classify.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/classify.js +149 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts +29 -0
- package/dist/core/events/v3/support-storage/eligibility.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/eligibility.js +35 -0
- package/dist/core/events/v3/support-storage/index.d.ts +10 -0
- package/dist/core/events/v3/support-storage/index.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/index.js +9 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts +30 -0
- package/dist/core/events/v3/support-storage/inventory.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/inventory.js +94 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts +14 -0
- package/dist/core/events/v3/support-storage/logical-authority.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/logical-authority.js +104 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts +98 -0
- package/dist/core/events/v3/support-storage/maintenance.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/maintenance.js +352 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts +59 -0
- package/dist/core/events/v3/support-storage/pack-contract.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-contract.js +249 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts +34 -0
- package/dist/core/events/v3/support-storage/pack-reader.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-reader.js +258 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts +30 -0
- package/dist/core/events/v3/support-storage/pack-writer.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/pack-writer.js +268 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts +15 -0
- package/dist/core/events/v3/support-storage/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/support-storage/recovery.js +22 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +14 -8
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -1
- package/dist/core/events/v3/turn-telemetry.js +32 -2
- package/dist/core/events/v3/writer.d.ts +13 -1
- package/dist/core/events/v3/writer.d.ts.map +1 -1
- package/dist/core/events/v3/writer.js +126 -12
- package/dist/core/governor/plan-read.d.ts.map +1 -1
- package/dist/core/governor/plan-read.js +5 -21
- package/dist/core/governor/planning.js +6 -8
- package/dist/core/governor/service-read.d.ts +12 -0
- package/dist/core/governor/service-read.d.ts.map +1 -1
- package/dist/core/governor/service-read.js +266 -2
- package/dist/core/governor/service.d.ts +1 -0
- package/dist/core/governor/service.d.ts.map +1 -1
- package/dist/core/governor/service.js +53 -18
- package/dist/core/guard/evidence-v3.d.ts.map +1 -1
- package/dist/core/guard/evidence-v3.js +2 -0
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +1 -0
- package/dist/core/hooks/adapter/output.d.ts +12 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +23 -5
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts +27 -4
- package/dist/core/hooks/adapter/runtime-telemetry.d.ts.map +1 -1
- package/dist/core/hooks/adapter/runtime-telemetry.js +307 -6
- package/dist/core/hooks/cli.js +380 -207
- 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/health.d.ts +59 -0
- package/dist/core/hooks/health.d.ts.map +1 -0
- package/dist/core/hooks/health.js +84 -0
- package/dist/core/hooks/remediation-cap.d.ts +8 -3
- package/dist/core/hooks/remediation-cap.d.ts.map +1 -1
- package/dist/core/hooks/remediation-cap.js +3 -11
- package/dist/core/hooks/resolve/coord-root.d.ts +22 -9
- package/dist/core/hooks/resolve/coord-root.d.ts.map +1 -1
- package/dist/core/hooks/resolve/coord-root.js +92 -11
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +5 -0
- package/dist/core/hooks/resolve/transcript.d.ts +8 -0
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +11 -0
- package/dist/core/inbox/contract.d.ts +64 -0
- package/dist/core/inbox/contract.d.ts.map +1 -0
- package/dist/core/inbox/contract.js +13 -0
- package/dist/core/inbox/index.d.ts +5 -0
- package/dist/core/inbox/index.d.ts.map +1 -0
- package/dist/core/inbox/index.js +4 -0
- package/dist/core/inbox/lifecycle.d.ts +22 -0
- package/dist/core/inbox/lifecycle.d.ts.map +1 -0
- package/dist/core/inbox/lifecycle.js +41 -0
- package/dist/core/inbox/service.d.ts +36 -0
- package/dist/core/inbox/service.d.ts.map +1 -0
- package/dist/core/inbox/service.js +210 -0
- package/dist/core/inbox/watcher.d.ts +7 -0
- package/dist/core/inbox/watcher.d.ts.map +1 -0
- package/dist/core/inbox/watcher.js +26 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -1
- package/dist/core/presence/codec-digest.js +14 -3
- package/dist/core/presence/relay-client.d.ts +1 -0
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +52 -8
- package/dist/core/resources/contract.d.ts +90 -0
- package/dist/core/resources/contract.d.ts.map +1 -0
- package/dist/core/resources/contract.js +2 -0
- package/dist/core/resources/index.d.ts +6 -0
- package/dist/core/resources/index.d.ts.map +1 -0
- package/dist/core/resources/index.js +5 -0
- package/dist/core/resources/sampler.d.ts +27 -0
- package/dist/core/resources/sampler.d.ts.map +1 -0
- package/dist/core/resources/sampler.js +357 -0
- package/dist/core/resources/service-status.d.ts +3 -0
- package/dist/core/resources/service-status.d.ts.map +1 -0
- package/dist/core/resources/service-status.js +48 -0
- package/dist/core/resources/service.d.ts +26 -0
- package/dist/core/resources/service.d.ts.map +1 -0
- package/dist/core/resources/service.js +292 -0
- package/dist/core/resources/storage.d.ts +13 -0
- package/dist/core/resources/storage.d.ts.map +1 -0
- package/dist/core/resources/storage.js +30 -0
- package/dist/core/semantic/adapters.d.ts +11 -8
- package/dist/core/semantic/adapters.d.ts.map +1 -1
- package/dist/core/semantic/adapters.js +169 -31
- package/dist/core/semantic/contract.d.ts +532 -48
- package/dist/core/semantic/contract.d.ts.map +1 -1
- package/dist/core/semantic/contract.js +104 -3
- package/dist/core/semantic/index.d.ts +7 -3
- package/dist/core/semantic/index.d.ts.map +1 -1
- package/dist/core/semantic/index.js +7 -3
- package/dist/core/semantic/once.d.ts +6 -1
- package/dist/core/semantic/once.d.ts.map +1 -1
- package/dist/core/semantic/once.js +80 -9
- package/dist/core/semantic/prompt.d.ts.map +1 -1
- package/dist/core/semantic/prompt.js +14 -1
- package/dist/core/semantic/review.d.ts +144 -0
- package/dist/core/semantic/review.d.ts.map +1 -0
- package/dist/core/semantic/review.js +544 -0
- package/dist/core/semantic/routes.d.ts +10 -0
- package/dist/core/semantic/routes.d.ts.map +1 -0
- package/dist/core/semantic/routes.js +21 -0
- package/dist/core/semantic/scheduler.d.ts +14 -3
- package/dist/core/semantic/scheduler.d.ts.map +1 -1
- package/dist/core/semantic/scheduler.js +30 -6
- package/dist/core/semantic/service-status.d.ts +20 -0
- package/dist/core/semantic/service-status.d.ts.map +1 -1
- package/dist/core/semantic/service-status.js +60 -4
- package/dist/core/semantic/service.d.ts +1 -0
- package/dist/core/semantic/service.d.ts.map +1 -1
- package/dist/core/semantic/service.js +104 -15
- package/dist/core/semantic/soak.d.ts +75 -0
- package/dist/core/semantic/soak.d.ts.map +1 -0
- package/dist/core/semantic/soak.js +476 -0
- package/dist/core/semantic/storage.d.ts +11 -1
- package/dist/core/semantic/storage.d.ts.map +1 -1
- package/dist/core/semantic/storage.js +4 -3
- package/dist/core/semantic/usage.d.ts +43 -0
- package/dist/core/semantic/usage.d.ts.map +1 -0
- package/dist/core/semantic/usage.js +193 -0
- package/dist/core/semantic/validate.d.ts +3 -1
- package/dist/core/semantic/validate.d.ts.map +1 -1
- package/dist/core/semantic/validate.js +34 -1
- package/dist/core/storage/atomic-json.d.ts +3 -0
- package/dist/core/storage/atomic-json.d.ts.map +1 -0
- package/dist/core/storage/atomic-json.js +15 -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 +722 -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 +84 -0
- package/dist/core/storage/logger.d.ts.map +1 -0
- package/dist/core/storage/logger.js +413 -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 +48 -0
- package/dist/core/storage/query.d.ts.map +1 -0
- package/dist/core/storage/query.js +346 -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/supervisor/activity.d.ts +4 -0
- package/dist/core/supervisor/activity.d.ts.map +1 -0
- package/dist/core/supervisor/activity.js +141 -0
- package/dist/core/supervisor/contract.d.ts +268 -0
- package/dist/core/supervisor/contract.d.ts.map +1 -0
- package/dist/core/supervisor/contract.js +35 -0
- package/dist/core/supervisor/explanations.d.ts +4 -0
- package/dist/core/supervisor/explanations.d.ts.map +1 -0
- package/dist/core/supervisor/explanations.js +71 -0
- package/dist/core/supervisor/findings.d.ts +20 -0
- package/dist/core/supervisor/findings.d.ts.map +1 -0
- package/dist/core/supervisor/findings.js +399 -0
- package/dist/core/supervisor/history.d.ts +9 -0
- package/dist/core/supervisor/history.d.ts.map +1 -0
- package/dist/core/supervisor/history.js +46 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts +14 -0
- package/dist/core/supervisor/hook-health-alerts.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-alerts.js +70 -0
- package/dist/core/supervisor/hook-health-storage.d.ts +5 -0
- package/dist/core/supervisor/hook-health-storage.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health-storage.js +24 -0
- package/dist/core/supervisor/hook-health.d.ts +72 -0
- package/dist/core/supervisor/hook-health.d.ts.map +1 -0
- package/dist/core/supervisor/hook-health.js +203 -0
- package/dist/core/supervisor/hooks.d.ts +10 -0
- package/dist/core/supervisor/hooks.d.ts.map +1 -0
- package/dist/core/supervisor/hooks.js +28 -0
- package/dist/core/supervisor/index.d.ts +15 -0
- package/dist/core/supervisor/index.d.ts.map +1 -0
- package/dist/core/supervisor/index.js +14 -0
- package/dist/core/supervisor/log-feed.d.ts +9 -0
- package/dist/core/supervisor/log-feed.d.ts.map +1 -0
- package/dist/core/supervisor/log-feed.js +103 -0
- package/dist/core/supervisor/service.d.ts +29 -0
- package/dist/core/supervisor/service.d.ts.map +1 -0
- package/dist/core/supervisor/service.js +450 -0
- package/dist/core/supervisor/services.d.ts +11 -0
- package/dist/core/supervisor/services.d.ts.map +1 -0
- package/dist/core/supervisor/services.js +155 -0
- package/dist/core/supervisor/status.d.ts +3 -0
- package/dist/core/supervisor/status.d.ts.map +1 -0
- package/dist/core/supervisor/status.js +48 -0
- package/dist/core/supervisor/storage.d.ts +30 -0
- package/dist/core/supervisor/storage.d.ts.map +1 -0
- package/dist/core/supervisor/storage.js +73 -0
- package/dist/core/supervisor/timeline.d.ts +3 -0
- package/dist/core/supervisor/timeline.d.ts.map +1 -0
- package/dist/core/supervisor/timeline.js +87 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +10 -14
- package/dist/core/workflow/admission.d.ts +23 -0
- package/dist/core/workflow/admission.d.ts.map +1 -0
- package/dist/core/workflow/admission.js +136 -0
- package/dist/core/workflow/engine.d.ts.map +1 -1
- package/dist/core/workflow/engine.js +77 -2
- package/dist/core/workflow/index.d.ts +3 -2
- package/dist/core/workflow/index.d.ts.map +1 -1
- package/dist/core/workflow/index.js +2 -1
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -1
- package/dist/core/workflow/live-session-v3.js +2 -1
- package/dist/core/workflow/proof.d.ts +2 -1
- package/dist/core/workflow/proof.d.ts.map +1 -1
- package/dist/core/workflow/proof.js +39 -1
- package/dist/core/workflow/run-state.d.ts +3 -2
- package/dist/core/workflow/run-state.d.ts.map +1 -1
- package/dist/core/workflow/run-state.js +8 -1
- package/dist/core/workflow/types.d.ts +33 -1
- package/dist/core/workflow/types.d.ts.map +1 -1
- package/dist/core/workflow/types.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 +5 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +1 -0
- package/dist/lib/browser/index.d.ts +2 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +2 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +173 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
- package/dist/lib/browser/qa-run-contracts.js +226 -0
- package/dist/lib/browser/qa-run.d.ts +51 -0
- package/dist/lib/browser/qa-run.d.ts.map +1 -0
- package/dist/lib/browser/qa-run.js +684 -0
- package/dist/lib/coord-root-id.d.ts +9 -0
- package/dist/lib/coord-root-id.d.ts.map +1 -0
- package/dist/lib/coord-root-id.js +17 -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 +3 -1
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +74 -3
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +11 -0
- package/dist/lib/local-file-url.d.ts +9 -0
- package/dist/lib/local-file-url.d.ts.map +1 -0
- package/dist/lib/local-file-url.js +20 -0
- package/dist/lib/web-performance.d.ts +118 -0
- package/dist/lib/web-performance.d.ts.map +1 -0
- package/dist/lib/web-performance.js +192 -0
- package/package.json +40 -2
- package/schemas/config.schema.json +58 -0
- package/schemas/event-v3.schema.json +324 -112
- package/src/commander.ts +488 -95
- package/src/commands/agents.ts +617 -237
- package/src/commands/artifacts.ts +40 -2
- package/src/commands/backup.ts +18 -14
- package/src/commands/browse-session.ts +12 -0
- package/src/commands/browse.ts +21 -7
- package/src/commands/conversations.ts +279 -0
- package/src/commands/deinit.ts +6 -0
- package/src/commands/diagnostics.ts +271 -0
- package/src/commands/docs.ts +25 -6
- package/src/commands/doctor.ts +75 -9
- package/src/commands/fetch.ts +7 -6
- package/src/commands/files.ts +243 -0
- package/src/commands/governor.ts +21 -12
- package/src/commands/inbox.ts +61 -0
- package/src/commands/init.ts +78 -16
- package/src/commands/ledger-v3.ts +503 -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/qa-run.ts +184 -0
- package/src/commands/read.ts +6 -2
- package/src/commands/resources.ts +38 -0
- package/src/commands/semantic.ts +66 -1
- package/src/commands/storage.ts +310 -0
- package/src/commands/supervisor.ts +141 -0
- package/src/commands/tunnel.ts +66 -52
- package/src/commands/web.ts +96 -7
- package/src/commands/work.ts +3 -3
- package/src/commands/workflow.ts +21 -13
- package/src/core/agents/cli.ts +265 -55
- package/src/core/agents/health.ts +142 -0
- package/src/core/agents/live-authority-v3.ts +341 -10
- package/src/core/agents/live-lifecycle-v3.ts +6 -1
- package/src/core/agents/live-observation-v3.ts +6 -1
- package/src/core/agents/mailbox.ts +373 -0
- package/src/core/agents/reconcile-coordination-v3.ts +77 -0
- package/src/core/agents/render/prompt-context.ts +66 -15
- package/src/core/agents/render/session-context.ts +37 -3
- package/src/core/agents/rules/commit-conflict.ts +58 -1
- package/src/core/agents/rules/stop-hook.ts +105 -20
- 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 +8 -2
- package/src/core/agents/state/activity-log.ts +7 -2
- package/src/core/agents/state/heartbeat-writer.ts +27 -0
- package/src/core/agents/state/live-coordination-view.ts +16 -105
- package/src/core/agents/state/live-coordination-writer.ts +141 -0
- package/src/core/artifacts/index.ts +260 -11
- package/src/core/config.ts +235 -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/diagnostics/advice.ts +147 -0
- package/src/core/diagnostics/bundle.ts +1142 -0
- package/src/core/diagnostics/comparison.ts +565 -0
- package/src/core/diagnostics/contract.ts +311 -0
- package/src/core/diagnostics/identity.ts +11 -0
- package/src/core/diagnostics/index.ts +7 -0
- package/src/core/diagnostics/replay.ts +314 -0
- package/src/core/diagnostics/sanitize.ts +97 -0
- package/src/core/events/legacy-storage/canary.ts +177 -0
- package/src/core/events/legacy-storage/compression.ts +130 -0
- package/src/core/events/legacy-storage/fence.ts +129 -0
- package/src/core/events/legacy-storage/index.ts +6 -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/archive-retention.ts +251 -0
- package/src/core/events/v3/authority-outbox.ts +22 -1
- package/src/core/events/v3/base-contract.ts +17 -7
- package/src/core/events/v3/bootstrap.ts +195 -2
- package/src/core/events/v3/capabilities.ts +5 -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 +14 -2
- package/src/core/events/v3/live-route-observer.ts +80 -0
- package/src/core/events/v3/live-routing.ts +65 -46
- package/src/core/events/v3/producers/coordination-recorder.ts +95 -10
- package/src/core/events/v3/producers/diagnostic-summaries.ts +593 -0
- package/src/core/events/v3/producers/hook-base.ts +15 -3
- package/src/core/events/v3/producers/intake.ts +31 -2
- package/src/core/events/v3/producers/producer-state-observer.ts +52 -0
- package/src/core/events/v3/producers/recorder.ts +681 -34
- package/src/core/events/v3/reader.ts +243 -2
- package/src/core/events/v3/rotation-config.ts +98 -0
- package/src/core/events/v3/runtime-build.ts +41 -0
- package/src/core/events/v3/runtime-identity.ts +16 -0
- package/src/core/events/v3/runtime-telemetry-capabilities.ts +14 -8
- package/src/core/events/v3/support-storage/classify.ts +209 -0
- package/src/core/events/v3/support-storage/eligibility.ts +58 -0
- package/src/core/events/v3/support-storage/index.ts +9 -0
- package/src/core/events/v3/support-storage/inventory.ts +135 -0
- package/src/core/events/v3/support-storage/logical-authority.ts +117 -0
- package/src/core/events/v3/support-storage/maintenance.ts +501 -0
- package/src/core/events/v3/support-storage/pack-contract.ts +337 -0
- package/src/core/events/v3/support-storage/pack-reader.ts +346 -0
- package/src/core/events/v3/support-storage/pack-writer.ts +352 -0
- package/src/core/events/v3/support-storage/recovery.ts +43 -0
- package/src/core/events/v3/turn-telemetry.ts +58 -7
- package/src/core/events/v3/writer.ts +168 -16
- package/src/core/governor/plan-read.ts +5 -18
- package/src/core/governor/planning.ts +5 -8
- package/src/core/governor/service-read.ts +320 -2
- package/src/core/governor/service.ts +49 -22
- package/src/core/guard/evidence-v3.ts +1 -0
- package/src/core/hooks/adapter/events.ts +1 -0
- package/src/core/hooks/adapter/output.ts +23 -5
- package/src/core/hooks/adapter/runtime-telemetry.ts +408 -13
- package/src/core/hooks/cli.ts +404 -233
- package/src/core/hooks/effects/image-capture.ts +4 -1
- package/src/core/hooks/health.ts +146 -0
- package/src/core/hooks/remediation-cap.ts +12 -6
- package/src/core/hooks/resolve/coord-root.ts +91 -11
- package/src/core/hooks/resolve/owner.ts +4 -0
- package/src/core/hooks/resolve/transcript.ts +18 -0
- package/src/core/inbox/contract.ts +81 -0
- package/src/core/inbox/index.ts +4 -0
- package/src/core/inbox/lifecycle.ts +104 -0
- package/src/core/inbox/service.ts +305 -0
- package/src/core/inbox/watcher.ts +36 -0
- package/src/core/presence/codec-digest.ts +15 -9
- package/src/core/presence/relay-client.ts +55 -7
- package/src/core/resources/contract.ts +98 -0
- package/src/core/resources/index.ts +5 -0
- package/src/core/resources/sampler.ts +458 -0
- package/src/core/resources/service-status.ts +62 -0
- package/src/core/resources/service.ts +337 -0
- package/src/core/resources/storage.ts +44 -0
- package/src/core/semantic/adapters.ts +200 -41
- package/src/core/semantic/contract.ts +135 -3
- package/src/core/semantic/index.ts +76 -2
- package/src/core/semantic/once.ts +93 -7
- package/src/core/semantic/prompt.ts +13 -1
- package/src/core/semantic/review.ts +803 -0
- package/src/core/semantic/routes.ts +30 -0
- package/src/core/semantic/scheduler.ts +49 -5
- package/src/core/semantic/service-status.ts +99 -5
- package/src/core/semantic/service.ts +116 -15
- package/src/core/semantic/soak.ts +638 -0
- package/src/core/semantic/storage.ts +20 -6
- package/src/core/semantic/usage.ts +272 -0
- package/src/core/semantic/validate.ts +31 -0
- package/src/core/storage/atomic-json.ts +15 -0
- package/src/core/storage/buffer.ts +124 -0
- package/src/core/storage/builtins.ts +972 -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 +548 -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 +418 -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/supervisor/activity.ts +193 -0
- package/src/core/supervisor/contract.ts +312 -0
- package/src/core/supervisor/explanations.ts +104 -0
- package/src/core/supervisor/findings.ts +788 -0
- package/src/core/supervisor/history.ts +61 -0
- package/src/core/supervisor/hook-health-alerts.ts +108 -0
- package/src/core/supervisor/hook-health-storage.ts +25 -0
- package/src/core/supervisor/hook-health.ts +301 -0
- package/src/core/supervisor/hooks.ts +35 -0
- package/src/core/supervisor/index.ts +14 -0
- package/src/core/supervisor/log-feed.ts +131 -0
- package/src/core/supervisor/service.ts +511 -0
- package/src/core/supervisor/services.ts +203 -0
- package/src/core/supervisor/status.ts +59 -0
- package/src/core/supervisor/storage.ts +126 -0
- package/src/core/supervisor/timeline.ts +133 -0
- package/src/core/work/state.ts +12 -21
- package/src/core/workflow/admission.ts +215 -0
- package/src/core/workflow/engine.ts +93 -1
- package/src/core/workflow/index.ts +10 -0
- package/src/core/workflow/live-session-v3.ts +2 -4
- package/src/core/workflow/proof.ts +54 -1
- package/src/core/workflow/run-state.ts +13 -1
- package/src/core/workflow/types.ts +39 -1
- package/src/index.ts +2 -0
- package/src/lazy-commands.ts +294 -0
- package/src/lib/browser/client.ts +6 -0
- package/src/lib/browser/index.ts +29 -0
- package/src/lib/browser/qa-run-contracts.ts +380 -0
- package/src/lib/browser/qa-run.ts +784 -0
- package/src/lib/coord-root-id.ts +23 -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 +81 -2
- package/src/lib/instructions/templates.ts +11 -0
- package/src/lib/local-file-url.ts +31 -0
- package/src/lib/web-performance.ts +335 -0
|
@@ -0,0 +1,784 @@
|
|
|
1
|
+
// One-command page-QA matrix runner: planner, deterministic gates per
|
|
2
|
+
// context, interaction assertions, manifest-required critique, and the QA
|
|
3
|
+
// snapshot — executed as child `browse` processes through a bounded pool, and
|
|
4
|
+
// reported as one fail-closed machine-readable result.
|
|
5
|
+
//
|
|
6
|
+
// The runner never builds a shell string: every child is an argv array handed
|
|
7
|
+
// to an injectable exec function (default: node:child_process execFile with a
|
|
8
|
+
// closed stdin, bounded output, and an explicit timeout). Every child that
|
|
9
|
+
// fails, times out, or dies silently becomes a named blocker or a failed
|
|
10
|
+
// outcome in the result — nothing is filtered away.
|
|
11
|
+
//
|
|
12
|
+
// Toolkit tier: this module must not import src/core (layering check).
|
|
13
|
+
|
|
14
|
+
import { execFile } from "node:child_process";
|
|
15
|
+
import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
16
|
+
import { join } from "node:path";
|
|
17
|
+
import type { QaManifest } from "./qa-plan.js";
|
|
18
|
+
import {
|
|
19
|
+
computeVerdict,
|
|
20
|
+
mergeCoverage,
|
|
21
|
+
QA_RUN_RESULT_SCHEMA_VERSION,
|
|
22
|
+
type QaRunBlocker,
|
|
23
|
+
type QaRunCommandOutcome,
|
|
24
|
+
type QaRunContext,
|
|
25
|
+
type QaRunCritiqueOutcome,
|
|
26
|
+
type QaRunJob,
|
|
27
|
+
type QaRunResult,
|
|
28
|
+
} from "./qa-run-contracts.js";
|
|
29
|
+
|
|
30
|
+
/** Set on critique children unless the job permits metered critique: the
|
|
31
|
+
* host's critique provider must stay on subscription-backed headless
|
|
32
|
+
* harnesses and surface exhaustion instead of falling back to a metered API. */
|
|
33
|
+
export const QA_RUN_HEADLESS_ONLY_ENV = "HARNERY_CRITIQUE_HEADLESS_ONLY";
|
|
34
|
+
|
|
35
|
+
/** Result document written into the run's output directory. */
|
|
36
|
+
export const QA_RUN_RESULT_FILENAME = "page-qa-result.json";
|
|
37
|
+
|
|
38
|
+
const DEFAULT_COMMAND_TIMEOUT_MS = 120_000;
|
|
39
|
+
const DEFAULT_COMMAND_CONCURRENCY = 2;
|
|
40
|
+
const EXEC_MAX_BUFFER = 16 * 1024 * 1024;
|
|
41
|
+
|
|
42
|
+
/** The planner's deterministic vocabulary is an executable contract, not a
|
|
43
|
+
* report-only hint. A job may add checks, but these arguments always run for
|
|
44
|
+
* every manifest context. `console` is enforced from the browse envelope
|
|
45
|
+
* because browse captures diagnostics without a separate fail flag. */
|
|
46
|
+
const MANIFEST_DETERMINISTIC_ARGS: Readonly<Record<string, readonly string[]>> = {
|
|
47
|
+
console: [],
|
|
48
|
+
overflow: ["--check-overflow", "--check-overflow-fail"],
|
|
49
|
+
truncation: ["--check-truncation", "--check-truncation-fail"],
|
|
50
|
+
placeholder: ["--check-placeholder", "--check-placeholder-fail"],
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export interface QaRunExecOptions {
|
|
54
|
+
/** Hard per-command timeout in milliseconds. */
|
|
55
|
+
timeoutMs: number;
|
|
56
|
+
/** Complete child environment (already layered by the runner). */
|
|
57
|
+
env: NodeJS.ProcessEnv;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export interface QaRunExecResult {
|
|
61
|
+
/** Process exit code; null when the command never completed normally. */
|
|
62
|
+
exitCode: number | null;
|
|
63
|
+
stdout: string;
|
|
64
|
+
stderr: string;
|
|
65
|
+
/** Spawn failure / timeout / signal description. Presence means the
|
|
66
|
+
* command's outcome cannot be trusted. */
|
|
67
|
+
error?: string;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Injectable child-process executor. `argv[0]` is the executable. */
|
|
71
|
+
export type QaRunExec = (argv: string[], options: QaRunExecOptions) => Promise<QaRunExecResult>;
|
|
72
|
+
|
|
73
|
+
/** Default executor: execFile with argv arrays only (never a shell string),
|
|
74
|
+
* closed stdin, bounded output buffers, and the policy timeout. */
|
|
75
|
+
export const defaultQaRunExec: QaRunExec = (argv, options) =>
|
|
76
|
+
new Promise((resolvePromise) => {
|
|
77
|
+
const [command, ...args] = argv;
|
|
78
|
+
if (!command) {
|
|
79
|
+
resolvePromise({ exitCode: null, stdout: "", stderr: "", error: "empty argv" });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
const child = execFile(
|
|
83
|
+
command,
|
|
84
|
+
args,
|
|
85
|
+
{
|
|
86
|
+
timeout: options.timeoutMs,
|
|
87
|
+
maxBuffer: EXEC_MAX_BUFFER,
|
|
88
|
+
env: options.env,
|
|
89
|
+
killSignal: "SIGTERM",
|
|
90
|
+
},
|
|
91
|
+
(err, stdout, stderr) => {
|
|
92
|
+
const out = String(stdout ?? "");
|
|
93
|
+
const errOut = String(stderr ?? "");
|
|
94
|
+
if (!err) {
|
|
95
|
+
resolvePromise({ exitCode: 0, stdout: out, stderr: errOut });
|
|
96
|
+
return;
|
|
97
|
+
}
|
|
98
|
+
const failure = err as NodeJS.ErrnoException & {
|
|
99
|
+
code?: number | string;
|
|
100
|
+
killed?: boolean;
|
|
101
|
+
signal?: NodeJS.Signals | null;
|
|
102
|
+
};
|
|
103
|
+
if (typeof failure.code === "number") {
|
|
104
|
+
// Completed with a nonzero exit code: a real outcome, not an error.
|
|
105
|
+
resolvePromise({ exitCode: failure.code, stdout: out, stderr: errOut });
|
|
106
|
+
return;
|
|
107
|
+
}
|
|
108
|
+
const reason =
|
|
109
|
+
failure.killed || failure.signal
|
|
110
|
+
? `killed by ${failure.signal ?? "signal"} (timeout ${options.timeoutMs}ms)`
|
|
111
|
+
: failure.message || "spawn failed";
|
|
112
|
+
resolvePromise({ exitCode: null, stdout: out, stderr: errOut, error: reason });
|
|
113
|
+
},
|
|
114
|
+
);
|
|
115
|
+
child.stdin?.end();
|
|
116
|
+
});
|
|
117
|
+
|
|
118
|
+
export interface QaRunMatrixOptions {
|
|
119
|
+
/** A validated job (see validateQaRunJob — the runner trusts its shape). */
|
|
120
|
+
job: QaRunJob;
|
|
121
|
+
/** Directory for artifacts and the result document. Created if missing. */
|
|
122
|
+
outDir: string;
|
|
123
|
+
/** argv prefix that reaches the host CLI's browse command, e.g.
|
|
124
|
+
* `[process.execPath, cliScript, "browse"]`. */
|
|
125
|
+
browseArgv: string[];
|
|
126
|
+
/** Injectable executor (tests). Default: execFile via defaultQaRunExec. */
|
|
127
|
+
exec?: QaRunExec;
|
|
128
|
+
/** Extra child-environment overrides layered over process.env. */
|
|
129
|
+
childEnv?: NodeJS.ProcessEnv;
|
|
130
|
+
/** Progress callback for human-facing per-stage lines. */
|
|
131
|
+
onLog?: (message: string) => void;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
interface TimedExec {
|
|
135
|
+
res: QaRunExecResult;
|
|
136
|
+
wallTimeMs: number;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
/** One-line tail excerpt of a failed child's output for blockers and
|
|
140
|
+
* failures, preferring stderr and falling back to stdout (browse prints its
|
|
141
|
+
* JSON error envelope there). Without this, a blocker like "planner exited 1"
|
|
142
|
+
* gives the reader nothing to act on. */
|
|
143
|
+
function execErrorExcerpt(res: QaRunExecResult, maxLength = 240): string | undefined {
|
|
144
|
+
const source = res.stderr.trim().length > 0 ? res.stderr : res.stdout;
|
|
145
|
+
const flat = source.trim().replace(/\s+/g, " ");
|
|
146
|
+
if (flat.length === 0) return undefined;
|
|
147
|
+
return flat.length > maxLength ? `…${flat.slice(-maxLength)}` : flat;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/** Fixed-size promise pool: at most `limit` workers in flight, items claimed
|
|
151
|
+
* in order, results written by index so completion order never matters. */
|
|
152
|
+
async function runPool<T>(
|
|
153
|
+
items: readonly T[],
|
|
154
|
+
limit: number,
|
|
155
|
+
worker: (item: T, index: number) => Promise<void>,
|
|
156
|
+
): Promise<void> {
|
|
157
|
+
let next = 0;
|
|
158
|
+
const lanes = Array.from(
|
|
159
|
+
{ length: Math.max(1, Math.min(limit, items.length)) },
|
|
160
|
+
async (): Promise<void> => {
|
|
161
|
+
while (true) {
|
|
162
|
+
const index = next;
|
|
163
|
+
next += 1;
|
|
164
|
+
if (index >= items.length) return;
|
|
165
|
+
const item = items[index] as T;
|
|
166
|
+
await worker(item, index);
|
|
167
|
+
}
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
await Promise.all(lanes);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function readEnvelope(jsonPath: string): Record<string, unknown> | undefined {
|
|
174
|
+
try {
|
|
175
|
+
const parsed: unknown = JSON.parse(readFileSync(jsonPath, "utf8"));
|
|
176
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
177
|
+
return parsed as Record<string, unknown>;
|
|
178
|
+
}
|
|
179
|
+
} catch {
|
|
180
|
+
// Best-effort: a missing or unparseable artifact is handled by the caller.
|
|
181
|
+
}
|
|
182
|
+
return undefined;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function gatherArtifacts(outPrefix: string): QaRunCommandOutcome["artifacts"] {
|
|
186
|
+
const artifacts: QaRunCommandOutcome["artifacts"] = {};
|
|
187
|
+
const png = `${outPrefix}.png`;
|
|
188
|
+
const html = `${outPrefix}.html`;
|
|
189
|
+
const json = `${outPrefix}.json`;
|
|
190
|
+
if (existsSync(png)) artifacts.png = png;
|
|
191
|
+
if (existsSync(html)) artifacts.html = html;
|
|
192
|
+
if (existsSync(json)) artifacts.json = json;
|
|
193
|
+
return artifacts;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/** Best-effort extraction of failing-check details from a browse JSON
|
|
197
|
+
* envelope. The exit-code entry the caller records is the guaranteed
|
|
198
|
+
* minimum; these lines add human-readable specifics when parseable. */
|
|
199
|
+
function parseGateFailures(envelope: Record<string, unknown> | undefined): string[] {
|
|
200
|
+
if (!envelope) return [];
|
|
201
|
+
const failures: string[] = [];
|
|
202
|
+
const overflow = envelope.overflow as
|
|
203
|
+
| { hasHorizontalOverflow?: boolean; overflowPx?: number }
|
|
204
|
+
| undefined;
|
|
205
|
+
if (overflow?.hasHorizontalOverflow) {
|
|
206
|
+
failures.push(`overflow: +${overflow.overflowPx ?? "?"}px horizontal overflow`);
|
|
207
|
+
}
|
|
208
|
+
const asserts = envelope.asserts as
|
|
209
|
+
| Array<{ op?: string; selector?: string; outcome?: string; actual?: string }>
|
|
210
|
+
| undefined;
|
|
211
|
+
for (const entry of asserts ?? []) {
|
|
212
|
+
if (entry.outcome === "fail") {
|
|
213
|
+
failures.push(`assert ${entry.op ?? "?"} ${entry.selector ?? "?"} → "${entry.actual ?? ""}"`);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
const visibility = envelope.visibility as
|
|
217
|
+
| Array<{ selector?: string; found?: boolean; cssVisible?: boolean; visibleRatio?: number }>
|
|
218
|
+
| undefined;
|
|
219
|
+
for (const entry of visibility ?? []) {
|
|
220
|
+
if (entry.found === false) failures.push(`visibility ${entry.selector ?? "?"}: not found`);
|
|
221
|
+
else if (entry.cssVisible === false) {
|
|
222
|
+
failures.push(`visibility ${entry.selector ?? "?"}: CSS-hidden`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
const critique = envelope.critique as
|
|
226
|
+
| { outcome?: string; findings?: Array<{ severity?: string; description?: string }> }
|
|
227
|
+
| undefined;
|
|
228
|
+
if (critique?.outcome === "fail") {
|
|
229
|
+
for (const finding of critique.findings ?? []) {
|
|
230
|
+
failures.push(`critique [${finding.severity ?? "?"}]: ${finding.description ?? ""}`);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return failures;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
function diagnosticSummary(entry: unknown): string {
|
|
237
|
+
if (typeof entry === "string") return entry;
|
|
238
|
+
if (entry && typeof entry === "object" && !Array.isArray(entry)) {
|
|
239
|
+
const record = entry as Record<string, unknown>;
|
|
240
|
+
for (const key of ["text", "message", "errorText", "failure", "url"]) {
|
|
241
|
+
const value = record[key];
|
|
242
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
return JSON.stringify(entry);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
/** `console` in the planner contract covers every browser diagnostic that the
|
|
249
|
+
* browse envelope records. Keep the first three details actionable and name
|
|
250
|
+
* any remainder without allowing an unbounded page log to bloat the result. */
|
|
251
|
+
function parseConsoleFailures(envelope: Record<string, unknown> | undefined): string[] {
|
|
252
|
+
if (!envelope) return [];
|
|
253
|
+
const failures: string[] = [];
|
|
254
|
+
const groups: Array<[string, unknown]> = [
|
|
255
|
+
["console", envelope.consoleErrors],
|
|
256
|
+
["page", envelope.pageErrors],
|
|
257
|
+
["request", envelope.failedRequests],
|
|
258
|
+
];
|
|
259
|
+
for (const [label, value] of groups) {
|
|
260
|
+
if (!Array.isArray(value) || value.length === 0) continue;
|
|
261
|
+
for (const entry of value.slice(0, 3)) failures.push(`${label}: ${diagnosticSummary(entry)}`);
|
|
262
|
+
if (value.length > 3) failures.push(`${label}: ${value.length - 3} additional failure(s)`);
|
|
263
|
+
}
|
|
264
|
+
return failures;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
interface EnvelopeCritique {
|
|
268
|
+
tiles?: number;
|
|
269
|
+
provider?: boolean;
|
|
270
|
+
outcome?: string;
|
|
271
|
+
findings?: Array<{ severity?: string; category?: string; description?: string }>;
|
|
272
|
+
provider_meta?: Record<string, unknown>;
|
|
273
|
+
error?: string;
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
function providerLabel(critique: EnvelopeCritique | undefined): string {
|
|
277
|
+
const meta = critique?.provider_meta;
|
|
278
|
+
if (meta) {
|
|
279
|
+
for (const key of ["provider", "route", "model"]) {
|
|
280
|
+
const value = meta[key];
|
|
281
|
+
if (typeof value === "string" && value.length > 0) return value;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
return critique?.provider ? "host" : "none";
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
/**
|
|
288
|
+
* Execute the whole QA matrix for one validated job and return the result
|
|
289
|
+
* (also written to `<outDir>/page-qa-result.json`). Stages: plan →
|
|
290
|
+
* deterministic gates (bounded pool) → interactions (serial) → critique (one
|
|
291
|
+
* context at a time; the critique provider owns tile concurrency) → snapshot.
|
|
292
|
+
* The verdict is computeVerdict over everything recorded — fail-closed.
|
|
293
|
+
*/
|
|
294
|
+
export async function runQaMatrix(options: QaRunMatrixOptions): Promise<QaRunResult> {
|
|
295
|
+
const { job, outDir, browseArgv } = options;
|
|
296
|
+
const exec = options.exec ?? defaultQaRunExec;
|
|
297
|
+
const log = options.onLog ?? (() => {});
|
|
298
|
+
const timeoutMs = job.policy?.command_timeout_ms ?? DEFAULT_COMMAND_TIMEOUT_MS;
|
|
299
|
+
const concurrency = job.policy?.command_concurrency ?? DEFAULT_COMMAND_CONCURRENCY;
|
|
300
|
+
mkdirSync(outDir, { recursive: true });
|
|
301
|
+
|
|
302
|
+
const startedAt = Date.now();
|
|
303
|
+
const wall = { plan: 0, gates: 0, interactions: 0, critique: 0, snapshot: 0, total: 0 };
|
|
304
|
+
const blockers: QaRunBlocker[] = [];
|
|
305
|
+
const commands: QaRunCommandOutcome[] = [];
|
|
306
|
+
const critique: QaRunCritiqueOutcome[] = [];
|
|
307
|
+
let manifest: QaManifest | null = null;
|
|
308
|
+
let contexts: QaRunContext[] = [];
|
|
309
|
+
let snapshot: QaRunResult["snapshot"] = { saved: false };
|
|
310
|
+
|
|
311
|
+
const baseEnv: NodeJS.ProcessEnv = { ...process.env, ...options.childEnv };
|
|
312
|
+
|
|
313
|
+
const timedExec = async (argv: string[], env: NodeJS.ProcessEnv): Promise<TimedExec> => {
|
|
314
|
+
const started = Date.now();
|
|
315
|
+
let res: QaRunExecResult;
|
|
316
|
+
try {
|
|
317
|
+
res = await exec(argv, { timeoutMs, env });
|
|
318
|
+
} catch (err: unknown) {
|
|
319
|
+
res = {
|
|
320
|
+
exitCode: null,
|
|
321
|
+
stdout: "",
|
|
322
|
+
stderr: "",
|
|
323
|
+
error: err instanceof Error ? err.message : String(err),
|
|
324
|
+
};
|
|
325
|
+
}
|
|
326
|
+
return { res, wallTimeMs: Date.now() - started };
|
|
327
|
+
};
|
|
328
|
+
|
|
329
|
+
const finalize = (): QaRunResult => {
|
|
330
|
+
wall.total = Date.now() - startedAt;
|
|
331
|
+
const result: QaRunResult = {
|
|
332
|
+
schema_version: QA_RUN_RESULT_SCHEMA_VERSION,
|
|
333
|
+
target: job.target,
|
|
334
|
+
...(job.tested_revision !== undefined ? { tested_revision: job.tested_revision } : {}),
|
|
335
|
+
mode: job.mode,
|
|
336
|
+
qa_plan: manifest,
|
|
337
|
+
contexts,
|
|
338
|
+
commands,
|
|
339
|
+
critique,
|
|
340
|
+
snapshot,
|
|
341
|
+
wall_time_ms: { ...wall },
|
|
342
|
+
blockers,
|
|
343
|
+
verdict: computeVerdict({
|
|
344
|
+
mode: job.mode,
|
|
345
|
+
blockers,
|
|
346
|
+
commands,
|
|
347
|
+
critique,
|
|
348
|
+
snapshotSaved: snapshot.saved,
|
|
349
|
+
}),
|
|
350
|
+
};
|
|
351
|
+
writeFileSync(join(outDir, QA_RUN_RESULT_FILENAME), `${JSON.stringify(result, null, 2)}\n`);
|
|
352
|
+
return result;
|
|
353
|
+
};
|
|
354
|
+
|
|
355
|
+
// Base render arguments shared by every per-context invocation.
|
|
356
|
+
const contextRenderArgs = (ctx: QaRunContext): string[] => [
|
|
357
|
+
"--viewport",
|
|
358
|
+
ctx.viewport,
|
|
359
|
+
...(ctx.theme === "dark" ? ["--color-scheme", "dark"] : []),
|
|
360
|
+
...(ctx.args ?? []),
|
|
361
|
+
];
|
|
362
|
+
|
|
363
|
+
// ------------------------------------------------------------------ plan
|
|
364
|
+
const planArgv = [
|
|
365
|
+
...browseArgv,
|
|
366
|
+
job.target,
|
|
367
|
+
"--qa-plan",
|
|
368
|
+
"--json",
|
|
369
|
+
"--no-screenshot",
|
|
370
|
+
...(job.qa_hints?.scopes ?? []).flatMap((selector) => ["--qa-scope", selector]),
|
|
371
|
+
...(job.qa_hints?.states?.length ? ["--qa-states", job.qa_hints.states.join(",")] : []),
|
|
372
|
+
];
|
|
373
|
+
log(`plan: ${job.target}`);
|
|
374
|
+
const planStart = Date.now();
|
|
375
|
+
const plan = await timedExec(planArgv, baseEnv);
|
|
376
|
+
wall.plan = Date.now() - planStart;
|
|
377
|
+
let planEnvelope: Record<string, unknown> | undefined;
|
|
378
|
+
if (!plan.res.error && plan.res.exitCode === 0) {
|
|
379
|
+
try {
|
|
380
|
+
const parsed: unknown = JSON.parse(plan.res.stdout);
|
|
381
|
+
if (parsed && typeof parsed === "object" && !Array.isArray(parsed)) {
|
|
382
|
+
planEnvelope = parsed as Record<string, unknown>;
|
|
383
|
+
}
|
|
384
|
+
} catch {
|
|
385
|
+
// handled below as a plan blocker
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
const qaPlanReport = planEnvelope?.qaPlan as { manifest?: QaManifest } | undefined;
|
|
389
|
+
manifest = qaPlanReport?.manifest ?? null;
|
|
390
|
+
const planUsable = manifest !== null && !manifest.incomplete && plan.res.exitCode === 0;
|
|
391
|
+
commands.push({
|
|
392
|
+
context_id: "plan",
|
|
393
|
+
check_id: "plan",
|
|
394
|
+
argv: planArgv,
|
|
395
|
+
exit_code: plan.res.exitCode,
|
|
396
|
+
outcome: planUsable ? "passed" : "unknown",
|
|
397
|
+
failures: planUsable
|
|
398
|
+
? []
|
|
399
|
+
: [plan.res.error, execErrorExcerpt(plan.res)].filter((entry): entry is string =>
|
|
400
|
+
Boolean(entry),
|
|
401
|
+
),
|
|
402
|
+
artifacts: {},
|
|
403
|
+
wall_time_ms: plan.wallTimeMs,
|
|
404
|
+
});
|
|
405
|
+
if (plan.res.error) {
|
|
406
|
+
blockers.push({ stage: "plan", reason: `planner command did not complete: ${plan.res.error}` });
|
|
407
|
+
} else if (plan.res.exitCode !== 0) {
|
|
408
|
+
const excerpt = execErrorExcerpt(plan.res);
|
|
409
|
+
blockers.push({
|
|
410
|
+
stage: "plan",
|
|
411
|
+
reason: `planner exited ${plan.res.exitCode}${excerpt ? `: ${excerpt}` : ""}`,
|
|
412
|
+
});
|
|
413
|
+
} else if (!manifest) {
|
|
414
|
+
blockers.push({
|
|
415
|
+
stage: "plan",
|
|
416
|
+
reason: "planner envelope carried no parseable qaPlan.manifest",
|
|
417
|
+
});
|
|
418
|
+
} else if (manifest.incomplete) {
|
|
419
|
+
blockers.push({
|
|
420
|
+
stage: "plan",
|
|
421
|
+
reason: `planner manifest is incomplete: ${manifest.incomplete.reason}`,
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
if (!planUsable || !manifest) {
|
|
425
|
+
// Stop before any further browser work: an untrusted plan cannot gate.
|
|
426
|
+
contexts = manifest ? mergeCoverage(manifest, job) : [];
|
|
427
|
+
return finalize();
|
|
428
|
+
}
|
|
429
|
+
|
|
430
|
+
// ----------------------------------------------------------------- gates
|
|
431
|
+
contexts = mergeCoverage(manifest, job);
|
|
432
|
+
const unsupportedDeterministic = manifest.checks.deterministic.filter(
|
|
433
|
+
(check) => MANIFEST_DETERMINISTIC_ARGS[check] === undefined,
|
|
434
|
+
);
|
|
435
|
+
if (unsupportedDeterministic.length > 0) {
|
|
436
|
+
for (const check of unsupportedDeterministic) {
|
|
437
|
+
blockers.push({
|
|
438
|
+
stage: "gates",
|
|
439
|
+
reason:
|
|
440
|
+
`planner requires deterministic check "${check}" but qa-run has no executable ` +
|
|
441
|
+
"mapping for it — coverage cannot be narrowed",
|
|
442
|
+
});
|
|
443
|
+
}
|
|
444
|
+
return finalize();
|
|
445
|
+
}
|
|
446
|
+
const manifestGateArgs = manifest.checks.deterministic.flatMap(
|
|
447
|
+
(check) => MANIFEST_DETERMINISTIC_ARGS[check] ?? [],
|
|
448
|
+
);
|
|
449
|
+
const enforceConsole = manifest.checks.deterministic.includes("console");
|
|
450
|
+
const checks = job.checks ?? [];
|
|
451
|
+
const gateOutcomes = new Array<QaRunCommandOutcome>(contexts.length);
|
|
452
|
+
const gatesStart = Date.now();
|
|
453
|
+
await runPool(contexts, concurrency, async (ctx, index) => {
|
|
454
|
+
const applicable = checks.filter(
|
|
455
|
+
(check) => check.contexts === undefined || check.contexts.includes(ctx.id),
|
|
456
|
+
);
|
|
457
|
+
const checkId =
|
|
458
|
+
[
|
|
459
|
+
...manifest.checks.deterministic.map((check) => `manifest:${check}`),
|
|
460
|
+
...applicable.map((check) => check.id),
|
|
461
|
+
].join("+") || "capture";
|
|
462
|
+
const outPrefix = join(outDir, ctx.id);
|
|
463
|
+
const argv = [
|
|
464
|
+
...browseArgv,
|
|
465
|
+
job.target,
|
|
466
|
+
...contextRenderArgs(ctx),
|
|
467
|
+
"--out",
|
|
468
|
+
outPrefix,
|
|
469
|
+
...manifestGateArgs,
|
|
470
|
+
...applicable.flatMap((check) => check.args),
|
|
471
|
+
];
|
|
472
|
+
log(`gate ${ctx.id}: ${checkId}`);
|
|
473
|
+
const { res, wallTimeMs } = await timedExec(argv, baseEnv);
|
|
474
|
+
const jsonPath = `${outPrefix}.json`;
|
|
475
|
+
const failures: string[] = [];
|
|
476
|
+
let outcome: QaRunCommandOutcome["outcome"];
|
|
477
|
+
const envelope = existsSync(jsonPath) ? readEnvelope(jsonPath) : undefined;
|
|
478
|
+
const consoleFailures = enforceConsole ? parseConsoleFailures(envelope) : [];
|
|
479
|
+
if (!res.error && res.exitCode === 0 && existsSync(jsonPath)) {
|
|
480
|
+
if (consoleFailures.length > 0) {
|
|
481
|
+
outcome = "failed";
|
|
482
|
+
failures.push(...consoleFailures);
|
|
483
|
+
} else {
|
|
484
|
+
outcome = "passed";
|
|
485
|
+
}
|
|
486
|
+
} else if (!res.error && res.exitCode === 2 && existsSync(jsonPath)) {
|
|
487
|
+
outcome = "failed";
|
|
488
|
+
failures.push(`exit code 2 (${jsonPath})`);
|
|
489
|
+
failures.push(...parseGateFailures(envelope), ...consoleFailures);
|
|
490
|
+
} else {
|
|
491
|
+
outcome = "unknown";
|
|
492
|
+
const excerpt = execErrorExcerpt(res);
|
|
493
|
+
const base = res.error
|
|
494
|
+
? res.error
|
|
495
|
+
: !existsSync(jsonPath)
|
|
496
|
+
? `exit code ${res.exitCode ?? "null"}, missing JSON artifact ${jsonPath}`
|
|
497
|
+
: `exit code ${res.exitCode ?? "null"}`;
|
|
498
|
+
const reason = excerpt ? `${base}: ${excerpt}` : base;
|
|
499
|
+
failures.push(reason);
|
|
500
|
+
blockers.push({
|
|
501
|
+
stage: "gates",
|
|
502
|
+
context_id: ctx.id,
|
|
503
|
+
reason: `gate command did not complete: ${reason}`,
|
|
504
|
+
});
|
|
505
|
+
}
|
|
506
|
+
gateOutcomes[index] = {
|
|
507
|
+
context_id: ctx.id,
|
|
508
|
+
check_id: checkId,
|
|
509
|
+
argv,
|
|
510
|
+
exit_code: res.exitCode,
|
|
511
|
+
outcome,
|
|
512
|
+
failures,
|
|
513
|
+
artifacts: gatherArtifacts(outPrefix),
|
|
514
|
+
wall_time_ms: wallTimeMs,
|
|
515
|
+
};
|
|
516
|
+
});
|
|
517
|
+
wall.gates = Date.now() - gatesStart;
|
|
518
|
+
// Manifest order regardless of completion order: outcomes were written by
|
|
519
|
+
// context index, so a straight push preserves it.
|
|
520
|
+
commands.push(...gateOutcomes);
|
|
521
|
+
|
|
522
|
+
// ---------------------------------------------------------- interactions
|
|
523
|
+
const interactionsStart = Date.now();
|
|
524
|
+
const declaredStates = new Set((job.interaction_states ?? []).map((state) => state.name));
|
|
525
|
+
const manifestStates = [
|
|
526
|
+
...new Set(
|
|
527
|
+
manifest.contexts.map((context) => context.state).filter((state) => state !== "default"),
|
|
528
|
+
),
|
|
529
|
+
];
|
|
530
|
+
for (const state of manifestStates) {
|
|
531
|
+
if (!declaredStates.has(state)) {
|
|
532
|
+
blockers.push({
|
|
533
|
+
stage: "interactions",
|
|
534
|
+
reason:
|
|
535
|
+
`manifest requires interaction state "${state}" but the job declares no matching ` +
|
|
536
|
+
"interaction_states entry — job coverage may never be narrower than the manifest",
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
for (const state of job.interaction_states ?? []) {
|
|
541
|
+
const outPrefix = join(outDir, `interaction-${state.name}`);
|
|
542
|
+
const argv = [
|
|
543
|
+
...browseArgv,
|
|
544
|
+
job.target,
|
|
545
|
+
"--out",
|
|
546
|
+
outPrefix,
|
|
547
|
+
...state.setup,
|
|
548
|
+
...state.assertions.flatMap((assertion) => ["--assert", assertion]),
|
|
549
|
+
"--assert-fail",
|
|
550
|
+
];
|
|
551
|
+
log(`interaction ${state.name}`);
|
|
552
|
+
const { res, wallTimeMs } = await timedExec(argv, baseEnv);
|
|
553
|
+
const jsonPath = `${outPrefix}.json`;
|
|
554
|
+
const failures: string[] = [];
|
|
555
|
+
let outcome: QaRunCommandOutcome["outcome"];
|
|
556
|
+
if (!res.error && res.exitCode === 0 && existsSync(jsonPath)) {
|
|
557
|
+
outcome = "passed";
|
|
558
|
+
} else if (!res.error && res.exitCode === 2 && existsSync(jsonPath)) {
|
|
559
|
+
outcome = "failed";
|
|
560
|
+
failures.push(`exit code 2 (${jsonPath})`);
|
|
561
|
+
failures.push(...parseGateFailures(readEnvelope(jsonPath)));
|
|
562
|
+
} else {
|
|
563
|
+
outcome = "unknown";
|
|
564
|
+
const excerpt = execErrorExcerpt(res);
|
|
565
|
+
const base = res.error
|
|
566
|
+
? res.error
|
|
567
|
+
: !existsSync(jsonPath)
|
|
568
|
+
? `exit code ${res.exitCode ?? "null"}, missing JSON artifact ${jsonPath}`
|
|
569
|
+
: `exit code ${res.exitCode ?? "null"}`;
|
|
570
|
+
const reason = excerpt ? `${base}: ${excerpt}` : base;
|
|
571
|
+
failures.push(reason);
|
|
572
|
+
blockers.push({
|
|
573
|
+
stage: "interactions",
|
|
574
|
+
context_id: state.name,
|
|
575
|
+
reason: `interaction command did not complete: ${reason}`,
|
|
576
|
+
});
|
|
577
|
+
}
|
|
578
|
+
commands.push({
|
|
579
|
+
context_id: state.name,
|
|
580
|
+
check_id: `interaction:${state.name}`,
|
|
581
|
+
argv,
|
|
582
|
+
exit_code: res.exitCode,
|
|
583
|
+
outcome,
|
|
584
|
+
failures,
|
|
585
|
+
artifacts: gatherArtifacts(outPrefix),
|
|
586
|
+
wall_time_ms: wallTimeMs,
|
|
587
|
+
});
|
|
588
|
+
}
|
|
589
|
+
wall.interactions = Date.now() - interactionsStart;
|
|
590
|
+
|
|
591
|
+
// -------------------------------------------------------------- critique
|
|
592
|
+
const visual = manifest.checks.visual;
|
|
593
|
+
const cleanSoFar =
|
|
594
|
+
blockers.length === 0 && commands.every((command) => command.outcome === "passed");
|
|
595
|
+
const critiqueStart = Date.now();
|
|
596
|
+
const savedSnapshots = new Map<string, string>();
|
|
597
|
+
if (cleanSoFar && visual !== "none") {
|
|
598
|
+
const critiqueEnv: NodeJS.ProcessEnv = job.policy?.allow_metered_critique
|
|
599
|
+
? { ...baseEnv }
|
|
600
|
+
: { ...baseEnv, [QA_RUN_HEADLESS_ONLY_ENV]: "1" };
|
|
601
|
+
const scopeSelectors =
|
|
602
|
+
visual === "full-page" ? [undefined] : manifest.scopes.map((s) => s.selector);
|
|
603
|
+
for (const ctx of contexts) {
|
|
604
|
+
let tilesTotal = 0;
|
|
605
|
+
let tilesReviewed = 0;
|
|
606
|
+
let tilesReused = 0;
|
|
607
|
+
let provider = "none";
|
|
608
|
+
let contextOutcome: QaRunCritiqueOutcome["outcome"] = "passed";
|
|
609
|
+
const findings: QaRunCritiqueOutcome["findings"] = [];
|
|
610
|
+
for (const [scopeIndex, selector] of scopeSelectors.entries()) {
|
|
611
|
+
const suffix = scopeSelectors.length > 1 ? `-scope${scopeIndex}` : "";
|
|
612
|
+
const outPrefix = join(outDir, `${ctx.id}-critique${suffix}`);
|
|
613
|
+
const argv = [
|
|
614
|
+
...browseArgv,
|
|
615
|
+
job.target,
|
|
616
|
+
...contextRenderArgs(ctx),
|
|
617
|
+
"--out",
|
|
618
|
+
outPrefix,
|
|
619
|
+
...(selector !== undefined ? ["--check-critique", selector] : ["--check-critique"]),
|
|
620
|
+
"--check-critique-fail",
|
|
621
|
+
...(manifest.baseline_source !== "none" ? ["--qa-reuse"] : []),
|
|
622
|
+
...(job.mode === "signoff"
|
|
623
|
+
? ["--qa-snapshot", "--qa-theme", ctx.theme, "--qa-state", ctx.state]
|
|
624
|
+
: []),
|
|
625
|
+
];
|
|
626
|
+
log(`critique ${ctx.id}${selector !== undefined ? ` [${selector}]` : ""}`);
|
|
627
|
+
const { res, wallTimeMs } = await timedExec(argv, critiqueEnv);
|
|
628
|
+
const jsonPath = `${outPrefix}.json`;
|
|
629
|
+
const envelope = readEnvelope(jsonPath);
|
|
630
|
+
const envelopeCritique = envelope?.critique as EnvelopeCritique | undefined;
|
|
631
|
+
const failures: string[] = [];
|
|
632
|
+
let commandOutcome: QaRunCommandOutcome["outcome"];
|
|
633
|
+
if (res.error || (res.exitCode !== 0 && res.exitCode !== 2) || !envelope) {
|
|
634
|
+
commandOutcome = "unknown";
|
|
635
|
+
const excerpt = execErrorExcerpt(res);
|
|
636
|
+
const base = res.error
|
|
637
|
+
? res.error
|
|
638
|
+
: !envelope
|
|
639
|
+
? `exit code ${res.exitCode ?? "null"}, missing JSON artifact ${jsonPath}`
|
|
640
|
+
: `exit code ${res.exitCode ?? "null"}`;
|
|
641
|
+
const reason = excerpt ? `${base}: ${excerpt}` : base;
|
|
642
|
+
failures.push(reason);
|
|
643
|
+
blockers.push({
|
|
644
|
+
stage: "critique",
|
|
645
|
+
context_id: ctx.id,
|
|
646
|
+
reason: `critique command did not complete: ${reason}`,
|
|
647
|
+
});
|
|
648
|
+
contextOutcome = "unknown";
|
|
649
|
+
} else {
|
|
650
|
+
tilesTotal += envelopeCritique?.tiles ?? 0;
|
|
651
|
+
const reuse = envelope.qaReuse as
|
|
652
|
+
| { tiles_reused?: number; tiles_reviewed?: number }
|
|
653
|
+
| undefined;
|
|
654
|
+
tilesReused += reuse?.tiles_reused ?? 0;
|
|
655
|
+
tilesReviewed += reuse?.tiles_reviewed ?? envelopeCritique?.tiles ?? 0;
|
|
656
|
+
provider = providerLabel(envelopeCritique);
|
|
657
|
+
for (const finding of envelopeCritique?.findings ?? []) {
|
|
658
|
+
findings.push({
|
|
659
|
+
severity: finding.severity ?? "unknown",
|
|
660
|
+
summary: finding.category
|
|
661
|
+
? `${finding.category}: ${finding.description ?? ""}`
|
|
662
|
+
: (finding.description ?? ""),
|
|
663
|
+
...(selector !== undefined ? { selector } : {}),
|
|
664
|
+
});
|
|
665
|
+
}
|
|
666
|
+
if (envelopeCritique?.outcome === "pass" && res.exitCode === 0) {
|
|
667
|
+
commandOutcome = "passed";
|
|
668
|
+
} else if (envelopeCritique?.outcome === "fail") {
|
|
669
|
+
commandOutcome = "failed";
|
|
670
|
+
failures.push(`critique found ${envelopeCritique.findings?.length ?? 0} defect(s)`);
|
|
671
|
+
contextOutcome = "failed";
|
|
672
|
+
} else {
|
|
673
|
+
// "skipped" (no provider / exhausted headless list) or anything
|
|
674
|
+
// unrecognized: the review did not happen, so nothing is proven.
|
|
675
|
+
commandOutcome = "unknown";
|
|
676
|
+
const detail = envelopeCritique?.error ?? "critique reported no conclusive outcome";
|
|
677
|
+
failures.push(detail);
|
|
678
|
+
blockers.push({
|
|
679
|
+
stage: "critique",
|
|
680
|
+
context_id: ctx.id,
|
|
681
|
+
reason: job.policy?.allow_metered_critique
|
|
682
|
+
? `critique did not complete: ${detail}`
|
|
683
|
+
: `critique did not complete under the headless-only policy ` +
|
|
684
|
+
`(${QA_RUN_HEADLESS_ONLY_ENV}=1; permit metered fallback with ` +
|
|
685
|
+
`policy.allow_metered_critique / --allow-metered): ${detail}`,
|
|
686
|
+
});
|
|
687
|
+
if (contextOutcome !== "failed") contextOutcome = "unknown";
|
|
688
|
+
}
|
|
689
|
+
if (job.mode === "signoff") {
|
|
690
|
+
const saved = (envelope.qaPlan as { snapshotSaved?: { path?: string } } | undefined)
|
|
691
|
+
?.snapshotSaved;
|
|
692
|
+
if (saved?.path) savedSnapshots.set(ctx.id, saved.path);
|
|
693
|
+
}
|
|
694
|
+
}
|
|
695
|
+
commands.push({
|
|
696
|
+
context_id: ctx.id,
|
|
697
|
+
check_id: "critique",
|
|
698
|
+
argv,
|
|
699
|
+
exit_code: res.exitCode,
|
|
700
|
+
outcome: commandOutcome,
|
|
701
|
+
failures,
|
|
702
|
+
artifacts: gatherArtifacts(outPrefix),
|
|
703
|
+
wall_time_ms: wallTimeMs,
|
|
704
|
+
});
|
|
705
|
+
}
|
|
706
|
+
critique.push({
|
|
707
|
+
context_id: ctx.id,
|
|
708
|
+
provider,
|
|
709
|
+
tiles_total: tilesTotal,
|
|
710
|
+
tiles_reviewed: tilesReviewed,
|
|
711
|
+
tiles_reused: tilesReused,
|
|
712
|
+
outcome: contextOutcome,
|
|
713
|
+
findings,
|
|
714
|
+
});
|
|
715
|
+
if (job.mode === "signoff" && contextOutcome === "passed" && !savedSnapshots.has(ctx.id)) {
|
|
716
|
+
blockers.push({
|
|
717
|
+
stage: "snapshot",
|
|
718
|
+
context_id: ctx.id,
|
|
719
|
+
reason: "signoff critique passed but no QA snapshot was persisted for the context",
|
|
720
|
+
});
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
wall.critique = Date.now() - critiqueStart;
|
|
725
|
+
|
|
726
|
+
// -------------------------------------------------------------- snapshot
|
|
727
|
+
// Critique invocations carry --qa-snapshot in signoff mode. When the
|
|
728
|
+
// manifest requires no visual pass (visual === "none"), a passing signoff
|
|
729
|
+
// still needs its baseline persisted, so a dedicated snapshot pass runs.
|
|
730
|
+
const snapshotStart = Date.now();
|
|
731
|
+
if (job.mode === "signoff" && visual === "none" && blockers.length === 0) {
|
|
732
|
+
const stillClean = commands.every((command) => command.outcome === "passed");
|
|
733
|
+
if (stillClean) {
|
|
734
|
+
for (const ctx of contexts) {
|
|
735
|
+
const outPrefix = join(outDir, `${ctx.id}-snapshot`);
|
|
736
|
+
const argv = [
|
|
737
|
+
...browseArgv,
|
|
738
|
+
job.target,
|
|
739
|
+
...contextRenderArgs(ctx),
|
|
740
|
+
"--out",
|
|
741
|
+
outPrefix,
|
|
742
|
+
"--qa-snapshot",
|
|
743
|
+
"--qa-theme",
|
|
744
|
+
ctx.theme,
|
|
745
|
+
"--qa-state",
|
|
746
|
+
ctx.state,
|
|
747
|
+
];
|
|
748
|
+
log(`snapshot ${ctx.id}`);
|
|
749
|
+
const { res, wallTimeMs } = await timedExec(argv, baseEnv);
|
|
750
|
+
const envelope = readEnvelope(`${outPrefix}.json`);
|
|
751
|
+
const saved = (envelope?.qaPlan as { snapshotSaved?: { path?: string } } | undefined)
|
|
752
|
+
?.snapshotSaved;
|
|
753
|
+
const ok = !res.error && res.exitCode === 0 && Boolean(saved?.path);
|
|
754
|
+
if (ok && saved?.path) savedSnapshots.set(ctx.id, saved.path);
|
|
755
|
+
else {
|
|
756
|
+
blockers.push({
|
|
757
|
+
stage: "snapshot",
|
|
758
|
+
context_id: ctx.id,
|
|
759
|
+
reason: `snapshot command did not persist a baseline${res.error ? `: ${res.error}` : ` (exit code ${res.exitCode ?? "null"})`}`,
|
|
760
|
+
});
|
|
761
|
+
}
|
|
762
|
+
commands.push({
|
|
763
|
+
context_id: ctx.id,
|
|
764
|
+
check_id: "snapshot",
|
|
765
|
+
argv,
|
|
766
|
+
exit_code: res.exitCode,
|
|
767
|
+
outcome: ok ? "passed" : "unknown",
|
|
768
|
+
failures: ok ? [] : [res.error ?? `exit code ${res.exitCode ?? "null"}`],
|
|
769
|
+
artifacts: gatherArtifacts(outPrefix),
|
|
770
|
+
wall_time_ms: wallTimeMs,
|
|
771
|
+
});
|
|
772
|
+
}
|
|
773
|
+
}
|
|
774
|
+
}
|
|
775
|
+
wall.snapshot = Date.now() - snapshotStart;
|
|
776
|
+
|
|
777
|
+
if (job.mode === "signoff") {
|
|
778
|
+
const allSaved = contexts.length > 0 && contexts.every((ctx) => savedSnapshots.has(ctx.id));
|
|
779
|
+
const lastPath = [...savedSnapshots.values()].pop();
|
|
780
|
+
snapshot = { saved: allSaved, ...(lastPath ? { path: lastPath } : {}) };
|
|
781
|
+
}
|
|
782
|
+
|
|
783
|
+
return finalize();
|
|
784
|
+
}
|