@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,4 +1,5 @@
|
|
|
1
1
|
import { Client } from '@modelcontextprotocol/sdk/client/index.js';
|
|
2
|
+
import { CLI_CLIENT_NAME } from '../../judgement/runs/verification-sync.js';
|
|
2
3
|
import { SSEClientTransport } from '@modelcontextprotocol/sdk/client/sse.js';
|
|
3
4
|
import { LOOPBACK_HOST, MCP_SSE_PATH } from '@reticlehq/core';
|
|
4
5
|
import { TOKEN_QUERY_PARAM } from '../../portal/bridge/token-auth.js';
|
|
@@ -20,12 +21,30 @@ const leaseFailedLine = (url) => `could not open ${url} in a Reticle browser, so
|
|
|
20
21
|
* the caller must hand to `releaseLease`; `{ failed }` is the lease's own refusal, as lines to print —
|
|
21
22
|
* a missing browser, an app that is not up — so nothing is asserted against a page that never opened.
|
|
22
23
|
*/
|
|
23
|
-
export async function leaseIfNoTab(caller, url, sessions
|
|
24
|
+
export async function leaseIfNoTab(caller, url, sessions,
|
|
25
|
+
/** The caller's project `.reticle`, so the lease's runs land where this command looks. */
|
|
26
|
+
root) {
|
|
24
27
|
const open = [...(await sessions())];
|
|
25
28
|
if ('open' !== decideOpen(open, url).action) {
|
|
26
29
|
return open.some((s) => sameDocument(s.url, url)) ? { alreadyAt: true } : {};
|
|
27
30
|
}
|
|
28
|
-
return acquireLease(caller, url);
|
|
31
|
+
return acquireLease(caller, url, false, root);
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Whether the tab named by `sessionId` already shows `url`'s document.
|
|
35
|
+
*
|
|
36
|
+
* Read from the same status the unpinned path reads. A status read that fails, or a session the
|
|
37
|
+
* daemon does not list, answers false: navigating is the old behaviour, so a doubt costs a reload
|
|
38
|
+
* rather than an assert against a page that is not there.
|
|
39
|
+
*/
|
|
40
|
+
async function pinnedTabIsAt(sessions, sessionId, url) {
|
|
41
|
+
try {
|
|
42
|
+
const pinned = (await sessions()).find((s) => s.sessionId === sessionId);
|
|
43
|
+
return pinned !== undefined && sameDocument(pinned.url, url);
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
29
48
|
}
|
|
30
49
|
/**
|
|
31
50
|
* Whether two urls name the same document, ignoring a trailing slash and the hash.
|
|
@@ -50,8 +69,20 @@ function sameDocument(a, b) {
|
|
|
50
69
|
* caller hands to `releaseLease`; `{ failed }` is the lease's own refusal, as lines to print.
|
|
51
70
|
* `init`'s connect proof on a machine with no system browser takes this path directly.
|
|
52
71
|
*/
|
|
53
|
-
export async function acquireLease(caller, url
|
|
54
|
-
|
|
72
|
+
export async function acquireLease(caller, url,
|
|
73
|
+
/** Open it in a window somebody can watch, whatever the daemon was started as. */
|
|
74
|
+
headed,
|
|
75
|
+
/** The `.reticle` the lease's runs belong in: the caller's project, not wherever the page resolves. */
|
|
76
|
+
root) {
|
|
77
|
+
const acquired = await caller.call(ReticleTool.RUN, {
|
|
78
|
+
tool: ReticleTool.LEASE,
|
|
79
|
+
args: {
|
|
80
|
+
action: LeaseAction.ACQUIRE,
|
|
81
|
+
url,
|
|
82
|
+
...(true === headed ? { headed } : {}),
|
|
83
|
+
...(root === undefined ? {} : { root }),
|
|
84
|
+
},
|
|
85
|
+
}, LEASE_TIMEOUT_MS);
|
|
55
86
|
const report = verdictOf(acquired, 'sessionId');
|
|
56
87
|
const sessionId = report?.['sessionId'];
|
|
57
88
|
// `zeroInstall`: the page never dialled in, so the lease supplied Reticle's own reader.
|
|
@@ -84,7 +115,7 @@ export function endpointFor(port, token) {
|
|
|
84
115
|
return url;
|
|
85
116
|
}
|
|
86
117
|
export async function connectOverSse(endpoint) {
|
|
87
|
-
const client = new Client({ name:
|
|
118
|
+
const client = new Client({ name: CLI_CLIENT_NAME, version: '1' }, { capabilities: {} });
|
|
88
119
|
await client.connect(new SSEClientTransport(endpoint));
|
|
89
120
|
return {
|
|
90
121
|
call: async (name, args, timeoutMs) => await client.callTool({ name, arguments: args }, undefined, timeoutMs === undefined ? undefined : { timeout: timeoutMs }),
|
|
@@ -193,8 +224,14 @@ export async function runAdhocVerdict(options) {
|
|
|
193
224
|
// OTHER listening port as the one to open. The caller already said which url; open it here, in
|
|
194
225
|
// a Reticle browser, and hand the lease back when the verdict is in.
|
|
195
226
|
let alreadyAt = false;
|
|
227
|
+
// A named tab gets the same same-document rule: navigating to the url it already shows is a
|
|
228
|
+
// reload, which throws away client-only state (page 2, a half-filled form) and in a desktop
|
|
229
|
+
// window disconnects the session the assert is about to read (#1409).
|
|
230
|
+
if (url !== undefined && options.sessionId !== undefined && options.sessions !== undefined) {
|
|
231
|
+
alreadyAt = await pinnedTabIsAt(options.sessions, options.sessionId, url);
|
|
232
|
+
}
|
|
196
233
|
if (url !== undefined && options.sessionId === undefined && options.sessions !== undefined) {
|
|
197
|
-
const opened = await leaseIfNoTab(caller, url, options.sessions);
|
|
234
|
+
const opened = await leaseIfNoTab(caller, url, options.sessions, options.root);
|
|
198
235
|
if ('failed' in opened)
|
|
199
236
|
return { code: 1, lines: ['verified: unknown', ...opened.failed] };
|
|
200
237
|
leased = opened.leased;
|
|
@@ -240,3 +277,30 @@ export async function runAdhocVerdict(options) {
|
|
|
240
277
|
await caller.close().catch(() => undefined);
|
|
241
278
|
}
|
|
242
279
|
}
|
|
280
|
+
const EXPLORE_ACTION = 'explore';
|
|
281
|
+
const DRIVE_RUNNING = 'running';
|
|
282
|
+
/** The most one explore call waits on its drive (the tool's own ceiling), and the call's slack. */
|
|
283
|
+
const EXPLORE_WAIT_MAX_S = 240;
|
|
284
|
+
const CALL_SLACK_MS = 15_000;
|
|
285
|
+
const MS_PER_S = 1000;
|
|
286
|
+
/**
|
|
287
|
+
* One Harness drive through the daemon, polled to its end or until `budgetMs` runs out.
|
|
288
|
+
*
|
|
289
|
+
* An explore answers `{ status: "running", runId }` when its drive outlasts the call's wait, so a
|
|
290
|
+
* caller that wants the finished report asks again by `runId` rather than starting a second drive.
|
|
291
|
+
*/
|
|
292
|
+
export async function exploreToEnd(caller, args, budgetMs, now = Date.now) {
|
|
293
|
+
const deadline = now() + budgetMs;
|
|
294
|
+
const ask = (more) => {
|
|
295
|
+
const wait = Math.max(0, Math.min(EXPLORE_WAIT_MAX_S, Math.floor((deadline - now() - CALL_SLACK_MS) / MS_PER_S)));
|
|
296
|
+
return caller.call(ReticleTool.VERIFY, { ...more, action: EXPLORE_ACTION, wait }, wait * MS_PER_S + CALL_SLACK_MS);
|
|
297
|
+
};
|
|
298
|
+
let result = await ask(args);
|
|
299
|
+
for (;;) {
|
|
300
|
+
const report = verdictOf(result, 'status');
|
|
301
|
+
const runId = report?.['runId'];
|
|
302
|
+
if (DRIVE_RUNNING !== report?.['status'] || 'string' !== typeof runId || now() >= deadline)
|
|
303
|
+
return result;
|
|
304
|
+
result = await ask({ runId });
|
|
305
|
+
}
|
|
306
|
+
}
|
|
@@ -18,4 +18,27 @@ export declare const GateExit: {
|
|
|
18
18
|
readonly FAIL: 1;
|
|
19
19
|
/** The gate ran and had nothing to judge — no flows recorded. Non-zero, but not a regression. */
|
|
20
20
|
readonly NOTHING_TO_CHECK: 2;
|
|
21
|
+
/** The platform knows a flow that passed before and is broken now: `reticle runs regression`'s code. */
|
|
22
|
+
readonly REGRESSION: 3;
|
|
21
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* The gate's code once the platform has been asked about regressions: a known one fails the build
|
|
26
|
+
* with `reticle runs regression`'s code, whatever the local answer was, so the gate is the one
|
|
27
|
+
* command CI needs. `undefined` (not linked, or the platform did not answer) changes nothing.
|
|
28
|
+
*/
|
|
29
|
+
export declare function gateExitWith(local: number, regressed: number | undefined,
|
|
30
|
+
/** The platform the project is linked to refused its credential: the gate fails closed. */
|
|
31
|
+
refused?: boolean): number;
|
|
32
|
+
/**
|
|
33
|
+
* Said when the linked platform refused the key. A CI pipeline whose key was revoked stayed green
|
|
34
|
+
* and silent: the gate lost the platform's regression report and the only trace was a log line.
|
|
35
|
+
*/
|
|
36
|
+
export declare function msgGateRefused(why: string): string;
|
|
37
|
+
/** Said when the gate had no saved flows to judge, so exit 2 does not read as the change failing. */
|
|
38
|
+
export declare const MSG_GATE_NO_FLOWS: string;
|
|
39
|
+
/**
|
|
40
|
+
* Said when the platform knows a regression, outside a hook. Exit 3 printed only the JSON log, whose
|
|
41
|
+
* coverage field still read "no flows recorded — nothing was checked", so nothing a person read
|
|
42
|
+
* said "regression".
|
|
43
|
+
*/
|
|
44
|
+
export declare function msgGateRegression(broken: readonly unknown[]): string;
|
|
@@ -18,4 +18,49 @@ export const GateExit = {
|
|
|
18
18
|
FAIL: 1,
|
|
19
19
|
/** The gate ran and had nothing to judge — no flows recorded. Non-zero, but not a regression. */
|
|
20
20
|
NOTHING_TO_CHECK: 2,
|
|
21
|
+
/** The platform knows a flow that passed before and is broken now: `reticle runs regression`'s code. */
|
|
22
|
+
REGRESSION: 3,
|
|
21
23
|
};
|
|
24
|
+
/**
|
|
25
|
+
* The gate's code once the platform has been asked about regressions: a known one fails the build
|
|
26
|
+
* with `reticle runs regression`'s code, whatever the local answer was, so the gate is the one
|
|
27
|
+
* command CI needs. `undefined` (not linked, or the platform did not answer) changes nothing.
|
|
28
|
+
*/
|
|
29
|
+
export function gateExitWith(local, regressed,
|
|
30
|
+
/** The platform the project is linked to refused its credential: the gate fails closed. */
|
|
31
|
+
refused = false) {
|
|
32
|
+
if (regressed !== undefined && 0 < regressed)
|
|
33
|
+
return GateExit.REGRESSION;
|
|
34
|
+
return refused && GateExit.PASS === local ? GateExit.FAIL : local;
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Said when the linked platform refused the key. A CI pipeline whose key was revoked stayed green
|
|
38
|
+
* and silent: the gate lost the platform's regression report and the only trace was a log line.
|
|
39
|
+
*/
|
|
40
|
+
export function msgGateRefused(why) {
|
|
41
|
+
return (`Reticle gate: ${why.replace(/\.+$/, '')}. The gate could not ask the platform this project is linked to for its ` +
|
|
42
|
+
'regression report, so it fails closed rather than pass without it.');
|
|
43
|
+
}
|
|
44
|
+
/** Said when the gate had no saved flows to judge, so exit 2 does not read as the change failing. */
|
|
45
|
+
export const MSG_GATE_NO_FLOWS = 'Reticle gate: no saved flows here, so there was nothing to check; this is not a failure of this ' +
|
|
46
|
+
'change. Record one by driving the app with reticle_act_and_wait, or run ' +
|
|
47
|
+
'`reticle verify <url> --explore`, then run the gate again.';
|
|
48
|
+
/**
|
|
49
|
+
* Said when the platform knows a regression, outside a hook. Exit 3 printed only the JSON log, whose
|
|
50
|
+
* coverage field still read "no flows recorded — nothing was checked", so nothing a person read
|
|
51
|
+
* said "regression".
|
|
52
|
+
*/
|
|
53
|
+
export function msgGateRegression(broken) {
|
|
54
|
+
const names = broken.map((entry) => {
|
|
55
|
+
if ('string' === typeof entry)
|
|
56
|
+
return entry;
|
|
57
|
+
const record = 'object' === typeof entry && null !== entry ? entry : {};
|
|
58
|
+
const name = record['flowName'] ?? record['name'];
|
|
59
|
+
const was = record['previousStatus'];
|
|
60
|
+
const now = record['currentStatus'];
|
|
61
|
+
const flow = 'string' === typeof name ? name : 'a flow';
|
|
62
|
+
return 'string' === typeof was && 'string' === typeof now ? `${flow} (${was} → ${now})` : flow;
|
|
63
|
+
});
|
|
64
|
+
return (`Reticle gate: regression — ${names.join(', ')} passed before and fails now on the platform. ` +
|
|
65
|
+
'See `reticle runs regression`.');
|
|
66
|
+
}
|
|
@@ -27,6 +27,8 @@ interface GateHookInput {
|
|
|
27
27
|
coverageRegressed?: readonly string[];
|
|
28
28
|
/** Changed files the browser loaded and never ran a function of. */
|
|
29
29
|
unexecuted?: readonly string[];
|
|
30
|
+
/** Flows the platform says passed before and are broken now. */
|
|
31
|
+
regressed?: number;
|
|
30
32
|
}
|
|
31
33
|
/**
|
|
32
34
|
* The message, or undefined when there is nothing to say.
|
|
@@ -28,9 +28,11 @@ function name(list) {
|
|
|
28
28
|
* interrupted.
|
|
29
29
|
*/
|
|
30
30
|
export function gateHookMessage(exit, input) {
|
|
31
|
-
if (GateExit.FAIL !== exit)
|
|
31
|
+
if (GateExit.FAIL !== exit && GateExit.REGRESSION !== exit)
|
|
32
32
|
return undefined;
|
|
33
33
|
const lines = ['Reticle: this change is not verified.'];
|
|
34
|
+
if (input.regressed !== undefined && 0 < input.regressed)
|
|
35
|
+
lines.push(` ${String(input.regressed)} flow(s) that passed before are broken now — \`reticle runs regression\` names them`);
|
|
34
36
|
if (input.uncovered.length > 0)
|
|
35
37
|
lines.push(` no passing run covers: ${name(input.uncovered)}`);
|
|
36
38
|
if (input.downgraded.length > 0)
|
|
@@ -19,19 +19,19 @@ export declare const DeviceStartSchema: z.ZodObject<{
|
|
|
19
19
|
interval: z.ZodNumber;
|
|
20
20
|
expiresAt: z.ZodNumber;
|
|
21
21
|
}, "strip", z.ZodTypeAny, {
|
|
22
|
-
expiresAt: number;
|
|
23
22
|
deviceCode: string;
|
|
24
23
|
userCode: string;
|
|
25
24
|
verificationUri: string;
|
|
26
25
|
verificationUriComplete: string;
|
|
27
26
|
interval: number;
|
|
28
|
-
}, {
|
|
29
27
|
expiresAt: number;
|
|
28
|
+
}, {
|
|
30
29
|
deviceCode: string;
|
|
31
30
|
userCode: string;
|
|
32
31
|
verificationUri: string;
|
|
33
32
|
verificationUriComplete: string;
|
|
34
33
|
interval: number;
|
|
34
|
+
expiresAt: number;
|
|
35
35
|
}>;
|
|
36
36
|
/**
|
|
37
37
|
* What `/v1/auth/device/token` answers while polling. Everything past `status` is optional because
|
|
@@ -66,6 +66,17 @@ export declare const DevicePollSchema: z.ZodObject<{
|
|
|
66
66
|
id?: string | undefined;
|
|
67
67
|
} | undefined;
|
|
68
68
|
}>;
|
|
69
|
+
/**
|
|
70
|
+
* Where a sign-in started, carried to the approval page as `from` so the platform can attribute the
|
|
71
|
+
* signup. The platform's `/device` reads the same closed set (plus `app`, its own).
|
|
72
|
+
*/
|
|
73
|
+
export declare const LoginOrigin: {
|
|
74
|
+
readonly TERMINAL: "terminal";
|
|
75
|
+
readonly HUD: "hud";
|
|
76
|
+
};
|
|
77
|
+
export type LoginOrigin = (typeof LoginOrigin)[keyof typeof LoginOrigin];
|
|
78
|
+
/** The approval URL with `from` set; a URL that does not parse is left as the cloud sent it. */
|
|
79
|
+
export declare function withLoginOrigin(url: string, from: LoginOrigin): string;
|
|
69
80
|
/**
|
|
70
81
|
* Best-effort open the approval page in the default browser.
|
|
71
82
|
*
|
|
@@ -31,6 +31,23 @@ export const DevicePollSchema = z.object({
|
|
|
31
31
|
token: z.string().optional(),
|
|
32
32
|
org: z.object({ id: z.string().optional(), name: z.string() }).optional(),
|
|
33
33
|
});
|
|
34
|
+
/**
|
|
35
|
+
* Where a sign-in started, carried to the approval page as `from` so the platform can attribute the
|
|
36
|
+
* signup. The platform's `/device` reads the same closed set (plus `app`, its own).
|
|
37
|
+
*/
|
|
38
|
+
export const LoginOrigin = { TERMINAL: 'terminal', HUD: 'hud' };
|
|
39
|
+
const FROM_PARAM = 'from';
|
|
40
|
+
/** The approval URL with `from` set; a URL that does not parse is left as the cloud sent it. */
|
|
41
|
+
export function withLoginOrigin(url, from) {
|
|
42
|
+
try {
|
|
43
|
+
const parsed = new URL(url);
|
|
44
|
+
parsed.searchParams.set(FROM_PARAM, from);
|
|
45
|
+
return parsed.toString();
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
return url;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
34
51
|
/**
|
|
35
52
|
* Best-effort open the approval page in the default browser.
|
|
36
53
|
*
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { existsSync, readFileSync } from 'node:fs';
|
|
2
|
+
import { keychainNoteFor } from './doctor/doctor-signing-line.js';
|
|
2
3
|
import { join } from 'node:path';
|
|
3
4
|
import { devServersForProject, ReticleEnv } from '@reticlehq/core';
|
|
4
5
|
import { readPid, reticleStateHome } from '../daemon/daemon.js';
|
|
@@ -18,6 +19,11 @@ import { CONTRACT_FINGERPRINT } from '@reticlehq/core';
|
|
|
18
19
|
import { CspBasis, diagnoseDesktop, diagnoseObservedWebCsp, diagnoseWebCsp, isDesktopProject, resolveWebCspFindings, webCspOptionsFor, } from '@reticlehq/init';
|
|
19
20
|
import { RETICLE_CONFIG_BASENAME, diagnosePortMismatch, readProjectFramework, readProjectId, readProjectPort, } from './ports/resolve/cli-port.js';
|
|
20
21
|
import { DoctorRow, doctorRow } from './doctor/doctor-rows.js';
|
|
22
|
+
import { coverageLines } from './doctor/doctor-coverage-line.js';
|
|
23
|
+
import { homedir } from 'node:os';
|
|
24
|
+
import { createNodeFileSystem } from '../../memory/project/fs/fs-port.js';
|
|
25
|
+
import { describeUnsynced } from '../../memory/cloud/unsynced-roots.js';
|
|
26
|
+
import { machineUnsyncedRoots } from '../../memory/project/sync-status.js';
|
|
21
27
|
import { attachState, describeAttachState } from '../../surface/mcp/attach-memory.js';
|
|
22
28
|
import { findOccupiedSiblings, siblingListenerNote } from './ports/sibling-ports.js';
|
|
23
29
|
import { daemonsServingProjectElsewhere, resolveDaemonForProject, splitBrainNote, wrongDaemonNote, } from '../daemon/daemon-resolve.js';
|
|
@@ -118,6 +124,11 @@ export async function handleDoctor(port) {
|
|
|
118
124
|
}
|
|
119
125
|
if (sessions !== undefined)
|
|
120
126
|
line(sessions.text);
|
|
127
|
+
for (const row of coverageLines(daemonStatus))
|
|
128
|
+
line(row);
|
|
129
|
+
// Runs nothing will send, named by folder with the one command that sends them.
|
|
130
|
+
for (const entry of await machineUnsyncedRoots(createNodeFileSystem(), homedir(), process.env))
|
|
131
|
+
line(doctorRow(DoctorRow.UNSYNCED, `✗ ${describeUnsynced(entry, process.cwd())}`));
|
|
121
132
|
line(doctorRow(DoctorRow.BRIDGE_PORT, `${port} (your app must dial THIS port, not your dev-server port)`));
|
|
122
133
|
const projectPort = readProjectPort(process.cwd());
|
|
123
134
|
const mismatch = diagnosePortMismatch(port, projectPort);
|
|
@@ -234,4 +245,7 @@ export async function handleDoctor(port) {
|
|
|
234
245
|
// findings above exist to remove.
|
|
235
246
|
line(doctorRow(DoctorRow.DESKTOP, '✓ desktop wiring looks right'));
|
|
236
247
|
}
|
|
248
|
+
const keychain = keychainNoteFor({ read: readProjectFile });
|
|
249
|
+
if (keychain !== undefined)
|
|
250
|
+
line(doctorRow(DoctorRow.DESKTOP, `⚠ ${keychain}`));
|
|
237
251
|
}
|
|
@@ -26,17 +26,6 @@ export declare function resolveChangedFiles(files: string[], since: string | und
|
|
|
26
26
|
* confident negative about somebody else's project, which is worse than an error.
|
|
27
27
|
*/
|
|
28
28
|
export declare function loadNamedFlows(fs: FileSystemPort, reticleRoot: string, projectId: ProjectId | undefined): Promise<NamedFlow[]>;
|
|
29
|
-
/**
|
|
30
|
-
* `reticle watch [url]` — on every save, report which saved flows must re-verify (the affected set).
|
|
31
|
-
* Environment-side (costs the agent nothing per turn); the buddy loop. This v1 detects + reports on
|
|
32
|
-
* change; auto-replaying the affected flows against the app is the next increment. Long-running.
|
|
33
|
-
*/
|
|
34
|
-
export declare function handleWatch(): void;
|
|
35
|
-
/**
|
|
36
|
-
* `reticle capsules` — list saved fail-to-pass bug capsules (.reticle/capsules). Each is a minimal
|
|
37
|
-
* failing reproduction plus the consequence that should have held; replay one with reticle_flow_replay.
|
|
38
|
-
*/
|
|
39
|
-
export declare function handleCapsules(): Promise<void>;
|
|
40
29
|
export declare function handleGate(files: string[], since: string | undefined,
|
|
41
30
|
/** Hook mode: prose for a human, and silence when there was simply nothing to check. */
|
|
42
31
|
hook?: boolean,
|
|
@@ -5,7 +5,8 @@
|
|
|
5
5
|
* opens first. These five functions form one cohesive group: they all read the flow store and report on
|
|
6
6
|
* verification state, and none of them touch daemon lifecycle, which is what the rest of cli.ts does.
|
|
7
7
|
*/
|
|
8
|
-
import { GateExit } from './answers/gate-exit.js';
|
|
8
|
+
import { GateExit, MSG_GATE_NO_FLOWS, msgGateRegression, msgGateRefused, gateExitWith, } from './answers/gate-exit.js';
|
|
9
|
+
import { knownRegression } from './known-regression.js';
|
|
9
10
|
import { gateHookMessage, GATE_SKIP_ENV } from './answers/gate-hook-message.js';
|
|
10
11
|
import { readProjectId } from './ports/resolve/cli-port.js';
|
|
11
12
|
import { changedFilesSince } from '../../language/flows/change/git-changed.js';
|
|
@@ -19,13 +20,10 @@ import { isInteractiveSource, unflowedFiles } from '../../language/flows/change/
|
|
|
19
20
|
import { LedgerStore, regressions, staleChanged, unexecutedChanged, } from '../../features/exhaust/ledger.js';
|
|
20
21
|
import { gateDecision, passingFlowNames } from '../../language/flows/change/gate.js';
|
|
21
22
|
import { FlakeStore } from '../../language/flows/stores/flake-store.js';
|
|
22
|
-
import { formatBuddyStatus } from '../../language/flows/buddy-status.js';
|
|
23
|
-
import { CapsuleStore } from '../../judgement/capsule/capsule-store.js';
|
|
24
23
|
import { AssertionTiersStore } from '../../language/flows/stores/assertion-tiers-store.js';
|
|
25
24
|
import { detectDowngrades } from '../../judgement/outcome/assertion-integrity.js';
|
|
26
25
|
import { computeCoverage, flowCoverageReport } from '../../language/flows/suite/coverage.js';
|
|
27
|
-
import {
|
|
28
|
-
import { readFileSync, statSync, watch } from 'node:fs';
|
|
26
|
+
import { readFileSync, statSync } from 'node:fs';
|
|
29
27
|
import { log } from '../../log.js';
|
|
30
28
|
/** Load the {name, steps} of every saved flow for the active project. */
|
|
31
29
|
/** Explicit files plus, when --since is given, the git-changed files since that ref. */
|
|
@@ -63,101 +61,6 @@ export async function loadNamedFlows(fs, reticleRoot, projectId) {
|
|
|
63
61
|
}
|
|
64
62
|
return flows;
|
|
65
63
|
}
|
|
66
|
-
/** File-change extensions worth reacting to (skip node_modules churn, dotfiles, build output). */
|
|
67
|
-
/**
|
|
68
|
-
* The buddy channel: one ambient line a human can park in a statusline. Deliberately best-effort
|
|
69
|
-
* and silent on failure — a status line that throws is worse than no status line, and it must never
|
|
70
|
-
* interfere with the watch loop it rides on.
|
|
71
|
-
*/
|
|
72
|
-
async function emitBuddyStatus(fs, reticleRoot, flows, affected) {
|
|
73
|
-
try {
|
|
74
|
-
const latest = await new RunStore(fs, reticleRoot).latest();
|
|
75
|
-
const passingNames = new Set(passingFlowNames(latest?.flows ?? []));
|
|
76
|
-
const quarantined = await new FlakeStore(fs, reticleRoot).flakyFlows();
|
|
77
|
-
const flaky = new Set(quarantined);
|
|
78
|
-
// A deviation is an at-risk flow with no passing artifact — and a quarantined flake is not a deviation.
|
|
79
|
-
const deviations = affected.filter((n) => !passingNames.has(n) && !flaky.has(n));
|
|
80
|
-
log('reticle_buddy', {
|
|
81
|
-
status: formatBuddyStatus({
|
|
82
|
-
total: flows.length,
|
|
83
|
-
passing: passingNames.size,
|
|
84
|
-
deviations,
|
|
85
|
-
quarantined,
|
|
86
|
-
}),
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
catch {
|
|
90
|
-
// never let the ambient line break the watcher
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
const WATCHED_EXTENSIONS = /\.(ts|tsx|js|jsx|mjs|cjs|vue|svelte)$/;
|
|
94
|
-
const WATCH_DEBOUNCE_MS = 200;
|
|
95
|
-
/**
|
|
96
|
-
* `reticle watch [url]` — on every save, report which saved flows must re-verify (the affected set).
|
|
97
|
-
* Environment-side (costs the agent nothing per turn); the buddy loop. This v1 detects + reports on
|
|
98
|
-
* change; auto-replaying the affected flows against the app is the next increment. Long-running.
|
|
99
|
-
*/
|
|
100
|
-
export function handleWatch() {
|
|
101
|
-
const fs = createNodeFileSystem();
|
|
102
|
-
const reticleRoot = join(process.cwd(), ReticleDir.ROOT);
|
|
103
|
-
const batcher = createWatchBatcher({
|
|
104
|
-
debounceMs: WATCH_DEBOUNCE_MS,
|
|
105
|
-
schedule: (fn, ms) => {
|
|
106
|
-
setTimeout(fn, ms).unref();
|
|
107
|
-
},
|
|
108
|
-
onFlush: (files) => {
|
|
109
|
-
void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
|
|
110
|
-
.then(async (flows) => {
|
|
111
|
-
const result = affectedSavedFlows(flows, files);
|
|
112
|
-
if (result.affected.length > 0) {
|
|
113
|
-
log('reticle_watch_affected', { changed: files, affected: result.affected });
|
|
114
|
-
}
|
|
115
|
-
await emitBuddyStatus(fs, reticleRoot, flows, result.affected);
|
|
116
|
-
})
|
|
117
|
-
.catch((error) => {
|
|
118
|
-
log('reticle_watch_failed', {
|
|
119
|
-
error: error instanceof Error ? error.message : String(error),
|
|
120
|
-
});
|
|
121
|
-
});
|
|
122
|
-
},
|
|
123
|
-
});
|
|
124
|
-
log('reticle_watch_started', { cwd: process.cwd() });
|
|
125
|
-
// Print the ambient line once at startup so the human sees where they stand before touching anything.
|
|
126
|
-
void loadNamedFlows(fs, reticleRoot, readProjectId(process.cwd()))
|
|
127
|
-
.then((flows) => emitBuddyStatus(fs, reticleRoot, flows, []))
|
|
128
|
-
.catch(() => undefined);
|
|
129
|
-
watch(process.cwd(), { recursive: true }, (_event, filename) => {
|
|
130
|
-
if ('string' === typeof filename && WATCHED_EXTENSIONS.test(filename))
|
|
131
|
-
batcher.onChange(filename);
|
|
132
|
-
});
|
|
133
|
-
}
|
|
134
|
-
/**
|
|
135
|
-
* `reticle capsules` — list saved fail-to-pass bug capsules (.reticle/capsules). Each is a minimal
|
|
136
|
-
* failing reproduction plus the consequence that should have held; replay one with reticle_flow_replay.
|
|
137
|
-
*/
|
|
138
|
-
export async function handleCapsules() {
|
|
139
|
-
try {
|
|
140
|
-
const fs = createNodeFileSystem();
|
|
141
|
-
const capsules = await new CapsuleStore(fs, join(process.cwd(), ReticleDir.ROOT)).all();
|
|
142
|
-
log('reticle_capsules', {
|
|
143
|
-
count: capsules.length,
|
|
144
|
-
capsules: capsules.map((c) => ({
|
|
145
|
-
id: c.id,
|
|
146
|
-
...(c.flow === undefined ? {} : { flow: c.flow }),
|
|
147
|
-
origin: c.origin,
|
|
148
|
-
expected: c.expected,
|
|
149
|
-
observed: c.observed,
|
|
150
|
-
steps: c.steps.length,
|
|
151
|
-
})),
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
catch (error) {
|
|
155
|
-
log('reticle_capsules_failed', {
|
|
156
|
-
error: error instanceof Error ? error.message : String(error),
|
|
157
|
-
});
|
|
158
|
-
process.exitCode = 1;
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
64
|
/**
|
|
162
65
|
* `reticle gate <file...>` — exit non-zero unless passing artifacts cover the flows affected by the
|
|
163
66
|
* changed files. Flaky flows are quarantined (surfaced, not blocking). The environment-side enforcement
|
|
@@ -260,8 +163,19 @@ acceptCoverage = false) {
|
|
|
260
163
|
// verdict already applies to `reticle verify`; see flowCoverageReport.
|
|
261
164
|
const flowCoverage = flowCoverageReport(coverage.flows);
|
|
262
165
|
const pass = result.pass && flowCoverage.outcome === undefined;
|
|
166
|
+
// What the platform knows decides too (a regression, a refused key), so the line is written
|
|
167
|
+
// once the exit code is: it said "pass": true over an exit of 1 or 3.
|
|
168
|
+
const known = await knownRegression(reticleRoot);
|
|
169
|
+
const regressed = known.broken;
|
|
170
|
+
const local = pass
|
|
171
|
+
? GateExit.PASS
|
|
172
|
+
: result.pass && flowCoverage.outcome !== undefined
|
|
173
|
+
? GateExit.NOTHING_TO_CHECK
|
|
174
|
+
: GateExit.FAIL;
|
|
175
|
+
// Fails closed in CI, not in an agent's stop hook, where it would block over a key, not a change.
|
|
176
|
+
const code = gateExitWith(local, regressed?.length, !hook && known.refused !== undefined);
|
|
263
177
|
log('reticle_gate', {
|
|
264
|
-
pass,
|
|
178
|
+
pass: GateExit.PASS === code,
|
|
265
179
|
uncovered: result.uncovered,
|
|
266
180
|
quarantined: result.quarantined,
|
|
267
181
|
...(result.downgraded.length > 0 ? { downgraded: result.downgraded } : {}),
|
|
@@ -279,10 +193,18 @@ acceptCoverage = false) {
|
|
|
279
193
|
// problem to fail. A Stop hook wants to block a real regression and NOT block a project that
|
|
280
194
|
// has simply not recorded a flow yet — which is every project on its first day, and measured
|
|
281
195
|
// before this change as an exit 1 that would have blocked every stop. See GateExit.
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
196
|
+
// A regression the platform already knows fails the build here too, with `reticle runs
|
|
197
|
+
// regression`'s code, so the gate is the one command CI needs. Best-effort: unlinked or offline
|
|
198
|
+
// changes nothing.
|
|
199
|
+
if (regressed !== undefined && 0 < regressed.length)
|
|
200
|
+
log('reticle_gate_regression', { broken: regressed });
|
|
201
|
+
if (known.refused !== undefined)
|
|
202
|
+
process.stderr.write(`${msgGateRefused(known.refused)}\n`);
|
|
203
|
+
if (GateExit.NOTHING_TO_CHECK === code && !hook)
|
|
204
|
+
process.stderr.write(`${MSG_GATE_NO_FLOWS}\n`);
|
|
205
|
+
if (GateExit.REGRESSION === code && !hook && regressed !== undefined)
|
|
206
|
+
process.stderr.write(`${msgGateRegression(regressed)}\n`);
|
|
207
|
+
if (GateExit.PASS !== code) {
|
|
286
208
|
process.exitCode = code;
|
|
287
209
|
if (hook) {
|
|
288
210
|
// An honest escape hatch, because the alternative to one is not compliance — it is somebody
|
|
@@ -301,6 +223,7 @@ acceptCoverage = false) {
|
|
|
301
223
|
unflowed: result.unflowed,
|
|
302
224
|
coverageRegressed: result.coverageRegressed.map((r) => `${r.level} ${String(r.was)}% -> ${String(r.now)}%`),
|
|
303
225
|
unexecuted: result.unexecuted,
|
|
226
|
+
regressed: regressed?.length ?? 0,
|
|
304
227
|
});
|
|
305
228
|
if (message !== undefined)
|
|
306
229
|
process.stderr.write(`${message}\n`);
|
|
@@ -64,8 +64,9 @@ export function planKill(input) {
|
|
|
64
64
|
holder: listener,
|
|
65
65
|
reason: `pid ${String(listener.pid)} ("${listener.command}") is listening, and it is not a Reticle ` +
|
|
66
66
|
`daemon — it never answered /status and it is not the pid Reticle recorded. Killing it would ` +
|
|
67
|
-
`be killing someone else's process.
|
|
68
|
-
`
|
|
67
|
+
`be killing someone else's process. If that is what you meant, \`reticle restart ${FORCE_FLAG}\` ` +
|
|
68
|
+
`stops it and starts Reticle there (\`stop ${FORCE_FLAG}\` never does); or start Reticle on ` +
|
|
69
|
+
`another port.`,
|
|
69
70
|
};
|
|
70
71
|
}
|
|
71
72
|
/** How long the target gets to exit on SIGTERM before we stop asking politely. */
|
|
@@ -34,3 +34,27 @@ export declare const VERIFY_COMMAND = "verify";
|
|
|
34
34
|
* missed for a release.
|
|
35
35
|
*/
|
|
36
36
|
export declare const EXPECT_FLAG = "--expect";
|
|
37
|
+
/**
|
|
38
|
+
* The account and cloud commands. They are dispatched before the typed parser, and listed here so
|
|
39
|
+
* that the dispatcher and the telemetry vocabulary read one list instead of two.
|
|
40
|
+
*/
|
|
41
|
+
export declare const CLOUD_COMMANDS: readonly string[];
|
|
42
|
+
/**
|
|
43
|
+
* Old command names that still run, for one release, under the name that replaced them. Each one
|
|
44
|
+
* prints a single line saying so, then does what it always did.
|
|
45
|
+
*/
|
|
46
|
+
export declare const RENAMED_COMMANDS: ReadonlyMap<string, string>;
|
|
47
|
+
/**
|
|
48
|
+
* The command an old name now goes by, when the note saying so should print; otherwise undefined.
|
|
49
|
+
* Not for a request for help (that answer names the new command itself), and not for
|
|
50
|
+
* `login --email`, which `connect --help` documents as the sign-in for CI and agents.
|
|
51
|
+
*/
|
|
52
|
+
export declare function renamedCommandFor(argv: readonly string[]): string | undefined;
|
|
53
|
+
/**
|
|
54
|
+
* Commands that were removed, and what to use instead. They stay in the telemetry vocabulary, so
|
|
55
|
+
* the people still typing one show up as that name rather than as `unknown`.
|
|
56
|
+
*/
|
|
57
|
+
export declare const REMOVED_COMMANDS: ReadonlyMap<string, string>;
|
|
58
|
+
export declare const removedNote: (command: string, instead: string) => string;
|
|
59
|
+
/** One line on stderr when an old name ran: dim on a terminal, plain anywhere else. */
|
|
60
|
+
export declare const renamedNote: (command: string, now: string, colour: boolean) => string;
|
|
@@ -44,3 +44,78 @@ export const VERIFY_COMMAND = 'verify';
|
|
|
44
44
|
* missed for a release.
|
|
45
45
|
*/
|
|
46
46
|
export const EXPECT_FLAG = '--expect';
|
|
47
|
+
/**
|
|
48
|
+
* The account and cloud commands. They are dispatched before the typed parser, and listed here so
|
|
49
|
+
* that the dispatcher and the telemetry vocabulary read one list instead of two.
|
|
50
|
+
*/
|
|
51
|
+
export const CLOUD_COMMANDS = [
|
|
52
|
+
'login',
|
|
53
|
+
'connect',
|
|
54
|
+
'try',
|
|
55
|
+
'logout',
|
|
56
|
+
'whoami',
|
|
57
|
+
'link',
|
|
58
|
+
'project',
|
|
59
|
+
'config',
|
|
60
|
+
'issues',
|
|
61
|
+
'memory',
|
|
62
|
+
'push',
|
|
63
|
+
'sync',
|
|
64
|
+
'runs',
|
|
65
|
+
'regression',
|
|
66
|
+
'share',
|
|
67
|
+
];
|
|
68
|
+
/**
|
|
69
|
+
* Old command names that still run, for one release, under the name that replaced them. Each one
|
|
70
|
+
* prints a single line saying so, then does what it always did.
|
|
71
|
+
*/
|
|
72
|
+
export const RENAMED_COMMANDS = new Map([
|
|
73
|
+
['kill', 'stop --force'],
|
|
74
|
+
['login', 'connect'],
|
|
75
|
+
['link', 'connect'],
|
|
76
|
+
['project', 'connect --project <name|id>'],
|
|
77
|
+
['whoami', 'status'],
|
|
78
|
+
['push', 'sync'],
|
|
79
|
+
['regression', 'runs regression'],
|
|
80
|
+
['share', 'runs share <runId>'],
|
|
81
|
+
['issues', 'runs issues'],
|
|
82
|
+
['memory', 'runs memory'],
|
|
83
|
+
]);
|
|
84
|
+
const HELP_FLAGS = new Set(['--help', '-h']);
|
|
85
|
+
/** `login --email` is the documented sign-in without a browser, so it is not a renamed `connect`. */
|
|
86
|
+
const BROWSERLESS_LOGIN = { command: 'login', flag: '--email' };
|
|
87
|
+
/**
|
|
88
|
+
* The command an old name now goes by, when the note saying so should print; otherwise undefined.
|
|
89
|
+
* Not for a request for help (that answer names the new command itself), and not for
|
|
90
|
+
* `login --email`, which `connect --help` documents as the sign-in for CI and agents.
|
|
91
|
+
*/
|
|
92
|
+
export function renamedCommandFor(argv) {
|
|
93
|
+
const name = argv[0];
|
|
94
|
+
if (name === undefined || argv.some((arg) => HELP_FLAGS.has(arg)))
|
|
95
|
+
return undefined;
|
|
96
|
+
if (BROWSERLESS_LOGIN.command === name && argv.includes(BROWSERLESS_LOGIN.flag))
|
|
97
|
+
return undefined;
|
|
98
|
+
return RENAMED_COMMANDS.get(name);
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Commands that were removed, and what to use instead. They stay in the telemetry vocabulary, so
|
|
102
|
+
* the people still typing one show up as that name rather than as `unknown`.
|
|
103
|
+
*/
|
|
104
|
+
export const REMOVED_COMMANDS = new Map([
|
|
105
|
+
['hunt', 'it has no replacement'],
|
|
106
|
+
['watch', 'use `reticle affected` after you save, or `reticle gate` before you commit'],
|
|
107
|
+
['capsules', 'it has no replacement; saved capsules stay in .reticle/capsules'],
|
|
108
|
+
['tutorial', "use `reticle init` in your app's folder, or `reticle try <url>`"],
|
|
109
|
+
[
|
|
110
|
+
'identify',
|
|
111
|
+
'it has no replacement; delete ~/.reticle/identity.json to forget a saved identity, and use `reticle feedback` to reach us',
|
|
112
|
+
],
|
|
113
|
+
]);
|
|
114
|
+
export const removedNote = (command, instead) => `\`reticle ${command}\` was removed in this version; ${instead}`;
|
|
115
|
+
const DIM = '\u001b[2m';
|
|
116
|
+
const RESET = '\u001b[0m';
|
|
117
|
+
/** One line on stderr when an old name ran: dim on a terminal, plain anywhere else. */
|
|
118
|
+
export const renamedNote = (command, now, colour) => {
|
|
119
|
+
const line = `\`reticle ${command}\` is now \`reticle ${now}\``;
|
|
120
|
+
return colour ? `${DIM}${line}${RESET}` : line;
|
|
121
|
+
};
|