@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
|
@@ -16,16 +16,23 @@
|
|
|
16
16
|
import { spawn } from 'node:child_process';
|
|
17
17
|
import { randomUUID, createHash } from 'node:crypto';
|
|
18
18
|
import { appendFileSync, readFileSync, writeFileSync, mkdirSync, existsSync, rmSync, } from 'node:fs';
|
|
19
|
-
import { homedir, platform } from 'node:os';
|
|
19
|
+
import { homedir, platform, tmpdir } from 'node:os';
|
|
20
20
|
import { dirname, join } from 'node:path';
|
|
21
|
-
import { TelemetryEventKind, TELEMETRY_EVENT_VERSION, ProjectIdSource, isSessionScoped, } from '@reticlehq/core/telemetry';
|
|
21
|
+
import { TelemetryAccountState, TelemetryEventKind, TELEMETRY_EVENT_VERSION, TelemetryEventSchema, ProjectIdSource, isSessionScoped, } from '@reticlehq/core/telemetry';
|
|
22
22
|
import { ReticleEnv } from '@reticlehq/core';
|
|
23
23
|
import { SERVER_VERSION } from '../command/version/identity/server-version.js';
|
|
24
24
|
const RETICLE_DIR = join(homedir(), '.reticle');
|
|
25
|
-
const
|
|
26
|
-
const
|
|
25
|
+
const ID_FILE_NAME = 'telemetry-id';
|
|
26
|
+
const ID_FILE = join(RETICLE_DIR, ID_FILE_NAME);
|
|
27
|
+
const NOTICE_FILE_NAME = 'telemetry-notice-shown';
|
|
27
28
|
/** Presence of this file = a persistent, machine-wide opt-out (`reticle telemetry disable`). */
|
|
28
|
-
const
|
|
29
|
+
const OPT_OUT_FILE_NAME = 'telemetry-opt-out';
|
|
30
|
+
/**
|
|
31
|
+
* Presence of this file marks the MACHINE as the Reticle team's own: every event carries
|
|
32
|
+
* `internal: true`. The persistent twin of `RETICLE_INTERNAL=1`, for a dev machine where setting a
|
|
33
|
+
* variable in every shell would be forgotten once and pollute the numbers for good.
|
|
34
|
+
*/
|
|
35
|
+
export const INTERNAL_MARKER_FILE = 'telemetry-internal';
|
|
29
36
|
/** Where the full disclosure lives — printed in the first-run notice and `reticle telemetry status`. */
|
|
30
37
|
const POLICY_URL = 'https://github.com/reticlehq/reticle/blob/main/docs/telemetry.md';
|
|
31
38
|
/** PostHog batch-capture endpoint (US cloud). `RETICLE_TELEMETRY_URL` overrides the host (EU/self-host). */
|
|
@@ -91,15 +98,28 @@ const FEEDBACK_RETRY_BACKOFF_MS = 750;
|
|
|
91
98
|
* likely to be dropped, and it fails silently like everything else here.
|
|
92
99
|
*/
|
|
93
100
|
const DETACHED_SEND_TIMEOUT_MS = 15_000;
|
|
94
|
-
|
|
95
|
-
|
|
101
|
+
/**
|
|
102
|
+
* The body never rides in argv: argv is readable by every user on the machine through `ps`, and
|
|
103
|
+
* the body is the whole event. It is handed over in a file only its owner can read, which the child
|
|
104
|
+
* reads and deletes before sending. A file rather than a stdin pipe because the parent is a
|
|
105
|
+
* short-lived CLI that may `process.exit` the moment this returns, and an unflushed pipe write dies
|
|
106
|
+
* with it; a file is on disk before `spawn` is even called.
|
|
107
|
+
*/
|
|
108
|
+
const DETACHED_SEND_SCRIPT = "const fs=require('fs');const f=process.argv[2];let b='';" +
|
|
109
|
+
'try{b=fs.readFileSync(f,"utf8")}catch{}try{fs.unlinkSync(f)}catch{}' +
|
|
110
|
+
"fetch(process.argv[1],{method:'POST',headers:{'content-type':'application/json'}," +
|
|
111
|
+
`body:b,signal:AbortSignal.timeout(${DETACHED_SEND_TIMEOUT_MS})})` +
|
|
96
112
|
'.catch(()=>{}).finally(()=>process.exit(0))';
|
|
113
|
+
/** Owner read/write only: the body file must not be readable by anyone else on the machine. */
|
|
114
|
+
const BODY_FILE_MODE = 0o600;
|
|
97
115
|
/** Env var names — mirror cloud-sync's `RETICLE_*` convention. */
|
|
98
116
|
import { isReticleSourceCheckout } from './dev-repo.js';
|
|
99
117
|
import { projectInstallSource } from './install-source.js';
|
|
100
118
|
import { licenseFacts } from './license-activation.js';
|
|
101
119
|
import { gitFacts } from './git-facts.js';
|
|
102
120
|
import { currentAutomationHint } from './automation-hint.js';
|
|
121
|
+
import { accountEnvelope } from './account-envelope.js';
|
|
122
|
+
import { currentAgentClient, launchMethodOf } from './agent-client.js';
|
|
103
123
|
const Env = {
|
|
104
124
|
DISABLE: ReticleEnv.TELEMETRY, // "0" / "false" / "off" → disabled
|
|
105
125
|
DO_NOT_TRACK: ReticleEnv.DO_NOT_TRACK, // the cross-tool opt-out convention (any truthy value)
|
|
@@ -107,6 +127,7 @@ const Env = {
|
|
|
107
127
|
FILE: 'RETICLE_TELEMETRY_FILE', // record to a local JSONL file and send NOTHING — see the sink note
|
|
108
128
|
KEY: 'RETICLE_TELEMETRY_KEY', // override the PostHog project key
|
|
109
129
|
CI: 'CI', // presence marks a CI environment
|
|
130
|
+
INTERNAL: 'RETICLE_INTERNAL', // "1" marks the run as the Reticle team's own (dogfooding, sweeps)
|
|
110
131
|
VITEST: 'VITEST', // set by vitest — unit tests must never phone home
|
|
111
132
|
};
|
|
112
133
|
const isDisabled = (env, cwd = process.cwd()) => {
|
|
@@ -183,8 +204,9 @@ export const resolveIdentity = (file = ID_FILE) => {
|
|
|
183
204
|
return { anonymousId: id, firstRun: true };
|
|
184
205
|
}
|
|
185
206
|
catch {
|
|
186
|
-
// Can't persist (read-only home, sandbox): still report,
|
|
187
|
-
|
|
207
|
+
// Can't persist (read-only home, sandbox): still report, as a fresh id each process, and SAY so —
|
|
208
|
+
// otherwise every process on that machine reads as a new user.
|
|
209
|
+
return { anonymousId: randomUUID(), firstRun: false, ephemeral: true };
|
|
188
210
|
}
|
|
189
211
|
};
|
|
190
212
|
/**
|
|
@@ -236,12 +258,12 @@ const packageRoot = (cwd) => {
|
|
|
236
258
|
return null;
|
|
237
259
|
};
|
|
238
260
|
/** Print the opt-out notice exactly once per machine (honest disclosure, the OSS-trust bar). */
|
|
239
|
-
const showNoticeOnce = () => {
|
|
261
|
+
const showNoticeOnce = (dir) => {
|
|
240
262
|
try {
|
|
241
|
-
mkdirSync(
|
|
263
|
+
mkdirSync(dir, { recursive: true });
|
|
242
264
|
// Exclusive create IS the "once": it throws when the file is already there, so the check and
|
|
243
265
|
// the write cannot be split by a second process printing the notice too.
|
|
244
|
-
writeFileSync(
|
|
266
|
+
writeFileSync(join(dir, NOTICE_FILE_NAME), '1', { encoding: 'utf8', flag: 'wx' });
|
|
245
267
|
process.stderr.write('reticle: anonymous usage telemetry helps improve reticle — no code, no PII, ' +
|
|
246
268
|
`and your app's data never leaves your machine (${POLICY_URL}). ` +
|
|
247
269
|
'Opt out any time: reticle telemetry disable\n');
|
|
@@ -264,7 +286,7 @@ export const describeTelemetry = (env = process.env, dir = RETICLE_DIR, cwd = pr
|
|
|
264
286
|
if (isDisabled(env, cwd)) {
|
|
265
287
|
return { enabled: false, reason: 'disabled by environment variable', policyUrl: POLICY_URL };
|
|
266
288
|
}
|
|
267
|
-
if (existsSync(join(dir,
|
|
289
|
+
if (existsSync(join(dir, OPT_OUT_FILE_NAME))) {
|
|
268
290
|
return {
|
|
269
291
|
enabled: false,
|
|
270
292
|
reason: 'disabled via `reticle telemetry disable`',
|
|
@@ -279,7 +301,7 @@ export const describeTelemetry = (env = process.env, dir = RETICLE_DIR, cwd = pr
|
|
|
279
301
|
};
|
|
280
302
|
/** Persist (or lift) the machine-wide opt-out — `reticle telemetry disable` / `enable`. */
|
|
281
303
|
export const setTelemetryEnabled = (enabled, dir = RETICLE_DIR) => {
|
|
282
|
-
const optOutFile = join(dir,
|
|
304
|
+
const optOutFile = join(dir, OPT_OUT_FILE_NAME);
|
|
283
305
|
if (enabled) {
|
|
284
306
|
rmSync(optOutFile, { force: true });
|
|
285
307
|
return;
|
|
@@ -296,6 +318,7 @@ const NOOP = { emit: () => Promise.resolve(false), enabled: false, firstRun: fal
|
|
|
296
318
|
* injected so this is testable without a clock or network.
|
|
297
319
|
*/
|
|
298
320
|
export const createTelemetry = (opts) => {
|
|
321
|
+
const reticleDir = opts.reticleDir ?? RETICLE_DIR;
|
|
299
322
|
const env = opts.env ?? process.env;
|
|
300
323
|
const cwd = opts.cwd ?? process.cwd();
|
|
301
324
|
// A source checkout silences metrics but must not silence FEEDBACK — see onlyBlockedBySourceCheckout.
|
|
@@ -303,7 +326,7 @@ export const createTelemetry = (opts) => {
|
|
|
303
326
|
if (isDisabled(env, cwd) && !feedbackOnly)
|
|
304
327
|
return NOOP;
|
|
305
328
|
try {
|
|
306
|
-
if (existsSync(
|
|
329
|
+
if (existsSync(join(reticleDir, OPT_OUT_FILE_NAME)))
|
|
307
330
|
return NOOP; // the persistent `reticle telemetry disable` opt-out
|
|
308
331
|
}
|
|
309
332
|
catch {
|
|
@@ -322,7 +345,14 @@ export const createTelemetry = (opts) => {
|
|
|
322
345
|
const os = platform();
|
|
323
346
|
// Negated so it reads the way people say it: UTC+2 is +120, not -120.
|
|
324
347
|
const tzOffsetMin = -new Date().getTimezoneOffset();
|
|
325
|
-
|
|
348
|
+
// Feedback-only (a source checkout) sends one kind of event, typed by a person: it borrows an
|
|
349
|
+
// existing id but never MINTS one, because minting spends `firstRun` and the machine's real first
|
|
350
|
+
// run would then never report its install.
|
|
351
|
+
const idFile = join(reticleDir, ID_FILE_NAME);
|
|
352
|
+
const { anonymousId, firstRun, ephemeral } = feedbackOnly
|
|
353
|
+
? { anonymousId: readIdFile(idFile) ?? randomUUID(), firstRun: false, ephemeral: undefined }
|
|
354
|
+
: resolveIdentity(idFile);
|
|
355
|
+
const internal = isInternal(env, reticleDir);
|
|
326
356
|
/**
|
|
327
357
|
* One id per PROCESS, minted in memory and never persisted — which is exactly right: a daemon run
|
|
328
358
|
* IS the session, and a restarted daemon is genuinely a new one. Ephemeral by construction, so it
|
|
@@ -336,10 +366,16 @@ export const createTelemetry = (opts) => {
|
|
|
336
366
|
// was unknown for every event that could show whether they got anywhere. Reading it here puts it
|
|
337
367
|
// on all of them, which is the only shape in which the question can be asked.
|
|
338
368
|
const installSource = projectInstallSource(opts.cwd ?? process.cwd());
|
|
339
|
-
|
|
369
|
+
// How this process was launched: a property of the process, so read once. Only the bucket leaves.
|
|
370
|
+
const launch = launchMethodOf(process.argv[1]);
|
|
371
|
+
const home = opts.home ?? homedir();
|
|
372
|
+
if (!feedbackOnly)
|
|
373
|
+
showNoticeOnce(reticleDir);
|
|
340
374
|
const spawnDetached = opts.spawnImpl ??
|
|
341
|
-
((command, args) => {
|
|
342
|
-
|
|
375
|
+
((command, args, input) => {
|
|
376
|
+
const bodyFile = join(tmpdir(), `reticle-telemetry-${randomUUID()}.json`);
|
|
377
|
+
writeFileSync(bodyFile, input, { encoding: 'utf8', mode: BODY_FILE_MODE, flag: 'wx' });
|
|
378
|
+
spawn(command, [...args, bodyFile], { detached: true, stdio: 'ignore' }).unref();
|
|
343
379
|
});
|
|
344
380
|
/**
|
|
345
381
|
* Returns whether the event was actually DELIVERED.
|
|
@@ -372,6 +408,9 @@ export const createTelemetry = (opts) => {
|
|
|
372
408
|
// A SCALAR, so it needs the event build and the wire schema and no `blocks` entry — the same
|
|
373
409
|
// three-place trap `outage` fell into, and `installSource` documents below.
|
|
374
410
|
...(automation !== undefined ? { automation } : {}),
|
|
411
|
+
// Two SCALARS, like `automation`: event build + wire schema, no `blocks` entry.
|
|
412
|
+
...(internal ? { internal: true } : {}),
|
|
413
|
+
...(true === ephemeral ? { idEphemeral: true } : {}),
|
|
375
414
|
os,
|
|
376
415
|
tzOffsetMin,
|
|
377
416
|
projectIdSource,
|
|
@@ -406,13 +445,35 @@ export const createTelemetry = (opts) => {
|
|
|
406
445
|
// the ambient one here would silently ignore it. Identical in production, wrong everywhere the
|
|
407
446
|
// seam is actually used.
|
|
408
447
|
...licenseFacts(eventTs, env),
|
|
448
|
+
// Account, workspace and client: SCALARS on every event, so the event build and the wire
|
|
449
|
+
// schema and no `blocks` entry. Account and client are read per event: a HUD sign-in changes
|
|
450
|
+
// the first mid-session, and the second is whichever agent's call is in flight.
|
|
451
|
+
...accountEnvelope(cwd, env, home),
|
|
452
|
+
...(extra?.workspaceId !== undefined
|
|
453
|
+
? {
|
|
454
|
+
workspaceId: extra.workspaceId,
|
|
455
|
+
linked: true,
|
|
456
|
+
accountState: TelemetryAccountState.LINKED,
|
|
457
|
+
}
|
|
458
|
+
: {}),
|
|
459
|
+
...((client) => (client === undefined ? {} : { client }))(currentAgentClient(env)),
|
|
460
|
+
launch,
|
|
461
|
+
...(extra?.hud !== undefined ? { hud: extra.hud } : {}),
|
|
462
|
+
...(extra?.link !== undefined ? { link: extra.link } : {}),
|
|
463
|
+
...(extra?.harness !== undefined ? { harness: extra.harness } : {}),
|
|
409
464
|
};
|
|
465
|
+
// The wire schema's caps are only real if something applies them. An event that fails is
|
|
466
|
+
// DROPPED, never sent and never repaired: the payload is exactly what the caps exist to stop.
|
|
467
|
+
if (!TelemetryEventSchema.safeParse(event).success) {
|
|
468
|
+
invalidDropped += 1;
|
|
469
|
+
return false;
|
|
470
|
+
}
|
|
410
471
|
// Map the core contract onto PostHog's capture shape: id/name/time move up, the rest are properties.
|
|
411
472
|
// The feedback body is FLATTENED into `feedback_*` properties rather than sent as a nested object:
|
|
412
473
|
// PostHog filters and breakdowns operate on top-level properties, so a nested `feedback.stack`
|
|
413
474
|
// would be invisible to the exact "which stacks report the most bugs" question this exists to
|
|
414
475
|
// answer. One prefix keeps them grouped in the UI without a nested path.
|
|
415
|
-
const { anonymousId: distinctId, event: name, ts, sessionId: eventSessionId, feedback, session, project, verification, versionChange, crash, identity, connection, init, onboarding, bug, refusal, outage, instrumentation, ...rest } = event;
|
|
476
|
+
const { anonymousId: distinctId, event: name, ts, sessionId: eventSessionId, feedback, session, project, verification, versionChange, crash, identity, connection, init, onboarding, bug, refusal, outage, instrumentation, hud, link, harness, ...rest } = event;
|
|
416
477
|
// `$session_id` is PostHog's OWN session property, so sending ours under that name lights up
|
|
417
478
|
// its built-in session views and funnels for free rather than requiring custom HogQL everywhere.
|
|
418
479
|
// `sessionId` rides only on events that happened inside a daemon run. A one-shot CLI command
|
|
@@ -444,6 +505,9 @@ export const createTelemetry = (opts) => {
|
|
|
444
505
|
refusal,
|
|
445
506
|
outage,
|
|
446
507
|
instrumentation,
|
|
508
|
+
hud,
|
|
509
|
+
link,
|
|
510
|
+
harness,
|
|
447
511
|
};
|
|
448
512
|
for (const [prefix, block] of Object.entries(blocks)) {
|
|
449
513
|
for (const [key, value] of Object.entries(block ?? {})) {
|
|
@@ -480,7 +544,7 @@ export const createTelemetry = (opts) => {
|
|
|
480
544
|
}
|
|
481
545
|
try {
|
|
482
546
|
if (true === extra?.detach && opts.fetchImpl === undefined) {
|
|
483
|
-
spawnDetached(process.execPath, ['-e', DETACHED_SEND_SCRIPT, url, body
|
|
547
|
+
spawnDetached(process.execPath, ['-e', DETACHED_SEND_SCRIPT, url], body);
|
|
484
548
|
return false; // handed off, outcome unknowable from here
|
|
485
549
|
}
|
|
486
550
|
// Feedback is slower and retried; everything else keeps the fire-and-forget budget.
|
|
@@ -517,6 +581,23 @@ export const createTelemetry = (opts) => {
|
|
|
517
581
|
};
|
|
518
582
|
return { emit, enabled: true, firstRun };
|
|
519
583
|
};
|
|
584
|
+
/**
|
|
585
|
+
* Events dropped because they failed the wire schema, this process. Local only: the bad payload is
|
|
586
|
+
* the thing that must not leave, so not even a count of it is sent from here.
|
|
587
|
+
*/
|
|
588
|
+
let invalidDropped = 0;
|
|
589
|
+
export const droppedInvalidEvents = () => invalidDropped;
|
|
590
|
+
/** `RETICLE_INTERNAL=1`, or the machine-wide marker file. Unreadable home → not internal. */
|
|
591
|
+
const isInternal = (env, dir) => {
|
|
592
|
+
if ('1' === env[Env.INTERNAL] || 'true' === env[Env.INTERNAL])
|
|
593
|
+
return true;
|
|
594
|
+
try {
|
|
595
|
+
return existsSync(join(dir, INTERNAL_MARKER_FILE));
|
|
596
|
+
}
|
|
597
|
+
catch {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
};
|
|
520
601
|
/**
|
|
521
602
|
* The process-wide emitter. One identity resolution + one opt-out check per process; both the CLI
|
|
522
603
|
* lifecycle (install/invoke/session) and the per-tool hook in `runTool` share it.
|
|
@@ -17,4 +17,6 @@ import { type BrowserBrand, type Verification } from '@reticlehq/core';
|
|
|
17
17
|
* `falseGreenCaught` is the one that matters: the assertion PASSED and Reticle still refused to call
|
|
18
18
|
* it verified. That is the product's thesis reduced to a boolean.
|
|
19
19
|
*/
|
|
20
|
-
export declare function verificationOf(toolName: string, result: Record<string, unknown>, durationMs: number, brand?: BrowserBrand
|
|
20
|
+
export declare function verificationOf(toolName: string, result: Record<string, unknown>, durationMs: number, brand?: BrowserBrand,
|
|
21
|
+
/** The call ran inside a Harness drive's async context (`currentDrivenBy()`), read by the caller. */
|
|
22
|
+
drivenByHarness?: boolean): Verification | undefined;
|
|
@@ -13,7 +13,6 @@
|
|
|
13
13
|
import { CaptureLoss, ReplayStatus, ReticleTool, VerificationDriver, Verified, VerifiedReason, } from '@reticlehq/core';
|
|
14
14
|
import { VERDICT_TOOLS } from '../surface/tools/feedback-tools.js';
|
|
15
15
|
import { getBrowserMode } from './browser-mode.js';
|
|
16
|
-
import { harnessDriving } from './harness-drive.js';
|
|
17
16
|
/**
|
|
18
17
|
* The deciding clause, read off the result `decideVerified` wrote it onto.
|
|
19
18
|
*
|
|
@@ -115,7 +114,9 @@ function passedOf(result, status) {
|
|
|
115
114
|
* `falseGreenCaught` is the one that matters: the assertion PASSED and Reticle still refused to call
|
|
116
115
|
* it verified. That is the product's thesis reduced to a boolean.
|
|
117
116
|
*/
|
|
118
|
-
export function verificationOf(toolName, result, durationMs, brand
|
|
117
|
+
export function verificationOf(toolName, result, durationMs, brand,
|
|
118
|
+
/** The call ran inside a Harness drive's async context (`currentDrivenBy()`), read by the caller. */
|
|
119
|
+
drivenByHarness = false) {
|
|
119
120
|
if (!VERDICT_TOOLS.has(toolName))
|
|
120
121
|
return undefined;
|
|
121
122
|
// A paused session REFUSES the call — nothing driven, nothing asserted. The refusal carries a
|
|
@@ -123,6 +124,11 @@ export function verificationOf(toolName, result, durationMs, brand) {
|
|
|
123
124
|
// here for work that happened.
|
|
124
125
|
if (true === result['paused'])
|
|
125
126
|
return undefined;
|
|
127
|
+
// A wait that stopped at the per-call limit is "not yet", not a verdict: it answers `pass: false`
|
|
128
|
+
// with `resume_ms`, and read here that became `verified: "no"`, so every paused wait was recorded
|
|
129
|
+
// as a red and advanced the feedback-prompt counter (#1119).
|
|
130
|
+
if ('number' === typeof result['resume_ms'])
|
|
131
|
+
return undefined;
|
|
126
132
|
const replay = replayVerdict(toolName, result['status']);
|
|
127
133
|
const verified = 'string' === typeof result['verified'] ? result['verified'] : (replay?.verified ?? undefined);
|
|
128
134
|
// flow_verify reports `status: pass|fail|unverifiable`; assert reports a boolean `pass`. Accept
|
|
@@ -169,7 +175,9 @@ export function verificationOf(toolName, result, durationMs, brand) {
|
|
|
169
175
|
// WHAT was lost, when the reason was that something was. Three owners, three fixes, one bar
|
|
170
176
|
// until now.
|
|
171
177
|
...(uncleanLoss === undefined ? {} : { uncleanLoss }),
|
|
172
|
-
// WHOSE drive this was
|
|
173
|
-
|
|
178
|
+
// WHOSE drive this was, read per call by the caller: a drive runs in the background while the
|
|
179
|
+
// agent keeps calling tools, so a process-wide flag credited the agent's verdicts too. Absent is
|
|
180
|
+
// the ordinary case — the agent called the tool itself.
|
|
181
|
+
...(drivenByHarness ? { driven: VerificationDriver.HARNESS } : {}),
|
|
174
182
|
};
|
|
175
183
|
}
|
package/dist/wire-journal.d.ts
CHANGED
|
@@ -19,7 +19,7 @@ export declare function attachJournal(bridge: Bridge, deps: {
|
|
|
19
19
|
fs: FileSystemPort;
|
|
20
20
|
reticleRoot: string;
|
|
21
21
|
enabled: boolean;
|
|
22
|
-
takeAmbientTape?: () => {
|
|
22
|
+
takeAmbientTape?: (sessionId: string) => {
|
|
23
23
|
steps: readonly TapeStep[];
|
|
24
24
|
startPath?: string;
|
|
25
25
|
} | undefined;
|
|
@@ -31,4 +31,4 @@ export declare function attachJournal(bridge: Bridge, deps: {
|
|
|
31
31
|
author?: () => FlowFile['author'];
|
|
32
32
|
/** What this project is willing to keep — the `retain` block of its `.reticle.json`. */
|
|
33
33
|
retain?: PruneWorkspaceOptions;
|
|
34
|
-
}): void
|
|
34
|
+
}): () => Promise<void>;
|
package/dist/wire-journal.js
CHANGED
|
@@ -8,12 +8,13 @@
|
|
|
8
8
|
* the 1000-line backstop is what asked for the split.
|
|
9
9
|
*/
|
|
10
10
|
import { artifactRootResolver } from './memory/project/artifact-root-resolver.js';
|
|
11
|
+
import { claimedArtifactRoot } from './memory/project/root-claims.js';
|
|
11
12
|
import { servingDirectoryOf } from './portal/session/serving-directory.js';
|
|
12
13
|
import { originOf } from './portal/session/session-manager.js';
|
|
13
14
|
import { Bridge } from './portal/bridge/bridge.js';
|
|
14
15
|
import { FlowStore } from './language/flows/flows.js';
|
|
15
16
|
import { makeJournalAttach } from './memory/journal/attach-journal.js';
|
|
16
|
-
import { makeSessionEnd, recordDriveRun } from './memory/journal/session-end.js';
|
|
17
|
+
import { endLiveSessions, makeSessionEnd, recordDriveRun } from './memory/journal/session-end.js';
|
|
17
18
|
import { attachDriveRunFlush } from './memory/journal/drive-run-flush.js';
|
|
18
19
|
import { AmbientStore } from './memory/journal/ambient-store.js';
|
|
19
20
|
import { ensureWorkspaceGitignore } from './memory/journal/on-disk/workspace-gitignore.js';
|
|
@@ -45,7 +46,11 @@ export function attachJournal(bridge, deps) {
|
|
|
45
46
|
// reached a different account's production dashboard.
|
|
46
47
|
// The origin is passed for the case where the page never stamped a project id: it is the only
|
|
47
48
|
// distinguishing fact left, and without it every such app shares one bucket.
|
|
48
|
-
|
|
49
|
+
// A lease opened by `try`, a chat drive or `verify` carries the root of whoever opened it; the
|
|
50
|
+
// resolver would send a page with no project id to `unmatched/`, which nothing syncs.
|
|
51
|
+
session.artifactRoot =
|
|
52
|
+
claimedArtifactRoot(session.id, session.url) ??
|
|
53
|
+
resolveArtifactRoot(session.projectId, originOf(session.url)).root;
|
|
49
54
|
// The project's config sits beside its `.reticle/`, so the declaration is read from the tab's
|
|
50
55
|
// own project rather than from wherever the daemon was started.
|
|
51
56
|
session.background = readBackgroundTraffic(findProjectConfig(dirname(session.artifactRoot)));
|
|
@@ -66,17 +71,20 @@ export function attachJournal(bridge, deps) {
|
|
|
66
71
|
}
|
|
67
72
|
});
|
|
68
73
|
// Teardown: flush the journal tail to disk + persist what this session learned.
|
|
69
|
-
|
|
74
|
+
const teardown = makeSessionEnd({
|
|
70
75
|
...deps,
|
|
71
76
|
// A drive is saved in the session's own project, where replay will look for it.
|
|
72
77
|
...(deps.flows === undefined
|
|
73
78
|
? {}
|
|
74
|
-
: {
|
|
79
|
+
: {
|
|
80
|
+
flowsAt: (root) => new FlowStore(deps.fs, root, { now: Date.now }, deps.onRunPersisted === undefined ? {} : { onWrote: deps.onRunPersisted }),
|
|
81
|
+
}),
|
|
75
82
|
...(deps.retain === undefined ? {} : { retain: deps.retain }),
|
|
76
83
|
// Retention runs from teardown, and it must not delete the journal of a session that is still
|
|
77
84
|
// being written. The registry is the only thing that knows which those are.
|
|
78
85
|
liveSessionIds: () => new Set(bridge.sessions.all().map((s) => s.id)),
|
|
79
|
-
})
|
|
86
|
+
});
|
|
87
|
+
bridge.attachSessionEnd(teardown);
|
|
80
88
|
/*
|
|
81
89
|
* And the same write, DURING the session rather than only at the end of it.
|
|
82
90
|
*
|
|
@@ -92,6 +100,7 @@ export function attachJournal(bridge, deps) {
|
|
|
92
100
|
if (deps.enabled) {
|
|
93
101
|
attachDriveRunFlush({
|
|
94
102
|
resolve: (sessionId) => bridge.sessions.get(sessionId),
|
|
103
|
+
all: () => bridge.sessions.all(),
|
|
95
104
|
write: (session) => recordDriveRun(deps, session),
|
|
96
105
|
});
|
|
97
106
|
}
|
|
@@ -104,4 +113,6 @@ export function attachJournal(bridge, deps) {
|
|
|
104
113
|
// under which nothing ever deleted what was already there. Visual diffs, feedback copies and run
|
|
105
114
|
// artifacts do not need the journal to be written at all and kept accumulating regardless.
|
|
106
115
|
void pruneWorkspace(deps.fs, deps.reticleRoot, new Set(bridge.sessions.all().map((s) => s.id)), deps.retain ?? {});
|
|
116
|
+
// For a closing daemon: tear down the tabs still open, awaited, before its last sync.
|
|
117
|
+
return () => endLiveSessions(bridge.sessions, teardown);
|
|
107
118
|
}
|
package/docs/README.md
CHANGED
|
@@ -27,7 +27,7 @@ Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `d
|
|
|
27
27
|
| [actions.mdx](actions.mdx) | every action and its arguments, including `press` and its history |
|
|
28
28
|
| [environment.mdx](environment.mdx) | every environment variable Reticle reads, what it changes, and which process reads it |
|
|
29
29
|
| [faq.mdx](faq.mdx) | production, frameworks, comparisons, and the honest limits |
|
|
30
|
-
| [tools/overview.mdx](tools/overview.mdx) | the
|
|
30
|
+
| [tools/overview.mdx](tools/overview.mdx) | the ten advertised tools, the rest reachable on demand, and why |
|
|
31
31
|
| [tools/snapshot.mdx](tools/snapshot.mdx) | `reticle_look { action: "page" }`: three modes, from full tree to a 25-token route check |
|
|
32
32
|
| [tools/query.mdx](tools/query.mdx) | `reticle_look { action: "find" }` finds elements by their reported roles, names and labels |
|
|
33
33
|
| [tools/inspect.mdx](tools/inspect.mdx) | `reticle_look { action: "element" }`: one element, down to source and design tokens |
|
|
@@ -42,7 +42,7 @@ Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `d
|
|
|
42
42
|
| [tools/wait-for.mdx](tools/wait-for.mdx) | `reticle_assert { action: "wait" }`, for consequences you did not cause |
|
|
43
43
|
| [tools/assert.mdx](tools/assert.mdx) | `reticle_assert`: verdicts, and a real failure explained |
|
|
44
44
|
| [tools/sessions.mdx](tools/sessions.mdx) | `reticle_session { action: "list" }`: the health fields that decide if driving works |
|
|
45
|
-
| [tools/tools-and-run.mdx](tools/tools-and-run.mdx) | `reticle_tools` / `reticle_run`, reaching the
|
|
45
|
+
| [tools/tools-and-run.mdx](tools/tools-and-run.mdx) | `reticle_tools` / `reticle_run`, reaching the tools that are not advertised |
|
|
46
46
|
| [tools/session-and-feedback.mdx](tools/session-and-feedback.mdx) | `reticle_session` / `reticle_session { action: "feedback" }`, the human boundary |
|
|
47
47
|
| [packages.mdx](packages.mdx) | every library at a glance: what it does, why it exists, when you need it |
|
|
48
48
|
| [packages/](packages/) | one page per published package, with its real exported API and dependencies |
|
package/docs/actions.mdx
CHANGED
|
@@ -22,8 +22,11 @@ Every action Reticle can perform takes the same shape: a `ref` from [`reticle_lo
|
|
|
22
22
|
| `select` | `{ value }` | For `<select>` |
|
|
23
23
|
| `check` / `uncheck` | none | Checkbox and radio, or a `role="checkbox"`/`role="switch"` element (fails if `aria-checked` does not change) |
|
|
24
24
|
| `submit` | none | Submits the element's `<form>` |
|
|
25
|
-
| `press` | `{ text }` |
|
|
25
|
+
| `press` | `{ text, modifiers?, holdMs?, keys?, code? }` | `text` is the key **name**: `Escape`, `Tab`, `Enter`. `key` is an accepted alias. `modifiers` is an array of `Meta`, `Control`, `Shift`, `Alt`. `holdMs` holds the key down; `keys` holds several together; `code` names the physical key |
|
|
26
26
|
| `scrollIntoView` | none | |
|
|
27
|
+
| `scroll` | `{ dy?, dx?, fraction? }` | Scrolls the nearest scrollable container (or the page, with no `ref`) by `dy`/`dx` pixels, either direction. `fraction` (0 to 1) jumps to that point of the height. No args steps down most of a screen |
|
|
28
|
+
| `tap` | `{ holdMs? }` | A touch tap: pointer and touch events, then `click`. `holdMs` makes it a long press |
|
|
29
|
+
| `zoom` | none | Page zoom. Refused inside the page, because CSS zoom changes how a page looks without changing its layout, and a passing check on it would be false |
|
|
27
30
|
| `upload` | `{ content?, name?, type?, path? }` | Sets a file on `<input type="file">`. Inline bytes default to `"reticle test file"` / `"file.txt"` / `"text/plain"`. `path` reads a file from disk, scoped to the project root plus any opt-in directories listed in `.reticle.json` as `"uploadRoots": ["~/Downloads", "/Volumes/fixtures"]`. A refusal names every allowed root. |
|
|
28
31
|
| `drag` | `{ toRef }` | Pointer-based drag (dnd-kit, react-beautiful-dnd) plus HTML5 DnD. `target` is an alias |
|
|
29
32
|
|
|
@@ -71,7 +74,7 @@ This one has history worth knowing. The implementation used to read `args.key` a
|
|
|
71
74
|
|
|
72
75
|
Three consequences, worst last: the requested key never arrived, so Escape-to-close and Tab-traversal went unverified while looking verified; nothing in the result said the argument had been ignored; and `Enter` is not a neutral substitute. On a focused field inside a form it **submits it**. A request to close a dialog could file the form behind it.
|
|
73
76
|
|
|
74
|
-
|
|
77
|
+
This is often misdiagnosed as "synthetic events don't reach the app". That is the wrong root cause: the event reached the app perfectly well and simply said `Enter`.
|
|
75
78
|
|
|
76
79
|
</Warning>
|
|
77
80
|
|
|
@@ -112,7 +115,7 @@ Several actions in one round trip:
|
|
|
112
115
|
|
|
113
116
|
Fields sitting at their uninformative default are **omitted**, so a clean action collapses to its consequence. A missing `visible` means `true`, not `false`. Read an absence as "nothing to report" rather than as a failure.
|
|
114
117
|
|
|
115
|
-
`occluded` is the answer to
|
|
118
|
+
`occluded` is often the answer to "the button doesn't work": the click landed on the modal overlay sitting on top of it.
|
|
116
119
|
|
|
117
120
|
<Card title="Full field-by-field walkthrough" icon="hand-pointer" href="/tools/act">
|
|
118
121
|
What each effect field tells you, with a real response.
|
package/docs/adapters.md
CHANGED
|
@@ -72,4 +72,4 @@ A **realm adapter** teaches Reticle about a kind of app that is not a browser ta
|
|
|
72
72
|
|
|
73
73
|
If you want to write either, open an issue and say what you are building. The interfaces exist; what is missing is the door.
|
|
74
74
|
|
|
75
|
-
A template for each
|
|
75
|
+
A template for each kind is in [`adapters/CONTRIBUTING.md`](https://github.com/reticlehq/reticle/blob/main/adapters/CONTRIBUTING.md). It also covers a fourth kind, lint (an ordinary ESLint plugin such as `@reticlehq/eslint-plugin`, which needs no registration and so is also contributable today), and carries the rules each kind must hold to, and why each rule exists.
|