harnery 0.32.0 → 0.34.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/README.md +2 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +7 -1
- package/dist/commands/adapter.js +2 -2
- package/dist/commands/agents.d.ts +144 -1
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +1408 -565
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +7 -6
- package/dist/commands/backup.d.ts +1 -1
- package/dist/commands/backup.d.ts.map +1 -1
- package/dist/commands/backup.js +29 -16
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +234 -12
- package/dist/commands/checkpoint.d.ts.map +1 -1
- package/dist/commands/checkpoint.js +3 -2
- package/dist/commands/claude-desktop.d.ts +2 -2
- package/dist/commands/claude-desktop.d.ts.map +1 -1
- package/dist/commands/claude-desktop.js +2 -2
- package/dist/commands/context.js +1 -6
- package/dist/commands/decision.d.ts.map +1 -1
- package/dist/commands/decision.js +22 -38
- package/dist/commands/docs.d.ts.map +1 -1
- package/dist/commands/docs.js +91 -28
- package/dist/commands/doctor.d.ts +4 -2
- package/dist/commands/doctor.d.ts.map +1 -1
- package/dist/commands/doctor.js +55 -7
- package/dist/commands/events.d.ts +5 -0
- package/dist/commands/events.d.ts.map +1 -0
- package/dist/commands/events.js +189 -0
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +13 -4
- package/dist/commands/init.d.ts +10 -2
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +233 -51
- package/dist/commands/instructions.d.ts +4 -0
- package/dist/commands/instructions.d.ts.map +1 -0
- package/dist/commands/instructions.js +100 -0
- package/dist/commands/journal.d.ts.map +1 -1
- package/dist/commands/journal.js +4 -13
- package/dist/commands/ledger-v3.d.ts +5 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -0
- package/dist/commands/ledger-v3.js +91 -0
- package/dist/commands/presence.d.ts.map +1 -1
- package/dist/commands/presence.js +15 -6
- package/dist/commands/sync.d.ts +1 -1
- package/dist/commands/sync.js +1 -1
- package/dist/commands/web.d.ts +6 -0
- package/dist/commands/web.d.ts.map +1 -1
- package/dist/commands/web.js +67 -7
- package/dist/commands/work.d.ts.map +1 -1
- package/dist/commands/work.js +22 -5
- package/dist/core/adapter.d.ts +5 -0
- package/dist/core/adapter.d.ts.map +1 -0
- package/dist/core/adapter.js +1 -0
- package/dist/core/adapters/attest.d.ts +5 -2
- package/dist/core/adapters/attest.d.ts.map +1 -1
- package/dist/core/adapters/attest.js +8 -3
- package/dist/core/adapters/profiles.d.ts +6 -6
- package/dist/core/adapters/profiles.d.ts.map +1 -1
- package/dist/core/adapters/profiles.js +4 -4
- package/dist/core/agents/canonical-emit.d.ts +17 -15
- package/dist/core/agents/canonical-emit.d.ts.map +1 -1
- package/dist/core/agents/canonical-emit.js +27 -25
- package/dist/core/agents/cli.js +212 -235
- package/dist/core/agents/codex-archive-v3.d.ts +14 -0
- package/dist/core/agents/codex-archive-v3.d.ts.map +1 -0
- package/dist/core/agents/codex-archive-v3.js +110 -0
- package/dist/core/agents/coord-client.d.ts +19 -70
- package/dist/core/agents/coord-client.d.ts.map +1 -1
- package/dist/core/agents/coord-client.js +65 -155
- package/dist/core/agents/finalization.d.ts +4 -1
- package/dist/core/agents/finalization.d.ts.map +1 -1
- package/dist/core/agents/finalization.js +89 -32
- package/dist/core/agents/index.d.ts +5 -5
- package/dist/core/agents/index.d.ts.map +1 -1
- package/dist/core/agents/index.js +5 -5
- package/dist/core/agents/live-authority-v3.d.ts +59 -0
- package/dist/core/agents/live-authority-v3.d.ts.map +1 -0
- package/dist/core/agents/live-authority-v3.js +233 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts +20 -0
- package/dist/core/agents/live-lifecycle-v3.d.ts.map +1 -0
- package/dist/core/agents/live-lifecycle-v3.js +91 -0
- package/dist/core/agents/live-observation-v3.d.ts +25 -0
- package/dist/core/agents/live-observation-v3.d.ts.map +1 -0
- package/dist/core/agents/live-observation-v3.js +157 -0
- package/dist/core/agents/render/prompt-context.d.ts +10 -4
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +61 -55
- package/dist/core/agents/render/session-context.d.ts +1 -1
- package/dist/core/agents/render/session-context.d.ts.map +1 -1
- package/dist/core/agents/render/session-context.js +15 -33
- package/dist/core/agents/rules/claim-conflict.d.ts +3 -3
- package/dist/core/agents/rules/claim-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/claim-conflict.js +79 -127
- package/dist/core/agents/rules/commit-conflict.d.ts.map +1 -1
- package/dist/core/agents/rules/commit-conflict.js +3 -18
- package/dist/core/agents/rules/stop-hook.d.ts +9 -50
- package/dist/core/agents/rules/stop-hook.d.ts.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +193 -236
- package/dist/core/agents/session-events.d.ts +5 -7
- package/dist/core/agents/session-events.d.ts.map +1 -1
- package/dist/core/agents/session-events.js +127 -95
- package/dist/core/agents/session-finalization-state-v3.d.ts +30 -0
- package/dist/core/agents/session-finalization-state-v3.d.ts.map +1 -0
- package/dist/core/agents/session-finalization-state-v3.js +40 -0
- package/dist/core/agents/session-finalizer-v3.d.ts +107 -0
- package/dist/core/agents/session-finalizer-v3.d.ts.map +1 -0
- package/dist/core/agents/session-finalizer-v3.js +734 -0
- package/dist/core/agents/session-name-display.d.ts +40 -0
- package/dist/core/agents/session-name-display.d.ts.map +1 -0
- package/dist/core/agents/session-name-display.js +119 -0
- package/dist/core/agents/state/activity-log.d.ts +3 -3
- package/dist/core/agents/state/activity-log.d.ts.map +1 -1
- package/dist/core/agents/state/activity-log.js +7 -16
- package/dist/core/agents/state/heartbeat-writer.d.ts +29 -46
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +59 -199
- package/dist/core/agents/state/live-coordination-view.d.ts +31 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -0
- package/dist/core/agents/state/live-coordination-view.js +209 -0
- package/dist/core/agents/state/session-state.d.ts +45 -0
- package/dist/core/agents/state/session-state.d.ts.map +1 -0
- package/dist/core/agents/state/session-state.js +90 -0
- package/dist/core/agents/state/stale-sweep.d.ts +1 -1
- package/dist/core/agents/state/stale-sweep.d.ts.map +1 -1
- package/dist/core/agents/state/stale-sweep.js +26 -15
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +5 -7
- package/dist/core/config.d.ts +33 -2
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +98 -2
- package/dist/core/context/index.d.ts +1 -4
- package/dist/core/context/index.d.ts.map +1 -1
- package/dist/core/context/index.js +9 -9
- package/dist/core/events/span-parent.d.ts +15 -0
- package/dist/core/events/span-parent.d.ts.map +1 -0
- package/dist/core/events/span-parent.js +34 -0
- package/dist/core/events/v3/advance.d.ts +14 -0
- package/dist/core/events/v3/advance.d.ts.map +1 -0
- package/dist/core/events/v3/advance.js +134 -0
- package/dist/core/events/v3/authority-outbox.d.ts +78 -0
- package/dist/core/events/v3/authority-outbox.d.ts.map +1 -0
- package/dist/core/events/v3/authority-outbox.js +399 -0
- package/dist/core/events/v3/base-builder.d.ts +20 -0
- package/dist/core/events/v3/base-builder.d.ts.map +1 -0
- package/dist/core/events/v3/base-builder.js +29 -0
- package/dist/core/events/v3/base-contract.d.ts +7576 -0
- package/dist/core/events/v3/base-contract.d.ts.map +1 -0
- package/dist/core/events/v3/base-contract.js +647 -0
- package/dist/core/events/v3/bootstrap.d.ts +34 -0
- package/dist/core/events/v3/bootstrap.d.ts.map +1 -0
- package/dist/core/events/v3/bootstrap.js +175 -0
- package/dist/core/events/v3/builder.d.ts +20 -0
- package/dist/core/events/v3/builder.d.ts.map +1 -0
- package/dist/core/events/v3/builder.js +28 -0
- package/dist/core/events/v3/canonical.d.ts +31 -0
- package/dist/core/events/v3/canonical.d.ts.map +1 -0
- package/dist/core/events/v3/canonical.js +100 -0
- package/dist/core/events/v3/capabilities.d.ts +31 -0
- package/dist/core/events/v3/capabilities.d.ts.map +1 -0
- package/dist/core/events/v3/capabilities.js +107 -0
- package/dist/core/events/v3/capability-drift.d.ts +22 -0
- package/dist/core/events/v3/capability-drift.d.ts.map +1 -0
- package/dist/core/events/v3/capability-drift.js +134 -0
- package/dist/core/events/v3/catalog.d.ts +38 -0
- package/dist/core/events/v3/catalog.d.ts.map +1 -0
- package/dist/core/events/v3/catalog.js +135 -0
- package/dist/core/events/v3/clock-order.d.ts +34 -0
- package/dist/core/events/v3/clock-order.d.ts.map +1 -0
- package/dist/core/events/v3/clock-order.js +35 -0
- package/dist/core/events/v3/contract.d.ts +171 -0
- package/dist/core/events/v3/contract.d.ts.map +1 -0
- package/dist/core/events/v3/contract.js +180 -0
- package/dist/core/events/v3/control.d.ts +111 -0
- package/dist/core/events/v3/control.d.ts.map +1 -0
- package/dist/core/events/v3/control.js +419 -0
- package/dist/core/events/v3/coordination-view.d.ts +69 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -0
- package/dist/core/events/v3/coordination-view.js +119 -0
- package/dist/core/events/v3/economics.d.ts +77 -0
- package/dist/core/events/v3/economics.d.ts.map +1 -0
- package/dist/core/events/v3/economics.js +274 -0
- package/dist/core/events/v3/finalization-view.d.ts +26 -0
- package/dist/core/events/v3/finalization-view.d.ts.map +1 -0
- package/dist/core/events/v3/finalization-view.js +37 -0
- package/dist/core/events/v3/fingerprint-keys.d.ts +25 -0
- package/dist/core/events/v3/fingerprint-keys.d.ts.map +1 -0
- package/dist/core/events/v3/fingerprint-keys.js +217 -0
- package/dist/core/events/v3/generated.d.ts +4 -0
- package/dist/core/events/v3/generated.d.ts.map +1 -0
- package/dist/core/events/v3/generated.js +47 -0
- package/dist/core/events/v3/ids.d.ts +9 -0
- package/dist/core/events/v3/ids.d.ts.map +1 -0
- package/dist/core/events/v3/ids.js +25 -0
- package/dist/core/events/v3/index.d.ts +35 -0
- package/dist/core/events/v3/index.d.ts.map +1 -0
- package/dist/core/events/v3/index.js +33 -0
- package/dist/core/events/v3/latency.d.ts +63 -0
- package/dist/core/events/v3/latency.d.ts.map +1 -0
- package/dist/core/events/v3/latency.js +412 -0
- package/dist/core/events/v3/live-feed.d.ts +45 -0
- package/dist/core/events/v3/live-feed.d.ts.map +1 -0
- package/dist/core/events/v3/live-feed.js +246 -0
- package/dist/core/events/v3/live-observation.d.ts +35 -0
- package/dist/core/events/v3/live-observation.d.ts.map +1 -0
- package/dist/core/events/v3/live-observation.js +1 -0
- package/dist/core/events/v3/live-routing.d.ts +57 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -0
- package/dist/core/events/v3/live-routing.js +107 -0
- package/dist/core/events/v3/producers/command-recorder.d.ts +67 -0
- package/dist/core/events/v3/producers/command-recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/command-recorder.js +477 -0
- package/dist/core/events/v3/producers/command.d.ts +50 -0
- package/dist/core/events/v3/producers/command.d.ts.map +1 -0
- package/dist/core/events/v3/producers/command.js +135 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts +53 -0
- package/dist/core/events/v3/producers/coordination-recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/coordination-recorder.js +376 -0
- package/dist/core/events/v3/producers/coordination.d.ts +90 -0
- package/dist/core/events/v3/producers/coordination.d.ts.map +1 -0
- package/dist/core/events/v3/producers/coordination.js +229 -0
- package/dist/core/events/v3/producers/hook-base.d.ts +54 -0
- package/dist/core/events/v3/producers/hook-base.d.ts.map +1 -0
- package/dist/core/events/v3/producers/hook-base.js +424 -0
- package/dist/core/events/v3/producers/hook.d.ts +29 -0
- package/dist/core/events/v3/producers/hook.d.ts.map +1 -0
- package/dist/core/events/v3/producers/hook.js +71 -0
- package/dist/core/events/v3/producers/intake.d.ts +65 -0
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -0
- package/dist/core/events/v3/producers/intake.js +244 -0
- package/dist/core/events/v3/producers/recorder.d.ts +240 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -0
- package/dist/core/events/v3/producers/recorder.js +2176 -0
- package/dist/core/events/v3/projection.d.ts +101 -0
- package/dist/core/events/v3/projection.d.ts.map +1 -0
- package/dist/core/events/v3/projection.js +479 -0
- package/dist/core/events/v3/reader.d.ts +75 -0
- package/dist/core/events/v3/reader.d.ts.map +1 -0
- package/dist/core/events/v3/reader.js +778 -0
- package/dist/core/events/v3/recovery-record.d.ts +47 -0
- package/dist/core/events/v3/recovery-record.d.ts.map +1 -0
- package/dist/core/events/v3/recovery-record.js +167 -0
- package/dist/core/events/v3/recovery.d.ts +22 -0
- package/dist/core/events/v3/recovery.d.ts.map +1 -0
- package/dist/core/events/v3/recovery.js +227 -0
- package/dist/core/events/v3/span-state.d.ts +52 -0
- package/dist/core/events/v3/span-state.d.ts.map +1 -0
- package/dist/core/events/v3/span-state.js +142 -0
- package/dist/core/events/v3/targets.d.ts +23 -0
- package/dist/core/events/v3/targets.d.ts.map +1 -0
- package/dist/core/events/v3/targets.js +134 -0
- package/dist/core/events/v3/turn-telemetry.d.ts +41 -0
- package/dist/core/events/v3/turn-telemetry.d.ts.map +1 -0
- package/dist/core/events/v3/turn-telemetry.js +168 -0
- package/dist/core/events/v3/validate.d.ts +9 -0
- package/dist/core/events/v3/validate.d.ts.map +1 -0
- package/dist/core/events/v3/validate.js +281 -0
- package/dist/core/events/v3/writer.d.ts +56 -0
- package/dist/core/events/v3/writer.d.ts.map +1 -0
- package/dist/core/events/v3/writer.js +335 -0
- package/dist/core/governor/index.d.ts +1 -1
- package/dist/core/governor/index.d.ts.map +1 -1
- package/dist/core/governor/index.js +1 -1
- package/dist/core/governor/plan-api.d.ts +2 -1
- package/dist/core/governor/plan-api.d.ts.map +1 -1
- package/dist/core/governor/plan-api.js +6 -3
- package/dist/core/governor/read.d.ts +1 -1
- package/dist/core/governor/read.d.ts.map +1 -1
- package/dist/core/governor/read.js +1 -1
- package/dist/core/governor/state.d.ts +9 -0
- package/dist/core/governor/state.d.ts.map +1 -1
- package/dist/core/governor/state.js +40 -3
- package/dist/core/guard/config.d.ts +5 -0
- package/dist/core/guard/config.d.ts.map +1 -0
- package/dist/core/guard/config.js +157 -0
- package/dist/core/guard/coordinator.d.ts +14 -0
- package/dist/core/guard/coordinator.d.ts.map +1 -0
- package/dist/core/guard/coordinator.js +173 -0
- package/dist/core/guard/evaluator.d.ts +4 -0
- package/dist/core/guard/evaluator.d.ts.map +1 -0
- package/dist/core/guard/evaluator.js +242 -0
- package/dist/core/guard/evidence-v3.d.ts +15 -0
- package/dist/core/guard/evidence-v3.d.ts.map +1 -0
- package/dist/core/guard/evidence-v3.js +171 -0
- package/dist/core/guard/index.d.ts +10 -0
- package/dist/core/guard/index.d.ts.map +1 -0
- package/dist/core/guard/index.js +6 -0
- package/dist/core/guard/live-source-v3.d.ts +40 -0
- package/dist/core/guard/live-source-v3.d.ts.map +1 -0
- package/dist/core/guard/live-source-v3.js +128 -0
- package/dist/core/guard/storage.d.ts +27 -0
- package/dist/core/guard/storage.d.ts.map +1 -0
- package/dist/core/guard/storage.js +140 -0
- package/dist/core/guard/types.d.ts +119 -0
- package/dist/core/guard/types.d.ts.map +1 -0
- package/dist/core/guard/types.js +1 -0
- package/dist/core/hooks/adapter/detect.d.ts +18 -1
- package/dist/core/hooks/adapter/detect.d.ts.map +1 -1
- package/dist/core/hooks/adapter/detect.js +29 -0
- package/dist/core/hooks/adapter/events.d.ts +7 -4
- package/dist/core/hooks/adapter/events.d.ts.map +1 -1
- package/dist/core/hooks/adapter/events.js +13 -4
- package/dist/core/hooks/adapter/output.d.ts +2 -2
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.d.ts +7 -4
- package/dist/core/hooks/adapter/parse.d.ts.map +1 -1
- package/dist/core/hooks/adapter/parse.js +64 -24
- package/dist/core/hooks/adapter/wiring.d.ts +30 -4
- package/dist/core/hooks/adapter/wiring.d.ts.map +1 -1
- package/dist/core/hooks/adapter/wiring.js +89 -11
- package/dist/core/hooks/cli.d.ts +1 -1
- package/dist/core/hooks/cli.js +345 -400
- package/dist/core/hooks/codex-authorization.d.ts +30 -0
- package/dist/core/hooks/codex-authorization.d.ts.map +1 -0
- package/dist/core/hooks/codex-authorization.js +199 -0
- package/dist/core/hooks/effects/image-capture.d.ts +20 -34
- package/dist/core/hooks/effects/image-capture.d.ts.map +1 -1
- package/dist/core/hooks/effects/image-capture.js +212 -221
- package/dist/core/hooks/effects/index.d.ts +1 -9
- package/dist/core/hooks/effects/index.d.ts.map +1 -1
- package/dist/core/hooks/effects/index.js +1 -24
- package/dist/core/hooks/events/input-hash.d.ts +7 -0
- package/dist/core/hooks/events/input-hash.d.ts.map +1 -0
- package/dist/core/hooks/events/input-hash.js +43 -0
- package/dist/core/hooks/index.d.ts +4 -3
- package/dist/core/hooks/index.d.ts.map +1 -1
- package/dist/core/hooks/index.js +2 -3
- package/dist/core/hooks/resolve/coord-root.d.ts +1 -1
- package/dist/core/hooks/resolve/coord-root.js +1 -1
- package/dist/core/hooks/resolve/owner.d.ts +16 -15
- package/dist/core/hooks/resolve/owner.d.ts.map +1 -1
- package/dist/core/hooks/resolve/owner.js +51 -42
- package/dist/core/hooks/resolve/transcript.d.ts +33 -3
- package/dist/core/hooks/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +155 -14
- package/dist/core/hooks/session-name-presence.d.ts +9 -10
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +15 -15
- package/dist/core/hooks/unsafe-cross-shell.d.ts +1 -1
- package/dist/core/hooks/unsafe-cross-shell.d.ts.map +1 -1
- package/dist/core/journal/index.d.ts +2 -2
- package/dist/core/journal/index.d.ts.map +1 -1
- package/dist/core/journal/index.js +9 -22
- package/dist/core/presence/blob.d.ts +8 -3
- package/dist/core/presence/blob.d.ts.map +1 -1
- package/dist/core/presence/blob.js +54 -41
- package/dist/core/presence/codec-digest.d.ts +29 -0
- package/dist/core/presence/codec-digest.d.ts.map +1 -0
- package/dist/core/presence/codec-digest.js +170 -0
- package/dist/core/presence/index.js +15 -1
- package/dist/core/presence/relay-client.d.ts +1 -1
- package/dist/core/presence/relay-client.d.ts.map +1 -1
- package/dist/core/presence/relay-client.js +5 -5
- package/dist/core/work/index.d.ts +1 -1
- package/dist/core/work/index.d.ts.map +1 -1
- package/dist/core/work/index.js +1 -1
- package/dist/core/work/read.d.ts +1 -1
- package/dist/core/work/read.d.ts.map +1 -1
- package/dist/core/work/read.js +1 -1
- package/dist/core/work/runner.d.ts.map +1 -1
- package/dist/core/work/runner.js +6 -0
- package/dist/core/work/state.d.ts +9 -0
- package/dist/core/work/state.d.ts.map +1 -1
- package/dist/core/work/state.js +17 -3
- package/dist/core/workflow/engine.js +24 -25
- package/dist/core/workflow/live-session-v3.d.ts +19 -0
- package/dist/core/workflow/live-session-v3.d.ts.map +1 -0
- package/dist/core/workflow/live-session-v3.js +86 -0
- package/dist/core/workflow/scope-id.d.ts +3 -0
- package/dist/core/workflow/scope-id.d.ts.map +1 -0
- package/dist/core/workflow/scope-id.js +5 -0
- package/dist/core/workflow/workspaces/leases.d.ts +4 -0
- package/dist/core/workflow/workspaces/leases.d.ts.map +1 -1
- package/dist/core/workflow/workspaces/leases.js +53 -19
- package/dist/index.d.ts +1 -1
- package/dist/index.js +1 -1
- package/dist/lib/browser/client.d.ts +41 -0
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +203 -0
- package/dist/lib/browser/critique.d.ts +28 -2
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +74 -18
- package/dist/lib/browser/geometry.d.ts +1 -1
- package/dist/lib/browser/geometry.d.ts.map +1 -1
- package/dist/lib/browser/geometry.js +130 -6
- package/dist/lib/browser/index.d.ts +3 -0
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +3 -0
- package/dist/lib/browser/qa-plan.d.ts +174 -0
- package/dist/lib/browser/qa-plan.d.ts.map +1 -0
- package/dist/lib/browser/qa-plan.js +321 -0
- package/dist/lib/browser/qa-reuse.d.ts +99 -0
- package/dist/lib/browser/qa-reuse.d.ts.map +1 -0
- package/dist/lib/browser/qa-reuse.js +222 -0
- package/dist/lib/browser/qa-snapshot.d.ts +64 -0
- package/dist/lib/browser/qa-snapshot.d.ts.map +1 -0
- package/dist/lib/browser/qa-snapshot.js +171 -0
- package/dist/lib/browser/runts.d.ts.map +1 -1
- package/dist/lib/browser/runts.js +22 -1
- package/dist/lib/browser/tiling.d.ts +71 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -0
- package/dist/lib/browser/tiling.js +118 -0
- package/dist/lib/context/index.d.ts +0 -3
- package/dist/lib/context/index.d.ts.map +1 -1
- package/dist/lib/context/index.js +20 -42
- package/dist/lib/council/index.d.ts +2 -2
- package/dist/lib/council/index.d.ts.map +1 -1
- package/dist/lib/council/index.js +9 -20
- package/dist/lib/docs-frontmatter.d.ts +1 -6
- package/dist/lib/docs-frontmatter.d.ts.map +1 -1
- package/dist/lib/docs-frontmatter.js +12 -78
- package/dist/lib/docs-index.d.ts +9 -0
- package/dist/lib/docs-index.d.ts.map +1 -1
- package/dist/lib/docs-index.js +32 -3
- package/dist/lib/docs-lint.d.ts.map +1 -1
- package/dist/lib/docs-lint.js +14 -30
- package/dist/lib/docs-metadata-audit.d.ts +19 -0
- package/dist/lib/docs-metadata-audit.d.ts.map +1 -0
- package/dist/lib/docs-metadata-audit.js +132 -0
- package/dist/lib/docs-metadata-managed.d.ts +23 -0
- package/dist/lib/docs-metadata-managed.d.ts.map +1 -0
- package/dist/lib/docs-metadata-managed.js +78 -0
- package/dist/lib/docs-metadata-sync.d.ts +20 -0
- package/dist/lib/docs-metadata-sync.d.ts.map +1 -0
- package/dist/lib/docs-metadata-sync.js +222 -0
- package/dist/lib/docs-metadata-v2-schema.d.ts +273 -0
- package/dist/lib/docs-metadata-v2-schema.d.ts.map +1 -0
- package/dist/lib/docs-metadata-v2-schema.js +134 -0
- package/dist/lib/docs-metadata-v2.d.ts +21 -0
- package/dist/lib/docs-metadata-v2.d.ts.map +1 -0
- package/dist/lib/docs-metadata-v2.js +424 -0
- package/dist/lib/docs-new.d.ts +11 -0
- package/dist/lib/docs-new.d.ts.map +1 -0
- package/dist/lib/docs-new.js +52 -0
- package/dist/lib/docs-sweep.d.ts.map +1 -1
- package/dist/lib/docs-sweep.js +45 -29
- package/dist/lib/headless/index.d.ts +98 -0
- package/dist/lib/headless/index.d.ts.map +1 -0
- package/dist/lib/headless/index.js +211 -0
- package/dist/lib/identities/assume.d.ts +4 -4
- package/dist/lib/identities/assume.d.ts.map +1 -1
- package/dist/lib/identities/assume.js +52 -68
- package/dist/lib/instructions/apply.d.ts +5 -4
- package/dist/lib/instructions/apply.d.ts.map +1 -1
- package/dist/lib/instructions/apply.js +32 -20
- package/dist/lib/instructions/bundle.d.ts +33 -0
- package/dist/lib/instructions/bundle.d.ts.map +1 -0
- package/dist/lib/instructions/bundle.js +149 -0
- package/dist/lib/instructions/splice.d.ts +0 -1
- package/dist/lib/instructions/splice.d.ts.map +1 -1
- package/dist/lib/instructions/splice.js +22 -6
- package/dist/lib/instructions/templates.d.ts +7 -5
- package/dist/lib/instructions/templates.d.ts.map +1 -1
- package/dist/lib/instructions/templates.js +79 -9
- package/package.json +27 -6
- package/schemas/config.schema.json +120 -2
- package/schemas/docs-metadata-v2.schema.json +441 -0
- package/schemas/event-v3.schema.json +24472 -0
- package/src/commander.ts +7 -1
- package/src/commands/adapter.ts +2 -2
- package/src/commands/agents.ts +1737 -570
- package/src/commands/artifacts.ts +7 -6
- package/src/commands/backup.ts +29 -21
- package/src/commands/browse.ts +349 -8
- package/src/commands/checkpoint.ts +4 -3
- package/src/commands/claude-desktop.ts +7 -5
- package/src/commands/context.ts +1 -6
- package/src/commands/decision.ts +27 -44
- package/src/commands/docs.ts +100 -33
- package/src/commands/doctor.ts +73 -8
- package/src/commands/events.ts +256 -0
- package/src/commands/governor.ts +18 -4
- package/src/commands/init.ts +264 -57
- package/src/commands/instructions.ts +129 -0
- package/src/commands/journal.ts +4 -13
- package/src/commands/ledger-v3.ts +111 -0
- package/src/commands/presence.ts +18 -11
- package/src/commands/sync.ts +1 -1
- package/src/commands/web.ts +67 -8
- package/src/commands/work.ts +28 -5
- package/src/core/adapter.ts +5 -0
- package/src/core/adapters/attest.ts +8 -3
- package/src/core/adapters/profiles.ts +4 -6
- package/src/core/agents/canonical-emit.ts +39 -28
- package/src/core/agents/cli.ts +242 -263
- package/src/core/agents/codex-archive-v3.ts +138 -0
- package/src/core/agents/coord-client.ts +75 -177
- package/src/core/agents/finalization.ts +120 -38
- package/src/core/agents/index.ts +5 -5
- package/src/core/agents/live-authority-v3.ts +375 -0
- package/src/core/agents/live-lifecycle-v3.ts +140 -0
- package/src/core/agents/live-observation-v3.ts +216 -0
- package/src/core/agents/render/prompt-context.ts +89 -55
- package/src/core/agents/render/session-context.ts +23 -32
- package/src/core/agents/rules/claim-conflict.ts +85 -126
- package/src/core/agents/rules/commit-conflict.ts +3 -14
- package/src/core/agents/rules/stop-hook.ts +239 -293
- package/src/core/agents/session-events.ts +137 -104
- package/src/core/agents/session-finalization-state-v3.ts +90 -0
- package/src/core/agents/session-finalizer-v3.ts +953 -0
- package/src/core/agents/session-name-display.ts +149 -0
- package/src/core/agents/state/activity-log.ts +6 -14
- package/src/core/agents/state/heartbeat-writer.ts +98 -242
- package/src/core/agents/state/live-coordination-view.ts +290 -0
- package/src/core/agents/state/session-state.ts +143 -0
- package/src/core/agents/state/stale-sweep.ts +40 -17
- package/src/core/artifacts/index.ts +4 -5
- package/src/core/config.ts +148 -3
- package/src/core/context/index.ts +9 -17
- package/src/core/events/span-parent.ts +46 -0
- package/src/core/events/v3/advance.ts +168 -0
- package/src/core/events/v3/authority-outbox.ts +548 -0
- package/src/core/events/v3/base-builder.ts +60 -0
- package/src/core/events/v3/base-contract.ts +882 -0
- package/src/core/events/v3/bootstrap.ts +226 -0
- package/src/core/events/v3/builder.ts +59 -0
- package/src/core/events/v3/canonical.ts +153 -0
- package/src/core/events/v3/capabilities.ts +171 -0
- package/src/core/events/v3/capability-drift.ts +177 -0
- package/src/core/events/v3/catalog.ts +202 -0
- package/src/core/events/v3/clock-order.ts +41 -0
- package/src/core/events/v3/contract.ts +365 -0
- package/src/core/events/v3/control.ts +576 -0
- package/src/core/events/v3/coordination-view.ts +193 -0
- package/src/core/events/v3/economics.ts +384 -0
- package/src/core/events/v3/finalization-view.ts +67 -0
- package/src/core/events/v3/fingerprint-keys.ts +260 -0
- package/src/core/events/v3/generated.ts +48 -0
- package/src/core/events/v3/ids.ts +33 -0
- package/src/core/events/v3/index.ts +322 -0
- package/src/core/events/v3/latency.ts +551 -0
- package/src/core/events/v3/live-feed.ts +319 -0
- package/src/core/events/v3/live-observation.ts +39 -0
- package/src/core/events/v3/live-routing.ts +135 -0
- package/src/core/events/v3/producers/command-recorder.ts +631 -0
- package/src/core/events/v3/producers/command.ts +201 -0
- package/src/core/events/v3/producers/coordination-recorder.ts +538 -0
- package/src/core/events/v3/producers/coordination.ts +355 -0
- package/src/core/events/v3/producers/hook-base.ts +578 -0
- package/src/core/events/v3/producers/hook.ts +119 -0
- package/src/core/events/v3/producers/intake.ts +319 -0
- package/src/core/events/v3/producers/recorder.ts +2805 -0
- package/src/core/events/v3/projection.ts +653 -0
- package/src/core/events/v3/reader.ts +1127 -0
- package/src/core/events/v3/recovery-record.ts +244 -0
- package/src/core/events/v3/recovery.ts +271 -0
- package/src/core/events/v3/span-state.ts +187 -0
- package/src/core/events/v3/targets.ts +182 -0
- package/src/core/events/v3/turn-telemetry.ts +259 -0
- package/src/core/events/v3/validate.ts +361 -0
- package/src/core/events/v3/writer.ts +419 -0
- package/src/core/governor/index.ts +3 -0
- package/src/core/governor/plan-api.ts +10 -2
- package/src/core/governor/read.ts +3 -0
- package/src/core/governor/state.ts +52 -5
- package/src/core/guard/config.ts +206 -0
- package/src/core/guard/coordinator.ts +227 -0
- package/src/core/guard/evaluator.ts +343 -0
- package/src/core/guard/evidence-v3.ts +227 -0
- package/src/core/guard/index.ts +35 -0
- package/src/core/guard/live-source-v3.ts +204 -0
- package/src/core/guard/storage.ts +188 -0
- package/src/core/guard/types.ts +152 -0
- package/src/core/hooks/adapter/detect.ts +28 -1
- package/src/core/hooks/adapter/events.ts +15 -6
- package/src/core/hooks/adapter/output.ts +7 -2
- package/src/core/hooks/adapter/parse.ts +81 -36
- package/src/core/hooks/adapter/wiring.ts +119 -13
- package/src/core/hooks/cli.ts +398 -422
- package/src/core/hooks/codex-authorization.ts +253 -0
- package/src/core/hooks/effects/image-capture.ts +228 -238
- package/src/core/hooks/effects/index.ts +1 -36
- package/src/core/hooks/events/input-hash.ts +47 -0
- package/src/core/hooks/index.ts +4 -11
- package/src/core/hooks/resolve/coord-root.ts +1 -1
- package/src/core/hooks/resolve/owner.ts +52 -45
- package/src/core/hooks/resolve/transcript.ts +165 -14
- package/src/core/hooks/session-name-presence.ts +14 -15
- package/src/core/hooks/unsafe-cross-shell.ts +1 -1
- package/src/core/journal/index.ts +15 -22
- package/src/core/presence/blob.ts +63 -38
- package/src/core/presence/codec-digest.ts +215 -0
- package/src/core/presence/index.ts +18 -1
- package/src/core/presence/relay-client.ts +5 -5
- package/src/core/work/index.ts +3 -0
- package/src/core/work/read.ts +3 -0
- package/src/core/work/runner.ts +6 -0
- package/src/core/work/state.ts +27 -3
- package/src/core/workflow/engine.ts +24 -24
- package/src/core/workflow/live-session-v3.ts +126 -0
- package/src/core/workflow/scope-id.ts +6 -0
- package/src/core/workflow/workspaces/leases.ts +56 -19
- package/src/index.ts +1 -1
- package/src/lib/browser/client.ts +230 -0
- package/src/lib/browser/critique.ts +104 -27
- package/src/lib/browser/geometry.ts +143 -14
- package/src/lib/browser/index.ts +34 -0
- package/src/lib/browser/qa-plan.ts +501 -0
- package/src/lib/browser/qa-reuse.ts +306 -0
- package/src/lib/browser/qa-snapshot.ts +223 -0
- package/src/lib/browser/runts.ts +27 -2
- package/src/lib/browser/tiling.ts +164 -0
- package/src/lib/context/index.ts +22 -46
- package/src/lib/council/index.ts +9 -21
- package/src/lib/docs-frontmatter.ts +8 -79
- package/src/lib/docs-index.ts +33 -3
- package/src/lib/docs-lint.ts +15 -29
- package/src/lib/docs-metadata-audit.ts +166 -0
- package/src/lib/docs-metadata-managed.ts +83 -0
- package/src/lib/docs-metadata-sync.ts +262 -0
- package/src/lib/docs-metadata-v2-schema.ts +138 -0
- package/src/lib/docs-metadata-v2.ts +646 -0
- package/src/lib/docs-new.ts +63 -0
- package/src/lib/docs-sweep.ts +42 -28
- package/src/lib/headless/index.ts +287 -0
- package/src/lib/identities/assume.ts +67 -86
- package/src/lib/instructions/apply.ts +33 -20
- package/src/lib/instructions/bundle.ts +199 -0
- package/src/lib/instructions/splice.ts +21 -7
- package/src/lib/instructions/templates.ts +85 -13
- package/dist/core/agents/cli-emit.d.ts +0 -27
- package/dist/core/agents/cli-emit.d.ts.map +0 -1
- package/dist/core/agents/cli-emit.js +0 -57
- package/dist/core/agents/codex-replay.d.ts +0 -29
- package/dist/core/agents/codex-replay.d.ts.map +0 -1
- package/dist/core/agents/codex-replay.js +0 -138
- package/dist/core/agents/events/consume.d.ts +0 -82
- package/dist/core/agents/events/consume.d.ts.map +0 -1
- package/dist/core/agents/events/consume.js +0 -195
- package/dist/core/agents/events/emit.d.ts +0 -42
- package/dist/core/agents/events/emit.d.ts.map +0 -1
- package/dist/core/agents/events/emit.js +0 -75
- package/dist/core/agents/events/ulid.d.ts +0 -11
- package/dist/core/agents/events/ulid.d.ts.map +0 -1
- package/dist/core/agents/events/ulid.js +0 -47
- package/dist/core/agents/state/heartbeat-projector.d.ts +0 -65
- package/dist/core/agents/state/heartbeat-projector.d.ts.map +0 -1
- package/dist/core/agents/state/heartbeat-projector.js +0 -527
- package/dist/core/hooks/events/emit.d.ts +0 -31
- package/dist/core/hooks/events/emit.d.ts.map +0 -1
- package/dist/core/hooks/events/emit.js +0 -93
- package/dist/core/hooks/events/rotate.d.ts +0 -43
- package/dist/core/hooks/events/rotate.d.ts.map +0 -1
- package/dist/core/hooks/events/rotate.js +0 -142
- package/dist/core/hooks/events/schema.d.ts +0 -312
- package/dist/core/hooks/events/schema.d.ts.map +0 -1
- package/dist/core/hooks/events/schema.js +0 -12
- package/dist/core/hooks/events/ulid.d.ts +0 -10
- package/dist/core/hooks/events/ulid.d.ts.map +0 -1
- package/dist/core/hooks/events/ulid.js +0 -47
- package/dist/lib/docs-frontmatter-migrate.d.ts +0 -33
- package/dist/lib/docs-frontmatter-migrate.d.ts.map +0 -1
- package/dist/lib/docs-frontmatter-migrate.js +0 -364
- package/src/core/agents/cli-emit.ts +0 -64
- package/src/core/agents/codex-replay.ts +0 -163
- package/src/core/agents/events/consume.ts +0 -254
- package/src/core/agents/events/emit.ts +0 -115
- package/src/core/agents/events/ulid.ts +0 -51
- package/src/core/agents/state/heartbeat-projector.ts +0 -582
- package/src/core/hooks/events/emit.ts +0 -125
- package/src/core/hooks/events/rotate.ts +0 -151
- package/src/core/hooks/events/schema.ts +0 -538
- package/src/core/hooks/events/ulid.ts +0 -51
- package/src/lib/docs-frontmatter-migrate.ts +0 -427
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { EmitContext, HarneryProgramContext } from "../commander.ts";
|
|
3
|
-
import { monorepoRoot,
|
|
3
|
+
import { monorepoRoot, resolveOwner } from "../core/agents/index.ts";
|
|
4
|
+
import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.ts";
|
|
4
5
|
import {
|
|
5
6
|
type ArtifactActor,
|
|
6
7
|
cleanArtifacts,
|
|
@@ -30,7 +31,7 @@ export function registerArtifactsCommand(
|
|
|
30
31
|
.action((slug: string, opts: { purpose: string; days?: string }) => {
|
|
31
32
|
run(emit, () => {
|
|
32
33
|
const repoRoot = requireRepoRoot(context);
|
|
33
|
-
const actor = currentActor();
|
|
34
|
+
const actor = currentActor(repoRoot);
|
|
34
35
|
const retentionDays = opts.days
|
|
35
36
|
? parseDays(opts.days)
|
|
36
37
|
: artifactDefaultRetentionDays(repoRoot);
|
|
@@ -85,7 +86,7 @@ export function registerArtifactsCommand(
|
|
|
85
86
|
run(emit, () => {
|
|
86
87
|
const repoRoot = requireRepoRoot(context);
|
|
87
88
|
const manifest = renewArtifact(repoRoot, ref, parseDays(opts.days), opts.reason, {
|
|
88
|
-
actor: currentActor(),
|
|
89
|
+
actor: currentActor(repoRoot),
|
|
89
90
|
});
|
|
90
91
|
emit.data(manifest);
|
|
91
92
|
});
|
|
@@ -97,7 +98,7 @@ export function registerArtifactsCommand(
|
|
|
97
98
|
.action((ref: string) => {
|
|
98
99
|
run(emit, () => {
|
|
99
100
|
const repoRoot = requireRepoRoot(context);
|
|
100
|
-
emit.data(releaseArtifact(repoRoot, ref, { actor: currentActor() }));
|
|
101
|
+
emit.data(releaseArtifact(repoRoot, ref, { actor: currentActor(repoRoot) }));
|
|
101
102
|
});
|
|
102
103
|
});
|
|
103
104
|
|
|
@@ -117,10 +118,10 @@ export function registerArtifactsCommand(
|
|
|
117
118
|
});
|
|
118
119
|
}
|
|
119
120
|
|
|
120
|
-
function currentActor(): ArtifactActor | undefined {
|
|
121
|
+
function currentActor(repoRoot: string): ArtifactActor | undefined {
|
|
121
122
|
const instanceId = resolveOwner();
|
|
122
123
|
if (!instanceId) return undefined;
|
|
123
|
-
const hb =
|
|
124
|
+
const hb = readLiveCoordinationRow(repoRoot, instanceId);
|
|
124
125
|
return {
|
|
125
126
|
instance_id: instanceId,
|
|
126
127
|
session_id: hb?.session_id,
|
package/src/commands/backup.ts
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* paths and are init'd on first `harn backup init`. Subcommands:
|
|
7
7
|
*
|
|
8
8
|
* init restic init the repo (one-time)
|
|
9
|
-
* snapshot restic backup
|
|
9
|
+
* snapshot restic backup of the durable, privacy-safe V3 state
|
|
10
10
|
* list restic snapshots
|
|
11
11
|
* restore restic restore <id>
|
|
12
12
|
* prune restic forget --keep-daily 7 --keep-weekly 4 --prune
|
|
@@ -134,17 +134,11 @@ export function registerBackupCommand(program: Command, emit: EmitContext): void
|
|
|
134
134
|
backup
|
|
135
135
|
.command("snapshot")
|
|
136
136
|
.description(
|
|
137
|
-
"Take a restic snapshot of
|
|
138
|
-
".lock files and artifacts/ by default). Pass --target to back up a different path.",
|
|
137
|
+
"Take a restic snapshot of the durable, privacy-safe V3 ledger and coordination state.",
|
|
139
138
|
)
|
|
140
|
-
.option("--target <path>", "Path to snapshot (default: .harnery/ from cwd walk-up)")
|
|
141
139
|
.option("--tag <tag>", "Restic tag (repeatable)", collect, [] as string[])
|
|
142
140
|
.option("--repo <path>", "Repository path")
|
|
143
141
|
.option("--password-file <path>", "Password file")
|
|
144
|
-
.option(
|
|
145
|
-
"--include-events",
|
|
146
|
-
"Don't exclude events.ndjson (default: excluded; large + machine-local)",
|
|
147
|
-
)
|
|
148
142
|
.option(
|
|
149
143
|
"--include-artifacts",
|
|
150
144
|
"Include managed working artifacts (default: excluded; potentially large + ephemeral)",
|
|
@@ -152,9 +146,7 @@ export function registerBackupCommand(program: Command, emit: EmitContext): void
|
|
|
152
146
|
.action(
|
|
153
147
|
(
|
|
154
148
|
opts: BaseOpts & {
|
|
155
|
-
target?: string;
|
|
156
149
|
tag: string[];
|
|
157
|
-
includeEvents?: boolean;
|
|
158
150
|
includeArtifacts?: boolean;
|
|
159
151
|
},
|
|
160
152
|
) => {
|
|
@@ -162,27 +154,43 @@ export function registerBackupCommand(program: Command, emit: EmitContext): void
|
|
|
162
154
|
emit.setExitCode(1);
|
|
163
155
|
return;
|
|
164
156
|
}
|
|
165
|
-
const
|
|
166
|
-
if (!
|
|
157
|
+
const harnery = findHarneryDir();
|
|
158
|
+
if (!harnery) {
|
|
167
159
|
emit.error({
|
|
168
160
|
code: "target_missing",
|
|
169
|
-
message:
|
|
170
|
-
"No .harnery/ found above cwd; pass --target explicitly or run from a monorepo with .harnery/",
|
|
161
|
+
message: "No .harnery/ found above cwd; run from an initialized project",
|
|
171
162
|
});
|
|
172
163
|
emit.setExitCode(1);
|
|
173
164
|
return;
|
|
174
165
|
}
|
|
175
166
|
const passThrough: string[] = [];
|
|
176
|
-
if (!opts.includeEvents) {
|
|
177
|
-
passThrough.push("--exclude", "events.ndjson");
|
|
178
|
-
passThrough.push("--exclude", ".lock");
|
|
179
|
-
passThrough.push("--exclude", ".log.lock");
|
|
180
|
-
}
|
|
181
|
-
if (!opts.includeArtifacts) passThrough.push("--exclude", "artifacts");
|
|
182
167
|
for (const t of opts.tag) {
|
|
183
168
|
passThrough.push("--tag", t);
|
|
184
169
|
}
|
|
185
|
-
const
|
|
170
|
+
const safeTargets = [
|
|
171
|
+
"ledgers",
|
|
172
|
+
"councils",
|
|
173
|
+
"journal",
|
|
174
|
+
"work",
|
|
175
|
+
"workflows",
|
|
176
|
+
"decisions",
|
|
177
|
+
"config.jsonc",
|
|
178
|
+
".name-history",
|
|
179
|
+
]
|
|
180
|
+
.map((entry) => path.join(harnery, entry))
|
|
181
|
+
.filter(existsSync);
|
|
182
|
+
if (opts.includeArtifacts && existsSync(path.join(harnery, "artifacts"))) {
|
|
183
|
+
safeTargets.push(path.join(harnery, "artifacts"));
|
|
184
|
+
}
|
|
185
|
+
if (safeTargets.length === 0) {
|
|
186
|
+
emit.error({
|
|
187
|
+
code: "backup_empty",
|
|
188
|
+
message: "No durable V3 state is available to back up",
|
|
189
|
+
});
|
|
190
|
+
emit.setExitCode(1);
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
const r = runRestic(["backup", ...safeTargets], {
|
|
186
194
|
repo: opts.repo,
|
|
187
195
|
passwordFile: opts.passwordFile,
|
|
188
196
|
stdio: "inherit",
|
package/src/commands/browse.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { existsSync, mkdirSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
1
|
+
import { existsSync, mkdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, isAbsolute, resolve } from "node:path";
|
|
4
4
|
import type { Command } from "commander";
|
|
@@ -33,6 +33,24 @@ import {
|
|
|
33
33
|
writeNetscapeCookieFile,
|
|
34
34
|
wslHeadedLaunchArgs,
|
|
35
35
|
} from "../lib/browser/index.ts";
|
|
36
|
+
import {
|
|
37
|
+
buildQaManifest,
|
|
38
|
+
classifySignatures,
|
|
39
|
+
type QaClassification,
|
|
40
|
+
type QaContext,
|
|
41
|
+
type QaManifest,
|
|
42
|
+
type QaScope,
|
|
43
|
+
type QaSignature,
|
|
44
|
+
} from "../lib/browser/qa-plan.ts";
|
|
45
|
+
import {
|
|
46
|
+
type CritiqueReusePlan,
|
|
47
|
+
DEFAULT_REUSE_MISMATCH_RATIO,
|
|
48
|
+
type PersistedCritique,
|
|
49
|
+
planCritiqueReuse,
|
|
50
|
+
QA_CRITIQUE_CONTRACT_VERSION,
|
|
51
|
+
rubricDigest,
|
|
52
|
+
} from "../lib/browser/qa-reuse.ts";
|
|
53
|
+
import { loadQaSnapshot, resolveQaBaseline, saveQaSnapshot } from "../lib/browser/qa-snapshot.ts";
|
|
36
54
|
import {
|
|
37
55
|
type BrowserSessionServer,
|
|
38
56
|
startBrowserSessionServer,
|
|
@@ -181,6 +199,16 @@ interface BrowseOpts {
|
|
|
181
199
|
diff?: string;
|
|
182
200
|
diffThreshold?: string;
|
|
183
201
|
diffFail?: boolean;
|
|
202
|
+
// Diff-aware QA planning (qa-plan.ts / qa-snapshot.ts)
|
|
203
|
+
qaPlan?: boolean;
|
|
204
|
+
qaSnapshot?: boolean;
|
|
205
|
+
qaTarget?: string;
|
|
206
|
+
qaTheme?: string;
|
|
207
|
+
qaState?: string;
|
|
208
|
+
qaScope?: string[];
|
|
209
|
+
qaStates?: string[];
|
|
210
|
+
qaReuse?: boolean;
|
|
211
|
+
qaReuseThreshold?: string;
|
|
184
212
|
// Next.js dev-overlay capture (auto-on; --no-dev-overlay opts out)
|
|
185
213
|
devOverlay?: boolean;
|
|
186
214
|
}
|
|
@@ -590,6 +618,67 @@ export function registerBrowseCommand(
|
|
|
590
618
|
"--diff-fail",
|
|
591
619
|
"Exit non-zero if --diff mismatchRatio exceeds --diff-threshold; requires --diff.",
|
|
592
620
|
)
|
|
621
|
+
.option(
|
|
622
|
+
"--qa-plan",
|
|
623
|
+
"Classify this render against the persisted QA baseline and emit a review manifest " +
|
|
624
|
+
"(change class, scope selectors, required contexts, provider-call ceiling) under " +
|
|
625
|
+
"`qaPlan` in the JSON envelope — BEFORE any vision spend. Text/data-only edits plan " +
|
|
626
|
+
"zero model calls; ambiguity widens, never narrows. Baseline comes from the snapshot " +
|
|
627
|
+
"store (seed one with --qa-snapshot); no baseline classifies as `unknown`.",
|
|
628
|
+
)
|
|
629
|
+
.option(
|
|
630
|
+
"--qa-snapshot",
|
|
631
|
+
"Persist this render (signature + DOM + full-page screenshot) as the QA baseline for the " +
|
|
632
|
+
"target + context, replacing any prior snapshot atomically. Run it on a page state you " +
|
|
633
|
+
"trust — typically right after a passing QA run — so the next --qa-plan inherits its " +
|
|
634
|
+
"baseline for free.",
|
|
635
|
+
)
|
|
636
|
+
.option(
|
|
637
|
+
"--qa-target <key>",
|
|
638
|
+
"Override the snapshot-store key (default: the url argument). Lets a production render " +
|
|
639
|
+
"seed the baseline for a local file/route: browse the prod URL with --qa-snapshot " +
|
|
640
|
+
"--qa-target <local-target>, then --qa-plan the local target.",
|
|
641
|
+
)
|
|
642
|
+
.option(
|
|
643
|
+
"--qa-theme <theme>",
|
|
644
|
+
"Context label for the QA snapshot store: light | dark (default light). Labels the " +
|
|
645
|
+
"stored/compared context; it does not switch the page's rendered theme.",
|
|
646
|
+
"light",
|
|
647
|
+
)
|
|
648
|
+
.option(
|
|
649
|
+
"--qa-state <name>",
|
|
650
|
+
"Context state label for the QA snapshot store (default 'default').",
|
|
651
|
+
"default",
|
|
652
|
+
)
|
|
653
|
+
.option(
|
|
654
|
+
"--qa-scope <selector>",
|
|
655
|
+
"Explicit scope selector from the producing task (repeatable) — resolution-order rung 1; " +
|
|
656
|
+
"overrides lifted anchors in the --qa-plan manifest.",
|
|
657
|
+
(value: string, previous: string[] = []) => [...previous, value],
|
|
658
|
+
[] as string[],
|
|
659
|
+
)
|
|
660
|
+
.option(
|
|
661
|
+
"--qa-states <names>",
|
|
662
|
+
"Comma-separated interaction states to review (promotes the plan to interaction-state).",
|
|
663
|
+
(value: string) =>
|
|
664
|
+
value
|
|
665
|
+
.split(",")
|
|
666
|
+
.map((s) => s.trim())
|
|
667
|
+
.filter(Boolean),
|
|
668
|
+
)
|
|
669
|
+
.option(
|
|
670
|
+
"--qa-reuse",
|
|
671
|
+
"Reuse the baseline run's critique verdicts for tiles whose pixels provably didn't " +
|
|
672
|
+
"change (band-diff against the persisted --qa-snapshot screenshot; strict mismatch " +
|
|
673
|
+
"threshold). Only clean regions are reused — a region with baseline findings or any " +
|
|
674
|
+
"pixel drift is always re-reviewed. Requires --check-critique; misses degrade to a " +
|
|
675
|
+
"full fresh review, never an error. Stats land under `qaReuse` in the JSON envelope.",
|
|
676
|
+
)
|
|
677
|
+
.option(
|
|
678
|
+
"--qa-reuse-threshold <ratio>",
|
|
679
|
+
"Band-diff mismatch ratio at or below which a clean tile region is reused " +
|
|
680
|
+
`(default ${DEFAULT_REUSE_MISMATCH_RATIO}; lower it toward 0 for stricter reuse).`,
|
|
681
|
+
)
|
|
593
682
|
.option(
|
|
594
683
|
"--no-dev-overlay",
|
|
595
684
|
"Skip auto-capture of Next.js dev-overlay issues. Default: capture every queued error (kind/code/message/stack) when a <nextjs-portal> shadow root is present. Necessary because Next.js 16 + React 19 route hydration errors + most React warnings through onCaughtError → next-devtools' errorQueue, NOT through console.error, so Playwright's standard listener doesn't see them. Surfaces them in the JSON envelope under `devOverlay`.",
|
|
@@ -818,18 +907,139 @@ async function runBrowse(
|
|
|
818
907
|
opts.checkContrast !== undefined ? { scope: contentScope(opts.checkContrast) } : null,
|
|
819
908
|
});
|
|
820
909
|
}
|
|
910
|
+
// Diff-aware QA planning. Signature capture must also happen BEFORE any
|
|
911
|
+
// annotation overlays are injected — an annotation box is a DOM change.
|
|
912
|
+
let qaPlan: QaPlanReport | undefined;
|
|
913
|
+
let qaCapture: QaCaptureState | undefined;
|
|
914
|
+
if (opts.qaPlan || opts.qaSnapshot) {
|
|
915
|
+
const qa = await runQaPlanning(browser, url, navResult.url, opts);
|
|
916
|
+
qaPlan = qa.report;
|
|
917
|
+
qaCapture = qa.capture;
|
|
918
|
+
if (qaPlan?.manifest) {
|
|
919
|
+
const m = qaPlan.manifest;
|
|
920
|
+
emit.log(
|
|
921
|
+
`qa-plan: class=${m.change_class} scopes=${m.scopes.map((s) => s.selector).join(",") || "-"} ` +
|
|
922
|
+
`contexts=${m.contexts.length} model-calls<=${m.predicted.model_calls_ceiling} baseline=${m.baseline_source}`,
|
|
923
|
+
"info",
|
|
924
|
+
);
|
|
925
|
+
}
|
|
926
|
+
}
|
|
821
927
|
// Vision critique. Capture tiles BEFORE any annotation overlays are injected
|
|
822
928
|
// so the model sees the real page, not our boxes.
|
|
823
929
|
let critique: CritiqueResult | undefined;
|
|
930
|
+
let qaReuse: CritiqueReusePlan | undefined;
|
|
931
|
+
let critiqueTiles: CritiqueTile[] | undefined;
|
|
932
|
+
let critiqueFullPage: Buffer | undefined;
|
|
824
933
|
if (opts.checkCritique !== undefined) {
|
|
825
|
-
const
|
|
934
|
+
const rubric = opts.checkCritiqueRubric ?? DEFAULT_CRITIQUE_RUBRIC;
|
|
935
|
+
const captured = await captureCritiqueTiles(
|
|
936
|
+
browser,
|
|
937
|
+
opts,
|
|
938
|
+
context?.critiqueProvider?.tileBudgetPx,
|
|
939
|
+
);
|
|
940
|
+
critiqueTiles = captured.tiles;
|
|
941
|
+
critiqueFullPage = captured.fullPage;
|
|
942
|
+
let tilesToReview = captured.tiles;
|
|
943
|
+
if (opts.qaReuse) {
|
|
944
|
+
const reuseContext: QaContext = {
|
|
945
|
+
viewport: opts.viewport ?? "desktop",
|
|
946
|
+
theme: opts.qaTheme === "dark" ? "dark" : "light",
|
|
947
|
+
state: opts.qaState ?? "default",
|
|
948
|
+
};
|
|
949
|
+
const stored = loadQaSnapshot(opts.qaTarget ?? url, reuseContext, {});
|
|
950
|
+
if (stored?.screenshotPath && stored.critique) {
|
|
951
|
+
qaReuse = planCritiqueReuse({
|
|
952
|
+
baselineScreenshot: readFileSync(stored.screenshotPath),
|
|
953
|
+
baselineCritique: stored.critique,
|
|
954
|
+
currentScreenshot: captured.fullPage,
|
|
955
|
+
tiles: captured.tiles,
|
|
956
|
+
rubric,
|
|
957
|
+
mismatchThreshold: opts.qaReuseThreshold
|
|
958
|
+
? Number.parseFloat(opts.qaReuseThreshold)
|
|
959
|
+
: undefined,
|
|
960
|
+
});
|
|
961
|
+
} else {
|
|
962
|
+
qaReuse = {
|
|
963
|
+
mode: "band-diff",
|
|
964
|
+
review: captured.tiles,
|
|
965
|
+
decisions: [],
|
|
966
|
+
tiles_total: captured.tiles.length,
|
|
967
|
+
tiles_reused: 0,
|
|
968
|
+
tiles_reviewed: captured.tiles.length,
|
|
969
|
+
provider_calls_avoided: 0,
|
|
970
|
+
mismatch_threshold: DEFAULT_REUSE_MISMATCH_RATIO,
|
|
971
|
+
invalidation:
|
|
972
|
+
"no persisted baseline snapshot with critique results for this target/context",
|
|
973
|
+
};
|
|
974
|
+
}
|
|
975
|
+
tilesToReview = qaReuse.review;
|
|
976
|
+
emit.log(
|
|
977
|
+
`qa-reuse: ${qaReuse.tiles_reused}/${qaReuse.tiles_total} tiles reused (band-diff), ` +
|
|
978
|
+
`${qaReuse.tiles_reviewed} reviewed fresh${qaReuse.invalidation ? ` — ${qaReuse.invalidation}` : ""}`,
|
|
979
|
+
"info",
|
|
980
|
+
);
|
|
981
|
+
}
|
|
826
982
|
critique = await runCritique({
|
|
827
983
|
url: navResult.url,
|
|
828
|
-
rubric
|
|
829
|
-
tiles,
|
|
984
|
+
rubric,
|
|
985
|
+
tiles: tilesToReview,
|
|
830
986
|
provider: context?.critiqueProvider,
|
|
831
987
|
});
|
|
832
988
|
}
|
|
989
|
+
// Persist the QA baseline AFTER critique so a passing run's verdicts ride
|
|
990
|
+
// along with the snapshot (still before annotations mutate the page).
|
|
991
|
+
if (opts.qaSnapshot && qaCapture) {
|
|
992
|
+
const screenshotPng = critiqueFullPage ?? (await browser.fullPageScreenshotBuffer());
|
|
993
|
+
// Persist critique results only when the full tile set was freshly
|
|
994
|
+
// reviewed — a partially-reused run must never become the next
|
|
995
|
+
// baseline's finding record.
|
|
996
|
+
const fullCoverage =
|
|
997
|
+
critique?.provider &&
|
|
998
|
+
critique.outcome !== "skipped" &&
|
|
999
|
+
critiqueTiles !== undefined &&
|
|
1000
|
+
(!qaReuse || qaReuse.tiles_reused === 0);
|
|
1001
|
+
const persistedCritique: PersistedCritique | undefined =
|
|
1002
|
+
fullCoverage && critique && critiqueTiles
|
|
1003
|
+
? {
|
|
1004
|
+
contract_version: QA_CRITIQUE_CONTRACT_VERSION,
|
|
1005
|
+
rubric_digest: rubricDigest(opts.checkCritiqueRubric ?? DEFAULT_CRITIQUE_RUBRIC),
|
|
1006
|
+
outcome: critique.outcome as "pass" | "fail",
|
|
1007
|
+
findings: critique.findings,
|
|
1008
|
+
tiles: critiqueTiles.map((t) => ({
|
|
1009
|
+
index: t.index,
|
|
1010
|
+
label: t.label,
|
|
1011
|
+
x: t.x ?? 0,
|
|
1012
|
+
scrollY: t.scrollY,
|
|
1013
|
+
width: t.width,
|
|
1014
|
+
height: t.height,
|
|
1015
|
+
})),
|
|
1016
|
+
}
|
|
1017
|
+
: undefined;
|
|
1018
|
+
const saved = saveQaSnapshot(
|
|
1019
|
+
qaCapture.target,
|
|
1020
|
+
qaCapture.context,
|
|
1021
|
+
{
|
|
1022
|
+
signature: qaCapture.signature,
|
|
1023
|
+
domHtml: qaCapture.domHtml,
|
|
1024
|
+
screenshotPng,
|
|
1025
|
+
...(persistedCritique ? { critique: persistedCritique } : {}),
|
|
1026
|
+
},
|
|
1027
|
+
{},
|
|
1028
|
+
);
|
|
1029
|
+
if (qaPlan) {
|
|
1030
|
+
qaPlan.snapshotSaved = {
|
|
1031
|
+
path: saved.path,
|
|
1032
|
+
target: qaCapture.target,
|
|
1033
|
+
context: qaCapture.context,
|
|
1034
|
+
};
|
|
1035
|
+
}
|
|
1036
|
+
emit.log(
|
|
1037
|
+
`qa-snapshot: saved baseline for ${qaCapture.target} ` +
|
|
1038
|
+
`[${qaCapture.context.viewport}/${qaCapture.context.theme}/${qaCapture.context.state}]` +
|
|
1039
|
+
`${persistedCritique ? " (with critique results)" : ""}`,
|
|
1040
|
+
"info",
|
|
1041
|
+
);
|
|
1042
|
+
}
|
|
833
1043
|
let asserts: AssertResult[] | undefined;
|
|
834
1044
|
if (opts.assert && opts.assert.length > 0) {
|
|
835
1045
|
const specs = opts.assert.map(parseAssertSpec);
|
|
@@ -948,6 +1158,8 @@ async function runBrowse(
|
|
|
948
1158
|
asserts,
|
|
949
1159
|
devOverlay,
|
|
950
1160
|
batchResult,
|
|
1161
|
+
qaPlan,
|
|
1162
|
+
qaReuse ? summarizeReuse(qaReuse) : undefined,
|
|
951
1163
|
);
|
|
952
1164
|
} else {
|
|
953
1165
|
await runTrioMode(
|
|
@@ -966,6 +1178,8 @@ async function runBrowse(
|
|
|
966
1178
|
asserts,
|
|
967
1179
|
devOverlay,
|
|
968
1180
|
batchResult,
|
|
1181
|
+
qaPlan,
|
|
1182
|
+
qaReuse ? summarizeReuse(qaReuse) : undefined,
|
|
969
1183
|
);
|
|
970
1184
|
}
|
|
971
1185
|
|
|
@@ -1209,6 +1423,8 @@ async function runPrintMode(
|
|
|
1209
1423
|
asserts: AssertResult[] | undefined,
|
|
1210
1424
|
devOverlay: DevOverlayResult | undefined,
|
|
1211
1425
|
batchResult: BatchResult | undefined,
|
|
1426
|
+
qaPlan: QaPlanReport | undefined,
|
|
1427
|
+
qaReuse: Record<string, unknown> | undefined,
|
|
1212
1428
|
): Promise<void> {
|
|
1213
1429
|
let body: string | null = null;
|
|
1214
1430
|
if (opts.html) {
|
|
@@ -1243,6 +1459,8 @@ async function runPrintMode(
|
|
|
1243
1459
|
if (critique) result.critique = critique;
|
|
1244
1460
|
if (asserts) result.asserts = asserts;
|
|
1245
1461
|
if (devOverlay) result.devOverlay = devOverlay;
|
|
1462
|
+
if (qaPlan) result.qaPlan = qaPlan;
|
|
1463
|
+
if (qaReuse) result.qaReuse = qaReuse;
|
|
1246
1464
|
if (batchResult && batchResult.clipboardReads.length > 0) {
|
|
1247
1465
|
result.batchClipboardReads = batchResult.clipboardReads;
|
|
1248
1466
|
}
|
|
@@ -1279,6 +1497,8 @@ async function runTrioMode(
|
|
|
1279
1497
|
asserts: AssertResult[] | undefined,
|
|
1280
1498
|
devOverlay: DevOverlayResult | undefined,
|
|
1281
1499
|
batchResult: BatchResult | undefined,
|
|
1500
|
+
qaPlan: QaPlanReport | undefined,
|
|
1501
|
+
qaReuse: Record<string, unknown> | undefined,
|
|
1282
1502
|
): Promise<void> {
|
|
1283
1503
|
const prefix = resolveOutPrefix(opts.out);
|
|
1284
1504
|
mkdirSync(dirname(prefix), { recursive: true });
|
|
@@ -1351,6 +1571,8 @@ async function runTrioMode(
|
|
|
1351
1571
|
if (critique) envelope.critique = critique;
|
|
1352
1572
|
if (asserts) envelope.asserts = asserts;
|
|
1353
1573
|
if (devOverlay) envelope.devOverlay = devOverlay;
|
|
1574
|
+
if (qaPlan) envelope.qaPlan = qaPlan;
|
|
1575
|
+
if (qaReuse) envelope.qaReuse = qaReuse;
|
|
1354
1576
|
if (batchResult && batchResult.clipboardReads.length > 0) {
|
|
1355
1577
|
envelope.batchClipboardReads = batchResult.clipboardReads;
|
|
1356
1578
|
}
|
|
@@ -1812,9 +2034,113 @@ function applyContentFailGates(opts: BrowseOpts, content: ContentChecksResult |
|
|
|
1812
2034
|
// Vision critique tiling
|
|
1813
2035
|
// ---------------------------------------------------------------------------
|
|
1814
2036
|
|
|
1815
|
-
|
|
2037
|
+
/** Envelope-safe reuse stats: everything except the `review` tiles, whose
|
|
2038
|
+
* base64 PNGs would bloat the JSON by megabytes. */
|
|
2039
|
+
function summarizeReuse(plan: CritiqueReusePlan): Record<string, unknown> {
|
|
2040
|
+
const { review: _review, ...rest } = plan;
|
|
2041
|
+
return rest;
|
|
2042
|
+
}
|
|
2043
|
+
|
|
2044
|
+
/** What `--qa-plan` / `--qa-snapshot` put in the JSON envelope. */
|
|
2045
|
+
interface QaPlanReport {
|
|
2046
|
+
manifest?: QaManifest;
|
|
2047
|
+
classification?: QaClassification;
|
|
2048
|
+
snapshotSaved?: { path: string; target: string; context: QaContext };
|
|
2049
|
+
signature: { nodes: number; stylesheets: number; truncated: boolean };
|
|
2050
|
+
}
|
|
2051
|
+
|
|
2052
|
+
/** The captured page state a later --qa-snapshot persist needs. Kept out of
|
|
2053
|
+
* the envelope: domHtml can be megabytes. */
|
|
2054
|
+
interface QaCaptureState {
|
|
2055
|
+
target: string;
|
|
2056
|
+
context: QaContext;
|
|
2057
|
+
signature: QaSignature;
|
|
2058
|
+
domHtml: string;
|
|
2059
|
+
}
|
|
2060
|
+
|
|
2061
|
+
/**
|
|
2062
|
+
* Diff-aware QA planning inside a browse run: capture the page's QA signature
|
|
2063
|
+
* (before any annotation overlay mutates the DOM) and classify against the
|
|
2064
|
+
* persisted baseline. Persistence happens later in the run — after critique —
|
|
2065
|
+
* so a passing run's verdicts ride along with the snapshot; this helper only
|
|
2066
|
+
* supplies the live-page inputs (signature, page height, explicit scope match
|
|
2067
|
+
* counts). Classification and manifest math live in lib/browser/qa-plan.ts.
|
|
2068
|
+
*/
|
|
2069
|
+
async function runQaPlanning(
|
|
2070
|
+
browser: Browser,
|
|
2071
|
+
targetArg: string,
|
|
2072
|
+
renderedUrl: string,
|
|
2073
|
+
opts: BrowseOpts,
|
|
2074
|
+
): Promise<{ report: QaPlanReport; capture: QaCaptureState }> {
|
|
2075
|
+
const context: QaContext = {
|
|
2076
|
+
viewport: opts.viewport ?? "desktop",
|
|
2077
|
+
theme: opts.qaTheme === "dark" ? "dark" : "light",
|
|
2078
|
+
state: opts.qaState ?? "default",
|
|
2079
|
+
};
|
|
2080
|
+
const target = opts.qaTarget ?? targetArg;
|
|
2081
|
+
const captured = await browser.qaSignature();
|
|
2082
|
+
const signature: QaSignature = {
|
|
2083
|
+
url: renderedUrl,
|
|
2084
|
+
capturedAt: new Date().toISOString(),
|
|
2085
|
+
nodes: captured.nodes,
|
|
2086
|
+
stylesheets: captured.stylesheets,
|
|
2087
|
+
...(captured.truncated ? { truncated: true } : {}),
|
|
2088
|
+
};
|
|
2089
|
+
const report: QaPlanReport = {
|
|
2090
|
+
signature: {
|
|
2091
|
+
nodes: captured.nodes.length,
|
|
2092
|
+
stylesheets: captured.stylesheets.length,
|
|
2093
|
+
truncated: captured.truncated,
|
|
2094
|
+
},
|
|
2095
|
+
};
|
|
2096
|
+
|
|
2097
|
+
if (opts.qaPlan) {
|
|
2098
|
+
const baseline = await resolveQaBaseline({ target, context });
|
|
2099
|
+
const classification = classifySignatures(baseline.signature, signature);
|
|
2100
|
+
// Full-page tile ceiling from the real page height and the critique
|
|
2101
|
+
// tiling knobs, so the predicted cost matches what --check-critique
|
|
2102
|
+
// would actually spend.
|
|
2103
|
+
const pageHeight = await browser.currentPage.evaluate(() =>
|
|
2104
|
+
Math.max(document.documentElement.scrollHeight, document.body?.scrollHeight ?? 0),
|
|
2105
|
+
);
|
|
2106
|
+
const band = Number.parseInt(opts.checkCritiqueBand ?? "1400", 10);
|
|
2107
|
+
const overlap = Number.parseInt(opts.checkCritiqueOverlap ?? "120", 10);
|
|
2108
|
+
const maxTiles = Number.parseInt(opts.checkCritiqueMaxTiles ?? "24", 10);
|
|
2109
|
+
const estimatedFullPageTiles = Math.min(
|
|
2110
|
+
maxTiles,
|
|
2111
|
+
Math.max(1, Math.ceil(pageHeight / Math.max(1, band - overlap))),
|
|
2112
|
+
);
|
|
2113
|
+
const explicitScopes: QaScope[] = [];
|
|
2114
|
+
for (const selector of opts.qaScope ?? []) {
|
|
2115
|
+
const matches = await browser.currentPage.evaluate(
|
|
2116
|
+
(sel) => document.querySelectorAll(sel).length,
|
|
2117
|
+
selector,
|
|
2118
|
+
);
|
|
2119
|
+
explicitScopes.push({ selector, reason: "explicit input (--qa-scope)", matches });
|
|
2120
|
+
}
|
|
2121
|
+
report.classification = classification;
|
|
2122
|
+
report.manifest = buildQaManifest(classification, {
|
|
2123
|
+
baselineSource: baseline.source,
|
|
2124
|
+
...(explicitScopes.length > 0 ? { explicitScopes } : {}),
|
|
2125
|
+
...(opts.qaStates?.length ? { states: opts.qaStates } : {}),
|
|
2126
|
+
...(opts.assert?.length ? { outcomeAssertions: opts.assert } : {}),
|
|
2127
|
+
estimatedFullPageTiles,
|
|
2128
|
+
});
|
|
2129
|
+
}
|
|
2130
|
+
|
|
2131
|
+
return { report, capture: { target, context, signature, domHtml: captured.domHtml } };
|
|
2132
|
+
}
|
|
2133
|
+
|
|
2134
|
+
async function captureCritiqueTiles(
|
|
2135
|
+
browser: Browser,
|
|
2136
|
+
opts: BrowseOpts,
|
|
2137
|
+
tileBudgetPx?: number,
|
|
2138
|
+
): Promise<{ tiles: CritiqueTile[]; fullPage: Buffer }> {
|
|
1816
2139
|
const maxTiles = Math.max(1, Number.parseInt(opts.checkCritiqueMaxTiles ?? "24", 10));
|
|
1817
|
-
|
|
2140
|
+
// The routed provider's vision long-edge budget caps band height so tiles
|
|
2141
|
+
// are never silently downscaled by the model.
|
|
2142
|
+
const bandFlag = Math.max(200, Number.parseInt(opts.checkCritiqueBand ?? "1400", 10));
|
|
2143
|
+
const band = tileBudgetPx ? Math.max(200, Math.min(bandFlag, tileBudgetPx)) : bandFlag;
|
|
1818
2144
|
const overlap = Math.max(0, Number.parseInt(opts.checkCritiqueOverlap ?? "120", 10));
|
|
1819
2145
|
|
|
1820
2146
|
// Capture the whole page ONCE, then crop tiles from the pixels. Playwright's
|
|
@@ -1826,7 +2152,22 @@ async function captureCritiqueTiles(browser: Browser, opts: BrowseOpts): Promise
|
|
|
1826
2152
|
typeof opts.checkCritique === "string"
|
|
1827
2153
|
? await browser.elementTiles(opts.checkCritique)
|
|
1828
2154
|
: undefined;
|
|
1829
|
-
|
|
2155
|
+
// Content-aware seams: atoms let band cuts snap into gaps and over-tall
|
|
2156
|
+
// selector tiles band internally. Extraction failing is never fatal — the
|
|
2157
|
+
// tiler falls back to fixed bands, today's behavior.
|
|
2158
|
+
let atoms: Awaited<ReturnType<Browser["visualAtoms"]>> | undefined;
|
|
2159
|
+
try {
|
|
2160
|
+
atoms = await browser.visualAtoms();
|
|
2161
|
+
} catch {
|
|
2162
|
+
atoms = undefined;
|
|
2163
|
+
}
|
|
2164
|
+
const tiles = tilesFromFullPage(buffer, {
|
|
2165
|
+
elementRects,
|
|
2166
|
+
bandHeight: band,
|
|
2167
|
+
overlap,
|
|
2168
|
+
maxTiles,
|
|
2169
|
+
atoms,
|
|
2170
|
+
});
|
|
1830
2171
|
|
|
1831
2172
|
if (elementRects && elementRects.length > maxTiles) {
|
|
1832
2173
|
emit.log(
|
|
@@ -1839,7 +2180,7 @@ async function captureCritiqueTiles(browser: Browser, opts: BrowseOpts): Promise
|
|
|
1839
2180
|
"warn",
|
|
1840
2181
|
);
|
|
1841
2182
|
}
|
|
1842
|
-
return tiles;
|
|
2183
|
+
return { tiles, fullPage: buffer };
|
|
1843
2184
|
}
|
|
1844
2185
|
function logCritiqueSummary(critique: CritiqueResult): void {
|
|
1845
2186
|
if (critique.outcome === "skipped") {
|
|
@@ -1,13 +1,14 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
2
|
import type { EmitContext, HarneryProgramContext } from "../commander.ts";
|
|
3
|
-
import {
|
|
3
|
+
import type { Adapter } from "../core/adapter.ts";
|
|
4
|
+
import { monorepoRoot, resolveOwner } from "../core/agents/index.ts";
|
|
5
|
+
import { readLiveCoordinationRow } from "../core/agents/state/live-coordination-view.ts";
|
|
4
6
|
import {
|
|
5
7
|
type CheckpointReason,
|
|
6
8
|
checkpointContext,
|
|
7
9
|
readContextState,
|
|
8
10
|
readLatestCapsule,
|
|
9
11
|
} from "../core/context/index.ts";
|
|
10
|
-
import type { Adapter } from "../core/hooks/events/schema.ts";
|
|
11
12
|
|
|
12
13
|
/**
|
|
13
14
|
* `harn checkpoint`: durable context continuity across compaction.
|
|
@@ -156,7 +157,7 @@ function resolveContinuityIdentity(
|
|
|
156
157
|
if (!instanceId) {
|
|
157
158
|
throw new Error("could not resolve the current agent; pass --instance and --session");
|
|
158
159
|
}
|
|
159
|
-
const heartbeat =
|
|
160
|
+
const heartbeat = readLiveCoordinationRow(coordRoot, instanceId);
|
|
160
161
|
const sessionId = opts.session ?? heartbeat?.session_id ?? instanceId;
|
|
161
162
|
const adapter = opts.adapter
|
|
162
163
|
? parseAdapter(opts.adapter)
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { Command } from "commander";
|
|
2
|
-
import type { EmitContext } from "../commander.ts";
|
|
2
|
+
import type { EmitContext, HarneryProgramContext } from "../commander.ts";
|
|
3
3
|
import {
|
|
4
4
|
applyMirror,
|
|
5
5
|
type DesktopAccount,
|
|
@@ -24,12 +24,14 @@ import {
|
|
|
24
24
|
* desktop app picks the copies up, and opening one resumes with full
|
|
25
25
|
* history.
|
|
26
26
|
*/
|
|
27
|
-
export function registerClaudeDesktopCommand(
|
|
27
|
+
export function registerClaudeDesktopCommand(
|
|
28
|
+
program: Command,
|
|
29
|
+
emit: EmitContext,
|
|
30
|
+
_context?: HarneryProgramContext,
|
|
31
|
+
): void {
|
|
28
32
|
const cmd = program
|
|
29
33
|
.command("claude-desktop")
|
|
30
|
-
.description(
|
|
31
|
-
"Claude desktop-app session index: list accounts/sessions, mirror sessions across accounts",
|
|
32
|
-
)
|
|
34
|
+
.description("Claude desktop-app session index: list and mirror sessions across accounts")
|
|
33
35
|
.action(() => {
|
|
34
36
|
const dirs = requireDataDirs(emit, undefined);
|
|
35
37
|
for (const dir of dirs) {
|
package/src/commands/context.ts
CHANGED
|
@@ -112,10 +112,6 @@ function renderSelf(s: NonNullable<ContextReport["self"]>): string[] {
|
|
|
112
112
|
` agent-${s.name ?? "?"} (${formatAge(s.session_age_secs)} old, owner=${s.instance_id.slice(0, 8)}…)`,
|
|
113
113
|
);
|
|
114
114
|
if (s.task) body.push(` task: "${s.task}"`);
|
|
115
|
-
if (s.last_tool) {
|
|
116
|
-
const target = s.last_tool_target ? ` ${truncate(s.last_tool_target, 80)}` : "";
|
|
117
|
-
body.push(` last: ${s.last_tool}${target}`);
|
|
118
|
-
}
|
|
119
115
|
if (s.files_held.length > 0) {
|
|
120
116
|
body.push(` holds ${s.files_held.length} file(s):`);
|
|
121
117
|
for (const f of s.files_held.slice(0, 5)) body.push(` ${f}`);
|
|
@@ -175,8 +171,7 @@ function renderPeers(p: NonNullable<ContextReport["peers"]>): string[] {
|
|
|
175
171
|
const lines = p.rows.map((peer) => {
|
|
176
172
|
const taskBit = peer.task ? ` "${truncate(peer.task, 40)}"` : "";
|
|
177
173
|
const filesBit = peer.files > 0 ? `${peer.files}f` : "0f";
|
|
178
|
-
|
|
179
|
-
return ` agent-${peer.name.padEnd(12)}${taskBit} (${peer.age_min}m old, ${filesBit}${lastBit})`;
|
|
174
|
+
return ` agent-${peer.name.padEnd(12)}${taskBit} (${peer.age_min}m old, ${filesBit})`;
|
|
180
175
|
});
|
|
181
176
|
return section("peers", lines);
|
|
182
177
|
}
|