@reticlehq/server 3.6.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/SKILL.md +122 -123
- 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 +18 -2
- package/dist/command/cli/adhoc-verdict.js +70 -6
- 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/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 +28 -105
- 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 +34 -4
- package/dist/command/cli/cli-verify.js +81 -12
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +145 -333
- 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 +15 -1
- package/dist/command/cli/cloud-login.js +67 -13
- 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/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/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 +11 -2
- 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.js +1 -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 +29 -8
- 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 -178
- 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 +14 -0
- package/dist/command/cli.js +103 -83
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +9 -1
- package/dist/command/daemon/daemon-resolve.js +49 -10
- 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/dev-server-log-cap.js +2 -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 +10 -1
- package/dist/command/setup/init/init-port.js +22 -2
- package/dist/command/setup/init/init-runtime.d.ts +12 -2
- package/dist/command/setup/init/init-runtime.js +96 -37
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +36 -8
- 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 +1 -1
- package/dist/command/setup/run-setup.d.ts +29 -9
- package/dist/command/setup/run-setup.js +34 -28
- package/dist/command/setup/setup-command.d.ts +23 -0
- package/dist/command/setup/setup-command.js +57 -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 +38 -2
- package/dist/features/crawl/crawl.js +14 -1
- package/dist/features/exhaust/ledger.d.ts +14 -14
- package/dist/features/harness/drive-report.d.ts +39 -5
- package/dist/features/harness/drive-report.js +271 -54
- 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 +1 -1
- package/dist/features/harness/drivers.js +1 -1
- 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/goals.d.ts +68 -7
- package/dist/features/harness/goals.js +289 -36
- package/dist/features/harness/harness.d.ts +30 -1
- package/dist/features/harness/harness.js +141 -7
- package/dist/features/harness/platform/local-apps.d.ts +36 -3
- package/dist/features/harness/platform/local-apps.js +81 -5
- 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 +8 -2
- package/dist/features/harness/platform/remote-drive.js +22 -9
- package/dist/features/harness/platform/script.d.ts +57 -11
- package/dist/features/harness/platform/script.js +144 -12
- package/dist/features/harness/platform/server-driver.d.ts +17 -4
- package/dist/features/harness/platform/server-driver.js +29 -26
- package/dist/features/harness/platform-config.d.ts +38 -5
- package/dist/features/harness/platform-config.js +93 -8
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/script-run.d.ts +30 -1
- package/dist/features/harness/script/script-run.js +355 -48
- 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.js +22 -14
- 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 +21 -2
- package/dist/hooks/driven-by.js +42 -2
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -183
- 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 +20 -4
- 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.js +25 -9
- package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
- package/dist/judgement/runs/artifact/run-store.js +175 -8
- 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 +53 -5
- package/dist/judgement/runs/drive-run.js +234 -20
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +5 -2
- 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 +2 -0
- package/dist/judgement/runs/verification-sync.js +36 -15
- package/dist/language/flows/decision.js +2 -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 +7 -2
- package/dist/language/flows/flow-anchor.js +10 -3
- 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 +37 -3
- package/dist/language/flows/flow-replay-run.js +16 -18
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +18 -1
- package/dist/language/flows/flow-replay.js +22 -7
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-step-runners.d.ts +2 -0
- package/dist/language/flows/flow-step-runners.js +12 -6
- package/dist/language/flows/flow-store-for-session.js +5 -1
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +61 -62
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +69 -10
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
- package/dist/language/flows/recording/tape/recordings.js +60 -10
- package/dist/language/flows/replay.js +29 -6
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +200 -193
- package/dist/memory/cloud/cloud-config.d.ts +10 -1
- package/dist/memory/cloud/cloud-config.js +19 -5
- package/dist/memory/cloud/cloud-sync.js +3 -3
- package/dist/memory/cloud/harness-config.d.ts +49 -0
- package/dist/memory/cloud/harness-config.js +16 -20
- package/dist/memory/cloud/memory-scope.d.ts +17 -0
- package/dist/memory/cloud/memory-scope.js +22 -0
- package/dist/memory/cloud/sync-cycle.d.ts +32 -4
- package/dist/memory/cloud/sync-cycle.js +113 -12
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +114 -4
- package/dist/memory/cloud/sync-disk.js +26 -2
- 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 +16 -1
- package/dist/memory/impact/account-watch.js +26 -1
- package/dist/memory/impact/impact-store.d.ts +1 -4
- package/dist/memory/impact/impact-store.js +32 -42
- 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 +12 -0
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +42 -2
- 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/journal-recorder.js +46 -3
- package/dist/memory/journal/on-disk/retention.d.ts +5 -0
- package/dist/memory/journal/on-disk/retention.js +27 -2
- package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +38 -7
- package/dist/memory/project/artifact-root-resolver.js +33 -5
- package/dist/memory/project/artifact-root.d.ts +4 -3
- package/dist/memory/project/artifact-root.js +2 -2
- package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
- package/dist/memory/project/dir/reticle-dir.js +23 -2
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- 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 +2 -0
- package/dist/memory/project/session-root.js +9 -1
- package/dist/memory/project/sync-status.d.ts +46 -0
- package/dist/memory/project/sync-status.js +135 -1
- package/dist/memory/recall/memory-tools.js +46 -3
- 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.js +36 -8
- package/dist/portal/bridge/bridge.d.ts +9 -5
- package/dist/portal/bridge/bridge.js +66 -23
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -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 +2 -0
- package/dist/portal/input/real-input.js +13 -10
- package/dist/portal/pool/browser-pool.d.ts +48 -0
- package/dist/portal/pool/browser-pool.js +120 -2
- 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 +27 -5
- package/dist/portal/pool/playwright-launcher.js +59 -14
- package/dist/portal/pool/pool-contract.d.ts +21 -1
- 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.js +6 -1
- 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 +9 -0
- package/dist/portal/session/dev-server/dev-command.js +27 -1
- 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/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/live-control-tools.js +82 -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 +1 -1
- package/dist/portal/session/no-session-diagnosis.js +31 -9
- package/dist/portal/session/no-session-next-action.d.ts +20 -0
- package/dist/portal/session/no-session-next-action.js +134 -61
- package/dist/portal/session/no-session-watch.js +179 -22
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/session-health.d.ts +11 -0
- package/dist/portal/session/session-health.js +3 -1
- package/dist/portal/session/session-info.js +2 -1
- package/dist/portal/session/session-manager.d.ts +18 -0
- package/dist/portal/session/session-manager.js +54 -3
- package/dist/portal/session/session-successor.d.ts +8 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session.d.ts +15 -28
- package/dist/portal/session/session.js +60 -61
- 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 +7 -1
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +13 -1
- package/dist/status-payload.js +13 -1
- package/dist/surface/http-server.js +7 -1
- 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 +4 -0
- package/dist/surface/mcp/mcp-proxy.js +29 -8
- package/dist/surface/mcp/mcp.d.ts +23 -0
- package/dist/surface/mcp/mcp.js +34 -4
- 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.js +22 -14
- package/dist/surface/mcp/shared-params.js +1 -1
- 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/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-sequence-tool.js +136 -27
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +48 -34
- 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.js +25 -15
- package/dist/surface/tools/browser-tools.js +43 -1
- package/dist/surface/tools/chat-drives.d.ts +75 -0
- package/dist/surface/tools/chat-drives.js +265 -21
- 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 +10 -0
- package/dist/surface/tools/empty-session-list.js +45 -5
- package/dist/surface/tools/error-recovery.d.ts +8 -0
- package/dist/surface/tools/error-recovery.js +69 -5
- package/dist/surface/tools/explore-tools.d.ts +23 -2
- package/dist/surface/tools/explore-tools.js +377 -74
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +4 -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 +52 -73
- package/dist/surface/tools/harness-explore.js +177 -146
- 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 +5 -0
- package/dist/surface/tools/harness-plan.js +7 -0
- package/dist/surface/tools/harness-script.d.ts +22 -0
- package/dist/surface/tools/harness-script.js +256 -38
- 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 +8 -0
- package/dist/surface/tools/harness-toolset.js +27 -4
- 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 +220 -93
- 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 +20 -0
- package/dist/surface/tools/lease-seed.js +45 -1
- package/dist/surface/tools/lease-tools.d.ts +10 -1
- package/dist/surface/tools/lease-tools.js +119 -69
- package/dist/surface/tools/live-call-text.js +2 -2
- 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 +11 -1
- package/dist/surface/tools/next-step.js +73 -18
- package/dist/surface/tools/observe-tools.js +43 -5
- package/dist/surface/tools/platform-moment.d.ts +60 -0
- package/dist/surface/tools/platform-moment.js +132 -4
- package/dist/surface/tools/read-tools.js +65 -14
- 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 +68 -2
- package/dist/surface/tools/tool-kit.js +73 -1
- package/dist/surface/tools/tools.js +25 -13
- 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 +27 -6
- package/dist/telemetry/hud-metrics.js +99 -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 +26 -2
- package/dist/telemetry/telemetry.js +102 -21
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +12 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +16 -5
- package/docs/README.md +2 -2
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +24 -27
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +13 -12
- 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 +8 -3
- package/docs/cli/drive.mdx +12 -12
- 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 +32 -15
- 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 +13 -4
- 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 +3 -2
- package/docs/cli.mdx +110 -41
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +5 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +5 -2
- 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 +66 -64
- package/docs/human-control.md +15 -14
- package/docs/index.mdx +15 -43
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +22 -12
- 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 +8 -8
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +11 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +58 -29
- 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 +22 -24
- 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 +13 -4
- 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 +51 -45
- 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 +7 -5
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +6 -5
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -249
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- 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/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
|
@@ -11,25 +11,42 @@
|
|
|
11
11
|
* them deterministically with no model in the loop at all.
|
|
12
12
|
*/
|
|
13
13
|
import { z } from 'zod';
|
|
14
|
+
import { randomUUID } from 'node:crypto';
|
|
15
|
+
import { join } from 'node:path';
|
|
14
16
|
import { unprovedGoals } from '../../features/harness/goals.js';
|
|
15
|
-
import { ReticleTool, asRecord } from '@reticlehq/core';
|
|
17
|
+
import { ReticleEnv, ReticleTool, asRecord } from '@reticlehq/core';
|
|
16
18
|
import { stepCountSchema } from './args/numeric-bounds.js';
|
|
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';
|
|
17
27
|
import { runTool } from './invoke-tool.js';
|
|
28
|
+
import { harnessRunSource, reportHarnessBlocked, reportHarnessRun, } from '../../telemetry/harness-run.js';
|
|
18
29
|
import { driveVerdict } from '../../features/harness/platform/remote-drive.js';
|
|
19
|
-
import { exploreApp, harnessAvailable, withLinkedCredential, MSG_NO_HARNESS_KEY, } from './harness-explore.js';
|
|
30
|
+
import { harnessLockRefusal, firstLine, exploreApp, harnessAvailable, withLinkedCredential, MSG_NO_HARNESS_KEY, } from './harness-explore.js';
|
|
20
31
|
import { EXPLORE_NEEDS } from '../../features/harness/drivers.js';
|
|
21
|
-
import { checkTally, describeDrive, replayedFlows } from '../../features/harness/drive-report.js';
|
|
32
|
+
import { checkTally, describeDrive, replayedFlows, runProved, } from '../../features/harness/drive-report.js';
|
|
22
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;
|
|
23
36
|
export const EXPLORE_TOOLS = [
|
|
24
37
|
{
|
|
25
38
|
name: ReticleTool.VERIFY_EXPLORE,
|
|
26
|
-
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,
|
|
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. ' +
|
|
27
40
|
EXPLORE_NEEDS,
|
|
28
41
|
inputSchema: {
|
|
29
42
|
persona: z
|
|
30
43
|
.string()
|
|
31
44
|
.optional()
|
|
32
|
-
.describe('The journey in plain words;
|
|
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())
|
|
48
|
+
.optional()
|
|
49
|
+
.describe('Predicate it must end in (route, net, state), asserted after.'),
|
|
33
50
|
maxSteps: stepCountSchema
|
|
34
51
|
.optional()
|
|
35
52
|
.describe('Ceiling on model turns; the drive is graded however it ends.'),
|
|
@@ -37,110 +54,373 @@ export const EXPLORE_TOOLS = [
|
|
|
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(),
|
|
50
88
|
/** Saved flows with no step that asserts anything: their replay verifies nothing. */
|
|
51
|
-
unverifiedFlows: z.array(z.string()),
|
|
89
|
+
unverifiedFlows: z.array(z.string()).optional(),
|
|
52
90
|
/** Whether the drive ran at least one check. A drive that did not proved nothing. */
|
|
53
|
-
proved: z.boolean(),
|
|
91
|
+
proved: z.boolean().optional(),
|
|
54
92
|
/**
|
|
55
93
|
* Whether every journey reached its goal, as the platform judged when the drive finished.
|
|
56
94
|
* Absent when no journey's goal was judged. Checks that held are not the goal reached.
|
|
57
95
|
*/
|
|
58
96
|
goalMet: z.boolean().optional(),
|
|
59
97
|
/** How the drive's checks came out, one per control and claim at its worst. */
|
|
60
|
-
checks: z.object({ held: z.number(), failed: z.number(), undecided: z.number() }),
|
|
98
|
+
checks: z.object({ held: z.number(), failed: z.number(), undecided: z.number() }).optional(),
|
|
61
99
|
/** The runs this drive syncs as (`harness-<uuid>`): what the platform links its check to. */
|
|
62
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(),
|
|
63
108
|
/** One verdict per requested goal, checked by the harness itself. Only `yes` is proved. */
|
|
64
|
-
goals: z
|
|
109
|
+
goals: z
|
|
110
|
+
.array(z.object({ text: z.string(), verified: z.string(), reason: z.string().optional() }))
|
|
111
|
+
.optional(),
|
|
65
112
|
/**
|
|
66
113
|
* What the drive set out to do, read from `.reticle` BEFORE it started — every recorded
|
|
67
114
|
* journey with the consequence that must still hold, and the declared intent nobody has
|
|
68
115
|
* tested. Returned so the caller can see the drive was aimed rather than wandering.
|
|
69
116
|
*/
|
|
70
|
-
plan: z.object({ summary: z.string(), steps: z.array(z.unknown()) }),
|
|
117
|
+
plan: z.object({ summary: z.string(), steps: z.array(z.unknown()) }).optional(),
|
|
71
118
|
/**
|
|
72
119
|
* What the drive did, derived from the calls it made and the verdicts the engine returned.
|
|
73
120
|
*
|
|
74
121
|
* Not the driver's narration. A driver that cannot write a sentence used to leave this empty,
|
|
75
122
|
* and a driver that can is the one witness with a reason to round "unknown" up to "worked".
|
|
76
123
|
*/
|
|
77
|
-
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(),
|
|
78
130
|
/** Present when the drive broke: a model that would not answer, a wedged browser. */
|
|
79
131
|
error: z.string().optional(),
|
|
80
132
|
/** What the drive cost, cache hits included, so an expensive run is visible rather than felt. */
|
|
81
|
-
usage: z
|
|
133
|
+
usage: z
|
|
134
|
+
.object({
|
|
82
135
|
input: z.number(),
|
|
83
136
|
output: z.number(),
|
|
84
137
|
cacheRead: z.number(),
|
|
85
138
|
cacheWrite: z.number(),
|
|
86
|
-
})
|
|
139
|
+
})
|
|
140
|
+
.optional(),
|
|
87
141
|
/** Said out loud when a drive recorded nothing, because that is not a verified app. */
|
|
88
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(),
|
|
89
156
|
},
|
|
90
|
-
handler:
|
|
91
|
-
// The credential `reticle link` already filed counts as configured, so somebody who has
|
|
92
|
-
// signed in and linked does not also have to export a key by hand.
|
|
93
|
-
const env = await withLinkedCredential(deps, process.env);
|
|
94
|
-
if (!harnessAvailable(env))
|
|
95
|
-
throw new Error(MSG_NO_HARNESS_KEY);
|
|
96
|
-
const persona = args['persona'];
|
|
97
|
-
const maxSteps = args['maxSteps'];
|
|
98
|
-
const sessionId = args['sessionId'];
|
|
99
|
-
const { drive, savedFlows, rewroteFlows, unverifiedFlows, driverName, plan, goals, planLines, runIds, } = await exploreApp(deps, env, {
|
|
100
|
-
...('string' === typeof persona ? { focus: persona } : {}),
|
|
101
|
-
...('number' === typeof maxSteps ? { maxSteps } : {}),
|
|
102
|
-
...('string' === typeof sessionId ? { sessionId } : {}),
|
|
103
|
-
});
|
|
104
|
-
return {
|
|
105
|
-
stopReason: drive.stopReason,
|
|
106
|
-
driver: driverName,
|
|
107
|
-
steps: drive.steps,
|
|
108
|
-
savedFlows: [...savedFlows],
|
|
109
|
-
rewroteFlows: [...rewroteFlows],
|
|
110
|
-
unverifiedFlows: [...unverifiedFlows],
|
|
111
|
-
proved: drive.proved,
|
|
112
|
-
checks: checkTally(drive.toolCalls),
|
|
113
|
-
...(drive.goalMet === undefined ? {} : { goalMet: drive.goalMet }),
|
|
114
|
-
...(runIds === undefined ? {} : { runIds: [...runIds] }),
|
|
115
|
-
goals: [...goals],
|
|
116
|
-
plan: { summary: plan.summary, steps: [...plan.steps] },
|
|
117
|
-
// Derived, not narrated. The driver's own `summary` is appended only when it said
|
|
118
|
-
// something — it is the one part of this a model authored, so it goes last and is labelled.
|
|
119
|
-
summary: [
|
|
120
|
-
...(planLines ?? []),
|
|
121
|
-
describeDrive(drive.toolCalls, [...savedFlows, ...rewroteFlows], unverifiedFlows),
|
|
122
|
-
...[unprovedGoals(goals)].filter((line) => line !== undefined),
|
|
123
|
-
...(0 === drive.summary.length ? [] : [`The driver's own account: ${drive.summary}`]),
|
|
124
|
-
].join('\n'),
|
|
125
|
-
...(drive.error === undefined ? {} : { error: drive.error }),
|
|
126
|
-
usage: drive.usage,
|
|
127
|
-
// The note only fires when the drive left NOTHING behind. A rewritten flow is a flow: it
|
|
128
|
-
// replays, it proves what it asserts, and telling its author that "nothing will replay" is
|
|
129
|
-
// a lie this tool used to tell on every second run.
|
|
130
|
-
/*
|
|
131
|
-
* The note fires only when the run left NOTHING behind — and a run that REPLAYED left
|
|
132
|
-
* plenty. Sixteen recorded journeys re-proved for zero model tokens is the cheap half of
|
|
133
|
-
* the plan doing its job, and telling its author to "raise maxSteps" reads as a failure.
|
|
134
|
-
*/
|
|
135
|
-
...(0 === savedFlows.length &&
|
|
136
|
-
0 === rewroteFlows.length &&
|
|
137
|
-
0 === replayedFlows(drive.toolCalls).length
|
|
138
|
-
? { note: `${NOTHING_RECORDED[drive.stopReason]}${failureDetail(drive)}` }
|
|
139
|
-
: {}),
|
|
140
|
-
};
|
|
141
|
-
},
|
|
157
|
+
handler: (deps, args, call) => answerExplore(deps, args, call, exploreDrive),
|
|
142
158
|
},
|
|
143
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
|
+
}
|
|
144
424
|
/**
|
|
145
425
|
* The tool failure behind an empty drive, when there was one.
|
|
146
426
|
*
|
|
@@ -182,6 +462,24 @@ const NOTHING_RECORDED = {
|
|
|
182
462
|
[StopReason.BROKEN]: 'The drive broke before saving anything — read `error`. Nothing is proved.',
|
|
183
463
|
[StopReason.STOPPED]: 'Autonomous driving was switched off before the drive saved anything. Nothing is proved; switch it back on to drive again.',
|
|
184
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
|
+
}
|
|
185
483
|
/**
|
|
186
484
|
* A drive the platform's chat asked for, run as the very tool an agent would call.
|
|
187
485
|
*
|
|
@@ -189,14 +487,19 @@ const NOTHING_RECORDED = {
|
|
|
189
487
|
* counted, and the chat's answer is then the same derived summary the agent would have read — never
|
|
190
488
|
* a model's account of its own drive.
|
|
191
489
|
*/
|
|
192
|
-
export async function driveForChat(deps, goal, sessionId
|
|
490
|
+
export async function driveForChat(deps, goal, sessionId, planId,
|
|
491
|
+
/** The person who started it acknowledged the saved flows' destructive steps. */
|
|
492
|
+
confirmDangerous) {
|
|
193
493
|
const explore = EXPLORE_TOOLS.find((tool) => ReticleTool.VERIFY_EXPLORE === tool.name);
|
|
194
494
|
if (explore === undefined)
|
|
195
495
|
throw new Error('this build has no Harness drive');
|
|
196
|
-
const out = asRecord(await runTool(explore, deps, {
|
|
197
|
-
|
|
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,
|
|
198
500
|
...(sessionId === undefined ? {} : { sessionId }),
|
|
199
|
-
|
|
501
|
+
...(true === confirmDangerous ? { confirmDangerous } : {}),
|
|
502
|
+
})));
|
|
200
503
|
const summary = 'string' === typeof out['summary'] ? out['summary'] : '';
|
|
201
504
|
const error = 'string' === typeof out['error'] ? out['error'] : undefined;
|
|
202
505
|
const note = 'string' === typeof out['note'] ? out['note'] : undefined;
|
|
@@ -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
|
/**
|
|
@@ -222,9 +222,8 @@ const FEEDBACK_PROMPT = {
|
|
|
222
222
|
* outputSchema, returns the whole verdict block, and its own description calls it "one hop for the
|
|
223
223
|
* act->observe->assert loop" — it IS the verification path most agents take. The guard that should
|
|
224
224
|
* have caught the omission keyed on the tool NAME (/assert|verify/), which act_and_wait does not
|
|
225
|
-
* match, so it slipped through in silence
|
|
226
|
-
*
|
|
227
|
-
* 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.
|
|
228
227
|
*/
|
|
229
228
|
export const VERDICT_TOOLS = new Set([
|
|
230
229
|
ReticleTool.ACT_AND_WAIT,
|
|
@@ -234,6 +233,8 @@ export const VERDICT_TOOLS = new Set([
|
|
|
234
233
|
// here rather than six months from now in a metric that had quietly read low the whole time.
|
|
235
234
|
ReticleTool.ACT_SEQUENCE,
|
|
236
235
|
ReticleTool.ASSERT,
|
|
236
|
+
// `reticle_assert { action: "wait" }` lands here, and grades its answer as `assert` does.
|
|
237
|
+
ReticleTool.WAIT_FOR,
|
|
237
238
|
// Merged: `flow_verify` and `verify_change` are actions on this tool now. Naming the merged tool
|
|
238
239
|
// does NOT make every action a verification — `verificationOf` still requires the result to carry
|
|
239
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. */
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
*
|
|
21
21
|
* Scoped per session id, because a new session is a new agent that has been told nothing.
|
|
22
22
|
*/
|
|
23
|
+
import { recordGaps } from '../../portal/session/recorded-gaps.js';
|
|
23
24
|
/** The fields worth repeating. Everything else on a gap is the remedy, said once. */
|
|
24
25
|
const FACT_KEYS = ['kind', 'ref', 'source'];
|
|
25
26
|
/** Sessions that have already been given the full text, by gap kind. */
|
|
@@ -30,9 +31,15 @@ const toldBySession = new Map();
|
|
|
30
31
|
* Returns a NEW array and never mutates its input — the same gap objects travel into telemetry and
|
|
31
32
|
* into the persisted capsule, and trimming those would lose the remedy where it is read cold.
|
|
32
33
|
*/
|
|
33
|
-
export function withGapNovelty(sessionId, gaps
|
|
34
|
+
export function withGapNovelty(sessionId, gaps,
|
|
35
|
+
/** When the verdict was taken: stamps the gaps recorded for the app's coverage. */
|
|
36
|
+
now = Date.now()) {
|
|
34
37
|
if (0 === gaps.length)
|
|
35
38
|
return [];
|
|
39
|
+
// Before the trim, while each gap still carries its remedy: the app's coverage and the platform
|
|
40
|
+
// report read the full gap, and this is the one place every verdict's gaps pass through.
|
|
41
|
+
if (sessionId !== undefined)
|
|
42
|
+
recordGaps(sessionId, gaps, now);
|
|
36
43
|
// No session id means no memory to check against, so nothing can be a repeat. Sending the full
|
|
37
44
|
// text is the safe direction: a reader who has seen it skims, a reader who has not is stuck.
|
|
38
45
|
if (sessionId === undefined)
|