@reticlehq/server 2.11.0 → 2.13.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 +93 -111
- package/dist/bridge/auth-failure-reason.d.ts +6 -2
- package/dist/bridge/auth-failure-reason.js +15 -8
- package/dist/bridge/bridge.d.ts +18 -14
- package/dist/bridge/bridge.js +248 -165
- package/dist/bridge/bridge.test-harness.d.ts +2 -0
- package/dist/bridge/bridge.test-harness.js +8 -1
- package/dist/bridge/pairing-token.d.ts +5 -0
- package/dist/bridge/pairing-token.js +28 -0
- package/dist/bridge/protocol-skew.d.ts +37 -0
- package/dist/bridge/protocol-skew.js +45 -0
- package/dist/capsule/capsule-store.d.ts +8 -7
- package/dist/capsule/capsule-store.js +1 -1
- package/dist/capsule/causal-summary.d.ts +2 -2
- package/dist/capsule/causal-summary.js +7 -2
- package/dist/chromium-launch-options.d.ts +28 -0
- package/dist/chromium-launch-options.js +29 -0
- package/dist/cli/cli-doctor.js +39 -1
- package/dist/cli/cli-flow-commands.d.ts +3 -1
- package/dist/cli/cli-flow-commands.js +34 -4
- package/dist/cli/cli-kill.d.ts +2 -1
- package/dist/cli/cli-launch.d.ts +11 -1
- package/dist/cli/cli-launch.js +59 -10
- package/dist/cli/cli-parse.d.ts +17 -1
- package/dist/cli/cli-parse.js +238 -12
- package/dist/cli/cli-update-commands.js +20 -1
- package/dist/cli/cli-verify.d.ts +2 -1
- package/dist/cli/cli-verify.js +5 -4
- package/dist/cli/cloud-cli.js +428 -253
- package/dist/cli/cloud-keystore.d.ts +37 -0
- package/dist/cli/cloud-keystore.js +97 -0
- package/dist/cli/cloud-kit.d.ts +37 -0
- package/dist/cli/cloud-kit.js +121 -0
- package/dist/cli/cloud-login.d.ts +17 -0
- package/dist/cli/cloud-login.js +183 -0
- package/dist/cli/cloud-session.d.ts +48 -0
- package/dist/cli/cloud-session.js +53 -0
- package/dist/cli/config-discovery.d.ts +2 -1
- package/dist/cli/config-discovery.js +1 -0
- package/dist/cli/daemon-start-options.d.ts +32 -0
- package/dist/cli/daemon-start-options.js +38 -0
- package/dist/cli/device-flow.d.ts +76 -0
- package/dist/cli/device-flow.js +56 -0
- package/dist/cli/doctor-rows.d.ts +12 -1
- package/dist/cli/doctor-rows.js +12 -1
- package/dist/cli/drive-attach.d.ts +13 -0
- package/dist/cli/drive-attach.js +18 -0
- package/dist/cli/drive-command.js +7 -3
- package/dist/cli/gate-exit.d.ts +21 -0
- package/dist/cli/gate-exit.js +21 -0
- package/dist/cli/gate-hook-message.d.ts +33 -0
- package/dist/cli/gate-hook-message.js +46 -0
- package/dist/cli/mcp-command.d.ts +25 -0
- package/dist/cli/mcp-command.js +174 -0
- package/dist/cli/project-name.d.ts +30 -0
- package/dist/cli/project-name.js +44 -0
- package/dist/cli/sibling-ports.d.ts +37 -0
- package/dist/cli/sibling-ports.js +56 -0
- package/dist/cli/status-next-action.d.ts +14 -0
- package/dist/cli/status-next-action.js +4 -4
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +167 -186
- package/dist/cloud/cloud-config.d.ts +24 -2
- package/dist/cloud/cloud-config.js +64 -5
- package/dist/cloud/cloud-sync.d.ts +16 -5
- package/dist/cloud/cloud-sync.js +64 -1
- package/dist/cloud/sync-cycle.d.ts +110 -0
- package/dist/cloud/sync-cycle.js +270 -0
- package/dist/cloud/sync-daemon.d.ts +69 -0
- package/dist/cloud/sync-daemon.js +260 -0
- package/dist/cloud/sync-disk.d.ts +9 -0
- package/dist/cloud/sync-disk.js +191 -0
- package/dist/cloud/sync-hash.d.ts +2 -0
- package/dist/cloud/sync-hash.js +35 -0
- package/dist/crawl/crawl-tools.js +5 -3
- package/dist/crawl/crawl.d.ts +12 -13
- package/dist/crawl/crawl.js +25 -3
- package/dist/daemon/daemon-resolve.d.ts +122 -0
- package/dist/daemon/daemon-resolve.js +187 -0
- package/dist/daemon/dev-servers.d.ts +15 -0
- package/dist/daemon/dev-servers.js +68 -0
- package/dist/daemon/free-port.d.ts +29 -0
- package/dist/daemon/free-port.js +55 -0
- package/dist/daemon/heartbeat.d.ts +0 -4
- package/dist/daemon/heartbeat.js +2 -2
- package/dist/daemon/wake-decision.d.ts +32 -0
- package/dist/daemon/wake-decision.js +38 -0
- package/dist/dev/stale-issue-guard.d.ts +0 -2
- package/dist/dev/stale-issue-guard.js +1 -1
- package/dist/domain/domain-tools.js +2 -2
- package/dist/events/contradictions.d.ts +59 -0
- package/dist/events/contradictions.js +253 -27
- package/dist/events/declared.d.ts +17 -0
- package/dist/events/declared.js +43 -1
- package/dist/events/echo-mismatch.js +65 -1
- package/dist/events/event-filters.d.ts +8 -0
- package/dist/events/event-filters.js +19 -2
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +17 -0
- package/dist/events/predicate-asks.d.ts +13 -0
- package/dist/events/predicate-asks.js +22 -0
- package/dist/events/predicate-eval.js +117 -27
- package/dist/events/predicate-parse.d.ts +0 -6
- package/dist/events/predicate-parse.js +43 -3
- package/dist/events/predicate-precheck.d.ts +8 -0
- package/dist/events/predicate-precheck.js +41 -0
- package/dist/events/predicate-route.d.ts +14 -0
- package/dist/events/predicate-route.js +36 -8
- package/dist/events/predicate-schema.d.ts +44 -0
- package/dist/events/predicate-schema.js +126 -23
- package/dist/events/predicate.d.ts +20 -0
- package/dist/events/predicate.js +77 -6
- package/dist/events/split-text-miss.d.ts +30 -0
- package/dist/events/split-text-miss.js +44 -0
- package/dist/flows/coverage.d.ts +0 -8
- package/dist/flows/coverage.js +1 -1
- package/dist/flows/decision.d.ts +5 -1
- package/dist/flows/decision.js +33 -7
- package/dist/flows/flake.d.ts +6 -8
- package/dist/flows/flake.js +1 -1
- package/dist/flows/flow-intent.d.ts +52 -0
- package/dist/flows/flow-intent.js +123 -0
- package/dist/flows/flow-memory-consult.d.ts +55 -0
- package/dist/flows/flow-memory-consult.js +38 -0
- package/dist/flows/flow-replay-run.d.ts +18 -7
- package/dist/flows/flow-replay-run.js +263 -23
- package/dist/flows/flow-replay.js +11 -2
- package/dist/flows/flow-step-runners.d.ts +8 -0
- package/dist/flows/flow-step-runners.js +8 -2
- package/dist/flows/flow-store-for-session.d.ts +31 -0
- package/dist/flows/flow-store-for-session.js +33 -0
- package/dist/flows/flow-success.js +15 -3
- package/dist/flows/flow-tools.js +87 -33
- package/dist/flows/flows.d.ts +14 -1
- package/dist/flows/flows.js +502 -24
- package/dist/flows/heal-run.js +5 -2
- package/dist/flows/predicate-to-expect.d.ts +17 -12
- package/dist/flows/predicate-to-expect.js +36 -15
- package/dist/flows/recordings.d.ts +13 -1
- package/dist/flows/recordings.js +17 -2
- package/dist/flows/replay.d.ts +22 -2
- package/dist/flows/replay.js +28 -2
- package/dist/flows/server-verify.js +16 -2
- package/dist/flows/verify-change-tools.js +9 -3
- package/dist/honesty/blind-spots.d.ts +51 -15
- package/dist/honesty/blind-spots.js +64 -4
- package/dist/honesty/feature-capture.d.ts +150 -0
- package/dist/honesty/feature-capture.js +233 -0
- package/dist/honesty/honesty.d.ts +24 -0
- package/dist/honesty/honesty.js +25 -1
- package/dist/honesty/instrumentation-gaps.d.ts +39 -6
- package/dist/honesty/instrumentation-gaps.js +88 -5
- package/dist/honesty/tool-hit-rate.d.ts +86 -0
- package/dist/honesty/tool-hit-rate.js +90 -0
- package/dist/honesty/undeclared-change.d.ts +51 -0
- package/dist/honesty/undeclared-change.js +56 -0
- package/dist/honesty/verified.d.ts +16 -0
- package/dist/honesty/verified.js +84 -5
- package/dist/http-server.d.ts +0 -1
- package/dist/http-server.js +13 -1
- package/dist/hunt/hunt-report.d.ts +0 -2
- package/dist/hunt/hunt-report.js +1 -1
- package/dist/impact/impact-recorder.d.ts +31 -8
- package/dist/impact/impact-recorder.js +104 -21
- package/dist/impact/impact-store.d.ts +13 -4
- package/dist/impact/impact-store.js +44 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +113 -7
- package/dist/init/agent-rules.d.ts +30 -6
- package/dist/init/agent-rules.js +54 -13
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +28 -0
- package/dist/init/capabilities.d.ts +4 -3
- package/dist/init/capabilities.js +23 -3
- package/dist/init/closing-hint.d.ts +36 -0
- package/dist/init/closing-hint.js +120 -0
- package/dist/init/confirm.d.ts +27 -28
- package/dist/init/confirm.js +51 -11
- package/dist/init/cra.d.ts +34 -5
- package/dist/init/cra.js +96 -25
- package/dist/init/csp-check.js +17 -2
- package/dist/init/csp-doctor.d.ts +8 -1
- package/dist/init/csp-doctor.js +8 -3
- package/dist/init/dev-script.d.ts +50 -0
- package/dist/init/dev-script.js +66 -0
- package/dist/init/format-generated.d.ts +18 -0
- package/dist/init/format-generated.js +39 -0
- package/dist/init/install-hint.d.ts +9 -0
- package/dist/init/install-hint.js +29 -0
- package/dist/init/mcp-clients.d.ts +7 -0
- package/dist/init/mcp-clients.js +7 -0
- package/dist/init/mcp.d.ts +17 -6
- package/dist/init/mcp.js +27 -11
- package/dist/init/node-io.js +11 -1
- package/dist/init/plan-framework.d.ts +0 -5
- package/dist/init/plan-framework.js +147 -37
- package/dist/init/plan.d.ts +30 -37
- package/dist/init/plan.js +50 -60
- package/dist/init/preflight.d.ts +28 -0
- package/dist/init/preflight.js +38 -0
- package/dist/init/refresh-rules.d.ts +39 -0
- package/dist/init/refresh-rules.js +51 -0
- package/dist/init/run.d.ts +32 -35
- package/dist/init/run.js +151 -202
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/snippets.js +90 -31
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +39 -25
- package/dist/init/workspace-apps.d.ts +17 -10
- package/dist/init/workspace-apps.js +110 -0
- package/dist/input/network-mock-tools.js +3 -6
- package/dist/input/real-input.d.ts +2 -0
- package/dist/input/real-input.js +28 -7
- package/dist/input/scroll-find.d.ts +7 -4
- package/dist/input/scroll-find.js +63 -25
- package/dist/input/scroll-tools.js +4 -6
- package/dist/input/viewport-tools.js +5 -4
- package/dist/intent/inline-intent.d.ts +37 -0
- package/dist/intent/inline-intent.js +193 -0
- package/dist/intent/intent-shard-store.d.ts +72 -0
- package/dist/intent/intent-shard-store.js +203 -0
- package/dist/intent/intent-shard.d.ts +411 -0
- package/dist/intent/intent-shard.js +176 -0
- package/dist/intent/intent-store.d.ts +49 -0
- package/dist/intent/intent-store.js +133 -0
- package/dist/intent/intent-subject.d.ts +45 -0
- package/dist/intent/intent-subject.js +177 -0
- package/dist/intent/intent-tools.d.ts +2 -0
- package/dist/intent/intent-tools.js +143 -0
- package/dist/intent/open-intents.d.ts +42 -0
- package/dist/intent/open-intents.js +40 -0
- package/dist/journal/envelope.d.ts +26 -26
- package/dist/journal/journal-recorder.d.ts +23 -0
- package/dist/journal/journal-recorder.js +35 -0
- package/dist/license/license-env.d.ts +29 -0
- package/dist/license/license-env.js +148 -0
- package/dist/loopback-agent.d.ts +31 -0
- package/dist/loopback-agent.js +57 -0
- package/dist/mcp/attach-memory.d.ts +83 -0
- package/dist/mcp/attach-memory.js +185 -0
- package/dist/mcp/client-identity.d.ts +31 -0
- package/dist/mcp/client-identity.js +51 -0
- package/dist/mcp/mcp-post-transport.d.ts +26 -0
- package/dist/mcp/mcp-post-transport.js +109 -0
- package/dist/mcp/mcp-proxy.d.ts +2 -8
- package/dist/mcp/mcp-proxy.js +64 -62
- package/dist/mcp/mcp.d.ts +2 -0
- package/dist/mcp/mcp.js +52 -24
- package/dist/mcp/proxy-backoff.d.ts +11 -0
- package/dist/mcp/proxy-backoff.js +13 -0
- package/dist/mcp/proxy-daemon-probe.d.ts +1 -0
- package/dist/mcp/proxy-daemon-probe.js +7 -1
- package/dist/mcp/proxy-handshake.d.ts +23 -0
- package/dist/mcp/proxy-handshake.js +31 -0
- package/dist/mcp/server-instructions.js +45 -3
- package/dist/mcp/tool-catalog-cache.d.ts +16 -0
- package/dist/mcp/tool-catalog-cache.js +22 -0
- package/dist/memory/memory-tools.d.ts +2 -0
- package/dist/memory/memory-tools.js +82 -0
- package/dist/memory/project-memory.d.ts +34 -0
- package/dist/memory/project-memory.js +96 -0
- package/dist/oracles/flow-instrument-gaps.d.ts +4 -4
- package/dist/oracles/flow-instrument-gaps.js +4 -5
- package/dist/oracles/propose-consequences.js +12 -3
- package/dist/oracles/self-instrument.d.ts +9 -9
- package/dist/oracles/self-instrument.js +19 -13
- package/dist/pool/browser-pool.d.ts +75 -5
- package/dist/pool/browser-pool.js +144 -5
- package/dist/pool/playwright-launcher.js +12 -1
- package/dist/project/fs-port.d.ts +3 -0
- package/dist/project/fs-port.js +3 -2
- package/dist/project/memory-fs.js +6 -1
- package/dist/project/project-tools.js +6 -35
- package/dist/project/reticle-dir.d.ts +17 -2
- package/dist/project/reticle-dir.js +22 -4
- package/dist/runs/context-tools.d.ts +2 -0
- package/dist/runs/context-tools.js +89 -0
- package/dist/runs/run-context.d.ts +40 -0
- package/dist/runs/run-context.js +158 -0
- package/dist/runs/run-diff.d.ts +2 -1
- package/dist/runs/run-store.d.ts +10 -0
- package/dist/runs/run-store.js +10 -0
- package/dist/runs/verification-sync.d.ts +0 -11
- package/dist/runs/verification-sync.js +24 -3
- package/dist/runs/verify-server.d.ts +8 -1
- package/dist/runs/verify-server.js +14 -2
- package/dist/session/command-timeout.d.ts +5 -2
- package/dist/session/command-timeout.js +5 -4
- package/dist/session/dev-server-probe.d.ts +0 -8
- package/dist/session/dev-server-probe.js +1 -1
- package/dist/session/last-act.d.ts +7 -1
- package/dist/session/last-act.js +2 -2
- package/dist/session/lease-visibility.d.ts +67 -0
- package/dist/session/lease-visibility.js +76 -0
- package/dist/session/live-control-tools.js +1 -42
- package/dist/session/no-session-diagnosis.d.ts +33 -0
- package/dist/session/no-session-diagnosis.js +82 -24
- package/dist/session/no-session-next-action.d.ts +12 -0
- package/dist/session/no-session-next-action.js +77 -6
- package/dist/session/no-session-watch.d.ts +18 -6
- package/dist/session/no-session-watch.js +125 -75
- package/dist/session/output-budget.js +4 -1
- package/dist/session/pending-commands.d.ts +11 -1
- package/dist/session/pending-commands.js +12 -2
- package/dist/session/resolve-within.d.ts +34 -0
- package/dist/session/resolve-within.js +53 -0
- package/dist/session/session-health.d.ts +9 -0
- package/dist/session/session-health.js +23 -0
- package/dist/session/session-info.d.ts +18 -0
- package/dist/session/session-info.js +11 -0
- package/dist/session/session-manager.d.ts +14 -0
- package/dist/session/session-manager.js +111 -4
- package/dist/session/session-mirror.d.ts +16 -0
- package/dist/session/session-mirror.js +22 -0
- package/dist/session/session-recommendation.d.ts +19 -5
- package/dist/session/session-recommendation.js +25 -9
- package/dist/session/session-successor.d.ts +37 -0
- package/dist/session/session-successor.js +113 -0
- package/dist/session/session-tools.js +2 -2
- package/dist/session/session.d.ts +53 -3
- package/dist/session/session.js +162 -9
- package/dist/session/wall-clock.d.ts +12 -0
- package/dist/session/wall-clock.js +14 -0
- package/dist/setup/agent-configs.d.ts +96 -0
- package/dist/setup/agent-configs.js +333 -0
- package/dist/setup/agent-io.d.ts +9 -0
- package/dist/setup/agent-io.js +16 -0
- package/dist/setup/agent-writer.d.ts +51 -0
- package/dist/setup/agent-writer.js +115 -0
- package/dist/setup/approval-migration.d.ts +47 -0
- package/dist/setup/approval-migration.js +68 -0
- package/dist/setup/auto-approve.d.ts +85 -0
- package/dist/setup/auto-approve.js +150 -0
- package/dist/setup/bridge-port.d.ts +15 -0
- package/dist/setup/bridge-port.js +24 -0
- package/dist/setup/desktop-shape.d.ts +57 -0
- package/dist/setup/desktop-shape.js +63 -0
- package/dist/setup/dev-server-wait.d.ts +60 -0
- package/dist/setup/dev-server-wait.js +65 -0
- package/dist/setup/drive-agent.d.ts +71 -0
- package/dist/setup/drive-agent.js +171 -0
- package/dist/setup/drive-plan.d.ts +68 -0
- package/dist/setup/drive-plan.js +130 -0
- package/dist/setup/ensure-daemon.d.ts +29 -0
- package/dist/setup/ensure-daemon.js +58 -0
- package/dist/setup/init-runtime.d.ts +47 -0
- package/dist/setup/init-runtime.js +160 -0
- package/dist/setup/interrupt.d.ts +25 -0
- package/dist/setup/interrupt.js +40 -0
- package/dist/setup/license-key.d.ts +39 -0
- package/dist/setup/license-key.js +72 -0
- package/dist/setup/listeners.d.ts +37 -0
- package/dist/setup/listeners.js +85 -0
- package/dist/setup/node-effects.d.ts +60 -0
- package/dist/setup/node-effects.js +210 -0
- package/dist/setup/page-probe.d.ts +39 -0
- package/dist/setup/page-probe.js +49 -0
- package/dist/setup/relaunch.d.ts +36 -0
- package/dist/setup/relaunch.js +57 -0
- package/dist/setup/remaining-steps.d.ts +19 -0
- package/dist/setup/remaining-steps.js +31 -0
- package/dist/setup/run-setup.d.ts +99 -0
- package/dist/setup/run-setup.js +187 -0
- package/dist/setup/session-pick.d.ts +47 -0
- package/dist/setup/session-pick.js +51 -0
- package/dist/setup/setup-command.d.ts +45 -0
- package/dist/setup/setup-command.js +199 -0
- package/dist/setup/setup-options.d.ts +74 -0
- package/dist/setup/setup-options.js +67 -0
- package/dist/setup/transcripts.d.ts +16 -0
- package/dist/setup/transcripts.js +43 -0
- package/dist/status-payload.d.ts +14 -1
- package/dist/status-payload.js +23 -1
- package/dist/telemetry/automation-hint.d.ts +2 -1
- package/dist/telemetry/daemon-telemetry.d.ts +8 -1
- package/dist/telemetry/daemon-telemetry.js +52 -5
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +9 -1
- package/dist/telemetry/feedback-context.js +60 -29
- package/dist/telemetry/feedback-local.d.ts +15 -0
- package/dist/telemetry/feedback-local.js +56 -0
- package/dist/telemetry/feedback-outbox.d.ts +2 -1
- package/dist/telemetry/feedback.d.ts +11 -0
- package/dist/telemetry/feedback.js +19 -6
- package/dist/telemetry/init-telemetry.d.ts +2 -0
- package/dist/telemetry/init-telemetry.js +2 -0
- package/dist/telemetry/install-source.d.ts +14 -0
- package/dist/telemetry/install-source.js +30 -0
- package/dist/telemetry/license-activation.d.ts +7 -1
- package/dist/telemetry/license-activation.js +9 -5
- package/dist/telemetry/mcp-connection.js +7 -0
- package/dist/telemetry/project-profile.d.ts +12 -9
- package/dist/telemetry/project-profile.js +12 -7
- package/dist/telemetry/proxy-telemetry.d.ts +3 -0
- package/dist/telemetry/proxy-telemetry.js +21 -0
- package/dist/telemetry/run-telemetry.d.ts +0 -2
- package/dist/telemetry/run-telemetry.js +1 -1
- package/dist/telemetry/session-metrics.d.ts +12 -0
- package/dist/telemetry/session-metrics.js +35 -1
- package/dist/telemetry/telemetry.js +17 -2
- package/dist/telemetry/tool-refused.d.ts +3 -1
- package/dist/telemetry/tool-refused.js +34 -2
- package/dist/telemetry/verification-of.js +2 -2
- package/dist/tools/act-capsule.d.ts +10 -0
- package/dist/tools/act-capsule.js +8 -2
- package/dist/tools/act-danger.d.ts +2 -1
- package/dist/tools/act-danger.js +11 -3
- package/dist/tools/act-observation.d.ts +41 -0
- package/dist/tools/act-observation.js +36 -0
- package/dist/tools/act-preflight.d.ts +20 -0
- package/dist/tools/act-preflight.js +98 -0
- package/dist/tools/act-sequence-retry.d.ts +45 -0
- package/dist/tools/act-sequence-retry.js +58 -0
- package/dist/tools/act-sequence-tool.d.ts +13 -0
- package/dist/tools/act-sequence-tool.js +135 -0
- package/dist/tools/act-target.d.ts +14 -0
- package/dist/tools/act-target.js +47 -0
- package/dist/tools/act-tools.d.ts +21 -1
- package/dist/tools/act-tools.js +196 -204
- package/dist/tools/assert-source.d.ts +22 -0
- package/dist/tools/assert-source.js +53 -0
- package/dist/tools/assert-verdict.d.ts +20 -3
- package/dist/tools/assert-verdict.js +58 -20
- package/dist/tools/browser-tools.js +6 -22
- package/dist/tools/complete-snapshot.d.ts +48 -0
- package/dist/tools/complete-snapshot.js +75 -0
- package/dist/tools/coverage-tools.d.ts +10 -1
- package/dist/tools/coverage-tools.js +123 -69
- package/dist/tools/dynamic-tools.js +53 -13
- package/dist/tools/error-recovery.d.ts +25 -14
- package/dist/tools/error-recovery.js +78 -9
- package/dist/tools/feedback-tools.d.ts +1 -1
- package/dist/tools/feedback-tools.js +2 -2
- package/dist/tools/invoke-tool.js +121 -11
- package/dist/tools/lease-hint.d.ts +10 -0
- package/dist/tools/lease-hint.js +53 -4
- package/dist/tools/lease-tools.d.ts +35 -5
- package/dist/tools/lease-tools.js +191 -13
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +22 -0
- package/dist/tools/navigate-arrival.d.ts +0 -2
- package/dist/tools/navigate-arrival.js +1 -1
- package/dist/tools/numeric-bounds.d.ts +100 -0
- package/dist/tools/numeric-bounds.js +125 -0
- package/dist/tools/observe-tools.js +109 -65
- package/dist/tools/read-tools.js +31 -8
- package/dist/tools/real-input-attempt.d.ts +32 -0
- package/dist/tools/real-input-attempt.js +212 -2
- package/dist/tools/reconcile-tools.js +22 -8
- package/dist/tools/resolve-target.d.ts +0 -7
- package/dist/tools/sdk-marker-probe.d.ts +29 -0
- package/dist/tools/sdk-marker-probe.js +57 -0
- package/dist/tools/snapshot-delta.d.ts +1 -1
- package/dist/tools/tool-kit.d.ts +24 -0
- package/dist/tools/tool-kit.js +21 -0
- package/dist/tools/tool-names.d.ts +5 -0
- package/dist/tools/tool-names.js +5 -0
- package/dist/tools/tool-surface.d.ts +85 -6
- package/dist/tools/tool-surface.js +122 -2
- package/dist/tools/tools-helpers.d.ts +19 -0
- package/dist/tools/tools-helpers.js +46 -0
- package/dist/tools/tools.d.ts +2 -0
- package/dist/tools/tools.js +78 -12
- package/dist/tools/unadvertised-help.js +4 -4
- package/dist/tools/verify-next-baton.d.ts +53 -0
- package/dist/tools/verify-next-baton.js +52 -0
- package/dist/update/reticle-deps.d.ts +9 -0
- package/dist/update/reticle-deps.js +27 -0
- package/dist/update/sdk-sync.d.ts +1 -2
- package/dist/update/sdk-sync.js +1 -21
- package/dist/update/update-nudge.d.ts +25 -10
- package/dist/update/update-nudge.js +32 -3
- package/dist/update/updater.d.ts +1 -1
- package/dist/version/peer-announce.js +4 -2
- package/dist/version/sdk-fix.d.ts +47 -0
- package/dist/version/sdk-fix.js +127 -0
- package/dist/version/version-nudge.d.ts +14 -0
- package/dist/version/version-nudge.js +21 -0
- package/dist/version/version-skew.d.ts +38 -3
- package/dist/version/version-skew.js +83 -7
- package/dist/visual/visual-store.d.ts +6 -6
- package/dist/visual/visual-store.js +18 -16
- package/dist/visual/visual-tools.js +57 -12
- package/docs/README.md +2 -1
- package/docs/cli/cloud.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -0
- package/docs/cli/serve.mdx +4 -2
- package/docs/cli/verify.mdx +4 -5
- package/docs/cli.mdx +7 -3
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +2 -2
- package/docs/gates.md +1 -1
- package/docs/getting-started.md +19 -3
- package/docs/index.mdx +9 -6
- package/docs/install-agentic.mdx +38 -12
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/browser.mdx +2 -2
- package/docs/packages/server.mdx +1 -1
- package/docs/packages.mdx +8 -6
- package/docs/platform-integration.md +17 -0
- package/docs/predicates.mdx +8 -0
- package/docs/reticle-manual.md +106 -0
- package/docs/skill-file.mdx +3 -3
- package/docs/telemetry-contract.md +108 -4
- package/docs/tools-act-sequence.mdx +16 -0
- package/docs/tools-tools-and-run.mdx +2 -4
- package/docs/troubleshooting.mdx +9 -0
- package/docs/usage.md +4 -3
- package/package.json +4 -3
- package/dist/init/cursor.d.ts +0 -24
- package/dist/init/cursor.js +0 -80
- package/dist/session/session-readiness.d.ts +0 -34
- package/dist/session/session-readiness.js +0 -36
|
@@ -3,15 +3,17 @@
|
|
|
3
3
|
* Split out of `plan.ts` — that file is the plan's SHAPE (statuses, ordering, the agent/MCP steps),
|
|
4
4
|
* this one is the per-framework detail, and they grow for different reasons.
|
|
5
5
|
*/
|
|
6
|
+
import { bridgeWsUrl } from '@reticlehq/core';
|
|
6
7
|
import { patchViteConfig, VitePatchKind } from './vite-config.js';
|
|
7
8
|
import { patchNextConfig, patchRootLayout, patchPagesApp } from './next-patch.js';
|
|
8
|
-
import { patchAstroConfig, patchAstroLayout } from './astro-patch.js';
|
|
9
|
-
import { CRA_DEV_MODULE_IMPORT,
|
|
9
|
+
import { ASTRO_ENV_DTS_PATH, patchAstroConfig, patchAstroEnvDts, patchAstroLayout, } from './astro-patch.js';
|
|
10
|
+
import { CRA_DEV_MODULE_IMPORT, CRA_ENV_PATH, CRA_TOKEN_PER_MACHINE_NOTICE, TOKEN_VAR, craDevModuleFile, craDevModulePath, craEnvPatch, craImportPatch, } from './cra.js';
|
|
10
11
|
import { PatchKind } from './patch-kind.js';
|
|
11
12
|
import { viteManual, NEXT_LAYOUT_MANUAL, NEXT_LAYOUT_PATH, viteDevModuleFile, VITE_DEV_MODULE_PATH, nextReticleDevFile, NEXT_RETICLE_DEV_PATH, nextConfigManual, svelteKitHooksFile, SVELTEKIT_HOOKS_PATH, UNVERIFIED_FRAMEWORK_NOTE, astroManual, nuxtManual, NUXT_PLUGIN_PATH, } from './snippets.js';
|
|
12
|
-
import {
|
|
13
|
+
import { StepStatus } from './plan.js';
|
|
13
14
|
import { RETICLE_DEFAULT_PORT } from '@reticlehq/core';
|
|
14
|
-
import { CSP_STEP_TITLE
|
|
15
|
+
import { CSP_STEP_TITLE } from './csp-check.js';
|
|
16
|
+
import { diagnoseWebCsp } from './csp-doctor.js';
|
|
15
17
|
/** What adding `reticle()` to a Vite config buys, which differs by framework. */
|
|
16
18
|
export const VITE_PLUGIN_DETAIL = {
|
|
17
19
|
/** A plain Vite app gets both halves from the plugin. */
|
|
@@ -40,20 +42,13 @@ const CAPABILITIES_TITLE = 'Capabilities + store';
|
|
|
40
42
|
*/
|
|
41
43
|
const CAPABILITIES_TODO_TITLE = 'AGENT: finish the capabilities file';
|
|
42
44
|
function capabilitiesTodo(path, stores) {
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
`${stores.join('; ')}.`
|
|
47
|
-
: `No state library was detected. If the app holds state somewhere init cannot see, register ` +
|
|
48
|
-
`it — see node_modules/@reticlehq/server/docs/usage.md.`;
|
|
49
|
-
return (`${path} was written but registers nothing, so \`hasCapabilities\` stays false and reticle_state ` +
|
|
50
|
-
`has nothing to read.\n` +
|
|
45
|
+
return (`This app's state lives in a library nothing in the running app points at, so it is the one ` +
|
|
46
|
+
`thing Reticle cannot find for itself — reticle_state will not see it until you say where it ` +
|
|
47
|
+
`is.\n` +
|
|
51
48
|
`Do this now, before driving anything:\n` +
|
|
52
|
-
` 1. ${
|
|
53
|
-
` 2.
|
|
54
|
-
`
|
|
55
|
-
` 3. Prove it: drive one flow and check reticle_state returns your keys. An empty state read ` +
|
|
56
|
-
`means this file is still not doing anything, whatever else went green.`);
|
|
49
|
+
` 1. In ${path}, uncomment the suggested line and complete it: ${stores.join('; ')}.\n` +
|
|
50
|
+
` 2. Prove it: drive one flow and check reticle_state returns your key. An empty state read ` +
|
|
51
|
+
`means the line is still not doing anything, whatever else went green.`);
|
|
57
52
|
}
|
|
58
53
|
/**
|
|
59
54
|
* The dev module carrying `registerCapabilities` / `registerStore`.
|
|
@@ -62,6 +57,28 @@ function capabilitiesTodo(path, stores) {
|
|
|
62
57
|
* `__reticle_renders` — the state-truth read was unavailable on every app out of the box. Written
|
|
63
58
|
* only when absent, because it is the one generated file a user is expected to EDIT.
|
|
64
59
|
*/
|
|
60
|
+
/**
|
|
61
|
+
* Is there state left that ONLY the app can hand over?
|
|
62
|
+
*
|
|
63
|
+
* This used to ask a much bigger question — "does the generated file register anything at all?" —
|
|
64
|
+
* and fired on almost every install, because almost every install generated a file whose testids
|
|
65
|
+
* and stores were both empty. The answer was homework: go read the source, uncomment a line, add
|
|
66
|
+
* data-testid attributes, then drive to prove it. Several turns, on every onboarding.
|
|
67
|
+
*
|
|
68
|
+
* Two of those three are no longer anyone's homework. Testids are read from the live DOM, and a
|
|
69
|
+
* store passed through a React context provider (Redux, TanStack Query) is discovered and
|
|
70
|
+
* registered on the first commit. What is left is the genuinely unreachable case: a module-scope
|
|
71
|
+
* store, or one needing an argument only the source supplies — Zustand, Jotai atoms, an XState
|
|
72
|
+
* actor. Nothing in the running app points at those, so the notice still has to fire, and it now
|
|
73
|
+
* fires ONLY there.
|
|
74
|
+
*
|
|
75
|
+
* `wired` are stores init resolved and wrote a live `registerStore` call for. Hints are not
|
|
76
|
+
* registrations: they land in the file as a commented line, and counting one as a registration
|
|
77
|
+
* silences the notice whose whole purpose is to say "act on the hint".
|
|
78
|
+
*/
|
|
79
|
+
function needsManualStore(hints, wired) {
|
|
80
|
+
return hints.length > 0 && 0 === wired.length;
|
|
81
|
+
}
|
|
65
82
|
function capabilitiesStep(input) {
|
|
66
83
|
if (true === input.viteDevModuleExists) {
|
|
67
84
|
return [
|
|
@@ -76,11 +93,26 @@ function capabilitiesStep(input) {
|
|
|
76
93
|
const testids = input.testids ?? [];
|
|
77
94
|
const stores = input.storeHints ?? [];
|
|
78
95
|
const wired = input.foundStores ?? [];
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
//
|
|
83
|
-
const
|
|
96
|
+
// Testids no longer need counting here. They are read from the live DOM at announce time, so a
|
|
97
|
+
// number printed at install time would be a stale claim about a codebase that is about to change —
|
|
98
|
+
// which is exactly what "no data-testid values yet" used to be on an app whose testids arrive with
|
|
99
|
+
// a lazy route.
|
|
100
|
+
const found = 'testids read from the live DOM';
|
|
101
|
+
// A store we found and WIRED is a registration, so the notice must not fire. A store HINT is not:
|
|
102
|
+
// `stores` holds suggestions, written into the file as a commented line of the form
|
|
103
|
+
// `// import your store, then: registerStore(...)`. Counting a suggestion as a registration let
|
|
104
|
+
// the hint silence the notice whose entire job is to say "act on the hint".
|
|
105
|
+
//
|
|
106
|
+
// Measured against a real product UI (rowy — 70+ deps, jotai, a whole src/atoms tree): init
|
|
107
|
+
// detected jotai, offered one commented line, emitted NO notice, and wrote
|
|
108
|
+
// `registerCapabilities({ testids: [], signals: [], stores: [] })`. So `hasCapabilities` stayed
|
|
109
|
+
// false, `reticle_state` was empty forever, and the install gate reported "connected: 1,
|
|
110
|
+
// manual ⚠: none". Every check green, state observability zero.
|
|
111
|
+
//
|
|
112
|
+
// jotai is still exactly that case. A Redux or TanStack app is not, any more: its store rides a
|
|
113
|
+
// context provider and the React adapter registers it on the first commit, so `storeHints` no
|
|
114
|
+
// longer names either one and this notice no longer fires for them.
|
|
115
|
+
const nothingToRegister = needsManualStore(stores, wired);
|
|
84
116
|
return [
|
|
85
117
|
{
|
|
86
118
|
title: CAPABILITIES_TITLE,
|
|
@@ -135,7 +167,7 @@ function viteConfigSteps(input, detail) {
|
|
|
135
167
|
},
|
|
136
168
|
];
|
|
137
169
|
}
|
|
138
|
-
const patch = patchViteConfig(cfg.source, port);
|
|
170
|
+
const patch = patchViteConfig(cfg.source, port, true === input.captureBodies);
|
|
139
171
|
if (patch.kind === VitePatchKind.ALREADY) {
|
|
140
172
|
return [
|
|
141
173
|
{
|
|
@@ -197,16 +229,44 @@ function patchStep(title, path, patch, applyDetail, manualDetail) {
|
|
|
197
229
|
* skipped, so a Next user's app booted, connected to nothing, and said nothing about why. Both are
|
|
198
230
|
* now patched by the same conservative rules the Vite config gets.
|
|
199
231
|
*/
|
|
232
|
+
/** The env var withReticle sets from the discovered daemon, and the component must read. */
|
|
233
|
+
const NEXT_DAEMON_URL_ENV = 'NEXT_PUBLIC_RETICLE_URL';
|
|
234
|
+
/**
|
|
235
|
+
* The two-line edit that unfreezes an existing install's port.
|
|
236
|
+
*
|
|
237
|
+
* Stated as the edit rather than as a problem, because the reader is an agent that can apply it in
|
|
238
|
+
* one write and is otherwise going to ask what to do.
|
|
239
|
+
*/
|
|
240
|
+
const NEXT_DEV_FILE_STALE_DETAIL = 'predates daemon discovery, so it dials the port init saw when it ran. In this file add ' +
|
|
241
|
+
'`const url = process.env.NEXT_PUBLIC_RETICLE_URL;` and spread `...(url ? { url } : {})` into ' +
|
|
242
|
+
'reticle.connect(), after any url already there. Nothing else needs to change.';
|
|
200
243
|
export function nextSteps(input) {
|
|
201
244
|
const configFile = input.nextConfigFile ?? 'next.config.mjs';
|
|
202
245
|
const devPath = input.nextReticleDevPath ?? NEXT_RETICLE_DEV_PATH;
|
|
246
|
+
// An install that predates daemon discovery has a component that never reads the discovered URL,
|
|
247
|
+
// so it keeps dialling whatever port `init` saw on the day it ran. Re-running `init` used to call
|
|
248
|
+
// that "file exists" and move on, which is why the defect survives an upgrade. Named as work.
|
|
249
|
+
//
|
|
250
|
+
// Never overwritten: this file is the one an app owner edits — registered stores, capabilities,
|
|
251
|
+
// their own signals. Rewriting it to fix two lines would take the rest with it. Undefined source
|
|
252
|
+
// means it was not read, and an unread file stays ALREADY rather than becoming invented work.
|
|
253
|
+
const devStale = true === input.nextReticleDevExists &&
|
|
254
|
+
'string' === typeof input.nextReticleDevSource &&
|
|
255
|
+
!input.nextReticleDevSource.includes(NEXT_DAEMON_URL_ENV);
|
|
203
256
|
const devFile = input.nextReticleDevExists
|
|
204
|
-
?
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
257
|
+
? devStale
|
|
258
|
+
? {
|
|
259
|
+
title: 'ReticleDev component',
|
|
260
|
+
target: devPath,
|
|
261
|
+
status: StepStatus.MANUAL,
|
|
262
|
+
detail: NEXT_DEV_FILE_STALE_DETAIL,
|
|
263
|
+
}
|
|
264
|
+
: {
|
|
265
|
+
title: 'ReticleDev component',
|
|
266
|
+
target: devPath,
|
|
267
|
+
status: StepStatus.ALREADY,
|
|
268
|
+
detail: 'file exists',
|
|
269
|
+
}
|
|
210
270
|
: {
|
|
211
271
|
title: 'ReticleDev component',
|
|
212
272
|
target: devPath,
|
|
@@ -233,8 +293,22 @@ export function nextSteps(input) {
|
|
|
233
293
|
: isPagesRouter
|
|
234
294
|
? patchPagesApp(layout.source, input.nextReticleDevImport)
|
|
235
295
|
: patchRootLayout(layout.source);
|
|
296
|
+
// The same question the Vite path asks. Skipped when the module already exists: its contents are
|
|
297
|
+
// the user's, and re-nagging about a file we did not write is noise.
|
|
298
|
+
const nextTodo = true !== input.nextReticleDevExists &&
|
|
299
|
+
needsManualStore(input.storeHints ?? [], input.nextFoundStores ?? [])
|
|
300
|
+
? [
|
|
301
|
+
{
|
|
302
|
+
title: CAPABILITIES_TODO_TITLE,
|
|
303
|
+
target: devPath,
|
|
304
|
+
status: StepStatus.NOTICE,
|
|
305
|
+
detail: capabilitiesTodo(devPath, input.storeHints ?? []),
|
|
306
|
+
},
|
|
307
|
+
]
|
|
308
|
+
: [];
|
|
236
309
|
return [
|
|
237
310
|
devFile,
|
|
311
|
+
...nextTodo,
|
|
238
312
|
patchStep('Next config (withReticle)', configFile, configPatch, 'wrap the export in withReticle (source mapping, dev-only)', nextConfigManual(configFile)),
|
|
239
313
|
patchStep('Mount ReticleDev', layout?.path ?? NEXT_LAYOUT_PATH, layoutPatch, 'mount <ReticleDev /> in the root layout (dev-only)', NEXT_LAYOUT_MANUAL),
|
|
240
314
|
];
|
|
@@ -255,21 +329,27 @@ export function nextSteps(input) {
|
|
|
255
329
|
*/
|
|
256
330
|
export function craSteps(input) {
|
|
257
331
|
const entry = input.craEntry ?? null;
|
|
332
|
+
// Match the project language the same way Next does (#675): a JS CRA app cannot resolve `.ts`.
|
|
333
|
+
const modulePath = craDevModulePath(input.detection.typescript);
|
|
258
334
|
const steps = [
|
|
259
335
|
{
|
|
260
336
|
title: 'Reticle connect module',
|
|
261
|
-
target:
|
|
337
|
+
target: modulePath,
|
|
262
338
|
status: StepStatus.APPLY,
|
|
263
339
|
detail: 'create the dev-only connect (CRA cannot inject through public/index.html)',
|
|
264
340
|
write: {
|
|
265
|
-
path:
|
|
266
|
-
content: craDevModuleFile(input.options.port, input.options.projectId
|
|
341
|
+
path: modulePath,
|
|
342
|
+
content: craDevModuleFile(input.options.port, input.options.projectId, {
|
|
343
|
+
typescript: input.detection.typescript,
|
|
344
|
+
}),
|
|
267
345
|
},
|
|
268
346
|
dependsOnInstall: true,
|
|
269
347
|
},
|
|
270
348
|
];
|
|
271
349
|
const token = input.pairingToken ?? '';
|
|
272
|
-
|
|
350
|
+
// The daemon that is live NOW, not the one baked into the module at first install. CRA has no
|
|
351
|
+
// build hook, so this is refreshed by re-running `init` rather than by starting the dev server.
|
|
352
|
+
const env = craEnvPatch(input.craEnv ?? null, token, input.options.port === undefined ? undefined : bridgeWsUrl(input.options.port));
|
|
273
353
|
if (env !== null) {
|
|
274
354
|
steps.push({
|
|
275
355
|
title: 'Pairing token',
|
|
@@ -426,9 +506,14 @@ export function astroSteps(input) {
|
|
|
426
506
|
},
|
|
427
507
|
];
|
|
428
508
|
}
|
|
509
|
+
const envPatch = patchAstroEnvDts(input.astroEnvDts ?? null);
|
|
429
510
|
return [
|
|
430
511
|
patchStep('Astro config (token + build target)', config.path, configPatch, 'inline the pairing token and raise build.target to es2022', manualWithLayout),
|
|
431
512
|
patchStep('Connect snippet (Astro)', layout.path, layoutPatch, 'add the dev-only connect <script> before </body>', manualWithLayout),
|
|
513
|
+
// Declares the Vite define names so `astro check` (create-astro's default build) can see them
|
|
514
|
+
// (#677). Independent of the two halves above: even an ALREADY config/layout still needs this
|
|
515
|
+
// when the env file was never written.
|
|
516
|
+
patchStep('Astro env types (Vite defines)', ASTRO_ENV_DTS_PATH, envPatch, 'declare __RETICLE_TOKEN__ / __RETICLE_ROOT__ for astro check', manualWithLayout),
|
|
432
517
|
];
|
|
433
518
|
}
|
|
434
519
|
/**
|
|
@@ -441,15 +526,40 @@ export function astroSteps(input) {
|
|
|
441
526
|
* warning and a fix.
|
|
442
527
|
*/
|
|
443
528
|
export function cspStep(input) {
|
|
444
|
-
|
|
445
|
-
|
|
529
|
+
// Reads the SAME list `reticle doctor` reads. It used to read a hand-written pair —
|
|
530
|
+
// `[nextConfigSource, nextLayout?.source]` — while csp-doctor.ts already carried the full set
|
|
531
|
+
// including `index.html`, which is where every Vite and Electron app declares its policy. So the
|
|
532
|
+
// command you run BEFORE anything works checked less than the one you run after it has failed.
|
|
533
|
+
//
|
|
534
|
+
// Measured on MarkText, a production Electron editor: its renderer sets `default-src 'self'` with
|
|
535
|
+
// no `connect-src`, the browser blocked the bridge WebSocket, and `init` printed a clean plan. The
|
|
536
|
+
// daemon cannot see a dial that never left the page, so nothing anywhere said why — and the check
|
|
537
|
+
// that would have said it was sitting one import away.
|
|
538
|
+
// The pre-read Next sources are folded in ON TOP of the shared list, not replaced by it: init
|
|
539
|
+
// resolves `nextConfigFile` across more spellings than CSP_FILES names (`.mts`, for one), and a
|
|
540
|
+
// layout is found by search rather than by a fixed path. Two sources of the same truth is the
|
|
541
|
+
// problem being fixed here — one of them being a SUPERSET is not.
|
|
542
|
+
const extra = {
|
|
543
|
+
...(input.nextConfigFile !== null && input.nextConfigFile !== undefined
|
|
544
|
+
? { [input.nextConfigFile]: input.nextConfigSource ?? undefined }
|
|
545
|
+
: {}),
|
|
546
|
+
...(input.nextLayout ? { [input.nextLayout.path]: input.nextLayout.source } : {}),
|
|
547
|
+
};
|
|
548
|
+
const read = (file) => extra[file] ?? input.cspSources?.[file];
|
|
549
|
+
const findings = diagnoseWebCsp(read, input.options.port ?? RETICLE_DEFAULT_PORT, [
|
|
550
|
+
...Object.keys(extra),
|
|
551
|
+
]);
|
|
552
|
+
const first = findings[0];
|
|
553
|
+
if (first === undefined)
|
|
446
554
|
return [];
|
|
447
555
|
return [
|
|
448
556
|
{
|
|
449
557
|
title: CSP_STEP_TITLE,
|
|
450
|
-
target:
|
|
558
|
+
target: first.file,
|
|
451
559
|
status: StepStatus.NOTICE,
|
|
452
|
-
|
|
560
|
+
// `problem` already ends with the text to paste; `fix` is the same sentence for callers that
|
|
561
|
+
// want it on its own (doctor renders them separately). Printing both said it twice.
|
|
562
|
+
detail: first.problem,
|
|
453
563
|
},
|
|
454
564
|
];
|
|
455
565
|
}
|
package/dist/init/plan.d.ts
CHANGED
|
@@ -5,17 +5,7 @@
|
|
|
5
5
|
*/
|
|
6
6
|
import { Framework, UiLibrary, type Detection } from './detect.js';
|
|
7
7
|
import type { FoundStore } from './capabilities.js';
|
|
8
|
-
import {
|
|
9
|
-
/**
|
|
10
|
-
* Pin the SDK to the CLI's own version.
|
|
11
|
-
*
|
|
12
|
-
* `pnpm add -D @reticlehq/react` installed **2.2.1** in one project while npm and yarn took 2.3.0 in
|
|
13
|
-
* the next — a stale registry metadata cache, invisible to the user and to us. A version-skewed SDK
|
|
14
|
-
* talking to a newer daemon is the `-32000` failure path: the app connects, the protocol disagrees,
|
|
15
|
-
* and nothing on either side names a version. Asking for the CLI's exact version makes the cache
|
|
16
|
-
* irrelevant, and a skewed pair impossible to install by accident.
|
|
17
|
-
*/
|
|
18
|
-
export declare function pinnedPackages(packages: readonly string[], version: string | undefined): readonly string[];
|
|
8
|
+
import { McpClient } from './mcp-clients.js';
|
|
19
9
|
/**
|
|
20
10
|
* The dev-dependencies `reticle init` installs — kit (or sensor) first, build plugin next.
|
|
21
11
|
*
|
|
@@ -95,18 +85,28 @@ export interface Plan {
|
|
|
95
85
|
}
|
|
96
86
|
export interface PlanInput {
|
|
97
87
|
detection: Detection;
|
|
88
|
+
/**
|
|
89
|
+
* Write `captureNetworkBodies: true` into the app's config. Off unless the caller asked (#705).
|
|
90
|
+
*
|
|
91
|
+
* Optional so every existing caller and test keeps the safe default without naming it — the one
|
|
92
|
+
* direction a default about somebody else's data should be wrong in.
|
|
93
|
+
*/
|
|
94
|
+
captureBodies?: boolean | undefined;
|
|
95
|
+
/**
|
|
96
|
+
* The CSP-bearing files this project actually has, keyed by path — read once in `gatherPlanInput`.
|
|
97
|
+
*
|
|
98
|
+
* Pre-read rather than given a reader, because `PlanInput` is the pure input to a pure planner and
|
|
99
|
+
* handing it an io would let any later step reach the disk from inside `buildPlan`.
|
|
100
|
+
*/
|
|
101
|
+
cspSources?: Readonly<Record<string, string | undefined>> | undefined;
|
|
98
102
|
/** Whether the `claude` CLI is installed (so we can register the MCP server globally). */
|
|
99
103
|
claudeCli: boolean;
|
|
100
104
|
/** Whether an `reticle` MCP server is already registered with Claude (any scope) — idempotency. */
|
|
101
105
|
mcpExists: boolean;
|
|
102
|
-
/**
|
|
103
|
-
|
|
106
|
+
/** `process.platform`. Injected so this module stays pure. Windows is the only branch. */
|
|
107
|
+
platform?: string;
|
|
104
108
|
/** Whether THIS project has a .cursor/ directory — the signal that Cursor works on this repo. */
|
|
105
109
|
cursorProjectPresent?: boolean | undefined;
|
|
106
|
-
/** Current ~/.cursor/mcp.json content, or null if absent. */
|
|
107
|
-
cursorConfig: string | null;
|
|
108
|
-
/** Absolute path of ~/.cursor/mcp.json (the write target). */
|
|
109
|
-
cursorConfigPath: string;
|
|
110
110
|
/**
|
|
111
111
|
* Every OTHER MCP client detected on this machine, with its config path and current content.
|
|
112
112
|
*
|
|
@@ -139,6 +139,11 @@ export interface PlanInput {
|
|
|
139
139
|
path: string;
|
|
140
140
|
source: string;
|
|
141
141
|
} | null | undefined;
|
|
142
|
+
/**
|
|
143
|
+
* Existing `src/env.d.ts` content, when present — where the Vite-define ambient declarations go
|
|
144
|
+
* so `astro check` can see `__RETICLE_TOKEN__` / `__RETICLE_ROOT__` (#677).
|
|
145
|
+
*/
|
|
146
|
+
astroEnvDts?: string | null | undefined;
|
|
142
147
|
/** Discovered Next config filename (e.g. 'next.config.mjs'), or null. */
|
|
143
148
|
nextConfigFile: string | null;
|
|
144
149
|
/** Source of that Next config, so the export can be wrapped in withReticle. */
|
|
@@ -154,6 +159,14 @@ export interface PlanInput {
|
|
|
154
159
|
nextReticleDevImport?: string | undefined;
|
|
155
160
|
/** Whether the ReticleDev component file already exists. */
|
|
156
161
|
nextReticleDevExists: boolean;
|
|
162
|
+
/**
|
|
163
|
+
* The existing ReticleDev component's source, when there is one.
|
|
164
|
+
*
|
|
165
|
+
* Read so an install predating daemon discovery can be told apart from a current one. Undefined
|
|
166
|
+
* means NOT READ, and an unread file is reported as already-wired rather than as stale: inventing
|
|
167
|
+
* work from missing information is how a plan grows steps that can never be completed.
|
|
168
|
+
*/
|
|
169
|
+
nextReticleDevSource?: string | null | undefined;
|
|
157
170
|
/** `data-testid` values scanned from the app's source, for the generated capabilities block. */
|
|
158
171
|
testids?: readonly string[] | undefined;
|
|
159
172
|
/** Ready-to-uncomment `registerStore` lines for the state libraries the app actually depends on. */
|
|
@@ -226,24 +239,4 @@ export interface PlanInput {
|
|
|
226
239
|
sdkVersion?: string;
|
|
227
240
|
};
|
|
228
241
|
}
|
|
229
|
-
/**
|
|
230
|
-
* Every coding agent `reticle init` knows how to wire itself into, and the three surfaces it wires:
|
|
231
|
-
* the global MCP registration, the project rule file that makes the agent USE Reticle, and the
|
|
232
|
-
* `/reticle` command.
|
|
233
|
-
*
|
|
234
|
-
* One list, because those three surfaces used to enumerate Claude and Cursor separately in three
|
|
235
|
-
* places — so supporting a fourth agent meant finding all three and getting each right. Adding one
|
|
236
|
-
* is now an entry here plus its builders; each builder answers null when that agent is not present
|
|
237
|
-
* for this user or this project, which is also how "no agent detected" falls through to the
|
|
238
|
-
* cross-agent AGENTS.md.
|
|
239
|
-
*
|
|
240
|
-
* Deliberately functions rather than data: registering with Claude runs its CLI while Cursor merges
|
|
241
|
-
* a JSON file, and pretending those are the same shape would cost more than it saves.
|
|
242
|
-
*/
|
|
243
|
-
declare const AgentId: {
|
|
244
|
-
readonly CLAUDE: "claude";
|
|
245
|
-
readonly CURSOR: "cursor";
|
|
246
|
-
};
|
|
247
|
-
export type AgentId = (typeof AgentId)[keyof typeof AgentId];
|
|
248
242
|
export declare function buildPlan(input: PlanInput): Plan;
|
|
249
|
-
export {};
|
package/dist/init/plan.js
CHANGED
|
@@ -4,15 +4,16 @@
|
|
|
4
4
|
* runner performs the `write` side-effects; this module decides *what* should happen.
|
|
5
5
|
*/
|
|
6
6
|
import { Framework, PackageManager, UiLibrary, installCommand, installCommandParts, } from './detect.js';
|
|
7
|
-
import {
|
|
8
|
-
import {
|
|
9
|
-
import {
|
|
7
|
+
import { installFailureHint } from './install-hint.js';
|
|
8
|
+
import { claudeAddCommand, mcpManual, mcpWindowsNote } from './mcp.js';
|
|
9
|
+
import { NodePlatform } from '../platform.js';
|
|
10
|
+
import { mergeClientConfig, ClientMergeStatus, clientSnippet, clientSpec, McpClient, } from './mcp-clients.js';
|
|
10
11
|
import { CLAUDE_COMMAND_PATH, CURSOR_COMMAND_PATH, SLASH_COMMAND_BODY, SLASH_COMMAND_SIGNATURE, } from './slash-command.js';
|
|
11
12
|
import { mergeMarkedInstruction, reticleMdFile, cursorRuleFile, AgentRuleStatus, CLAUDE_MD_PATH, AGENTS_MD_PATH, RETICLE_MD_PATH, CURSOR_RULE_PATH, } from './agent-rules.js';
|
|
12
13
|
import { viteSteps, nextSteps, craSteps, svelteKitSteps, nuxtSteps, astroSteps, cspStep, VITE_PLUGIN_DETAIL, } from './plan-framework.js';
|
|
13
14
|
import { join } from 'node:path';
|
|
14
15
|
import { htmlManual, reticleConfigContent, unverifiedUiLibraryNote } from './snippets.js';
|
|
15
|
-
import { declaredInstallSource } from '../telemetry/install-source.js';
|
|
16
|
+
import { configWithInstallSource, declaredInstallSource } from '../telemetry/install-source.js';
|
|
16
17
|
import { devServerPortWarning, isLikelyDevServerPort } from '../cli/cli-port.js';
|
|
17
18
|
// An app dev installs exactly the audience-scoped browser-side dependencies — never the retired
|
|
18
19
|
// `@reticlehq/core` umbrella (which dragged the Node MCP server + ws into every app). The kit is the
|
|
@@ -32,7 +33,7 @@ const RETICLE_NEXT_PLUGIN = '@reticlehq/next';
|
|
|
32
33
|
* and nothing on either side names a version. Asking for the CLI's exact version makes the cache
|
|
33
34
|
* irrelevant, and a skewed pair impossible to install by accident.
|
|
34
35
|
*/
|
|
35
|
-
|
|
36
|
+
function pinnedPackages(packages, version) {
|
|
36
37
|
if (version === undefined || 0 === version.length)
|
|
37
38
|
return packages;
|
|
38
39
|
return packages.map((p) => `${p}@${version}`);
|
|
@@ -121,7 +122,6 @@ function agentFile(input, relPath) {
|
|
|
121
122
|
return root === undefined || 0 === root.length ? relPath : join(root, relPath);
|
|
122
123
|
}
|
|
123
124
|
const CLAUDE_MCP_TITLE = 'MCP server (Claude, global)';
|
|
124
|
-
const CURSOR_MCP_TITLE = 'MCP server (Cursor, global)';
|
|
125
125
|
function claudeMcpStep(input) {
|
|
126
126
|
if (!input.claudeCli)
|
|
127
127
|
return null;
|
|
@@ -142,34 +142,6 @@ function claudeMcpStep(input) {
|
|
|
142
142
|
exec: { command: cmd.command, args: cmd.args, fallback: cmd.display },
|
|
143
143
|
};
|
|
144
144
|
}
|
|
145
|
-
function cursorMcpStep(input) {
|
|
146
|
-
if (!input.cursorPresent)
|
|
147
|
-
return null;
|
|
148
|
-
const r = mergeCursorConfig(input.cursorConfig);
|
|
149
|
-
if (r.status === CursorMergeStatus.ALREADY) {
|
|
150
|
-
return {
|
|
151
|
-
title: CURSOR_MCP_TITLE,
|
|
152
|
-
target: input.cursorConfigPath,
|
|
153
|
-
status: StepStatus.ALREADY,
|
|
154
|
-
detail: 'reticle already in Cursor global config',
|
|
155
|
-
};
|
|
156
|
-
}
|
|
157
|
-
if (r.status === CursorMergeStatus.MANUAL) {
|
|
158
|
-
return {
|
|
159
|
-
title: CURSOR_MCP_TITLE,
|
|
160
|
-
target: input.cursorConfigPath,
|
|
161
|
-
status: StepStatus.MANUAL,
|
|
162
|
-
detail: `couldn't parse ${input.cursorConfigPath} — add this server by hand:\n "reticle": ${JSON.stringify(cursorServerEntry())}`,
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
return {
|
|
166
|
-
title: CURSOR_MCP_TITLE,
|
|
167
|
-
target: input.cursorConfigPath,
|
|
168
|
-
status: StepStatus.APPLY,
|
|
169
|
-
detail: 'register reticle in Cursor global config',
|
|
170
|
-
write: { path: input.cursorConfigPath, content: r.content },
|
|
171
|
-
};
|
|
172
|
-
}
|
|
173
145
|
/**
|
|
174
146
|
* One step per OTHER detected client.
|
|
175
147
|
*
|
|
@@ -232,19 +204,33 @@ function mcpSteps(input) {
|
|
|
232
204
|
// client. A machine with Cursor AND Windsurf gets both — registering only the first one found is
|
|
233
205
|
// how a user ends up with Reticle in the editor they were not using.
|
|
234
206
|
const steps = [...stepsForAgents(input, (a) => a.mcpStep), ...otherClientSteps(input)];
|
|
235
|
-
if (steps.length
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
207
|
+
if (0 === steps.length) {
|
|
208
|
+
// No agent detected. mcpManual already carries the Windows cmd fallback — do not append it again.
|
|
209
|
+
return [
|
|
210
|
+
{
|
|
211
|
+
title: 'MCP server (global)',
|
|
212
|
+
target: MCP_TARGET,
|
|
213
|
+
status: StepStatus.MANUAL,
|
|
214
|
+
detail: mcpManual(),
|
|
215
|
+
},
|
|
216
|
+
];
|
|
217
|
+
}
|
|
218
|
+
const windowsNote = windowsMcpNoteStep(input);
|
|
219
|
+
if (windowsNote !== null)
|
|
220
|
+
steps.push(windowsNote);
|
|
221
|
+
return steps;
|
|
222
|
+
}
|
|
223
|
+
const WINDOWS_MCP_TITLE = 'Windows MCP spawn';
|
|
224
|
+
/** Windows only. The reported install never reached mcpManual because `claude mcp add` succeeded. */
|
|
225
|
+
function windowsMcpNoteStep(input) {
|
|
226
|
+
if (input.platform !== NodePlatform.WINDOWS)
|
|
227
|
+
return null;
|
|
228
|
+
return {
|
|
229
|
+
title: WINDOWS_MCP_TITLE,
|
|
230
|
+
target: MCP_TARGET,
|
|
231
|
+
status: StepStatus.NOTICE,
|
|
232
|
+
detail: mcpWindowsNote(),
|
|
233
|
+
};
|
|
248
234
|
}
|
|
249
235
|
const SLASH_COMMAND_TITLE = 'The /reticle command';
|
|
250
236
|
/**
|
|
@@ -289,7 +275,8 @@ function claudeCommandStep(input) {
|
|
|
289
275
|
return commandStepFor(agentFile(input, CLAUDE_COMMAND_PATH), input.claudeCli, input.claudeCommandContent);
|
|
290
276
|
}
|
|
291
277
|
function cursorCommandStep(input) {
|
|
292
|
-
const
|
|
278
|
+
const cursorGlobal = (input.detectedClients ?? []).some((c) => c.id === McpClient.CURSOR);
|
|
279
|
+
const present = true === input.cursorProjectPresent || (cursorGlobal && !input.claudeCli);
|
|
293
280
|
return commandStepFor(agentFile(input, CURSOR_COMMAND_PATH), present, input.cursorCommandContent);
|
|
294
281
|
}
|
|
295
282
|
const AGENT_RULE_TITLE = 'Agent verification rule';
|
|
@@ -324,7 +311,8 @@ function claudeRuleStep(input) {
|
|
|
324
311
|
* committed into their repo. (Global MCP registration is different: it is global, and stays.)
|
|
325
312
|
*/
|
|
326
313
|
function cursorRuleStep(input) {
|
|
327
|
-
|
|
314
|
+
const cursorGlobal = (input.detectedClients ?? []).some((c) => c.id === McpClient.CURSOR);
|
|
315
|
+
if (!cursorGlobal && true !== input.cursorProjectPresent)
|
|
328
316
|
return null;
|
|
329
317
|
if (input.cursorProjectPresent !== true && input.claudeCli)
|
|
330
318
|
return null;
|
|
@@ -374,14 +362,13 @@ const AGENT_INTEGRATIONS = [
|
|
|
374
362
|
},
|
|
375
363
|
{
|
|
376
364
|
id: AgentId.CURSOR,
|
|
377
|
-
mcpStep: cursorMcpStep,
|
|
378
365
|
ruleStep: cursorRuleStep,
|
|
379
366
|
commandStep: cursorCommandStep,
|
|
380
367
|
},
|
|
381
368
|
];
|
|
382
369
|
/** The steps one surface contributes across every known agent, in registry order. */
|
|
383
370
|
function stepsForAgents(input, surface) {
|
|
384
|
-
return AGENT_INTEGRATIONS.map((a) => surface(a)(input)).filter((s) => s !== null);
|
|
371
|
+
return AGENT_INTEGRATIONS.map((a) => surface(a)?.(input) ?? null).filter((s) => s !== null);
|
|
385
372
|
}
|
|
386
373
|
/** The `/reticle` command file for every agent that has a command surface and is present here. */
|
|
387
374
|
function slashCommandSteps(input) {
|
|
@@ -488,15 +475,6 @@ function unpinnedRetryNote(version, pm) {
|
|
|
488
475
|
`installed instead. That may not match the daemon — if the agent reports protocol errors, check ` +
|
|
489
476
|
`\`versionSkew\` in reticle_sessions.${remedy}`);
|
|
490
477
|
}
|
|
491
|
-
function installFailureHint(pm) {
|
|
492
|
-
if (pm !== PackageManager.PNPM)
|
|
493
|
-
return 'If the version was refused, install the SDK yourself.';
|
|
494
|
-
return ('If pnpm reported ERR_PNPM_NO_MATURE_MATCHING_VERSION, its minimumReleaseAge setting is holding ' +
|
|
495
|
-
'this release back. Either wait out the window, or allow these packages explicitly:\n' +
|
|
496
|
-
' pnpm config set minimumReleaseAgeExclude "@reticlehq/*"\n' +
|
|
497
|
-
'Do NOT drop the version pin — unpinned, pnpm installs an older SDK against a newer daemon, and ' +
|
|
498
|
-
'that mismatch surfaces as a -32000 with nothing naming a version.');
|
|
499
|
-
}
|
|
500
478
|
function installStep(input) {
|
|
501
479
|
const pm = input.detection.packageManager;
|
|
502
480
|
const packages = pinnedPackages(frameworkPackages(input.detection.framework, input.detection.uiLibrary), input.options.sdkVersion);
|
|
@@ -614,6 +592,18 @@ function reticleConfigStep(input, content) {
|
|
|
614
592
|
detail: problem,
|
|
615
593
|
};
|
|
616
594
|
}
|
|
595
|
+
// The one thing a re-run can still learn: which channel the user actually arrived through.
|
|
596
|
+
// See configWithInstallSource — it only ever ADDS a field that is absent.
|
|
597
|
+
const backfilled = configWithInstallSource(input.reticleConfigSource, declaredInstallSource());
|
|
598
|
+
if (backfilled !== undefined) {
|
|
599
|
+
return {
|
|
600
|
+
title: RETICLE_CONFIG_TITLE,
|
|
601
|
+
target: RETICLE_CONFIG_FILE,
|
|
602
|
+
status: StepStatus.APPLY,
|
|
603
|
+
detail: 'record which install route this project came through',
|
|
604
|
+
write: { path: RETICLE_CONFIG_FILE, content: backfilled },
|
|
605
|
+
};
|
|
606
|
+
}
|
|
617
607
|
return {
|
|
618
608
|
title: RETICLE_CONFIG_TITLE,
|
|
619
609
|
target: RETICLE_CONFIG_FILE,
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two conditions that make every later phase fail, checked before anything is written.
|
|
3
|
+
*
|
|
4
|
+
* Both lived in setup/reticle.mjs and neither survived the port into `init`. What they buy is the
|
|
5
|
+
* distance between a failure and its cause: without them, an unwritable checkout arrives as EACCES
|
|
6
|
+
* in a stack trace at phase four, and a missing package manager arrives as `spawn pnpm ENOENT`
|
|
7
|
+
* inside "the dev server exited" — which sends the reader into their own dev script hunting a bug
|
|
8
|
+
* that is not there.
|
|
9
|
+
*/
|
|
10
|
+
/** The parts of the environment preflight reads, so the rules are testable without a filesystem. */
|
|
11
|
+
export interface PreflightIo {
|
|
12
|
+
/** Absolute path of the directory init is running in. */
|
|
13
|
+
cwd(): string;
|
|
14
|
+
/** Can this process write into the project root. */
|
|
15
|
+
canWrite(): boolean;
|
|
16
|
+
/** Runs a command quietly for a yes/no check; true on exit code 0. */
|
|
17
|
+
probe(command: string, args: readonly string[]): boolean;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* The refusal to print, or undefined when this machine can run the install.
|
|
21
|
+
*
|
|
22
|
+
* `packageManager` is the one init RESOLVED, never a raw lockfile check. An inherited
|
|
23
|
+
* `pnpm-lock.yaml` at a monorepo root does not mean the app in `frontend/` uses pnpm — that app's own
|
|
24
|
+
* installed tree outranks an ancestor lockfile, and detect.ts already works this out. Re-deriving it
|
|
25
|
+
* here from `exists('pnpm-lock.yaml')` refused an npm app sitting under a pnpm monorepo on a machine
|
|
26
|
+
* with no pnpm, which the install gate proves must succeed.
|
|
27
|
+
*/
|
|
28
|
+
export declare function preflightRefusal(io: PreflightIo, packageManager: string): string | undefined;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two conditions that make every later phase fail, checked before anything is written.
|
|
3
|
+
*
|
|
4
|
+
* Both lived in setup/reticle.mjs and neither survived the port into `init`. What they buy is the
|
|
5
|
+
* distance between a failure and its cause: without them, an unwritable checkout arrives as EACCES
|
|
6
|
+
* in a stack trace at phase four, and a missing package manager arrives as `spawn pnpm ENOENT`
|
|
7
|
+
* inside "the dev server exited" — which sends the reader into their own dev script hunting a bug
|
|
8
|
+
* that is not there.
|
|
9
|
+
*/
|
|
10
|
+
/**
|
|
11
|
+
* npm ships with node, so refusing for its absence would refuse on a machine that is fine.
|
|
12
|
+
*/
|
|
13
|
+
const ALWAYS_PRESENT = 'npm';
|
|
14
|
+
/**
|
|
15
|
+
* The refusal to print, or undefined when this machine can run the install.
|
|
16
|
+
*
|
|
17
|
+
* `packageManager` is the one init RESOLVED, never a raw lockfile check. An inherited
|
|
18
|
+
* `pnpm-lock.yaml` at a monorepo root does not mean the app in `frontend/` uses pnpm — that app's own
|
|
19
|
+
* installed tree outranks an ancestor lockfile, and detect.ts already works this out. Re-deriving it
|
|
20
|
+
* here from `exists('pnpm-lock.yaml')` refused an npm app sitting under a pnpm monorepo on a machine
|
|
21
|
+
* with no pnpm, which the install gate proves must succeed.
|
|
22
|
+
*/
|
|
23
|
+
export function preflightRefusal(io, packageManager) {
|
|
24
|
+
// First: on a read-only checkout nothing else matters, and one access check is cheaper and
|
|
25
|
+
// quieter than spawning a subprocess to discover the same thing.
|
|
26
|
+
if (!io.canWrite()) {
|
|
27
|
+
return (`${io.cwd()} is not writable, and init has to write into it (.reticle.json, the build config, ` +
|
|
28
|
+
'a capabilities file). Fix the permissions, or run init from a checkout you own.');
|
|
29
|
+
}
|
|
30
|
+
// What the project resolves to says nothing about what the machine HAS, and a project committed to
|
|
31
|
+
// pnpm on an npm-only box is an ordinary Monday.
|
|
32
|
+
if (ALWAYS_PRESENT !== packageManager && !io.probe(packageManager, ['--version'])) {
|
|
33
|
+
return (`this project uses ${packageManager} (its lockfile says so) and ${packageManager} is not ` +
|
|
34
|
+
`installed on this machine. Install it (npm i -g ${packageManager}, or corepack enable), or ` +
|
|
35
|
+
'pass --url with the address the app already serves.');
|
|
36
|
+
}
|
|
37
|
+
return undefined;
|
|
38
|
+
}
|