harnery 0.36.0 → 0.38.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 +9 -0
- package/dist/commander.d.ts.map +1 -1
- package/dist/commander.js +10 -1
- package/dist/commands/admission.d.ts +21 -0
- package/dist/commands/admission.d.ts.map +1 -0
- package/dist/commands/admission.js +565 -0
- package/dist/commands/agents.d.ts +7 -0
- package/dist/commands/agents.d.ts.map +1 -1
- package/dist/commands/agents.js +148 -47
- package/dist/commands/artifacts.d.ts.map +1 -1
- package/dist/commands/artifacts.js +73 -2
- package/dist/commands/browse-ai.d.ts +2 -2
- package/dist/commands/browse-ai.d.ts.map +1 -1
- package/dist/commands/browse-ai.js +6 -4
- package/dist/commands/browse.d.ts.map +1 -1
- package/dist/commands/browse.js +360 -21
- 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/fetch.js +1 -0
- package/dist/commands/files.d.ts +12 -0
- package/dist/commands/files.d.ts.map +1 -1
- package/dist/commands/files.js +54 -1
- package/dist/commands/governor.d.ts.map +1 -1
- package/dist/commands/governor.js +4 -0
- package/dist/commands/ledger-v3.d.ts.map +1 -1
- package/dist/commands/ledger-v3.js +71 -2
- package/dist/commands/qa-record.d.ts +144 -0
- package/dist/commands/qa-record.d.ts.map +1 -0
- package/dist/commands/qa-record.js +0 -0
- package/dist/commands/qa-run.d.ts +8 -0
- package/dist/commands/qa-run.d.ts.map +1 -0
- package/dist/commands/qa-run.js +396 -0
- package/dist/commands/qa-status.d.ts +71 -0
- package/dist/commands/qa-status.d.ts.map +1 -0
- package/dist/commands/qa-status.js +490 -0
- package/dist/commands/qa-verify.d.ts +40 -0
- package/dist/commands/qa-verify.d.ts.map +1 -0
- package/dist/commands/qa-verify.js +180 -0
- 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/review-pack.d.ts +4 -0
- package/dist/commands/review-pack.d.ts.map +1 -0
- package/dist/commands/review-pack.js +1001 -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/web.d.ts.map +1 -1
- package/dist/commands/web.js +17 -0
- package/dist/commands/workflow.d.ts.map +1 -1
- package/dist/commands/workflow.js +4 -0
- package/dist/core/agents/cli.js +7 -3
- 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/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/qa-signal.d.ts +111 -0
- package/dist/core/agents/qa-signal.d.ts.map +1 -0
- package/dist/core/agents/qa-signal.js +231 -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 +5 -0
- package/dist/core/agents/render/prompt-context.d.ts.map +1 -1
- package/dist/core/agents/render/prompt-context.js +34 -13
- 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.map +1 -1
- package/dist/core/agents/rules/stop-hook.js +6 -10
- package/dist/core/agents/session-finalizer-v3.js +4 -1
- package/dist/core/agents/session-name-display.d.ts +20 -5
- package/dist/core/agents/session-name-display.d.ts.map +1 -1
- package/dist/core/agents/session-name-display.js +67 -7
- package/dist/core/agents/state/heartbeat-reader.d.ts +7 -0
- package/dist/core/agents/state/heartbeat-reader.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.d.ts +11 -0
- package/dist/core/agents/state/heartbeat-writer.d.ts.map +1 -1
- package/dist/core/agents/state/heartbeat-writer.js +17 -0
- package/dist/core/agents/state/live-coordination-view.d.ts.map +1 -1
- package/dist/core/agents/state/live-coordination-view.js +1 -0
- package/dist/core/agents/state/live-coordination-writer.js +5 -0
- package/dist/core/artifacts/constants.d.ts +1 -1
- package/dist/core/artifacts/constants.js +1 -1
- package/dist/core/artifacts/index.d.ts +82 -6
- package/dist/core/artifacts/index.d.ts.map +1 -1
- package/dist/core/artifacts/index.js +410 -15
- package/dist/core/config.d.ts +20 -0
- package/dist/core/config.d.ts.map +1 -1
- package/dist/core/config.js +59 -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 +51 -0
- package/dist/core/diagnostics/bundle.d.ts.map +1 -0
- package/dist/core/diagnostics/bundle.js +968 -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/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/index.d.ts +1 -0
- package/dist/core/events/legacy-storage/index.d.ts.map +1 -1
- package/dist/core/events/legacy-storage/index.js +1 -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/bootstrap.d.ts.map +1 -1
- package/dist/core/events/v3/bootstrap.js +10 -0
- 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 +1 -0
- package/dist/core/events/v3/coordination-view.d.ts +3 -0
- package/dist/core/events/v3/coordination-view.d.ts.map +1 -1
- package/dist/core/events/v3/coordination-view.js +69 -8
- package/dist/core/events/v3/index.d.ts +1 -0
- package/dist/core/events/v3/index.d.ts.map +1 -1
- package/dist/core/events/v3/index.js +1 -0
- package/dist/core/events/v3/live-routing.d.ts.map +1 -1
- package/dist/core/events/v3/live-routing.js +1 -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 +13 -2
- package/dist/core/events/v3/producers/intake.d.ts.map +1 -1
- package/dist/core/events/v3/producers/intake.js +10 -2
- package/dist/core/events/v3/producers/recorder.d.ts +39 -0
- package/dist/core/events/v3/producers/recorder.d.ts.map +1 -1
- package/dist/core/events/v3/producers/recorder.js +350 -17
- package/dist/core/hooks/adapter/output.d.ts +8 -0
- package/dist/core/hooks/adapter/output.d.ts.map +1 -1
- package/dist/core/hooks/adapter/output.js +11 -1
- package/dist/core/hooks/cli.js +303 -219
- 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/resolve/transcript.d.ts.map +1 -1
- package/dist/core/hooks/resolve/transcript.js +10 -3
- package/dist/core/hooks/session-name-presence.d.ts.map +1 -1
- package/dist/core/hooks/session-name-presence.js +4 -1
- package/dist/core/qa-artifacts.d.ts +20 -0
- package/dist/core/qa-artifacts.d.ts.map +1 -0
- package/dist/core/qa-artifacts.js +110 -0
- package/dist/core/resources/contract.d.ts +96 -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 +34 -0
- package/dist/core/resources/sampler.d.ts.map +1 -0
- package/dist/core/resources/sampler.js +458 -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/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/builtins.d.ts.map +1 -1
- package/dist/core/storage/builtins.js +45 -6
- package/dist/core/storage/logger.d.ts +2 -0
- package/dist/core/storage/logger.d.ts.map +1 -1
- package/dist/core/storage/logger.js +2 -0
- package/dist/core/storage/query.d.ts +14 -0
- package/dist/core/storage/query.d.ts.map +1 -1
- package/dist/core/storage/query.js +51 -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/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/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/lib/admission.d.ts +71 -0
- package/dist/lib/admission.d.ts.map +1 -0
- package/dist/lib/admission.js +264 -0
- package/dist/lib/agent-browser/client.d.ts +1 -1
- package/dist/lib/agent-browser/client.d.ts.map +1 -1
- package/dist/lib/agent-browser/client.js +1 -5
- package/dist/lib/browser/capture-fidelity.d.ts +39 -0
- package/dist/lib/browser/capture-fidelity.d.ts.map +1 -0
- package/dist/lib/browser/capture-fidelity.js +84 -0
- package/dist/lib/browser/client.d.ts +46 -1
- package/dist/lib/browser/client.d.ts.map +1 -1
- package/dist/lib/browser/client.js +168 -9
- package/dist/lib/browser/critique.d.ts +38 -1
- package/dist/lib/browser/critique.d.ts.map +1 -1
- package/dist/lib/browser/critique.js +34 -6
- package/dist/lib/browser/index.d.ts +5 -1
- package/dist/lib/browser/index.d.ts.map +1 -1
- package/dist/lib/browser/index.js +4 -0
- package/dist/lib/browser/page-review-judge.d.ts +64 -0
- package/dist/lib/browser/page-review-judge.d.ts.map +1 -0
- package/dist/lib/browser/page-review-judge.js +270 -0
- package/dist/lib/browser/page-review-pack.d.ts +613 -0
- package/dist/lib/browser/page-review-pack.d.ts.map +1 -0
- package/dist/lib/browser/page-review-pack.js +1751 -0
- package/dist/lib/browser/qa-run-contracts.d.ts +377 -0
- package/dist/lib/browser/qa-run-contracts.d.ts.map +1 -0
- package/dist/lib/browser/qa-run-contracts.js +361 -0
- package/dist/lib/browser/qa-run.d.ts +141 -0
- package/dist/lib/browser/qa-run.d.ts.map +1 -0
- package/dist/lib/browser/qa-run.js +1283 -0
- package/dist/lib/browser/request-diagnostics.d.ts +13 -0
- package/dist/lib/browser/request-diagnostics.d.ts.map +1 -0
- package/dist/lib/browser/request-diagnostics.js +18 -0
- package/dist/lib/browser/tiling.d.ts +19 -0
- package/dist/lib/browser/tiling.d.ts.map +1 -1
- package/dist/lib/browser/tiling.js +28 -0
- package/dist/lib/cookies/client.d.ts +9 -0
- package/dist/lib/cookies/client.d.ts.map +1 -1
- package/dist/lib/cookies/client.js +197 -44
- package/dist/lib/cookies/extra.d.ts +18 -0
- package/dist/lib/cookies/extra.d.ts.map +1 -0
- package/dist/lib/cookies/extra.js +14 -0
- package/dist/lib/cookies/index.d.ts +2 -1
- package/dist/lib/cookies/index.d.ts.map +1 -1
- package/dist/lib/cookies/index.js +2 -1
- 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/durable-job.d.ts +124 -0
- package/dist/lib/durable-job.d.ts.map +1 -0
- package/dist/lib/durable-job.js +296 -0
- package/dist/lib/http/client.d.ts +7 -1
- package/dist/lib/http/client.d.ts.map +1 -1
- package/dist/lib/http/client.js +2 -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 -2
- package/package.json +19 -2
- package/src/commander.ts +75 -1
- package/src/commands/admission.ts +699 -0
- package/src/commands/agents.ts +189 -50
- package/src/commands/artifacts.ts +132 -18
- package/src/commands/browse-ai.ts +10 -5
- package/src/commands/browse.ts +496 -20
- package/src/commands/diagnostics.ts +271 -0
- package/src/commands/fetch.ts +1 -0
- package/src/commands/files.ts +102 -2
- package/src/commands/governor.ts +8 -0
- package/src/commands/ledger-v3.ts +82 -0
- package/src/commands/qa-record.ts +682 -0
- package/src/commands/qa-run.ts +503 -0
- package/src/commands/qa-status.ts +608 -0
- package/src/commands/qa-verify.ts +238 -0
- package/src/commands/resources.ts +38 -0
- package/src/commands/review-pack.ts +1281 -0
- package/src/commands/supervisor.ts +141 -0
- package/src/commands/web.ts +19 -0
- package/src/commands/workflow.ts +8 -0
- package/src/core/agents/cli.ts +7 -3
- package/src/core/agents/health.ts +142 -0
- package/src/core/agents/mailbox.ts +373 -0
- package/src/core/agents/qa-signal.ts +261 -0
- package/src/core/agents/reconcile-coordination-v3.ts +77 -0
- package/src/core/agents/render/prompt-context.ts +42 -12
- 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 +6 -12
- package/src/core/agents/session-finalizer-v3.ts +4 -1
- package/src/core/agents/session-name-display.ts +78 -7
- package/src/core/agents/state/heartbeat-reader.ts +7 -0
- package/src/core/agents/state/heartbeat-writer.ts +23 -0
- package/src/core/agents/state/live-coordination-view.ts +1 -0
- package/src/core/agents/state/live-coordination-writer.ts +5 -0
- package/src/core/artifacts/constants.ts +1 -1
- package/src/core/artifacts/index.ts +565 -30
- package/src/core/config.ts +134 -2
- package/src/core/diagnostics/advice.ts +147 -0
- package/src/core/diagnostics/bundle.ts +1250 -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/compression.ts +130 -0
- package/src/core/events/legacy-storage/index.ts +1 -0
- package/src/core/events/v3/archive-retention.ts +251 -0
- package/src/core/events/v3/bootstrap.ts +10 -0
- package/src/core/events/v3/capabilities.ts +2 -0
- package/src/core/events/v3/coordination-view.ts +100 -11
- package/src/core/events/v3/index.ts +9 -0
- package/src/core/events/v3/live-routing.ts +1 -0
- package/src/core/events/v3/producers/hook-base.ts +14 -2
- package/src/core/events/v3/producers/intake.ts +10 -2
- package/src/core/events/v3/producers/recorder.ts +420 -17
- package/src/core/hooks/adapter/output.ts +12 -1
- package/src/core/hooks/cli.ts +332 -247
- package/src/core/hooks/health.ts +146 -0
- package/src/core/hooks/resolve/transcript.ts +10 -3
- package/src/core/hooks/session-name-presence.ts +6 -1
- package/src/core/qa-artifacts.ts +126 -0
- package/src/core/resources/contract.ts +105 -0
- package/src/core/resources/index.ts +5 -0
- package/src/core/resources/sampler.ts +590 -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/storage/atomic-json.ts +15 -0
- package/src/core/storage/builtins.ts +62 -6
- package/src/core/storage/logger.ts +2 -0
- package/src/core/storage/query.ts +58 -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/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/proof.ts +54 -1
- package/src/core/workflow/run-state.ts +13 -1
- package/src/core/workflow/types.ts +39 -1
- package/src/lib/admission.ts +347 -0
- package/src/lib/agent-browser/client.ts +2 -10
- package/src/lib/browser/capture-fidelity.ts +98 -0
- package/src/lib/browser/client.ts +212 -10
- package/src/lib/browser/critique.ts +62 -7
- package/src/lib/browser/index.ts +65 -0
- package/src/lib/browser/page-review-judge.ts +360 -0
- package/src/lib/browser/page-review-pack.ts +2384 -0
- package/src/lib/browser/qa-run-contracts.ts +743 -0
- package/src/lib/browser/qa-run.ts +1462 -0
- package/src/lib/browser/request-diagnostics.ts +27 -0
- package/src/lib/browser/tiling.ts +32 -0
- package/src/lib/cookies/client.ts +228 -42
- package/src/lib/cookies/extra.ts +28 -0
- package/src/lib/cookies/index.ts +2 -0
- package/src/lib/coord-root-id.ts +23 -0
- package/src/lib/durable-job.ts +407 -0
- package/src/lib/http/client.ts +13 -1
- package/src/lib/instructions/apply.ts +81 -2
- package/src/lib/instructions/templates.ts +11 -2
|
@@ -17,7 +17,7 @@
|
|
|
17
17
|
// false pass. That keeps this portable — the tiling, prompt, and
|
|
18
18
|
// orchestration live here; the model call lives in the host.
|
|
19
19
|
import { PNG } from "pngjs";
|
|
20
|
-
import { bandOversizedRect, snappedBandRects } from "./tiling.js";
|
|
20
|
+
import { bandOversizedRect, bandsCoveringRects, snappedBandRects, } from "./tiling.js";
|
|
21
21
|
export const DEFAULT_CRITIQUE_RUBRIC = [
|
|
22
22
|
"You are reviewing one vertical slice of a rendered web page for visual defects.",
|
|
23
23
|
"Report ONLY concrete, visible problems a careful designer would flag:",
|
|
@@ -71,6 +71,15 @@ export function bandRects(pageHeight, pageWidth, bandHeight, overlap) {
|
|
|
71
71
|
* the provider would downscale. Atom coordinates must be in the same pixel
|
|
72
72
|
* space as the screenshot (identical at deviceScaleFactor 1; scale them if
|
|
73
73
|
* the capture DPR differs).
|
|
74
|
+
*
|
|
75
|
+
* `hitRects` (document-space rectangles a deterministic gate already flagged)
|
|
76
|
+
* add bands past the `maxTiles` cap: every full-page band that intersects a
|
|
77
|
+
* hit rect and was dropped by the cap is cut as well, labelled `hit band N`
|
|
78
|
+
* (N is the band's 1-based position in the full band list, and the tile's
|
|
79
|
+
* `index` is that position minus one), and appended after the kept bands.
|
|
80
|
+
* `coverage` stays honest about the kept prefix; `hitBands` counts the
|
|
81
|
+
* extras. Ignored for selector tiling (`elementRects`), which has no cap to
|
|
82
|
+
* look past in that sense.
|
|
74
83
|
*/
|
|
75
84
|
export function tilesFromFullPage(fullPageBuffer, opts) {
|
|
76
85
|
const png = PNG.sync.read(fullPageBuffer);
|
|
@@ -105,8 +114,7 @@ export function tilesFromFullPage(fullPageBuffer, opts) {
|
|
|
105
114
|
height: b.height,
|
|
106
115
|
}));
|
|
107
116
|
}
|
|
108
|
-
const
|
|
109
|
-
for (const rect of rects.slice(0, opts.maxTiles)) {
|
|
117
|
+
const cutTile = (rect) => {
|
|
110
118
|
const sx = Math.max(0, Math.min(Math.round(rect.x), png.width - 1));
|
|
111
119
|
const sy = Math.max(0, Math.min(Math.round(rect.y), png.height - 1));
|
|
112
120
|
const w = Math.max(1, Math.min(Math.round(rect.width), png.width - sx));
|
|
@@ -119,7 +127,7 @@ export function tilesFromFullPage(fullPageBuffer, opts) {
|
|
|
119
127
|
const dstStart = row * w * 4;
|
|
120
128
|
png.data.copy(dst.data, dstStart, srcStart, srcStart + w * 4);
|
|
121
129
|
}
|
|
122
|
-
|
|
130
|
+
return {
|
|
123
131
|
index: rect.index,
|
|
124
132
|
label: rect.label,
|
|
125
133
|
scrollY: sy,
|
|
@@ -127,9 +135,29 @@ export function tilesFromFullPage(fullPageBuffer, opts) {
|
|
|
127
135
|
width: w,
|
|
128
136
|
height: h,
|
|
129
137
|
pngBase64: PNG.sync.write(dst).toString("base64"),
|
|
130
|
-
}
|
|
138
|
+
};
|
|
139
|
+
};
|
|
140
|
+
const kept = rects.slice(0, opts.maxTiles);
|
|
141
|
+
const tiles = kept.map(cutTile);
|
|
142
|
+
let hitBands = 0;
|
|
143
|
+
const banding = !(opts.elementRects && opts.elementRects.length > 0);
|
|
144
|
+
if (banding && opts.hitRects && opts.hitRects.length > 0) {
|
|
145
|
+
for (const index of bandsCoveringRects(rects, kept.length, opts.hitRects, opts.maxHitBands)) {
|
|
146
|
+
const band = rects[index];
|
|
147
|
+
if (!band)
|
|
148
|
+
continue;
|
|
149
|
+
tiles.push(cutTile({ ...band, label: `hit band ${index + 1}` }));
|
|
150
|
+
hitBands++;
|
|
151
|
+
}
|
|
131
152
|
}
|
|
132
|
-
|
|
153
|
+
const coverage = {
|
|
154
|
+
page_height_px: png.height,
|
|
155
|
+
reviewed_height_px: kept.reduce((max, rect) => Math.max(max, Math.min(png.height, Math.round(rect.y + rect.height))), 0),
|
|
156
|
+
bands_total: rects.length,
|
|
157
|
+
bands_reviewed: kept.length,
|
|
158
|
+
capped: rects.length > kept.length,
|
|
159
|
+
};
|
|
160
|
+
return { tiles, coverage, hitBands };
|
|
133
161
|
}
|
|
134
162
|
/**
|
|
135
163
|
* Validate + normalize a provider's raw output into CritiqueFindings. Tolerant
|
|
@@ -1,15 +1,19 @@
|
|
|
1
1
|
export { type AssertOp, type AssertResult, type AssertSpec, buildAssertCheck, parseAssertSpec, } from "./asserts.js";
|
|
2
2
|
export { Browser, type BrowserOptions, BrowserSessionActionError, type BrowserSessionControl, type BrowserSessionInspection, type BrowserSessionLocator, type BrowserSessionNavigation, type BrowserSessionNavigationType, type BrowserSessionScreenshot, type BrowserSessionStatus, type BrowserSessionTab, type ConsoleEvent, type Diagnostics, type FailedRequest, type NavigateResult, type PageErrorEvent, } from "./client.js";
|
|
3
3
|
export type { CheckRect, ContentAnnotationBox, ContentChecksRequest, ContentChecksResult, ContrastHit, ContrastResult, ImageHealthResult, ImageHit, PlaceholderHit, PlaceholderResult, TruncationHit, TruncationResult, } from "./content-checks.js";
|
|
4
|
-
export { bandRects, type CritiqueFinding, type CritiqueProvider, type CritiqueResult, type CritiqueTile, DEFAULT_CRITIQUE_RUBRIC, normalizeFindings, runCritique, tilesFromFullPage, } from "./critique.js";
|
|
4
|
+
export { bandRects, type CritiqueCoverage, type CritiqueFinding, type CritiqueProvider, type CritiqueResult, type CritiqueTile, DEFAULT_CRITIQUE_RUBRIC, normalizeFindings, runCritique, tilesFromFullPage, } from "./critique.js";
|
|
5
5
|
export { captureDevOverlay, type DevOverlayError, type DevOverlayResult, } from "./dev-overlay.js";
|
|
6
6
|
export type { AlignChild, AlignCluster, AlignResult, ClipIssue, ClipResult, CrowdPair, CrowdResult, GapCluster, GapPair, GapResult, LayoutAxis, LayoutElementMeasurement, LayoutExclusion, LayoutLintRequest, LayoutLintResult, LayoutOutcome, LayoutRect, OverlapIssue, OverlapResult, } from "./geometry.js";
|
|
7
7
|
export { buildLayoutLintCheck } from "./geometry.js";
|
|
8
8
|
export { isWSL, wslHeadedLaunchArgs } from "./launch-args.js";
|
|
9
9
|
export type { OverflowElement, OverflowResult, WidthResult, } from "./layout.js";
|
|
10
10
|
export { serializeNetscapeCookies, writeNetscapeCookieFile, } from "./netscape-cookies.js";
|
|
11
|
+
export { type JudgedContext, type JudgePageReviewPackOptions, type JudgePageReviewPackResult, judgePageReviewPack, toCritiqueRecords, } from "./page-review-judge.js";
|
|
12
|
+
export { buildInspectionPlan, type FinalizePageReviewPackInput, finalizePageReviewPack, findingsSchemaDocument, listPackContexts, PAGE_REVIEW_FINDINGS_SCHEMA, PAGE_REVIEW_PACK_DIRNAME, PAGE_REVIEW_PACK_SCHEMA, type PageReviewContextCapture, type PageReviewContextRecord, type PageReviewCritiqueRecord, type PageReviewGateRecord, type PageReviewInspectionPlan, type PageReviewPackManifest, type PageReviewTileRecord, packPaths, readPackContext, readPackDom, readPackFullPage, readPackManifest, readPackSignature, readPackTiles, renderReviewMarkdown, writePackContext, } from "./page-review-pack.js";
|
|
11
13
|
export { type BrowserProxy, type BrowserProxyGate, browserProxyFromEnv, browserProxyGateFromEnv, extractObservedIp, WEBRTC_PROXY_ONLY_ARG, } from "./proxy.js";
|
|
12
14
|
export { buildQaManifest, type ChangeClass, type ClassifyOptions, classifySignatures, fnv1a32, type ManifestOptions, type QaClassification, type QaContext, type QaManifest, type QaNodeSignature, type QaScope, type QaSignature, type QaStylesheetSignature, } from "./qa-plan.js";
|
|
15
|
+
export { defaultQaRunExec, QA_RUN_HEADLESS_ONLY_ENV, QA_RUN_RESULT_FILENAME, type QaRunExec, type QaRunExecOptions, type QaRunExecResult, type QaRunMatrixOptions, runQaMatrix, } from "./qa-run.js";
|
|
16
|
+
export { computeVerdict, contextIdFor, mergeCoverage, QA_RUN_JOB_SCHEMA_VERSION, QA_RUN_RESULT_SCHEMA_VERSION, type QaRunBlocker, type QaRunCheck, type QaRunCommandOutcome, type QaRunContext, type QaRunCritiqueOutcome, type QaRunCritiquePool, type QaRunInteraction, type QaRunJob, type QaRunJobValidation, type QaRunPolicy, type QaRunResult, type QaRunReviewPack, type QaRunVerdict, validateQaRunJob, } from "./qa-run-contracts.js";
|
|
13
17
|
export { listQaSnapshotTargets, loadQaSnapshot, QA_SNAPSHOT_DIR, type QaSnapshotStoreOptions, qaSnapshotKey, type ResolvedQaBaseline, resolveQaBaseline, type StoredQaSnapshot, saveQaSnapshot, } from "./qa-snapshot.js";
|
|
14
18
|
export type { RuntHit, RuntsResult, } from "./runts.js";
|
|
15
19
|
export { BROWSER_SESSION_MAX_FILL_BYTES, BROWSER_SESSION_MAX_FRAME_BYTES, BROWSER_SESSION_MAX_INSPECTION_TEXT_BYTES, BROWSER_SESSION_PROTOCOL_VERSION, type BrowserSessionDescriptor, BrowserSessionError, type BrowserSessionRequest, type BrowserSessionResponse, type BrowserSessionResult, type BrowserSessionServer, type BrowserSessionTarget, browserSessionTransport, readBrowserSessionDescriptor, sendBrowserSessionRequest, startBrowserSessionServer, } from "./session-control.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/index.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,8 +5,12 @@ export { captureDevOverlay, } from "./dev-overlay.js";
|
|
|
5
5
|
export { buildLayoutLintCheck } from "./geometry.js";
|
|
6
6
|
export { isWSL, wslHeadedLaunchArgs } from "./launch-args.js";
|
|
7
7
|
export { serializeNetscapeCookies, writeNetscapeCookieFile, } from "./netscape-cookies.js";
|
|
8
|
+
export { judgePageReviewPack, toCritiqueRecords, } from "./page-review-judge.js";
|
|
9
|
+
export { buildInspectionPlan, finalizePageReviewPack, findingsSchemaDocument, listPackContexts, PAGE_REVIEW_FINDINGS_SCHEMA, PAGE_REVIEW_PACK_DIRNAME, PAGE_REVIEW_PACK_SCHEMA, packPaths, readPackContext, readPackDom, readPackFullPage, readPackManifest, readPackSignature, readPackTiles, renderReviewMarkdown, writePackContext, } from "./page-review-pack.js";
|
|
8
10
|
export { browserProxyFromEnv, browserProxyGateFromEnv, extractObservedIp, WEBRTC_PROXY_ONLY_ARG, } from "./proxy.js";
|
|
9
11
|
export { buildQaManifest, classifySignatures, fnv1a32, } from "./qa-plan.js";
|
|
12
|
+
export { defaultQaRunExec, QA_RUN_HEADLESS_ONLY_ENV, QA_RUN_RESULT_FILENAME, runQaMatrix, } from "./qa-run.js";
|
|
13
|
+
export { computeVerdict, contextIdFor, mergeCoverage, QA_RUN_JOB_SCHEMA_VERSION, QA_RUN_RESULT_SCHEMA_VERSION, validateQaRunJob, } from "./qa-run-contracts.js";
|
|
10
14
|
export { listQaSnapshotTargets, loadQaSnapshot, QA_SNAPSHOT_DIR, qaSnapshotKey, resolveQaBaseline, saveQaSnapshot, } from "./qa-snapshot.js";
|
|
11
15
|
export { BROWSER_SESSION_MAX_FILL_BYTES, BROWSER_SESSION_MAX_FRAME_BYTES, BROWSER_SESSION_MAX_INSPECTION_TEXT_BYTES, BROWSER_SESSION_PROTOCOL_VERSION, BrowserSessionError, browserSessionTransport, readBrowserSessionDescriptor, sendBrowserSessionRequest, startBrowserSessionServer, } from "./session-control.js";
|
|
12
16
|
export { bandOversizedRect, cutCost, snappedBandRects, } from "./tiling.js";
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
import type { CritiqueProvider } from "./critique.js";
|
|
2
|
+
import { type PageReviewContextRecord, type PageReviewCritiqueRecord } from "./page-review-pack.js";
|
|
3
|
+
import { type CritiqueReusePlan } from "./qa-reuse.js";
|
|
4
|
+
import { type QaSnapshotStoreOptions } from "./qa-snapshot.js";
|
|
5
|
+
export interface JudgePageReviewPackOptions {
|
|
6
|
+
packDir: string;
|
|
7
|
+
/** Host-injected vision call. Absent: every context reports `skipped`. */
|
|
8
|
+
provider: CritiqueProvider | undefined;
|
|
9
|
+
rubric: string;
|
|
10
|
+
/** Vision calls in flight across the whole pack. Default: the provider's
|
|
11
|
+
* own concurrency, then 4. */
|
|
12
|
+
concurrency?: number;
|
|
13
|
+
/** Subset of context ids to judge (default: every context in the pack). */
|
|
14
|
+
contextIds?: string[];
|
|
15
|
+
/** Band-diff reuse against persisted snapshots keyed by `target`. */
|
|
16
|
+
reuse?: {
|
|
17
|
+
target: string;
|
|
18
|
+
store?: QaSnapshotStoreOptions;
|
|
19
|
+
mismatchThreshold?: number;
|
|
20
|
+
};
|
|
21
|
+
/** Absolute epoch-ms deadline. Workers stop claiming tiles once past it;
|
|
22
|
+
* a context with unjudged tiles reports `incomplete`, never `pass`. */
|
|
23
|
+
deadlineAt?: number;
|
|
24
|
+
onLog?: (message: string) => void;
|
|
25
|
+
}
|
|
26
|
+
export interface JudgedContext extends PageReviewCritiqueRecord {
|
|
27
|
+
record: PageReviewContextRecord;
|
|
28
|
+
/** Tiles selected for review that the pool never reached (deadline). */
|
|
29
|
+
tiles_unjudged: number;
|
|
30
|
+
reuse?: Pick<CritiqueReusePlan, "tiles_total" | "tiles_reused" | "tiles_reviewed" | "invalidation" | "mismatch_threshold">;
|
|
31
|
+
}
|
|
32
|
+
export interface JudgePageReviewPackResult {
|
|
33
|
+
contexts: JudgedContext[];
|
|
34
|
+
pool: {
|
|
35
|
+
concurrency: number;
|
|
36
|
+
wall_time_ms: number;
|
|
37
|
+
provider: string;
|
|
38
|
+
};
|
|
39
|
+
tiles_total: number;
|
|
40
|
+
tiles_reviewed: number;
|
|
41
|
+
tiles_reused: number;
|
|
42
|
+
outcome: "pass" | "fail" | "skipped" | "incomplete";
|
|
43
|
+
provider_meta?: Record<string, unknown>;
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Orientation the provider reads before the rubric: which band this tile is,
|
|
47
|
+
* where it sits on the page, how much of it repeats a neighbour, whether it
|
|
48
|
+
* touches the page top or bottom, and how it was captured. A tile edge that
|
|
49
|
+
* continues in the next band is not a clipped element, and a fixed header at
|
|
50
|
+
* the top of a scrolled-band capture is not a layout defect; the preamble
|
|
51
|
+
* says so where the pixels cannot. Adds context only: the finding taxonomy
|
|
52
|
+
* the rubric defines is unchanged. Empty for an unknown tile id.
|
|
53
|
+
*/
|
|
54
|
+
export declare function tileRubricPreamble(record: PageReviewContextRecord, tileId: string): string;
|
|
55
|
+
/**
|
|
56
|
+
* Judge every tile in the pack through one pool. Findings keep the tiler
|
|
57
|
+
* index (`tile`) for compatibility with `CritiqueFinding` and add the pack's
|
|
58
|
+
* stable `tile_id`. A provider throw on one tile becomes a `high`
|
|
59
|
+
* `provider-error` finding for that tile; nothing else is affected.
|
|
60
|
+
*/
|
|
61
|
+
export declare function judgePageReviewPack(options: JudgePageReviewPackOptions): Promise<JudgePageReviewPackResult>;
|
|
62
|
+
/** Strip the in-memory `record` so the result can be written into the pack. */
|
|
63
|
+
export declare function toCritiqueRecords(result: JudgePageReviewPackResult): PageReviewCritiqueRecord[];
|
|
64
|
+
//# sourceMappingURL=page-review-judge.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"page-review-judge.d.ts","sourceRoot":"","sources":["../../../src/lib/browser/page-review-judge.ts"],"names":[],"mappings":"AAYA,OAAO,KAAK,EAAmB,gBAAgB,EAAgB,MAAM,eAAe,CAAC;AACrF,OAAO,EAEL,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,EAI9B,MAAM,uBAAuB,CAAC;AAE/B,OAAO,EAAE,KAAK,iBAAiB,EAAqB,MAAM,eAAe,CAAC;AAC1E,OAAO,EAAkB,KAAK,sBAAsB,EAAE,MAAM,kBAAkB,CAAC;AAE/E,MAAM,WAAW,0BAA0B;IACzC,OAAO,EAAE,MAAM,CAAC;IAChB,0EAA0E;IAC1E,QAAQ,EAAE,gBAAgB,GAAG,SAAS,CAAC;IACvC,MAAM,EAAE,MAAM,CAAC;IACf;kCAC8B;IAC9B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,2EAA2E;IAC3E,UAAU,CAAC,EAAE,MAAM,EAAE,CAAC;IACtB,qEAAqE;IACrE,KAAK,CAAC,EAAE;QACN,MAAM,EAAE,MAAM,CAAC;QACf,KAAK,CAAC,EAAE,sBAAsB,CAAC;QAC/B,iBAAiB,CAAC,EAAE,MAAM,CAAC;KAC5B,CAAC;IACF;2EACuE;IACvE,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,KAAK,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;CACnC;AAED,MAAM,WAAW,aAAc,SAAQ,wBAAwB;IAC7D,MAAM,EAAE,uBAAuB,CAAC;IAChC,wEAAwE;IACxE,cAAc,EAAE,MAAM,CAAC;IACvB,KAAK,CAAC,EAAE,IAAI,CACV,iBAAiB,EACjB,aAAa,GAAG,cAAc,GAAG,gBAAgB,GAAG,cAAc,GAAG,oBAAoB,CAC1F,CAAC;CACH;AAED,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,aAAa,EAAE,CAAC;IAC1B,IAAI,EAAE;QAAE,WAAW,EAAE,MAAM,CAAC;QAAC,YAAY,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IACtE,WAAW,EAAE,MAAM,CAAC;IACpB,cAAc,EAAE,MAAM,CAAC;IACvB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,YAAY,CAAC;IACpD,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACzC;AAUD;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,uBAAuB,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CA2E1F;AAaD;;;;;GAKG;AACH,wBAAsB,mBAAmB,CACvC,OAAO,EAAE,0BAA0B,GAClC,OAAO,CAAC,yBAAyB,CAAC,CA4KpC;AAED,+EAA+E;AAC/E,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,yBAAyB,GAAG,wBAAwB,EAAE,CAI/F"}
|
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
// Judge a page review pack: one bounded pool of vision calls over every tile
|
|
2
|
+
// of every context, read from disk, with no browser open. This is the second
|
|
3
|
+
// half of the capture-then-judge split; `page-review-pack.ts` owns the first.
|
|
4
|
+
//
|
|
5
|
+
// Reuse: when a persisted QA snapshot exists for a context, the band-diff
|
|
6
|
+
// planner compares the pack's own full-page screenshot with the baseline and
|
|
7
|
+
// skips tiles whose pixels provably did not change and carried no baseline
|
|
8
|
+
// finding (false reviews are allowed, false passes never).
|
|
9
|
+
//
|
|
10
|
+
// Toolkit tier: this module must not import src/core (layering check).
|
|
11
|
+
import { readFileSync } from "node:fs";
|
|
12
|
+
import { listPackContexts, readPackContext, readPackFullPage, readPackTiles, } from "./page-review-pack.js";
|
|
13
|
+
import { planCritiqueReuse } from "./qa-reuse.js";
|
|
14
|
+
import { loadQaSnapshot } from "./qa-snapshot.js";
|
|
15
|
+
/**
|
|
16
|
+
* Orientation the provider reads before the rubric: which band this tile is,
|
|
17
|
+
* where it sits on the page, how much of it repeats a neighbour, whether it
|
|
18
|
+
* touches the page top or bottom, and how it was captured. A tile edge that
|
|
19
|
+
* continues in the next band is not a clipped element, and a fixed header at
|
|
20
|
+
* the top of a scrolled-band capture is not a layout defect; the preamble
|
|
21
|
+
* says so where the pixels cannot. Adds context only: the finding taxonomy
|
|
22
|
+
* the rubric defines is unchanged. Empty for an unknown tile id.
|
|
23
|
+
*/
|
|
24
|
+
export function tileRubricPreamble(record, tileId) {
|
|
25
|
+
const tile = record.tiles.find((entry) => entry.id === tileId);
|
|
26
|
+
if (!tile)
|
|
27
|
+
return "";
|
|
28
|
+
const pageHeight = record.page.height;
|
|
29
|
+
const top = tile.scrollY;
|
|
30
|
+
const bottom = tile.scrollY + tile.height;
|
|
31
|
+
const lines = [];
|
|
32
|
+
if (tile.scope !== undefined) {
|
|
33
|
+
lines.push(`Tile ${tile.id}: selector tile for ${tile.scope} (${tile.label}), ` +
|
|
34
|
+
`document y ${top}-${bottom} px of a ${pageHeight} px tall page.`);
|
|
35
|
+
}
|
|
36
|
+
else {
|
|
37
|
+
const bands = record.tiles
|
|
38
|
+
.filter((entry) => entry.scope === undefined)
|
|
39
|
+
.sort((a, b) => a.scrollY - b.scrollY || a.index - b.index);
|
|
40
|
+
const n = bands.findIndex((entry) => entry.id === tile.id);
|
|
41
|
+
const capped = record.coverage.capped
|
|
42
|
+
? ` (the page has ${record.coverage.bands_total} bands; those past the cap are not in this pack)`
|
|
43
|
+
: "";
|
|
44
|
+
lines.push(`Tile ${tile.id}: band ${n + 1} of ${bands.length}${capped}, ` +
|
|
45
|
+
`document y ${top}-${bottom} px of a ${pageHeight} px tall page.`);
|
|
46
|
+
const prev = bands[n - 1];
|
|
47
|
+
const next = bands[n + 1];
|
|
48
|
+
const overlaps = [];
|
|
49
|
+
if (prev) {
|
|
50
|
+
const above = Math.max(0, prev.scrollY + prev.height - top);
|
|
51
|
+
overlaps.push(above > 0
|
|
52
|
+
? `its top ${above} px repeat the bottom of ${prev.id}`
|
|
53
|
+
: `it starts where ${prev.id} ends, with no overlap`);
|
|
54
|
+
}
|
|
55
|
+
if (next) {
|
|
56
|
+
const below = Math.max(0, bottom - next.scrollY);
|
|
57
|
+
overlaps.push(below > 0
|
|
58
|
+
? `its bottom ${below} px repeat the top of ${next.id}`
|
|
59
|
+
: `it ends where ${next.id} starts, with no overlap`);
|
|
60
|
+
}
|
|
61
|
+
if (overlaps.length > 0) {
|
|
62
|
+
const joined = overlaps.join("; ");
|
|
63
|
+
lines.push(`${joined.charAt(0).toUpperCase()}${joined.slice(1)}.`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
const touchesTop = top <= 0;
|
|
67
|
+
const touchesBottom = bottom >= pageHeight;
|
|
68
|
+
if (touchesTop && touchesBottom) {
|
|
69
|
+
lines.push("This tile covers the whole page height.");
|
|
70
|
+
}
|
|
71
|
+
else if (touchesTop) {
|
|
72
|
+
lines.push("This tile touches the page top; content cut at its bottom edge continues in the next band.");
|
|
73
|
+
}
|
|
74
|
+
else if (touchesBottom) {
|
|
75
|
+
lines.push("This tile touches the page bottom; content cut at its top edge continues in the previous band.");
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
lines.push("This tile is interior: content cut at its top and bottom edges continues in the neighbouring bands.");
|
|
79
|
+
}
|
|
80
|
+
const source = record.capture_fidelity?.source ?? "full-page";
|
|
81
|
+
lines.push(source === "scrolled-bands"
|
|
82
|
+
? "Capture source: scrolled-bands (the viewport was scrolled to this band and clipped, because " +
|
|
83
|
+
"the full-page screenshot disagreed with the viewport render). Fixed and sticky elements " +
|
|
84
|
+
"are shown once, at their document position, as a full-page screenshot shows them; a " +
|
|
85
|
+
"fixed bar that is absent from this band is therefore not a defect."
|
|
86
|
+
: "Capture source: full-page (one full-page screenshot, cropped to this band).");
|
|
87
|
+
return lines.join(" ");
|
|
88
|
+
}
|
|
89
|
+
function providerLabel(meta, present) {
|
|
90
|
+
if (meta) {
|
|
91
|
+
for (const key of ["provider", "active_harness", "route", "model"]) {
|
|
92
|
+
const value = meta[key];
|
|
93
|
+
if (typeof value === "string" && value.length > 0)
|
|
94
|
+
return value;
|
|
95
|
+
if (Array.isArray(value) && typeof value[0] === "string")
|
|
96
|
+
return value[0];
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
return present ? "host" : "none";
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Judge every tile in the pack through one pool. Findings keep the tiler
|
|
103
|
+
* index (`tile`) for compatibility with `CritiqueFinding` and add the pack's
|
|
104
|
+
* stable `tile_id`. A provider throw on one tile becomes a `high`
|
|
105
|
+
* `provider-error` finding for that tile; nothing else is affected.
|
|
106
|
+
*/
|
|
107
|
+
export async function judgePageReviewPack(options) {
|
|
108
|
+
const { packDir, provider, rubric } = options;
|
|
109
|
+
const log = options.onLog ?? (() => { });
|
|
110
|
+
const ids = options.contextIds ?? listPackContexts(packDir);
|
|
111
|
+
const records = ids.map((id) => readPackContext(packDir, id));
|
|
112
|
+
const started = Date.now();
|
|
113
|
+
const perContext = records.map((record) => {
|
|
114
|
+
const tiles = readPackTiles(packDir, record);
|
|
115
|
+
let review = tiles;
|
|
116
|
+
let reuse;
|
|
117
|
+
// Reuse only for unscoped captures: scope tiles share tiler indices with
|
|
118
|
+
// the bands, and a mixed set would mis-associate baseline findings.
|
|
119
|
+
// Never for a scrolled-bands context: its tiles were cut from scrolled
|
|
120
|
+
// viewport captures, not from the full-page PNG the band diff compares.
|
|
121
|
+
const scrolled = record.capture_fidelity?.source === "scrolled-bands";
|
|
122
|
+
if (options.reuse && provider && scrolled) {
|
|
123
|
+
log(`judge ${record.id}: band-diff reuse skipped (tiles came from scrolled bands)`);
|
|
124
|
+
}
|
|
125
|
+
if (options.reuse && provider && record.scopes.length === 0 && !scrolled) {
|
|
126
|
+
const context = {
|
|
127
|
+
viewport: record.viewport,
|
|
128
|
+
theme: record.theme,
|
|
129
|
+
state: record.state,
|
|
130
|
+
};
|
|
131
|
+
const stored = loadQaSnapshot(options.reuse.target, context, options.reuse.store ?? {});
|
|
132
|
+
if (stored?.screenshotPath && stored.critique) {
|
|
133
|
+
reuse = planCritiqueReuse({
|
|
134
|
+
baselineScreenshot: readFileSync(stored.screenshotPath),
|
|
135
|
+
baselineCritique: stored.critique,
|
|
136
|
+
currentScreenshot: readPackFullPage(packDir, record),
|
|
137
|
+
tiles,
|
|
138
|
+
rubric,
|
|
139
|
+
...(options.reuse.mismatchThreshold !== undefined
|
|
140
|
+
? { mismatchThreshold: options.reuse.mismatchThreshold }
|
|
141
|
+
: {}),
|
|
142
|
+
});
|
|
143
|
+
const keep = new Set(reuse.review.map((tile) => tile.index));
|
|
144
|
+
// planCritiqueReuse returns CritiqueTile objects; re-attach ids by
|
|
145
|
+
// tiler index so the pool cites the pack's stable tile ids.
|
|
146
|
+
review = tiles.filter((tile) => keep.has(tile.index));
|
|
147
|
+
log(`judge ${record.id}: ${reuse.tiles_reused}/${reuse.tiles_total} tiles reused (band-diff)` +
|
|
148
|
+
(reuse.invalidation ? ` — ${reuse.invalidation}` : ""));
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
return { record, tiles, review, ...(reuse ? { reuse } : {}), findings: [], judged: new Set() };
|
|
152
|
+
});
|
|
153
|
+
const work = [];
|
|
154
|
+
perContext.forEach((entry, contextIndex) => {
|
|
155
|
+
for (const tile of entry.review) {
|
|
156
|
+
const preamble = tileRubricPreamble(entry.record, tile.id);
|
|
157
|
+
work.push({
|
|
158
|
+
contextIndex,
|
|
159
|
+
tile,
|
|
160
|
+
url: entry.record.url,
|
|
161
|
+
rubric: preamble ? `${preamble}\n\n${rubric}` : rubric,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
});
|
|
165
|
+
let meta;
|
|
166
|
+
let concurrency = 0;
|
|
167
|
+
if (provider && work.length > 0) {
|
|
168
|
+
concurrency = Math.max(1, Math.min(options.concurrency ?? provider.concurrency ?? 4, work.length));
|
|
169
|
+
log(`judge: ${work.length} tile(s) across ${records.length} context(s), pool ${concurrency}`);
|
|
170
|
+
let cursor = 0;
|
|
171
|
+
const worker = async () => {
|
|
172
|
+
while (true) {
|
|
173
|
+
if (options.deadlineAt !== undefined && Date.now() >= options.deadlineAt)
|
|
174
|
+
return;
|
|
175
|
+
const i = cursor++;
|
|
176
|
+
if (i >= work.length)
|
|
177
|
+
return;
|
|
178
|
+
const item = work[i];
|
|
179
|
+
const entry = perContext[item.contextIndex];
|
|
180
|
+
if (!entry)
|
|
181
|
+
continue;
|
|
182
|
+
entry.judged.add(item.tile.id);
|
|
183
|
+
try {
|
|
184
|
+
const found = await provider({ url: item.url, rubric: item.rubric, tile: item.tile });
|
|
185
|
+
for (const finding of found) {
|
|
186
|
+
entry.findings.push({ ...finding, tile: item.tile.index, tile_id: item.tile.id });
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
catch (err) {
|
|
190
|
+
entry.findings.push({
|
|
191
|
+
tile: item.tile.index,
|
|
192
|
+
tile_id: item.tile.id,
|
|
193
|
+
severity: "high",
|
|
194
|
+
category: "provider-error",
|
|
195
|
+
description: `critique provider failed on ${item.tile.label}: ${err instanceof Error ? err.message : String(err)}`,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
};
|
|
200
|
+
await Promise.all(Array.from({ length: concurrency }, () => worker()));
|
|
201
|
+
meta = provider.meta?.();
|
|
202
|
+
}
|
|
203
|
+
else if (provider) {
|
|
204
|
+
meta = provider.meta?.();
|
|
205
|
+
}
|
|
206
|
+
const label = providerLabel(meta, Boolean(provider));
|
|
207
|
+
const contexts = perContext.map((entry) => {
|
|
208
|
+
// Deterministic order: by tile id, then insertion.
|
|
209
|
+
const findings = [...entry.findings].sort((a, b) => a.tile_id.localeCompare(b.tile_id));
|
|
210
|
+
const unjudged = entry.review.filter((tile) => !entry.judged.has(tile.id)).length;
|
|
211
|
+
const outcome = !provider
|
|
212
|
+
? "skipped"
|
|
213
|
+
: findings.some((f) => f.severity === "high")
|
|
214
|
+
? "fail"
|
|
215
|
+
: unjudged > 0
|
|
216
|
+
? "incomplete"
|
|
217
|
+
: "pass";
|
|
218
|
+
return {
|
|
219
|
+
context_id: entry.record.id,
|
|
220
|
+
provider: provider ? label : "none",
|
|
221
|
+
tiles_total: entry.tiles.length,
|
|
222
|
+
tiles_reviewed: entry.review.length - unjudged,
|
|
223
|
+
tiles_unjudged: unjudged,
|
|
224
|
+
tiles_reused: entry.reuse?.tiles_reused ?? 0,
|
|
225
|
+
outcome,
|
|
226
|
+
findings,
|
|
227
|
+
coverage: entry.record.coverage,
|
|
228
|
+
...(provider
|
|
229
|
+
? {}
|
|
230
|
+
: {
|
|
231
|
+
error: "no critiqueProvider injected by the host (see HarneryProgramContext.critiqueProvider)",
|
|
232
|
+
}),
|
|
233
|
+
record: entry.record,
|
|
234
|
+
...(entry.reuse
|
|
235
|
+
? {
|
|
236
|
+
reuse: {
|
|
237
|
+
tiles_total: entry.reuse.tiles_total,
|
|
238
|
+
tiles_reused: entry.reuse.tiles_reused,
|
|
239
|
+
tiles_reviewed: entry.reuse.tiles_reviewed,
|
|
240
|
+
mismatch_threshold: entry.reuse.mismatch_threshold,
|
|
241
|
+
...(entry.reuse.invalidation ? { invalidation: entry.reuse.invalidation } : {}),
|
|
242
|
+
},
|
|
243
|
+
}
|
|
244
|
+
: {}),
|
|
245
|
+
};
|
|
246
|
+
});
|
|
247
|
+
const tilesTotal = contexts.reduce((sum, c) => sum + c.tiles_total, 0);
|
|
248
|
+
const tilesReviewed = contexts.reduce((sum, c) => sum + c.tiles_reviewed, 0);
|
|
249
|
+
const tilesReused = contexts.reduce((sum, c) => sum + c.tiles_reused, 0);
|
|
250
|
+
const outcome = !provider
|
|
251
|
+
? "skipped"
|
|
252
|
+
: contexts.some((c) => c.outcome === "fail")
|
|
253
|
+
? "fail"
|
|
254
|
+
: contexts.some((c) => c.outcome === "incomplete")
|
|
255
|
+
? "incomplete"
|
|
256
|
+
: "pass";
|
|
257
|
+
return {
|
|
258
|
+
contexts,
|
|
259
|
+
pool: { concurrency, wall_time_ms: Date.now() - started, provider: label },
|
|
260
|
+
tiles_total: tilesTotal,
|
|
261
|
+
tiles_reviewed: tilesReviewed,
|
|
262
|
+
tiles_reused: tilesReused,
|
|
263
|
+
outcome,
|
|
264
|
+
...(meta ? { provider_meta: meta } : {}),
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/** Strip the in-memory `record` so the result can be written into the pack. */
|
|
268
|
+
export function toCritiqueRecords(result) {
|
|
269
|
+
return result.contexts.map(({ record: _record, reuse: _reuse, tiles_unjudged: _unjudged, ...rest }) => rest);
|
|
270
|
+
}
|