@reticlehq/server 2.13.1 → 2.14.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.
Files changed (449) hide show
  1. package/SKILL.md +8 -18
  2. package/bin/reticle.js +3 -0
  3. package/dist/bridge/auth-failure-reason.js +12 -1
  4. package/dist/bridge/bridge-security.d.ts +8 -0
  5. package/dist/bridge/bridge-security.js +6 -1
  6. package/dist/bridge/bridge.d.ts +3 -0
  7. package/dist/bridge/bridge.js +23 -1
  8. package/dist/bridge/bridge.test-harness.d.ts +10 -1
  9. package/dist/bridge/bridge.test-harness.js +7 -1
  10. package/dist/bridge/pairing-token.d.ts +17 -0
  11. package/dist/bridge/pairing-token.js +26 -0
  12. package/dist/bridge/token-auth.d.ts +7 -0
  13. package/dist/bridge/token-auth.js +7 -1
  14. package/dist/capsule/capsule-store.d.ts +4 -4
  15. package/dist/capsule/capsule.d.ts +1 -1
  16. package/dist/capsule/capsule.js +3 -3
  17. package/dist/capsule/causal-summary.d.ts +21 -1
  18. package/dist/capsule/causal-summary.js +8 -6
  19. package/dist/capsule/divergence.d.ts +1 -1
  20. package/dist/capsule/divergence.js +26 -10
  21. package/dist/chromium-launch-options.d.ts +2 -1
  22. package/dist/cli/adhoc-verdict.d.ts +58 -0
  23. package/dist/cli/adhoc-verdict.js +115 -0
  24. package/dist/cli/chromium-hint.d.ts +18 -4
  25. package/dist/cli/chromium-hint.js +54 -6
  26. package/dist/cli/cli-doctor.js +1 -2
  27. package/dist/cli/cli-flow-commands.d.ts +16 -2
  28. package/dist/cli/cli-flow-commands.js +28 -9
  29. package/dist/cli/cli-parse-feedback.js +1 -1
  30. package/dist/cli/cli-parse.d.ts +2 -1
  31. package/dist/cli/cli-parse.js +38 -0
  32. package/dist/cli/cli-port.d.ts +5 -13
  33. package/dist/cli/cli-port.js +5 -38
  34. package/dist/cli/cli-update-commands.js +4 -4
  35. package/dist/cli/cli-verify.d.ts +24 -7
  36. package/dist/cli/cli-verify.js +87 -13
  37. package/dist/cli/cloud-keystore.d.ts +2 -1
  38. package/dist/cli/cloud-login.d.ts +2 -1
  39. package/dist/cli/cloud-session.d.ts +2 -1
  40. package/dist/cli/cloud-session.js +1 -1
  41. package/dist/cli/daemon-start-options.d.ts +2 -1
  42. package/dist/cli/device-flow.d.ts +2 -2
  43. package/dist/cli/doctor-daemon-line.d.ts +2 -1
  44. package/dist/cli/doctor-project-line.d.ts +2 -1
  45. package/dist/cli/doctor-rows.d.ts +2 -1
  46. package/dist/cli/drive-attach.d.ts +4 -3
  47. package/dist/cli/gate-hook-message.d.ts +2 -1
  48. package/dist/cli/status-next-action.js +10 -11
  49. package/dist/cli.d.ts +1 -0
  50. package/dist/cli.js +21 -9
  51. package/dist/cloud/account-state.d.ts +20 -0
  52. package/dist/cloud/account-state.js +65 -0
  53. package/dist/cloud/cloud-sync.d.ts +46 -3
  54. package/dist/cloud/cloud-sync.js +116 -0
  55. package/dist/cloud/sync-cycle.d.ts +5 -4
  56. package/dist/cloud/sync-cycle.js +1 -1
  57. package/dist/cloud/sync-daemon.d.ts +3 -19
  58. package/dist/cloud/sync-daemon.js +2 -2
  59. package/dist/crawl/crawl-tools.js +1 -1
  60. package/dist/crawl/crawl.d.ts +5 -5
  61. package/dist/crawl/crawl.js +138 -4
  62. package/dist/daemon/daemon-resilience.d.ts +3 -2
  63. package/dist/daemon/daemon-resilience.js +43 -4
  64. package/dist/daemon/daemon-resolve.d.ts +0 -9
  65. package/dist/daemon/daemon-resolve.js +2 -2
  66. package/dist/daemon/dev-servers.d.ts +1 -1
  67. package/dist/daemon/dev-servers.js +1 -1
  68. package/dist/daemon/loopback-alias.d.ts +2 -1
  69. package/dist/daemon/startup-failure.d.ts +11 -0
  70. package/dist/daemon/startup-failure.js +46 -0
  71. package/dist/events/contradictions.d.ts +10 -16
  72. package/dist/events/contradictions.js +149 -17
  73. package/dist/events/declared.d.ts +13 -1
  74. package/dist/events/declared.js +59 -3
  75. package/dist/events/echo-mismatch.js +75 -6
  76. package/dist/events/lineage.d.ts +52 -0
  77. package/dist/events/lineage.js +122 -0
  78. package/dist/events/net-evidence.d.ts +21 -0
  79. package/dist/events/net-evidence.js +81 -0
  80. package/dist/events/predicate-console.d.ts +13 -0
  81. package/dist/events/predicate-console.js +138 -0
  82. package/dist/events/predicate-element.d.ts +13 -0
  83. package/dist/events/predicate-element.js +214 -0
  84. package/dist/events/predicate-eval.d.ts +15 -3
  85. package/dist/events/predicate-eval.js +128 -110
  86. package/dist/events/predicate-parse.js +34 -1
  87. package/dist/events/predicate-request-body.d.ts +50 -0
  88. package/dist/events/predicate-request-body.js +120 -0
  89. package/dist/events/predicate-route.d.ts +21 -1
  90. package/dist/events/predicate-route.js +149 -21
  91. package/dist/events/predicate-schema.d.ts +8 -1
  92. package/dist/events/predicate-schema.js +34 -0
  93. package/dist/events/predicate.d.ts +2 -0
  94. package/dist/events/predicate.js +52 -159
  95. package/dist/events/split-text-miss.d.ts +6 -4
  96. package/dist/events/split-text-miss.js +12 -5
  97. package/dist/flows/affected-tools.js +22 -9
  98. package/dist/flows/annotate.d.ts +2 -1
  99. package/dist/flows/annotate.js +19 -1
  100. package/dist/flows/coverage.d.ts +2 -2
  101. package/dist/flows/flake.d.ts +3 -3
  102. package/dist/flows/flow-expect-grammar.d.ts +33 -0
  103. package/dist/flows/flow-expect-grammar.js +155 -0
  104. package/dist/flows/flow-replay-run.d.ts +1 -1
  105. package/dist/flows/flow-replay-run.js +28 -15
  106. package/dist/flows/flow-replay.d.ts +10 -0
  107. package/dist/flows/flow-replay.js +57 -22
  108. package/dist/flows/flow-secret-field.d.ts +14 -0
  109. package/dist/flows/flow-secret-field.js +22 -0
  110. package/dist/flows/flow-step-runners.d.ts +1 -0
  111. package/dist/flows/flow-step-runners.js +91 -34
  112. package/dist/flows/flow-success.js +22 -0
  113. package/dist/flows/flow-tools.js +27 -8
  114. package/dist/flows/flow-upload-resolve.d.ts +23 -0
  115. package/dist/flows/flow-upload-resolve.js +46 -0
  116. package/dist/flows/flows.d.ts +15 -0
  117. package/dist/flows/flows.js +17 -14
  118. package/dist/flows/git-changed.d.ts +23 -4
  119. package/dist/flows/git-changed.js +32 -6
  120. package/dist/flows/heal-run.js +2 -2
  121. package/dist/flows/predicate-to-expect.d.ts +3 -2
  122. package/dist/flows/predicate-to-expect.js +11 -5
  123. package/dist/flows/recording-backtrack.d.ts +24 -0
  124. package/dist/flows/recording-backtrack.js +73 -0
  125. package/dist/flows/recordings.d.ts +6 -0
  126. package/dist/flows/replay-halt.d.ts +26 -0
  127. package/dist/flows/replay-halt.js +30 -0
  128. package/dist/flows/replay.d.ts +0 -8
  129. package/dist/flows/replay.js +15 -3
  130. package/dist/flows/suite-flakes.d.ts +2 -1
  131. package/dist/flows/verify-change-tools.js +16 -4
  132. package/dist/honesty/already-true.d.ts +14 -0
  133. package/dist/honesty/already-true.js +47 -4
  134. package/dist/honesty/blind-spots.d.ts +3 -1
  135. package/dist/honesty/blind-spots.js +24 -1
  136. package/dist/honesty/body-capture-remedy.d.ts +42 -0
  137. package/dist/honesty/body-capture-remedy.js +95 -0
  138. package/dist/honesty/feature-capture.d.ts +3 -2
  139. package/dist/honesty/feature-capture.js +1 -1
  140. package/dist/honesty/gap-ledger.d.ts +1 -1
  141. package/dist/honesty/gap-ledger.js +1 -1
  142. package/dist/honesty/instrumentation-gaps.d.ts +8 -1
  143. package/dist/honesty/instrumentation-gaps.js +12 -2
  144. package/dist/honesty/observability.d.ts +4 -3
  145. package/dist/honesty/tool-hit-rate.d.ts +3 -2
  146. package/dist/honesty/uncaptured-bodies.d.ts +3 -1
  147. package/dist/honesty/uncaptured-bodies.js +6 -2
  148. package/dist/honesty/unsettled.d.ts +9 -0
  149. package/dist/honesty/unsettled.js +45 -0
  150. package/dist/honesty/verified.d.ts +32 -1
  151. package/dist/honesty/verified.js +37 -10
  152. package/dist/impact/impact-store.d.ts +5 -14
  153. package/dist/impact/impact-store.js +49 -6
  154. package/dist/index.js +1 -1
  155. package/dist/input/network-detail.d.ts +26 -1
  156. package/dist/input/network-detail.js +44 -12
  157. package/dist/input/network-mock-tools.js +24 -17
  158. package/dist/input/real-input.js +1 -1
  159. package/dist/input/viewport-tools.js +25 -13
  160. package/dist/intent/inline-intent.d.ts +0 -10
  161. package/dist/intent/inline-intent.js +1 -1
  162. package/dist/intent/intent-shard-store.d.ts +3 -2
  163. package/dist/intent/intent-shard-store.js +1 -1
  164. package/dist/intent/intent-shard.d.ts +14 -14
  165. package/dist/intent/intent-shard.js +4 -4
  166. package/dist/intent/intent-store.d.ts +1 -1
  167. package/dist/intent/intent-store.js +1 -1
  168. package/dist/intent/intent-subject.d.ts +2 -1
  169. package/dist/intent/open-intents.d.ts +3 -2
  170. package/dist/license/license.d.ts +4 -4
  171. package/dist/license/license.js +1 -1
  172. package/dist/mcp/attach-memory.d.ts +2 -1
  173. package/dist/mcp/client-identity.d.ts +2 -1
  174. package/dist/mcp/mcp-outage.d.ts +1 -1
  175. package/dist/mcp/mcp-outage.js +1 -1
  176. package/dist/mcp/mcp-proxy.d.ts +3 -1
  177. package/dist/mcp/mcp-proxy.js +32 -7
  178. package/dist/mcp/mcp.js +3 -1
  179. package/dist/mcp/proxy-handshake.d.ts +2 -1
  180. package/dist/mcp/proxy-idle-exit.d.ts +45 -0
  181. package/dist/mcp/proxy-idle-exit.js +94 -0
  182. package/dist/mcp/server-instructions.d.ts +2 -1
  183. package/dist/memory/project-memory.d.ts +2 -3
  184. package/dist/memory/project-memory.js +1 -1
  185. package/dist/oracles/propose-consequences.js +5 -5
  186. package/dist/oracles/self-instrument.d.ts +2 -2
  187. package/dist/oracles/self-instrument.js +1 -1
  188. package/dist/platform.d.ts +3 -5
  189. package/dist/platform.js +3 -5
  190. package/dist/pool/browser-pool.d.ts +92 -0
  191. package/dist/pool/browser-pool.js +119 -5
  192. package/dist/pool/playwright-launcher.js +29 -2
  193. package/dist/pool/storage-seed.d.ts +23 -0
  194. package/dist/pool/storage-seed.js +198 -0
  195. package/dist/project/artifact-root.d.ts +2 -1
  196. package/dist/project/memory-fs.d.ts +2 -1
  197. package/dist/project/reticle-dir.js +1 -1
  198. package/dist/project/session-root.d.ts +8 -0
  199. package/dist/project/session-root.js +9 -2
  200. package/dist/runs/reticle-runner.d.ts +14 -1
  201. package/dist/runs/reticle-runner.js +39 -2
  202. package/dist/session/attachment-history.d.ts +2 -1
  203. package/dist/session/fake-session.d.ts +37 -0
  204. package/dist/session/fake-session.js +81 -0
  205. package/dist/session/lease-visibility.d.ts +2 -1
  206. package/dist/session/live-control-tools.js +6 -0
  207. package/dist/session/no-session-diagnosis.d.ts +17 -1
  208. package/dist/session/no-session-diagnosis.js +32 -6
  209. package/dist/session/no-session-next-action.d.ts +14 -0
  210. package/dist/session/no-session-next-action.js +18 -0
  211. package/dist/session/no-session-watch.js +46 -3
  212. package/dist/session/registered-projects.d.ts +54 -0
  213. package/dist/session/registered-projects.js +73 -0
  214. package/dist/session/review-store.d.ts +2 -1
  215. package/dist/session/session-health.d.ts +62 -1
  216. package/dist/session/session-health.js +82 -2
  217. package/dist/session/session-manager.d.ts +11 -1
  218. package/dist/session/session-manager.js +18 -3
  219. package/dist/session/session-replaced.d.ts +24 -0
  220. package/dist/session/session-replaced.js +29 -0
  221. package/dist/session/session-successor.js +20 -4
  222. package/dist/session/session.d.ts +13 -5
  223. package/dist/session/session.js +31 -23
  224. package/dist/setup/agent-configs.d.ts +3 -2
  225. package/dist/setup/agent-writer.d.ts +3 -2
  226. package/dist/setup/approval-migration.d.ts +2 -1
  227. package/dist/setup/approval-migration.js +1 -1
  228. package/dist/setup/auto-approve.d.ts +11 -19
  229. package/dist/setup/auto-approve.js +15 -12
  230. package/dist/{init → setup}/confirm.js +1 -1
  231. package/dist/setup/desktop-shape.d.ts +3 -2
  232. package/dist/setup/drive-agent.d.ts +2 -3
  233. package/dist/setup/drive-agent.js +1 -1
  234. package/dist/setup/drive-plan.d.ts +3 -2
  235. package/dist/setup/ensure-daemon.d.ts +2 -1
  236. package/dist/setup/existing-app.d.ts +12 -0
  237. package/dist/setup/existing-app.js +13 -0
  238. package/dist/setup/init-host.d.ts +11 -0
  239. package/dist/setup/init-host.js +26 -0
  240. package/dist/setup/init-runtime.d.ts +4 -10
  241. package/dist/setup/init-runtime.js +23 -16
  242. package/dist/setup/license-key.d.ts +2 -1
  243. package/dist/setup/listeners.d.ts +2 -1
  244. package/dist/setup/loopback-probe-urls.d.ts +18 -0
  245. package/dist/setup/loopback-probe-urls.js +52 -0
  246. package/dist/setup/node-effects.d.ts +3 -0
  247. package/dist/setup/node-effects.js +26 -11
  248. package/dist/setup/page-probe.d.ts +5 -0
  249. package/dist/setup/relaunch.d.ts +2 -1
  250. package/dist/setup/run-setup.d.ts +5 -1
  251. package/dist/setup/run-setup.js +141 -50
  252. package/dist/setup/setup-command.d.ts +3 -2
  253. package/dist/setup/setup-command.js +8 -0
  254. package/dist/setup/setup-options.d.ts +5 -3
  255. package/dist/setup/setup-options.js +3 -2
  256. package/dist/setup/wait-progress.d.ts +28 -0
  257. package/dist/setup/wait-progress.js +43 -0
  258. package/dist/telemetry/app-instrumented.d.ts +2 -1
  259. package/dist/telemetry/app-instrumented.js +1 -1
  260. package/dist/telemetry/automation-hint.d.ts +1 -1
  261. package/dist/telemetry/automation-hint.js +1 -1
  262. package/dist/telemetry/cli-telemetry.js +1 -1
  263. package/dist/telemetry/connect-failure.d.ts +1 -1
  264. package/dist/telemetry/connect-failure.js +1 -1
  265. package/dist/telemetry/crash-cause.d.ts +3 -2
  266. package/dist/telemetry/crash-cause.js +1 -1
  267. package/dist/telemetry/daemon-telemetry.d.ts +3 -2
  268. package/dist/telemetry/daemon-telemetry.js +1 -1
  269. package/dist/telemetry/error-class.d.ts +3 -2
  270. package/dist/telemetry/error-class.js +1 -1
  271. package/dist/telemetry/feedback-cli.js +1 -1
  272. package/dist/telemetry/feedback-context.d.ts +3 -2
  273. package/dist/telemetry/feedback-context.js +5 -4
  274. package/dist/telemetry/feedback-local.d.ts +3 -2
  275. package/dist/telemetry/feedback.d.ts +4 -3
  276. package/dist/telemetry/feedback.js +1 -1
  277. package/dist/telemetry/git-facts.d.ts +2 -2
  278. package/dist/telemetry/git-facts.js +1 -1
  279. package/dist/telemetry/identify.d.ts +1 -1
  280. package/dist/telemetry/identify.js +1 -1
  281. package/dist/telemetry/init-telemetry.d.ts +2 -14
  282. package/dist/telemetry/init-telemetry.js +4 -13
  283. package/dist/telemetry/install-source.d.ts +7 -13
  284. package/dist/telemetry/install-source.js +7 -29
  285. package/dist/telemetry/license-activation.d.ts +3 -2
  286. package/dist/telemetry/license-activation.js +1 -1
  287. package/dist/telemetry/machine-snapshot.d.ts +1 -1
  288. package/dist/telemetry/mcp-connection.js +1 -1
  289. package/dist/telemetry/project-profile.d.ts +0 -14
  290. package/dist/telemetry/project-profile.js +1 -1
  291. package/dist/telemetry/proxy-telemetry.js +1 -1
  292. package/dist/telemetry/session-metrics.d.ts +1 -1
  293. package/dist/telemetry/session-metrics.js +1 -1
  294. package/dist/telemetry/telemetry.d.ts +1 -17
  295. package/dist/telemetry/telemetry.js +4 -4
  296. package/dist/telemetry/tool-refused.d.ts +1 -1
  297. package/dist/telemetry/tool-refused.js +1 -1
  298. package/dist/tools/act-observation.d.ts +3 -2
  299. package/dist/tools/act-preflight.js +8 -3
  300. package/dist/tools/act-target.d.ts +4 -0
  301. package/dist/tools/act-target.js +14 -5
  302. package/dist/tools/act-tools.d.ts +0 -2
  303. package/dist/tools/act-tools.js +45 -15
  304. package/dist/tools/assert-source.d.ts +30 -0
  305. package/dist/tools/assert-source.js +21 -0
  306. package/dist/tools/assert-verdict.d.ts +1 -1
  307. package/dist/tools/assert-verdict.js +14 -4
  308. package/dist/tools/browser-tools.js +28 -8
  309. package/dist/tools/complete-snapshot.d.ts +3 -2
  310. package/dist/tools/dynamic-tools.js +8 -0
  311. package/dist/tools/error-recovery.d.ts +10 -0
  312. package/dist/tools/error-recovery.js +23 -0
  313. package/dist/tools/feedback-tools.js +1 -1
  314. package/dist/tools/invoke-tool.js +2 -0
  315. package/dist/tools/lease-tools.d.ts +48 -20
  316. package/dist/tools/lease-tools.js +311 -76
  317. package/dist/tools/lineage-tools.d.ts +14 -0
  318. package/dist/tools/lineage-tools.js +64 -0
  319. package/dist/tools/merge-tools.js +1 -3
  320. package/dist/tools/navigate-arrival.d.ts +45 -1
  321. package/dist/tools/navigate-arrival.js +39 -6
  322. package/dist/tools/navigate-result.d.ts +8 -1
  323. package/dist/tools/navigate-result.js +14 -4
  324. package/dist/tools/numeric-bounds.d.ts +0 -11
  325. package/dist/tools/numeric-bounds.js +4 -4
  326. package/dist/tools/observe-tools.js +22 -26
  327. package/dist/tools/observed-nothing.d.ts +9 -0
  328. package/dist/tools/observed-nothing.js +2 -1
  329. package/dist/tools/read-tools.js +12 -17
  330. package/dist/tools/real-input-attempt.d.ts +14 -6
  331. package/dist/tools/real-input-attempt.js +75 -18
  332. package/dist/tools/reconcile-tools.js +2 -1
  333. package/dist/tools/reload-result.d.ts +6 -1
  334. package/dist/tools/reload-result.js +7 -2
  335. package/dist/tools/resolve-target.d.ts +7 -1
  336. package/dist/tools/resolve-target.js +72 -9
  337. package/dist/tools/settle-in-flight.d.ts +1 -1
  338. package/dist/tools/settle-in-flight.js +9 -2
  339. package/dist/tools/snapshot-delta.d.ts +24 -1
  340. package/dist/tools/snapshot-delta.js +66 -7
  341. package/dist/tools/tool-names.d.ts +1 -0
  342. package/dist/tools/tool-names.js +1 -0
  343. package/dist/tools/tool-surface.js +20 -2
  344. package/dist/tools/tools.js +120 -11
  345. package/dist/tools/verify-next-baton.d.ts +2 -1
  346. package/dist/update/sdk-sync.d.ts +1 -1
  347. package/dist/update/sdk-sync.js +1 -1
  348. package/dist/update/updater.js +1 -1
  349. package/dist/version/sdk-fix.d.ts +2 -1
  350. package/dist/version/version-skew.d.ts +0 -8
  351. package/dist/version/version-skew.js +1 -1
  352. package/docs/README.md +8 -6
  353. package/docs/actions.mdx +1 -1
  354. package/docs/agent-cheatsheet.md +4 -2
  355. package/docs/architecture.md +1 -1
  356. package/docs/cli/mcp.mdx +3 -1
  357. package/docs/cli/watch.mdx +1 -1
  358. package/docs/cli.mdx +1 -1
  359. package/docs/desktop.mdx +1 -1
  360. package/docs/docs.json +8 -3
  361. package/docs/faq.mdx +9 -0
  362. package/docs/first-drive.md +136 -0
  363. package/docs/frameworks.mdx +29 -7
  364. package/docs/gate-plan.md +2 -2
  365. package/docs/gates.md +19 -11
  366. package/docs/getting-started.md +7 -1
  367. package/docs/http-transport.md +164 -0
  368. package/docs/index.mdx +5 -3
  369. package/docs/install-manual.mdx +1 -1
  370. package/docs/packages/tauri.mdx +1 -1
  371. package/docs/packages.mdx +15 -3
  372. package/docs/platform-integration.md +1 -1
  373. package/docs/predicates.mdx +2 -0
  374. package/docs/system-map.md +2 -2
  375. package/docs/telemetry-contract.md +4 -4
  376. package/docs/telemetry-events.mdx +1 -1
  377. package/docs/telemetry.md +3 -3
  378. package/docs/tools-navigate.mdx +14 -6
  379. package/docs/usage.md +4 -4
  380. package/package.json +7 -4
  381. package/dist/init/agent-rules.d.ts +0 -116
  382. package/dist/init/agent-rules.js +0 -279
  383. package/dist/init/app-choice.d.ts +0 -20
  384. package/dist/init/app-choice.js +0 -25
  385. package/dist/init/astro-host.d.ts +0 -21
  386. package/dist/init/astro-host.js +0 -27
  387. package/dist/init/astro-patch.d.ts +0 -33
  388. package/dist/init/astro-patch.js +0 -300
  389. package/dist/init/capabilities.d.ts +0 -40
  390. package/dist/init/capabilities.js +0 -150
  391. package/dist/init/closing-hint.d.ts +0 -36
  392. package/dist/init/closing-hint.js +0 -120
  393. package/dist/init/connect-steps.d.ts +0 -2
  394. package/dist/init/connect-steps.js +0 -50
  395. package/dist/init/cra.d.ts +0 -79
  396. package/dist/init/cra.js +0 -178
  397. package/dist/init/csp-check.d.ts +0 -38
  398. package/dist/init/csp-check.js +0 -107
  399. package/dist/init/csp-doctor.d.ts +0 -32
  400. package/dist/init/csp-doctor.js +0 -54
  401. package/dist/init/desktop-doctor.d.ts +0 -41
  402. package/dist/init/desktop-doctor.js +0 -198
  403. package/dist/init/detect.d.ts +0 -96
  404. package/dist/init/detect.js +0 -209
  405. package/dist/init/dev-script.d.ts +0 -50
  406. package/dist/init/dev-script.js +0 -66
  407. package/dist/init/format-generated.d.ts +0 -18
  408. package/dist/init/format-generated.js +0 -39
  409. package/dist/init/install-hint.d.ts +0 -9
  410. package/dist/init/install-hint.js +0 -29
  411. package/dist/init/mcp-clients.d.ts +0 -89
  412. package/dist/init/mcp-clients.js +0 -299
  413. package/dist/init/mcp-registered.d.ts +0 -12
  414. package/dist/init/mcp-registered.js +0 -14
  415. package/dist/init/mcp.d.ts +0 -89
  416. package/dist/init/mcp.js +0 -129
  417. package/dist/init/next-patch.d.ts +0 -39
  418. package/dist/init/next-patch.js +0 -196
  419. package/dist/init/node-io.d.ts +0 -7
  420. package/dist/init/node-io.js +0 -117
  421. package/dist/init/non-js-project.d.ts +0 -27
  422. package/dist/init/non-js-project.js +0 -84
  423. package/dist/init/patch-kind.d.ts +0 -20
  424. package/dist/init/patch-kind.js +0 -10
  425. package/dist/init/plan-framework.d.ts +0 -64
  426. package/dist/init/plan-framework.js +0 -565
  427. package/dist/init/plan.d.ts +0 -242
  428. package/dist/init/plan.js +0 -703
  429. package/dist/init/preflight.d.ts +0 -28
  430. package/dist/init/preflight.js +0 -38
  431. package/dist/init/project-id.d.ts +0 -12
  432. package/dist/init/project-id.js +0 -25
  433. package/dist/init/refresh-rules.d.ts +0 -39
  434. package/dist/init/refresh-rules.js +0 -51
  435. package/dist/init/run.d.ts +0 -117
  436. package/dist/init/run.js +0 -806
  437. package/dist/init/slash-command.d.ts +0 -27
  438. package/dist/init/slash-command.js +0 -132
  439. package/dist/init/snippets.d.ts +0 -134
  440. package/dist/init/snippets.js +0 -572
  441. package/dist/init/vite-config.d.ts +0 -18
  442. package/dist/init/vite-config.js +0 -114
  443. package/dist/init/windows-quote.d.ts +0 -38
  444. package/dist/init/windows-quote.js +0 -70
  445. package/dist/init/workspace-apps.d.ts +0 -30
  446. package/dist/init/workspace-apps.js +0 -178
  447. package/dist/project/remember-project.d.ts +0 -24
  448. package/dist/project/remember-project.js +0 -40
  449. /package/dist/{init → setup}/confirm.d.ts +0 -0
