@reticlehq/server 3.5.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SKILL.md +123 -116
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-suite.d.ts +14 -0
- package/dist/command/cli/adhoc-suite.js +42 -7
- package/dist/command/cli/adhoc-verdict.d.ts +19 -2
- package/dist/command/cli/adhoc-verdict.js +76 -9
- package/dist/command/cli/answers/gate-exit.d.ts +23 -0
- package/dist/command/cli/answers/gate-exit.js +45 -0
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +3 -1
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/auth/device-flow.d.ts +13 -2
- package/dist/command/cli/auth/device-flow.js +17 -0
- package/dist/command/cli/cli-doctor.js +14 -0
- package/dist/command/cli/cli-flow-commands.d.ts +0 -11
- package/dist/command/cli/cli-flow-commands.js +31 -112
- package/dist/command/cli/cli-kill.js +3 -2
- package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
- package/dist/command/cli/cli-parse-grammar.js +75 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -0
- package/dist/command/cli/cli-parse-verify.js +18 -0
- package/dist/command/cli/cli-parse.d.ts +19 -28
- package/dist/command/cli/cli-parse.js +82 -182
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +61 -9
- package/dist/command/cli/cli-usage.d.ts +33 -0
- package/dist/command/cli/cli-usage.js +287 -0
- package/dist/command/cli/cli-verify.d.ts +35 -5
- package/dist/command/cli/cli-verify.js +114 -35
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +192 -341
- package/dist/command/cli/cloud-kit.d.ts +12 -0
- package/dist/command/cli/cloud-kit.js +41 -2
- package/dist/command/cli/cloud-link.d.ts +57 -0
- package/dist/command/cli/cloud-link.js +308 -0
- package/dist/command/cli/cloud-login.d.ts +22 -0
- package/dist/command/cli/cloud-login.js +96 -8
- package/dist/command/cli/context-command.d.ts +1 -0
- package/dist/command/cli/context-command.js +33 -0
- package/dist/command/cli/daemon-start-options.d.ts +3 -0
- package/dist/command/cli/daemon-start-options.js +24 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
- package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
- package/dist/command/cli/doctor/doctor-project-line.js +5 -4
- package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
- package/dist/command/cli/doctor/doctor-rows.js +6 -0
- package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
- package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/known-regression.d.ts +13 -0
- package/dist/command/cli/known-regression.js +34 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
- package/dist/command/cli/launch/sdk-version-match.js +25 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
- package/dist/command/cli/mcp-command.d.ts +6 -0
- package/dist/command/cli/mcp-command.js +13 -5
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +25 -1
- package/dist/command/cli/project-name.d.ts +29 -1
- package/dist/command/cli/project-name.js +107 -2
- package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
- package/dist/command/cli/setup-mcp-cli.js +35 -12
- package/dist/command/cli/status/status-lines.d.ts +1 -0
- package/dist/command/cli/status/status-lines.js +47 -2
- package/dist/command/cli/status/workspace-links.d.ts +10 -0
- package/dist/command/cli/status/workspace-links.js +29 -0
- package/dist/command/cli/try-command.d.ts +96 -0
- package/dist/command/cli/try-command.js +362 -0
- package/dist/command/cli/tutorial.d.ts +0 -100
- package/dist/command/cli/tutorial.js +0 -181
- package/dist/command/cli/verify-results.d.ts +19 -0
- package/dist/command/cli/verify-results.js +29 -0
- package/dist/command/cli-onboarding.d.ts +0 -11
- package/dist/command/cli-onboarding.js +0 -15
- package/dist/command/cli.d.ts +20 -0
- package/dist/command/cli.js +130 -104
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +23 -1
- package/dist/command/daemon/daemon-resolve.js +79 -9
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
- package/dist/command/setup/bringup/bridge-port.js +13 -3
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
- package/dist/command/setup/bringup/dev-server-wait.js +19 -0
- package/dist/command/setup/bringup/ensure-daemon.js +9 -2
- package/dist/command/setup/init/agent-restart.d.ts +23 -0
- package/dist/command/setup/init/agent-restart.js +28 -0
- package/dist/command/setup/init/init-port.d.ts +14 -1
- package/dist/command/setup/init/init-port.js +32 -2
- package/dist/command/setup/init/init-runtime.d.ts +22 -2
- package/dist/command/setup/init/init-runtime.js +114 -38
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +38 -9
- package/dist/command/setup/probe/existing-app.d.ts +12 -0
- package/dist/command/setup/probe/existing-app.js +14 -0
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +34 -9
- package/dist/command/setup/run-setup.js +65 -51
- package/dist/command/setup/setup-command.d.ts +25 -1
- package/dist/command/setup/setup-command.js +59 -4
- package/dist/command/setup/setup-mcp.js +25 -2
- package/dist/command/setup/tauri-signing.d.ts +19 -0
- package/dist/command/setup/tauri-signing.js +79 -0
- package/dist/command/setup/terminal/listeners.d.ts +10 -1
- package/dist/command/setup/terminal/listeners.js +37 -6
- package/dist/command/update/update-nudge.d.ts +9 -0
- package/dist/command/update/update-nudge.js +1 -1
- package/dist/command/update/updater.js +11 -15
- package/dist/command/version/version-nudge.js +3 -0
- package/dist/command/version/version-skew.d.ts +20 -1
- package/dist/command/version/version-skew.js +49 -4
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +23 -2
- package/dist/features/exhaust/ledger.d.ts +21 -14
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +61 -1
- package/dist/features/harness/drive-report.js +394 -26
- package/dist/features/harness/drive-runs.d.ts +120 -0
- package/dist/features/harness/drive-runs.js +289 -0
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/explore/console-pages.d.ts +15 -0
- package/dist/features/harness/explore/console-pages.js +146 -0
- package/dist/features/harness/explore/disparity.d.ts +19 -0
- package/dist/features/harness/explore/disparity.js +71 -0
- package/dist/features/harness/explore/fake-app.d.ts +16 -0
- package/dist/features/harness/explore/fake-app.js +49 -0
- package/dist/features/harness/explore/goal-search.d.ts +26 -0
- package/dist/features/harness/explore/goal-search.js +144 -0
- package/dist/features/harness/explore/page-tree.d.ts +49 -0
- package/dist/features/harness/explore/page-tree.js +148 -0
- package/dist/features/harness/explore/site-map.d.ts +34 -0
- package/dist/features/harness/explore/site-map.js +150 -0
- package/dist/features/harness/fill-values.d.ts +3 -73
- package/dist/features/harness/fill-values.js +3 -169
- package/dist/features/harness/goals.d.ts +82 -0
- package/dist/features/harness/goals.js +330 -0
- package/dist/features/harness/harness.d.ts +51 -1
- package/dist/features/harness/harness.js +207 -6
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +127 -0
- package/dist/features/harness/platform/local-apps.js +280 -0
- package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
- package/dist/features/harness/platform/persona-credentials.js +69 -0
- package/dist/features/harness/platform/platform-drives.d.ts +61 -0
- package/dist/features/harness/platform/platform-drives.js +114 -0
- package/dist/features/harness/platform/refusal.d.ts +52 -0
- package/dist/features/harness/platform/refusal.js +71 -0
- package/dist/features/harness/platform/remote-drive.d.ts +186 -0
- package/dist/features/harness/platform/remote-drive.js +378 -0
- package/dist/features/harness/platform/script.d.ts +94 -0
- package/dist/features/harness/platform/script.js +260 -0
- package/dist/features/harness/platform/server-driver.d.ts +54 -0
- package/dist/features/harness/platform/server-driver.js +182 -0
- package/dist/features/harness/platform-config.d.ts +41 -1
- package/dist/features/harness/platform-config.js +106 -9
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +70 -0
- package/dist/features/harness/script/script-run.js +606 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/step-shots.d.ts +31 -0
- package/dist/features/visual/step-shots.js +231 -0
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +62 -17
- package/dist/hooks/client-directory.d.ts +18 -0
- package/dist/hooks/client-directory.js +57 -0
- package/dist/hooks/coding-agents.d.ts +34 -0
- package/dist/hooks/coding-agents.js +117 -0
- package/dist/hooks/driven-by.d.ts +23 -0
- package/dist/hooks/driven-by.js +56 -0
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -243
- package/dist/judgement/capsule/capsule-store.d.ts +2 -2
- package/dist/judgement/capsule/causal-summary.d.ts +15 -1
- package/dist/judgement/capsule/causal-summary.js +33 -0
- package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
- package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
- package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
- package/dist/judgement/runs/artifact/gap-summary.js +12 -3
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
- package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
- package/dist/judgement/runs/artifact/run-store.js +195 -3
- package/dist/judgement/runs/context-tools.js +59 -1
- package/dist/judgement/runs/default-run-id.d.ts +3 -0
- package/dist/judgement/runs/default-run-id.js +16 -0
- package/dist/judgement/runs/drive-run.d.ts +71 -1
- package/dist/judgement/runs/drive-run.js +317 -5
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +13 -3
- package/dist/judgement/runs/runner-port.d.ts +5 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +5 -2
- package/dist/judgement/runs/verification-sync.js +40 -18
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +36 -1
- package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
- package/dist/language/flows/fields/flow-secret-field.js +25 -2
- package/dist/language/flows/flow-anchor.d.ts +61 -10
- package/dist/language/flows/flow-anchor.js +98 -6
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-intent.d.ts +1 -0
- package/dist/language/flows/flow-journey.d.ts +6 -0
- package/dist/language/flows/flow-journey.js +20 -0
- package/dist/language/flows/flow-learning.d.ts +4 -0
- package/dist/language/flows/flow-learning.js +45 -14
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +115 -110
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +40 -1
- package/dist/language/flows/flow-replay.js +110 -22
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +22 -2
- package/dist/language/flows/flow-step-runners.js +247 -47
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +7 -3
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +112 -89
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +74 -12
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
- package/dist/language/flows/recording/tape/recordings.js +95 -13
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +56 -15
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +202 -191
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +22 -1
- package/dist/memory/cloud/cloud-config.js +34 -5
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +15 -4
- package/dist/memory/cloud/harness-config.d.ts +75 -1
- package/dist/memory/cloud/harness-config.js +115 -24
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +161 -0
- package/dist/memory/cloud/memory-scope.js +227 -0
- package/dist/memory/cloud/sync-cycle.d.ts +44 -7
- package/dist/memory/cloud/sync-cycle.js +129 -15
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +121 -9
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +31 -10
- package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
- package/dist/memory/cloud/sync-screenshots.js +105 -0
- package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
- package/dist/memory/cloud/unsynced-roots.js +166 -0
- package/dist/memory/impact/account-watch.d.ts +34 -0
- package/dist/memory/impact/account-watch.js +59 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +17 -4
- package/dist/memory/impact/impact-store.js +169 -63
- package/dist/memory/intent/inline-intent.d.ts +1 -0
- package/dist/memory/intent/intent-shard-store.js +16 -4
- package/dist/memory/intent/intent-shard.d.ts +14 -2
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +122 -4
- package/dist/memory/intent/open-intents.d.ts +6 -0
- package/dist/memory/intent/open-intents.js +10 -1
- package/dist/memory/intent/settled-words.d.ts +24 -0
- package/dist/memory/intent/settled-words.js +130 -0
- package/dist/memory/journal/drive-flow.d.ts +16 -0
- package/dist/memory/journal/drive-flow.js +34 -2
- package/dist/memory/journal/drive-run-flush.d.ts +2 -0
- package/dist/memory/journal/drive-run-flush.js +20 -5
- package/dist/memory/journal/envelope.d.ts +8 -8
- package/dist/memory/journal/journal-recorder.js +52 -3
- package/dist/memory/journal/on-disk/retention.d.ts +8 -0
- package/dist/memory/journal/on-disk/retention.js +32 -2
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +42 -9
- package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
- package/dist/memory/project/artifact-root-resolver.js +125 -16
- package/dist/memory/project/artifact-root.d.ts +46 -8
- package/dist/memory/project/artifact-root.js +89 -10
- package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
- package/dist/memory/project/dir/reticle-dir.js +26 -3
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/root-claims.d.ts +6 -0
- package/dist/memory/project/root-claims.js +39 -0
- package/dist/memory/project/session-root.d.ts +26 -1
- package/dist/memory/project/session-root.js +49 -5
- package/dist/memory/project/sync-status.d.ts +85 -0
- package/dist/memory/project/sync-status.js +224 -0
- package/dist/memory/recall/memory-tools.js +47 -2
- package/dist/memory/recall/platform-memory.d.ts +34 -0
- package/dist/memory/recall/platform-memory.js +139 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +80 -13
- package/dist/portal/bridge/bridge.d.ts +9 -3
- package/dist/portal/bridge/bridge.js +82 -22
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -0
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/bridge/wrong-path.d.ts +17 -0
- package/dist/portal/bridge/wrong-path.js +35 -0
- package/dist/portal/input/network-mock-tools.js +11 -2
- package/dist/portal/input/real-input.d.ts +83 -10
- package/dist/portal/input/real-input.js +218 -30
- package/dist/portal/input/viewport-tools.js +3 -3
- package/dist/portal/pool/browser-pool.d.ts +70 -9
- package/dist/portal/pool/browser-pool.js +190 -37
- package/dist/portal/pool/context-permissions.d.ts +33 -0
- package/dist/portal/pool/context-permissions.js +33 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
- package/dist/portal/pool/lease-marker-stamp.js +49 -0
- package/dist/portal/pool/playwright-launcher.d.ts +35 -0
- package/dist/portal/pool/playwright-launcher.js +64 -3
- package/dist/portal/pool/pool-contract.d.ts +28 -5
- package/dist/portal/session/agent-link.d.ts +8 -0
- package/dist/portal/session/agent-link.js +17 -0
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +24 -0
- package/dist/portal/session/daemon-answers.d.ts +3 -3
- package/dist/portal/session/daemon-answers.js +4 -2
- package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
- package/dist/portal/session/dev-server/dev-command.js +87 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/observed-state.d.ts +16 -18
- package/dist/portal/session/facts/observed-state.js +46 -3
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +107 -13
- package/dist/portal/session/narration-args.d.ts +5 -0
- package/dist/portal/session/narration-args.js +17 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
- package/dist/portal/session/no-session-diagnosis.js +46 -9
- package/dist/portal/session/no-session-next-action.d.ts +31 -0
- package/dist/portal/session/no-session-next-action.js +159 -60
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +227 -17
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +18 -0
- package/dist/portal/session/session-health.js +9 -1
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +8 -1
- package/dist/portal/session/session-manager.d.ts +39 -0
- package/dist/portal/session/session-manager.js +98 -11
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +13 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +22 -30
- package/dist/portal/session/session.js +81 -79
- package/dist/portal/session/timing/command-timeout.js +25 -1
- package/dist/portal/session/timing/wall-clock.d.ts +1 -1
- package/dist/portal/session/timing/wall-clock.js +1 -1
- package/dist/portal/session/zero-install-first-call.d.ts +31 -0
- package/dist/portal/session/zero-install-first-call.js +88 -0
- package/dist/start-options.d.ts +12 -0
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +23 -1
- package/dist/status-payload.js +36 -1
- package/dist/surface/http-server.js +18 -2
- package/dist/surface/mcp/attach-memory.d.ts +1 -0
- package/dist/surface/mcp/attach-memory.js +12 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
- package/dist/surface/mcp/mcp-proxy.js +65 -13
- package/dist/surface/mcp/mcp.d.ts +34 -6
- package/dist/surface/mcp/mcp.js +61 -17
- package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
- package/dist/surface/mcp/proxy/drive-calls.js +27 -0
- package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +32 -14
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +1 -0
- package/dist/surface/tools/account-tool.d.ts +22 -0
- package/dist/surface/tools/account-tool.js +157 -0
- package/dist/surface/tools/act/act-danger.d.ts +11 -0
- package/dist/surface/tools/act/act-danger.js +38 -1
- package/dist/surface/tools/act/act-observation.d.ts +33 -0
- package/dist/surface/tools/act/act-observation.js +57 -0
- package/dist/surface/tools/act/act-preflight.js +25 -2
- package/dist/surface/tools/act/act-target.js +8 -3
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/resolve-target.d.ts +1 -1
- package/dist/surface/tools/act/resolve-target.js +18 -3
- package/dist/surface/tools/act/screen-request.d.ts +34 -0
- package/dist/surface/tools/act/screen-request.js +113 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +138 -29
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +71 -41
- package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
- package/dist/surface/tools/agent/app-notes-learning.js +80 -0
- package/dist/surface/tools/agent/app-notes.d.ts +4 -0
- package/dist/surface/tools/agent/app-notes.js +48 -0
- package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
- package/dist/surface/tools/agent/build-staleness.js +62 -0
- package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
- package/dist/surface/tools/agent/compact-envelope.js +374 -0
- package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
- package/dist/surface/tools/agent/for-the-agent.js +44 -0
- package/dist/surface/tools/agent/notices.d.ts +50 -0
- package/dist/surface/tools/agent/notices.js +152 -0
- package/dist/surface/tools/agent/reteach.d.ts +11 -0
- package/dist/surface/tools/agent/reteach.js +50 -0
- package/dist/surface/tools/args/alias-args.d.ts +5 -0
- package/dist/surface/tools/args/alias-args.js +10 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
- package/dist/surface/tools/assert/assert-source.d.ts +15 -0
- package/dist/surface/tools/assert/assert-source.js +40 -0
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +42 -17
- package/dist/surface/tools/browser-tools.js +51 -2
- package/dist/surface/tools/chat-drives.d.ts +101 -0
- package/dist/surface/tools/chat-drives.js +409 -0
- package/dist/surface/tools/coverage-tools.d.ts +2 -10
- package/dist/surface/tools/coverage-tools.js +2 -53
- package/dist/surface/tools/dynamic-tools.js +29 -1
- package/dist/surface/tools/empty-session-list.d.ts +51 -0
- package/dist/surface/tools/empty-session-list.js +120 -0
- package/dist/surface/tools/error-recovery.d.ts +14 -0
- package/dist/surface/tools/error-recovery.js +105 -8
- package/dist/surface/tools/explore-tools.d.ts +31 -1
- package/dist/surface/tools/explore-tools.js +438 -66
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +18 -3
- package/dist/surface/tools/gap-novelty.d.ts +3 -1
- package/dist/surface/tools/gap-novelty.js +8 -1
- package/dist/surface/tools/harness-explore.d.ts +118 -57
- package/dist/surface/tools/harness-explore.js +344 -292
- package/dist/surface/tools/harness-gate.d.ts +88 -0
- package/dist/surface/tools/harness-gate.js +235 -0
- package/dist/surface/tools/harness-hunt.d.ts +43 -0
- package/dist/surface/tools/harness-hunt.js +215 -0
- package/dist/surface/tools/harness-plan.d.ts +17 -0
- package/dist/surface/tools/harness-plan.js +38 -0
- package/dist/surface/tools/harness-script.d.ts +30 -0
- package/dist/surface/tools/harness-script.js +560 -0
- package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
- package/dist/surface/tools/harness-tab-guard.js +27 -0
- package/dist/surface/tools/harness-toolset.d.ts +22 -1
- package/dist/surface/tools/harness-toolset.js +101 -7
- package/dist/surface/tools/human-notes.d.ts +16 -0
- package/dist/surface/tools/human-notes.js +27 -0
- package/dist/surface/tools/invoke-tool.d.ts +5 -2
- package/dist/surface/tools/invoke-tool.js +263 -85
- package/dist/surface/tools/lease-hint.js +26 -5
- package/dist/surface/tools/lease-permissions.d.ts +33 -0
- package/dist/surface/tools/lease-permissions.js +73 -0
- package/dist/surface/tools/lease-readiness.d.ts +38 -0
- package/dist/surface/tools/lease-readiness.js +57 -0
- package/dist/surface/tools/lease-seed.d.ts +49 -0
- package/dist/surface/tools/lease-seed.js +167 -0
- package/dist/surface/tools/lease-tools.d.ts +13 -24
- package/dist/surface/tools/lease-tools.js +146 -197
- package/dist/surface/tools/live-call-text.js +4 -4
- package/dist/surface/tools/merge-tools.js +42 -2
- package/dist/surface/tools/merged-name-redirect.js +4 -0
- package/dist/surface/tools/next-step.d.ts +29 -0
- package/dist/surface/tools/next-step.js +214 -0
- package/dist/surface/tools/observe-tools.js +45 -9
- package/dist/surface/tools/platform-moment.d.ts +72 -0
- package/dist/surface/tools/platform-moment.js +296 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +71 -14
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/reticle-result.d.ts +120 -0
- package/dist/surface/tools/reticle-result.js +364 -0
- package/dist/surface/tools/tool-kit.d.ts +83 -3
- package/dist/surface/tools/tool-kit.js +77 -7
- package/dist/surface/tools/tools.js +43 -59
- package/dist/telemetry/account-envelope.d.ts +7 -0
- package/dist/telemetry/account-envelope.js +61 -0
- package/dist/telemetry/agent-client.d.ts +15 -0
- package/dist/telemetry/agent-client.js +57 -0
- package/dist/telemetry/app-instrumented.js +9 -2
- package/dist/telemetry/argument-shape.d.ts +7 -0
- package/dist/telemetry/argument-shape.js +86 -1
- package/dist/telemetry/automation-hint.d.ts +2 -3
- package/dist/telemetry/automation-hint.js +33 -8
- package/dist/telemetry/cli-telemetry.js +7 -2
- package/dist/telemetry/daemon-telemetry.js +3 -0
- package/dist/telemetry/error-fingerprint.d.ts +10 -1
- package/dist/telemetry/error-fingerprint.js +61 -5
- package/dist/telemetry/feedback-cli.d.ts +0 -13
- package/dist/telemetry/feedback-cli.js +0 -77
- package/dist/telemetry/feedback.d.ts +13 -0
- package/dist/telemetry/feedback.js +183 -17
- package/dist/telemetry/harness-run.d.ts +18 -0
- package/dist/telemetry/harness-run.js +80 -0
- package/dist/telemetry/hud-events.d.ts +16 -0
- package/dist/telemetry/hud-events.js +27 -0
- package/dist/telemetry/hud-metrics.d.ts +29 -6
- package/dist/telemetry/hud-metrics.js +116 -25
- package/dist/telemetry/init-telemetry.js +2 -2
- package/dist/telemetry/install-source.d.ts +13 -25
- package/dist/telemetry/install-source.js +44 -3
- package/dist/telemetry/mcp-connection.d.ts +0 -14
- package/dist/telemetry/mcp-connection.js +5 -1
- package/dist/telemetry/onboarding-firsts.d.ts +32 -0
- package/dist/telemetry/onboarding-firsts.js +81 -6
- package/dist/telemetry/platform-linked.d.ts +5 -0
- package/dist/telemetry/platform-linked.js +32 -0
- package/dist/telemetry/project-profile.js +5 -3
- package/dist/telemetry/proxy-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +15 -4
- package/dist/telemetry/session-metrics.js +88 -52
- package/dist/telemetry/telemetry.d.ts +38 -2
- package/dist/telemetry/telemetry.js +144 -34
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +13 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +20 -6
- package/docs/README.md +3 -3
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +25 -28
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +33 -28
- package/docs/benchmarks.md +5 -5
- package/docs/best-practices.mdx +27 -9
- package/docs/capabilities.mdx +14 -16
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +54 -75
- package/docs/cli/doctor.mdx +14 -3
- package/docs/cli/drive.mdx +20 -14
- package/docs/cli/feedback.mdx +3 -3
- package/docs/cli/gate.mdx +7 -2
- package/docs/cli/help.mdx +50 -55
- package/docs/cli/init.mdx +43 -28
- package/docs/cli/license.mdx +12 -8
- package/docs/cli/mcp.mdx +4 -4
- package/docs/cli/open.mdx +3 -3
- package/docs/cli/report.mdx +4 -2
- package/docs/cli/restart.mdx +2 -2
- package/docs/cli/rollback.mdx +14 -8
- package/docs/cli/serve.mdx +4 -4
- package/docs/cli/setup.mdx +23 -0
- package/docs/cli/status.mdx +18 -5
- package/docs/cli/stop.mdx +67 -8
- package/docs/cli/try.mdx +62 -0
- package/docs/cli/update.mdx +4 -3
- package/docs/cli/verify.mdx +17 -6
- package/docs/cli/version.mdx +5 -4
- package/docs/cli.mdx +111 -42
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +9 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +7 -8
- package/docs/faq.mdx +3 -3
- package/docs/first-drive.md +5 -4
- package/docs/flows.md +35 -27
- package/docs/for-agents.md +4 -5
- package/docs/frameworks.mdx +32 -21
- package/docs/getting-started.md +65 -61
- package/docs/human-control.md +16 -16
- package/docs/index.mdx +15 -42
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +23 -13
- package/docs/instrumentation.mdx +5 -3
- package/docs/integration-patterns.md +7 -7
- package/docs/license-activation.mdx +1 -1
- package/docs/multi-agent-testing.md +24 -6
- package/docs/packages/babel-plugin.mdx +4 -2
- package/docs/packages/browser.mdx +16 -10
- package/docs/packages/core.mdx +12 -5
- package/docs/packages/electron.mdx +3 -2
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/eslint-plugin.mdx +18 -12
- package/docs/packages/next.mdx +8 -7
- package/docs/packages/open-verification.mdx +1 -1
- package/docs/packages/server.mdx +5 -5
- package/docs/packages/tauri.mdx +9 -9
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +32 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +69 -30
- package/docs/required-checks.md +8 -7
- package/docs/reticle-manual.md +15 -5
- package/docs/skill-file.mdx +17 -79
- package/docs/skill-setup.md +9 -9
- package/docs/skill.md +200 -0
- package/docs/system-map.md +7 -7
- package/docs/telemetry.md +23 -25
- package/docs/testing.md +4 -4
- package/docs/token-efficiency.md +12 -12
- package/docs/tools/act-and-wait.mdx +9 -2
- package/docs/tools/act-sequence.mdx +6 -7
- package/docs/tools/act.mdx +2 -2
- package/docs/tools/assert.mdx +18 -17
- package/docs/tools/console.mdx +9 -9
- package/docs/tools/inspect.mdx +16 -7
- package/docs/tools/look.mdx +24 -0
- package/docs/tools/navigate.mdx +5 -3
- package/docs/tools/network.mdx +2 -2
- package/docs/tools/observe.mdx +6 -6
- package/docs/tools/overview.mdx +34 -33
- package/docs/tools/query.mdx +5 -5
- package/docs/tools/session-and-feedback.mdx +22 -13
- package/docs/tools/sessions.mdx +8 -8
- package/docs/tools/snapshot.mdx +6 -5
- package/docs/tools/state.mdx +9 -9
- package/docs/tools/tools-and-run.mdx +26 -24
- package/docs/tools/verify.mdx +28 -0
- package/docs/tools/wait-for.mdx +8 -4
- package/docs/troubleshooting.mdx +21 -6
- package/docs/usage.md +55 -46
- package/docs/use-cases.mdx +3 -3
- package/docs/vs-chrome-devtools-mcp.mdx +9 -6
- package/docs/vs-playwright-mcp.mdx +3 -1
- package/docs/what-is-recorded.md +17 -5
- package/docs/what-is-reticle.mdx +5 -3
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -241
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -58
- package/dist/features/harness/openai-driver.js +0 -206
- package/dist/judgement/hunt/hunt-report.d.ts +0 -49
- package/dist/judgement/hunt/hunt-report.js +0 -84
- package/dist/language/flows/buddy-status.d.ts +0 -25
- package/dist/language/flows/buddy-status.js +0 -32
- package/dist/language/flows/change/watch-batcher.d.ts +0 -18
- package/dist/language/flows/change/watch-batcher.js +0 -19
- package/dist/memory/cloud/harness-offer.d.ts +0 -44
- package/dist/memory/cloud/harness-offer.js +0 -145
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/dist/surface/tools/feature-capture.d.ts +0 -151
- package/dist/surface/tools/feature-capture.js +0 -235
- package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
- package/dist/surface/tools/tool-hit-rate.js +0 -90
- package/dist/telemetry/harness-drive.d.ts +0 -4
- package/dist/telemetry/harness-drive.js +0 -35
- package/dist/telemetry/identify.d.ts +0 -22
- package/dist/telemetry/identify.js +0 -73
- package/docs/cli/capsules.mdx +0 -70
- package/docs/cli/hunt.mdx +0 -73
- package/docs/cli/identify.mdx +0 -76
- package/docs/cli/kill.mdx +0 -91
- package/docs/cli/watch.mdx +0 -62
- package/docs/local-registry.md +0 -143
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Sign the Tauri dev build Reticle starts with the project's own signing identity, so macOS stops
|
|
3
|
+
* asking for the keychain password.
|
|
4
|
+
*
|
|
5
|
+
* macOS ties a keychain item to the designated requirement of the app that saved it: its code
|
|
6
|
+
* identifier and its signing team. `tauri dev` produces an ad-hoc signed binary named after the
|
|
7
|
+
* crate, so every keychain read from it is a different app asking, and macOS prompts each time.
|
|
8
|
+
* `reticle doctor` explained that; this removes it when the project has said who signs it.
|
|
9
|
+
*
|
|
10
|
+
* `APPLE_SIGNING_IDENTITY` cannot simply be passed through: Tauri reads it only when it bundles
|
|
11
|
+
* (`tauri build`), never in `tauri dev`. What `tauri dev` does run is `cargo run`, and Cargo hands
|
|
12
|
+
* the freshly built binary to a per-target RUNNER before executing it. The runner written here signs
|
|
13
|
+
* that binary — with the identity, and with the app's bundle identifier so the requirement matches
|
|
14
|
+
* the release app's — and then executes it unchanged. A signing failure is said on stderr and never
|
|
15
|
+
* stops the app.
|
|
16
|
+
*
|
|
17
|
+
* Nothing happens off macOS, outside a Tauri project, with no identity, with the ad-hoc identity
|
|
18
|
+
* `-` (which matches nothing), or when the project already sets a Cargo runner of its own.
|
|
19
|
+
*/
|
|
20
|
+
import { join } from 'node:path';
|
|
21
|
+
/** The env the runner reads its arguments from: the script stays a fixed file. */
|
|
22
|
+
export const SigningEnv = {
|
|
23
|
+
IDENTITY: 'RETICLE_SIGNING_IDENTITY',
|
|
24
|
+
IDENTIFIER: 'RETICLE_SIGNING_IDENTIFIER',
|
|
25
|
+
APPLE: 'APPLE_SIGNING_IDENTITY',
|
|
26
|
+
};
|
|
27
|
+
/** Cargo's runner variable for each Mac target `tauri dev` builds. */
|
|
28
|
+
const RUNNER_VARS = [
|
|
29
|
+
'CARGO_TARGET_AARCH64_APPLE_DARWIN_RUNNER',
|
|
30
|
+
'CARGO_TARGET_X86_64_APPLE_DARWIN_RUNNER',
|
|
31
|
+
];
|
|
32
|
+
const DARWIN = 'darwin';
|
|
33
|
+
const AD_HOC = '-';
|
|
34
|
+
const TAURI_CONF = join('src-tauri', 'tauri.conf.json');
|
|
35
|
+
export const RUNNER_FILE = 'tauri-sign-runner.sh';
|
|
36
|
+
/** The runner: sign the binary Cargo built, then run it exactly as Cargo would have. */
|
|
37
|
+
export const RUNNER_SCRIPT = `#!/bin/sh
|
|
38
|
+
# Written by Reticle. Signs the Tauri dev build with this project's signing identity before it
|
|
39
|
+
# starts, so macOS treats it as the app that owns your keychain items and stops asking for the
|
|
40
|
+
# password. Remove RETICLE_SIGNING_IDENTITY from the environment to turn it off.
|
|
41
|
+
codesign --force --sign "$${SigningEnv.IDENTITY}" --identifier "$${SigningEnv.IDENTIFIER}" "$1" >/dev/null 2>&1 ||
|
|
42
|
+
echo "reticle: could not sign $1 with $${SigningEnv.IDENTITY}; macOS may ask for the keychain password" >&2
|
|
43
|
+
exec "$@"
|
|
44
|
+
`;
|
|
45
|
+
const asRecord = (value) => 'object' === typeof value && null !== value ? value : {};
|
|
46
|
+
const asText = (value) => 'string' === typeof value && 0 < value.trim().length ? value.trim() : undefined;
|
|
47
|
+
/** The extra env for starting a Tauri dev build signed, or `{}` when there is nothing to sign with. */
|
|
48
|
+
export function tauriSigningEnv(deps) {
|
|
49
|
+
if (DARWIN !== deps.platform)
|
|
50
|
+
return {};
|
|
51
|
+
const raw = deps.read(TAURI_CONF);
|
|
52
|
+
if (raw === undefined)
|
|
53
|
+
return {};
|
|
54
|
+
let conf;
|
|
55
|
+
try {
|
|
56
|
+
conf = asRecord(JSON.parse(raw));
|
|
57
|
+
}
|
|
58
|
+
catch {
|
|
59
|
+
return {};
|
|
60
|
+
}
|
|
61
|
+
const macOS = asRecord(asRecord(conf['bundle'])['macOS']);
|
|
62
|
+
const identity = asText(deps.env[SigningEnv.APPLE]) ?? asText(macOS['signingIdentity']);
|
|
63
|
+
const identifier = asText(conf['identifier']);
|
|
64
|
+
if (identity === undefined || AD_HOC === identity || identifier === undefined)
|
|
65
|
+
return {};
|
|
66
|
+
// A project that runs its builds through a runner of its own keeps it.
|
|
67
|
+
if (RUNNER_VARS.some((name) => deps.env[name] !== undefined))
|
|
68
|
+
return {};
|
|
69
|
+
const runner = deps.writeRunner(RUNNER_FILE, RUNNER_SCRIPT);
|
|
70
|
+
// Cargo splits a runner given in the environment on whitespace, so a path with a space in it
|
|
71
|
+
// would run the wrong program. ponytail: skip it; doctor still explains the prompt.
|
|
72
|
+
if (/\s/.test(runner))
|
|
73
|
+
return {};
|
|
74
|
+
return {
|
|
75
|
+
[SigningEnv.IDENTITY]: identity,
|
|
76
|
+
[SigningEnv.IDENTIFIER]: identifier,
|
|
77
|
+
...Object.fromEntries(RUNNER_VARS.map((name) => [name, runner])),
|
|
78
|
+
};
|
|
79
|
+
}
|
|
@@ -21,11 +21,20 @@ export declare function parseLsofPorts(out: string): number[];
|
|
|
21
21
|
* and taking index 1 reads every IPv6 row as port 0 and silently drops half the table.
|
|
22
22
|
*/
|
|
23
23
|
export declare function parseNetstatListeners(out: string): Listener[];
|
|
24
|
-
/**
|
|
24
|
+
/**
|
|
25
|
+
* One (pid, parent) pair, as `wmic process get CreationDate,ParentProcessId,ProcessId` prints them.
|
|
26
|
+
*
|
|
27
|
+
* `startedAtMs` is the process's own creation time, when the source gave one. It is what tells a
|
|
28
|
+
* real child from a stale link: Windows never clears ParentProcessId when a parent exits, and it
|
|
29
|
+
* reuses pids, so "ppid matches" alone can adopt an unrelated, older process. See `descendants`.
|
|
30
|
+
*/
|
|
25
31
|
export interface ProcessPair {
|
|
26
32
|
readonly pid: number;
|
|
27
33
|
readonly ppid: number;
|
|
34
|
+
readonly startedAtMs?: number;
|
|
28
35
|
}
|
|
36
|
+
/** Epoch milliseconds of a WMI datetime, or undefined when it is not one. */
|
|
37
|
+
export declare function parseWmiDatetime(text: string): number | undefined;
|
|
29
38
|
export declare function parseWmicProcesses(out: string): ProcessPair[];
|
|
30
39
|
/**
|
|
31
40
|
* `root` and everything descended from it.
|
|
@@ -39,16 +39,37 @@ export function parseNetstatListeners(out) {
|
|
|
39
39
|
}
|
|
40
40
|
return rows;
|
|
41
41
|
}
|
|
42
|
+
/** A WMI datetime: `yyyymmddHHMMSS.ffffff` then the offset from UTC in minutes, `+000` / `-300`. */
|
|
43
|
+
const WMI_DATETIME = /^(\d{4})(\d{2})(\d{2})(\d{2})(\d{2})(\d{2})\.(\d{6})([+-])(\d{3})$/;
|
|
44
|
+
const MICROS_PER_MS = 1000;
|
|
45
|
+
const MS_PER_MINUTE = 60_000;
|
|
46
|
+
/** Epoch milliseconds of a WMI datetime, or undefined when it is not one. */
|
|
47
|
+
export function parseWmiDatetime(text) {
|
|
48
|
+
const m = WMI_DATETIME.exec(text);
|
|
49
|
+
if (null === m)
|
|
50
|
+
return undefined;
|
|
51
|
+
const n = (index) => Number(m[index]);
|
|
52
|
+
const local = Date.UTC(n(1), n(2) - 1, n(3), n(4), n(5), n(6), Math.floor(n(7) / MICROS_PER_MS));
|
|
53
|
+
const minutesEast = '-' === m[8] ? -n(9) : n(9);
|
|
54
|
+
return local - minutesEast * MS_PER_MINUTE;
|
|
55
|
+
}
|
|
42
56
|
export function parseWmicProcesses(out) {
|
|
43
57
|
const pairs = [];
|
|
44
58
|
for (const line of String(out).split(/\r?\n/)) {
|
|
45
59
|
const f = line.trim().split(/\s+/);
|
|
46
|
-
|
|
60
|
+
// Two columns (ppid pid), or three with the creation time first: wmic prints its columns in
|
|
61
|
+
// alphabetical order, and the PowerShell fallback prints the same shape on purpose.
|
|
62
|
+
const timed = 3 === f.length;
|
|
63
|
+
if (!timed && 2 !== f.length)
|
|
64
|
+
continue;
|
|
65
|
+
const startedAtMs = timed ? parseWmiDatetime(f[0] ?? '') : undefined;
|
|
66
|
+
if (timed && undefined === startedAtMs)
|
|
67
|
+
continue;
|
|
68
|
+
const ppid = Number(f[timed ? 1 : 0]);
|
|
69
|
+
const pid = Number(f[timed ? 2 : 1]);
|
|
70
|
+
if (!Number.isInteger(pid) || !Number.isInteger(ppid))
|
|
47
71
|
continue;
|
|
48
|
-
|
|
49
|
-
const pid = Number(f[1]);
|
|
50
|
-
if (Number.isInteger(pid) && Number.isInteger(ppid))
|
|
51
|
-
pairs.push({ pid, ppid });
|
|
72
|
+
pairs.push(undefined === startedAtMs ? { pid, ppid } : { pid, ppid, startedAtMs });
|
|
52
73
|
}
|
|
53
74
|
return pairs;
|
|
54
75
|
}
|
|
@@ -60,8 +81,18 @@ export function parseWmicProcesses(out) {
|
|
|
60
81
|
* indistinguishable from "no server".
|
|
61
82
|
*/
|
|
62
83
|
export function descendants(pairs, root) {
|
|
84
|
+
const startedAt = new Map();
|
|
85
|
+
for (const { pid, startedAtMs } of pairs) {
|
|
86
|
+
if (undefined !== startedAtMs)
|
|
87
|
+
startedAt.set(pid, startedAtMs);
|
|
88
|
+
}
|
|
63
89
|
const byParent = new Map();
|
|
64
|
-
for (const { pid, ppid } of pairs) {
|
|
90
|
+
for (const { pid, ppid, startedAtMs } of pairs) {
|
|
91
|
+
// A child created before the parent it names is a stale link left by pid reuse, not a child.
|
|
92
|
+
const parentStarted = startedAt.get(ppid);
|
|
93
|
+
if (undefined !== startedAtMs && undefined !== parentStarted && startedAtMs < parentStarted) {
|
|
94
|
+
continue;
|
|
95
|
+
}
|
|
65
96
|
const kids = byParent.get(ppid);
|
|
66
97
|
if (kids === undefined)
|
|
67
98
|
byParent.set(ppid, [pid]);
|
|
@@ -1,3 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Is `candidate` a strictly NEWER release than `current`?
|
|
3
|
+
*
|
|
4
|
+
* Replaces a plain `!==`, which told anyone on a version newer than the published one — a
|
|
5
|
+
* prerelease, a local build, a rollback in progress — to "update" to something older. A nudge that
|
|
6
|
+
* prompts a downgrade is one people learn to ignore. Numeric per segment, so a 10 patch correctly
|
|
7
|
+
* beats a 9 (string order does not), and a bare release beats its own prerelease.
|
|
8
|
+
*/
|
|
9
|
+
export declare function isNewerVersion(candidate: string, current: string): boolean;
|
|
1
10
|
interface UpdateNudge {
|
|
2
11
|
/** The version available, so the agent can tell the human what they would be moving to. */
|
|
3
12
|
latestVersion: string;
|
|
@@ -28,7 +28,7 @@ import { creditNudge } from './nudge-credit.js';
|
|
|
28
28
|
* prompts a downgrade is one people learn to ignore. Numeric per segment, so a 10 patch correctly
|
|
29
29
|
* beats a 9 (string order does not), and a bare release beats its own prerelease.
|
|
30
30
|
*/
|
|
31
|
-
function isNewerVersion(candidate, current) {
|
|
31
|
+
export function isNewerVersion(candidate, current) {
|
|
32
32
|
const parse = (v) => {
|
|
33
33
|
const [core = '', ...rest] = v.split(/[-+]/);
|
|
34
34
|
return { parts: core.split('.').map((n) => Number.parseInt(n, 10) || 0), pre: rest.length > 0 };
|
|
@@ -168,15 +168,6 @@ async function installVersion(version, kind) {
|
|
|
168
168
|
}
|
|
169
169
|
await runNpm(plan.args, plan.cwd !== undefined ? { cwd: plan.cwd } : {});
|
|
170
170
|
}
|
|
171
|
-
async function installVersionRollback(version, kind) {
|
|
172
|
-
if (kind === ExecutionKind.NPX) {
|
|
173
|
-
log('reticle_rollback_npx_strategy', {
|
|
174
|
-
note: 'Running via npx — update your .mcp.json args to pin the version you want to restore',
|
|
175
|
-
});
|
|
176
|
-
return;
|
|
177
|
-
}
|
|
178
|
-
await installVersion(version, kind);
|
|
179
|
-
}
|
|
180
171
|
/**
|
|
181
172
|
* Install targetVersion using the appropriate strategy for the detected execution kind,
|
|
182
173
|
* then exit so Claude Code restarts with the new binary. Saves the current version
|
|
@@ -209,15 +200,20 @@ export async function rollback() {
|
|
|
209
200
|
}
|
|
210
201
|
const prev = manifest.previousVersion;
|
|
211
202
|
const kind = detectExecutionKind();
|
|
203
|
+
// Under npx there is nothing to reinstall: the next start re-resolves the package. Say how to pin
|
|
204
|
+
// the old version and stop, rather than logging and reporting a rollback that never landed.
|
|
205
|
+
if (kind === ExecutionKind.NPX) {
|
|
206
|
+
log('reticle_rollback_npx_strategy', {
|
|
207
|
+
version: prev,
|
|
208
|
+
note: 'Running via npx — update your .mcp.json args to pin the version you want to restore',
|
|
209
|
+
});
|
|
210
|
+
return;
|
|
211
|
+
}
|
|
212
212
|
log('reticle_rollback_applying', { version: prev, executionKind: kind });
|
|
213
|
-
await
|
|
213
|
+
await installVersion(prev, kind);
|
|
214
214
|
log('reticle_rollback_applied', { version: prev, executionKind: kind });
|
|
215
215
|
// A rollback is a release-quality alarm — someone shipped something that broke a real user badly
|
|
216
216
|
// enough for them to go backwards. Worth knowing about within the hour, not at the next retro.
|
|
217
217
|
await reportVersionChange(SERVER_VERSION, prev, VersionChangeDirection.ROLLBACK);
|
|
218
|
-
|
|
219
|
-
// of rollback. installVersionRollback already told the user to pin the version in.mcp.json, so
|
|
220
|
-
// stay running rather than trigger that. Other kinds installed the old version and must restart.
|
|
221
|
-
if (kind !== ExecutionKind.NPX)
|
|
222
|
-
process.exit(0);
|
|
218
|
+
process.exit(0);
|
|
223
219
|
}
|
|
@@ -68,6 +68,9 @@ export function takeVersionSkewOnto(payload, connection) {
|
|
|
68
68
|
const skew = takeVersionSkew(connection);
|
|
69
69
|
if (skew === undefined)
|
|
70
70
|
return payload;
|
|
71
|
+
// Compatible, so it did not cause this error: ride along, and leave the advice and the ask alone.
|
|
72
|
+
if (SkewPair.SDK_BEHIND === skew.pair)
|
|
73
|
+
return { ...payload, [EnvelopeKey.VERSION_SKEW]: skew };
|
|
71
74
|
const { feedback, ...rest } = payload;
|
|
72
75
|
return {
|
|
73
76
|
...rest,
|
|
@@ -28,6 +28,12 @@ export declare const SkewPair: {
|
|
|
28
28
|
readonly SDK: "sdk";
|
|
29
29
|
/** Another Reticle process — a CLI, or the MCP server an agent spawned — vs this daemon. */
|
|
30
30
|
readonly DAEMON: "daemon";
|
|
31
|
+
/**
|
|
32
|
+
* The SDK in the page is a minor or more behind, on the same contract: compatible, so it is news
|
|
33
|
+
* and not a cause. Its own pair so it never displaces an untold real skew, and never stands in for
|
|
34
|
+
* the advice on an error it did not cause (see takeVersionSkewOnto).
|
|
35
|
+
*/
|
|
36
|
+
readonly SDK_BEHIND: "sdk_behind";
|
|
31
37
|
};
|
|
32
38
|
export type SkewPair = (typeof SkewPair)[keyof typeof SkewPair];
|
|
33
39
|
/** What a piece says about itself when it connects. */
|
|
@@ -78,7 +84,7 @@ interface SelfIdentity {
|
|
|
78
84
|
* a build provably older than this daemon. With neither signal there is nothing to go on, and
|
|
79
85
|
* inventing a warning would be as dishonest as staying silent about a real one.
|
|
80
86
|
*/
|
|
81
|
-
export declare function describeSkew(
|
|
87
|
+
export declare function describeSkew(given: PeerIdentity, self: SelfIdentity): string | undefined;
|
|
82
88
|
/**
|
|
83
89
|
* The fix line for a page whose SDK disagrees with this daemon, with no project to read.
|
|
84
90
|
*
|
|
@@ -88,6 +94,19 @@ export declare function describeSkew(peer: PeerIdentity, self: SelfIdentity): st
|
|
|
88
94
|
* `@reticlehq/react` and told Vue projects to install a React package (#618).
|
|
89
95
|
*/
|
|
90
96
|
export declare function sdkFix(daemonVersion: string): string;
|
|
97
|
+
/** The same fact for the person looking at the page, on its overlay. */
|
|
98
|
+
export declare const SDK_BEHIND_NARRATION: (sdk: string, daemon: string) => string;
|
|
99
|
+
/**
|
|
100
|
+
* A page whose SDK is a minor release or more behind this daemon.
|
|
101
|
+
*
|
|
102
|
+
* `describeSkew` is silent here on purpose: the contract matches, so the page connects and every
|
|
103
|
+
* verdict is sound. But whatever shipped since is not in the page, the overlay included, and from
|
|
104
|
+
* the field that looked exactly like a broken release: the CLI reported the new version while the
|
|
105
|
+
* page showed an overlay without the newer controls, and nothing anywhere said which SDK it was
|
|
106
|
+
* running. Patch releases stay silent for the cry-wolf reason in the header. `fix` is a thunk
|
|
107
|
+
* because reading the project's manifest is only worth it when the page IS behind.
|
|
108
|
+
*/
|
|
109
|
+
export declare function describeSdkBehind(sdk: string | undefined, daemon: string, fix: () => string): string | undefined;
|
|
91
110
|
/**
|
|
92
111
|
* The fix line for another Reticle process that disagrees with the daemon it attached to.
|
|
93
112
|
*
|
|
@@ -22,6 +22,7 @@
|
|
|
22
22
|
* the wire changes and stays put when internals do. Versions still ride along, because they are what
|
|
23
23
|
* a human acts on.
|
|
24
24
|
*/
|
|
25
|
+
import { RETIRED_WIRE_NAMES } from '@reticlehq/core';
|
|
25
26
|
import { resolveSdkFix } from './sdk-fix.js';
|
|
26
27
|
/** Which pair disagreed. Named so the nudge can report each independently. */
|
|
27
28
|
export const SkewPair = {
|
|
@@ -29,6 +30,12 @@ export const SkewPair = {
|
|
|
29
30
|
SDK: 'sdk',
|
|
30
31
|
/** Another Reticle process — a CLI, or the MCP server an agent spawned — vs this daemon. */
|
|
31
32
|
DAEMON: 'daemon',
|
|
33
|
+
/**
|
|
34
|
+
* The SDK in the page is a minor or more behind, on the same contract: compatible, so it is news
|
|
35
|
+
* and not a cause. Its own pair so it never displaces an untold real skew, and never stands in for
|
|
36
|
+
* the advice on an error it did not cause (see takeVersionSkewOnto).
|
|
37
|
+
*/
|
|
38
|
+
SDK_BEHIND: 'sdk_behind',
|
|
32
39
|
};
|
|
33
40
|
/**
|
|
34
41
|
* Names the peer speaks that we have never heard of.
|
|
@@ -38,15 +45,20 @@ export const SkewPair = {
|
|
|
38
45
|
* is not a browser to do -- there is no touch equivalent of a console error. A peer speaking a name
|
|
39
46
|
* we do not know was built against a contract this daemon does not have, and that is a genuine
|
|
40
47
|
* mismatch: one of us is stale, and tools will behave in ways neither side reports.
|
|
48
|
+
*
|
|
49
|
+
* A name we RETIRED is not unknown: an older peer still lists it, and we never send it (#1343).
|
|
41
50
|
*/
|
|
42
51
|
function namesWeDoNotKnow(peer, self) {
|
|
43
52
|
const unknown = [
|
|
44
53
|
...peer.commands.filter((name) => !self.commands.includes(name)),
|
|
45
54
|
...peer.events.filter((name) => !self.events.includes(name)),
|
|
46
55
|
...peer.actions.filter((name) => !self.actions.includes(name)),
|
|
47
|
-
];
|
|
56
|
+
].filter((name) => !RETIRED_WIRE_NAMES.includes(name));
|
|
48
57
|
return [...new Set(unknown)].sort();
|
|
49
58
|
}
|
|
59
|
+
/** The fix for two builds of one version. */
|
|
60
|
+
const SAME_VERSION_FIX = 'Both say the same version, so one of them is an older build of it: run `reticle restart`, then ' +
|
|
61
|
+
'reload the page so it loads the SDK the dev server serves now.';
|
|
50
62
|
function versionPhrase(peer, self) {
|
|
51
63
|
return peer.version === undefined
|
|
52
64
|
? `${peer.what} is on an unknown version; this daemon is ${self.version}`
|
|
@@ -69,16 +81,25 @@ function versionPhrase(peer, self) {
|
|
|
69
81
|
* a build provably older than this daemon. With neither signal there is nothing to go on, and
|
|
70
82
|
* inventing a warning would be as dishonest as staying silent about a real one.
|
|
71
83
|
*/
|
|
72
|
-
export function describeSkew(
|
|
73
|
-
if (
|
|
84
|
+
export function describeSkew(given, self) {
|
|
85
|
+
if (given.contract !== undefined && given.contract === self.contract)
|
|
74
86
|
return undefined;
|
|
87
|
+
// One version, two builds (a daemon running code older than its install, a cached page bundle):
|
|
88
|
+
// installing that version again changes nothing, so the fix is the restart and the reload.
|
|
89
|
+
const peer = given.version === self.version ? { ...given, fix: SAME_VERSION_FIX } : given;
|
|
75
90
|
// Both sides said which names they speak, so compare the names rather than a hash over them.
|
|
76
91
|
if (peer.contractParts !== undefined && self.contractParts !== undefined) {
|
|
77
92
|
const unknown = namesWeDoNotKnow(peer.contractParts, self.contractParts);
|
|
78
93
|
if (0 === unknown.length)
|
|
79
94
|
return undefined;
|
|
95
|
+
// Direction comes from the versions when both are known. An older peer naming something we do
|
|
96
|
+
// not know has a name we removed without retiring it, not a newer contract.
|
|
97
|
+
const order = compareVersions(peer.version, self.version);
|
|
98
|
+
const why = order !== undefined && order < 0
|
|
99
|
+
? 'though it is the older of the two — so this daemon dropped a name it still uses'
|
|
100
|
+
: 'so it was built against a newer contract than this one';
|
|
80
101
|
return (`version skew: ${versionPhrase(peer, self)}, and ${peer.what} speaks names this daemon does ` +
|
|
81
|
-
`not know (${unknown.join(', ')}) —
|
|
102
|
+
`not know (${unknown.join(', ')}) — ${why}. ` +
|
|
82
103
|
`Tools will behave in ways neither side reports. ${peer.fix}`);
|
|
83
104
|
}
|
|
84
105
|
if (peer.contract === undefined) {
|
|
@@ -143,6 +164,30 @@ function compareVersions(a, b) {
|
|
|
143
164
|
}
|
|
144
165
|
return 0;
|
|
145
166
|
}
|
|
167
|
+
/** The same fact for the person looking at the page, on its overlay. */
|
|
168
|
+
export const SDK_BEHIND_NARRATION = (sdk, daemon) => `This app runs Reticle SDK ${sdk}, older than Reticle ${daemon}. Run \`reticle update\` in the ` +
|
|
169
|
+
"app's folder, then restart its dev server.";
|
|
170
|
+
/**
|
|
171
|
+
* A page whose SDK is a minor release or more behind this daemon.
|
|
172
|
+
*
|
|
173
|
+
* `describeSkew` is silent here on purpose: the contract matches, so the page connects and every
|
|
174
|
+
* verdict is sound. But whatever shipped since is not in the page, the overlay included, and from
|
|
175
|
+
* the field that looked exactly like a broken release: the CLI reported the new version while the
|
|
176
|
+
* page showed an overlay without the newer controls, and nothing anywhere said which SDK it was
|
|
177
|
+
* running. Patch releases stay silent for the cry-wolf reason in the header. `fix` is a thunk
|
|
178
|
+
* because reading the project's manifest is only worth it when the page IS behind.
|
|
179
|
+
*/
|
|
180
|
+
export function describeSdkBehind(sdk, daemon, fix) {
|
|
181
|
+
const minorOf = (v) => v.split('-')[0]?.split('.').slice(0, 2).join('.') ?? v;
|
|
182
|
+
if (sdk === undefined)
|
|
183
|
+
return undefined;
|
|
184
|
+
const order = compareVersions(minorOf(sdk), minorOf(daemon));
|
|
185
|
+
if (order === undefined || order >= 0)
|
|
186
|
+
return undefined;
|
|
187
|
+
return (`This page runs Reticle SDK ${sdk}, older than Reticle ${daemon}. It connects and verifies, ` +
|
|
188
|
+
`but everything added since is missing from the page, the overlay's newer controls included. ` +
|
|
189
|
+
fix());
|
|
190
|
+
}
|
|
146
191
|
/**
|
|
147
192
|
* The fix line for another Reticle process that disagrees with the daemon it attached to.
|
|
148
193
|
*
|
|
@@ -87,6 +87,10 @@ export const CRAWL_TOOLS = [
|
|
|
87
87
|
.optional()
|
|
88
88
|
.describe('Present only when the page exceeded one snapshot, so controls past the cap were never listed. When present, a zero-anomaly result does NOT mean the app is clean.'),
|
|
89
89
|
truncated: z.boolean(),
|
|
90
|
+
notJudged: z
|
|
91
|
+
.array(z.object({ ref: z.string(), desc: z.string(), reason: z.string() }))
|
|
92
|
+
.optional()
|
|
93
|
+
.describe('Controls clicked whose silence could not be judged, e.g. on a background tab. They are NOT reported as dead, and they are not known to work either.'),
|
|
90
94
|
// Only on `exhaustive` — see features/exhaust/exhaust-run.ts. Loose: it carries the levels.
|
|
91
95
|
exhaustive: z.record(z.unknown()).optional(),
|
|
92
96
|
},
|
|
@@ -81,6 +81,12 @@ export interface CrawlReport {
|
|
|
81
81
|
truncated: boolean;
|
|
82
82
|
/** Present only when the snapshot itself was capped, i.e. controls exist that were never listed. */
|
|
83
83
|
coverageNote?: string;
|
|
84
|
+
/** Controls whose silence could not be judged, present only when non-empty. */
|
|
85
|
+
notJudged?: {
|
|
86
|
+
ref: string;
|
|
87
|
+
desc: string;
|
|
88
|
+
reason: string;
|
|
89
|
+
}[];
|
|
84
90
|
}
|
|
85
91
|
export interface CrawlOptions {
|
|
86
92
|
maxSteps?: number;
|
|
@@ -33,6 +33,15 @@ function revealedControlsNote(count) {
|
|
|
33
33
|
'started were never visited — interactiveFound is a floor, not a total; re-run the crawl from ' +
|
|
34
34
|
'the state you are now in to cover them');
|
|
35
35
|
}
|
|
36
|
+
/**
|
|
37
|
+
* Controls that end the signed-in session. Not destructive (signing out is reversible, so the
|
|
38
|
+
* action gate lets it through), but a crawl that presses one drives everything after it signed out:
|
|
39
|
+
* every Harness plan run clicked the sidebar's "Sign out", then stale refs on the sign-in page.
|
|
40
|
+
*/
|
|
41
|
+
const ENDS_SESSION = /\b(?:sign ?out|log ?out|sign ?off|log ?off)\b/i;
|
|
42
|
+
const ENDS_SESSION_NOT_PRESSED = 'not pressed: it ends the signed-in session the crawl is driving';
|
|
43
|
+
/** Why a silent control on a throttled page is not reported as dead. */
|
|
44
|
+
const BACKGROUND_TAB_NOT_JUDGED = 'not judged: the page is throttled (its tab is in the background, or it has not been heard from recently), so a reaction may not show inside the sample window; bring the tab to the front and crawl again';
|
|
36
45
|
/** Any buffer event that proves the app reacted to a click (vs a dead/no-op control). */
|
|
37
46
|
function isActivity(e) {
|
|
38
47
|
return (e.type === EventType.NET_REQUEST ||
|
|
@@ -255,6 +264,7 @@ export async function crawl(session, opts, sleep) {
|
|
|
255
264
|
// `truncated:false` would positively assert that nothing was cut.
|
|
256
265
|
const coverageCapped = true === snapshot.truncated;
|
|
257
266
|
const anomalies = [];
|
|
267
|
+
const notJudged = [];
|
|
258
268
|
const visited = [];
|
|
259
269
|
const counts = { consoleErrors: 0, failedRequests: 0, deadControls: 0, contradictions: 0 };
|
|
260
270
|
const seen = new Set();
|
|
@@ -275,6 +285,10 @@ export async function crawl(session, opts, sleep) {
|
|
|
275
285
|
if (seen.has(dedupeKey))
|
|
276
286
|
continue; // don't re-click the same control
|
|
277
287
|
seen.add(dedupeKey);
|
|
288
|
+
if (ENDS_SESSION.test(item.desc)) {
|
|
289
|
+
notJudged.push({ ref: item.ref, desc: item.desc, reason: ENDS_SESSION_NOT_PRESSED });
|
|
290
|
+
continue;
|
|
291
|
+
}
|
|
278
292
|
stepsRun += 1;
|
|
279
293
|
visited.push(item.desc);
|
|
280
294
|
const since = session.elapsed();
|
|
@@ -401,7 +415,11 @@ export async function crawl(session, opts, sleep) {
|
|
|
401
415
|
//
|
|
402
416
|
// A second click costs one round trip on the rare control that looked dead, and nothing at all
|
|
403
417
|
// on every control that did not. A genuinely dead control is silent twice; the flake is not.
|
|
404
|
-
|
|
418
|
+
// A throttled page may defer DOM observer flushes, so silence cannot prove a dead control.
|
|
419
|
+
if (true === session.throttled?.()) {
|
|
420
|
+
notJudged.push({ ref: item.ref, desc: item.desc, reason: BACKGROUND_TAB_NOT_JUDGED });
|
|
421
|
+
}
|
|
422
|
+
else if (await stillSilent(session, item, settleMs, confirm, sleep)) {
|
|
405
423
|
counts.deadControls += 1;
|
|
406
424
|
anomalies.push({
|
|
407
425
|
kind: CrawlAnomalyKind.DEAD_CONTROL,
|
|
@@ -429,16 +447,19 @@ export async function crawl(session, opts, sleep) {
|
|
|
429
447
|
// unvisited. Skipped when the snapshot was already capped: that case has its own note and a second
|
|
430
448
|
// one would only muddy it.
|
|
431
449
|
const revealed = coverageCapped ? 0 : (await revealedItems(session, opts, found)).length;
|
|
450
|
+
// Left alone on purpose, so not a step the budget ran out before.
|
|
451
|
+
const leftAlone = notJudged.filter((n) => ENDS_SESSION_NOT_PRESSED === n.reason).length;
|
|
432
452
|
return {
|
|
433
453
|
interactiveFound: found.length,
|
|
434
454
|
stepsRun,
|
|
435
455
|
anomalies,
|
|
436
456
|
counts,
|
|
437
457
|
visited,
|
|
458
|
+
...(0 === notJudged.length ? {} : { notJudged }),
|
|
438
459
|
// True when coverage was bounded for EITHER reason: the step budget ran out, or the page was
|
|
439
460
|
// bigger than one snapshot. Conflating "I stopped early" with "I saw everything" is what turns a
|
|
440
461
|
// partial sweep into "all controls healthy".
|
|
441
|
-
truncated: found.length > stepsRun || coverageCapped || revealed > 0,
|
|
462
|
+
truncated: found.length - leftAlone > stepsRun || coverageCapped || revealed > 0,
|
|
442
463
|
...(coverageCapped
|
|
443
464
|
? { coverageNote: CAPPED_SNAPSHOT_NOTE }
|
|
444
465
|
: revealed > 0
|
|
@@ -47,12 +47,12 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
47
47
|
proved: z.ZodArray<z.ZodString, "many">;
|
|
48
48
|
}, "strip", z.ZodTypeAny, {
|
|
49
49
|
proved: string[];
|
|
50
|
-
touched: string[];
|
|
51
50
|
seen: string[];
|
|
51
|
+
touched: string[];
|
|
52
52
|
}, {
|
|
53
53
|
proved: string[];
|
|
54
|
-
touched: string[];
|
|
55
54
|
seen: string[];
|
|
55
|
+
touched: string[];
|
|
56
56
|
}>;
|
|
57
57
|
journeys: z.ZodObject<{
|
|
58
58
|
completed: z.ZodArray<z.ZodString, "many">;
|
|
@@ -66,12 +66,12 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
66
66
|
branched: z.ZodArray<z.ZodString, "many">;
|
|
67
67
|
unhandled: z.ZodArray<z.ZodString, "many">;
|
|
68
68
|
}, "strip", z.ZodTypeAny, {
|
|
69
|
-
branched: string[];
|
|
70
69
|
seen: string[];
|
|
70
|
+
branched: string[];
|
|
71
71
|
unhandled: string[];
|
|
72
72
|
}, {
|
|
73
|
-
branched: string[];
|
|
74
73
|
seen: string[];
|
|
74
|
+
branched: string[];
|
|
75
75
|
unhandled: string[];
|
|
76
76
|
}>;
|
|
77
77
|
code: z.ZodRecord<z.ZodString, z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
@@ -92,6 +92,9 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
92
92
|
name: string;
|
|
93
93
|
executed: boolean;
|
|
94
94
|
}>>;
|
|
95
|
+
journeys: {
|
|
96
|
+
completed: string[];
|
|
97
|
+
};
|
|
95
98
|
best: Record<string, number>;
|
|
96
99
|
routes: {
|
|
97
100
|
reached: string[];
|
|
@@ -99,15 +102,12 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
99
102
|
};
|
|
100
103
|
controls: {
|
|
101
104
|
proved: string[];
|
|
102
|
-
touched: string[];
|
|
103
105
|
seen: string[];
|
|
104
|
-
|
|
105
|
-
journeys: {
|
|
106
|
-
completed: string[];
|
|
106
|
+
touched: string[];
|
|
107
107
|
};
|
|
108
108
|
writes: {
|
|
109
|
-
branched: string[];
|
|
110
109
|
seen: string[];
|
|
110
|
+
branched: string[];
|
|
111
111
|
unhandled: string[];
|
|
112
112
|
};
|
|
113
113
|
codeTaken: Record<string, number>;
|
|
@@ -116,6 +116,9 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
116
116
|
name: string;
|
|
117
117
|
executed: boolean;
|
|
118
118
|
}>>;
|
|
119
|
+
journeys: {
|
|
120
|
+
completed: string[];
|
|
121
|
+
};
|
|
119
122
|
best: Record<string, number>;
|
|
120
123
|
routes: {
|
|
121
124
|
reached: string[];
|
|
@@ -123,15 +126,12 @@ declare const LedgerSchema: z.ZodObject<{
|
|
|
123
126
|
};
|
|
124
127
|
controls: {
|
|
125
128
|
proved: string[];
|
|
126
|
-
touched: string[];
|
|
127
129
|
seen: string[];
|
|
128
|
-
|
|
129
|
-
journeys: {
|
|
130
|
-
completed: string[];
|
|
130
|
+
touched: string[];
|
|
131
131
|
};
|
|
132
132
|
writes: {
|
|
133
|
-
branched: string[];
|
|
134
133
|
seen: string[];
|
|
134
|
+
branched: string[];
|
|
135
135
|
unhandled: string[];
|
|
136
136
|
};
|
|
137
137
|
codeTaken?: Record<string, number> | undefined;
|
|
@@ -158,6 +158,13 @@ export interface LevelReport {
|
|
|
158
158
|
/** How many more are missing than `missing` names. */
|
|
159
159
|
missingOverflow?: number;
|
|
160
160
|
}
|
|
161
|
+
/**
|
|
162
|
+
* Each level's percentage for the project at `reticleRoot`, for the HUD: numbers only, and only the
|
|
163
|
+
* levels with an honest denominator. Undefined when nothing has been measured yet.
|
|
164
|
+
*
|
|
165
|
+
* Synchronous because the impact snapshot it feeds is: one small file read per snapshot.
|
|
166
|
+
*/
|
|
167
|
+
export declare function coveragePercents(reticleRoot: string): Record<string, number> | undefined;
|
|
161
168
|
export declare function emptyLedger(): AppLedger;
|
|
162
169
|
export declare function mergeLedger(into: AppLedger, delta: LedgerDelta): AppLedger;
|
|
163
170
|
export declare function levelsOf(ledger: AppLedger): LevelReport[];
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
* Union-only. A later drive can add coverage and never remove it, so the number only moves down when
|
|
19
19
|
* the app grows something nobody has covered yet — which is precisely what the ratchet is for.
|
|
20
20
|
*/
|
|
21
|
+
import { readFileSync } from 'node:fs';
|
|
21
22
|
import { dirname } from 'node:path';
|
|
22
23
|
import { z } from 'zod';
|
|
23
24
|
import { writeFileAtomic } from '../../memory/project/fs/write-atomic.js';
|
|
@@ -45,6 +46,39 @@ const LedgerSchema = z.object({
|
|
|
45
46
|
codeTaken: z.record(z.number()).default({}),
|
|
46
47
|
best: z.record(z.number()),
|
|
47
48
|
});
|
|
49
|
+
/** A ledger file's text, or an empty ledger for anything unreadable: coverage never throws. */
|
|
50
|
+
function parseLedger(text) {
|
|
51
|
+
try {
|
|
52
|
+
const parsed = z
|
|
53
|
+
.object({ version: z.literal(LEDGER_VERSION), ledger: LedgerSchema })
|
|
54
|
+
.safeParse(JSON.parse(text));
|
|
55
|
+
return parsed.success ? parsed.data.ledger : emptyLedger();
|
|
56
|
+
}
|
|
57
|
+
catch {
|
|
58
|
+
return emptyLedger();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* Each level's percentage for the project at `reticleRoot`, for the HUD: numbers only, and only the
|
|
63
|
+
* levels with an honest denominator. Undefined when nothing has been measured yet.
|
|
64
|
+
*
|
|
65
|
+
* Synchronous because the impact snapshot it feeds is: one small file read per snapshot.
|
|
66
|
+
*/
|
|
67
|
+
export function coveragePercents(reticleRoot) {
|
|
68
|
+
let text;
|
|
69
|
+
try {
|
|
70
|
+
text = readFileSync(reticleDirPaths(reticleRoot).coverage, 'utf8');
|
|
71
|
+
}
|
|
72
|
+
catch {
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
const out = {};
|
|
76
|
+
for (const report of levelsOf(parseLedger(text))) {
|
|
77
|
+
if (report.pct !== undefined)
|
|
78
|
+
out[report.level] = report.pct;
|
|
79
|
+
}
|
|
80
|
+
return 0 < Object.keys(out).length ? out : undefined;
|
|
81
|
+
}
|
|
48
82
|
export function emptyLedger() {
|
|
49
83
|
return {
|
|
50
84
|
routes: { discovered: [], reached: [] },
|
|
@@ -213,15 +247,7 @@ export class LedgerStore {
|
|
|
213
247
|
return emptyLedger();
|
|
214
248
|
throw error;
|
|
215
249
|
}
|
|
216
|
-
|
|
217
|
-
const parsed = z
|
|
218
|
-
.object({ version: z.literal(LEDGER_VERSION), ledger: LedgerSchema })
|
|
219
|
-
.safeParse(JSON.parse(text));
|
|
220
|
-
return parsed.success ? parsed.data.ledger : emptyLedger();
|
|
221
|
-
}
|
|
222
|
-
catch {
|
|
223
|
-
return emptyLedger();
|
|
224
|
-
}
|
|
250
|
+
return parseLedger(text);
|
|
225
251
|
}
|
|
226
252
|
/**
|
|
227
253
|
* Fold a delta in, raise the best, persist, and hand back the result. Under the file's lock: two
|