@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
|
@@ -1,78 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The page the tutorial drives when the user has no app of their own yet.
|
|
3
|
-
*
|
|
4
|
-
* `reticle tutorial` used to print four steps and stop. Printing is not teaching: the reader is told
|
|
5
|
-
* that a verdict is the point, and then watches nothing produce one. So the tour now RUNS — against a
|
|
6
|
-
* page served from here, because the alternative (drive whatever is in front of the user) is how a
|
|
7
|
-
* first run ends on a login wall, and a tutorial that fails on step one teaches that Reticle does not
|
|
8
|
-
* work.
|
|
9
|
-
*
|
|
10
|
-
* It carries the real SDK, not a stub. A demo instrumented by something other than the thing being
|
|
11
|
-
* demonstrated proves nothing about the thing being demonstrated.
|
|
12
|
-
*
|
|
13
|
-
* WHY THERE IS NO IMPORT MAP WRITTEN DOWN HERE. The SDK is ESM with bare specifiers, the shipped
|
|
14
|
-
* server has no bundler, and the obvious fix — a hand-written map of specifier to path — is the exact
|
|
15
|
-
* defect this repository keeps paying for: two lists that must agree, where the one nobody updated is
|
|
16
|
-
* the one that breaks. A dependency added to the SDK would leave this map short by one, the page
|
|
17
|
-
* would fail to load a module, and the tour would report that the user's setup is broken.
|
|
18
|
-
*
|
|
19
|
-
* So the map is DISCOVERED. Start at the SDK entry, scan the files beside it for bare specifiers,
|
|
20
|
-
* resolve each one, and repeat. It cannot be short by one, because nothing here knows the names.
|
|
21
|
-
*
|
|
22
|
-
* The walk follows imports out of OUR packages only; a third-party one is mounted whole and not
|
|
23
|
-
* read. That is a deliberate line, not an oversight. Reading zod means walking several thousand
|
|
24
|
-
* files to learn something that has not changed in this repository's lifetime, and it measurably
|
|
25
|
-
* cost about a minute — on the one command whose whole job is a good first impression. The drift
|
|
26
|
-
* this guards against is our own SDK gaining a dependency, which is the thing that actually moves;
|
|
27
|
-
* a third-party leaf that grows a bare runtime import would fail loudly on the page instead, which
|
|
28
|
-
* is a worse message but not a silent one.
|
|
29
|
-
*/
|
|
30
|
-
/** The signal the demo app fires when it saves — the consequence the tour declares in advance. */
|
|
31
|
-
export declare const DEMO_SIGNAL = "demo:saved";
|
|
32
|
-
/** Controls the tour points at. Named here so the page and the run cannot disagree about them. */
|
|
33
|
-
export declare const DemoTestId: {
|
|
34
|
-
readonly SAVE: "demo-save";
|
|
35
|
-
readonly NAME: "demo-name";
|
|
36
|
-
readonly STATUS: "demo-status";
|
|
37
|
-
};
|
|
38
|
-
export interface SdkMount {
|
|
39
|
-
/** URL prefix the page fetches under. */
|
|
40
|
-
prefix: string;
|
|
41
|
-
/** Directory on disk it serves from. */
|
|
42
|
-
dir: string;
|
|
43
|
-
}
|
|
44
|
-
export interface SdkGraph {
|
|
45
|
-
/** Bare specifier to the URL the page should load it from. */
|
|
46
|
-
imports: Record<string, string>;
|
|
47
|
-
mounts: SdkMount[];
|
|
48
|
-
/** URL of the SDK entry module itself. */
|
|
49
|
-
entry: string;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Resolve the SDK and everything it reaches, as URLs a page can fetch.
|
|
53
|
-
*
|
|
54
|
-
* `resolve` is injected so a test can describe a dependency graph without one existing on disk —
|
|
55
|
-
* and because the real one is `import.meta.resolve`, which answers against THIS module's location
|
|
56
|
-
* and so cannot be pointed at a fixture.
|
|
57
|
-
*/
|
|
58
|
-
export declare function sdkGraph(resolve?: (spec: string) => string): SdkGraph;
|
|
59
|
-
/**
|
|
60
|
-
* The demo app, and the one line that makes it verifiable.
|
|
61
|
-
*
|
|
62
|
-
* Saving fires a SIGNAL as well as changing the text. Both are here on purpose: the text is what a
|
|
63
|
-
* person sees, the signal is what the app itself says happened, and the tour waits on the signal
|
|
64
|
-
* because that is the difference it exists to teach — a rendered word can be a coincidence, and an
|
|
65
|
-
* app declaring its own state cannot.
|
|
66
|
-
*/
|
|
67
|
-
export declare function demoPageHtml(graph: SdkGraph, token: string, bridgeUrl: string): string;
|
|
68
|
-
/**
|
|
69
|
-
* Serve the demo on a port the OS picks.
|
|
70
|
-
*
|
|
71
|
-
* Port 0 rather than a chosen number: this starts while a daemon, a dev server and possibly another
|
|
72
|
-
* copy of this tour are already running, and a tutorial whose first act is a port collision has
|
|
73
|
-
* taught the wrong lesson about the product.
|
|
74
|
-
*/
|
|
75
|
-
export declare function serveDemoPage(html: string, graph: SdkGraph): Promise<{
|
|
76
|
-
url: string;
|
|
77
|
-
close: () => Promise<void>;
|
|
78
|
-
}>;
|
|
@@ -1,249 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The page the tutorial drives when the user has no app of their own yet.
|
|
3
|
-
*
|
|
4
|
-
* `reticle tutorial` used to print four steps and stop. Printing is not teaching: the reader is told
|
|
5
|
-
* that a verdict is the point, and then watches nothing produce one. So the tour now RUNS — against a
|
|
6
|
-
* page served from here, because the alternative (drive whatever is in front of the user) is how a
|
|
7
|
-
* first run ends on a login wall, and a tutorial that fails on step one teaches that Reticle does not
|
|
8
|
-
* work.
|
|
9
|
-
*
|
|
10
|
-
* It carries the real SDK, not a stub. A demo instrumented by something other than the thing being
|
|
11
|
-
* demonstrated proves nothing about the thing being demonstrated.
|
|
12
|
-
*
|
|
13
|
-
* WHY THERE IS NO IMPORT MAP WRITTEN DOWN HERE. The SDK is ESM with bare specifiers, the shipped
|
|
14
|
-
* server has no bundler, and the obvious fix — a hand-written map of specifier to path — is the exact
|
|
15
|
-
* defect this repository keeps paying for: two lists that must agree, where the one nobody updated is
|
|
16
|
-
* the one that breaks. A dependency added to the SDK would leave this map short by one, the page
|
|
17
|
-
* would fail to load a module, and the tour would report that the user's setup is broken.
|
|
18
|
-
*
|
|
19
|
-
* So the map is DISCOVERED. Start at the SDK entry, scan the files beside it for bare specifiers,
|
|
20
|
-
* resolve each one, and repeat. It cannot be short by one, because nothing here knows the names.
|
|
21
|
-
*
|
|
22
|
-
* The walk follows imports out of OUR packages only; a third-party one is mounted whole and not
|
|
23
|
-
* read. That is a deliberate line, not an oversight. Reading zod means walking several thousand
|
|
24
|
-
* files to learn something that has not changed in this repository's lifetime, and it measurably
|
|
25
|
-
* cost about a minute — on the one command whose whole job is a good first impression. The drift
|
|
26
|
-
* this guards against is our own SDK gaining a dependency, which is the thing that actually moves;
|
|
27
|
-
* a third-party leaf that grows a bare runtime import would fail loudly on the page instead, which
|
|
28
|
-
* is a worse message but not a silent one.
|
|
29
|
-
*/
|
|
30
|
-
import { fileURLToPath } from 'node:url';
|
|
31
|
-
import { createServer } from 'node:http';
|
|
32
|
-
import { dirname, join, relative, extname, sep } from 'node:path';
|
|
33
|
-
import { existsSync, readFileSync, readdirSync } from 'node:fs';
|
|
34
|
-
/** Where the tour starts. Everything else on the page is reached from here. */
|
|
35
|
-
const SDK_ENTRY = '@reticlehq/browser';
|
|
36
|
-
/** The signal the demo app fires when it saves — the consequence the tour declares in advance. */
|
|
37
|
-
export const DEMO_SIGNAL = 'demo:saved';
|
|
38
|
-
/** Controls the tour points at. Named here so the page and the run cannot disagree about them. */
|
|
39
|
-
export const DemoTestId = {
|
|
40
|
-
SAVE: 'demo-save',
|
|
41
|
-
NAME: 'demo-name',
|
|
42
|
-
STATUS: 'demo-status',
|
|
43
|
-
};
|
|
44
|
-
/** What the status line says before anything has been proved. */
|
|
45
|
-
const STATUS_BEFORE = 'nothing saved yet';
|
|
46
|
-
/** Bare specifiers this cannot serve and must not try to: the page is a browser. */
|
|
47
|
-
const NOT_SERVABLE = /^node:/;
|
|
48
|
-
/**
|
|
49
|
-
* The packages whose imports are followed. See the note at the top for why the walk stops here.
|
|
50
|
-
*
|
|
51
|
-
* `open-verification` is listed by NAME because it is ours without being in the scope: it left the
|
|
52
|
-
* org to stand on its own as the specification, and matching on `@reticlehq/` alone would silently
|
|
53
|
-
* demote it to an unscanned third-party leaf. Today its only dependency is zod, which core already
|
|
54
|
-
* pulls in, so nothing would have broken yet — which is exactly the kind of gap that is cheap now
|
|
55
|
-
* and expensive on the day the spec grows a second dependency.
|
|
56
|
-
*/
|
|
57
|
-
const OURS = /^(@reticlehq\/|open-verification$)/;
|
|
58
|
-
const JS_CONTENT_TYPE = 'text/javascript; charset=utf-8';
|
|
59
|
-
const HTML_CONTENT_TYPE = 'text/html; charset=utf-8';
|
|
60
|
-
/**
|
|
61
|
-
* A compiled package's own imports, read off disk.
|
|
62
|
-
*
|
|
63
|
-
* Test files are skipped: `dist` carries compiled specs, and those import `vitest` and `node:fs`,
|
|
64
|
-
* which are not part of what a page loads and would send the walk looking for packages that only
|
|
65
|
-
* exist in this repository.
|
|
66
|
-
*/
|
|
67
|
-
function bareSpecifiersIn(dir) {
|
|
68
|
-
const found = new Set();
|
|
69
|
-
const walk = (at) => {
|
|
70
|
-
for (const entry of readdirSync(at, { withFileTypes: true })) {
|
|
71
|
-
const name = entry.name;
|
|
72
|
-
const path = join(at, name);
|
|
73
|
-
if (entry.isDirectory()) {
|
|
74
|
-
if ('node_modules' !== name)
|
|
75
|
-
walk(path);
|
|
76
|
-
continue;
|
|
77
|
-
}
|
|
78
|
-
if (!name.endsWith('.js') || name.endsWith('.test.js'))
|
|
79
|
-
continue;
|
|
80
|
-
// `from` as a keyword, not the tail of a string: core's `z.discriminatedUnion('from', [...])`
|
|
81
|
-
// read as an import of everything up to the next quote. A specifier never holds whitespace.
|
|
82
|
-
for (const match of readFileSync(path, 'utf8').matchAll(/(?<![\w$.'"])from\s*'([^.'\s][^'\s]*)'/g)) {
|
|
83
|
-
const spec = match[1];
|
|
84
|
-
if (spec !== undefined && !NOT_SERVABLE.test(spec))
|
|
85
|
-
found.add(spec);
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
};
|
|
89
|
-
walk(dir);
|
|
90
|
-
return found;
|
|
91
|
-
}
|
|
92
|
-
/** The directory holding a resolved entry's `package.json` — what has to be mounted whole. */
|
|
93
|
-
function packageRootOf(entryPath) {
|
|
94
|
-
let at = dirname(entryPath);
|
|
95
|
-
for (;;) {
|
|
96
|
-
if (existsSync(join(at, 'package.json')))
|
|
97
|
-
return at;
|
|
98
|
-
const up = dirname(at);
|
|
99
|
-
if (up === at)
|
|
100
|
-
return undefined;
|
|
101
|
-
at = up;
|
|
102
|
-
}
|
|
103
|
-
}
|
|
104
|
-
/**
|
|
105
|
-
* Resolve the SDK and everything it reaches, as URLs a page can fetch.
|
|
106
|
-
*
|
|
107
|
-
* `resolve` is injected so a test can describe a dependency graph without one existing on disk —
|
|
108
|
-
* and because the real one is `import.meta.resolve`, which answers against THIS module's location
|
|
109
|
-
* and so cannot be pointed at a fixture.
|
|
110
|
-
*/
|
|
111
|
-
export function sdkGraph(resolve = defaultResolve) {
|
|
112
|
-
const imports = {};
|
|
113
|
-
const mounts = [];
|
|
114
|
-
const roots = new Map();
|
|
115
|
-
const queue = [SDK_ENTRY];
|
|
116
|
-
const seen = new Set();
|
|
117
|
-
let entry = '';
|
|
118
|
-
while (queue.length > 0) {
|
|
119
|
-
const spec = queue.shift();
|
|
120
|
-
if (spec === undefined || seen.has(spec))
|
|
121
|
-
continue;
|
|
122
|
-
seen.add(spec);
|
|
123
|
-
const entryPath = resolve(spec);
|
|
124
|
-
const root = packageRootOf(entryPath);
|
|
125
|
-
if (root === undefined) {
|
|
126
|
-
throw new Error(`the demo page cannot serve ${spec}: it resolves outside any package`);
|
|
127
|
-
}
|
|
128
|
-
let prefix = roots.get(root);
|
|
129
|
-
if (prefix === undefined) {
|
|
130
|
-
prefix = `/sdk/${String(mounts.length)}/`;
|
|
131
|
-
roots.set(root, prefix);
|
|
132
|
-
mounts.push({ prefix, dir: root });
|
|
133
|
-
}
|
|
134
|
-
const url = prefix + relative(root, entryPath).split(sep).join('/');
|
|
135
|
-
if (SDK_ENTRY === spec)
|
|
136
|
-
entry = url;
|
|
137
|
-
else
|
|
138
|
-
imports[spec] = url;
|
|
139
|
-
if (OURS.test(spec)) {
|
|
140
|
-
for (const next of bareSpecifiersIn(dirname(entryPath)))
|
|
141
|
-
queue.push(next);
|
|
142
|
-
}
|
|
143
|
-
}
|
|
144
|
-
return { imports, mounts, entry };
|
|
145
|
-
}
|
|
146
|
-
function defaultResolve(spec) {
|
|
147
|
-
return fileURLToPath(import.meta.resolve(spec));
|
|
148
|
-
}
|
|
149
|
-
/**
|
|
150
|
-
* The demo app, and the one line that makes it verifiable.
|
|
151
|
-
*
|
|
152
|
-
* Saving fires a SIGNAL as well as changing the text. Both are here on purpose: the text is what a
|
|
153
|
-
* person sees, the signal is what the app itself says happened, and the tour waits on the signal
|
|
154
|
-
* because that is the difference it exists to teach — a rendered word can be a coincidence, and an
|
|
155
|
-
* app declaring its own state cannot.
|
|
156
|
-
*/
|
|
157
|
-
export function demoPageHtml(graph, token, bridgeUrl) {
|
|
158
|
-
const importMap = JSON.stringify({ imports: graph.imports });
|
|
159
|
-
const connect = JSON.stringify({ session: 'demo', url: bridgeUrl, token });
|
|
160
|
-
return `<!doctype html>
|
|
161
|
-
<html lang="en"><head><meta charset="utf-8"><title>Reticle demo</title>
|
|
162
|
-
<script type="importmap">${importMap}</script>
|
|
163
|
-
<style>
|
|
164
|
-
body{font:16px/1.5 system-ui,sans-serif;margin:0;padding:2.5rem 1.5rem;max-width:34rem}
|
|
165
|
-
h1{font-size:1.3rem;margin:0 0 .25rem}
|
|
166
|
-
p.lede{color:#555;margin:0 0 2rem}
|
|
167
|
-
label{display:block;font-weight:600;margin:0 0 .4rem}
|
|
168
|
-
input{font:inherit;padding:.5rem .6rem;width:100%;box-sizing:border-box;border:1px solid #bbb;border-radius:6px}
|
|
169
|
-
button{font:inherit;margin-top:1rem;padding:.55rem 1.1rem;border:0;border-radius:6px;background:#111;color:#fff;cursor:pointer}
|
|
170
|
-
p.status{margin-top:1.5rem;padding:.75rem;background:#f4f4f5;border-radius:6px}
|
|
171
|
-
</style></head>
|
|
172
|
-
<body>
|
|
173
|
-
<h1>Reticle demo</h1>
|
|
174
|
-
<p class="lede">A tiny app, instrumented with the real SDK. The tutorial is about to drive it.</p>
|
|
175
|
-
<label for="${DemoTestId.NAME}">Display name</label>
|
|
176
|
-
<input id="${DemoTestId.NAME}" data-testid="${DemoTestId.NAME}" value="Ada">
|
|
177
|
-
<button data-testid="${DemoTestId.SAVE}">Save</button>
|
|
178
|
-
<p class="status" data-testid="${DemoTestId.STATUS}">${STATUS_BEFORE}</p>
|
|
179
|
-
<script type="module">
|
|
180
|
-
import { reticle } from ${JSON.stringify(graph.entry)};
|
|
181
|
-
reticle.connect(${connect});
|
|
182
|
-
const status = document.querySelector('[data-testid="${DemoTestId.STATUS}"]');
|
|
183
|
-
document.querySelector('[data-testid="${DemoTestId.SAVE}"]').addEventListener('click', () => {
|
|
184
|
-
const name = document.querySelector('[data-testid="${DemoTestId.NAME}"]').value;
|
|
185
|
-
status.textContent = 'saved ' + name;
|
|
186
|
-
reticle.signal(${JSON.stringify(DEMO_SIGNAL)}, { name });
|
|
187
|
-
});
|
|
188
|
-
</script>
|
|
189
|
-
</body></html>`;
|
|
190
|
-
}
|
|
191
|
-
/**
|
|
192
|
-
* Serve the demo on a port the OS picks.
|
|
193
|
-
*
|
|
194
|
-
* Port 0 rather than a chosen number: this starts while a daemon, a dev server and possibly another
|
|
195
|
-
* copy of this tour are already running, and a tutorial whose first act is a port collision has
|
|
196
|
-
* taught the wrong lesson about the product.
|
|
197
|
-
*/
|
|
198
|
-
export function serveDemoPage(html, graph) {
|
|
199
|
-
const server = createServer((req, res) => {
|
|
200
|
-
const path = (req.url ?? '/').split('?')[0] ?? '/';
|
|
201
|
-
if ('/' === path) {
|
|
202
|
-
res.writeHead(200, { 'content-type': HTML_CONTENT_TYPE });
|
|
203
|
-
res.end(html);
|
|
204
|
-
return;
|
|
205
|
-
}
|
|
206
|
-
for (const mount of graph.mounts) {
|
|
207
|
-
if (!path.startsWith(mount.prefix))
|
|
208
|
-
continue;
|
|
209
|
-
const file = join(mount.dir, path.slice(mount.prefix.length));
|
|
210
|
-
// A request that climbed out of the mount is not served, whatever it points at.
|
|
211
|
-
if (!file.startsWith(mount.dir + sep))
|
|
212
|
-
break;
|
|
213
|
-
// One read, no prior exists/stat check: a missing file or a directory throws here, and there
|
|
214
|
-
// is no window between a check and the read for the path to change under it.
|
|
215
|
-
let body;
|
|
216
|
-
try {
|
|
217
|
-
body = readFileSync(file);
|
|
218
|
-
}
|
|
219
|
-
catch {
|
|
220
|
-
break;
|
|
221
|
-
}
|
|
222
|
-
res.writeHead(200, {
|
|
223
|
-
'content-type': '.js' === extname(file) ? JS_CONTENT_TYPE : 'application/octet-stream',
|
|
224
|
-
});
|
|
225
|
-
res.end(body);
|
|
226
|
-
return;
|
|
227
|
-
}
|
|
228
|
-
res.writeHead(404);
|
|
229
|
-
res.end('not found');
|
|
230
|
-
});
|
|
231
|
-
return new Promise((resolve, reject) => {
|
|
232
|
-
server.once('error', reject);
|
|
233
|
-
server.listen(0, '127.0.0.1', () => {
|
|
234
|
-
const address = server.address();
|
|
235
|
-
if (null === address || 'string' === typeof address) {
|
|
236
|
-
reject(new Error('the demo page could not be served: no port was assigned'));
|
|
237
|
-
return;
|
|
238
|
-
}
|
|
239
|
-
resolve({
|
|
240
|
-
url: `http://127.0.0.1:${String(address.port)}/`,
|
|
241
|
-
close: () => new Promise((done) => {
|
|
242
|
-
server.close(() => {
|
|
243
|
-
done();
|
|
244
|
-
});
|
|
245
|
-
}),
|
|
246
|
-
});
|
|
247
|
-
});
|
|
248
|
-
});
|
|
249
|
-
}
|
|
@@ -1,38 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The tutorial, run rather than printed.
|
|
3
|
-
*
|
|
4
|
-
* `reticle tutorial` described four steps and produced nothing. The last of those steps says that a
|
|
5
|
-
* drive without a verdict has no result — and the tour itself ended without one, which is the lesson
|
|
6
|
-
* taught by counter-example. So the same four steps now execute, against the demo page, and every
|
|
7
|
-
* line the reader sees is a thing that actually happened.
|
|
8
|
-
*
|
|
9
|
-
* The steps are NOT re-listed here. They come from `tutorialScript`, the same source the printed tour
|
|
10
|
-
* reads, because two descriptions of one sequence drift and the one nobody updated is the one
|
|
11
|
-
* somebody follows.
|
|
12
|
-
*
|
|
13
|
-
* Tools are called in-process rather than over the daemon's MCP transport. This command starts the
|
|
14
|
-
* daemon it drives, so it already holds the session; going back out over a socket to reach a server
|
|
15
|
-
* inside this process would add a transport that can fail to a tour whose job is to not fail. The
|
|
16
|
-
* funnel telemetry is unaffected either way — `runTool` is the chokepoint that reports it, and both
|
|
17
|
-
* routes pass through it.
|
|
18
|
-
*/
|
|
19
|
-
export interface DemoTourOptions {
|
|
20
|
-
port: number;
|
|
21
|
-
headless: boolean;
|
|
22
|
-
/** Every line the reader sees, in order. Injected so a test reads the tour instead of a terminal. */
|
|
23
|
-
say: (line: string) => void;
|
|
24
|
-
now?: () => number;
|
|
25
|
-
}
|
|
26
|
-
/** A tour either reached a verdict or it did not; the exit code says which. */
|
|
27
|
-
export interface DemoTourResult {
|
|
28
|
-
code: number;
|
|
29
|
-
verified: string | undefined;
|
|
30
|
-
}
|
|
31
|
-
/**
|
|
32
|
-
* Run the tour, and report whether it ended at a proof.
|
|
33
|
-
*
|
|
34
|
-
* A step that cannot be taken stops the tour and says which one. Carrying on past a failed step
|
|
35
|
-
* would end at a verdict taken against a page the earlier steps never reached — which is precisely
|
|
36
|
-
* the false green the fourth step is there to warn about.
|
|
37
|
-
*/
|
|
38
|
-
export declare function runDemoTour(options: DemoTourOptions): Promise<DemoTourResult>;
|
|
@@ -1,138 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The tutorial, run rather than printed.
|
|
3
|
-
*
|
|
4
|
-
* `reticle tutorial` described four steps and produced nothing. The last of those steps says that a
|
|
5
|
-
* drive without a verdict has no result — and the tour itself ended without one, which is the lesson
|
|
6
|
-
* taught by counter-example. So the same four steps now execute, against the demo page, and every
|
|
7
|
-
* line the reader sees is a thing that actually happened.
|
|
8
|
-
*
|
|
9
|
-
* The steps are NOT re-listed here. They come from `tutorialScript`, the same source the printed tour
|
|
10
|
-
* reads, because two descriptions of one sequence drift and the one nobody updated is the one
|
|
11
|
-
* somebody follows.
|
|
12
|
-
*
|
|
13
|
-
* Tools are called in-process rather than over the daemon's MCP transport. This command starts the
|
|
14
|
-
* daemon it drives, so it already holds the session; going back out over a socket to reach a server
|
|
15
|
-
* inside this process would add a transport that can fail to a tour whose job is to not fail. The
|
|
16
|
-
* funnel telemetry is unaffected either way — `runTool` is the chokepoint that reports it, and both
|
|
17
|
-
* routes pass through it.
|
|
18
|
-
*/
|
|
19
|
-
import { ReticleTool } from '@reticlehq/core';
|
|
20
|
-
// TOOLS comes through the package barrel rather than from `surface/tools/tools.js` directly. That
|
|
21
|
-
// aggregator composes the tool arrays out of five directories, and anything importing it back is how
|
|
22
|
-
// this package accumulated cycles; the barrel sits above both it and this file, which is the
|
|
23
|
-
// direction that does not close a loop.
|
|
24
|
-
import { start, TOOLS } from '../../../index.js';
|
|
25
|
-
import { runTool } from '../../../surface/tools/invoke-tool.js';
|
|
26
|
-
import { buildVerifyDeps } from '../cli-verify.js';
|
|
27
|
-
import { readOrCreatePairingTokenSync, defaultPairingTokenDir, } from '../../../portal/bridge/pairing-token.js';
|
|
28
|
-
import { tutorialScript, TutorialAudience, demoPlan } from '../tutorial.js';
|
|
29
|
-
import { sdkGraph, demoPageHtml, serveDemoPage, DEMO_SIGNAL } from './demo-page.js';
|
|
30
|
-
/** How long to wait for the demo page to dial the bridge before giving up on it. */
|
|
31
|
-
const SESSION_TIMEOUT_MS = 30_000;
|
|
32
|
-
const SESSION_POLL_MS = 250;
|
|
33
|
-
/** Only `verified: "yes"` is a pass — see the contract every verdict tool here is held to. */
|
|
34
|
-
const PROVED = 'yes';
|
|
35
|
-
function toolNamed(name) {
|
|
36
|
-
const found = TOOLS.find((t) => t.name === name);
|
|
37
|
-
if (found === undefined) {
|
|
38
|
-
throw new Error(`the tutorial cannot run: ${name} is not in the tool registry`);
|
|
39
|
-
}
|
|
40
|
-
return found;
|
|
41
|
-
}
|
|
42
|
-
function asRecord(value) {
|
|
43
|
-
return 'object' === typeof value && null !== value ? value : {};
|
|
44
|
-
}
|
|
45
|
-
function asText(value) {
|
|
46
|
-
return 'string' === typeof value ? value : undefined;
|
|
47
|
-
}
|
|
48
|
-
/** The controls `reticle_query` found, in the shape the safety rule reads them. */
|
|
49
|
-
function controlsIn(result) {
|
|
50
|
-
const raw = asRecord(result)['elements'];
|
|
51
|
-
if (!Array.isArray(raw))
|
|
52
|
-
return [];
|
|
53
|
-
const out = [];
|
|
54
|
-
for (const item of raw) {
|
|
55
|
-
const el = asRecord(item);
|
|
56
|
-
const ref = asText(el['ref']);
|
|
57
|
-
const name = asText(el['name']);
|
|
58
|
-
if (ref === undefined || name === undefined)
|
|
59
|
-
continue;
|
|
60
|
-
const role = asText(el['role']);
|
|
61
|
-
out.push(role === undefined ? { ref, name } : { ref, name, role });
|
|
62
|
-
}
|
|
63
|
-
return out;
|
|
64
|
-
}
|
|
65
|
-
async function waitForSession(running, now) {
|
|
66
|
-
const deadline = now() + SESSION_TIMEOUT_MS;
|
|
67
|
-
while (now() < deadline) {
|
|
68
|
-
if (running.bridge.sessions.count() > 0)
|
|
69
|
-
return true;
|
|
70
|
-
await new Promise((resolve) => setTimeout(resolve, SESSION_POLL_MS));
|
|
71
|
-
}
|
|
72
|
-
return running.bridge.sessions.count() > 0;
|
|
73
|
-
}
|
|
74
|
-
/**
|
|
75
|
-
* Run the tour, and report whether it ended at a proof.
|
|
76
|
-
*
|
|
77
|
-
* A step that cannot be taken stops the tour and says which one. Carrying on past a failed step
|
|
78
|
-
* would end at a verdict taken against a page the earlier steps never reached — which is precisely
|
|
79
|
-
* the false green the fourth step is there to warn about.
|
|
80
|
-
*/
|
|
81
|
-
export async function runDemoTour(options) {
|
|
82
|
-
const now = options.now ?? (() => Date.now());
|
|
83
|
-
const steps = new Map(tutorialScript(TutorialAudience.HUMAN).map((s) => [s.id, s]));
|
|
84
|
-
const announce = (id) => {
|
|
85
|
-
const step = steps.get(id);
|
|
86
|
-
if (step === undefined)
|
|
87
|
-
return;
|
|
88
|
-
options.say('');
|
|
89
|
-
options.say(step.say);
|
|
90
|
-
options.say(` why: ${step.why}`);
|
|
91
|
-
};
|
|
92
|
-
const graph = sdkGraph();
|
|
93
|
-
const token = readOrCreatePairingTokenSync(defaultPairingTokenDir()) ?? '';
|
|
94
|
-
const bridgeUrl = `ws://localhost:${String(options.port)}/reticle`;
|
|
95
|
-
const page = await serveDemoPage(demoPageHtml(graph, token, bridgeUrl), graph);
|
|
96
|
-
let running;
|
|
97
|
-
try {
|
|
98
|
-
running = await start({ port: options.port, driveUrl: page.url, headless: options.headless });
|
|
99
|
-
const deps = buildVerifyDeps(running, process.cwd(), now);
|
|
100
|
-
const call = async (name, args) => await runTool(toolNamed(name), deps, args);
|
|
101
|
-
announce('connect');
|
|
102
|
-
if (!(await waitForSession(running, now))) {
|
|
103
|
-
options.say(' the demo page never dialled the bridge, so there is nothing to show.');
|
|
104
|
-
return { code: 1, verified: undefined };
|
|
105
|
-
}
|
|
106
|
-
options.say(` one session connected: the demo app at ${page.url}`);
|
|
107
|
-
announce('look');
|
|
108
|
-
const snapshot = asRecord(await call(ReticleTool.SNAPSHOT, { mode: 'interactive' }));
|
|
109
|
-
for (const line of (asText(snapshot['tree']) ?? '').split('\n'))
|
|
110
|
-
options.say(` ${line}`);
|
|
111
|
-
announce('declare');
|
|
112
|
-
const found = controlsIn(await call(ReticleTool.QUERY, { role: 'button' }));
|
|
113
|
-
const plan = demoPlan(found);
|
|
114
|
-
if (!plan.ok) {
|
|
115
|
-
options.say(` ${plan.because}`);
|
|
116
|
-
return { code: 1, verified: undefined };
|
|
117
|
-
}
|
|
118
|
-
options.say(` "${plan.name}" is safe to press. Saving should make the app say so itself:`);
|
|
119
|
-
options.say(` reticle_act_and_wait { ref: "${plan.ref}", action: "click", until: {`);
|
|
120
|
-
options.say(` kind: "signal", name: "${DEMO_SIGNAL}" } }`);
|
|
121
|
-
announce('verdict');
|
|
122
|
-
const verdict = asRecord(await call(ReticleTool.ACT_AND_WAIT, {
|
|
123
|
-
ref: plan.ref,
|
|
124
|
-
action: 'click',
|
|
125
|
-
until: { kind: 'signal', name: DEMO_SIGNAL },
|
|
126
|
-
}));
|
|
127
|
-
const verified = asText(verdict['verified']);
|
|
128
|
-
const because = asText(verdict['verifiedReason']) ?? asText(verdict['failureReason']);
|
|
129
|
-
options.say(` verified: ${verified ?? 'unknown'}`);
|
|
130
|
-
if (because !== undefined)
|
|
131
|
-
options.say(` because: ${because}`);
|
|
132
|
-
return { code: PROVED === verified ? 0 : 1, verified };
|
|
133
|
-
}
|
|
134
|
-
finally {
|
|
135
|
-
await page.close();
|
|
136
|
-
await running?.close?.();
|
|
137
|
-
}
|
|
138
|
-
}
|
|
@@ -1,49 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Aggregate many crawl runs into the one number the core claim needs.
|
|
3
|
-
*
|
|
4
|
-
* Detection already exists: `reticle_crawl` drives every reachable control and reports contradictions
|
|
5
|
-
* — two channels disagreeing about the same click. It found `swallowed-500-login` and, separately,
|
|
6
|
-
* `ui-advanced-request-failed` on a control whose assertion was green, neither of them planted.
|
|
7
|
-
*
|
|
8
|
-
* What was missing is the arithmetic that turns those into evidence. The claim worth making is not
|
|
9
|
-
* "Reticle can find bugs"; it is:
|
|
10
|
-
*
|
|
11
|
-
* "Run over N already-merged, already-green changes, it found X real bugs their own tests
|
|
12
|
-
* certified as passing."
|
|
13
|
-
*
|
|
14
|
-
* That needs no control arm, which is why it is the cheapest credible proof available: the
|
|
15
|
-
* counterfactual is already established, because those changes SHIPPED. An A/B is the second study,
|
|
16
|
-
* and this tells you where to point it.
|
|
17
|
-
*
|
|
18
|
-
* Pure functions over already-collected reports — the driving is `reticle_crawl`'s job, and running
|
|
19
|
-
* it across a commit range is a shell loop. This is only the part that must not be done by eye.
|
|
20
|
-
*/
|
|
21
|
-
export interface HuntAnomaly {
|
|
22
|
-
kind: string;
|
|
23
|
-
ref?: string;
|
|
24
|
-
desc?: string;
|
|
25
|
-
detail?: string;
|
|
26
|
-
}
|
|
27
|
-
/** One crawl over one checkout. `label` is whatever identifies it — a commit sha, a PR number. */
|
|
28
|
-
export interface HuntRun {
|
|
29
|
-
label: string;
|
|
30
|
-
anomalies: readonly HuntAnomaly[];
|
|
31
|
-
/** Controls actually driven. A run that drove nothing proves nothing and is reported separately. */
|
|
32
|
-
stepsRun?: number;
|
|
33
|
-
}
|
|
34
|
-
interface HuntSummary {
|
|
35
|
-
runs: number;
|
|
36
|
-
/** Runs that actually drove at least one control. The denominator that can honestly be quoted. */
|
|
37
|
-
runsWithCoverage: number;
|
|
38
|
-
/** Runs where at least one CONTRADICTION was found — the headline numerator. */
|
|
39
|
-
runsWithContradictions: number;
|
|
40
|
-
contradictions: number;
|
|
41
|
-
/** Single-channel faults (console errors, failed requests, dead controls). Context, not the claim. */
|
|
42
|
-
singleChannelFaults: number;
|
|
43
|
-
byKind: Record<string, number>;
|
|
44
|
-
/** Labels with contradictions, so each one can be confirmed by hand before it is counted. */
|
|
45
|
-
flagged: string[];
|
|
46
|
-
headline: string;
|
|
47
|
-
}
|
|
48
|
-
export declare function summarizeHunt(runs: readonly HuntRun[]): HuntSummary;
|
|
49
|
-
export {};
|
|
@@ -1,84 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Aggregate many crawl runs into the one number the core claim needs.
|
|
3
|
-
*
|
|
4
|
-
* Detection already exists: `reticle_crawl` drives every reachable control and reports contradictions
|
|
5
|
-
* — two channels disagreeing about the same click. It found `swallowed-500-login` and, separately,
|
|
6
|
-
* `ui-advanced-request-failed` on a control whose assertion was green, neither of them planted.
|
|
7
|
-
*
|
|
8
|
-
* What was missing is the arithmetic that turns those into evidence. The claim worth making is not
|
|
9
|
-
* "Reticle can find bugs"; it is:
|
|
10
|
-
*
|
|
11
|
-
* "Run over N already-merged, already-green changes, it found X real bugs their own tests
|
|
12
|
-
* certified as passing."
|
|
13
|
-
*
|
|
14
|
-
* That needs no control arm, which is why it is the cheapest credible proof available: the
|
|
15
|
-
* counterfactual is already established, because those changes SHIPPED. An A/B is the second study,
|
|
16
|
-
* and this tells you where to point it.
|
|
17
|
-
*
|
|
18
|
-
* Pure functions over already-collected reports — the driving is `reticle_crawl`'s job, and running
|
|
19
|
-
* it across a commit range is a shell loop. This is only the part that must not be done by eye.
|
|
20
|
-
*/
|
|
21
|
-
/** The contradiction kinds — cross-channel disagreement, as opposed to a single-channel fault. */
|
|
22
|
-
const CONTRADICTION_KINDS = [
|
|
23
|
-
'ui-advanced-request-failed',
|
|
24
|
-
'signal-contradicted',
|
|
25
|
-
'response-ignored',
|
|
26
|
-
'duplicate-request',
|
|
27
|
-
'request-never-settled',
|
|
28
|
-
'failure-misattributed',
|
|
29
|
-
];
|
|
30
|
-
const isContradiction = (kind) => CONTRADICTION_KINDS.includes(kind);
|
|
31
|
-
export function summarizeHunt(runs) {
|
|
32
|
-
const byKind = {};
|
|
33
|
-
const flagged = [];
|
|
34
|
-
let contradictions = 0;
|
|
35
|
-
let singleChannelFaults = 0;
|
|
36
|
-
let runsWithCoverage = 0;
|
|
37
|
-
for (const run of runs) {
|
|
38
|
-
// A run that drove nothing is not evidence of cleanliness. Counting it in the denominator would
|
|
39
|
-
// dilute the rate with checkouts where the app never even came up — the arithmetic equivalent of
|
|
40
|
-
// reporting a green because no test ran.
|
|
41
|
-
if ((run.stepsRun ?? 0) > 0)
|
|
42
|
-
runsWithCoverage += 1;
|
|
43
|
-
let flaggedThisRun = false;
|
|
44
|
-
for (const anomaly of run.anomalies) {
|
|
45
|
-
byKind[anomaly.kind] = (byKind[anomaly.kind] ?? 0) + 1;
|
|
46
|
-
if (isContradiction(anomaly.kind)) {
|
|
47
|
-
contradictions += 1;
|
|
48
|
-
flaggedThisRun = true;
|
|
49
|
-
}
|
|
50
|
-
else {
|
|
51
|
-
singleChannelFaults += 1;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
if (flaggedThisRun)
|
|
55
|
-
flagged.push(run.label);
|
|
56
|
-
}
|
|
57
|
-
return {
|
|
58
|
-
runs: runs.length,
|
|
59
|
-
runsWithCoverage,
|
|
60
|
-
runsWithContradictions: flagged.length,
|
|
61
|
-
contradictions,
|
|
62
|
-
singleChannelFaults,
|
|
63
|
-
byKind,
|
|
64
|
-
flagged,
|
|
65
|
-
headline: buildHeadline(runsWithCoverage, flagged.length, contradictions),
|
|
66
|
-
};
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* The sentence that goes in front of someone, phrased so it cannot overstate itself.
|
|
70
|
-
*
|
|
71
|
-
* It counts CHECKOUTS with a finding rather than raw findings, because one broken control clicked
|
|
72
|
-
* five times is one bug and five anomalies. It also says "candidate": every flag still has to be
|
|
73
|
-
* confirmed by hand before it is a bug, and a number that skips that step is the kind of evidence
|
|
74
|
-
* this project exists to distrust.
|
|
75
|
-
*/
|
|
76
|
-
function buildHeadline(withCoverage, flaggedRuns, contradictions) {
|
|
77
|
-
if (0 === withCoverage) {
|
|
78
|
-
return 'no run drove a single control — nothing was measured, which is not the same as nothing being wrong';
|
|
79
|
-
}
|
|
80
|
-
if (0 === flaggedRuns) {
|
|
81
|
-
return `${String(withCoverage)} merged changes crawled, no cross-channel contradictions found — confirm coverage was real before reading this as clean`;
|
|
82
|
-
}
|
|
83
|
-
return `${String(flaggedRuns)} of ${String(withCoverage)} merged, already-green changes carried a candidate false green (${String(contradictions)} contradictions) — each needs manual confirmation before it is counted`;
|
|
84
|
-
}
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The buddy channel. The co-dev experience for the HUMAN: a single ambient line they can park in
|
|
3
|
-
* a statusline or terminal and glance at — never a wall of output, never something they have to ask for.
|
|
4
|
-
*
|
|
5
|
-
* The rule this encodes: say the reassuring thing briefly and the alarming thing specifically. "41 flows
|
|
6
|
-
* nominal" needs no detail; a deviation needs its name, because a status line that says only "1 deviation"
|
|
7
|
-
* forces the human to go digging, which is exactly the work the buddy exists to remove.
|
|
8
|
-
*/
|
|
9
|
-
interface BuddyStatusInput {
|
|
10
|
-
/** Every saved flow. */
|
|
11
|
-
total: number;
|
|
12
|
-
/** Flows with a passing artifact. */
|
|
13
|
-
passing: number;
|
|
14
|
-
/** Flows that changed files put at risk and that have NO passing artifact — the actionable set. */
|
|
15
|
-
deviations: readonly string[];
|
|
16
|
-
/** Flows quarantined as flaky — surfaced, never blocking. */
|
|
17
|
-
quarantined: readonly string[];
|
|
18
|
-
}
|
|
19
|
-
/**
|
|
20
|
-
* One line, safe to print on every save. Shape:
|
|
21
|
-
* `✓ 41 flows nominal`
|
|
22
|
-
* `✗ 2 deviations: checkout, billing · 39 nominal · 1 flaky quarantined`
|
|
23
|
-
*/
|
|
24
|
-
export declare function formatBuddyStatus(input: BuddyStatusInput): string;
|
|
25
|
-
export {};
|