@reticlehq/server 3.5.0 → 3.7.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 +1 -1
- package/SKILL.md +123 -116
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-suite.d.ts +14 -0
- package/dist/command/cli/adhoc-suite.js +42 -7
- package/dist/command/cli/adhoc-verdict.d.ts +19 -2
- package/dist/command/cli/adhoc-verdict.js +76 -9
- package/dist/command/cli/answers/gate-exit.d.ts +23 -0
- package/dist/command/cli/answers/gate-exit.js +45 -0
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +3 -1
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/auth/device-flow.d.ts +13 -2
- package/dist/command/cli/auth/device-flow.js +17 -0
- package/dist/command/cli/cli-doctor.js +14 -0
- package/dist/command/cli/cli-flow-commands.d.ts +0 -11
- package/dist/command/cli/cli-flow-commands.js +31 -112
- package/dist/command/cli/cli-kill.js +3 -2
- package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
- package/dist/command/cli/cli-parse-grammar.js +75 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -0
- package/dist/command/cli/cli-parse-verify.js +18 -0
- package/dist/command/cli/cli-parse.d.ts +19 -28
- package/dist/command/cli/cli-parse.js +82 -182
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +61 -9
- package/dist/command/cli/cli-usage.d.ts +33 -0
- package/dist/command/cli/cli-usage.js +287 -0
- package/dist/command/cli/cli-verify.d.ts +35 -5
- package/dist/command/cli/cli-verify.js +114 -35
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +192 -341
- package/dist/command/cli/cloud-kit.d.ts +12 -0
- package/dist/command/cli/cloud-kit.js +41 -2
- package/dist/command/cli/cloud-link.d.ts +57 -0
- package/dist/command/cli/cloud-link.js +308 -0
- package/dist/command/cli/cloud-login.d.ts +22 -0
- package/dist/command/cli/cloud-login.js +96 -8
- package/dist/command/cli/context-command.d.ts +1 -0
- package/dist/command/cli/context-command.js +33 -0
- package/dist/command/cli/daemon-start-options.d.ts +3 -0
- package/dist/command/cli/daemon-start-options.js +24 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
- package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
- package/dist/command/cli/doctor/doctor-project-line.js +5 -4
- package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
- package/dist/command/cli/doctor/doctor-rows.js +6 -0
- package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
- package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/known-regression.d.ts +13 -0
- package/dist/command/cli/known-regression.js +34 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
- package/dist/command/cli/launch/sdk-version-match.js +25 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
- package/dist/command/cli/mcp-command.d.ts +6 -0
- package/dist/command/cli/mcp-command.js +13 -5
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +25 -1
- package/dist/command/cli/project-name.d.ts +29 -1
- package/dist/command/cli/project-name.js +107 -2
- package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
- package/dist/command/cli/setup-mcp-cli.js +35 -12
- package/dist/command/cli/status/status-lines.d.ts +1 -0
- package/dist/command/cli/status/status-lines.js +47 -2
- package/dist/command/cli/status/workspace-links.d.ts +10 -0
- package/dist/command/cli/status/workspace-links.js +29 -0
- package/dist/command/cli/try-command.d.ts +96 -0
- package/dist/command/cli/try-command.js +362 -0
- package/dist/command/cli/tutorial.d.ts +0 -100
- package/dist/command/cli/tutorial.js +0 -181
- package/dist/command/cli/verify-results.d.ts +19 -0
- package/dist/command/cli/verify-results.js +29 -0
- package/dist/command/cli-onboarding.d.ts +0 -11
- package/dist/command/cli-onboarding.js +0 -15
- package/dist/command/cli.d.ts +20 -0
- package/dist/command/cli.js +130 -104
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +23 -1
- package/dist/command/daemon/daemon-resolve.js +79 -9
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
- package/dist/command/setup/bringup/bridge-port.js +13 -3
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
- package/dist/command/setup/bringup/dev-server-wait.js +19 -0
- package/dist/command/setup/bringup/ensure-daemon.js +9 -2
- package/dist/command/setup/init/agent-restart.d.ts +23 -0
- package/dist/command/setup/init/agent-restart.js +28 -0
- package/dist/command/setup/init/init-port.d.ts +14 -1
- package/dist/command/setup/init/init-port.js +32 -2
- package/dist/command/setup/init/init-runtime.d.ts +22 -2
- package/dist/command/setup/init/init-runtime.js +114 -38
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +38 -9
- package/dist/command/setup/probe/existing-app.d.ts +12 -0
- package/dist/command/setup/probe/existing-app.js +14 -0
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +34 -9
- package/dist/command/setup/run-setup.js +65 -51
- package/dist/command/setup/setup-command.d.ts +25 -1
- package/dist/command/setup/setup-command.js +59 -4
- package/dist/command/setup/setup-mcp.js +25 -2
- package/dist/command/setup/tauri-signing.d.ts +19 -0
- package/dist/command/setup/tauri-signing.js +79 -0
- package/dist/command/setup/terminal/listeners.d.ts +10 -1
- package/dist/command/setup/terminal/listeners.js +37 -6
- package/dist/command/update/update-nudge.d.ts +9 -0
- package/dist/command/update/update-nudge.js +1 -1
- package/dist/command/update/updater.js +11 -15
- package/dist/command/version/version-nudge.js +3 -0
- package/dist/command/version/version-skew.d.ts +20 -1
- package/dist/command/version/version-skew.js +49 -4
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +23 -2
- package/dist/features/exhaust/ledger.d.ts +21 -14
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +61 -1
- package/dist/features/harness/drive-report.js +394 -26
- package/dist/features/harness/drive-runs.d.ts +120 -0
- package/dist/features/harness/drive-runs.js +289 -0
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/explore/console-pages.d.ts +15 -0
- package/dist/features/harness/explore/console-pages.js +146 -0
- package/dist/features/harness/explore/disparity.d.ts +19 -0
- package/dist/features/harness/explore/disparity.js +71 -0
- package/dist/features/harness/explore/fake-app.d.ts +16 -0
- package/dist/features/harness/explore/fake-app.js +49 -0
- package/dist/features/harness/explore/goal-search.d.ts +26 -0
- package/dist/features/harness/explore/goal-search.js +144 -0
- package/dist/features/harness/explore/page-tree.d.ts +49 -0
- package/dist/features/harness/explore/page-tree.js +148 -0
- package/dist/features/harness/explore/site-map.d.ts +34 -0
- package/dist/features/harness/explore/site-map.js +150 -0
- package/dist/features/harness/fill-values.d.ts +3 -73
- package/dist/features/harness/fill-values.js +3 -169
- package/dist/features/harness/goals.d.ts +82 -0
- package/dist/features/harness/goals.js +330 -0
- package/dist/features/harness/harness.d.ts +51 -1
- package/dist/features/harness/harness.js +207 -6
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +127 -0
- package/dist/features/harness/platform/local-apps.js +280 -0
- package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
- package/dist/features/harness/platform/persona-credentials.js +69 -0
- package/dist/features/harness/platform/platform-drives.d.ts +61 -0
- package/dist/features/harness/platform/platform-drives.js +114 -0
- package/dist/features/harness/platform/refusal.d.ts +52 -0
- package/dist/features/harness/platform/refusal.js +71 -0
- package/dist/features/harness/platform/remote-drive.d.ts +186 -0
- package/dist/features/harness/platform/remote-drive.js +378 -0
- package/dist/features/harness/platform/script.d.ts +94 -0
- package/dist/features/harness/platform/script.js +260 -0
- package/dist/features/harness/platform/server-driver.d.ts +54 -0
- package/dist/features/harness/platform/server-driver.js +182 -0
- package/dist/features/harness/platform-config.d.ts +41 -1
- package/dist/features/harness/platform-config.js +106 -9
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +70 -0
- package/dist/features/harness/script/script-run.js +606 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/step-shots.d.ts +31 -0
- package/dist/features/visual/step-shots.js +231 -0
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +62 -17
- package/dist/hooks/client-directory.d.ts +18 -0
- package/dist/hooks/client-directory.js +57 -0
- package/dist/hooks/coding-agents.d.ts +34 -0
- package/dist/hooks/coding-agents.js +117 -0
- package/dist/hooks/driven-by.d.ts +23 -0
- package/dist/hooks/driven-by.js +56 -0
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -243
- package/dist/judgement/capsule/capsule-store.d.ts +2 -2
- package/dist/judgement/capsule/causal-summary.d.ts +15 -1
- package/dist/judgement/capsule/causal-summary.js +33 -0
- package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
- package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
- package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
- package/dist/judgement/runs/artifact/gap-summary.js +12 -3
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
- package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
- package/dist/judgement/runs/artifact/run-store.js +195 -3
- package/dist/judgement/runs/context-tools.js +59 -1
- package/dist/judgement/runs/default-run-id.d.ts +3 -0
- package/dist/judgement/runs/default-run-id.js +16 -0
- package/dist/judgement/runs/drive-run.d.ts +71 -1
- package/dist/judgement/runs/drive-run.js +317 -5
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +13 -3
- package/dist/judgement/runs/runner-port.d.ts +5 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +5 -2
- package/dist/judgement/runs/verification-sync.js +40 -18
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +36 -1
- package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
- package/dist/language/flows/fields/flow-secret-field.js +25 -2
- package/dist/language/flows/flow-anchor.d.ts +61 -10
- package/dist/language/flows/flow-anchor.js +98 -6
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-intent.d.ts +1 -0
- package/dist/language/flows/flow-journey.d.ts +6 -0
- package/dist/language/flows/flow-journey.js +20 -0
- package/dist/language/flows/flow-learning.d.ts +4 -0
- package/dist/language/flows/flow-learning.js +45 -14
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +115 -110
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +40 -1
- package/dist/language/flows/flow-replay.js +110 -22
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +22 -2
- package/dist/language/flows/flow-step-runners.js +247 -47
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +7 -3
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +112 -89
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +74 -12
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
- package/dist/language/flows/recording/tape/recordings.js +95 -13
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +56 -15
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +202 -191
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +22 -1
- package/dist/memory/cloud/cloud-config.js +34 -5
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +15 -4
- package/dist/memory/cloud/harness-config.d.ts +75 -1
- package/dist/memory/cloud/harness-config.js +115 -24
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +161 -0
- package/dist/memory/cloud/memory-scope.js +227 -0
- package/dist/memory/cloud/sync-cycle.d.ts +44 -7
- package/dist/memory/cloud/sync-cycle.js +129 -15
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +121 -9
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +31 -10
- package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
- package/dist/memory/cloud/sync-screenshots.js +105 -0
- package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
- package/dist/memory/cloud/unsynced-roots.js +166 -0
- package/dist/memory/impact/account-watch.d.ts +34 -0
- package/dist/memory/impact/account-watch.js +59 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +17 -4
- package/dist/memory/impact/impact-store.js +169 -63
- package/dist/memory/intent/inline-intent.d.ts +1 -0
- package/dist/memory/intent/intent-shard-store.js +16 -4
- package/dist/memory/intent/intent-shard.d.ts +14 -2
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +122 -4
- package/dist/memory/intent/open-intents.d.ts +6 -0
- package/dist/memory/intent/open-intents.js +10 -1
- package/dist/memory/intent/settled-words.d.ts +24 -0
- package/dist/memory/intent/settled-words.js +130 -0
- package/dist/memory/journal/drive-flow.d.ts +16 -0
- package/dist/memory/journal/drive-flow.js +34 -2
- package/dist/memory/journal/drive-run-flush.d.ts +2 -0
- package/dist/memory/journal/drive-run-flush.js +20 -5
- package/dist/memory/journal/envelope.d.ts +8 -8
- package/dist/memory/journal/journal-recorder.js +52 -3
- package/dist/memory/journal/on-disk/retention.d.ts +8 -0
- package/dist/memory/journal/on-disk/retention.js +32 -2
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +42 -9
- package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
- package/dist/memory/project/artifact-root-resolver.js +125 -16
- package/dist/memory/project/artifact-root.d.ts +46 -8
- package/dist/memory/project/artifact-root.js +89 -10
- package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
- package/dist/memory/project/dir/reticle-dir.js +26 -3
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/root-claims.d.ts +6 -0
- package/dist/memory/project/root-claims.js +39 -0
- package/dist/memory/project/session-root.d.ts +26 -1
- package/dist/memory/project/session-root.js +49 -5
- package/dist/memory/project/sync-status.d.ts +85 -0
- package/dist/memory/project/sync-status.js +224 -0
- package/dist/memory/recall/memory-tools.js +47 -2
- package/dist/memory/recall/platform-memory.d.ts +34 -0
- package/dist/memory/recall/platform-memory.js +139 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +80 -13
- package/dist/portal/bridge/bridge.d.ts +9 -3
- package/dist/portal/bridge/bridge.js +82 -22
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -0
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/bridge/wrong-path.d.ts +17 -0
- package/dist/portal/bridge/wrong-path.js +35 -0
- package/dist/portal/input/network-mock-tools.js +11 -2
- package/dist/portal/input/real-input.d.ts +83 -10
- package/dist/portal/input/real-input.js +218 -30
- package/dist/portal/input/viewport-tools.js +3 -3
- package/dist/portal/pool/browser-pool.d.ts +70 -9
- package/dist/portal/pool/browser-pool.js +190 -37
- package/dist/portal/pool/context-permissions.d.ts +33 -0
- package/dist/portal/pool/context-permissions.js +33 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
- package/dist/portal/pool/lease-marker-stamp.js +49 -0
- package/dist/portal/pool/playwright-launcher.d.ts +35 -0
- package/dist/portal/pool/playwright-launcher.js +64 -3
- package/dist/portal/pool/pool-contract.d.ts +28 -5
- package/dist/portal/session/agent-link.d.ts +8 -0
- package/dist/portal/session/agent-link.js +17 -0
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +24 -0
- package/dist/portal/session/daemon-answers.d.ts +3 -3
- package/dist/portal/session/daemon-answers.js +4 -2
- package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
- package/dist/portal/session/dev-server/dev-command.js +87 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/observed-state.d.ts +16 -18
- package/dist/portal/session/facts/observed-state.js +46 -3
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +107 -13
- package/dist/portal/session/narration-args.d.ts +5 -0
- package/dist/portal/session/narration-args.js +17 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
- package/dist/portal/session/no-session-diagnosis.js +46 -9
- package/dist/portal/session/no-session-next-action.d.ts +31 -0
- package/dist/portal/session/no-session-next-action.js +159 -60
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +227 -17
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +18 -0
- package/dist/portal/session/session-health.js +9 -1
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +8 -1
- package/dist/portal/session/session-manager.d.ts +39 -0
- package/dist/portal/session/session-manager.js +98 -11
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +13 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +22 -30
- package/dist/portal/session/session.js +81 -79
- package/dist/portal/session/timing/command-timeout.js +25 -1
- package/dist/portal/session/timing/wall-clock.d.ts +1 -1
- package/dist/portal/session/timing/wall-clock.js +1 -1
- package/dist/portal/session/zero-install-first-call.d.ts +31 -0
- package/dist/portal/session/zero-install-first-call.js +88 -0
- package/dist/start-options.d.ts +12 -0
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +23 -1
- package/dist/status-payload.js +36 -1
- package/dist/surface/http-server.js +18 -2
- package/dist/surface/mcp/attach-memory.d.ts +1 -0
- package/dist/surface/mcp/attach-memory.js +12 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
- package/dist/surface/mcp/mcp-proxy.js +65 -13
- package/dist/surface/mcp/mcp.d.ts +34 -6
- package/dist/surface/mcp/mcp.js +61 -17
- package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
- package/dist/surface/mcp/proxy/drive-calls.js +27 -0
- package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +32 -14
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +1 -0
- package/dist/surface/tools/account-tool.d.ts +22 -0
- package/dist/surface/tools/account-tool.js +157 -0
- package/dist/surface/tools/act/act-danger.d.ts +11 -0
- package/dist/surface/tools/act/act-danger.js +38 -1
- package/dist/surface/tools/act/act-observation.d.ts +33 -0
- package/dist/surface/tools/act/act-observation.js +57 -0
- package/dist/surface/tools/act/act-preflight.js +25 -2
- package/dist/surface/tools/act/act-target.js +8 -3
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/resolve-target.d.ts +1 -1
- package/dist/surface/tools/act/resolve-target.js +18 -3
- package/dist/surface/tools/act/screen-request.d.ts +34 -0
- package/dist/surface/tools/act/screen-request.js +113 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +138 -29
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +71 -41
- package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
- package/dist/surface/tools/agent/app-notes-learning.js +80 -0
- package/dist/surface/tools/agent/app-notes.d.ts +4 -0
- package/dist/surface/tools/agent/app-notes.js +48 -0
- package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
- package/dist/surface/tools/agent/build-staleness.js +62 -0
- package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
- package/dist/surface/tools/agent/compact-envelope.js +374 -0
- package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
- package/dist/surface/tools/agent/for-the-agent.js +44 -0
- package/dist/surface/tools/agent/notices.d.ts +50 -0
- package/dist/surface/tools/agent/notices.js +152 -0
- package/dist/surface/tools/agent/reteach.d.ts +11 -0
- package/dist/surface/tools/agent/reteach.js +50 -0
- package/dist/surface/tools/args/alias-args.d.ts +5 -0
- package/dist/surface/tools/args/alias-args.js +10 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
- package/dist/surface/tools/assert/assert-source.d.ts +15 -0
- package/dist/surface/tools/assert/assert-source.js +40 -0
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +42 -17
- package/dist/surface/tools/browser-tools.js +51 -2
- package/dist/surface/tools/chat-drives.d.ts +101 -0
- package/dist/surface/tools/chat-drives.js +409 -0
- package/dist/surface/tools/coverage-tools.d.ts +2 -10
- package/dist/surface/tools/coverage-tools.js +2 -53
- package/dist/surface/tools/dynamic-tools.js +29 -1
- package/dist/surface/tools/empty-session-list.d.ts +51 -0
- package/dist/surface/tools/empty-session-list.js +120 -0
- package/dist/surface/tools/error-recovery.d.ts +14 -0
- package/dist/surface/tools/error-recovery.js +105 -8
- package/dist/surface/tools/explore-tools.d.ts +31 -1
- package/dist/surface/tools/explore-tools.js +438 -66
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +18 -3
- package/dist/surface/tools/gap-novelty.d.ts +3 -1
- package/dist/surface/tools/gap-novelty.js +8 -1
- package/dist/surface/tools/harness-explore.d.ts +118 -57
- package/dist/surface/tools/harness-explore.js +344 -292
- package/dist/surface/tools/harness-gate.d.ts +88 -0
- package/dist/surface/tools/harness-gate.js +235 -0
- package/dist/surface/tools/harness-hunt.d.ts +43 -0
- package/dist/surface/tools/harness-hunt.js +215 -0
- package/dist/surface/tools/harness-plan.d.ts +17 -0
- package/dist/surface/tools/harness-plan.js +38 -0
- package/dist/surface/tools/harness-script.d.ts +30 -0
- package/dist/surface/tools/harness-script.js +560 -0
- package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
- package/dist/surface/tools/harness-tab-guard.js +27 -0
- package/dist/surface/tools/harness-toolset.d.ts +22 -1
- package/dist/surface/tools/harness-toolset.js +101 -7
- package/dist/surface/tools/human-notes.d.ts +16 -0
- package/dist/surface/tools/human-notes.js +27 -0
- package/dist/surface/tools/invoke-tool.d.ts +5 -2
- package/dist/surface/tools/invoke-tool.js +263 -85
- package/dist/surface/tools/lease-hint.js +26 -5
- package/dist/surface/tools/lease-permissions.d.ts +33 -0
- package/dist/surface/tools/lease-permissions.js +73 -0
- package/dist/surface/tools/lease-readiness.d.ts +38 -0
- package/dist/surface/tools/lease-readiness.js +57 -0
- package/dist/surface/tools/lease-seed.d.ts +49 -0
- package/dist/surface/tools/lease-seed.js +167 -0
- package/dist/surface/tools/lease-tools.d.ts +13 -24
- package/dist/surface/tools/lease-tools.js +146 -197
- package/dist/surface/tools/live-call-text.js +4 -4
- package/dist/surface/tools/merge-tools.js +42 -2
- package/dist/surface/tools/merged-name-redirect.js +4 -0
- package/dist/surface/tools/next-step.d.ts +29 -0
- package/dist/surface/tools/next-step.js +214 -0
- package/dist/surface/tools/observe-tools.js +45 -9
- package/dist/surface/tools/platform-moment.d.ts +72 -0
- package/dist/surface/tools/platform-moment.js +296 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +71 -14
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/reticle-result.d.ts +120 -0
- package/dist/surface/tools/reticle-result.js +364 -0
- package/dist/surface/tools/tool-kit.d.ts +83 -3
- package/dist/surface/tools/tool-kit.js +77 -7
- package/dist/surface/tools/tools.js +43 -59
- package/dist/telemetry/account-envelope.d.ts +7 -0
- package/dist/telemetry/account-envelope.js +61 -0
- package/dist/telemetry/agent-client.d.ts +15 -0
- package/dist/telemetry/agent-client.js +57 -0
- package/dist/telemetry/app-instrumented.js +9 -2
- package/dist/telemetry/argument-shape.d.ts +7 -0
- package/dist/telemetry/argument-shape.js +86 -1
- package/dist/telemetry/automation-hint.d.ts +2 -3
- package/dist/telemetry/automation-hint.js +33 -8
- package/dist/telemetry/cli-telemetry.js +7 -2
- package/dist/telemetry/daemon-telemetry.js +3 -0
- package/dist/telemetry/error-fingerprint.d.ts +10 -1
- package/dist/telemetry/error-fingerprint.js +61 -5
- package/dist/telemetry/feedback-cli.d.ts +0 -13
- package/dist/telemetry/feedback-cli.js +0 -77
- package/dist/telemetry/feedback.d.ts +13 -0
- package/dist/telemetry/feedback.js +183 -17
- package/dist/telemetry/harness-run.d.ts +18 -0
- package/dist/telemetry/harness-run.js +80 -0
- package/dist/telemetry/hud-events.d.ts +16 -0
- package/dist/telemetry/hud-events.js +27 -0
- package/dist/telemetry/hud-metrics.d.ts +29 -6
- package/dist/telemetry/hud-metrics.js +116 -25
- package/dist/telemetry/init-telemetry.js +2 -2
- package/dist/telemetry/install-source.d.ts +13 -25
- package/dist/telemetry/install-source.js +44 -3
- package/dist/telemetry/mcp-connection.d.ts +0 -14
- package/dist/telemetry/mcp-connection.js +5 -1
- package/dist/telemetry/onboarding-firsts.d.ts +32 -0
- package/dist/telemetry/onboarding-firsts.js +81 -6
- package/dist/telemetry/platform-linked.d.ts +5 -0
- package/dist/telemetry/platform-linked.js +32 -0
- package/dist/telemetry/project-profile.js +5 -3
- package/dist/telemetry/proxy-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +15 -4
- package/dist/telemetry/session-metrics.js +88 -52
- package/dist/telemetry/telemetry.d.ts +38 -2
- package/dist/telemetry/telemetry.js +144 -34
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +13 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +20 -6
- package/docs/README.md +3 -3
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +25 -28
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +33 -28
- package/docs/benchmarks.md +5 -5
- package/docs/best-practices.mdx +27 -9
- package/docs/capabilities.mdx +14 -16
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +54 -75
- package/docs/cli/doctor.mdx +14 -3
- package/docs/cli/drive.mdx +20 -14
- package/docs/cli/feedback.mdx +3 -3
- package/docs/cli/gate.mdx +7 -2
- package/docs/cli/help.mdx +50 -55
- package/docs/cli/init.mdx +43 -28
- package/docs/cli/license.mdx +12 -8
- package/docs/cli/mcp.mdx +4 -4
- package/docs/cli/open.mdx +3 -3
- package/docs/cli/report.mdx +4 -2
- package/docs/cli/restart.mdx +2 -2
- package/docs/cli/rollback.mdx +14 -8
- package/docs/cli/serve.mdx +4 -4
- package/docs/cli/setup.mdx +23 -0
- package/docs/cli/status.mdx +18 -5
- package/docs/cli/stop.mdx +67 -8
- package/docs/cli/try.mdx +62 -0
- package/docs/cli/update.mdx +4 -3
- package/docs/cli/verify.mdx +17 -6
- package/docs/cli/version.mdx +5 -4
- package/docs/cli.mdx +111 -42
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +9 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +7 -8
- package/docs/faq.mdx +3 -3
- package/docs/first-drive.md +5 -4
- package/docs/flows.md +35 -27
- package/docs/for-agents.md +4 -5
- package/docs/frameworks.mdx +32 -21
- package/docs/getting-started.md +65 -61
- package/docs/human-control.md +16 -16
- package/docs/index.mdx +15 -42
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +23 -13
- package/docs/instrumentation.mdx +5 -3
- package/docs/integration-patterns.md +7 -7
- package/docs/license-activation.mdx +1 -1
- package/docs/multi-agent-testing.md +24 -6
- package/docs/packages/babel-plugin.mdx +4 -2
- package/docs/packages/browser.mdx +16 -10
- package/docs/packages/core.mdx +12 -5
- package/docs/packages/electron.mdx +3 -2
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/eslint-plugin.mdx +18 -12
- package/docs/packages/next.mdx +8 -7
- package/docs/packages/open-verification.mdx +1 -1
- package/docs/packages/server.mdx +5 -5
- package/docs/packages/tauri.mdx +9 -9
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +32 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +69 -30
- package/docs/required-checks.md +8 -7
- package/docs/reticle-manual.md +15 -5
- package/docs/skill-file.mdx +17 -79
- package/docs/skill-setup.md +9 -9
- package/docs/skill.md +200 -0
- package/docs/system-map.md +7 -7
- package/docs/telemetry.md +23 -25
- package/docs/testing.md +4 -4
- package/docs/token-efficiency.md +12 -12
- package/docs/tools/act-and-wait.mdx +9 -2
- package/docs/tools/act-sequence.mdx +6 -7
- package/docs/tools/act.mdx +2 -2
- package/docs/tools/assert.mdx +18 -17
- package/docs/tools/console.mdx +9 -9
- package/docs/tools/inspect.mdx +16 -7
- package/docs/tools/look.mdx +24 -0
- package/docs/tools/navigate.mdx +5 -3
- package/docs/tools/network.mdx +2 -2
- package/docs/tools/observe.mdx +6 -6
- package/docs/tools/overview.mdx +34 -33
- package/docs/tools/query.mdx +5 -5
- package/docs/tools/session-and-feedback.mdx +22 -13
- package/docs/tools/sessions.mdx +8 -8
- package/docs/tools/snapshot.mdx +6 -5
- package/docs/tools/state.mdx +9 -9
- package/docs/tools/tools-and-run.mdx +26 -24
- package/docs/tools/verify.mdx +28 -0
- package/docs/tools/wait-for.mdx +8 -4
- package/docs/troubleshooting.mdx +21 -6
- package/docs/usage.md +55 -46
- package/docs/use-cases.mdx +3 -3
- package/docs/vs-chrome-devtools-mcp.mdx +9 -6
- package/docs/vs-playwright-mcp.mdx +3 -1
- package/docs/what-is-recorded.md +17 -5
- package/docs/what-is-reticle.mdx +5 -3
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -241
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -58
- package/dist/features/harness/openai-driver.js +0 -206
- package/dist/judgement/hunt/hunt-report.d.ts +0 -49
- package/dist/judgement/hunt/hunt-report.js +0 -84
- package/dist/language/flows/buddy-status.d.ts +0 -25
- package/dist/language/flows/buddy-status.js +0 -32
- package/dist/language/flows/change/watch-batcher.d.ts +0 -18
- package/dist/language/flows/change/watch-batcher.js +0 -19
- package/dist/memory/cloud/harness-offer.d.ts +0 -44
- package/dist/memory/cloud/harness-offer.js +0 -145
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/dist/surface/tools/feature-capture.d.ts +0 -151
- package/dist/surface/tools/feature-capture.js +0 -235
- package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
- package/dist/surface/tools/tool-hit-rate.js +0 -90
- package/dist/telemetry/harness-drive.d.ts +0 -4
- package/dist/telemetry/harness-drive.js +0 -35
- package/dist/telemetry/identify.d.ts +0 -22
- package/dist/telemetry/identify.js +0 -73
- package/docs/cli/capsules.mdx +0 -70
- package/docs/cli/hunt.mdx +0 -73
- package/docs/cli/identify.mdx +0 -76
- package/docs/cli/kill.mdx +0 -91
- package/docs/cli/watch.mdx +0 -62
- package/docs/local-registry.md +0 -143
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What a drive found that no single click's check could: the page rendering something other than
|
|
3
|
+
* what the API sent (`reticle_reconcile`, run on each page the Harness reaches), and the crawl's
|
|
4
|
+
* anomalies (blank routes, dead controls, console errors, contradictions).
|
|
5
|
+
*
|
|
6
|
+
* Listed in the drive's report beside the verdict, because the agent reading it reports what it is
|
|
7
|
+
* shown: a defect the drive saw and the report left out is a defect nobody hears about.
|
|
8
|
+
*/
|
|
9
|
+
import { ReticleTool, asRecord, asString } from '@reticlehq/core';
|
|
10
|
+
/** Enough to act on without burying the verdict. */
|
|
11
|
+
const MAX_FINDINGS = 20;
|
|
12
|
+
export function appFindings(toolCalls) {
|
|
13
|
+
const seen = new Set();
|
|
14
|
+
const lines = [];
|
|
15
|
+
const add = (key, line) => {
|
|
16
|
+
if (seen.has(key) || MAX_FINDINGS <= lines.length)
|
|
17
|
+
return;
|
|
18
|
+
seen.add(key);
|
|
19
|
+
lines.push(line);
|
|
20
|
+
};
|
|
21
|
+
for (const call of toolCalls) {
|
|
22
|
+
if (call.isError)
|
|
23
|
+
continue;
|
|
24
|
+
const result = asRecord(call.result);
|
|
25
|
+
if (ReticleTool.RECONCILE === call.name) {
|
|
26
|
+
const mismatches = result['mismatches'];
|
|
27
|
+
for (const raw of Array.isArray(mismatches) ? mismatches : []) {
|
|
28
|
+
const m = asRecord(raw);
|
|
29
|
+
const entity = asString(m['entity']) ?? '?';
|
|
30
|
+
const field = asString(m['field']) ?? '?';
|
|
31
|
+
const shown = asString(m['rendered']);
|
|
32
|
+
add(`r:${entity}:${field}`, ` RENDERED ≠ API: ${entity} ${field} — the API says ${String(m['api'])}${shown === undefined ? '' : `, the page shows ${shown}`} (${asString(m['why']) ?? ''})`);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (ReticleTool.CRAWL === call.name) {
|
|
36
|
+
const anomalies = result['anomalies'];
|
|
37
|
+
for (const raw of Array.isArray(anomalies) ? anomalies : []) {
|
|
38
|
+
const a = asRecord(raw);
|
|
39
|
+
const kind = asString(a['kind']) ?? 'anomaly';
|
|
40
|
+
const desc = asString(a['desc']) ?? '';
|
|
41
|
+
const detail = asString(a['detail']);
|
|
42
|
+
add(`c:${kind}:${desc}`, ` CRAWL ${kind}: ${desc}${detail === undefined ? '' : ` — ${detail}`}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return 0 === lines.length
|
|
47
|
+
? []
|
|
48
|
+
: [
|
|
49
|
+
'Found beyond the clicks (each page compared with the API, and a crawl of the app):',
|
|
50
|
+
...lines,
|
|
51
|
+
];
|
|
52
|
+
}
|
|
@@ -17,6 +17,7 @@
|
|
|
17
17
|
* that is what a coding agent has to gate on, and it says "not proved" in those words rather than
|
|
18
18
|
* leaving a verdict of `unknown` to be read as a pass.
|
|
19
19
|
*/
|
|
20
|
+
import { Verified } from '@reticlehq/core';
|
|
20
21
|
import type { ToolOutcome } from './harness.js';
|
|
21
22
|
/** One driven action, reduced to what a reader needs: what was done, and what it proved. */
|
|
22
23
|
export interface DrivenStep {
|
|
@@ -26,6 +27,8 @@ export interface DrivenStep {
|
|
|
26
27
|
target: string;
|
|
27
28
|
/** The engine's verdict for this step, when the step declared anything. */
|
|
28
29
|
verified: string | undefined;
|
|
30
|
+
/** A route claim that missed: the driver's own guess, or a menu it opened. Never a check. */
|
|
31
|
+
guess?: true;
|
|
29
32
|
/** The one sentence naming the deciding evidence. */
|
|
30
33
|
because: string | undefined;
|
|
31
34
|
/**
|
|
@@ -37,7 +40,15 @@ export interface DrivenStep {
|
|
|
37
40
|
* noise, and the report is read every drive.
|
|
38
41
|
*/
|
|
39
42
|
claimed: string | undefined;
|
|
43
|
+
/**
|
|
44
|
+
* What the engine saw that decided it: each channel that disagreed, and any write the app sent
|
|
45
|
+
* that failed. The act's own result carries all of it; a report that kept only the verdict word
|
|
46
|
+
* handed the caller "unit-mismatch" and left it unable to say what was wrong.
|
|
47
|
+
*/
|
|
48
|
+
evidence: string[];
|
|
40
49
|
}
|
|
50
|
+
/** Driving calls that ran with the destructive-action permission: these really changed the app. */
|
|
51
|
+
export declare function confirmedDestructive(toolCalls: readonly ToolOutcome[]): number;
|
|
41
52
|
/**
|
|
42
53
|
* Replays this drive ran, and what each came back with.
|
|
43
54
|
*
|
|
@@ -54,6 +65,10 @@ export declare const ReplayOutcome: {
|
|
|
54
65
|
readonly OK: "ok";
|
|
55
66
|
readonly DRIFT: "drift";
|
|
56
67
|
readonly ERROR: "error";
|
|
68
|
+
/** Stopped at a step the flow marks destructive: not run, which is not a regression. */
|
|
69
|
+
readonly GUARDED: "guarded";
|
|
70
|
+
/** Not saved on this computer: nothing ran, which is not a regression either. */
|
|
71
|
+
readonly MISSING: "missing";
|
|
57
72
|
};
|
|
58
73
|
export declare function replayedFlows(toolCalls: readonly ToolOutcome[]): {
|
|
59
74
|
name: string;
|
|
@@ -61,4 +76,49 @@ export declare function replayedFlows(toolCalls: readonly ToolOutcome[]): {
|
|
|
61
76
|
}[];
|
|
62
77
|
/** Reduce the raw call log to the actions that actually drove the app. */
|
|
63
78
|
export declare function drivenSteps(toolCalls: readonly ToolOutcome[]): DrivenStep[];
|
|
64
|
-
|
|
79
|
+
/** Whether the drive did anything to the app: an action that ran, or a flow it replayed. */
|
|
80
|
+
export declare function actedOnApp(toolCalls: readonly ToolOutcome[]): boolean;
|
|
81
|
+
/** The pages the drive's own snapshots reported, in order, each distinct page once. */
|
|
82
|
+
export declare function pagesReached(toolCalls: readonly ToolOutcome[]): string[];
|
|
83
|
+
/** The values the drive's acts filled or typed, sequence steps included. */
|
|
84
|
+
export declare function typedValues(toolCalls: readonly ToolOutcome[]): string[];
|
|
85
|
+
/** How the drive's checks came out: act_and_wait with an `until`, and asserts. */
|
|
86
|
+
export declare function checkTally(toolCalls: readonly ToolOutcome[]): {
|
|
87
|
+
held: number;
|
|
88
|
+
failed: number;
|
|
89
|
+
undecided: number;
|
|
90
|
+
};
|
|
91
|
+
/** A plan journey's status, as far as the run's verdict reads it. */
|
|
92
|
+
export interface JourneyStatus {
|
|
93
|
+
status: string;
|
|
94
|
+
}
|
|
95
|
+
/** A run's verdict and the line that says it: the word is decided once, never read back out of the line. */
|
|
96
|
+
export interface RunVerdict {
|
|
97
|
+
verified: Verified;
|
|
98
|
+
line: string;
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* The first line a caller reads, and the one the HUD ends on, with the verdict it states. A drive
|
|
102
|
+
* whose only passing check was a page change, beside a refund that failed, is NOT "proved its
|
|
103
|
+
* checks"; that line ended a run where the journey it was asked to prove had failed.
|
|
104
|
+
*/
|
|
105
|
+
export declare function runVerdict(tally: {
|
|
106
|
+
held: number;
|
|
107
|
+
failed: number;
|
|
108
|
+
undecided: number;
|
|
109
|
+
}, goalMet?: boolean,
|
|
110
|
+
/** A plan's journeys: when there are any, their verdict is the run's. */
|
|
111
|
+
journeys?: readonly JourneyStatus[]): RunVerdict;
|
|
112
|
+
/** The line alone. */
|
|
113
|
+
export declare function verdictLine(tally: {
|
|
114
|
+
held: number;
|
|
115
|
+
failed: number;
|
|
116
|
+
undecided: number;
|
|
117
|
+
}, goalMet?: boolean, journeys?: readonly JourneyStatus[]): string;
|
|
118
|
+
/** Whether the run is proved, exactly as its headline says: the `proved` an answer carries. */
|
|
119
|
+
export declare function runProved(tally: {
|
|
120
|
+
held: number;
|
|
121
|
+
failed: number;
|
|
122
|
+
undecided: number;
|
|
123
|
+
}, goalMet?: boolean, journeys?: readonly JourneyStatus[]): boolean;
|
|
124
|
+
export declare function describeDrive(toolCalls: readonly ToolOutcome[], savedFlows: readonly string[], unverifiedFlows?: readonly string[], goalMet?: boolean, journeys?: readonly JourneyStatus[]): string;
|
|
@@ -17,9 +17,76 @@
|
|
|
17
17
|
* that is what a coding agent has to gate on, and it says "not proved" in those words rather than
|
|
18
18
|
* leaving a verdict of `unknown` to be read as a pass.
|
|
19
19
|
*/
|
|
20
|
-
import {
|
|
20
|
+
import { appFindings } from './app-findings.js';
|
|
21
|
+
import { MSG_OPENED_MENU, MSG_ROUTE_GUESS_MISSED, claimsOnlyRoute } from './route-guess.js';
|
|
22
|
+
import { asRecord, asString, ActionType, NO_SUCH_FLOW, ReplayStatus, ReticleTool, ScriptStatus, Verified, } from '@reticlehq/core';
|
|
23
|
+
import { supersededChecks } from '@reticlehq/engine/evidence/superseded-checks.js';
|
|
24
|
+
import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate-schema.js';
|
|
25
|
+
import { describeWaitTarget } from '@reticlehq/engine/evidence/unsettled.js';
|
|
26
|
+
function refusedAsDestructive(call) {
|
|
27
|
+
const error = asString(asRecord(call.result)['error']) ?? '';
|
|
28
|
+
return call.isError && error.includes(DESTRUCTIVE_REFUSAL);
|
|
29
|
+
}
|
|
30
|
+
/** Driving calls that ran with the destructive-action permission: these really changed the app. */
|
|
31
|
+
export function confirmedDestructive(toolCalls) {
|
|
32
|
+
return toolCalls.filter((call) => DRIVING_TOOLS.has(call.name) &&
|
|
33
|
+
!call.isError &&
|
|
34
|
+
true === asRecord(asRecord(call.args)['args'])[DESTRUCTIVE_REFUSAL]).length;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* A failed claim whose page then showed a dialog: the control opens a confirmation, and the drive
|
|
38
|
+
* guessed it would send the request itself. Reported as a defect, a row's "Refund" button that opens
|
|
39
|
+
* the "Refund now" dialog sent the caller looking for a dead control.
|
|
40
|
+
*/
|
|
41
|
+
function openedADialog(result, after) {
|
|
42
|
+
if (Verified.NO !== result['verified'])
|
|
43
|
+
return [];
|
|
44
|
+
const next = after.find((call) => ReticleTool.SNAPSHOT === call.name);
|
|
45
|
+
const dialogs = asRecord(asRecord(next?.result)['status'])['visibleDialogs'];
|
|
46
|
+
return Array.isArray(dialogs) && 0 < dialogs.length
|
|
47
|
+
? [
|
|
48
|
+
'it opened a dialog instead: likely the drive guessed the consequence wrong, not an app defect',
|
|
49
|
+
]
|
|
50
|
+
: [];
|
|
51
|
+
}
|
|
52
|
+
/** Characters of a response body quoted in the evidence: enough for an error message. */
|
|
53
|
+
const MAX_BODY_CHARS = 200;
|
|
54
|
+
/** Contradictions quoted per step. */
|
|
55
|
+
const MAX_EVIDENCE = 3;
|
|
56
|
+
/** The deciding evidence an act result carries, as short lines. */
|
|
57
|
+
function evidenceOf(result) {
|
|
58
|
+
const lines = [];
|
|
59
|
+
const contradictions = result['contradictions'];
|
|
60
|
+
if (Array.isArray(contradictions)) {
|
|
61
|
+
for (const raw of contradictions.slice(0, MAX_EVIDENCE)) {
|
|
62
|
+
const c = asRecord(raw);
|
|
63
|
+
const parts = [asString(c['counter']), asString(c['detail'])].filter((part) => part !== undefined && 0 < part.length);
|
|
64
|
+
lines.push(`${asString(c['kind']) ?? 'contradiction'}: ${parts.join(' — ')}`);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
const verdict = asRecord(result['verdict']);
|
|
68
|
+
const seen = asRecord(verdict['evidence']);
|
|
69
|
+
const status = seen['status'];
|
|
70
|
+
if ('number' === typeof status && 400 <= status) {
|
|
71
|
+
const body = asString(seen['responseBody']);
|
|
72
|
+
lines.push(`${asString(seen['method']) ?? ''} ${asString(seen['url']) ?? ''} → ${String(status)}` +
|
|
73
|
+
(body === undefined ? '' : ` ${body.slice(0, MAX_BODY_CHARS)}`));
|
|
74
|
+
}
|
|
75
|
+
const observed = asString(verdict['observed']);
|
|
76
|
+
if (false === verdict['pass'] && observed !== undefined)
|
|
77
|
+
lines.push(`observed: ${observed}`);
|
|
78
|
+
return lines;
|
|
79
|
+
}
|
|
80
|
+
/** The permission a destructive action needs, named in the gate's refusal and carried on a retry. */
|
|
81
|
+
const DESTRUCTIVE_REFUSAL = 'confirmDangerous';
|
|
21
82
|
/** How many steps are listed before the account starts counting instead of naming. */
|
|
22
83
|
const MAX_LISTED = 12;
|
|
84
|
+
/**
|
|
85
|
+
* Failures are listed first, and up to this many of them however long the run. Listed in drive
|
|
86
|
+
* order, a whole-app run named 12 of 70 actions and left its failures in "… and 58 more", so the
|
|
87
|
+
* agent reading it could not say what any of them was.
|
|
88
|
+
*/
|
|
89
|
+
const MAX_FAILED = 40;
|
|
23
90
|
/** Actions that change the app. Reads are not part of the story of what was driven. */
|
|
24
91
|
const DRIVING_TOOLS = new Set([
|
|
25
92
|
ReticleTool.ACT,
|
|
@@ -61,16 +128,33 @@ function targetOf(args, result) {
|
|
|
61
128
|
* resolving — the app moved under a recording, which is a finding about the RECORDING rather than
|
|
62
129
|
* proof the feature broke, and collapsing it into "failed" would send somebody to fix working code.
|
|
63
130
|
*/
|
|
64
|
-
export const ReplayOutcome = {
|
|
131
|
+
export const ReplayOutcome = {
|
|
132
|
+
OK: 'ok',
|
|
133
|
+
DRIFT: 'drift',
|
|
134
|
+
ERROR: 'error',
|
|
135
|
+
/** Stopped at a step the flow marks destructive: not run, which is not a regression. */
|
|
136
|
+
GUARDED: 'guarded',
|
|
137
|
+
/** Not saved on this computer: nothing ran, which is not a regression either. */
|
|
138
|
+
MISSING: 'missing',
|
|
139
|
+
};
|
|
65
140
|
export function replayedFlows(toolCalls) {
|
|
66
141
|
const out = [];
|
|
67
142
|
for (const call of toolCalls) {
|
|
68
143
|
if (ReticleTool.FLOW_REPLAY !== call.name)
|
|
69
144
|
continue;
|
|
70
145
|
const name = asString(asRecord(call.args)['flowName']) ?? 'a flow';
|
|
146
|
+
const result = asRecord(call.result);
|
|
147
|
+
const message = asString(asRecord(result['error'])['message']) ?? asString(result['error']) ?? '';
|
|
148
|
+
const status = call.isError ? ReplayOutcome.ERROR : asString(result['status']);
|
|
71
149
|
out.push({
|
|
72
150
|
name,
|
|
73
|
-
status:
|
|
151
|
+
status: ReplayOutcome.ERROR !== status
|
|
152
|
+
? status
|
|
153
|
+
: message.includes(DESTRUCTIVE_REFUSAL)
|
|
154
|
+
? ReplayOutcome.GUARDED
|
|
155
|
+
: message.includes(NO_SUCH_FLOW)
|
|
156
|
+
? ReplayOutcome.MISSING
|
|
157
|
+
: status,
|
|
74
158
|
});
|
|
75
159
|
}
|
|
76
160
|
return out;
|
|
@@ -106,25 +190,134 @@ function describeClaim(until) {
|
|
|
106
190
|
return 'a request or a signal';
|
|
107
191
|
return kind;
|
|
108
192
|
}
|
|
193
|
+
/** The declared consequence: `until`, or `predicate`, its alias on act_and_wait and on assert. */
|
|
194
|
+
function untilOf(args) {
|
|
195
|
+
return args['until'] ?? args['predicate'];
|
|
196
|
+
}
|
|
197
|
+
/** A `no` on a click whose only claim was a route: the driver's guess, not the app (route-guess.ts). */
|
|
198
|
+
function routeGuessMissed(args, result) {
|
|
199
|
+
return Verified.NO === result['verified'] && claimsOnlyRoute(untilOf(args));
|
|
200
|
+
}
|
|
201
|
+
/** The line a re-press graded undecided carries instead of the raw `no`. */
|
|
202
|
+
const MSG_REPRESS = "a second press of a control whose claim already held: the Harness's own extra action, not the app";
|
|
203
|
+
/** Every check in drive order: act_and_wait with an `until` and asserts, through reticle_run too. */
|
|
204
|
+
function gradedChecks(toolCalls) {
|
|
205
|
+
const heldPresses = new Set();
|
|
206
|
+
const out = [];
|
|
207
|
+
const checks = toolCalls.flatMap((made, index) => {
|
|
208
|
+
const call = throughRun(made);
|
|
209
|
+
const args = asRecord(call.args);
|
|
210
|
+
const until = untilOf(args);
|
|
211
|
+
const isCheck = ReticleTool.ASSERT === call.name ||
|
|
212
|
+
(ReticleTool.ACT_AND_WAIT === call.name && until !== undefined);
|
|
213
|
+
if (!isCheck || call.isError)
|
|
214
|
+
return [];
|
|
215
|
+
const predicate = PredicateSchema.safeParse(until);
|
|
216
|
+
const key = predicate.success
|
|
217
|
+
? `${predicate.data.kind}|${describeWaitTarget(predicate.data)}`
|
|
218
|
+
: JSON.stringify(until ?? null);
|
|
219
|
+
return [{ index, call, args, result: asRecord(call.result), key }];
|
|
220
|
+
});
|
|
221
|
+
const superseded = supersededChecks(checks.map(({ call, result, key }) => ({
|
|
222
|
+
key,
|
|
223
|
+
passive: ReticleTool.ASSERT === call.name,
|
|
224
|
+
held: Verified.YES === asString(result['verified']),
|
|
225
|
+
failed: Verified.NO === asString(result['verified']),
|
|
226
|
+
})));
|
|
227
|
+
for (const [at, { index, args, result, key }] of checks.entries()) {
|
|
228
|
+
// The driver's own wrong guess about the route checked the driver, not the app.
|
|
229
|
+
if (routeGuessMissed(args, result))
|
|
230
|
+
continue;
|
|
231
|
+
const verified = asString(result['verified']);
|
|
232
|
+
// A passive assert that read too early: see superseded-checks.ts.
|
|
233
|
+
if (superseded.has(at))
|
|
234
|
+
continue;
|
|
235
|
+
// A second press of a control whose claim already held is the Harness's own extra action.
|
|
236
|
+
const ref = asString(args['ref']);
|
|
237
|
+
const pressed = ref === undefined ? undefined : `${ref}|${key}`;
|
|
238
|
+
const repress = Verified.NO === verified && pressed !== undefined && heldPresses.has(pressed);
|
|
239
|
+
if (Verified.YES === verified && pressed !== undefined)
|
|
240
|
+
heldPresses.add(pressed);
|
|
241
|
+
const outcome = Verified.YES === verified
|
|
242
|
+
? 'held'
|
|
243
|
+
: Verified.NO === verified && !repress
|
|
244
|
+
? 'failed'
|
|
245
|
+
: 'undecided';
|
|
246
|
+
out.push({ index, key, outcome, repress });
|
|
247
|
+
}
|
|
248
|
+
return out;
|
|
249
|
+
}
|
|
250
|
+
/**
|
|
251
|
+
* A `reticle_run` call as the tool it ran. A navigation made through it was recorded under the
|
|
252
|
+
* run's name, and a run that navigated between two pages said it made no action against the app.
|
|
253
|
+
*/
|
|
254
|
+
function throughRun(call) {
|
|
255
|
+
if (ReticleTool.RUN !== call.name)
|
|
256
|
+
return call;
|
|
257
|
+
const args = asRecord(call.args);
|
|
258
|
+
const name = asString(args['tool']);
|
|
259
|
+
return name === undefined ? call : { ...call, name, args: asRecord(args['args']) };
|
|
260
|
+
}
|
|
109
261
|
/** Reduce the raw call log to the actions that actually drove the app. */
|
|
110
262
|
export function drivenSteps(toolCalls) {
|
|
111
263
|
const steps = [];
|
|
112
|
-
|
|
264
|
+
const represses = new Set(gradedChecks(toolCalls)
|
|
265
|
+
.filter((check) => check.repress)
|
|
266
|
+
.map((check) => check.index));
|
|
267
|
+
for (const [index, made] of toolCalls.entries()) {
|
|
268
|
+
const call = throughRun(made);
|
|
113
269
|
if (!DRIVING_TOOLS.has(call.name))
|
|
114
270
|
continue;
|
|
115
271
|
const args = asRecord(call.args);
|
|
116
272
|
const result = asRecord(call.result);
|
|
273
|
+
// The gate's refusal never reached the app; listed beside the confirmed retry, it read as "the
|
|
274
|
+
// refund was blocked" to the agent reading this, about a refund that had gone through.
|
|
275
|
+
if (refusedAsDestructive(call))
|
|
276
|
+
continue;
|
|
117
277
|
const action = ReticleTool.NAVIGATE === call.name ? 'navigate' : (asString(args['action']) ?? 'act');
|
|
278
|
+
const guessMissed = !call.isError && routeGuessMissed(args, result);
|
|
279
|
+
if (represses.has(index)) {
|
|
280
|
+
steps.push({
|
|
281
|
+
action,
|
|
282
|
+
target: targetOf(args, result),
|
|
283
|
+
verified: Verified.UNKNOWN,
|
|
284
|
+
because: MSG_REPRESS,
|
|
285
|
+
claimed: describeClaim(untilOf(args)),
|
|
286
|
+
evidence: [],
|
|
287
|
+
});
|
|
288
|
+
continue;
|
|
289
|
+
}
|
|
290
|
+
// A menu or dialog it opened is the way to the route it named, not a wrong guess.
|
|
291
|
+
const opened = guessMissed && 0 < openedADialog(result, toolCalls.slice(index + 1)).length;
|
|
118
292
|
steps.push({
|
|
293
|
+
...(guessMissed ? { guess: true } : {}),
|
|
119
294
|
action,
|
|
120
295
|
target: targetOf(args, result),
|
|
121
|
-
verified: call.isError
|
|
122
|
-
|
|
123
|
-
|
|
296
|
+
verified: call.isError
|
|
297
|
+
? 'error'
|
|
298
|
+
: guessMissed
|
|
299
|
+
? Verified.UNKNOWN
|
|
300
|
+
: asString(result['verified']),
|
|
301
|
+
because: call.isError
|
|
302
|
+
? asString(result['error'])
|
|
303
|
+
: opened
|
|
304
|
+
? MSG_OPENED_MENU
|
|
305
|
+
: guessMissed
|
|
306
|
+
? MSG_ROUTE_GUESS_MISSED
|
|
307
|
+
: asString(result['because']),
|
|
308
|
+
claimed: describeClaim(untilOf(args)),
|
|
309
|
+
evidence: call.isError || opened
|
|
310
|
+
? []
|
|
311
|
+
: [...evidenceOf(result), ...openedADialog(result, toolCalls.slice(index + 1))],
|
|
124
312
|
});
|
|
125
313
|
}
|
|
126
314
|
return steps;
|
|
127
315
|
}
|
|
316
|
+
/** Whether the drive did anything to the app: an action that ran, or a flow it replayed. */
|
|
317
|
+
export function actedOnApp(toolCalls) {
|
|
318
|
+
return (drivenSteps(toolCalls).some((step) => 'error' !== step.verified) ||
|
|
319
|
+
0 < replayedFlows(toolCalls).length);
|
|
320
|
+
}
|
|
128
321
|
/**
|
|
129
322
|
* The account, as lines.
|
|
130
323
|
*
|
|
@@ -134,19 +327,147 @@ export function drivenSteps(toolCalls) {
|
|
|
134
327
|
* rather than as a failure — it calls for a better check, not a code change, and collapsing the two
|
|
135
328
|
* would send an agent to rewrite working code.
|
|
136
329
|
*/
|
|
330
|
+
/** Every `__reticle_*` query parameter, wherever it sits in the route. */
|
|
331
|
+
const RETICLE_PARAMS = /[?&]__reticle_[^&#]*/g;
|
|
137
332
|
/** The pages the drive's own snapshots reported, in order, each distinct page once. */
|
|
138
|
-
function pagesReached(toolCalls) {
|
|
333
|
+
export function pagesReached(toolCalls) {
|
|
139
334
|
const pages = [];
|
|
140
335
|
for (const call of toolCalls) {
|
|
141
336
|
if (ReticleTool.SNAPSHOT !== call.name || call.isError)
|
|
142
337
|
continue;
|
|
143
|
-
const
|
|
338
|
+
const raw = asString(asRecord(asRecord(call.result)['status'])['route']);
|
|
339
|
+
// Reticle's own parameters (a leased tab's session and project) are not part of the page.
|
|
340
|
+
const route = raw?.replace(RETICLE_PARAMS, '').replace(/^\/\?(?=#|$)/, '/');
|
|
144
341
|
if (route !== undefined && !pages.includes(route))
|
|
145
342
|
pages.push(route);
|
|
146
343
|
}
|
|
147
344
|
return pages;
|
|
148
345
|
}
|
|
149
|
-
|
|
346
|
+
/** The values the drive's acts filled or typed, sequence steps included. */
|
|
347
|
+
export function typedValues(toolCalls) {
|
|
348
|
+
const out = [];
|
|
349
|
+
const read = (act) => {
|
|
350
|
+
const inner = asRecord(act['args']);
|
|
351
|
+
const value = asString(inner['value']) ?? asString(inner['text']);
|
|
352
|
+
if (value !== undefined &&
|
|
353
|
+
(ActionType.FILL === act['action'] || ActionType.TYPE === act['action']))
|
|
354
|
+
out.push(value);
|
|
355
|
+
};
|
|
356
|
+
for (const call of toolCalls) {
|
|
357
|
+
const steps = call.args['steps'];
|
|
358
|
+
if (Array.isArray(steps))
|
|
359
|
+
for (const step of steps)
|
|
360
|
+
read(asRecord(step));
|
|
361
|
+
else
|
|
362
|
+
read(call.args);
|
|
363
|
+
}
|
|
364
|
+
return out;
|
|
365
|
+
}
|
|
366
|
+
/** How the drive's checks came out: act_and_wait with an `until`, and asserts. */
|
|
367
|
+
export function checkTally(toolCalls) {
|
|
368
|
+
// One check per (kind, claim, outcome), exactly as the platform counts a run's checks: a live
|
|
369
|
+
// drive pressed "Sign in" fifteen times and read "15 of 15 check(s) held" for one fact, and an
|
|
370
|
+
// answer that counted by control said "2 of 2" beside a dashboard counting the same run otherwise.
|
|
371
|
+
const seen = new Set();
|
|
372
|
+
const tally = { held: 0, failed: 0, undecided: 0 };
|
|
373
|
+
const count = (key, now) => {
|
|
374
|
+
if (seen.has(`${key}|${now}`))
|
|
375
|
+
return;
|
|
376
|
+
seen.add(`${key}|${now}`);
|
|
377
|
+
tally[now] += 1;
|
|
378
|
+
};
|
|
379
|
+
for (const check of gradedChecks(toolCalls))
|
|
380
|
+
count(check.key, check.outcome);
|
|
381
|
+
// A replayed flow is a check too: its own expects decided it. A passed replay counted as "no
|
|
382
|
+
// check" and its run read NOT PROVED beside a dashboard that said Passed.
|
|
383
|
+
for (const replay of replayedFlows(toolCalls)) {
|
|
384
|
+
const now = REPLAY_CHECK[replay.status ?? ''];
|
|
385
|
+
if (now === undefined)
|
|
386
|
+
continue;
|
|
387
|
+
count(`${ReticleTool.FLOW_REPLAY}|${replay.name}`, now);
|
|
388
|
+
}
|
|
389
|
+
return tally;
|
|
390
|
+
}
|
|
391
|
+
/** A replay as a check. Guarded and missing never ran, so they are no check at all. */
|
|
392
|
+
const REPLAY_CHECK = {
|
|
393
|
+
[ReplayOutcome.OK]: 'held',
|
|
394
|
+
[ReplayOutcome.ERROR]: 'failed',
|
|
395
|
+
[ReplayOutcome.DRIFT]: 'undecided',
|
|
396
|
+
[ReplayStatus.UNVERIFIABLE]: 'undecided',
|
|
397
|
+
};
|
|
398
|
+
/** Statuses that leave a plan proved: passed, or a side road deliberately not taken (named in its line). */
|
|
399
|
+
const SETTLED_JOURNEY = new Set([ScriptStatus.PASSED, ScriptStatus.NOT_TAKEN]);
|
|
400
|
+
/**
|
|
401
|
+
* A plan run's verdict is its journeys', decided as the platform decides it (`planRunVerdict`): any
|
|
402
|
+
* failed → failed; every journey passed (or deliberately not taken) → proved; some passed beside
|
|
403
|
+
* journeys left undecided or blocked → not proved. Undefined when there is no plan.
|
|
404
|
+
*
|
|
405
|
+
* "Any passed → proved" read PROVED for a plan whose other journeys a credit cut-off had blocked:
|
|
406
|
+
* one journey proved and the rest never decided, reported as the whole plan proved.
|
|
407
|
+
*/
|
|
408
|
+
function journeysVerdict(journeys, counts) {
|
|
409
|
+
if (0 === journeys.length)
|
|
410
|
+
return undefined;
|
|
411
|
+
const of = (status) => journeys.filter((j) => status === j.status).length;
|
|
412
|
+
const total = String(journeys.length);
|
|
413
|
+
const passed = of(ScriptStatus.PASSED);
|
|
414
|
+
if (0 < of(ScriptStatus.FAILED))
|
|
415
|
+
return {
|
|
416
|
+
verified: Verified.NO,
|
|
417
|
+
line: `NOT PROVED — ${String(of(ScriptStatus.FAILED))} of ${total} journey(s) failed${counts}.`,
|
|
418
|
+
};
|
|
419
|
+
if (0 < passed && journeys.every((j) => SETTLED_JOURNEY.has(j.status)))
|
|
420
|
+
return {
|
|
421
|
+
verified: Verified.YES,
|
|
422
|
+
line: `PROVED — ${String(passed)} of ${total} journey(s) passed${counts}.`,
|
|
423
|
+
};
|
|
424
|
+
if (0 < passed)
|
|
425
|
+
return {
|
|
426
|
+
verified: Verified.UNKNOWN,
|
|
427
|
+
line: `NOT PROVED — ${String(passed)} of ${total} journey(s) passed and the rest were not decided${counts}.`,
|
|
428
|
+
};
|
|
429
|
+
return { verified: Verified.UNKNOWN, line: `NOT PROVED — no journey passed${counts}.` };
|
|
430
|
+
}
|
|
431
|
+
/**
|
|
432
|
+
* The first line a caller reads, and the one the HUD ends on, with the verdict it states. A drive
|
|
433
|
+
* whose only passing check was a page change, beside a refund that failed, is NOT "proved its
|
|
434
|
+
* checks"; that line ended a run where the journey it was asked to prove had failed.
|
|
435
|
+
*/
|
|
436
|
+
export function runVerdict(tally, goalMet,
|
|
437
|
+
/** A plan's journeys: when there are any, their verdict is the run's. */
|
|
438
|
+
journeys = []) {
|
|
439
|
+
const total = tally.held + tally.failed + tally.undecided;
|
|
440
|
+
const counts = `${String(tally.held)} of ${String(total)} check(s) held, ${String(tally.failed)} failed, ${String(tally.undecided)} undecided`;
|
|
441
|
+
const planned = journeysVerdict(journeys, 0 === total ? '' : `; ${counts}`);
|
|
442
|
+
const not = (line) => ({ verified: Verified.UNKNOWN, line });
|
|
443
|
+
// Journeys that passed are not the run's goal reached: the goals the run was asked decide it too.
|
|
444
|
+
if (Verified.YES === planned?.verified && false === goalMet)
|
|
445
|
+
return not(`NOT PROVED — ${planned.line.slice('PROVED — '.length).replace(/\.$/, '')}, but the goal was not reached.`);
|
|
446
|
+
if (planned !== undefined)
|
|
447
|
+
return planned;
|
|
448
|
+
if (0 === total)
|
|
449
|
+
return not('NOT PROVED: the drive ran no check.');
|
|
450
|
+
if (0 < tally.failed)
|
|
451
|
+
return {
|
|
452
|
+
verified: Verified.NO,
|
|
453
|
+
line: `NOT PROVED — ${counts}. The failures below are findings.`,
|
|
454
|
+
};
|
|
455
|
+
if (0 < tally.undecided)
|
|
456
|
+
return not(`NOT PROVED — ${counts}.`);
|
|
457
|
+
// Checks that held on the way are not the journey done.
|
|
458
|
+
if (false === goalMet)
|
|
459
|
+
return not(`NOT PROVED — ${counts}, but the goal was not reached.`);
|
|
460
|
+
return { verified: Verified.YES, line: `PROVED — ${counts}.` };
|
|
461
|
+
}
|
|
462
|
+
/** The line alone. */
|
|
463
|
+
export function verdictLine(tally, goalMet, journeys = []) {
|
|
464
|
+
return runVerdict(tally, goalMet, journeys).line;
|
|
465
|
+
}
|
|
466
|
+
/** Whether the run is proved, exactly as its headline says: the `proved` an answer carries. */
|
|
467
|
+
export function runProved(tally, goalMet, journeys = []) {
|
|
468
|
+
return Verified.YES === runVerdict(tally, goalMet, journeys).verified;
|
|
469
|
+
}
|
|
470
|
+
export function describeDrive(toolCalls, savedFlows, unverifiedFlows = [], goalMet, journeys = []) {
|
|
150
471
|
const steps = drivenSteps(toolCalls);
|
|
151
472
|
const replays = replayedFlows(toolCalls);
|
|
152
473
|
/*
|
|
@@ -162,34 +483,59 @@ export function describeDrive(toolCalls, savedFlows) {
|
|
|
162
483
|
const held = replays.filter((r) => ReplayOutcome.OK === r.status);
|
|
163
484
|
const failed = replays.filter((r) => ReplayOutcome.ERROR === r.status);
|
|
164
485
|
const drifted = replays.filter((r) => ReplayOutcome.DRIFT === r.status);
|
|
486
|
+
const guarded = replays.filter((r) => ReplayOutcome.GUARDED === r.status);
|
|
487
|
+
const missing = replays.filter((r) => ReplayOutcome.MISSING === r.status);
|
|
165
488
|
const lines = [
|
|
166
489
|
`Replayed ${String(replays.length)} recorded journey(s) with NO model in the loop: ` +
|
|
167
|
-
`${String(held.length)} still hold, ${String(failed.length)} failed, ${String(drifted.length)} drifted
|
|
490
|
+
`${String(held.length)} still hold, ${String(failed.length)} failed, ${String(drifted.length)} drifted` +
|
|
491
|
+
`${0 === guarded.length ? '' : `, ${String(guarded.length)} not run`}` +
|
|
492
|
+
`${0 === missing.length ? '' : `, ${String(missing.length)} not on this computer`}.`,
|
|
168
493
|
];
|
|
494
|
+
if (0 < missing.length)
|
|
495
|
+
lines.push(` MISSING: ${missing.map((r) => r.name).join(', ')} — not saved on this computer, or calls a flow that is not, so it never ran. Not a regression: pull or record them here first.`);
|
|
169
496
|
if (0 < failed.length)
|
|
170
497
|
lines.push(` FAILED: ${failed.map((r) => r.name).join(', ')} — regressions in journeys that used to pass.`);
|
|
498
|
+
if (0 < guarded.length)
|
|
499
|
+
lines.push(` NOT RUN: ${guarded.map((r) => r.name).join(', ')} — stopped at a step marked destructive. Not a regression: replay with confirmDangerous to run it.`);
|
|
171
500
|
if (0 < drifted.length)
|
|
172
501
|
lines.push(` DRIFTED: ${drifted.map((r) => r.name).join(', ')} — the app moved under these recordings; the flow needs re-anchoring, not the app fixing.`);
|
|
173
502
|
return lines.join('\n');
|
|
174
503
|
})();
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
504
|
+
// A plan run leads with its journeys' verdict even when the model drove nothing: its replays, or
|
|
505
|
+
// a journey a guard stopped, are a result, never "no action against the app".
|
|
506
|
+
if (0 === steps.length) {
|
|
507
|
+
const lead = 0 === journeys.length ? undefined : verdictLine(checkTally(toolCalls), goalMet, journeys);
|
|
508
|
+
return [
|
|
509
|
+
lead,
|
|
510
|
+
replayLine ??
|
|
511
|
+
(lead === undefined
|
|
512
|
+
? 'Nothing was driven and nothing was replayed: the run made no action against the app.'
|
|
513
|
+
: undefined),
|
|
514
|
+
]
|
|
515
|
+
.filter((line) => line !== undefined)
|
|
516
|
+
.join('\n');
|
|
517
|
+
}
|
|
178
518
|
const proved = steps.filter((step) => Verified.YES === step.verified);
|
|
179
519
|
const failed = steps.filter((step) => Verified.NO === step.verified);
|
|
180
|
-
|
|
520
|
+
// The driver's own route guesses are no check (as `checkTally` counts), so not "not decided".
|
|
521
|
+
const guesses = steps.filter((step) => true === step.guess);
|
|
522
|
+
const undecided = steps.filter((step) => true !== step.guess && Verified.YES !== step.verified && Verified.NO !== step.verified);
|
|
181
523
|
const pages = pagesReached(toolCalls);
|
|
182
524
|
const lines = [
|
|
525
|
+
verdictLine(checkTally(toolCalls), goalMet, journeys),
|
|
183
526
|
...(replayLine === undefined ? [] : [replayLine]),
|
|
184
|
-
|
|
185
|
-
|
|
527
|
+
// The outcomes are counted once, in the checks line above: no second breakdown here.
|
|
528
|
+
`Drove ${String(steps.length)} action(s)` +
|
|
529
|
+
(0 === guesses.length ? '.' : `; ${String(guesses.length)} guess of its own, not a check.`),
|
|
186
530
|
// How DEEP it got. An action count reads the same for a checkout walked to its receipt and for
|
|
187
531
|
// eleven clicks on the home page; the pages reached are what tell them apart.
|
|
188
532
|
...(0 === pages.length
|
|
189
533
|
? []
|
|
190
534
|
: [`Reached ${String(pages.length)} page(s): ${pages.join(' → ')}.`]),
|
|
535
|
+
...appFindings(toolCalls),
|
|
191
536
|
];
|
|
192
|
-
|
|
537
|
+
const listed = [...failed, ...proved, ...undecided, ...guesses].slice(0, Math.max(MAX_LISTED, Math.min(failed.length, MAX_FAILED)));
|
|
538
|
+
for (const step of listed) {
|
|
193
539
|
const verdict = step.verified ?? 'nothing declared';
|
|
194
540
|
const because = step.because === undefined ? '' : ` — ${step.because}`;
|
|
195
541
|
// The claim, on failures only: it is what separates "the app is broken" from "the drive guessed
|
|
@@ -201,14 +547,36 @@ export function describeDrive(toolCalls, savedFlows) {
|
|
|
201
547
|
? ` (claimed ${step.claimed})`
|
|
202
548
|
: '';
|
|
203
549
|
lines.push(` ${step.action} ${step.target}: ${verdict}${claimed}${because}`);
|
|
550
|
+
for (const line of step.evidence)
|
|
551
|
+
lines.push(` ${line}`);
|
|
552
|
+
}
|
|
553
|
+
if (listed.length < steps.length) {
|
|
554
|
+
const unlistedFailed = Math.max(0, failed.length - MAX_FAILED);
|
|
555
|
+
lines.push(` … and ${String(steps.length - listed.length)} more` +
|
|
556
|
+
(0 === unlistedFailed
|
|
557
|
+
? ', none of them failed.'
|
|
558
|
+
: `, ${String(unlistedFailed)} of them failed.`));
|
|
204
559
|
}
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
if (0 <
|
|
212
|
-
lines.push(
|
|
560
|
+
const confirmed = confirmedDestructive(toolCalls);
|
|
561
|
+
if (0 < confirmed)
|
|
562
|
+
lines.push(`${String(confirmed)} destructive action(s) were confirmed and REALLY RAN against the app (the drive confirms one only after the gate refuses it; the refusal itself changed nothing).`);
|
|
563
|
+
// Counted from the same graded checks as the checks line, never from the raw step verdicts: an
|
|
564
|
+
// answer read "0 failed" beside "1 action(s) FAILED … These are findings" about one re-press.
|
|
565
|
+
const tally = checkTally(toolCalls);
|
|
566
|
+
if (0 < tally.failed)
|
|
567
|
+
lines.push(`${String(tally.failed)} check(s) FAILED — the app did not do what the drive declared it would. These are findings.`);
|
|
568
|
+
if (0 < tally.undecided)
|
|
569
|
+
lines.push(`${String(tally.undecided)} check(s) undecided. That is undecided evidence, not a failure: it calls for a better check, not a code change.`);
|
|
570
|
+
const undeclared = undecided.filter((step) => step.claimed === undefined).length;
|
|
571
|
+
if (0 < undeclared)
|
|
572
|
+
lines.push(`${String(undeclared)} action(s) declared no consequence, so they prove nothing either way: not a check, not a failure.`);
|
|
573
|
+
// A flow with no step that asserts anything replays as "verified nothing": offered as a replay it
|
|
574
|
+
// reads as evidence, so it is named for what it is instead.
|
|
575
|
+
const empty = new Set(unverifiedFlows);
|
|
576
|
+
const replayable = savedFlows.filter((name) => !empty.has(name));
|
|
577
|
+
if (0 < replayable.length)
|
|
578
|
+
lines.push(`Replay any of this without a model: reticle_verify { action: "flows" } — saved ${replayable.join(', ')}.`);
|
|
579
|
+
for (const name of unverifiedFlows)
|
|
580
|
+
lines.push(`Saved ${name}, but ${name} checks nothing: no step asserts a consequence, so its replay will verify nothing. Drive again naming the end state, or add an expect to its last step.`);
|
|
213
581
|
return lines.join('\n');
|
|
214
582
|
}
|