@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
package/docs/usage.md
CHANGED
|
@@ -4,7 +4,7 @@ description: 'The full reference and cookbook: every tool, flag, and workflow, w
|
|
|
4
4
|
icon: book
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
-
Every Reticle drive is the same four steps: **look** (`reticle_look { action: "page" }` / `reticle_look { action: "find" }`), **act** (`reticle_act` / `reticle_act { steps: [...] }`), **observe** (`reticle_observe` / `reticle_observe { action: "network" }` / `reticle_look { action: "state" }`), **assert** (`reticle_assert`). Verdicts come from `reticle_act_and_wait`, `reticle_assert`,
|
|
7
|
+
Every Reticle drive is the same four steps: **look** (`reticle_look { action: "page" }` / `reticle_look { action: "find" }`), **act** (`reticle_act` / `reticle_act { steps: [...] }`), **observe** (`reticle_observe` / `reticle_observe { action: "network" }` / `reticle_look { action: "state" }`), **assert** (`reticle_assert`). Verdicts come from `reticle_act_and_wait`, `reticle_assert`, `reticle_act { steps }` when a step declares `expect`, and `reticle_verify` (`change`/`flows`). Everything else moves or reads the app and proves nothing. Only `verified: "yes"` is a pass: `unknown` means Reticle could not tell, and `no-fault` means nothing was declared to prove. This page is the full reference for every tool, predicate, action and flag in that loop. Tools outside the ten advertised by default are called through `reticle_run({ tool, args })`, and examples use the default tool names.
|
|
8
8
|
|
|
9
9
|
If you haven't set up Reticle yet, start with [Getting Started](getting-started.md).
|
|
10
10
|
|
|
@@ -72,7 +72,7 @@ Who benefits most: anyone shipping **dashboards, internal tools, SaaS apps**. Be
|
|
|
72
72
|
3. **Observe** with `reticle_observe({ since })`: everything the app did _after_ that action.
|
|
73
73
|
4. **Assert** with `reticle_assert({ predicate })`. Verify it, get evidence.
|
|
74
74
|
|
|
75
|
-
**Refs.** Elements are addressed by stable handles like `e7`. You get them from `
|
|
75
|
+
**Refs.** Elements are addressed by stable handles like `e7`. You get them from `reticle_look { action: "page" }` or `reticle_look { action: "find" }`, then pass them to `act`/`inspect`. A ref re-resolves to its element across re-renders; if the element is gone, you get a clear error.
|
|
76
76
|
|
|
77
77
|
**Evidence, not prose.** Every tool returns structured data (counts, the matching network call, the snapshot delta) so the agent reasons over facts, not a vibe.
|
|
78
78
|
|
|
@@ -132,7 +132,7 @@ Perform one action / several in order.
|
|
|
132
132
|
- **`reticle_act { steps: [...] }` args:** `steps: [{ ref | target, action, args? }]`. Each step takes `ref` (from a snapshot/query) or `target` (`{ testid }` / `{ label }` / `{ role, name }` / `{ text }`). That is the same locator `reticle_act` accepts. → `{ since, dispatched, result }` where `result = { ok, count, effects: [...], steps: [...] }` (one `effect` per step; each step carries its own `dispatched`/`settled`/`settleReason`).
|
|
133
133
|
- See [§5](#5-actions-full-list) for the action list.
|
|
134
134
|
|
|
135
|
-
**Dispatch vs settle.** The action is two phases: the **dispatch** (the synchronous click/fill, which is what can fail) and the **settle** (waiting one animation frame so React's commit lands before we return). The settle is **bounded** (~200ms): in a throttled/background tab `requestAnimationFrame` never fires, so Reticle falls back to a timer and resolves anyway. A settle timeout is therefore **never an error**: `reticle_act` resolves with `settled:false, settleReason:"timeout"` and the dispatch (the click) has still landed. Only a real dispatch failure (stale ref, wrong element type) throws.
|
|
135
|
+
**Dispatch vs settle.** (Settle means the page has stopped changing for now.) The action is two phases: the **dispatch** (the synchronous click/fill, which is what can fail) and the **settle** (waiting one animation frame so React's commit lands before we return). The settle is **bounded** (~200ms): in a throttled/background tab `requestAnimationFrame` never fires, so Reticle falls back to a timer and resolves anyway. A settle timeout is therefore **never an error**: `reticle_act` resolves with `settled:false, settleReason:"timeout"` and the dispatch (the click) has still landed. Only a real dispatch failure (stale ref, wrong element type) throws.
|
|
136
136
|
|
|
137
137
|
| top-level field | meaning |
|
|
138
138
|
| --- | --- |
|
|
@@ -184,11 +184,11 @@ The timeline + summary of what happened.
|
|
|
184
184
|
Act, then wait for a predicate: the whole act→observe→assert loop in one hop.
|
|
185
185
|
|
|
186
186
|
- **args:** `ref`, `action`, `args?`, `until: <predicate>`, `timeout_ms?` (default 4000; 0 = evaluate once), `refuseWhenThrottled?`, `intent?`, `durable?` (after a yes, reload and require `until`'s element/text/state parts to hold again), `sessionId?`.
|
|
187
|
-
- **returns:** `{ effect, verdict, trace, session,
|
|
187
|
+
- **returns:** `{ verified, because, effect, verdict, trace, summary, honesty, since, session, … }`. **Gate on `verified`** (`yes` / `no` / `unknown` / `no-fault`; only `yes` is a pass) and read `because` for the deciding evidence. `effect` is the action result (`{ ok, ref, action }`), `verdict` is `{ pass, evidence?, failureReason? }` plus `verifiedReason`, the clause that decided it, `trace` is the reaction report of everything the app did after the action, and `session` is the tab-health block `{ lastSeenMs, throttled, focused }` (with a `warning` when throttled). A failing `verdict` still returns `effect` + `trace` so you can see what _did_ happen. The predicate is automatically floored at this act's cursor, so it only matches events the action actually caused.
|
|
188
188
|
|
|
189
189
|
### `reticle_assert { action: "wait" }`
|
|
190
190
|
|
|
191
|
-
Block until a predicate holds (or time out). Looks both backward (recent buffer) and forward.
|
|
191
|
+
Block until a predicate holds (or time out). Looks both backward (recent buffer) and forward. It returns `pass` and evidence with no `verified`: a wait is not a verdict. Put the consequence on `reticle_act_and_wait` or `reticle_assert` to get one.
|
|
192
192
|
|
|
193
193
|
- **args:** `predicate`, `timeout_ms?` (default 4000), `since?`, `sessionId?`.
|
|
194
194
|
- **No stale-signal false passes.** By default the evaluation window is floored at your **last act's cursor**, so a signal/network/console/animation event buffered _before_ the action can never satisfy the predicate (the report's "validation 68 == 68 was a lie" footgun). Pass an explicit `since` (an act/observe cursor) to widen or narrow the window deliberately. Element/text predicates query the live DOM and are unaffected by `since`.
|
|
@@ -218,13 +218,13 @@ Fast targeted lookups without a full timeline.
|
|
|
218
218
|
|
|
219
219
|
- `reticle_observe({ action: "network", since?, method?, urlContains?, status?, bodies? })` → `{ calls }`. Pass `bodies: false` for a body-free listing (method/url/status/timing only); bodies dominate the payload, so the common "did POST /x return 200?" read gets much cheaper.
|
|
220
220
|
- `reticle_observe({ action: "console", level?, since? })` → `{ logs }`
|
|
221
|
-
- `reticle_animations
|
|
221
|
+
- `reticle_run({ tool: "reticle_animations", args: {} })` → running/recent animations.
|
|
222
222
|
|
|
223
223
|
### `reticle_capabilities`
|
|
224
224
|
|
|
225
225
|
The app-advertised testable surface (registered via `reticle.describe`). Call this first to learn what to assert on without reading source.
|
|
226
226
|
|
|
227
|
-
- `
|
|
227
|
+
- `reticle_run({ tool: "reticle_capabilities", args: { sessionId? } })` → `{ testids, signals, stores, flows }`
|
|
228
228
|
|
|
229
229
|
`reticle_session { action: "list" }` also surfaces a `hasCapabilities` flag per session so you know when it's worth calling. Returns empty arrays (never errors) if the app advertised nothing.
|
|
230
230
|
|
|
@@ -232,7 +232,7 @@ The app-advertised testable surface (registered via `reticle.describe`). Call th
|
|
|
232
232
|
|
|
233
233
|
Read the app's domain model **before testing**: a synthesis of every saved flow + the registered capabilities. Tells you what to test and where the real risk is without crawling the app. Reads `.reticle/flows/` + `.reticle/contract.json`, no browser needed.
|
|
234
234
|
|
|
235
|
-
- `
|
|
235
|
+
- `reticle_run({ tool: "reticle_domain", args: {} })` → `{ flowCount, flows: [{ name, steps, grade, asserts, signals, testids, warning?, risk? }], declared: { testids, signals, stores }, coverage: { asserted, presenceOnly, assertionFree }, gaps: { unassertedFlows, declaredUntestedSignals, declaredUntestedTestids }, riskRanked, summary }`
|
|
236
236
|
- **`gaps`** is the point: `declaredUntestedSignals` are intents the app emits that **no flow asserts** (untested behavior); `unassertedFlows` act but verify no consequence. Close them with a flow + a consequence assertion (`reticle_annotate`).
|
|
237
237
|
- **`riskRanked`** orders flow names worst-first by combining run history (`.reticle/project.json`: recently failed/drifted, or passed-with-errors) with assertion quality (a green assertion-free flow is still risky). **Test these first.** Each flow's `risk` carries `{ level, reason, lastStatus? }`.
|
|
238
238
|
|
|
@@ -269,17 +269,17 @@ reticle_look({ action: "state", store: "__reticle_renders", path: "commits" })
|
|
|
269
269
|
|
|
270
270
|
A render storm shows up as a commit count that climbs with no corresponding DOM mutation: a perf regression invisible to any outside-the-page tool.
|
|
271
271
|
|
|
272
|
-
### `reticle_session {action:"narrate"}` / `reticle_clock`
|
|
272
|
+
### `reticle_session { action: "narrate" }` / `reticle_clock`
|
|
273
273
|
|
|
274
274
|
Show the agent's intent on the page, and control time (toasts/debounces/auto-dismiss). See [§16](#16-presenter-mode-narration--fake-clock-watch--control).
|
|
275
275
|
|
|
276
|
-
### `reticle_baseline {action:"save"}` / `reticle_baseline {action:"list"}` / `reticle_baseline {action:"diff"}`
|
|
276
|
+
### `reticle_run { tool: "reticle_baseline", args: { action: "save" } }` / `reticle_run { tool: "reticle_baseline", args: { action: "list" } }` / `reticle_run { tool: "reticle_baseline", args: { action: "diff" } }`
|
|
277
277
|
|
|
278
278
|
Regression detection. See [§8](#8-regression-baselines--diff).
|
|
279
279
|
|
|
280
|
-
### `reticle_record {action:"start"}` / `reticle_record {action:"stop"}` / `reticle_replay`
|
|
280
|
+
### `reticle_run { tool: "reticle_record", args: { action: "start" } }` / `reticle_run { tool: "reticle_record", args: { action: "stop" } }` / `reticle_replay`
|
|
281
281
|
|
|
282
|
-
Capture a flow's reaction report and compile it into a replayable program. See [§9](#9-recording-a-flow). `reticle_record {action:"stop"}` also returns a `cost:{ events, bytes }` hint alongside the reaction report so you can gauge the recording's size.
|
|
282
|
+
Capture a flow's reaction report and compile it into a replayable program. See [§9](#9-recording-a-flow). `reticle_run { tool: "reticle_record", args: { action: "stop" } }` also returns a `cost:{ events, bytes }` hint alongside the reaction report so you can gauge the recording's size.
|
|
283
283
|
|
|
284
284
|
### `reticle_explore`
|
|
285
285
|
|
|
@@ -287,32 +287,32 @@ List interactive elements + console-error count for autonomous exploration. See
|
|
|
287
287
|
|
|
288
288
|
### Flows, recorder & self-healing (`.reticle/`)
|
|
289
289
|
|
|
290
|
-
`reticle_contract_save`, `reticle_flow_save` / `reticle_flow_save_recorded` / `reticle_flow {action:"list"}` / `reticle_flow {action:"load"}` / `reticle_flow_replay` / `reticle_verify {action:"flows"}`, `reticle_verify { action: "heal" }`, `reticle_annotate`: record once, replay forever (anchored on testid/signal, or on an auto-derived component/source anchor when there's no testid), with legible drift + self-heal. Full guide: [Flows, the recorder & self-healing](flows.md).
|
|
290
|
+
`reticle_contract_save`, `reticle_flow_save` / `reticle_flow_save_recorded` / `reticle_run { tool: "reticle_flow", args: { action: "list" } }` / `reticle_run { tool: "reticle_flow", args: { action: "load" } }` / `reticle_flow_replay` / `reticle_verify { action: "flows" }`, `reticle_verify { action: "heal" }`, `reticle_annotate`: record once, replay forever (anchored on testid/signal, or on an auto-derived component/source anchor when there's no testid), with legible drift + self-heal. Full guide: [Flows, the recorder & self-healing](flows.md).
|
|
291
291
|
|
|
292
292
|
- **`reticle_verify({ action: "flows", names?, sessionId? })`** is the regression-suite call: it replays EVERY saved flow (or a subset) deterministically and returns one verdict `{ status, passed, failed, failures: [{ flow, verdict, whatChanged, whereInSource, nextAction }] }`. Passing flows are counted; only failures carry detail. Run it after any change: one call, no LLM per flow.
|
|
293
|
-
- **Decision envelope:** on a drift/fail, `reticle_flow_replay` (and each `reticle_verify {action:"flows"}` failure) returns the actionable fix: `whatChanged`, `whereInSource` (`file:line`), and a one-line `nextAction` (e.g. "rebind the anchor to 'new-deploy', or update the flow if intended").
|
|
293
|
+
- **Decision envelope:** on a drift/fail, `reticle_flow_replay` (and each `reticle_verify { action: "flows" }` failure) returns the actionable fix: `whatChanged`, `whereInSource` (`file:line`), and a one-line `nextAction` (e.g. "rebind the anchor to 'new-deploy', or update the flow if intended").
|
|
294
294
|
|
|
295
295
|
### Human-in-the-loop control
|
|
296
296
|
|
|
297
|
-
`reticle_session {action:"end"}`, `reticle_session {action:"resume"}`, `reticle_session {action:"messages"}`: the human can pause the agent, send it a correction, or end the session from the floating panel; the agent receives guidance on its next tool call. Full guide: [Human-in-the-loop control](human-control.md).
|
|
297
|
+
`reticle_session { action: "end" }`, `reticle_session { action: "resume" }`, `reticle_session { action: "messages" }`: the human can pause the agent, send it a correction, or end the session from the floating panel; the agent receives guidance on its next tool call. Full guide: [Human-in-the-loop control](human-control.md).
|
|
298
298
|
|
|
299
|
-
### `reticle_session {action:"review"}`: drain the bugs the human flagged on the page
|
|
299
|
+
### `reticle_session { action: "review" }`: drain the bugs the human flagged on the page
|
|
300
300
|
|
|
301
301
|
The dev clicks **"Flag a bug"** in the running app, points at the element that looks wrong, and types what's wrong (⌘/Ctrl+Enter to send). Each flag becomes a **mark** the agent drains:
|
|
302
302
|
|
|
303
303
|
```
|
|
304
|
-
reticle_session
|
|
304
|
+
reticle_session({ action: "review", sessionId })
|
|
305
305
|
→ { marks: [{ id: "m1", note: "this button is misaligned", label: "button \"Pay\"",
|
|
306
306
|
source: { file: "src/Checkout.tsx", line: 42 },
|
|
307
|
-
fix: "Open src/Checkout.tsx:42 and fix: this button is misaligned. Then reticle_session {action:"review"} { resolve: \"m1\" }" }],
|
|
307
|
+
fix: "Open src/Checkout.tsx:42 and fix: this button is misaligned. Then reticle_session { action: "review" } { resolve: \"m1\" }" }],
|
|
308
308
|
pendingCount: 1 }
|
|
309
309
|
```
|
|
310
310
|
|
|
311
|
-
Each pending mark carries the human note, the element label, the source **`file:line`** (when the framework stamped one), and a ready-to-act `fix` hint. Open the file, apply the fix, then `reticle_session
|
|
311
|
+
Each pending mark carries the human note, the element label, the source **`file:line`** (when the framework stamped one), and a ready-to-act `fix` hint. Open the file, apply the fix, then `reticle_session({ action: "review", resolve: "m1" })`. The human watching the panel sees **"✓ fixed: …"** land. Reading never consumes a mark, so you can list → fix → verify → resolve. `reticle_session { action: "list" }` also reports `pendingMarks` so you notice flagged bugs during normal orientation.
|
|
312
312
|
|
|
313
313
|
### `reticle_network_mock`: stub the network for error-state testing
|
|
314
314
|
|
|
315
|
-
On a page Reticle drives (`reticle drive`) or a leased Playwright tab (`reticle_lease acquire`), make a request return a 500, force it offline, or delay it, so testing error/edge states is one declared rule, no backend changes:
|
|
315
|
+
On a page Reticle drives (`reticle drive`) or a leased Playwright tab (`reticle_run { tool: "reticle_lease", args: { action: "acquire" } }`), make a request return a 500, force it offline, or delay it, so testing error/edge states is one declared rule, no backend changes:
|
|
316
316
|
|
|
317
317
|
```
|
|
318
318
|
reticle_run({ tool: "reticle_network_mock", args: { mocks: [{ urlContains: "/api/pay", method: "POST", status: 500 }] } })
|
|
@@ -334,9 +334,9 @@ reticle_run({ tool: "reticle_viewport", args: { width: 1280, height: 800 } })
|
|
|
334
334
|
|
|
335
335
|
This is one of three knobs for **CI-stable visual regression**. Set them together:
|
|
336
336
|
|
|
337
|
-
1. **`
|
|
338
|
-
2. **`
|
|
339
|
-
3. **`
|
|
337
|
+
1. **`reticle_run({ tool: "reticle_viewport", args: { width, height } })`** gives the same dimensions on every machine.
|
|
338
|
+
2. **`reticle_run({ tool: "reticle_clock", args: { freeze: true } })`** kills animation/time jitter so the pixels are stable.
|
|
339
|
+
3. **`reticle_run({ tool: "reticle_visual_diff", args: { baseline, masks: [{ x, y, width, height }] } })`** neutralizes volatile regions (clocks, avatars, ids) so only real changes fail.
|
|
340
340
|
|
|
341
341
|
---
|
|
342
342
|
|
|
@@ -381,6 +381,8 @@ A **predicate** declares what should be true. `reticle_assert` / `reticle_assert
|
|
|
381
381
|
{ "kind": "state", "store": "app", "path": "deployments.0.status", "equals": "live" }
|
|
382
382
|
```
|
|
383
383
|
|
|
384
|
+
`visible` excludes elements whose boxes are fully clipped by an ancestor's `overflow:hidden` or `overflow:clip`; a partly clipped element stays visible. Expanding a clamped card can therefore prove that its previously hidden paragraph became visible. `overflow:auto` and `overflow:scroll` keep their existing visibility semantics, including content beyond the scrollport. Ordinary document content outside the window remains visible; `inViewport` checks the window intersection after any hidden/clip ancestor clipping, without introducing scrollport clipping.
|
|
385
|
+
|
|
384
386
|
A `state` assertion is graded as a **consequence** (a wrong element or stale render cannot fake it), and is usable the same three ways anywhere predicates flow: ad-hoc (`reticle_assert` / `reticle_act_and_wait` `until`), as a flow step invariant (`reticle_annotate { kind: "assert-state", statePath, store?, equals? }`), and as a flow's golden end-condition (`reticle_annotate { kind: "success-state", statePath, … }`). On a miss it names the real store value and the keys that were available: legible, not a blind fail.
|
|
385
387
|
|
|
386
388
|
### Combinators
|
|
@@ -393,7 +395,7 @@ A `state` assertion is graded as a **consequence** (a wrong element or stale ren
|
|
|
393
395
|
|
|
394
396
|
### Timing
|
|
395
397
|
|
|
396
|
-
- `timeout_ms` (on `
|
|
398
|
+
- `timeout_ms` (on `reticle_assert`, either action): wait up to N ms for it to become true.
|
|
397
399
|
- `since` (on `net`/`console` leaves): only consider events after this cursor (from `act`).
|
|
398
400
|
|
|
399
401
|
`dataMatches` matches field by field; a key can be a dotted path (`"order.total"`, `"items.0.id"`), and `*` means "present, any value".
|
|
@@ -415,9 +417,12 @@ A `state` assertion is graded as a **consequence** (a wrong element or stale ren
|
|
|
415
417
|
| `select` | `{ value }` | `<select>` option |
|
|
416
418
|
| `check` / `uncheck` | n/a | checkbox/radio |
|
|
417
419
|
| `submit` | n/a | submits the element's `<form>` |
|
|
418
|
-
| `press` | `{
|
|
420
|
+
| `press` | `{ text, modifiers?, holdMs?, keys?, code? }` | keydown/up (default `Enter`). `text` is the key name (`Escape`, `Tab`); `key` is an accepted alias; `modifiers`: an array of `Meta` / `Control` / `Shift` / `Alt` for Cmd+K-style shortcuts. With a `ref` the key is dispatched AT that element; with NO ref it is a document key (Escape, Tab, a shortcut) and goes through the real keyboard, so it can actually move focus. `holdMs` keeps the key DOWN for that long (hold-to-confirm, hold-to-reveal). `keys` holds several keys together, pressed in order and released in reverse, and `code` names the physical key: both stay on the in-page dispatcher, which is the only path that can express them |
|
|
419
421
|
| `scrollIntoView` | n/a | |
|
|
420
|
-
| `
|
|
422
|
+
| `scroll` | `{ dy?, dx?, fraction? }` | Scrolls the nearest scrollable container (or the page, with no `ref`) by `dy`/`dx` pixels, either direction. `fraction` (0 to 1) jumps to that point of the height. No args steps down most of a screen |
|
|
423
|
+
| `tap` | `{ holdMs? }` | A touch tap: pointer and touch events, then `click`. `holdMs` makes it a long press |
|
|
424
|
+
| `zoom` | n/a | Page zoom. Refused inside the page, because CSS zoom changes how a page looks without changing its layout, and a passing check on it would be false |
|
|
425
|
+
| `upload` | `{ path }` or `{ name, content?, type? }` | sets a file on `<input type=file>`: `path` is a file on disk (absolute or relative to the project root) whose real bytes the daemon delivers; `name`/`content` supply inline bytes |
|
|
421
426
|
| `drag` | `{ toRef }` | pointer-based drag (dnd-kit / rbd) + HTML5 DnD |
|
|
422
427
|
|
|
423
428
|
---
|
|
@@ -491,7 +496,7 @@ reticle_assert({ timeout_ms: 3000, predicate: { kind: "element",
|
|
|
491
496
|
query: { text: "Invoice #4821", scope: "[data-testid=item-list]" }, state: "visible" } })
|
|
492
497
|
```
|
|
493
498
|
|
|
494
|
-
> Note: if your list is **virtualized** (react-window/virtuoso), an off-screen row is not in the DOM at all, so `reticle_look { action: "find" }` correctly finds nothing. Use **`reticle_scroll_to`** to scroll the windowed container until the row renders, then query it: `
|
|
499
|
+
> Note: if your list is **virtualized** (react-window/virtuoso), an off-screen row is not in the DOM at all, so `reticle_look { action: "find" }` correctly finds nothing. Use **`reticle_scroll_to`** to scroll the windowed container until the row renders, then query it: `reticle_run({ tool: "reticle_scroll_to", args: { by: "text", value: "Invoice #4821", container: "[data-testid=item-list]" } })`. Asserting against the data with `reticle.signal` or `reticle_look { action: "state" }` also works and is cheaper.
|
|
495
500
|
|
|
496
501
|
### "Login form: does it actually authorize?"
|
|
497
502
|
|
|
@@ -568,7 +573,7 @@ reticle.describe({
|
|
|
568
573
|
});
|
|
569
574
|
```
|
|
570
575
|
|
|
571
|
-
The agent reads this back with `reticle_capabilities
|
|
576
|
+
The agent reads this back with `reticle_run({ tool: "reticle_capabilities", args: {} })`; see [§3](#3-the-tools-full-reference).
|
|
572
577
|
|
|
573
578
|
```jsonc
|
|
574
579
|
reticle_assert({ timeout_ms: 30000, predicate: {
|
|
@@ -577,7 +582,7 @@ reticle_assert({ timeout_ms: 30000, predicate: {
|
|
|
577
582
|
|
|
578
583
|
#### Keeping signals from drifting (lint)
|
|
579
584
|
|
|
580
|
-
Signals only help if you actually emit one whenever user-visible state changes. The `@reticlehq/eslint-plugin` package ships `reticle/require-signal-on-mutation`, which flags any function that calls a configured store **mutator** but never fires the **signal callee** in the same body, so the signal map can't silently fall behind the store. (The package also ships `reticle/no-internal-tags`;
|
|
585
|
+
Signals only help if you actually emit one whenever user-visible state changes. The `@reticlehq/eslint-plugin` package ships `reticle/require-signal-on-mutation`, which flags any function that calls a configured store **mutator** but never fires the **signal callee** in the same body, so the signal map can't silently fall behind the store. (The package also ships `reticle/no-internal-tags` and `reticle/no-runaway-comment`; all three are on in its `recommended` config.)
|
|
581
586
|
|
|
582
587
|
```js
|
|
583
588
|
// eslint.config.mjs
|
|
@@ -606,10 +611,10 @@ The "did anything silently break/disappear?" workflow.
|
|
|
606
611
|
|
|
607
612
|
```jsonc
|
|
608
613
|
// after you've confirmed a screen is good:
|
|
609
|
-
reticle_baseline {action:"save"
|
|
614
|
+
reticle_run({ tool: "reticle_baseline", args: { action: "save", name: "checkout-ok" } })
|
|
610
615
|
|
|
611
616
|
// later, after a change:
|
|
612
|
-
reticle_baseline {action:"diff"
|
|
617
|
+
reticle_run({ tool: "reticle_baseline", args: { action: "diff", baseline: "checkout-ok" } })
|
|
613
618
|
// → { removed: ["- button \"Export\""], added: ["- alert \"Card declined\""],
|
|
614
619
|
// consoleErrors: 2, routeChanged: false }
|
|
615
620
|
```
|
|
@@ -618,7 +623,7 @@ reticle_baseline {action:"diff"}({ baseline: "checkout-ok" })
|
|
|
618
623
|
|
|
619
624
|
### Pixel-perfect visual regression that's stable in CI (driven mode)
|
|
620
625
|
|
|
621
|
-
The semantic `reticle_baseline {action:"diff"}` above never flakes. For an actual **pixel** diff (`reticle_screenshot` + `reticle_visual_diff`, driven mode), three knobs make it CI-stable instead of flaky:
|
|
626
|
+
The semantic `reticle_run { tool: "reticle_baseline", args: { action: "diff" } }` above never flakes. For an actual **pixel** diff (`reticle_screenshot` + `reticle_visual_diff`, driven mode), three knobs make it CI-stable instead of flaky:
|
|
622
627
|
|
|
623
628
|
```jsonc
|
|
624
629
|
reticle_run({ tool: "reticle_viewport", args: { width: 1280, height: 800 } }) // 1. same size on every machine
|
|
@@ -638,9 +643,9 @@ Without all three, a pixel diff fails on a different window size, a mid-animatio
|
|
|
638
643
|
Capture everything that happens across a span. Useful for "run my whole checkout flow and tell me what happened," or to keep a known-good trace.
|
|
639
644
|
|
|
640
645
|
```jsonc
|
|
641
|
-
reticle_record {action:"start"
|
|
646
|
+
reticle_run({ tool: "reticle_record", args: { action: "start", recordingName: "checkout" } })
|
|
642
647
|
// …agent performs the flow (reticle_act, single or with steps)…
|
|
643
|
-
reticle_record {action:"stop"
|
|
648
|
+
reticle_run({ tool: "reticle_record", args: { action: "stop", recordingName: "checkout" } })
|
|
644
649
|
// → {
|
|
645
650
|
// recordingName,
|
|
646
651
|
// program: { version, steps: [{ tool, args: { by:"testid", value, action, args }, stable }] },
|
|
@@ -650,7 +655,7 @@ reticle_record {action:"stop"}({ recordingName: "checkout" })
|
|
|
650
655
|
// }
|
|
651
656
|
```
|
|
652
657
|
|
|
653
|
-
`reticle_record {action:"stop"}` returns a compiled, replayable `program`: the agent's `reticle_act` / `reticle_act { steps: [...] }` invocations captured during the span, with each ref normalized to its element's `data-testid` where resolvable. Re-run it later:
|
|
658
|
+
`reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a compiled, replayable `program`: the agent's `reticle_act` / `reticle_act { steps: [...] }` invocations captured during the span, with each ref normalized to its element's `data-testid` where resolvable. Re-run it later:
|
|
654
659
|
|
|
655
660
|
```jsonc
|
|
656
661
|
reticle_run({ tool: "reticle_replay", args: { recordingName: "checkout" } })
|
|
@@ -658,7 +663,7 @@ reticle_run({ tool: "reticle_replay", args: { recordingName: "checkout" } })
|
|
|
658
663
|
// → { recordingName, ok, steps: [{ tool, ok, error?, note? }] } // stops at the first failure
|
|
659
664
|
```
|
|
660
665
|
|
|
661
|
-
**Limitation.** Normalization to a stable testid only works for elements that have a `data-testid`. A step whose element has none is stored in ref form (`stable: false`) and `reticle_record {action:"stop"}` returns a `warning`; replay best-effort re-uses the stored ref, which is only valid within the same live session and is not portable across reloads. Add `data-testid` to the elements you want replay-stable.
|
|
666
|
+
**Limitation.** Normalization to a stable testid only works for elements that have a `data-testid`. A step whose element has none is stored in ref form (`stable: false`) and `reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a `warning`; replay best-effort re-uses the stored ref, which is only valid within the same live session and is not portable across reloads. Add `data-testid` to the elements you want replay-stable.
|
|
662
667
|
|
|
663
668
|
---
|
|
664
669
|
|
|
@@ -714,6 +719,7 @@ Reticle is cheap by design ([benchmark](token-efficiency.md)), but keep it that
|
|
|
714
719
|
- **Always thread `since`.** Pass the cursor from `reticle_act` into `observe`/`assert` so you only consider what happened _after_ the action.
|
|
715
720
|
- **Use `timeout_ms` for async.** Don't assert instantly on something that arrives over the network or after a re-render.
|
|
716
721
|
- **Watch `session.throttled`.** Background tabs throttle timers/rAF/pointer gestures, so an act can silently no-op. Every `reticle_act` / `reticle_assert` / `reticle_act_and_wait` result carries `session: { lastSeenMs, throttled, focused }` and, when throttled, a `warning`. Refocus the tab (or run it foregrounded) before driving; pass `refuseWhenThrottled: true` to hard-fail instead.
|
|
722
|
+
- **`ready` is connection, not hydration.** A session or lease answering `ready: true` has an SDK attached and answering; it does not mean the app finished hydrating. A slow-hydrating page (SvelteKit, Next) can still be mid-render, with controls not yet wired up, so an act issued immediately can miss. If reads come back empty (a `find` for buttons returns 0 matches and there are no console lines), that may mean not hydrated. Make the first act `reticle_act_and_wait` with an `until` on something hydration renders, or `reticle_assert { action: "wait" }`.
|
|
717
723
|
- **Scope big pages.** On dashboards with hundreds of elements, scope queries to the panel you care about.
|
|
718
724
|
- **Never breaks your app.** Observers are additive and reversible (`reticle.disconnect()` restores patched globals). It won't interfere with your app's behavior.
|
|
719
725
|
|
|
@@ -754,7 +760,7 @@ Each is a session; pass `sessionId` to any tool when more than one is connected
|
|
|
754
760
|
## 15. Security & privacy
|
|
755
761
|
|
|
756
762
|
- **Dev-only, localhost-only by default.** The bridge binds `127.0.0.1`; the SDK is meant for dev builds.
|
|
757
|
-
- **No app data leaves your machine.** Baselines/recordings are local. The CLI sends anonymous, opt-out usage metrics only (random id + event names, no code and no PII; see [telemetry](telemetry.md)); opt out with `reticle telemetry disable`, `RETICLE_TELEMETRY=0`, or `DO_NOT_TRACK=1`. Feedback you or your agent deliberately send (`reticle feedback` / `reticle_session { action: "feedback" }`) is the only free text that ever leaves the machine: never passive, redacted first, and separately disabled with `RETICLE_FEEDBACK=0`.
|
|
763
|
+
- **No app data leaves your machine until you link a project.** Nothing from your app leaves the machine until you link a project (`reticle connect`, or `RETICLE_API_KEY` in CI). After that, what syncs is set by `reticle config`, and when the Harness (Reticle's model-driven explorer, which runs on the Reticle platform) drives, the platform sees the steps it drives. Secret values never leave. Baselines/recordings are local. The CLI sends anonymous, opt-out usage metrics only (random id + event names, no code and no PII; see [telemetry](telemetry.md)); opt out with `reticle telemetry disable`, `RETICLE_TELEMETRY=0`, or `DO_NOT_TRACK=1`. Feedback you or your agent deliberately send (`reticle feedback` / `reticle_session { action: "feedback" }`) is the only free text that ever leaves the machine: never passive, redacted first, and separately disabled with `RETICLE_FEEDBACK=0`.
|
|
758
764
|
- **Network bodies aren't captured by default:** only method/url/status/timing. Body capture is opt-in and runs through a redactor (drop `password`/`token`/`secret`/… + your patterns).
|
|
759
765
|
- **Additive & reversible.** Reticle patches `fetch`/History/console defensively and restores them on disconnect; it will not break the app under test.
|
|
760
766
|
|
|
@@ -809,21 +815,21 @@ All presenter DOM uses `data-reticle-*` and is excluded from snapshots/observers
|
|
|
809
815
|
|
|
810
816
|
#### Session liveness: the HUD never gets stuck "running"
|
|
811
817
|
|
|
812
|
-
A session starts on the agent's first activity and must reliably end even when the agent misbehaves. Reticle is an MCP tool, so the agent (Claude) can crash, disconnect, or simply forget to call `reticle_session {action:"end"}`, and a backgrounded tab's own timers are throttled by the browser. So **the Node server owns liveness, not the browser tab:**
|
|
818
|
+
A session starts on the agent's first activity and must reliably end even when the agent misbehaves. Reticle is an MCP tool, so the agent (Claude) can crash, disconnect, or simply forget to call `reticle_session { action: "end" }`, and a backgrounded tab's own timers are throttled by the browser. So **the Node server owns liveness, not the browser tab:**
|
|
813
819
|
|
|
814
820
|
- **Agent goes idle / forgets to end** → a server-side reaper (immune to tab throttling) ends the session after `idleEndMs` of no agent commands and pushes the end to the browser. A backgrounded tab still receives that push, so you can switch windows and come back to a correctly-ended HUD.
|
|
815
821
|
- **Agent (MCP client) disconnects cleanly** → every active session ends at once.
|
|
816
822
|
- **Agent kills the Reticle server process** (so no push can arrive) → the SDK self-ends the session after it can't reach the bridge for `BRIDGE_LOST_MS` (~15s), showing "lost connection to Reticle."
|
|
817
|
-
- **Slow-but-alive agent** → if it goes quiet long enough to auto-end and then acts again, the session **revives** automatically (an explicit `reticle_session {action:"end"}` stays terminal).
|
|
823
|
+
- **Slow-but-alive agent** → if it goes quiet long enough to auto-end and then acts again, the session **revives** automatically (an explicit `reticle_session { action: "end" }` stays terminal).
|
|
818
824
|
|
|
819
825
|
Tune the idle window with `reticle_session({ action: "tune", idleEndMs })`; it updates both the browser timer and the server reaper. When the HUD covers a control you have to test, `reticle_session({ action: "tune", hud: "top-left" })` moves it (any corner), and `hud: "hidden"`, `"shown"` or `"removed"` (until the page reloads) take it out of the way; the call fails rather than pretending if the page could not apply it. The human keeps the panel (with Copy/Export of the run) after any end.
|
|
820
826
|
|
|
821
|
-
### `reticle_session {action:"narrate"}`: show the agent's intent
|
|
827
|
+
### `reticle_session { action: "narrate" }`: show the agent's intent
|
|
822
828
|
|
|
823
829
|
So the human sees _what the agent is about to do and why_:
|
|
824
830
|
|
|
825
831
|
```jsonc
|
|
826
|
-
reticle_session
|
|
832
|
+
reticle_session({ action: "narrate", text: "Adding a beat, then checking the section count goes up" })
|
|
827
833
|
```
|
|
828
834
|
|
|
829
835
|
It renders on the HUD. (The agent's private reasoning isn't visible to Reticle; narration is how it surfaces intent on the page.)
|
|
@@ -845,7 +851,7 @@ It does **not** freeze `requestAnimationFrame`/microtasks (React's scheduler kee
|
|
|
845
851
|
### Action refinements (from real-app use)
|
|
846
852
|
|
|
847
853
|
- **`blur`** now fires a bubbling `focusout`, so React's commit-on-blur (`onBlur`) runs, and inline editors and form fields commit. `fill`/`type` focus first so a later `blur` commits.
|
|
848
|
-
- **`hover`** accepts `{ holdMs }` to dwell, so timer-gated reveals mount; then `
|
|
854
|
+
- **`hover`** accepts `{ holdMs }` to dwell, so timer-gated reveals mount; then `reticle_assert { action: "wait" }` for the revealed nodes.
|
|
849
855
|
- **`drag`** yields a frame between phases (React flushes between steps) and accepts `{ data: { mime, value } }` for custom `dataTransfer` payloads.
|
|
850
856
|
|
|
851
857
|
### Richer `dataMatches` (signals)
|
|
@@ -1027,7 +1033,7 @@ reticle_run({ tool: "reticle_capabilities", args: {} }) // → { testids, sign
|
|
|
1027
1033
|
|
|
1028
1034
|
### `reticle_replay`: recordings become re-runnable programs
|
|
1029
1035
|
|
|
1030
|
-
`reticle_record {action:"start"}` → drive the flow → `reticle_record {action:"stop"}` returns a **compiled program** (steps bound to testids/signals, not volatile refs). `
|
|
1036
|
+
`reticle_run { tool: "reticle_record", args: { action: "start" } }` → drive the flow → `reticle_run { tool: "reticle_record", args: { action: "stop" } }` returns a **compiled program** (steps bound to testids/signals, not volatile refs). `reticle_run({ tool: "reticle_replay", args: { recordingName } })` re-executes it, so your flow becomes a deterministic regression run, not a checklist.
|
|
1031
1037
|
|
|
1032
1038
|
---
|
|
1033
1039
|
|
|
@@ -1089,6 +1095,6 @@ That's it. Reticle correlates the CDP page to your SDK session by URL; pointer a
|
|
|
1089
1095
|
|
|
1090
1096
|
> **SPA navigation is handled.** The URL correlation tracks client-side route changes (`pushState`/`replaceState`/`popstate`), so real input keeps working after your app navigates into a sub-route, e.g. the hover/quick-edit cluster on a `/workspace` view stays drivable. (If you see `inputModeReason:"page-not-correlated-to-a-cdp-target"`, the reported session URL isn't correlated to a CDP target and real input silently falls back to synthetic.)
|
|
1091
1097
|
|
|
1092
|
-
> **Watching the agent (presenter).** With `present: true` the activity border now glows once while the agent is busy and fades when idle (no per-action strobe); the HUD
|
|
1098
|
+
> **Watching the agent (presenter).** With `present: true` the activity border now glows once while the agent is busy and fades when idle (no per-action strobe); the HUD docks **bottom-right** by default, shows a **READING** vs **ACTING** chip so you can tell observation from action at a glance, and `reticle_session { action: "narrate" }` lines are **queued** with a minimum on-screen dwell so none flash by unread.
|
|
1093
1099
|
|
|
1094
|
-
> **Limitation: un-scriptable tabs.** Reticle observes/drives a tab through the in-page SDK + (optionally) CDP; it **cannot bring to front or recover a browser tab the OS won't let it script** (e.g. a backgrounded or non-default-browser tab reporting `hidden:true`/`throttled:true`). When that happens, `reticle_session { action: "list" }` and every act/assert result carry a `session.recommendation` saying so
|
|
1100
|
+
> **Limitation: un-scriptable tabs.** Reticle observes/drives a tab through the in-page SDK + (optionally) CDP; it **cannot bring to front or recover a browser tab the OS won't let it script** (e.g. a backgrounded or non-default-browser tab reporting `hidden:true`/`throttled:true`). When that happens, `reticle_session { action: "list" }` and every act/assert result carry a `session.recommendation` saying so. For a hidden tab it points to `reticle_run { tool: "reticle_lease", args: { action: "acquire", url } }` (or `reticle drive <url>` for a human) for a guaranteed scriptable context. Refocus the tab, or lease one.
|
package/docs/use-cases.mdx
CHANGED
|
@@ -67,7 +67,7 @@ Reticle finds elements the way assistive technology does: by role and accessible
|
|
|
67
67
|
- **The keyboard works.** `press` with `Enter` or `Escape` fires the control's action, not just a mouse click. The [verify-keyboard-access](https://github.com/reticlehq/reticle/tree/main/skills/verify-keyboard-access) skill walks through it.
|
|
68
68
|
- **Visible, enabled, checked, expanded, pressed and in-viewport** are all element states you can assert.
|
|
69
69
|
|
|
70
|
-
A synthetic Tab key does not move focus in a browser, so Reticle cannot verify Tab order
|
|
70
|
+
A synthetic Tab key does not move focus in a browser, so Reticle cannot verify Tab order. Report Tab order as unknown, never as a pass.
|
|
71
71
|
|
|
72
72
|
Open the "Delete project" dialog with `press` (`args: { "text": "Enter" }`) and require focus to move into it:
|
|
73
73
|
|
|
@@ -122,8 +122,8 @@ After navigating to the old `/plans` URL, require the redirect and the page's ma
|
|
|
122
122
|
|
|
123
123
|
## Personas and simulation
|
|
124
124
|
|
|
125
|
-
- **Drive the app as a user.** `explore` takes a persona in plain words, drives that whole journey with
|
|
126
|
-
- **One context per role.** `reticle_lease { action: "acquire" }` opens an isolated browser context (its own cookies, storage and DOM) and can seed storage or cookies first, so an admin and a viewer drive the same app side by side. Reach it with `reticle_run`, or use `reticle verify <url> --storage-state <file>` from a terminal.
|
|
125
|
+
- **Drive the app as a user.** `explore` takes a persona in plain words, drives that whole journey with the Harness, Reticle's model-driven explorer, which runs on the Reticle platform (run `reticle connect` first; a new account gets 10 free credits), and saves what it drove as a flow that later replays with no model.
|
|
126
|
+
- **One context per role.** `reticle_run { tool: "reticle_lease", args: { action: "acquire" } }` opens an isolated browser context (its own cookies, storage and DOM) and can seed storage or cookies first, so an admin and a viewer drive the same app side by side. Reach it with `reticle_run`, or use `reticle verify <url> --storage-state <file>` from a terminal.
|
|
127
127
|
- **Reachability testing.** Signed in as a role, a control that role must not have is absent, and the call behind it never fires. `reticle_verify { action: "coverage" }` lists the controls you have and have not driven this session.
|
|
128
128
|
- **Multi-agent runs.** Several agents lease contexts from one shared headless Chromium, capped and queued, instead of starting a browser each. See [Multi-agent](/multi-agent-testing).
|
|
129
129
|
|
|
@@ -17,6 +17,8 @@ Same app, same bugs, same moment:
|
|
|
17
17
|
| Avg tokens per look | 815 | **758** |
|
|
18
18
|
| Verification efficiency | **12.27** | 10.55 |
|
|
19
19
|
|
|
20
|
+
Measured on 2026-06-22 against `chrome-devtools-mcp@1.3.0`; DevTools MCP has shipped since, and this pass has not been re-run.
|
|
21
|
+
|
|
20
22
|
DevTools MCP genuinely wins the cost column. We are not going to bury that. 758 against 815 is a real 7% advantage per observation, and if you are making a very large number of trivial looks it adds up.
|
|
21
23
|
|
|
22
24
|
But cost per look is only half a metric. Verification efficiency combines both. Regressions caught per 1,000 tokens spent, gated on catching **all** of them with zero false alarms on a known-good control. On that measure Reticle leads 12.27 to 10.55.
|
|
@@ -45,7 +47,7 @@ Note the flip. DevTools is cheaper on a small page and more expensive on a large
|
|
|
45
47
|
|
|
46
48
|
DevTools MCP is DOM-and-network only. It can describe what a page looks like and what it requested; it cannot ask the application what it believes.
|
|
47
49
|
|
|
48
|
-
|
|
50
|
+
The benchmark record keeps per-tool totals, not which two scenarios DevTools MCP missed. The class it structurally cannot reach is the one where the page is fine and the program is not. A mutation that never reached the store, a success handler that fired for the wrong reason. There is nothing in the DOM or the network log that distinguishes those from working code.
|
|
49
51
|
|
|
50
52
|
Reticle can require the app's own signal:
|
|
51
53
|
|
|
@@ -86,11 +88,12 @@ Neither tool forbids the other. A reasonable setup:
|
|
|
86
88
|
<AccordionGroup>
|
|
87
89
|
|
|
88
90
|
<Accordion title="Which two bugs did Chrome DevTools MCP miss?">
|
|
89
|
-
The
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
91
|
+
The benchmark record keeps per-tool totals, not the two scenarios by name. The class it cannot
|
|
92
|
+
reach is the one where the page is fine and the program is not, such as a mutation that never
|
|
93
|
+
reached the store, or a success handler that fired for the wrong reason. DevTools MCP is
|
|
94
|
+
DOM-and-network only, so it can describe what the page looks like and what it requested, but it
|
|
95
|
+
cannot ask the application what it believes. There is nothing in the DOM or the network log that
|
|
96
|
+
separates those cases from working code.
|
|
94
97
|
</Accordion>
|
|
95
98
|
|
|
96
99
|
<Accordion title="If DevTools MCP is cheaper, why not just use it?">
|
|
@@ -15,6 +15,8 @@ That single architectural choice explains every difference below. An outside-in
|
|
|
15
15
|
|
|
16
16
|
## Measured, on the same app at the same moment
|
|
17
17
|
|
|
18
|
+
These passes last ran on 2026-06-22, against `@playwright/mcp@0.0.76`. Both tools have shipped since, so treat the numbers as dated.
|
|
19
|
+
|
|
18
20
|
| | Reticle | Playwright MCP |
|
|
19
21
|
| ----------------------- | --------- | -------------- |
|
|
20
22
|
| Bugs caught (of 10) | **10** | 9 |
|
|
@@ -49,7 +51,7 @@ This is not a courtesy section. There are real cases where Playwright is the cor
|
|
|
49
51
|
- **Assert on the app's own success signal.** When your app emits `auth:granted`, Reticle can require that exact signal. Playwright can check that a DOM element appeared, which a mock also does.
|
|
50
52
|
- **Read application state.** `stateDiffs` shows `auth` moving from `null` to a real user. A POST that returns `200` without touching state is caught here and nowhere else.
|
|
51
53
|
- **Map a DOM node to source.** `src/components/Login.tsx:81`, via the React fiber tree. Playwright can tell you the selector; it cannot tell you the file.
|
|
52
|
-
- **Grade its own evidence.**
|
|
54
|
+
- **Grade its own evidence.** An `act_and_wait` verdict reports `honesty.grade`: `none`, `presence`, `state`, `net` or `signal`, weakest to strongest. Plus whether the capture was clean and complete.
|
|
53
55
|
- **Say "unknown".** Reticle distinguishes "did not happen" from "I could not tell". That third state is the difference between a check and a coin flip.
|
|
54
56
|
|
|
55
57
|
## The false-green case
|
package/docs/what-is-recorded.md
CHANGED
|
@@ -5,7 +5,7 @@ description: What Reticle keeps on your machine, what is redacted, and what it t
|
|
|
5
5
|
|
|
6
6
|
Reticle drives your app and reads what it did. That means it holds real content from real pages, so this page says exactly what it keeps, where it keeps it, and what it takes to make any of it leave.
|
|
7
7
|
|
|
8
|
-
If you read one line: **a verdict is entirely local and needs no account.** Nothing from your
|
|
8
|
+
If you read one line: **a verdict is entirely local and needs no account.** Nothing from your app leaves the machine until you link a project (`reticle connect`, or `RETICLE_API_KEY` in CI). After that, what syncs is set by `reticle config`, and when the Harness drives, the platform sees the steps it drives. Secret values never leave. (Anonymous usage counts, which carry nothing from your app, are separate and described in [Telemetry](telemetry.md).)
|
|
9
9
|
|
|
10
10
|
## On your machine
|
|
11
11
|
|
|
@@ -27,11 +27,11 @@ Everything lands in `.reticle/` in your project, and it is yours. Three kinds of
|
|
|
27
27
|
|
|
28
28
|
So: **drive staging.** Not because the risk is large, but because it is real and avoiding it is free.
|
|
29
29
|
|
|
30
|
-
Network bodies are **not** captured by default. When you turn body capture on (`captureNetworkBodies: true`, or `VITE_RETICLE_CAPTURE_BODIES=1`), redaction runs **before each body is kept**. Built-in rules mask keys such as `password`, `apiKey` and `authorization`, selected token keys, and high-confidence secret shapes such as JWTs and `sk_live_…` keys. Other credential values can remain under names or in formats those rules do not recognize; add app-specific field names with `redact.keys` and use staging. Page content that reaches a verdict is the element text and attributes the assertion needed, not a copy of the DOM.
|
|
30
|
+
Network bodies are **not** captured by default, with one exception: the response body of a failed request (HTTP 400 and up, at most 4 KB) is kept, because it says why the request failed. `captureErrorBodies: false` turns that off too. When you turn body capture on (`captureNetworkBodies: true`, or `VITE_RETICLE_CAPTURE_BODIES=1`), redaction runs **before each body is kept**. Built-in rules mask keys such as `password`, `apiKey` and `authorization`, selected token keys, and high-confidence secret shapes such as JWTs and `sk_live_…` keys. Other credential values can remain under names or in formats those rules do not recognize; add app-specific field names with `redact.keys` and use staging. Page content that reaches a verdict is the element text and attributes the assertion needed, not a copy of the DOM.
|
|
31
31
|
|
|
32
32
|
## What leaves, only if you ask
|
|
33
33
|
|
|
34
|
-
`reticle
|
|
34
|
+
`reticle connect` signs this machine in and binds one repo to one cloud project. Until that has happened, or `RETICLE_API_KEY` is set in the environment, `reticle sync` has nothing to talk to and the sync path is a no-op. The code calls this the no-phone-home default. A key in the environment is how CI syncs with no login and no link, and it goes to the hosted service unless `RETICLE_CLOUD_URL` names another host.
|
|
35
35
|
|
|
36
36
|
Once linked, you choose what syncs:
|
|
37
37
|
|
|
@@ -43,9 +43,9 @@ npx @reticlehq/server config --runs on|off --flows on|off --memory on|off
|
|
|
43
43
|
|
|
44
44
|
The Harness runs on the platform, so the platform sees what it drives: each step's result goes there so it can choose the next one. A secret field is sent by name only; its value is typed in on your machine.
|
|
45
45
|
|
|
46
|
-
**Your apps, for the platform
|
|
46
|
+
**Your apps, for the platform.** While a project is linked, the daemon tells the platform every ten seconds, with or without an app open, which apps on this machine have Reticle connected, so the dashboard can show which apps are live. For each app it sends: a key made from a hash of this machine and the project's folder (the folder path itself never leaves), the project's name (its package name, else its folder's name), the address the app is open at with Reticle's own query parameters removed, the page title, what it is built with (`react`, `vite`, `electron`, …), this machine's name, the Reticle version, and what this daemon can do for the platform. The platform keeps the last report for each app until the project is deleted. Its answer can ask this machine to open one of those apps again, or show you a short notice (for example, to update Reticle), which appears in the daemon's log and on the HUD.
|
|
47
47
|
|
|
48
|
-
**Drives asked for from the platform
|
|
48
|
+
**Drives asked for from the platform (older platforms).** To test an app on your machine, press Run Harness in its HUD or ask your coding agent; the dashboard chat no longer starts drives here. An older platform can still ask: when someone in your workspace asked its chat to drive one of your apps, the daemon drives it here, on your machine: in the tab you have open, or in a browser of its own, headless or in a window, as the chat asked. It only opens addresses on this machine or apps already open here. On a recent platform, the platform decides each step: it sends Reticle tool calls from a fixed list (reading the page, acting on it, asserting, recording and replaying flows), the daemon runs them in that one tab, and sends back what each returned, which includes what the page showed. On an older platform, the daemon drives and sends back each step's result and how the drive ended. Either way the platform keeps the drive as a check you can open in Runs. Unless the request said not to record, the daemon also sends a picture of the tab it is driving, a JPEG about once a second, so the chat can show the drive live and replay it afterwards. Pictures are kept with that check (at most a few minutes' worth per drive) and deleted with the project. A tab the daemon opened, headless or in a window, can be pictured, with Reticle's own panel left out; so can the window `reticle drive` opened, which is pictured as you see it, panel included. A tab in your own browser sends steps only. Unlinking the project stops all of it.
|
|
49
49
|
|
|
50
50
|
## Telemetry, which is separate from all of the above
|
|
51
51
|
|
|
@@ -61,6 +61,8 @@ Telemetry carries no free text. Free text leaves in three ways, each one somethi
|
|
|
61
61
|
|
|
62
62
|
The daemon also fetches a small public file, `https://reticle.sh/hud/notices.v1.json`, for the notices in the HUD's rail. The request carries nothing about you or your project. `RETICLE_TELEMETRY=0` or `DO_NOT_TRACK=1` stops it, and `RETICLE_HUD_NOTICES_URL` points it elsewhere.
|
|
63
63
|
|
|
64
|
+
The one-line installer fetches one public file too, `https://reticle.sh/install/agent-prompt.v1.json`: the prompt it prints for you to paste into your coding agent. It is a plain GET with a three-second timeout that sends nothing about you, your machine or your project. The installer checks the file (a JSON object whose `prompt` is text of at most 4000 characters), removes every control character but the newline, and only prints it; nothing in it is ever run. If the fetch is off, fails or the file does not pass, it prints the copy it carries instead. The same `RETICLE_TELEMETRY=0` or `DO_NOT_TRACK=1` stops the fetch, and `RETICLE_AGENT_PROMPT_URL` points it elsewhere.
|
|
65
|
+
|
|
64
66
|
## What `init` writes to your project
|
|
65
67
|
|
|
66
68
|
Run it with `--dry-run` and it prints the whole plan without writing anything:
|
package/docs/what-is-reticle.mdx
CHANGED
|
@@ -15,7 +15,7 @@ It exists because an agent that writes code cannot otherwise tell whether that c
|
|
|
15
15
|
2. **A local bridge.** The SDK connects over a WebSocket to a daemon on your machine, bound to `127.0.0.1`. The daemon never manages your dev server; it attaches to the app that is running. On first setup, `npx @reticlehq/server init` starts the dev server with your project's own dev script and opens the app.
|
|
16
16
|
3. **An MCP server.** The daemon exposes the app to your agent as tools. `reticle_look` to look, `reticle_act_and_wait` to act and prove in one call, `reticle_observe` to read what the app did, `reticle_assert` to check.
|
|
17
17
|
|
|
18
|
-
Your app's data stays on your machine: no application code, DOM, network traffic, state or console output leaves it. Anonymous usage counts are sent by default and can be [turned off](/telemetry).
|
|
18
|
+
Your app's data stays on your machine until you link a project: before that, no application code, DOM, network traffic, state or console output leaves it, and once linked, what syncs is your choice ([What is recorded](/what-is-recorded)). Anonymous usage counts are sent by default and can be [turned off](/telemetry).
|
|
19
19
|
|
|
20
20
|
## Where it fits
|
|
21
21
|
|
|
@@ -42,7 +42,7 @@ Reticle sits next to several familiar categories, and it works alongside each of
|
|
|
42
42
|
- **A web application you can run**, with a dev build. `init` starts its dev server for you.
|
|
43
43
|
- **A build step it can hook**, or two lines added by hand. [Frameworks](/frameworks) lists what is proven for each.
|
|
44
44
|
- **An agent that speaks MCP.** Claude Code, Cursor, Codex, Copilot, Windsurf, OpenCode and others.
|
|
45
|
-
- **Node 20 or newer.**
|
|
45
|
+
- **Node 20.11 or newer.**
|
|
46
46
|
|
|
47
47
|
Electron and Tauri desktop applications are supported, including the IPC boundary a browser-based tool cannot observe at all.
|
|
48
48
|
|
package/docs/why-reticle.mdx
CHANGED
|
@@ -72,7 +72,7 @@ On raw cost per glance, Chrome DevTools MCP is cheaper: 758 tokens against 815.
|
|
|
72
72
|
|
|
73
73
|
We ran a fix-loop ablation: agents fixed 8 bugs injected into a small fixture app, with Reticle and without it, on a strong model and on a weaker one. **It did not show a fix-rate improvement at either tier.** The strong model fixed 8 of 8 in both conditions and the weaker one 7 of 8 in both, and the Reticle arm made roughly five to six times the tool calls, because driving an app costs more than reading a few short files.
|
|
74
74
|
|
|
75
|
-
The test cannot settle the question in either direction, and the reasons are specific: the fixture is small enough to read whole, several injected bugs were labelled by a comment on the changed line, and "fixed" was checked by a string disappearing rather than by the app behaving. One case pointed each way. The weaker model without Reticle claimed a fix it never applied, and the live re-check caught that with Reticle; with Reticle, the same model over-edited a stylesheet the string check scored as a pass. The full log is in [`bench/fix-loop/results.md`](https://github.com/reticlehq/reticle/blob/
|
|
75
|
+
The test cannot settle the question in either direction, and the reasons are specific: the fixture is small enough to read whole, several injected bugs were labelled by a comment on the changed line, and "fixed" was checked by a string disappearing rather than by the app behaving. One case pointed each way. The weaker model without Reticle claimed a fix it never applied, and the live re-check caught that with Reticle; with Reticle, the same model over-edited a stylesheet the string check scored as a pass. The full log is in [`bench/fix-loop/results.md`](https://github.com/reticlehq/reticle/blob/ffe58e32a5b5860869be8b164ad68bb5d23d69e9/bench/fix-loop/results.md), kept in git history since the benchmark was retired.
|
|
76
76
|
|
|
77
77
|
A separate, smaller measurement of the source pointer alone found the same fix rate with and without it (6 of 6) and fewer tool calls with it (12 against 22). The pointer removed the search; it did not make the agent more capable.
|
|
78
78
|
|
package/package.json
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@reticlehq/server",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.7.0",
|
|
4
|
+
"mcpName": "io.github.reticlehq/reticle",
|
|
4
5
|
"description": "Reticle CLI, bridge and MCP server: a coding agent drives your running web app from the inside and gets a verdict with evidence, for change verification, access control, accessibility, performance and SEO checks.",
|
|
5
6
|
"type": "module",
|
|
6
7
|
"main": "./dist/index.js",
|
|
@@ -23,11 +24,11 @@
|
|
|
23
24
|
"ws": "^8.21.3",
|
|
24
25
|
"zod": "^3.24.1",
|
|
25
26
|
"zod-to-json-schema": "^3.24.0",
|
|
26
|
-
"@reticlehq/browser": "3.
|
|
27
|
-
"@reticlehq/
|
|
28
|
-
"@reticlehq/engine": "3.6.0",
|
|
27
|
+
"@reticlehq/browser": "3.7.0",
|
|
28
|
+
"@reticlehq/engine": "3.7.0",
|
|
29
29
|
"open-verification": "1.0.0",
|
|
30
|
-
"@reticlehq/
|
|
30
|
+
"@reticlehq/core": "3.7.0",
|
|
31
|
+
"@reticlehq/init": "3.7.0"
|
|
31
32
|
},
|
|
32
33
|
"devDependencies": {
|
|
33
34
|
"@types/pngjs": "^6.0.5",
|