package/dist/init/plan.js DELETED
@@ -1,703 +0,0 @@
1
- /**
2
- * Pure assembly of the `reticle init` action plan. Given the detection result and the relevant file
3
- * contents, produce an ordered list of steps — each marked apply / manual / already / skip. The
4
- * runner performs the `write` side-effects; this module decides *what* should happen.
5
- */
6
- import { Framework, PackageManager, UiLibrary, installCommand, installCommandParts, } from './detect.js';
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';
11
- import { CLAUDE_COMMAND_PATH, CURSOR_COMMAND_PATH, SLASH_COMMAND_BODY, SLASH_COMMAND_SIGNATURE, } from './slash-command.js';
12
- import { mergeMarkedInstruction, reticleMdFile, cursorRuleFile, AgentRuleStatus, CLAUDE_MD_PATH, AGENTS_MD_PATH, RETICLE_MD_PATH, CURSOR_RULE_PATH, } from './agent-rules.js';
13
- import { viteSteps, nextSteps, craSteps, svelteKitSteps, nuxtSteps, astroSteps, cspStep, VITE_PLUGIN_DETAIL, } from './plan-framework.js';
14
- import { join } from 'node:path';
15
- import { htmlManual, reticleConfigContent, unverifiedUiLibraryNote } from './snippets.js';
16
- import { configWithInstallSource, declaredInstallSource } from '../telemetry/install-source.js';
17
- import { devServerPortWarning, isLikelyDevServerPort } from '../cli/cli-port.js';
18
- // An app dev installs exactly the audience-scoped browser-side dependencies — never the retired
19
- // `@reticlehq/core` umbrella (which dragged the Node MCP server + ws into every app). The kit is the
20
- // framework adapter (it re-exports the browser sensor), paired with that framework's dev-only build
21
- // plugin for source mapping + connect injection.
22
- const RETICLE_REACT_KIT = '@reticlehq/react';
23
- /** The framework-neutral sensor, for stacks the React adapter has nothing to attach to. */
24
- const RETICLE_BROWSER_SDK = '@reticlehq/browser';
25
- const RETICLE_VITE_PLUGIN = '@reticlehq/vite-plugin';
26
- const RETICLE_NEXT_PLUGIN = '@reticlehq/next';
27
- /**
28
- * Pin the SDK to the CLI's own version.
29
- *
30
- * `pnpm add -D @reticlehq/react` installed **2.2.1** in one project while npm and yarn took 2.3.0 in
31
- * the next — a stale registry metadata cache, invisible to the user and to us. A version-skewed SDK
32
- * talking to a newer daemon is the `-32000` failure path: the app connects, the protocol disagrees,
33
- * and nothing on either side names a version. Asking for the CLI's exact version makes the cache
34
- * irrelevant, and a skewed pair impossible to install by accident.
35
- */
36
- function pinnedPackages(packages, version) {
37
- if (version === undefined || 0 === version.length)
38
- return packages;
39
- return packages.map((p) => `${p}@${version}`);
40
- }
41
- /**
42
- * Does this codebase want the React kit, or the framework-neutral sensor?
43
- *
44
- * The kit is what adds component identity — component names and stacks — and it is worth having
45
- * wherever React or Preact is rendering (the adapter reaches Preact through `preact/compat`).
46
- * Everywhere else it is a package named `@reticlehq/react`, carrying `react` in its peer
47
- * dependencies, being installed into a codebase that has no React in it.
48
- *
49
- * UNKNOWN keeps the kit deliberately. Absence of evidence is not evidence of Vue, and guessing
50
- * "sensor" on no information silently drops component identity from apps that should have it.
51
- */
52
- function wantsReactKit(ui) {
53
- return ui !== UiLibrary.VUE && ui !== UiLibrary.SVELTE;
54
- }
55
- /**
56
- * The dev-dependencies `reticle init` installs — kit (or sensor) first, build plugin next.
57
- *
58
- * `uiLibrary` matters because the framework does not always name the renderer. The rule below was
59
- * already written for Nuxt, correctly, and applied only there: a Vue app on plain Vite is
60
- * `Framework.VITE` and a SvelteKit app renders Svelte, and both were being handed the React kit
61
- * right after `init` had detected the real UI library and said so on screen.
62
- */
63
- export function frameworkPackages(framework, uiLibrary = UiLibrary.UNKNOWN) {
64
- const kit = wantsReactKit(uiLibrary) ? RETICLE_REACT_KIT : RETICLE_BROWSER_SDK;
65
- switch (framework) {
66
- case Framework.NEXT:
67
- // Next is React by construction, so the detection cannot disagree in a way worth honouring.
68
- return [RETICLE_REACT_KIT, RETICLE_NEXT_PLUGIN];
69
- case Framework.VITE:
70
- case Framework.SVELTEKIT:
71
- // SvelteKit builds on Vite; until a dedicated Svelte kit exists it uses the Vite build plugin.
72
- // The build plugin stamps `data-reticle-source` regardless of UI library, so a Vue or Svelte
73
- // app still gets source pointers — it is only component identity that needs the React kit.
74
- return [kit, RETICLE_VITE_PLUGIN];
75
- case Framework.NUXT:
76
- // The framework-neutral sensor, NOT the React kit. Nuxt renders Vue, and installing a package
77
- // named @reticlehq/react — with `react` in its peer dependencies — into a Vue codebase is the
78
- // single thing most likely to make someone abandon the setup, whether or not it works.
79
- return [RETICLE_BROWSER_SDK];
80
- case Framework.ASTRO:
81
- // Astro owns its own Vite instance and renders its own HTML, so there is no config for the
82
- // plugin to attach to — the kit alone, connected from a page <script> (see astroManual).
83
- return [kit];
84
- case Framework.CRA:
85
- // react-scripts owns its webpack config and cannot be extended without ejecting, so there is
86
- // no build plugin — the kit alone, imported from src/index.tsx (see cra.ts).
87
- return [RETICLE_REACT_KIT];
88
- case Framework.HTML:
89
- // No bundler plugin to install — just the kit; connect is wired by hand (see htmlManual).
90
- return [kit];
91
- }
92
- }
93
- /** Exported so the init telemetry can tell an MCP-registration failure from a dependency install. */
94
- export const MCP_TARGET = 'global (claude user scope)';
95
- /** The step that runs the package manager — the other thing that commonly fails on a user's machine. */
96
- export const DEPS_TARGET = 'package.json';
97
- export const RETICLE_CONFIG_FILE = '.reticle.json';
98
- export const StepStatus = {
99
- APPLY: 'apply',
100
- MANUAL: 'manual',
101
- ALREADY: 'already',
102
- SKIP: 'skip',
103
- /**
104
- * Something the user should KNOW, not something they must DO. The UNVERIFIED lines are the case:
105
- * a Preact or SvelteKit app is wired and working, it just isn't covered by a gate. Reporting those
106
- * as `manual` made "steps left to do" a number that could never reach zero, and made a release gate
107
- * read two regressions that were not regressions.
108
- */
109
- NOTICE: 'notice',
110
- };
111
- /**
112
- * Where the agent-facing files go, which is not always where the app is.
113
- *
114
- * Reported from the field (#318): a repo with its app at `src/admin` got `.claude/commands/reticle.md`
115
- * written into the app directory, while the human's agent session runs at the repo root — so
116
- * `/reticle` did not exist for them at all until they copied it up by hand. The rule and command
117
- * files are read by the AGENT, so they belong where the agent stands; the app files stay with the
118
- * app. The two are the same directory in a single-package repo, which is why this went unnoticed.
119
- */
120
- function agentFile(input, relPath) {
121
- const root = input.agentFileRoot;
122
- return root === undefined || 0 === root.length ? relPath : join(root, relPath);
123
- }
124
- const CLAUDE_MCP_TITLE = 'MCP server (Claude, global)';
125
- function claudeMcpStep(input) {
126
- if (!input.claudeCli)
127
- return null;
128
- if (input.mcpExists) {
129
- return {
130
- title: CLAUDE_MCP_TITLE,
131
- target: MCP_TARGET,
132
- status: StepStatus.ALREADY,
133
- detail: 'reticle already registered (install once, used by every project)',
134
- };
135
- }
136
- const cmd = claudeAddCommand();
137
- return {
138
- title: CLAUDE_MCP_TITLE,
139
- target: MCP_TARGET,
140
- status: StepStatus.APPLY,
141
- detail: 'register reticle globally for all projects',
142
- exec: { command: cmd.command, args: cmd.args, fallback: cmd.display },
143
- };
144
- }
145
- /**
146
- * One step per OTHER detected client.
147
- *
148
- * The shapes differ enough that a shared "write mcp.json" would be wrong for three of them — see
149
- * mcp-clients.ts. What is shared is the DECISION: already-correct is left alone, a file we cannot
150
- * parse is reported with a paste-able block rather than overwritten, and everything else is written.
151
- */
152
- function otherClientSteps(input) {
153
- const steps = [];
154
- for (const detected of input.detectedClients ?? []) {
155
- const spec = clientSpec(detected.id);
156
- const merged = mergeClientConfig(spec, detected.existing);
157
- const title = `MCP server (${spec.label})`;
158
- if (merged.status === ClientMergeStatus.ALREADY) {
159
- steps.push({
160
- title,
161
- target: detected.configPath,
162
- status: StepStatus.ALREADY,
163
- detail: `reticle already registered with ${spec.label}`,
164
- });
165
- continue;
166
- }
167
- if (merged.status === ClientMergeStatus.MANUAL) {
168
- // Either the file did not parse, or the format is one we refuse to edit blind (TOML). Both
169
- // end the same way: say so, and hand over the exact block.
170
- steps.push({
171
- title,
172
- target: detected.configPath,
173
- status: StepStatus.MANUAL,
174
- detail: `add this to ${detected.configPath} by hand:\n${clientSnippet(spec)}`,
175
- });
176
- continue;
177
- }
178
- steps.push({
179
- title,
180
- target: detected.configPath,
181
- status: StepStatus.APPLY,
182
- detail: `register reticle with ${spec.label}`,
183
- write: { path: detected.configPath, content: merged.content },
184
- });
185
- }
186
- return steps;
187
- }
188
- /** One global registration per detected agent (Claude + Cursor). Falls back to a manual note. */
189
- function mcpSteps(input) {
190
- if (!input.options.mcp) {
191
- return [
192
- {
193
- title: 'MCP server (global)',
194
- target: MCP_TARGET,
195
- status: StepStatus.SKIP,
196
- // Names everything it turns off. `--no-mcp` reads like "skip one step" and skips three: the
197
- // registration, the agent rule files, and the /reticle command. A gate running with this flag
198
- // therefore covers far less than its name suggests, which is worth saying out loud.
199
- detail: '--no-mcp — also skips the agent rule files (CLAUDE.md / AGENTS.md / .cursor) and the /reticle command',
200
- },
201
- ];
202
- }
203
- // Claude and Cursor first (they have their own registration paths), then every other detected
204
- // client. A machine with Cursor AND Windsurf gets both — registering only the first one found is
205
- // how a user ends up with Reticle in the editor they were not using.
206
- const steps = [...stepsForAgents(input, (a) => a.mcpStep), ...otherClientSteps(input)];
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
- };
234
- }
235
- const SLASH_COMMAND_TITLE = 'The /reticle command';
236
- /**
237
- * Nothing to do for this command file: it already holds the CURRENT body, or it is not ours at all.
238
- *
239
- * Gating on mere existence froze the command at whatever release wrote it. Rewriting anything found
240
- * there would be worse — a human may have claimed `/reticle` for their own prompt — so a file without
241
- * our signature is left exactly as it is.
242
- */
243
- function commandIsSettled(content) {
244
- if (null === content || content === undefined)
245
- return false;
246
- return content === SLASH_COMMAND_BODY || !content.includes(SLASH_COMMAND_SIGNATURE);
247
- }
248
- /**
249
- * `/reticle` — the entry point SKILL.md promises in three places and nothing ever created, so it
250
- * silently did nothing in every tool.
251
- *
252
- * CURRENT, not merely present — same reason as the Cursor rule: a command file frozen at whatever
253
- * release created it is a command that can never be improved for anyone who already ran init. The
254
- * whole file is Reticle's, so a stale one is rewritten.
255
- */
256
- function commandStepFor(path, present, content) {
257
- if (!present)
258
- return null;
259
- return commandIsSettled(content)
260
- ? {
261
- title: SLASH_COMMAND_TITLE,
262
- target: path,
263
- status: StepStatus.ALREADY,
264
- detail: 'command already exists',
265
- }
266
- : {
267
- title: SLASH_COMMAND_TITLE,
268
- target: path,
269
- status: StepStatus.APPLY,
270
- detail: 'type /reticle to verify one flow in the browser',
271
- write: { path, content: SLASH_COMMAND_BODY },
272
- };
273
- }
274
- function claudeCommandStep(input) {
275
- return commandStepFor(agentFile(input, CLAUDE_COMMAND_PATH), input.claudeCli, input.claudeCommandContent);
276
- }
277
- function cursorCommandStep(input) {
278
- const cursorGlobal = (input.detectedClients ?? []).some((c) => c.id === McpClient.CURSOR);
279
- const present = true === input.cursorProjectPresent || (cursorGlobal && !input.claudeCli);
280
- return commandStepFor(agentFile(input, CURSOR_COMMAND_PATH), present, input.cursorCommandContent);
281
- }
282
- const AGENT_RULE_TITLE = 'Agent verification rule';
283
- const AGENT_RULE_DETAIL = 'teach the agent to verify features with Reticle after building them';
284
- const RETICLE_MD_TITLE = 'Full agent rules';
285
- const RETICLE_MD_DETAIL = 'the reference the always-loaded rule points at (when NOT to verify, recovery, feedback)';
286
- function claudeRuleStep(input) {
287
- if (!input.claudeCli)
288
- return null;
289
- const path = agentFile(input, CLAUDE_MD_PATH);
290
- const r = mergeMarkedInstruction(input.claudeMdContent);
291
- if (r.status === AgentRuleStatus.ALREADY) {
292
- return {
293
- title: AGENT_RULE_TITLE,
294
- target: path,
295
- status: StepStatus.ALREADY,
296
- detail: 'Reticle rule already in CLAUDE.md',
297
- };
298
- }
299
- return {
300
- title: AGENT_RULE_TITLE,
301
- target: path,
302
- status: StepStatus.APPLY,
303
- detail: AGENT_RULE_DETAIL,
304
- write: { path, content: r.content },
305
- };
306
- }
307
- /**
308
- * The Cursor rule is a PROJECT file, so it is written only when Cursor plausibly works on THIS
309
- * project — the repo has a `.cursor/` dir, or Cursor is the only agent found. `~/.cursor` merely
310
- * existing on the machine meant every Claude Code user got an unexplained `.cursor/rules/reticle.mdc`
311
- * committed into their repo. (Global MCP registration is different: it is global, and stays.)
312
- */
313
- function cursorRuleStep(input) {
314
- const cursorGlobal = (input.detectedClients ?? []).some((c) => c.id === McpClient.CURSOR);
315
- if (!cursorGlobal && true !== input.cursorProjectPresent)
316
- return null;
317
- if (input.cursorProjectPresent !== true && input.claudeCli)
318
- return null;
319
- // The whole file is Reticle's — init created it — so a stale one is REWRITTEN rather than merged.
320
- // Comparing content is what makes the rule updatable; comparing existence made it permanent.
321
- const path = agentFile(input, CURSOR_RULE_PATH);
322
- if (input.cursorRuleContent === cursorRuleFile()) {
323
- return {
324
- title: AGENT_RULE_TITLE,
325
- target: path,
326
- status: StepStatus.ALREADY,
327
- detail: 'Reticle rule already in .cursor/rules',
328
- };
329
- }
330
- return {
331
- title: AGENT_RULE_TITLE,
332
- target: path,
333
- status: StepStatus.APPLY,
334
- detail: AGENT_RULE_DETAIL,
335
- write: { path, content: cursorRuleFile() },
336
- };
337
- }
338
- /**
339
- * Every coding agent `reticle init` knows how to wire itself into, and the three surfaces it wires:
340
- * the global MCP registration, the project rule file that makes the agent USE Reticle, and the
341
- * `/reticle` command.
342
- *
343
- * One list, because those three surfaces used to enumerate Claude and Cursor separately in three
344
- * places — so supporting a fourth agent meant finding all three and getting each right. Adding one
345
- * is now an entry here plus its builders; each builder answers null when that agent is not present
346
- * for this user or this project, which is also how "no agent detected" falls through to the
347
- * cross-agent AGENTS.md.
348
- *
349
- * Deliberately functions rather than data: registering with Claude runs its CLI while Cursor merges
350
- * a JSON file, and pretending those are the same shape would cost more than it saves.
351
- */
352
- const AgentId = {
353
- CLAUDE: 'claude',
354
- CURSOR: 'cursor',
355
- };
356
- const AGENT_INTEGRATIONS = [
357
- {
358
- id: AgentId.CLAUDE,
359
- mcpStep: claudeMcpStep,
360
- ruleStep: claudeRuleStep,
361
- commandStep: claudeCommandStep,
362
- },
363
- {
364
- id: AgentId.CURSOR,
365
- ruleStep: cursorRuleStep,
366
- commandStep: cursorCommandStep,
367
- },
368
- ];
369
- /** The steps one surface contributes across every known agent, in registry order. */
370
- function stepsForAgents(input, surface) {
371
- return AGENT_INTEGRATIONS.map((a) => surface(a)?.(input) ?? null).filter((s) => s !== null);
372
- }
373
- /** The `/reticle` command file for every agent that has a command surface and is present here. */
374
- function slashCommandSteps(input) {
375
- return stepsForAgents(input, (a) => a.commandStep);
376
- }
377
- /**
378
- * `AGENTS.md`, always. It is the file every agent that is not Claude or Cursor reads.
379
- *
380
- * This used to be a FALLBACK, written only when no agent was detected. So a repo set up on a machine
381
- * with Claude Code got `CLAUDE.md` and nothing else, and the next person to open it with Codex,
382
- * Copilot, Amp, Gemini or any other agent found a fully instrumented app whose rules were addressed
383
- * to somebody else's tool. The detection tells you which agent is running the install; it says
384
- * nothing about which agents will open the repository afterwards.
385
- */
386
- function agentsMdStep(input) {
387
- const r = mergeMarkedInstruction(input.agentsMdContent);
388
- const path = agentFile(input, AGENTS_MD_PATH);
389
- if (r.status === AgentRuleStatus.ALREADY) {
390
- return {
391
- title: AGENT_RULE_TITLE,
392
- target: path,
393
- status: StepStatus.ALREADY,
394
- detail: 'Reticle rule already in AGENTS.md',
395
- };
396
- }
397
- return {
398
- title: AGENT_RULE_TITLE,
399
- target: path,
400
- status: StepStatus.APPLY,
401
- detail: AGENT_RULE_DETAIL,
402
- write: { path, content: r.content },
403
- };
404
- }
405
- /**
406
- * `RETICLE.md`, the reference the always-loaded blocks point at.
407
- *
408
- * Written whole rather than merged, because `init` owns the entire file: there is no user content to
409
- * preserve, and the marker dance exists only for files somebody else already writes in.
410
- */
411
- function reticleMdStep(input) {
412
- const path = agentFile(input, RETICLE_MD_PATH);
413
- const content = reticleMdFile();
414
- if (input.reticleMdContent === content) {
415
- return {
416
- title: RETICLE_MD_TITLE,
417
- target: path,
418
- status: StepStatus.ALREADY,
419
- detail: 'full rules already current',
420
- };
421
- }
422
- return {
423
- title: RETICLE_MD_TITLE,
424
- target: path,
425
- status: StepStatus.APPLY,
426
- detail: RETICLE_MD_DETAIL,
427
- write: { path, content },
428
- };
429
- }
430
- /**
431
- * The behavioral rules that make the agent actually USE Reticle, and know when not to.
432
- *
433
- * Every detected agent's own file, plus `AGENTS.md` for the ones that will open this repo later, plus
434
- * `RETICLE.md` holding the reference half. Rides with the MCP wiring: `--no-mcp` opts out of
435
- * registering the tools AND of every rule file, because rules for tools the agent cannot reach are
436
- * noise.
437
- */
438
- function agentRuleSteps(input) {
439
- if (!input.options.mcp)
440
- return [];
441
- return [...stepsForAgents(input, (a) => a.ruleStep), agentsMdStep(input), reticleMdStep(input)];
442
- }
443
- /**
444
- * What to say when the install command fails.
445
- *
446
- * pnpm's `minimumReleaseAge` refuses any release younger than the configured window — a deliberate
447
- * supply-chain policy, not a bug — with `ERR_PNPM_NO_MATURE_MATCHING_VERSION`. Unpinned it silently
448
- * resolves to an OLDER version instead, which is how an app ends up running a 2.2.1 SDK against a
449
- * 2.3.0 daemon: the connection succeeds, the protocol disagrees, and the failure surfaces as -32000
450
- * with nothing naming a version. Pinning turns that into this loud failure, which is the better
451
- * trade — but only if the message says what to do about it.
452
- */
453
- /**
454
- * Said out loud when the exact-version install failed and the unpinned one worked.
455
- *
456
- * It used to assert a cause it cannot know. Every one of nine fixture apps got the same sentence —
457
- * "the registry refused 2.5.0 (pnpm's minimumReleaseAge holds new releases back)" — when the actual
458
- * cause on that run was that the version did not exist yet, and the remedy offered was a `pnpm
459
- * config` command handed to a yarn 1 project that will never read it.
460
- *
461
- * This note is built at PLAN time, before anything runs, and `io.exec` returns a bare boolean, so
462
- * the apply layer has no failure text to hand back either. The honest move is therefore to report
463
- * the CONSEQUENCE (which is certain and is the part that bites) and offer the remedy that belongs to
464
- * the manager actually in use — rather than name a cause that is one possibility among several.
465
- */
466
- function unpinnedRetryNote(version, pm) {
467
- const wanted = version === undefined ? 'the exact version' : version;
468
- // Kept verbatim for pnpm, where minimumReleaseAge is a real and common cause with a real remedy.
469
- const remedy = pm === PackageManager.PNPM
470
- ? ' One common cause on pnpm is minimumReleaseAge holding a new release back; if pnpm ' +
471
- 'reported ERR_PNPM_NO_MATURE_MATCHING_VERSION, either wait out the window or allow these ' +
472
- 'packages: pnpm config set minimumReleaseAgeExclude "@reticlehq/*"'
473
- : '';
474
- return (`the pinned install of ${wanted} failed, so the newest version the registry WOULD accept was ` +
475
- `installed instead. That may not match the daemon — if the agent reports protocol errors, check ` +
476
- `\`versionSkew\` in reticle_sessions.${remedy}`);
477
- }
478
- function installStep(input) {
479
- const pm = input.detection.packageManager;
480
- const packages = pinnedPackages(frameworkPackages(input.detection.framework, input.detection.uiLibrary), input.options.sdkVersion);
481
- const command = installCommand(pm, packages);
482
- if (!input.options.install) {
483
- return {
484
- title: 'Install dependencies',
485
- target: 'package.json',
486
- status: StepStatus.MANUAL,
487
- detail: command,
488
- };
489
- }
490
- const parts = installCommandParts(pm, packages);
491
- return {
492
- title: 'Install dependencies',
493
- target: 'package.json',
494
- status: StepStatus.APPLY,
495
- detail: command,
496
- exec: {
497
- command: parts.command,
498
- args: parts.args,
499
- fallback: `${command}\n\n${installFailureHint(pm)}`,
500
- },
501
- // Unpinned. pnpm resolves the newest MATURE version there, which is how a project with a
502
- // release-age hold gets a working install instead of no install.
503
- retry: {
504
- ...installCommandParts(pm, frameworkPackages(input.detection.framework, input.detection.uiLibrary)),
505
- note: unpinnedRetryNote(input.options.sdkVersion, pm),
506
- },
507
- };
508
- }
509
- /**
510
- * What is wrong with the config that is already there, if anything.
511
- *
512
- * Reported from the field (#317): a project carried `"port": 3000` — its own dev-server port, which
513
- * is the confusion SKILL.md names as the top setup failure — and `init` printed `.reticle.json
514
- * already exists` on every re-run without reading a single field of it, so the file could never be
515
- * repaired by the command that wrote it. It stayed invisible because a daemon on `127.0.0.1:3000`
516
- * and Vite on `[::1]:3000` split the port by address family and neither reported a conflict.
517
- *
518
- * Narrower than the issue asked for on purpose: `init`'s IO surface is synchronous, so this cannot
519
- * probe what is LISTENING right now. `isLikelyDevServerPort` covers the framework defaults, which is
520
- * where the mistake is actually made.
521
- */
522
- function existingConfigProblem(source) {
523
- if (null === source || source === undefined)
524
- return undefined;
525
- let parsed;
526
- try {
527
- parsed = JSON.parse(source);
528
- }
529
- catch {
530
- return (`${RETICLE_CONFIG_FILE} is present but is not valid JSON, so nothing reads it — neither the ` +
531
- 'daemon nor the SDK. Delete it and re-run `reticle init`.');
532
- }
533
- if ('object' !== typeof parsed || null === parsed)
534
- return undefined;
535
- const port = parsed['port'];
536
- if ('number' !== typeof port || !isLikelyDevServerPort(port))
537
- return undefined;
538
- return `${devServerPortWarning(port)} Fix it by removing the "port" field from ${RETICLE_CONFIG_FILE}.`;
539
- }
540
- const RETICLE_CONFIG_TITLE = 'Reticle config';
541
- const AGENT_ROOT_CONFIG_TITLE = 'Reticle config (agent root)';
542
- /**
543
- * The SECOND `.reticle.json`, in the directory the agent runs from.
544
- *
545
- * `.reticle.json` is not app wiring — nothing in the app reads it. The CLI and `reticle mcp` read it
546
- * from their own CWD (see cli-port), and that CWD is the repo root, not the app directory a redirect
547
- * wired. Reported from the field: an app in `frontend/` on a non-default bridge port left the root
548
- * with no config at all, so `reticle mcp` fell back to 4400 — which on that machine was ANOTHER
549
- * project's daemon, and `reticle_sessions` would have listed a different app's tabs while the wired
550
- * app sat unseen. Nothing in the report said so; every step was green.
551
- *
552
- * Written in BOTH places rather than moved: a human standing in the app runs `reticle status` there,
553
- * and the two files are byte-identical, so neither can disagree with the other about the port or the
554
- * project identity.
555
- */
556
- function agentRootConfigStep(input, content) {
557
- const root = input.agentFileRoot;
558
- if (root === undefined || 0 === root.length)
559
- return [];
560
- const path = agentFile(input, RETICLE_CONFIG_FILE);
561
- if (input.agentRootConfigSource === content) {
562
- return [
563
- {
564
- title: AGENT_ROOT_CONFIG_TITLE,
565
- target: path,
566
- status: StepStatus.ALREADY,
567
- detail: 'the agent already reads the same project config',
568
- },
569
- ];
570
- }
571
- return [
572
- {
573
- title: AGENT_ROOT_CONFIG_TITLE,
574
- target: path,
575
- status: StepStatus.APPLY,
576
- detail: 'the same config where the agent runs — `reticle mcp` reads it from ITS cwd, and without ' +
577
- 'it the agent talks to whatever daemon is on the default port',
578
- write: { path, content },
579
- },
580
- ];
581
- }
582
- function reticleConfigStep(input, content) {
583
- if (true === input.reticleConfigExists) {
584
- const problem = existingConfigProblem(input.reticleConfigSource);
585
- if (problem !== undefined) {
586
- // `ℹ`, not `·`: the step is done and something about the result still stops things working,
587
- // which is the one mark that says "there is something here to read".
588
- return {
589
- title: RETICLE_CONFIG_TITLE,
590
- target: RETICLE_CONFIG_FILE,
591
- status: StepStatus.NOTICE,
592
- detail: problem,
593
- };
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
- }
607
- return {
608
- title: RETICLE_CONFIG_TITLE,
609
- target: RETICLE_CONFIG_FILE,
610
- status: StepStatus.ALREADY,
611
- detail: '.reticle.json already exists',
612
- };
613
- }
614
- return {
615
- title: RETICLE_CONFIG_TITLE,
616
- target: RETICLE_CONFIG_FILE,
617
- status: StepStatus.APPLY,
618
- detail: 'write project config (framework + port)',
619
- write: { path: RETICLE_CONFIG_FILE, content },
620
- };
621
- }
622
- /**
623
- * The project config, in every directory that has to read it: the app's, and — after a redirect —
624
- * the one the agent runs from. One content string for both, so they cannot disagree; an existing
625
- * app-side config wins over a freshly derived one, or a re-run would copy a DIFFERENT identity up.
626
- */
627
- function reticleConfigSteps(input) {
628
- const existing = input.reticleConfigSource;
629
- const content = true === input.reticleConfigExists && null !== existing && existing !== undefined
630
- ? existing
631
- : reticleConfigContent(input.detection.framework, input.options.port, input.options.projectId,
632
- // Only when it is actually known. Writing `unknown` would be indistinguishable from a
633
- // config written before this field existed, and the two mean different things.
634
- declaredInstallSource());
635
- return [reticleConfigStep(input, content), ...agentRootConfigStep(input, content)];
636
- }
637
- /**
638
- * A step that says out loud when the app isn't React. SvelteKit already carries its own unverified
639
- * note, so it isn't doubled up here.
640
- */
641
- function uiLibraryStep(input) {
642
- const lib = input.detection.uiLibrary;
643
- // Nuxt and SvelteKit each carry their own unverified wording inside the recipe, so a second,
644
- // more generic notice beside it would only argue with the specific one.
645
- const framework = input.detection.framework;
646
- if (lib === UiLibrary.REACT ||
647
- framework === Framework.SVELTEKIT ||
648
- framework === Framework.NUXT) {
649
- return [];
650
- }
651
- if (lib === UiLibrary.UNKNOWN)
652
- return [];
653
- return [
654
- {
655
- title: `${lib} is UNVERIFIED`,
656
- target: 'package.json',
657
- status: StepStatus.NOTICE,
658
- detail: unverifiedUiLibraryNote(lib),
659
- },
660
- ];
661
- }
662
- export function buildPlan(input) {
663
- const steps = [
664
- ...cspStep(input),
665
- ...mcpSteps(input),
666
- ...agentRuleSteps(input),
667
- ...slashCommandSteps(input),
668
- ...uiLibraryStep(input),
669
- installStep(input),
670
- ...reticleConfigSteps(input),
671
- ];
672
- if (input.detection.framework === Framework.VITE) {
673
- steps.push(...viteSteps(input));
674
- }
675
- else if (input.detection.framework === Framework.NEXT) {
676
- steps.push(...nextSteps(input));
677
- }
678
- else if (input.detection.framework === Framework.ASTRO) {
679
- steps.push(...astroSteps(input));
680
- }
681
- else if (input.detection.framework === Framework.CRA) {
682
- steps.push(...craSteps(input));
683
- }
684
- else if (input.detection.framework === Framework.NUXT) {
685
- steps.push(...nuxtSteps(input));
686
- }
687
- else if (input.detection.framework === Framework.SVELTEKIT) {
688
- steps.push(...svelteKitSteps(input));
689
- // The Vite plugin as well as the client hook. `init` already INSTALLS @reticlehq/vite-plugin for
690
- // SvelteKit and then never wired it into the config, so it sat in package.json doing nothing —
691
- // which is why a SvelteKit app connected fine and every verdict came back with no file:line.
692
- steps.push(...viteSteps(input, VITE_PLUGIN_DETAIL.SVELTEKIT));
693
- }
694
- else {
695
- steps.push({
696
- title: 'Connect snippet',
697
- target: 'index.html',
698
- status: StepStatus.MANUAL,
699
- detail: htmlManual(input.options.port, input.options.projectId, input.pairingToken),
700
- });
701
- }
702
- return { framework: input.detection.framework, uiLibrary: input.detection.uiLibrary, steps };
703
- }