@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
|
@@ -11,115 +11,416 @@
|
|
|
11
11
|
* them deterministically with no model in the loop at all.
|
|
12
12
|
*/
|
|
13
13
|
import { z } from 'zod';
|
|
14
|
-
import {
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
15
|
+
import { join } from 'node:path';
|
|
16
|
+
import { unprovedGoals } from '../../features/harness/goals.js';
|
|
17
|
+
import { ReticleEnv, ReticleTool, asRecord } from '@reticlehq/core';
|
|
15
18
|
import { stepCountSchema } from './args/numeric-bounds.js';
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
import {
|
|
19
|
+
import { DriveOrigin, DriveRefusedError, DriveStatus, POLL_WAIT_DEFAULT_S, awaitDrive, driveRecord, runningDrive, sayToDrive, startDrive, stillRunning, stopDrive, } from '../../features/harness/drive-runs.js';
|
|
20
|
+
import { fetchPlatformRun, platformRunAnswer, } from '../../features/harness/platform/platform-drives.js';
|
|
21
|
+
import { serverOptionsFromEnv } from '../../features/harness/platform/server-driver.js';
|
|
22
|
+
import { reportPlanBlocked, savedPlanDrivesNothing } from '../../features/harness/platform/script.js';
|
|
23
|
+
import { harnessRunId } from '../../judgement/runs/drive-run.js';
|
|
24
|
+
import { DRIVE_RECORD_SUFFIX, reticleDirPaths } from '../../memory/project/dir/reticle-dir.js';
|
|
25
|
+
import { sessionRoot } from '../../memory/project/session-root.js';
|
|
26
|
+
import { RESULT_FIELD, exploreResult, resultField } from './reticle-result.js';
|
|
27
|
+
import { runTool } from './invoke-tool.js';
|
|
28
|
+
import { harnessRunSource, reportHarnessBlocked, reportHarnessRun, } from '../../telemetry/harness-run.js';
|
|
29
|
+
import { driveVerdict } from '../../features/harness/platform/remote-drive.js';
|
|
30
|
+
import { harnessLockRefusal, firstLine, exploreApp, harnessAvailable, withLinkedCredential, MSG_NO_HARNESS_KEY, } from './harness-explore.js';
|
|
31
|
+
import { EXPLORE_NEEDS } from '../../features/harness/drivers.js';
|
|
32
|
+
import { checkTally, describeDrive, replayedFlows, runProved, } from '../../features/harness/drive-report.js';
|
|
19
33
|
import { StopReason } from '../../features/harness/harness.js';
|
|
34
|
+
const isRecord = (v) => 'object' === typeof v && null !== v && !Array.isArray(v);
|
|
35
|
+
export const WAIT_MAX_S = 240;
|
|
20
36
|
export const EXPLORE_TOOLS = [
|
|
21
37
|
{
|
|
22
38
|
name: ReticleTool.VERIFY_EXPLORE,
|
|
23
|
-
description: 'Drive the app yourself? Do not — call this instead.
|
|
39
|
+
description: 'Drive the app yourself? Do not — call this instead. The Reticle Harness drives it through this same tool surface (it decides on the Reticle platform, this daemon executes each step), records what it drove as saved flows, and answers in a few lines instead of a context full of snapshots: within `wait` seconds, the result or { status: "running", runId } to poll with `runId`. Never start a second. Pass `persona` to say who to be or what to accomplish ("a returning customer checking out", "an admin revoking a seat") and it completes that whole journey rather than clicking at random. The saved flows are the point: from the next run on, reticle_verify { action: "flows" } replays them deterministically with NO model in the loop. DESTRUCTIVE — it really drives the app, and it spends Harness credits. ' +
|
|
40
|
+
EXPLORE_NEEDS,
|
|
24
41
|
inputSchema: {
|
|
25
42
|
persona: z
|
|
26
43
|
.string()
|
|
27
44
|
.optional()
|
|
28
|
-
.describe('
|
|
29
|
-
|
|
45
|
+
.describe('The journey in plain words; "quoted text" must show at the end. Outcome goes in `expect`.'),
|
|
46
|
+
expect: z
|
|
47
|
+
.record(z.string(), z.unknown())
|
|
30
48
|
.optional()
|
|
31
|
-
.describe('
|
|
32
|
-
|
|
33
|
-
.enum(DRIVER_NAMES)
|
|
49
|
+
.describe('Predicate it must end in (route, net, state), asserted after.'),
|
|
50
|
+
maxSteps: stepCountSchema
|
|
34
51
|
.optional()
|
|
35
|
-
.describe('
|
|
52
|
+
.describe('Ceiling on model turns; the drive is graded however it ends.'),
|
|
36
53
|
sessionId: z
|
|
37
54
|
.string()
|
|
38
55
|
.optional()
|
|
39
56
|
.describe('Active session ID from reticle_sessions. Omit when only one browser session is open.'),
|
|
57
|
+
driveId: z.string().optional(),
|
|
58
|
+
// Bare on purpose: the description and every `running` answer say how to poll, and this
|
|
59
|
+
// schema is re-sent on every turn of every session.
|
|
60
|
+
wait: z.number().min(0).max(WAIT_MAX_S).optional().describe('Seconds; default 50.'),
|
|
61
|
+
runId: z.string().optional(),
|
|
62
|
+
planId: z.string().optional().describe('Run a plan saved on the dashboard, as it stands.'),
|
|
63
|
+
stop: z.boolean().optional(),
|
|
64
|
+
say: z.string().optional(),
|
|
40
65
|
},
|
|
41
66
|
// Everything the handler returns has to be declared, or a schema-aware client never sees it.
|
|
67
|
+
// Optional throughout: a drive still running answers only its status, id and progress.
|
|
42
68
|
outputSchema: {
|
|
43
|
-
|
|
69
|
+
/** running | done | stopped | broken. */
|
|
70
|
+
status: z.string().optional(),
|
|
71
|
+
/** The drive's run (`harness-<uuid>`), known from the moment it starts. Poll with it. */
|
|
72
|
+
runId: z.string().optional(),
|
|
73
|
+
/** The drive's latest step or narrated line, while it runs. */
|
|
74
|
+
lastLine: z.string().optional(),
|
|
75
|
+
/** The call that reads this drive again. */
|
|
76
|
+
next: z.object({ action: z.string(), runId: z.string() }).optional(),
|
|
77
|
+
/** Seconds since the drive started, while it runs. */
|
|
78
|
+
elapsedS: z.number().optional(),
|
|
79
|
+
/** While it runs: poll again with the same call; stopping never stops the drive. */
|
|
80
|
+
instruction: z.string().optional(),
|
|
81
|
+
stopReason: z.string().optional(),
|
|
44
82
|
/** Which driver actually drove, so a comparison can never misattribute its own result. */
|
|
45
|
-
driver: z.string(),
|
|
46
|
-
steps: z.number(),
|
|
47
|
-
savedFlows: z.array(z.string()),
|
|
83
|
+
driver: z.string().optional(),
|
|
84
|
+
steps: z.number().optional(),
|
|
85
|
+
savedFlows: z.array(z.string()).optional(),
|
|
48
86
|
/** Flows that already existed and were driven and written again. A second run's ordinary result. */
|
|
49
|
-
rewroteFlows: z.array(z.string()),
|
|
87
|
+
rewroteFlows: z.array(z.string()).optional(),
|
|
88
|
+
/** Saved flows with no step that asserts anything: their replay verifies nothing. */
|
|
89
|
+
unverifiedFlows: z.array(z.string()).optional(),
|
|
90
|
+
/** Whether the drive ran at least one check. A drive that did not proved nothing. */
|
|
91
|
+
proved: z.boolean().optional(),
|
|
92
|
+
/**
|
|
93
|
+
* Whether every journey reached its goal, as the platform judged when the drive finished.
|
|
94
|
+
* Absent when no journey's goal was judged. Checks that held are not the goal reached.
|
|
95
|
+
*/
|
|
96
|
+
goalMet: z.boolean().optional(),
|
|
97
|
+
/** How the drive's checks came out, one per control and claim at its worst. */
|
|
98
|
+
checks: z.object({ held: z.number(), failed: z.number(), undecided: z.number() }).optional(),
|
|
99
|
+
/** The runs this drive syncs as (`harness-<uuid>`): what the platform links its check to. */
|
|
100
|
+
runIds: z.array(z.string()).optional(),
|
|
101
|
+
/** The run's page on the dashboard, when the project is linked. Give it to the user. */
|
|
102
|
+
runUrl: z.string().optional(),
|
|
103
|
+
/** The saved plan this run drove: the dashboard keeps it, edits it and runs it again. */
|
|
104
|
+
planId: z.string().optional(),
|
|
105
|
+
planUrl: z.string().optional(),
|
|
106
|
+
/** The credits the platform says this run spent. */
|
|
107
|
+
creditsSpent: z.number().optional(),
|
|
108
|
+
/** One verdict per requested goal, checked by the harness itself. Only `yes` is proved. */
|
|
109
|
+
goals: z
|
|
110
|
+
.array(z.object({ text: z.string(), verified: z.string(), reason: z.string().optional() }))
|
|
111
|
+
.optional(),
|
|
50
112
|
/**
|
|
51
113
|
* What the drive set out to do, read from `.reticle` BEFORE it started — every recorded
|
|
52
114
|
* journey with the consequence that must still hold, and the declared intent nobody has
|
|
53
115
|
* tested. Returned so the caller can see the drive was aimed rather than wandering.
|
|
54
116
|
*/
|
|
55
|
-
plan: z.object({ summary: z.string(), steps: z.array(z.unknown()) }),
|
|
117
|
+
plan: z.object({ summary: z.string(), steps: z.array(z.unknown()) }).optional(),
|
|
56
118
|
/**
|
|
57
119
|
* What the drive did, derived from the calls it made and the verdicts the engine returned.
|
|
58
120
|
*
|
|
59
121
|
* Not the driver's narration. A driver that cannot write a sentence used to leave this empty,
|
|
60
122
|
* and a driver that can is the one witness with a reason to round "unknown" up to "worked".
|
|
61
123
|
*/
|
|
62
|
-
summary: z.string(),
|
|
124
|
+
summary: z.string().optional(),
|
|
125
|
+
/**
|
|
126
|
+
* The driver's own account, alone. The platform's driver says here why a drive checked nothing
|
|
127
|
+
* at its end, which a caller that only shows the verdict otherwise cannot tell anybody.
|
|
128
|
+
*/
|
|
129
|
+
driverAccount: z.string().optional(),
|
|
63
130
|
/** Present when the drive broke: a model that would not answer, a wedged browser. */
|
|
64
131
|
error: z.string().optional(),
|
|
65
132
|
/** What the drive cost, cache hits included, so an expensive run is visible rather than felt. */
|
|
66
|
-
usage: z
|
|
133
|
+
usage: z
|
|
134
|
+
.object({
|
|
67
135
|
input: z.number(),
|
|
68
136
|
output: z.number(),
|
|
69
137
|
cacheRead: z.number(),
|
|
70
138
|
cacheWrite: z.number(),
|
|
71
|
-
})
|
|
139
|
+
})
|
|
140
|
+
.optional(),
|
|
72
141
|
/** Said out loud when a drive recorded nothing, because that is not a verified app. */
|
|
73
142
|
note: z.string().optional(),
|
|
143
|
+
/**
|
|
144
|
+
* Each journey of a platform plan and how it ended. Only `passed` is proved. `by`: its saved
|
|
145
|
+
* flows replayed (no model) or the model drove it; `tokens`: what the model spent on it.
|
|
146
|
+
*/
|
|
147
|
+
[RESULT_FIELD]: z.string().optional(),
|
|
148
|
+
journeys: z
|
|
149
|
+
.array(z.object({
|
|
150
|
+
title: z.string(),
|
|
151
|
+
status: z.string(),
|
|
152
|
+
by: z.string().optional(),
|
|
153
|
+
tokens: z.number().optional(),
|
|
154
|
+
}))
|
|
155
|
+
.optional(),
|
|
74
156
|
},
|
|
75
|
-
handler:
|
|
76
|
-
// The credential `reticle link` already filed counts as configured, so somebody who has
|
|
77
|
-
// signed in and linked does not also have to export a key by hand.
|
|
78
|
-
const env = await withLinkedCredential(deps, process.env);
|
|
79
|
-
if (!harnessAvailable(env))
|
|
80
|
-
throw new Error(MSG_NO_HARNESS_KEY);
|
|
81
|
-
const persona = args['persona'];
|
|
82
|
-
const maxSteps = args['maxSteps'];
|
|
83
|
-
const sessionId = args['sessionId'];
|
|
84
|
-
const driver = args['driver'];
|
|
85
|
-
const { drive, savedFlows, rewroteFlows, driverName, plan } = await exploreApp(deps, env, {
|
|
86
|
-
...('string' === typeof persona ? { focus: persona } : {}),
|
|
87
|
-
...('number' === typeof maxSteps ? { maxSteps } : {}),
|
|
88
|
-
...('string' === typeof sessionId ? { sessionId } : {}),
|
|
89
|
-
...('string' === typeof driver ? { driverName: driver } : {}),
|
|
90
|
-
});
|
|
91
|
-
return {
|
|
92
|
-
stopReason: drive.stopReason,
|
|
93
|
-
driver: driverName,
|
|
94
|
-
steps: drive.steps,
|
|
95
|
-
savedFlows: [...savedFlows],
|
|
96
|
-
rewroteFlows: [...rewroteFlows],
|
|
97
|
-
plan: { summary: plan.summary, steps: [...plan.steps] },
|
|
98
|
-
// Derived, not narrated. The driver's own `summary` is appended only when it said
|
|
99
|
-
// something — it is the one part of this a model authored, so it goes last and is labelled.
|
|
100
|
-
summary: [
|
|
101
|
-
describeDrive(drive.toolCalls, [...savedFlows, ...rewroteFlows]),
|
|
102
|
-
...(0 === drive.summary.length ? [] : [`The driver's own account: ${drive.summary}`]),
|
|
103
|
-
].join('\n'),
|
|
104
|
-
...(drive.error === undefined ? {} : { error: drive.error }),
|
|
105
|
-
usage: drive.usage,
|
|
106
|
-
// The note only fires when the drive left NOTHING behind. A rewritten flow is a flow: it
|
|
107
|
-
// replays, it proves what it asserts, and telling its author that "nothing will replay" is
|
|
108
|
-
// a lie this tool used to tell on every second run.
|
|
109
|
-
/*
|
|
110
|
-
* The note fires only when the run left NOTHING behind — and a run that REPLAYED left
|
|
111
|
-
* plenty. Sixteen recorded journeys re-proved for zero model tokens is the cheap half of
|
|
112
|
-
* the plan doing its job, and telling its author to "raise maxSteps" reads as a failure.
|
|
113
|
-
*/
|
|
114
|
-
...(0 === savedFlows.length &&
|
|
115
|
-
0 === rewroteFlows.length &&
|
|
116
|
-
0 === replayedFlows(drive.toolCalls).length
|
|
117
|
-
? { note: `${NOTHING_RECORDED[drive.stopReason]}${failureDetail(drive)}` }
|
|
118
|
-
: {}),
|
|
119
|
-
};
|
|
120
|
-
},
|
|
157
|
+
handler: (deps, args, call) => answerExplore(deps, args, call, exploreDrive),
|
|
121
158
|
},
|
|
122
159
|
];
|
|
160
|
+
const MS_PER_S = 1000;
|
|
161
|
+
export const MSG_ALREADY_DRIVING = 'A Harness drive is already running on this app; this is that drive. Poll it by runId; do not start another.';
|
|
162
|
+
const msgNoDrive = (runId) => `No Harness drive ${runId} on this machine, and no linked platform to ask for it.`;
|
|
163
|
+
const str = (v) => ('string' === typeof v ? v : undefined);
|
|
164
|
+
/**
|
|
165
|
+
* Start a drive and wait on it for a while, or poll, stop or speak to one by `runId`.
|
|
166
|
+
*
|
|
167
|
+
* The drive itself never runs inside the call: it is started in the registry and the call waits up
|
|
168
|
+
* to `wait` seconds, so a client's timeout loses nothing. A second start on the same app answers
|
|
169
|
+
* with the drive already running rather than paying for another.
|
|
170
|
+
*/
|
|
171
|
+
export async function answerExplore(deps, args, call, drive) {
|
|
172
|
+
const wait = args['wait'];
|
|
173
|
+
const waitMs = MS_PER_S *
|
|
174
|
+
Math.min(WAIT_MAX_S, Math.max(0, 'number' === typeof wait ? wait : POLL_WAIT_DEFAULT_S));
|
|
175
|
+
const sessionId = str(args['sessionId']);
|
|
176
|
+
const asked = str(args['runId']);
|
|
177
|
+
if (asked !== undefined) {
|
|
178
|
+
if (true === args['stop'])
|
|
179
|
+
stopDrive(asked);
|
|
180
|
+
const say = str(args['say']);
|
|
181
|
+
if (say !== undefined)
|
|
182
|
+
sayToDrive(asked, say);
|
|
183
|
+
return answerDrive(deps, asked, waitMs, call, sessionId, false);
|
|
184
|
+
}
|
|
185
|
+
const running = runningDrive(sessionId);
|
|
186
|
+
if (running !== undefined) {
|
|
187
|
+
const answer = await answerDrive(deps, running.harnessRun, waitMs, call, sessionId, false);
|
|
188
|
+
return { ...asRecord(answer), note: MSG_ALREADY_DRIVING };
|
|
189
|
+
}
|
|
190
|
+
// The credential `reticle link` already filed counts as configured, so somebody who has
|
|
191
|
+
// signed in and linked does not also have to export a key by hand.
|
|
192
|
+
const driveId = args['driveId'];
|
|
193
|
+
const env = {
|
|
194
|
+
// The driven tab's project: the plan it saves and the runs it syncs land in one place.
|
|
195
|
+
...(await withLinkedCredential(deps, process.env, { sessionId })),
|
|
196
|
+
// Billed to the one free drive the platform granted, never to another.
|
|
197
|
+
...('string' === typeof driveId ? { [ReticleEnv.DRIVE_ID]: driveId } : {}),
|
|
198
|
+
};
|
|
199
|
+
// The coverage gate first: it is local, and the one thing to fix before anything else matters.
|
|
200
|
+
// Not for a saved plan that only replays flows (no model turn to guard), and a plan it refuses
|
|
201
|
+
// is told so, so the plan's history records the attempt.
|
|
202
|
+
const planId = str(args['planId']);
|
|
203
|
+
const platform = serverOptionsFromEnv(env);
|
|
204
|
+
const replayOnly = planId !== undefined &&
|
|
205
|
+
platform !== undefined &&
|
|
206
|
+
(await savedPlanDrivesNothing(platform, planId));
|
|
207
|
+
// In-process callers name their origin. Over MCP nothing can (the schema does not carry it), and
|
|
208
|
+
// a granted free drive with no origin is `reticle try`'s: the HUD's own grant says HUD.
|
|
209
|
+
const origin = Object.values(DriveOrigin).find((o) => o === args['origin']) ??
|
|
210
|
+
('string' === typeof driveId ? DriveOrigin.TRY : DriveOrigin.AGENT);
|
|
211
|
+
// Hosted: the platform drives (the only driver this build ships), as opposed to an injected one.
|
|
212
|
+
const runStart = {
|
|
213
|
+
source: harnessRunSource(origin, planId),
|
|
214
|
+
hosted: platform !== undefined,
|
|
215
|
+
};
|
|
216
|
+
const locked = replayOnly ? undefined : await harnessLockRefusal(deps, sessionId, env);
|
|
217
|
+
if (locked !== undefined)
|
|
218
|
+
reportHarnessBlocked(runStart);
|
|
219
|
+
if (locked !== undefined) {
|
|
220
|
+
if (planId !== undefined && platform !== undefined)
|
|
221
|
+
await reportPlanBlocked(platform, planId, firstLine(locked));
|
|
222
|
+
throw new Error(locked);
|
|
223
|
+
}
|
|
224
|
+
if (!harnessAvailable(env)) {
|
|
225
|
+
reportHarnessBlocked(runStart);
|
|
226
|
+
throw new Error(MSG_NO_HARNESS_KEY);
|
|
227
|
+
}
|
|
228
|
+
const harness = randomUUID();
|
|
229
|
+
const runId = harnessRunId(harness);
|
|
230
|
+
if (runId === undefined)
|
|
231
|
+
throw new Error(`could not name a run for drive ${harness}`);
|
|
232
|
+
startDrive({
|
|
233
|
+
harness,
|
|
234
|
+
runId,
|
|
235
|
+
origin,
|
|
236
|
+
...(sessionId === undefined ? {} : { sessionId }),
|
|
237
|
+
now: deps.now,
|
|
238
|
+
persist: (record) => writeDriveFile(deps, sessionId, record),
|
|
239
|
+
run: (control) => reportHarnessRun(runStart, () => drive(deps, env, args, harness, control), (error) => error instanceof DriveRefusedError),
|
|
240
|
+
});
|
|
241
|
+
// A drive refused before it began (switched off, unentitled) is still a refusal to the caller.
|
|
242
|
+
return answerDrive(deps, runId, waitMs, call, sessionId, true);
|
|
243
|
+
}
|
|
244
|
+
/** Wait, then answer with the drive as it stands: running, its full result, or why it broke. */
|
|
245
|
+
async function answerDrive(deps, runId, waitMs, call, sessionId, refuseBroken) {
|
|
246
|
+
const progress = call?.progress;
|
|
247
|
+
await awaitDrive(runId, waitMs, call?.signal, progress === undefined ? undefined : (r) => progress(r.steps, r.lastLine));
|
|
248
|
+
const record = driveRecord(runId) ?? (await readDriveFile(deps, sessionId, runId));
|
|
249
|
+
if (record === undefined)
|
|
250
|
+
return fromPlatform(deps, runId);
|
|
251
|
+
if (DriveStatus.RUNNING === record.status) {
|
|
252
|
+
const elapsedS = Math.max(0, Math.round((deps.now() - record.startedAt) / MS_PER_S));
|
|
253
|
+
return {
|
|
254
|
+
status: record.status,
|
|
255
|
+
runId,
|
|
256
|
+
steps: record.steps,
|
|
257
|
+
lastLine: record.lastLine,
|
|
258
|
+
elapsedS,
|
|
259
|
+
next: { action: 'explore', runId },
|
|
260
|
+
instruction: stillRunning(runId, record.steps, elapsedS),
|
|
261
|
+
};
|
|
262
|
+
}
|
|
263
|
+
if (record.result !== undefined)
|
|
264
|
+
return { status: record.status, runId, ...record.result };
|
|
265
|
+
if (refuseBroken && record.error !== undefined)
|
|
266
|
+
throw new Error(record.error);
|
|
267
|
+
return { status: record.status, runId, steps: record.steps, error: record.error ?? 'no result' };
|
|
268
|
+
}
|
|
269
|
+
/** A run this machine no longer holds, from the platform it synced to. */
|
|
270
|
+
async function fromPlatform(deps, runId) {
|
|
271
|
+
const platform = serverOptionsFromEnv(await withLinkedCredential(deps, process.env));
|
|
272
|
+
if (platform === undefined)
|
|
273
|
+
throw new Error(msgNoDrive(runId));
|
|
274
|
+
const got = await fetchPlatformRun(platform, runId);
|
|
275
|
+
if ('error' in got)
|
|
276
|
+
throw new Error(got.error);
|
|
277
|
+
return platformRunAnswer(runId, got.run);
|
|
278
|
+
}
|
|
279
|
+
/** Where the drive's record lives: its session's own project, never wherever the daemon started. */
|
|
280
|
+
function driveFile(deps, sessionId, runId) {
|
|
281
|
+
return join(reticleDirPaths(sessionRoot(deps, sessionId)).runs, `${runId}${DRIVE_RECORD_SUFFIX}`);
|
|
282
|
+
}
|
|
283
|
+
/** `.reticle/runs/<run>.drive.json`: a new session or a restarted daemon can still read the drive. */
|
|
284
|
+
async function writeDriveFile(deps, sessionId, record) {
|
|
285
|
+
const path = driveFile(deps, sessionId, record.harnessRun);
|
|
286
|
+
await deps.fs.mkdir(join(path, '..'));
|
|
287
|
+
await deps.fs.writeFile(path, `${JSON.stringify(record, null, 2)}\n`);
|
|
288
|
+
}
|
|
289
|
+
async function readDriveFile(deps, sessionId, runId) {
|
|
290
|
+
try {
|
|
291
|
+
const parsed = asRecord(JSON.parse(await deps.fs.readFile(driveFile(deps, sessionId, runId))));
|
|
292
|
+
const status = Object.values(DriveStatus).find((s) => s === parsed['status']);
|
|
293
|
+
if (status === undefined || runId !== parsed['harnessRun'])
|
|
294
|
+
return undefined;
|
|
295
|
+
// A record left `running` by a daemon that has since gone will never finish.
|
|
296
|
+
const lost = DriveStatus.RUNNING === status;
|
|
297
|
+
return {
|
|
298
|
+
...parsed,
|
|
299
|
+
status: lost ? DriveStatus.BROKEN : status,
|
|
300
|
+
...(lost ? { error: MSG_DRIVE_LOST } : {}),
|
|
301
|
+
};
|
|
302
|
+
}
|
|
303
|
+
catch {
|
|
304
|
+
return undefined;
|
|
305
|
+
}
|
|
306
|
+
}
|
|
307
|
+
const MSG_DRIVE_LOST = 'The daemon that ran this drive stopped before it finished; what it drove up to then is kept.';
|
|
308
|
+
/** How a drive ended, as the registry records it. */
|
|
309
|
+
function statusOf(stopReason) {
|
|
310
|
+
if (StopReason.STOPPED === stopReason)
|
|
311
|
+
return DriveStatus.STOPPED;
|
|
312
|
+
if (StopReason.BROKEN === stopReason)
|
|
313
|
+
return DriveStatus.BROKEN;
|
|
314
|
+
return DriveStatus.DONE;
|
|
315
|
+
}
|
|
316
|
+
/** The shipped drive: `exploreApp`, steered by the registry, reported as the tool's answer. */
|
|
317
|
+
const exploreDrive = async (deps, env, args, harness, control) => {
|
|
318
|
+
const persona = args['persona'];
|
|
319
|
+
// Only a run a person started may carry the acknowledgement; an agent's drive keeps the guard.
|
|
320
|
+
const confirmDangerous = true === args['confirmDangerous'] &&
|
|
321
|
+
DriveOrigin.AGENT !==
|
|
322
|
+
(Object.values(DriveOrigin).find((o) => o === args['origin']) ?? DriveOrigin.AGENT);
|
|
323
|
+
const maxSteps = args['maxSteps'];
|
|
324
|
+
const sessionId = args['sessionId'];
|
|
325
|
+
const expect = args['expect'];
|
|
326
|
+
const planId = args['planId'];
|
|
327
|
+
const explored = await exploreApp(deps, env, {
|
|
328
|
+
...('string' === typeof planId ? { planId } : {}),
|
|
329
|
+
...(confirmDangerous ? { confirmDangerous } : {}),
|
|
330
|
+
...('string' === typeof persona ? { focus: persona } : {}),
|
|
331
|
+
...('number' === typeof maxSteps ? { maxSteps } : {}),
|
|
332
|
+
...('string' === typeof sessionId ? { sessionId } : {}),
|
|
333
|
+
...(isRecord(expect) ? { expect } : {}),
|
|
334
|
+
harnessId: harness,
|
|
335
|
+
stopped: control.stopped,
|
|
336
|
+
inbox: control.takeSaid,
|
|
337
|
+
});
|
|
338
|
+
const result = exploreReport(explored);
|
|
339
|
+
return {
|
|
340
|
+
status: statusOf(explored.drive.stopReason),
|
|
341
|
+
result: {
|
|
342
|
+
...result,
|
|
343
|
+
...resultField(() => exploreResult(sessionRoot(deps, 'string' === typeof sessionId ? sessionId : undefined), {
|
|
344
|
+
checks: checkTally(explored.drive.toolCalls),
|
|
345
|
+
goals: explored.goals,
|
|
346
|
+
...(explored.drive.goalMet === undefined ? {} : { goalMet: explored.drive.goalMet }),
|
|
347
|
+
...(explored.journeys === undefined ? {} : { journeys: explored.journeys }),
|
|
348
|
+
...(explored.runIds === undefined ? {} : { runIds: explored.runIds }),
|
|
349
|
+
})),
|
|
350
|
+
},
|
|
351
|
+
};
|
|
352
|
+
};
|
|
353
|
+
/** The tool's answer for a finished drive. */
|
|
354
|
+
export function exploreReport(explored) {
|
|
355
|
+
const { drive, savedFlows, rewroteFlows, unverifiedFlows, driverName, plan, goals, planLines, runIds, runUrl, journeys, planId, planUrl, disparity, } = explored;
|
|
356
|
+
const checks = checkTally(drive.toolCalls);
|
|
357
|
+
return {
|
|
358
|
+
stopReason: drive.stopReason,
|
|
359
|
+
driver: driverName,
|
|
360
|
+
steps: drive.steps,
|
|
361
|
+
savedFlows: [...savedFlows],
|
|
362
|
+
rewroteFlows: [...rewroteFlows],
|
|
363
|
+
unverifiedFlows: [...unverifiedFlows],
|
|
364
|
+
// The headline's own word, so the answer never says NOT PROVED beside `proved: true`.
|
|
365
|
+
proved: runProved(checks, drive.goalMet, journeys),
|
|
366
|
+
checks,
|
|
367
|
+
...(drive.goalMet === undefined ? {} : { goalMet: drive.goalMet }),
|
|
368
|
+
...(runIds === undefined ? {} : { runIds: [...runIds] }),
|
|
369
|
+
// Where the user sees this run, and what it cost: the two things an agent is asked after a run.
|
|
370
|
+
...(runUrl === undefined ? {} : { runUrl }),
|
|
371
|
+
...(planId === undefined ? {} : { planId }),
|
|
372
|
+
...(planUrl === undefined ? {} : { planUrl }),
|
|
373
|
+
...(drive.creditsSpent === undefined ? {} : { creditsSpent: drive.creditsSpent }),
|
|
374
|
+
...(journeys === undefined
|
|
375
|
+
? {}
|
|
376
|
+
: {
|
|
377
|
+
journeys: journeys.map((j) => ({
|
|
378
|
+
title: j.title,
|
|
379
|
+
status: j.status,
|
|
380
|
+
...(j.by === undefined ? {} : { by: j.by }),
|
|
381
|
+
...(j.tokens === undefined ? {} : { tokens: j.tokens }),
|
|
382
|
+
})),
|
|
383
|
+
}),
|
|
384
|
+
goals: [...goals],
|
|
385
|
+
// Each goal the agent also judged, compared: agent proved and Harness could not find is a
|
|
386
|
+
// discoverability finding, filed on the platform as its own kind.
|
|
387
|
+
...(disparity === undefined ? {} : { disparity: [...disparity] }),
|
|
388
|
+
// The local plan only when nothing else planned the drive. Beside a platform plan's journeys it
|
|
389
|
+
// was a second, unrelated plan — fifteen replays of other people's flows — in the same answer.
|
|
390
|
+
...(journeys === undefined ? { plan: { summary: plan.summary, steps: [...plan.steps] } } : {}),
|
|
391
|
+
// Derived, not narrated. The driver's own account stays out of it, in `driverAccount`: it
|
|
392
|
+
// named flows it never saved ("saved 1 flow(s)" beside "its recording was not saved"), and a
|
|
393
|
+
// summary must never contradict itself.
|
|
394
|
+
summary: [
|
|
395
|
+
...(planLines ?? []),
|
|
396
|
+
describeDrive(drive.toolCalls, [...savedFlows, ...rewroteFlows], unverifiedFlows, drive.goalMet, journeys),
|
|
397
|
+
...[unprovedGoals(goals)].filter((line) => line !== undefined),
|
|
398
|
+
].join('\n'),
|
|
399
|
+
// Not beside a platform plan: its lanes' accounts count saves the platform asked for ("saved 3
|
|
400
|
+
// flow(s)") where `savedFlows` lists what is on disk, and an answer has one count. Each journey's
|
|
401
|
+
// ending is in `journeys`, and the end state in `goals`.
|
|
402
|
+
...(0 === drive.summary.length || journeys !== undefined
|
|
403
|
+
? {}
|
|
404
|
+
: { driverAccount: drive.summary }),
|
|
405
|
+
...(drive.error === undefined ? {} : { error: drive.error }),
|
|
406
|
+
usage: drive.usage,
|
|
407
|
+
// The note only fires when the drive left NOTHING behind. A rewritten flow is a flow: it
|
|
408
|
+
// replays, it proves what it asserts, and telling its author that "nothing will replay" is
|
|
409
|
+
// a lie this tool used to tell on every second run.
|
|
410
|
+
/*
|
|
411
|
+
* The note fires only when the run left NOTHING behind — and a run that REPLAYED left
|
|
412
|
+
* plenty. Sixteen recorded journeys re-proved for zero model tokens is the cheap half of
|
|
413
|
+
* the plan doing its job, and telling its author to "raise maxSteps" reads as a failure.
|
|
414
|
+
*/
|
|
415
|
+
// A persona drive's advice: a plan run's journeys already say how each went.
|
|
416
|
+
...(journeys === undefined &&
|
|
417
|
+
0 === savedFlows.length &&
|
|
418
|
+
0 === rewroteFlows.length &&
|
|
419
|
+
0 === replayedFlows(drive.toolCalls).length
|
|
420
|
+
? { note: `${NOTHING_RECORDED[drive.stopReason]}${failureDetail(drive)}` }
|
|
421
|
+
: {}),
|
|
422
|
+
};
|
|
423
|
+
}
|
|
123
424
|
/**
|
|
124
425
|
* The tool failure behind an empty drive, when there was one.
|
|
125
426
|
*
|
|
@@ -159,4 +460,75 @@ const NOTHING_RECORDED = {
|
|
|
159
460
|
[StopReason.BUDGET]: 'The drive ran out of steps before saving a flow. Raise `maxSteps`, or give it a narrower `persona` so it spends the budget on one journey.',
|
|
160
461
|
[StopReason.STALLED]: 'The drive stopped asking for tools without finishing. Nothing was saved, and nothing is proved.',
|
|
161
462
|
[StopReason.BROKEN]: 'The drive broke before saving anything — read `error`. Nothing is proved.',
|
|
463
|
+
[StopReason.STOPPED]: 'Autonomous driving was switched off before the drive saved anything. Nothing is proved; switch it back on to drive again.',
|
|
162
464
|
};
|
|
465
|
+
/**
|
|
466
|
+
* The full answer of a drive a start left running: the chat answers once, so it waits for the end.
|
|
467
|
+
* Waited on the registry rather than by polling the tool, which would count every poll as a call.
|
|
468
|
+
*/
|
|
469
|
+
async function driveToEnd(out) {
|
|
470
|
+
const runId = out['runId'];
|
|
471
|
+
if (DriveStatus.RUNNING !== out['status'] || 'string' !== typeof runId)
|
|
472
|
+
return out;
|
|
473
|
+
await awaitDrive(runId, undefined);
|
|
474
|
+
const record = driveRecord(runId);
|
|
475
|
+
if (record?.result !== undefined)
|
|
476
|
+
return { status: record.status, runId, ...record.result };
|
|
477
|
+
return {
|
|
478
|
+
status: record?.status,
|
|
479
|
+
runId,
|
|
480
|
+
error: record?.error ?? 'the drive ended with no result',
|
|
481
|
+
};
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* A drive the platform's chat asked for, run as the very tool an agent would call.
|
|
485
|
+
*
|
|
486
|
+
* Through `runTool`, not a second path to `exploreApp`: a dispatch that skips it is a drive nobody
|
|
487
|
+
* counted, and the chat's answer is then the same derived summary the agent would have read — never
|
|
488
|
+
* a model's account of its own drive.
|
|
489
|
+
*/
|
|
490
|
+
export async function driveForChat(deps, goal, sessionId, planId,
|
|
491
|
+
/** The person who started it acknowledged the saved flows' destructive steps. */
|
|
492
|
+
confirmDangerous) {
|
|
493
|
+
const explore = EXPLORE_TOOLS.find((tool) => ReticleTool.VERIFY_EXPLORE === tool.name);
|
|
494
|
+
if (explore === undefined)
|
|
495
|
+
throw new Error('this build has no Harness drive');
|
|
496
|
+
const out = await driveToEnd(asRecord(await runTool(explore, deps, {
|
|
497
|
+
// A saved plan carries its own journeys: the request's words are only its label.
|
|
498
|
+
...(planId === undefined ? { persona: goal } : { planId }),
|
|
499
|
+
origin: DriveOrigin.CHAT,
|
|
500
|
+
...(sessionId === undefined ? {} : { sessionId }),
|
|
501
|
+
...(true === confirmDangerous ? { confirmDangerous } : {}),
|
|
502
|
+
})));
|
|
503
|
+
const summary = 'string' === typeof out['summary'] ? out['summary'] : '';
|
|
504
|
+
const error = 'string' === typeof out['error'] ? out['error'] : undefined;
|
|
505
|
+
const note = 'string' === typeof out['note'] ? out['note'] : undefined;
|
|
506
|
+
const goals = Array.isArray(out['goals'])
|
|
507
|
+
? out['goals'].flatMap((g) => {
|
|
508
|
+
const verified = asRecord(g)['verified'];
|
|
509
|
+
return 'string' === typeof verified ? [{ verified }] : [];
|
|
510
|
+
})
|
|
511
|
+
: [];
|
|
512
|
+
const goalMet = out['goalMet'];
|
|
513
|
+
const tally = asRecord(out['checks']);
|
|
514
|
+
const count = (key) => ('number' === typeof tally[key] ? tally[key] : 0);
|
|
515
|
+
const checks = { held: count('held'), failed: count('failed'), undecided: count('undecided') };
|
|
516
|
+
const runIds = Array.isArray(out['runIds'])
|
|
517
|
+
? out['runIds'].filter((id) => 'string' === typeof id)
|
|
518
|
+
: [];
|
|
519
|
+
return {
|
|
520
|
+
// Only a drive that ran a check and did not break counts as one that proved anything.
|
|
521
|
+
ok: true === out['proved'] && error === undefined,
|
|
522
|
+
...(0 === runIds.length ? {} : { runIds }),
|
|
523
|
+
verdict: driveVerdict({
|
|
524
|
+
proved: true === out['proved'],
|
|
525
|
+
checks,
|
|
526
|
+
goals,
|
|
527
|
+
...(error === undefined ? {} : { error }),
|
|
528
|
+
...('boolean' === typeof goalMet ? { goalMet } : {}),
|
|
529
|
+
}),
|
|
530
|
+
summary: [summary, note, error === undefined ? undefined : `Error: ${error}`]
|
|
531
|
+
.filter((line) => line !== undefined && 0 < line.length)
|
|
532
|
+
.join('\n'),
|
|
533
|
+
};
|
|
534
|
+
}
|
|
@@ -20,9 +20,8 @@ declare const FEEDBACK_PROMPT: {
|
|
|
20
20
|
* outputSchema, returns the whole verdict block, and its own description calls it "one hop for the
|
|
21
21
|
* act->observe->assert loop" — it IS the verification path most agents take. The guard that should
|
|
22
22
|
* have caught the omission keyed on the tool NAME (/assert|verify/), which act_and_wait does not
|
|
23
|
-
* match, so it slipped through in silence
|
|
24
|
-
*
|
|
25
|
-
* could not see it. The contract test now checks the SHAPE instead.
|
|
23
|
+
* match, so it slipped through in silence: agents verified through act_and_wait the entire time,
|
|
24
|
+
* and the metric could not see it. The contract test now checks the SHAPE instead.
|
|
26
25
|
*/
|
|
27
26
|
export declare const VERDICT_TOOLS: ReadonlySet<string>;
|
|
28
27
|
/**
|
|
@@ -17,6 +17,17 @@ import { ReticleTool } from '@reticlehq/core';
|
|
|
17
17
|
import { asNumber, asString } from '@reticlehq/core';
|
|
18
18
|
import { submitFeedback, feedbackDisabled } from '../../telemetry/feedback.js';
|
|
19
19
|
import { getTelemetry } from '../../telemetry/telemetry.js';
|
|
20
|
+
import { dirname } from 'node:path';
|
|
21
|
+
import { sessionRoot } from '../../memory/project/session-root.js';
|
|
22
|
+
/** The project folder this call's session belongs to, when one can be told. */
|
|
23
|
+
function projectDir(deps, sessionId) {
|
|
24
|
+
try {
|
|
25
|
+
return { cwd: dirname(sessionRoot(deps, sessionId)) };
|
|
26
|
+
}
|
|
27
|
+
catch {
|
|
28
|
+
return {};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
20
31
|
/** One optional string arg, present only when the agent actually supplied it. */
|
|
21
32
|
function optionalText(args, key) {
|
|
22
33
|
const value = asString(args[key]);
|
|
@@ -175,6 +186,9 @@ export const FEEDBACK_TOOLS = [
|
|
|
175
186
|
...optionalRating(args),
|
|
176
187
|
}, {
|
|
177
188
|
session: sessionFacts(deps, asString(args['sessionId'])),
|
|
189
|
+
// A report that cannot be sent is written into the project being verified, never into
|
|
190
|
+
// whatever folder the daemon happened to start in.
|
|
191
|
+
...projectDir(deps, asString(args['sessionId'])),
|
|
178
192
|
// The AGENT does not wait for the network. `reticle feedback` (a human, at a terminal,
|
|
179
193
|
// watching for an answer) still does — see submitFeedback's `background`.
|
|
180
194
|
background: true,
|
|
@@ -208,9 +222,8 @@ const FEEDBACK_PROMPT = {
|
|
|
208
222
|
* outputSchema, returns the whole verdict block, and its own description calls it "one hop for the
|
|
209
223
|
* act->observe->assert loop" — it IS the verification path most agents take. The guard that should
|
|
210
224
|
* have caught the omission keyed on the tool NAME (/assert|verify/), which act_and_wait does not
|
|
211
|
-
* match, so it slipped through in silence
|
|
212
|
-
*
|
|
213
|
-
* could not see it. The contract test now checks the SHAPE instead.
|
|
225
|
+
* match, so it slipped through in silence: agents verified through act_and_wait the entire time,
|
|
226
|
+
* and the metric could not see it. The contract test now checks the SHAPE instead.
|
|
214
227
|
*/
|
|
215
228
|
export const VERDICT_TOOLS = new Set([
|
|
216
229
|
ReticleTool.ACT_AND_WAIT,
|
|
@@ -220,6 +233,8 @@ export const VERDICT_TOOLS = new Set([
|
|
|
220
233
|
// here rather than six months from now in a metric that had quietly read low the whole time.
|
|
221
234
|
ReticleTool.ACT_SEQUENCE,
|
|
222
235
|
ReticleTool.ASSERT,
|
|
236
|
+
// `reticle_assert { action: "wait" }` lands here, and grades its answer as `assert` does.
|
|
237
|
+
ReticleTool.WAIT_FOR,
|
|
223
238
|
// Merged: `flow_verify` and `verify_change` are actions on this tool now. Naming the merged tool
|
|
224
239
|
// does NOT make every action a verification — `verificationOf` still requires the result to carry
|
|
225
240
|
// a `verified` or a pass/fail `status`, so `coverage` and `crawl` contribute nothing and cannot
|
|
@@ -31,7 +31,9 @@ interface GapLike {
|
|
|
31
31
|
* Returns a NEW array and never mutates its input — the same gap objects travel into telemetry and
|
|
32
32
|
* into the persisted capsule, and trimming those would lose the remedy where it is read cold.
|
|
33
33
|
*/
|
|
34
|
-
export declare function withGapNovelty<T extends GapLike>(sessionId: string | undefined, gaps: readonly T[]
|
|
34
|
+
export declare function withGapNovelty<T extends GapLike>(sessionId: string | undefined, gaps: readonly T[],
|
|
35
|
+
/** When the verdict was taken: stamps the gaps recorded for the app's coverage. */
|
|
36
|
+
now?: number): T[];
|
|
35
37
|
/** Forget a session. Called when a session ends so a long-lived daemon does not grow a map forever. */
|
|
36
38
|
export declare function forgetGapNovelty(sessionId: string): void;
|
|
37
39
|
/** Test seam: drop every session's memory. */
|