@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,19 +1,23 @@
|
|
|
1
|
-
import { HudPanel, HudView, type HudUseData } from '@reticlehq/core';
|
|
1
|
+
import { HudPanel, HudView, type HudPromptSurface, type HudUseData } from '@reticlehq/core';
|
|
2
2
|
/**
|
|
3
3
|
* How people use the in-page HUD, rolled into the session summary.
|
|
4
4
|
*
|
|
5
5
|
* Windowed like the tool histograms beside it: a periodic flush reports what happened since the
|
|
6
6
|
* last one, so a dashboard sums across a session's events. Names only — every key is a control id
|
|
7
7
|
* the wire schema already checked against core's closed list.
|
|
8
|
+
*
|
|
9
|
+
* Time is kept PER TAB and only while the tab is visible. Two tabs used to share one open view, so
|
|
10
|
+
* one tab's change closed the other's clock, and a hidden or closed tab kept accruing for as long as
|
|
11
|
+
* the daemon lived.
|
|
8
12
|
*/
|
|
9
13
|
/** How many steps of the journey one window keeps. A journey longer than this is cut, and says so. */
|
|
10
14
|
export declare const HUD_JOURNEY_MAX = 60;
|
|
11
15
|
export interface HudSummary {
|
|
12
16
|
/** Presses per control; a toggle counts under `id:on` / `id:off` so a switch reads both ways. */
|
|
13
17
|
hudControls?: Record<string, number>;
|
|
14
|
-
/** Milliseconds the HUD spent in each view during the window. */
|
|
18
|
+
/** Milliseconds the HUD spent in each view during the window, summed over visible tabs. */
|
|
15
19
|
hudViewMs?: Partial<Record<HudView, number>>;
|
|
16
|
-
/** Milliseconds each panel was showing during the window. */
|
|
20
|
+
/** Milliseconds each panel was showing during the window, summed over visible tabs. */
|
|
17
21
|
hudPanelMs?: Partial<Record<HudPanel, number>>;
|
|
18
22
|
/** The window's presses and view changes, in order, cut at HUD_JOURNEY_MAX. */
|
|
19
23
|
hudJourney?: string[];
|
|
@@ -22,13 +26,30 @@ export interface HudSummary {
|
|
|
22
26
|
/** Times each rail slide became the visible one. Slide ids are Reticle's own, never page text. */
|
|
23
27
|
hudSlides?: Record<string, number>;
|
|
24
28
|
}
|
|
29
|
+
/** The same page opened again on the same tab within this long is one view, not two. */
|
|
30
|
+
export declare const HUD_VIEW_DEDUPE_MS = 30000;
|
|
31
|
+
/** What one HUD use means for the per-event signals, beside what it adds to the summary. */
|
|
32
|
+
export interface HudSignals {
|
|
33
|
+
/** A page this tab had not opened within the dedupe window. */
|
|
34
|
+
viewed?: HudPanel;
|
|
35
|
+
/** A sign-in prompt this tab had not shown before. */
|
|
36
|
+
prompted?: HudPromptSurface;
|
|
37
|
+
/** Tabs with a HUD right now. */
|
|
38
|
+
tabs: number;
|
|
39
|
+
}
|
|
25
40
|
export declare class HudMetrics {
|
|
26
41
|
#private;
|
|
27
42
|
constructor(now: () => number);
|
|
28
|
-
record(use: HudUseData):
|
|
43
|
+
record(use: HudUseData, tabId?: string): HudSignals;
|
|
44
|
+
/** The tab went into the background: its HUD stops accruing time until it is shown again. */
|
|
45
|
+
hide(tabId: string): void;
|
|
46
|
+
/** The tab is in front again: its HUD's view and panel accrue from now. */
|
|
47
|
+
show(tabId: string): void;
|
|
48
|
+
/** The tab went away: whatever it had open is counted up to now and stops. */
|
|
49
|
+
close(tabId: string): void;
|
|
29
50
|
get empty(): boolean;
|
|
30
|
-
/** The window so far. Open
|
|
51
|
+
/** The window so far. Open views and panels are counted up to now, and keep running after. */
|
|
31
52
|
summarize(): HudSummary;
|
|
32
|
-
/** Start the next window.
|
|
53
|
+
/** Start the next window. Each visible tab's view and panel carry over, timed from now. */
|
|
33
54
|
reset(): void;
|
|
34
55
|
}
|
|
@@ -6,12 +6,20 @@ import { HudPanel, HudView } from '@reticlehq/core';
|
|
|
6
6
|
* Windowed like the tool histograms beside it: a periodic flush reports what happened since the
|
|
7
7
|
* last one, so a dashboard sums across a session's events. Names only — every key is a control id
|
|
8
8
|
* the wire schema already checked against core's closed list.
|
|
9
|
+
*
|
|
10
|
+
* Time is kept PER TAB and only while the tab is visible. Two tabs used to share one open view, so
|
|
11
|
+
* one tab's change closed the other's clock, and a hidden or closed tab kept accruing for as long as
|
|
12
|
+
* the daemon lived.
|
|
9
13
|
*/
|
|
10
14
|
/** How many steps of the journey one window keeps. A journey longer than this is cut, and says so. */
|
|
11
15
|
export const HUD_JOURNEY_MAX = 60;
|
|
12
16
|
/** Distinct slide ids counted per window; past this a broken notices file is not a dashboard. */
|
|
13
17
|
const MAX_SLIDE_IDS = 20;
|
|
14
18
|
const SLIDE_ID = /^[a-z0-9-]{1,56}$/;
|
|
19
|
+
/** The same page opened again on the same tab within this long is one view, not two. */
|
|
20
|
+
export const HUD_VIEW_DEDUPE_MS = 30_000;
|
|
21
|
+
/** A tab whose page reported HUD use without saying which tab: an older caller, or a test. */
|
|
22
|
+
const UNNAMED_TAB = '';
|
|
15
23
|
export class HudMetrics {
|
|
16
24
|
#now;
|
|
17
25
|
#controls = new Map();
|
|
@@ -19,39 +27,103 @@ export class HudMetrics {
|
|
|
19
27
|
#panelMs = new Map();
|
|
20
28
|
#journey = [];
|
|
21
29
|
#slides = new Map();
|
|
30
|
+
#tabs = new Map();
|
|
22
31
|
#cut = false;
|
|
23
32
|
/** Did anything happen this window. A HUD merely sitting open is not worth a flush of its own. */
|
|
24
33
|
#changed = false;
|
|
25
|
-
#view;
|
|
26
|
-
#panel;
|
|
27
34
|
constructor(now) {
|
|
28
35
|
this.#now = now;
|
|
29
36
|
}
|
|
30
|
-
record(use) {
|
|
37
|
+
record(use, tabId = UNNAMED_TAB) {
|
|
38
|
+
const tab = this.#tab(tabId);
|
|
39
|
+
const signals = { tabs: this.#tabs.size };
|
|
40
|
+
if (use.prompt !== undefined && !tab.prompted.has(use.prompt)) {
|
|
41
|
+
tab.prompted.add(use.prompt);
|
|
42
|
+
signals.prompted = use.prompt;
|
|
43
|
+
}
|
|
31
44
|
// A control the HUD never rendered is dropped here, the one place HUD use is counted, so free
|
|
32
45
|
// text cannot ride in on the id.
|
|
33
46
|
const control = use.control !== undefined && isHudControl(use.control) ? use.control : undefined;
|
|
34
47
|
if (use.slide !== undefined)
|
|
35
48
|
this.#countSlide(use.slide);
|
|
36
49
|
if (control === undefined && use.view === undefined && use.panel === undefined)
|
|
37
|
-
return;
|
|
50
|
+
return signals;
|
|
38
51
|
this.#changed = true;
|
|
39
52
|
if (control !== undefined) {
|
|
40
53
|
const key = use.toggle === undefined ? control : `${control}:${use.toggle}`;
|
|
41
54
|
this.#controls.set(key, (this.#controls.get(key) ?? 0) + 1);
|
|
42
55
|
this.#step(key);
|
|
43
56
|
}
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
57
|
+
const at = this.#now();
|
|
58
|
+
const since = tab.hidden ? undefined : at;
|
|
59
|
+
if (use.view !== undefined && use.view !== tab.view?.value) {
|
|
60
|
+
this.#close(tab.view, this.#viewMs);
|
|
61
|
+
tab.view = { value: use.view, since };
|
|
47
62
|
this.#step(`view:${use.view}`);
|
|
48
63
|
}
|
|
49
|
-
if (use.panel !== undefined && use.panel !==
|
|
50
|
-
this.#close(
|
|
51
|
-
|
|
52
|
-
if (use.panel !== HudPanel.NONE)
|
|
64
|
+
if (use.panel !== undefined && use.panel !== tab.panel?.value) {
|
|
65
|
+
this.#close(tab.panel, this.#panelMs);
|
|
66
|
+
tab.panel = { value: use.panel, since };
|
|
67
|
+
if (use.panel !== HudPanel.NONE) {
|
|
53
68
|
this.#step(`panel:${use.panel}`);
|
|
69
|
+
const last = tab.viewedAt.get(use.panel);
|
|
70
|
+
if (last === undefined || at - last >= HUD_VIEW_DEDUPE_MS) {
|
|
71
|
+
tab.viewedAt.set(use.panel, at);
|
|
72
|
+
signals.viewed = use.panel;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
54
75
|
}
|
|
76
|
+
return signals;
|
|
77
|
+
}
|
|
78
|
+
/** The tab went into the background: its HUD stops accruing time until it is shown again. */
|
|
79
|
+
hide(tabId) {
|
|
80
|
+
const tab = this.#tabs.get(tabId);
|
|
81
|
+
if (tab === undefined || tab.hidden)
|
|
82
|
+
return;
|
|
83
|
+
tab.hidden = true;
|
|
84
|
+
this.#pause(tab);
|
|
85
|
+
}
|
|
86
|
+
/** The tab is in front again: its HUD's view and panel accrue from now. */
|
|
87
|
+
show(tabId) {
|
|
88
|
+
const tab = this.#tabs.get(tabId);
|
|
89
|
+
if (tab === undefined || !tab.hidden)
|
|
90
|
+
return;
|
|
91
|
+
tab.hidden = false;
|
|
92
|
+
const at = this.#now();
|
|
93
|
+
if (tab.view !== undefined)
|
|
94
|
+
tab.view = { ...tab.view, since: at };
|
|
95
|
+
if (tab.panel !== undefined)
|
|
96
|
+
tab.panel = { ...tab.panel, since: at };
|
|
97
|
+
}
|
|
98
|
+
/** The tab went away: whatever it had open is counted up to now and stops. */
|
|
99
|
+
close(tabId) {
|
|
100
|
+
const tab = this.#tabs.get(tabId);
|
|
101
|
+
if (tab === undefined)
|
|
102
|
+
return;
|
|
103
|
+
this.#pause(tab);
|
|
104
|
+
this.#tabs.delete(tabId);
|
|
105
|
+
}
|
|
106
|
+
#tab(tabId) {
|
|
107
|
+
const known = this.#tabs.get(tabId);
|
|
108
|
+
if (known !== undefined)
|
|
109
|
+
return known;
|
|
110
|
+
const tab = {
|
|
111
|
+
view: undefined,
|
|
112
|
+
panel: undefined,
|
|
113
|
+
hidden: false,
|
|
114
|
+
viewedAt: new Map(),
|
|
115
|
+
prompted: new Set(),
|
|
116
|
+
};
|
|
117
|
+
this.#tabs.set(tabId, tab);
|
|
118
|
+
return tab;
|
|
119
|
+
}
|
|
120
|
+
#pause(tab) {
|
|
121
|
+
this.#close(tab.view, this.#viewMs);
|
|
122
|
+
this.#close(tab.panel, this.#panelMs);
|
|
123
|
+
if (tab.view !== undefined)
|
|
124
|
+
tab.view = { ...tab.view, since: undefined };
|
|
125
|
+
if (tab.panel !== undefined)
|
|
126
|
+
tab.panel = { ...tab.panel, since: undefined };
|
|
55
127
|
}
|
|
56
128
|
#countSlide(slide) {
|
|
57
129
|
// A slide id is Reticle's own (`notice-<id>` for the remote ones): lowercase words and dashes.
|
|
@@ -65,10 +137,14 @@ export class HudMetrics {
|
|
|
65
137
|
get empty() {
|
|
66
138
|
return !this.#changed;
|
|
67
139
|
}
|
|
68
|
-
/** The window so far. Open
|
|
140
|
+
/** The window so far. Open views and panels are counted up to now, and keep running after. */
|
|
69
141
|
summarize() {
|
|
70
|
-
const viewMs =
|
|
71
|
-
const panelMs =
|
|
142
|
+
const viewMs = new Map(this.#viewMs);
|
|
143
|
+
const panelMs = new Map(this.#panelMs);
|
|
144
|
+
for (const tab of this.#tabs.values()) {
|
|
145
|
+
this.#close(tab.view, viewMs);
|
|
146
|
+
this.#close(tab.panel, panelMs);
|
|
147
|
+
}
|
|
72
148
|
return {
|
|
73
149
|
...(this.#controls.size > 0 ? { hudControls: Object.fromEntries(this.#controls) } : {}),
|
|
74
150
|
...(viewMs.size > 0 ? { hudViewMs: Object.fromEntries(viewMs) } : {}),
|
|
@@ -78,7 +154,7 @@ export class HudMetrics {
|
|
|
78
154
|
...(this.#slides.size > 0 ? { hudSlides: Object.fromEntries(this.#slides) } : {}),
|
|
79
155
|
};
|
|
80
156
|
}
|
|
81
|
-
/** Start the next window.
|
|
157
|
+
/** Start the next window. Each visible tab's view and panel carry over, timed from now. */
|
|
82
158
|
reset() {
|
|
83
159
|
const at = this.#now();
|
|
84
160
|
this.#controls.clear();
|
|
@@ -88,10 +164,12 @@ export class HudMetrics {
|
|
|
88
164
|
this.#journey.length = 0;
|
|
89
165
|
this.#cut = false;
|
|
90
166
|
this.#changed = false;
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
167
|
+
for (const tab of this.#tabs.values()) {
|
|
168
|
+
if (tab.view?.since !== undefined)
|
|
169
|
+
tab.view = { ...tab.view, since: at };
|
|
170
|
+
if (tab.panel?.since !== undefined)
|
|
171
|
+
tab.panel = { ...tab.panel, since: at };
|
|
172
|
+
}
|
|
95
173
|
}
|
|
96
174
|
#step(entry) {
|
|
97
175
|
if (this.#journey.length < HUD_JOURNEY_MAX)
|
|
@@ -99,14 +177,10 @@ export class HudMetrics {
|
|
|
99
177
|
else
|
|
100
178
|
this.#cut = true;
|
|
101
179
|
}
|
|
180
|
+
/** Add an open view's time since it last started accruing; nothing while it is paused. */
|
|
102
181
|
#close(open, into) {
|
|
103
|
-
if (open === undefined)
|
|
182
|
+
if (open?.since === undefined)
|
|
104
183
|
return;
|
|
105
184
|
into.set(open.value, (into.get(open.value) ?? 0) + Math.max(0, this.#now() - open.since));
|
|
106
185
|
}
|
|
107
|
-
#withOpen(open, closed) {
|
|
108
|
-
const out = new Map(closed);
|
|
109
|
-
this.#close(open, out);
|
|
110
|
-
return out;
|
|
111
|
-
}
|
|
112
186
|
}
|
|
@@ -12,7 +12,7 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import { TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
14
14
|
import { getTelemetry } from './telemetry.js';
|
|
15
|
-
import { resolveInstallSource } from './install-source.js';
|
|
15
|
+
import { INSTALL_STATE_DIR, resolveInstallSource } from './install-source.js';
|
|
16
16
|
// The failure vocabulary lives in `@reticlehq/init`, which is what classifies a failed run.
|
|
17
17
|
// Re-exported so every consumer here is unchanged.
|
|
18
18
|
export { InitFailure } from '@reticlehq/init';
|
|
@@ -25,7 +25,7 @@ export function reportInitOutcome(init) {
|
|
|
25
25
|
// The other half of attribution: `reticle_installed` says a machine arrived, this says the
|
|
26
26
|
// setup on it finished, and only together do they say which route converts. Same self-declared
|
|
27
27
|
// marker, same refusal to infer — see install-source.ts.
|
|
28
|
-
installSource: resolveInstallSource(),
|
|
28
|
+
installSource: resolveInstallSource(process.env, INSTALL_STATE_DIR),
|
|
29
29
|
});
|
|
30
30
|
}
|
|
31
31
|
catch {
|
|
@@ -1,27 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Which published route brought an install in.
|
|
3
|
-
*
|
|
4
|
-
* Four install routes ship at once and none of them could be told apart, so every question about
|
|
5
|
-
* where distribution effort is working had no data behind it at all.
|
|
6
|
-
*
|
|
7
|
-
* ONE mechanism: an environment variable a channel sets on itself. Everything else that looked like
|
|
8
|
-
* a signal turned out not to be one — see `InstallSource` in core for why `npm_config_user_agent`,
|
|
9
|
-
* a `.claude-plugin/` directory and an installed skill folder all fail to separate these routes.
|
|
10
|
-
*
|
|
11
|
-
* WHICH CHANNELS ARE GENUINELY DETECTABLE TODAY, so nobody later reads a small `unknown` as success:
|
|
12
|
-
* - `plugin` — real. The Claude Code plugin registers the MCP server itself and can set the marker
|
|
13
|
-
* in that server's `env`, so it is carried by the process without anybody typing anything.
|
|
14
|
-
* - `skill_file` / `npx_skill` / `docs_site` / `readme` — real ONLY where that channel's own copy
|
|
15
|
-
* of the install command carries the marker. Each is a separately published artifact, so a copy
|
|
16
|
-
* that has not been updated is indistinguishable from no channel at all.
|
|
17
|
-
* - `cli_direct` — NOT detectable. Nobody types a marker to say they typed a command. It exists so
|
|
18
|
-
* a wrapper can declare it, and until something does, a direct install reports `unknown`.
|
|
19
|
-
*
|
|
20
|
-
* `unknown` is therefore expected to be the largest bucket for as long as the marker is spreading,
|
|
21
|
-
* and shrinking it is a distribution job, never a classifier job. A guessed attribution is worse
|
|
22
|
-
* than none: it is the number distribution decisions get steered on, and a guess and a measurement
|
|
23
|
-
* are indistinguishable once they are in the same column.
|
|
24
|
-
*/
|
|
25
1
|
import { InstallSource } from '@reticlehq/core/telemetry';
|
|
26
2
|
/** The one marker. Set by a channel on the process that runs the install. */
|
|
27
3
|
export declare const INSTALL_SOURCE_ENV = "RETICLE_INSTALL_SOURCE";
|
|
@@ -33,7 +9,19 @@ export declare const INSTALL_SOURCE_ENV = "RETICLE_INSTALL_SOURCE";
|
|
|
33
9
|
* whole contract is built on. Trimmed and lowercased first, because the marker travels through
|
|
34
10
|
* shell snippets and copy-paste, and `Skill_File` is the same channel as `skill_file`.
|
|
35
11
|
*/
|
|
36
|
-
export declare function resolveInstallSource(env?: NodeJS.ProcessEnv
|
|
12
|
+
export declare function resolveInstallSource(env?: NodeJS.ProcessEnv,
|
|
13
|
+
/** Where the machine's remembered channel lives. Omitted, only the environment is read. */
|
|
14
|
+
stateDir?: string): InstallSource;
|
|
15
|
+
export declare const INSTALL_STATE_DIR: string;
|
|
16
|
+
/**
|
|
17
|
+
* Remember a declared channel for the commands that follow, which declare nothing.
|
|
18
|
+
*
|
|
19
|
+
* The one-line installer declares itself on `reticle setup install`, and the next thing that runs
|
|
20
|
+
* is an agent spawning `reticle mcp` with no marker at all, so without this the declaration lived
|
|
21
|
+
* for one process. Write-once (exclusive create): the first channel is the one that brought this
|
|
22
|
+
* machine in, and a later command through a different route must not take that credit.
|
|
23
|
+
*/
|
|
24
|
+
export declare function rememberInstallSource(env?: NodeJS.ProcessEnv, stateDir?: string): void;
|
|
37
25
|
/**
|
|
38
26
|
* The install source declared by the environment, or undefined when nothing declared one.
|
|
39
27
|
*
|
|
@@ -22,6 +22,9 @@
|
|
|
22
22
|
* than none: it is the number distribution decisions get steered on, and a guess and a measurement
|
|
23
23
|
* are indistinguishable once they are in the same column.
|
|
24
24
|
*/
|
|
25
|
+
import { mkdirSync, readFileSync, writeFileSync } from 'node:fs';
|
|
26
|
+
import { homedir } from 'node:os';
|
|
27
|
+
import { join } from 'node:path';
|
|
25
28
|
import { InstallSource } from '@reticlehq/core/telemetry';
|
|
26
29
|
import { findProjectConfig } from '../command/cli/ports/resolve/cli-port.js';
|
|
27
30
|
/** The one marker. Set by a channel on the process that runs the install. */
|
|
@@ -35,9 +38,47 @@ const KNOWN = new Set(Object.values(InstallSource));
|
|
|
35
38
|
* whole contract is built on. Trimmed and lowercased first, because the marker travels through
|
|
36
39
|
* shell snippets and copy-paste, and `Skill_File` is the same channel as `skill_file`.
|
|
37
40
|
*/
|
|
38
|
-
export function resolveInstallSource(env = process.env
|
|
41
|
+
export function resolveInstallSource(env = process.env,
|
|
42
|
+
/** Where the machine's remembered channel lives. Omitted, only the environment is read. */
|
|
43
|
+
stateDir) {
|
|
39
44
|
const declared = (env[INSTALL_SOURCE_ENV] ?? '').trim().toLowerCase();
|
|
40
|
-
|
|
45
|
+
if (KNOWN.has(declared))
|
|
46
|
+
return declared;
|
|
47
|
+
return ((stateDir === undefined ? undefined : machineInstallSource(stateDir)) ?? InstallSource.UNKNOWN);
|
|
48
|
+
}
|
|
49
|
+
/** `~/.reticle/install-source`: the channel that installed the CLI on this machine, written once. */
|
|
50
|
+
const MACHINE_FILE = 'install-source';
|
|
51
|
+
export const INSTALL_STATE_DIR = join(homedir(), '.reticle');
|
|
52
|
+
function machineInstallSource(stateDir) {
|
|
53
|
+
try {
|
|
54
|
+
const recorded = readFileSync(join(stateDir, MACHINE_FILE), 'utf8').trim().toLowerCase();
|
|
55
|
+
return KNOWN.has(recorded) && InstallSource.UNKNOWN !== recorded
|
|
56
|
+
? recorded
|
|
57
|
+
: undefined;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Remember a declared channel for the commands that follow, which declare nothing.
|
|
65
|
+
*
|
|
66
|
+
* The one-line installer declares itself on `reticle setup install`, and the next thing that runs
|
|
67
|
+
* is an agent spawning `reticle mcp` with no marker at all, so without this the declaration lived
|
|
68
|
+
* for one process. Write-once (exclusive create): the first channel is the one that brought this
|
|
69
|
+
* machine in, and a later command through a different route must not take that credit.
|
|
70
|
+
*/
|
|
71
|
+
export function rememberInstallSource(env = process.env, stateDir = INSTALL_STATE_DIR) {
|
|
72
|
+
const declared = declaredInstallSource(env);
|
|
73
|
+
if (declared === undefined)
|
|
74
|
+
return;
|
|
75
|
+
try {
|
|
76
|
+
mkdirSync(stateDir, { recursive: true });
|
|
77
|
+
writeFileSync(join(stateDir, MACHINE_FILE), declared, { encoding: 'utf8', flag: 'wx' });
|
|
78
|
+
}
|
|
79
|
+
catch {
|
|
80
|
+
/* already remembered, or an unwritable home: attribution is never worth a failure */
|
|
81
|
+
}
|
|
41
82
|
}
|
|
42
83
|
/**
|
|
43
84
|
* The install source declared by the environment, or undefined when nothing declared one.
|
|
@@ -70,7 +111,7 @@ export function projectInstallSource(cwd, env = process.env) {
|
|
|
70
111
|
if (KNOWN.has(narrowed))
|
|
71
112
|
return narrowed;
|
|
72
113
|
}
|
|
73
|
-
return resolveInstallSource(env);
|
|
114
|
+
return resolveInstallSource(env, INSTALL_STATE_DIR);
|
|
74
115
|
}
|
|
75
116
|
/**
|
|
76
117
|
* `configWithInstallSource` lives in `@reticlehq/init` — `init` is the only thing that writes
|
|
@@ -1,18 +1,4 @@
|
|
|
1
1
|
export declare function markDaemonStart(now: number): void;
|
|
2
|
-
/**
|
|
3
|
-
* Report one client attaching, BY NAME. Best-effort; a metric must never affect whether a client
|
|
4
|
-
* connects.
|
|
5
|
-
*
|
|
6
|
-
* The name is required in practice, and that is the fix rather than a restriction. `connection.client`
|
|
7
|
-
* was defined and documented and never once populated: the only caller reported from
|
|
8
|
-
* `transport.connect().then(...)`, which resolves when the SSE stream opens — before the client has
|
|
9
|
-
* said who it is. `clientInfo` first exists at `oninitialized`, so the event carried every fact about
|
|
10
|
-
* the connection except the one that makes "which agent client converts best" answerable at all.
|
|
11
|
-
*
|
|
12
|
-
* An unnamed call reports NOTHING. A stream that opens and never completes a handshake is a probe,
|
|
13
|
-
* not a client attaching, and counting it was what put an unattributable row exactly where the name
|
|
14
|
-
* belonged.
|
|
15
|
-
*/
|
|
16
2
|
export declare function reportMcpConnected(client?: string, now?: () => number): void;
|
|
17
3
|
/** Tests only. */
|
|
18
4
|
export declare function resetMcpConnections(): void;
|
|
@@ -33,6 +33,8 @@ export function markDaemonStart(now) {
|
|
|
33
33
|
* not a client attaching, and counting it was what put an unattributable row exactly where the name
|
|
34
34
|
* belonged.
|
|
35
35
|
*/
|
|
36
|
+
/** `connection.client`'s wire cap. */
|
|
37
|
+
const MAX_CLIENT_NAME = 64;
|
|
36
38
|
export function reportMcpConnected(client, now = () => Date.now()) {
|
|
37
39
|
if (client === undefined)
|
|
38
40
|
return;
|
|
@@ -45,7 +47,9 @@ export function reportMcpConnected(client, now = () => Date.now()) {
|
|
|
45
47
|
// A large value on the FIRST connect is the interesting case: Reticle was started and then
|
|
46
48
|
// sat there. On a reconnect it is just how long the daemon has been up.
|
|
47
49
|
daemonAgeMs: daemonStartedAt === undefined ? 0 : Math.max(0, now() - daemonStartedAt),
|
|
48
|
-
client,
|
|
50
|
+
// Capped at the wire limit: the client names itself, and an over-long name would fail the
|
|
51
|
+
// schema and drop the whole event.
|
|
52
|
+
client: client.slice(0, MAX_CLIENT_NAME),
|
|
49
53
|
// WHAT THE AGENT HAD TO LOOK AT. Most clients that attach never call a tool, and that cohort
|
|
50
54
|
// emits nothing at all — an agent that reads the instructions, learns nothing is wired and
|
|
51
55
|
// stops has refused nothing, so `tool_refused` cannot see it either. Read off the same flag
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { type OnboardingStep } from '@reticlehq/core';
|
|
2
|
+
/** Report `step` once per process, and only if this machine + project has never reported it. */
|
|
3
|
+
export declare function reportFirstStep(step: OnboardingStep): void;
|
|
1
4
|
/** A successful page read. The dispatcher calls this after excluding refusals and pauses. */
|
|
2
5
|
export declare function noteOnboardingFirst(toolName: string): void;
|
|
3
6
|
/**
|
|
@@ -36,5 +39,34 @@ export declare function noteFirstVerdict(): void;
|
|
|
36
39
|
* chokepoint — a drive that is refused before its first action drove nothing and says nothing.
|
|
37
40
|
*/
|
|
38
41
|
export declare function noteDriven(): void;
|
|
42
|
+
/**
|
|
43
|
+
* The FIRST_RUN rung "a verdict was produced". Once per machine + project, with how long the call
|
|
44
|
+
* took: it fired on every verdict, so a busy session put hundreds of first-run steps in the funnel.
|
|
45
|
+
*/
|
|
46
|
+
export declare function noteVerdictProduced(elapsedMs: number): void;
|
|
39
47
|
/** Arm again for the next daemon run — the tests' seam, mirroring resetAppInstrumented. */
|
|
40
48
|
export declare function resetOnboardingFirsts(): void;
|
|
49
|
+
/**
|
|
50
|
+
* Has this machine + project EVER crossed this onboarding step?
|
|
51
|
+
*
|
|
52
|
+
* The in-memory flags in `onboarding-firsts.ts` and `app-instrumented.ts` answer "this daemon
|
|
53
|
+
* process", and a daemon restarts many times a day, so every "first" step re-fired on every start.
|
|
54
|
+
* The answer is kept on disk instead, as one empty marker file per step under the state home:
|
|
55
|
+
* `~/.reticle/firsts/<projectId>/<step>`. The exclusive create (`wx`) IS the claim, so two daemons
|
|
56
|
+
* racing for the same first cannot both win, and nothing is ever rewritten in place.
|
|
57
|
+
*
|
|
58
|
+
* Only while telemetry is ENABLED: a disabled emitter has nothing to report and must leave nothing
|
|
59
|
+
* behind on disk.
|
|
60
|
+
*/
|
|
61
|
+
export declare const FirstEver: {
|
|
62
|
+
/** This call claimed it: the true first on this machine + project. */
|
|
63
|
+
readonly FIRST: "first";
|
|
64
|
+
/** Claimed before, by this process or an earlier one. Report nothing. */
|
|
65
|
+
readonly SEEN: "seen";
|
|
66
|
+
/** The state home cannot be written. Report per process, and never claim a first. */
|
|
67
|
+
readonly UNKNOWN: "unknown";
|
|
68
|
+
};
|
|
69
|
+
export type FirstEver = (typeof FirstEver)[keyof typeof FirstEver];
|
|
70
|
+
/** Tests only: a state home and project of the test's own. `undefined` restores the default. */
|
|
71
|
+
export declare function setFirstEverDir(dir: string | undefined, projectId?: string): void;
|
|
72
|
+
export declare function claimFirstEver(step: string, projectId?: string): FirstEver;
|
|
@@ -1,5 +1,9 @@
|
|
|
1
|
-
import { ActionType, OnboardingPhase, OnboardingStepStatus, ReticleTool } from '@reticlehq/core';
|
|
1
|
+
import { ActionType, OnboardingPhase, OnboardingStepStatus, ReticleTool, } from '@reticlehq/core';
|
|
2
|
+
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
3
|
+
import { homedir } from 'node:os';
|
|
4
|
+
import { join } from 'node:path';
|
|
2
5
|
import { reportOnboardingStep } from './onboarding-funnel.js';
|
|
6
|
+
import { getTelemetry, projectFingerprint } from './telemetry.js';
|
|
3
7
|
/**
|
|
4
8
|
* The onboarding steps only the DAEMON can answer, reported once each per run.
|
|
5
9
|
*
|
|
@@ -13,13 +17,25 @@ import { reportOnboardingStep } from './onboarding-funnel.js';
|
|
|
13
17
|
*
|
|
14
18
|
* The flags are module state rather than per-session, because a person who tours in one tab and
|
|
15
19
|
* drives in another has still only crossed each of these once.
|
|
20
|
+
*
|
|
21
|
+
* And once per MACHINE + PROJECT on top of that: the flags only know this process, and a daemon
|
|
22
|
+
* restarts many times a day, so each first re-fired on every start. `claimFirstEver` answers from
|
|
23
|
+
* disk; the true first carries `firstEver: true`, and a home that cannot be written falls back to
|
|
24
|
+
* once per process without the flag.
|
|
16
25
|
*/
|
|
17
|
-
const seen = { look: false, act: false, verdict: false, driven: false };
|
|
26
|
+
const seen = { look: false, act: false, verdict: false, driven: false, verdictProduced: false };
|
|
27
|
+
/** Report `step` once per process, and only if this machine + project has never reported it. */
|
|
28
|
+
export function reportFirstStep(step) {
|
|
29
|
+
const ever = claimFirstEver(step.step);
|
|
30
|
+
if (FirstEver.SEEN === ever)
|
|
31
|
+
return;
|
|
32
|
+
void reportOnboardingStep({ ...step, ...(FirstEver.FIRST === ever ? { firstEver: true } : {}) });
|
|
33
|
+
}
|
|
18
34
|
/** A successful page read. The dispatcher calls this after excluding refusals and pauses. */
|
|
19
35
|
export function noteOnboardingFirst(toolName) {
|
|
20
36
|
if (!seen.look && LOOK_TOOLS.has(toolName)) {
|
|
21
37
|
seen.look = true;
|
|
22
|
-
|
|
38
|
+
reportFirstStep({
|
|
23
39
|
phase: OnboardingPhase.ONBOARD,
|
|
24
40
|
step: 'first_look',
|
|
25
41
|
status: OnboardingStepStatus.COMPLETED,
|
|
@@ -49,7 +65,7 @@ export function noteActed(args) {
|
|
|
49
65
|
if (seen.act)
|
|
50
66
|
return;
|
|
51
67
|
seen.act = true;
|
|
52
|
-
|
|
68
|
+
reportFirstStep({
|
|
53
69
|
phase: OnboardingPhase.ONBOARD,
|
|
54
70
|
step: 'first_act',
|
|
55
71
|
status: OnboardingStepStatus.COMPLETED,
|
|
@@ -65,7 +81,7 @@ export function noteFirstVerdict() {
|
|
|
65
81
|
if (seen.verdict)
|
|
66
82
|
return;
|
|
67
83
|
seen.verdict = true;
|
|
68
|
-
|
|
84
|
+
reportFirstStep({
|
|
69
85
|
phase: OnboardingPhase.ONBOARD,
|
|
70
86
|
step: 'first_verdict',
|
|
71
87
|
status: OnboardingStepStatus.COMPLETED,
|
|
@@ -87,12 +103,27 @@ export function noteDriven() {
|
|
|
87
103
|
if (seen.driven)
|
|
88
104
|
return;
|
|
89
105
|
seen.driven = true;
|
|
90
|
-
|
|
106
|
+
reportFirstStep({
|
|
91
107
|
phase: OnboardingPhase.FIRST_RUN,
|
|
92
108
|
step: 'driven',
|
|
93
109
|
status: OnboardingStepStatus.COMPLETED,
|
|
94
110
|
});
|
|
95
111
|
}
|
|
112
|
+
/**
|
|
113
|
+
* The FIRST_RUN rung "a verdict was produced". Once per machine + project, with how long the call
|
|
114
|
+
* took: it fired on every verdict, so a busy session put hundreds of first-run steps in the funnel.
|
|
115
|
+
*/
|
|
116
|
+
export function noteVerdictProduced(elapsedMs) {
|
|
117
|
+
if (seen.verdictProduced)
|
|
118
|
+
return;
|
|
119
|
+
seen.verdictProduced = true;
|
|
120
|
+
reportFirstStep({
|
|
121
|
+
phase: OnboardingPhase.FIRST_RUN,
|
|
122
|
+
step: 'verdict_produced',
|
|
123
|
+
status: OnboardingStepStatus.COMPLETED,
|
|
124
|
+
elapsedMs: Math.max(0, Math.round(elapsedMs)),
|
|
125
|
+
});
|
|
126
|
+
}
|
|
96
127
|
/** Looking: the tools that read the page without changing it. */
|
|
97
128
|
const LOOK_TOOLS = new Set([
|
|
98
129
|
ReticleTool.SNAPSHOT,
|
|
@@ -106,4 +137,48 @@ export function resetOnboardingFirsts() {
|
|
|
106
137
|
seen.act = false;
|
|
107
138
|
seen.verdict = false;
|
|
108
139
|
seen.driven = false;
|
|
140
|
+
seen.verdictProduced = false;
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Has this machine + project EVER crossed this onboarding step?
|
|
144
|
+
*
|
|
145
|
+
* The in-memory flags in `onboarding-firsts.ts` and `app-instrumented.ts` answer "this daemon
|
|
146
|
+
* process", and a daemon restarts many times a day, so every "first" step re-fired on every start.
|
|
147
|
+
* The answer is kept on disk instead, as one empty marker file per step under the state home:
|
|
148
|
+
* `~/.reticle/firsts/<projectId>/<step>`. The exclusive create (`wx`) IS the claim, so two daemons
|
|
149
|
+
* racing for the same first cannot both win, and nothing is ever rewritten in place.
|
|
150
|
+
*
|
|
151
|
+
* Only while telemetry is ENABLED: a disabled emitter has nothing to report and must leave nothing
|
|
152
|
+
* behind on disk.
|
|
153
|
+
*/
|
|
154
|
+
export const FirstEver = {
|
|
155
|
+
/** This call claimed it: the true first on this machine + project. */
|
|
156
|
+
FIRST: 'first',
|
|
157
|
+
/** Claimed before, by this process or an earlier one. Report nothing. */
|
|
158
|
+
SEEN: 'seen',
|
|
159
|
+
/** The state home cannot be written. Report per process, and never claim a first. */
|
|
160
|
+
UNKNOWN: 'unknown',
|
|
161
|
+
};
|
|
162
|
+
const DEFAULT_DIR = join(homedir(), '.reticle', 'firsts');
|
|
163
|
+
const EEXIST = 'EEXIST';
|
|
164
|
+
let override;
|
|
165
|
+
let cachedProjectId;
|
|
166
|
+
/** Tests only: a state home and project of the test's own. `undefined` restores the default. */
|
|
167
|
+
export function setFirstEverDir(dir, projectId = 'test-project') {
|
|
168
|
+
override = dir === undefined ? undefined : { dir, projectId };
|
|
169
|
+
}
|
|
170
|
+
const currentProjectId = () => (cachedProjectId ??= projectFingerprint(process.cwd()).projectId);
|
|
171
|
+
export function claimFirstEver(step, projectId) {
|
|
172
|
+
if (override === undefined && !getTelemetry().enabled)
|
|
173
|
+
return FirstEver.UNKNOWN;
|
|
174
|
+
try {
|
|
175
|
+
const dir = join(override?.dir ?? DEFAULT_DIR, projectId ?? override?.projectId ?? currentProjectId());
|
|
176
|
+
mkdirSync(dir, { recursive: true });
|
|
177
|
+
writeFileSync(join(dir, step), '', { flag: 'wx' });
|
|
178
|
+
return FirstEver.FIRST;
|
|
179
|
+
}
|
|
180
|
+
catch (error) {
|
|
181
|
+
const code = 'object' === typeof error && null !== error ? error.code : undefined;
|
|
182
|
+
return EEXIST === code ? FirstEver.SEEN : FirstEver.UNKNOWN;
|
|
183
|
+
}
|
|
109
184
|
}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
import { type PlatformLinked } from '../command/cli/cloud-link.js';
|
|
2
|
+
import { type Telemetry } from './telemetry.js';
|
|
3
|
+
export declare function reportPlatformLinked(link: PlatformLinked, telemetry?: Pick<Telemetry, 'emit'>): void;
|
|
4
|
+
/** Report every link this process makes. Installed once, by the entry point. */
|
|
5
|
+
export declare function installPlatformLinkTelemetry(): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `platform_linked`: a project on this machine was bound to a workspace.
|
|
3
|
+
*
|
|
4
|
+
* The join between OSS usage and the platform. The platform holds who is in each workspace; this
|
|
5
|
+
* event, and every event after it from a linked project, carries only the workspace's pseudonymous
|
|
6
|
+
* id. So a person is never named on this side, and the two sides still meet on `workspaceId`.
|
|
7
|
+
*
|
|
8
|
+
* Once per NEW binding: re-running `link` against the project a repo already reports to (rotating a
|
|
9
|
+
* key, an agent retrying) is not a link being created.
|
|
10
|
+
*/
|
|
11
|
+
import { PlatformLinkVia, TelemetryEventKind } from '@reticlehq/core/telemetry';
|
|
12
|
+
import { onPlatformLinked } from '../command/cli/cloud-link.js';
|
|
13
|
+
import { getTelemetry } from './telemetry.js';
|
|
14
|
+
export function reportPlatformLinked(link, telemetry = getTelemetry()) {
|
|
15
|
+
if (link.priorProjectId === link.projectId)
|
|
16
|
+
return;
|
|
17
|
+
try {
|
|
18
|
+
void telemetry.emit(TelemetryEventKind.PLATFORM_LINKED, {
|
|
19
|
+
link: { via: link.via },
|
|
20
|
+
...(link.workspaceId === undefined ? {} : { workspaceId: link.workspaceId }),
|
|
21
|
+
// A CLI command exits straight after; the daemon (a HUD link) sends in-process.
|
|
22
|
+
detach: PlatformLinkVia.HUD !== link.via,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
catch {
|
|
26
|
+
/* a metric never fails a link */
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
/** Report every link this process makes. Installed once, by the entry point. */
|
|
30
|
+
export function installPlatformLinkTelemetry() {
|
|
31
|
+
onPlatformLinked((link) => reportPlatformLinked(link));
|
|
32
|
+
}
|