@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.
Files changed (513) hide show
  1. package/SKILL.md +93 -111
  2. package/dist/bridge/auth-failure-reason.d.ts +6 -2
  3. package/dist/bridge/auth-failure-reason.js +15 -8
  4. package/dist/bridge/bridge.d.ts +18 -14
  5. package/dist/bridge/bridge.js +248 -165
  6. package/dist/bridge/bridge.test-harness.d.ts +2 -0
  7. package/dist/bridge/bridge.test-harness.js +8 -1
  8. package/dist/bridge/pairing-token.d.ts +5 -0
  9. package/dist/bridge/pairing-token.js +28 -0
  10. package/dist/bridge/protocol-skew.d.ts +37 -0
  11. package/dist/bridge/protocol-skew.js +45 -0
  12. package/dist/capsule/capsule-store.d.ts +8 -7
  13. package/dist/capsule/capsule-store.js +1 -1
  14. package/dist/capsule/causal-summary.d.ts +2 -2
  15. package/dist/capsule/causal-summary.js +7 -2
  16. package/dist/chromium-launch-options.d.ts +28 -0
  17. package/dist/chromium-launch-options.js +29 -0
  18. package/dist/cli/cli-doctor.js +39 -1
  19. package/dist/cli/cli-flow-commands.d.ts +3 -1
  20. package/dist/cli/cli-flow-commands.js +34 -4
  21. package/dist/cli/cli-kill.d.ts +2 -1
  22. package/dist/cli/cli-launch.d.ts +11 -1
  23. package/dist/cli/cli-launch.js +59 -10
  24. package/dist/cli/cli-parse.d.ts +17 -1
  25. package/dist/cli/cli-parse.js +238 -12
  26. package/dist/cli/cli-update-commands.js +20 -1
  27. package/dist/cli/cli-verify.d.ts +2 -1
  28. package/dist/cli/cli-verify.js +5 -4
  29. package/dist/cli/cloud-cli.js +428 -253
  30. package/dist/cli/cloud-keystore.d.ts +37 -0
  31. package/dist/cli/cloud-keystore.js +97 -0
  32. package/dist/cli/cloud-kit.d.ts +37 -0
  33. package/dist/cli/cloud-kit.js +121 -0
  34. package/dist/cli/cloud-login.d.ts +17 -0
  35. package/dist/cli/cloud-login.js +183 -0
  36. package/dist/cli/cloud-session.d.ts +48 -0
  37. package/dist/cli/cloud-session.js +53 -0
  38. package/dist/cli/config-discovery.d.ts +2 -1
  39. package/dist/cli/config-discovery.js +1 -0
  40. package/dist/cli/daemon-start-options.d.ts +32 -0
  41. package/dist/cli/daemon-start-options.js +38 -0
  42. package/dist/cli/device-flow.d.ts +76 -0
  43. package/dist/cli/device-flow.js +56 -0
  44. package/dist/cli/doctor-rows.d.ts +12 -1
  45. package/dist/cli/doctor-rows.js +12 -1
  46. package/dist/cli/drive-attach.d.ts +13 -0
  47. package/dist/cli/drive-attach.js +18 -0
  48. package/dist/cli/drive-command.js +7 -3
  49. package/dist/cli/gate-exit.d.ts +21 -0
  50. package/dist/cli/gate-exit.js +21 -0
  51. package/dist/cli/gate-hook-message.d.ts +33 -0
  52. package/dist/cli/gate-hook-message.js +46 -0
  53. package/dist/cli/mcp-command.d.ts +25 -0
  54. package/dist/cli/mcp-command.js +174 -0
  55. package/dist/cli/project-name.d.ts +30 -0
  56. package/dist/cli/project-name.js +44 -0
  57. package/dist/cli/sibling-ports.d.ts +37 -0
  58. package/dist/cli/sibling-ports.js +56 -0
  59. package/dist/cli/status-next-action.d.ts +14 -0
  60. package/dist/cli/status-next-action.js +4 -4
  61. package/dist/cli.d.ts +1 -0
  62. package/dist/cli.js +167 -186
  63. package/dist/cloud/cloud-config.d.ts +24 -2
  64. package/dist/cloud/cloud-config.js +64 -5
  65. package/dist/cloud/cloud-sync.d.ts +16 -5
  66. package/dist/cloud/cloud-sync.js +64 -1
  67. package/dist/cloud/sync-cycle.d.ts +110 -0
  68. package/dist/cloud/sync-cycle.js +270 -0
  69. package/dist/cloud/sync-daemon.d.ts +69 -0
  70. package/dist/cloud/sync-daemon.js +260 -0
  71. package/dist/cloud/sync-disk.d.ts +9 -0
  72. package/dist/cloud/sync-disk.js +191 -0
  73. package/dist/cloud/sync-hash.d.ts +2 -0
  74. package/dist/cloud/sync-hash.js +35 -0
  75. package/dist/crawl/crawl-tools.js +5 -3
  76. package/dist/crawl/crawl.d.ts +12 -13
  77. package/dist/crawl/crawl.js +25 -3
  78. package/dist/daemon/daemon-resolve.d.ts +122 -0
  79. package/dist/daemon/daemon-resolve.js +187 -0
  80. package/dist/daemon/dev-servers.d.ts +15 -0
  81. package/dist/daemon/dev-servers.js +68 -0
  82. package/dist/daemon/free-port.d.ts +29 -0
  83. package/dist/daemon/free-port.js +55 -0
  84. package/dist/daemon/heartbeat.d.ts +0 -4
  85. package/dist/daemon/heartbeat.js +2 -2
  86. package/dist/daemon/wake-decision.d.ts +32 -0
  87. package/dist/daemon/wake-decision.js +38 -0
  88. package/dist/dev/stale-issue-guard.d.ts +0 -2
  89. package/dist/dev/stale-issue-guard.js +1 -1
  90. package/dist/domain/domain-tools.js +2 -2
  91. package/dist/events/contradictions.d.ts +59 -0
  92. package/dist/events/contradictions.js +253 -27
  93. package/dist/events/declared.d.ts +17 -0
  94. package/dist/events/declared.js +43 -1
  95. package/dist/events/echo-mismatch.js +65 -1
  96. package/dist/events/event-filters.d.ts +8 -0
  97. package/dist/events/event-filters.js +19 -2
  98. package/dist/events/observed-in-window.d.ts +12 -0
  99. package/dist/events/observed-in-window.js +17 -0
  100. package/dist/events/predicate-asks.d.ts +13 -0
  101. package/dist/events/predicate-asks.js +22 -0
  102. package/dist/events/predicate-eval.js +117 -27
  103. package/dist/events/predicate-parse.d.ts +0 -6
  104. package/dist/events/predicate-parse.js +43 -3
  105. package/dist/events/predicate-precheck.d.ts +8 -0
  106. package/dist/events/predicate-precheck.js +41 -0
  107. package/dist/events/predicate-route.d.ts +14 -0
  108. package/dist/events/predicate-route.js +36 -8
  109. package/dist/events/predicate-schema.d.ts +44 -0
  110. package/dist/events/predicate-schema.js +126 -23
  111. package/dist/events/predicate.d.ts +20 -0
  112. package/dist/events/predicate.js +77 -6
  113. package/dist/events/split-text-miss.d.ts +30 -0
  114. package/dist/events/split-text-miss.js +44 -0
  115. package/dist/flows/coverage.d.ts +0 -8
  116. package/dist/flows/coverage.js +1 -1
  117. package/dist/flows/decision.d.ts +5 -1
  118. package/dist/flows/decision.js +33 -7
  119. package/dist/flows/flake.d.ts +6 -8
  120. package/dist/flows/flake.js +1 -1
  121. package/dist/flows/flow-intent.d.ts +52 -0
  122. package/dist/flows/flow-intent.js +123 -0
  123. package/dist/flows/flow-memory-consult.d.ts +55 -0
  124. package/dist/flows/flow-memory-consult.js +38 -0
  125. package/dist/flows/flow-replay-run.d.ts +18 -7
  126. package/dist/flows/flow-replay-run.js +263 -23
  127. package/dist/flows/flow-replay.js +11 -2
  128. package/dist/flows/flow-step-runners.d.ts +8 -0
  129. package/dist/flows/flow-step-runners.js +8 -2
  130. package/dist/flows/flow-store-for-session.d.ts +31 -0
  131. package/dist/flows/flow-store-for-session.js +33 -0
  132. package/dist/flows/flow-success.js +15 -3
  133. package/dist/flows/flow-tools.js +87 -33
  134. package/dist/flows/flows.d.ts +14 -1
  135. package/dist/flows/flows.js +502 -24
  136. package/dist/flows/heal-run.js +5 -2
  137. package/dist/flows/predicate-to-expect.d.ts +17 -12
  138. package/dist/flows/predicate-to-expect.js +36 -15
  139. package/dist/flows/recordings.d.ts +13 -1
  140. package/dist/flows/recordings.js +17 -2
  141. package/dist/flows/replay.d.ts +22 -2
  142. package/dist/flows/replay.js +28 -2
  143. package/dist/flows/server-verify.js +16 -2
  144. package/dist/flows/verify-change-tools.js +9 -3
  145. package/dist/honesty/blind-spots.d.ts +51 -15
  146. package/dist/honesty/blind-spots.js +64 -4
  147. package/dist/honesty/feature-capture.d.ts +150 -0
  148. package/dist/honesty/feature-capture.js +233 -0
  149. package/dist/honesty/honesty.d.ts +24 -0
  150. package/dist/honesty/honesty.js +25 -1
  151. package/dist/honesty/instrumentation-gaps.d.ts +39 -6
  152. package/dist/honesty/instrumentation-gaps.js +88 -5
  153. package/dist/honesty/tool-hit-rate.d.ts +86 -0
  154. package/dist/honesty/tool-hit-rate.js +90 -0
  155. package/dist/honesty/undeclared-change.d.ts +51 -0
  156. package/dist/honesty/undeclared-change.js +56 -0
  157. package/dist/honesty/verified.d.ts +16 -0
  158. package/dist/honesty/verified.js +84 -5
  159. package/dist/http-server.d.ts +0 -1
  160. package/dist/http-server.js +13 -1
  161. package/dist/hunt/hunt-report.d.ts +0 -2
  162. package/dist/hunt/hunt-report.js +1 -1
  163. package/dist/impact/impact-recorder.d.ts +31 -8
  164. package/dist/impact/impact-recorder.js +104 -21
  165. package/dist/impact/impact-store.d.ts +13 -4
  166. package/dist/impact/impact-store.js +44 -3
  167. package/dist/index.d.ts +4 -1
  168. package/dist/index.js +113 -7
  169. package/dist/init/agent-rules.d.ts +30 -6
  170. package/dist/init/agent-rules.js +54 -13
  171. package/dist/init/astro-patch.d.ts +16 -0
  172. package/dist/init/astro-patch.js +28 -0
  173. package/dist/init/capabilities.d.ts +4 -3
  174. package/dist/init/capabilities.js +23 -3
  175. package/dist/init/closing-hint.d.ts +36 -0
  176. package/dist/init/closing-hint.js +120 -0
  177. package/dist/init/confirm.d.ts +27 -28
  178. package/dist/init/confirm.js +51 -11
  179. package/dist/init/cra.d.ts +34 -5
  180. package/dist/init/cra.js +96 -25
  181. package/dist/init/csp-check.js +17 -2
  182. package/dist/init/csp-doctor.d.ts +8 -1
  183. package/dist/init/csp-doctor.js +8 -3
  184. package/dist/init/dev-script.d.ts +50 -0
  185. package/dist/init/dev-script.js +66 -0
  186. package/dist/init/format-generated.d.ts +18 -0
  187. package/dist/init/format-generated.js +39 -0
  188. package/dist/init/install-hint.d.ts +9 -0
  189. package/dist/init/install-hint.js +29 -0
  190. package/dist/init/mcp-clients.d.ts +7 -0
  191. package/dist/init/mcp-clients.js +7 -0
  192. package/dist/init/mcp.d.ts +17 -6
  193. package/dist/init/mcp.js +27 -11
  194. package/dist/init/node-io.js +11 -1
  195. package/dist/init/plan-framework.d.ts +0 -5
  196. package/dist/init/plan-framework.js +147 -37
  197. package/dist/init/plan.d.ts +30 -37
  198. package/dist/init/plan.js +50 -60
  199. package/dist/init/preflight.d.ts +28 -0
  200. package/dist/init/preflight.js +38 -0
  201. package/dist/init/refresh-rules.d.ts +39 -0
  202. package/dist/init/refresh-rules.js +51 -0
  203. package/dist/init/run.d.ts +32 -35
  204. package/dist/init/run.js +151 -202
  205. package/dist/init/slash-command.d.ts +1 -1
  206. package/dist/init/snippets.js +90 -31
  207. package/dist/init/vite-config.d.ts +1 -1
  208. package/dist/init/vite-config.js +39 -25
  209. package/dist/init/workspace-apps.d.ts +17 -10
  210. package/dist/init/workspace-apps.js +110 -0
  211. package/dist/input/network-mock-tools.js +3 -6
  212. package/dist/input/real-input.d.ts +2 -0
  213. package/dist/input/real-input.js +28 -7
  214. package/dist/input/scroll-find.d.ts +7 -4
  215. package/dist/input/scroll-find.js +63 -25
  216. package/dist/input/scroll-tools.js +4 -6
  217. package/dist/input/viewport-tools.js +5 -4
  218. package/dist/intent/inline-intent.d.ts +37 -0
  219. package/dist/intent/inline-intent.js +193 -0
  220. package/dist/intent/intent-shard-store.d.ts +72 -0
  221. package/dist/intent/intent-shard-store.js +203 -0
  222. package/dist/intent/intent-shard.d.ts +411 -0
  223. package/dist/intent/intent-shard.js +176 -0
  224. package/dist/intent/intent-store.d.ts +49 -0
  225. package/dist/intent/intent-store.js +133 -0
  226. package/dist/intent/intent-subject.d.ts +45 -0
  227. package/dist/intent/intent-subject.js +177 -0
  228. package/dist/intent/intent-tools.d.ts +2 -0
  229. package/dist/intent/intent-tools.js +143 -0
  230. package/dist/intent/open-intents.d.ts +42 -0
  231. package/dist/intent/open-intents.js +40 -0
  232. package/dist/journal/envelope.d.ts +26 -26
  233. package/dist/journal/journal-recorder.d.ts +23 -0
  234. package/dist/journal/journal-recorder.js +35 -0
  235. package/dist/license/license-env.d.ts +29 -0
  236. package/dist/license/license-env.js +148 -0
  237. package/dist/loopback-agent.d.ts +31 -0
  238. package/dist/loopback-agent.js +57 -0
  239. package/dist/mcp/attach-memory.d.ts +83 -0
  240. package/dist/mcp/attach-memory.js +185 -0
  241. package/dist/mcp/client-identity.d.ts +31 -0
  242. package/dist/mcp/client-identity.js +51 -0
  243. package/dist/mcp/mcp-post-transport.d.ts +26 -0
  244. package/dist/mcp/mcp-post-transport.js +109 -0
  245. package/dist/mcp/mcp-proxy.d.ts +2 -8
  246. package/dist/mcp/mcp-proxy.js +64 -62
  247. package/dist/mcp/mcp.d.ts +2 -0
  248. package/dist/mcp/mcp.js +52 -24
  249. package/dist/mcp/proxy-backoff.d.ts +11 -0
  250. package/dist/mcp/proxy-backoff.js +13 -0
  251. package/dist/mcp/proxy-daemon-probe.d.ts +1 -0
  252. package/dist/mcp/proxy-daemon-probe.js +7 -1
  253. package/dist/mcp/proxy-handshake.d.ts +23 -0
  254. package/dist/mcp/proxy-handshake.js +31 -0
  255. package/dist/mcp/server-instructions.js +45 -3
  256. package/dist/mcp/tool-catalog-cache.d.ts +16 -0
  257. package/dist/mcp/tool-catalog-cache.js +22 -0
  258. package/dist/memory/memory-tools.d.ts +2 -0
  259. package/dist/memory/memory-tools.js +82 -0
  260. package/dist/memory/project-memory.d.ts +34 -0
  261. package/dist/memory/project-memory.js +96 -0
  262. package/dist/oracles/flow-instrument-gaps.d.ts +4 -4
  263. package/dist/oracles/flow-instrument-gaps.js +4 -5
  264. package/dist/oracles/propose-consequences.js +12 -3
  265. package/dist/oracles/self-instrument.d.ts +9 -9
  266. package/dist/oracles/self-instrument.js +19 -13
  267. package/dist/pool/browser-pool.d.ts +75 -5
  268. package/dist/pool/browser-pool.js +144 -5
  269. package/dist/pool/playwright-launcher.js +12 -1
  270. package/dist/project/fs-port.d.ts +3 -0
  271. package/dist/project/fs-port.js +3 -2
  272. package/dist/project/memory-fs.js +6 -1
  273. package/dist/project/project-tools.js +6 -35
  274. package/dist/project/reticle-dir.d.ts +17 -2
  275. package/dist/project/reticle-dir.js +22 -4
  276. package/dist/runs/context-tools.d.ts +2 -0
  277. package/dist/runs/context-tools.js +89 -0
  278. package/dist/runs/run-context.d.ts +40 -0
  279. package/dist/runs/run-context.js +158 -0
  280. package/dist/runs/run-diff.d.ts +2 -1
  281. package/dist/runs/run-store.d.ts +10 -0
  282. package/dist/runs/run-store.js +10 -0
  283. package/dist/runs/verification-sync.d.ts +0 -11
  284. package/dist/runs/verification-sync.js +24 -3
  285. package/dist/runs/verify-server.d.ts +8 -1
  286. package/dist/runs/verify-server.js +14 -2
  287. package/dist/session/command-timeout.d.ts +5 -2
  288. package/dist/session/command-timeout.js +5 -4
  289. package/dist/session/dev-server-probe.d.ts +0 -8
  290. package/dist/session/dev-server-probe.js +1 -1
  291. package/dist/session/last-act.d.ts +7 -1
  292. package/dist/session/last-act.js +2 -2
  293. package/dist/session/lease-visibility.d.ts +67 -0
  294. package/dist/session/lease-visibility.js +76 -0
  295. package/dist/session/live-control-tools.js +1 -42
  296. package/dist/session/no-session-diagnosis.d.ts +33 -0
  297. package/dist/session/no-session-diagnosis.js +82 -24
  298. package/dist/session/no-session-next-action.d.ts +12 -0
  299. package/dist/session/no-session-next-action.js +77 -6
  300. package/dist/session/no-session-watch.d.ts +18 -6
  301. package/dist/session/no-session-watch.js +125 -75
  302. package/dist/session/output-budget.js +4 -1
  303. package/dist/session/pending-commands.d.ts +11 -1
  304. package/dist/session/pending-commands.js +12 -2
  305. package/dist/session/resolve-within.d.ts +34 -0
  306. package/dist/session/resolve-within.js +53 -0
  307. package/dist/session/session-health.d.ts +9 -0
  308. package/dist/session/session-health.js +23 -0
  309. package/dist/session/session-info.d.ts +18 -0
  310. package/dist/session/session-info.js +11 -0
  311. package/dist/session/session-manager.d.ts +14 -0
  312. package/dist/session/session-manager.js +111 -4
  313. package/dist/session/session-mirror.d.ts +16 -0
  314. package/dist/session/session-mirror.js +22 -0
  315. package/dist/session/session-recommendation.d.ts +19 -5
  316. package/dist/session/session-recommendation.js +25 -9
  317. package/dist/session/session-successor.d.ts +37 -0
  318. package/dist/session/session-successor.js +113 -0
  319. package/dist/session/session-tools.js +2 -2
  320. package/dist/session/session.d.ts +53 -3
  321. package/dist/session/session.js +162 -9
  322. package/dist/session/wall-clock.d.ts +12 -0
  323. package/dist/session/wall-clock.js +14 -0
  324. package/dist/setup/agent-configs.d.ts +96 -0
  325. package/dist/setup/agent-configs.js +333 -0
  326. package/dist/setup/agent-io.d.ts +9 -0
  327. package/dist/setup/agent-io.js +16 -0
  328. package/dist/setup/agent-writer.d.ts +51 -0
  329. package/dist/setup/agent-writer.js +115 -0
  330. package/dist/setup/approval-migration.d.ts +47 -0
  331. package/dist/setup/approval-migration.js +68 -0
  332. package/dist/setup/auto-approve.d.ts +85 -0
  333. package/dist/setup/auto-approve.js +150 -0
  334. package/dist/setup/bridge-port.d.ts +15 -0
  335. package/dist/setup/bridge-port.js +24 -0
  336. package/dist/setup/desktop-shape.d.ts +57 -0
  337. package/dist/setup/desktop-shape.js +63 -0
  338. package/dist/setup/dev-server-wait.d.ts +60 -0
  339. package/dist/setup/dev-server-wait.js +65 -0
  340. package/dist/setup/drive-agent.d.ts +71 -0
  341. package/dist/setup/drive-agent.js +171 -0
  342. package/dist/setup/drive-plan.d.ts +68 -0
  343. package/dist/setup/drive-plan.js +130 -0
  344. package/dist/setup/ensure-daemon.d.ts +29 -0
  345. package/dist/setup/ensure-daemon.js +58 -0
  346. package/dist/setup/init-runtime.d.ts +47 -0
  347. package/dist/setup/init-runtime.js +160 -0
  348. package/dist/setup/interrupt.d.ts +25 -0
  349. package/dist/setup/interrupt.js +40 -0
  350. package/dist/setup/license-key.d.ts +39 -0
  351. package/dist/setup/license-key.js +72 -0
  352. package/dist/setup/listeners.d.ts +37 -0
  353. package/dist/setup/listeners.js +85 -0
  354. package/dist/setup/node-effects.d.ts +60 -0
  355. package/dist/setup/node-effects.js +210 -0
  356. package/dist/setup/page-probe.d.ts +39 -0
  357. package/dist/setup/page-probe.js +49 -0
  358. package/dist/setup/relaunch.d.ts +36 -0
  359. package/dist/setup/relaunch.js +57 -0
  360. package/dist/setup/remaining-steps.d.ts +19 -0
  361. package/dist/setup/remaining-steps.js +31 -0
  362. package/dist/setup/run-setup.d.ts +99 -0
  363. package/dist/setup/run-setup.js +187 -0
  364. package/dist/setup/session-pick.d.ts +47 -0
  365. package/dist/setup/session-pick.js +51 -0
  366. package/dist/setup/setup-command.d.ts +45 -0
  367. package/dist/setup/setup-command.js +199 -0
  368. package/dist/setup/setup-options.d.ts +74 -0
  369. package/dist/setup/setup-options.js +67 -0
  370. package/dist/setup/transcripts.d.ts +16 -0
  371. package/dist/setup/transcripts.js +43 -0
  372. package/dist/status-payload.d.ts +14 -1
  373. package/dist/status-payload.js +23 -1
  374. package/dist/telemetry/automation-hint.d.ts +2 -1
  375. package/dist/telemetry/daemon-telemetry.d.ts +8 -1
  376. package/dist/telemetry/daemon-telemetry.js +52 -5
  377. package/dist/telemetry/error-class.js +1 -1
  378. package/dist/telemetry/feedback-context.d.ts +9 -1
  379. package/dist/telemetry/feedback-context.js +60 -29
  380. package/dist/telemetry/feedback-local.d.ts +15 -0
  381. package/dist/telemetry/feedback-local.js +56 -0
  382. package/dist/telemetry/feedback-outbox.d.ts +2 -1
  383. package/dist/telemetry/feedback.d.ts +11 -0
  384. package/dist/telemetry/feedback.js +19 -6
  385. package/dist/telemetry/init-telemetry.d.ts +2 -0
  386. package/dist/telemetry/init-telemetry.js +2 -0
  387. package/dist/telemetry/install-source.d.ts +14 -0
  388. package/dist/telemetry/install-source.js +30 -0
  389. package/dist/telemetry/license-activation.d.ts +7 -1
  390. package/dist/telemetry/license-activation.js +9 -5
  391. package/dist/telemetry/mcp-connection.js +7 -0
  392. package/dist/telemetry/project-profile.d.ts +12 -9
  393. package/dist/telemetry/project-profile.js +12 -7
  394. package/dist/telemetry/proxy-telemetry.d.ts +3 -0
  395. package/dist/telemetry/proxy-telemetry.js +21 -0
  396. package/dist/telemetry/run-telemetry.d.ts +0 -2
  397. package/dist/telemetry/run-telemetry.js +1 -1
  398. package/dist/telemetry/session-metrics.d.ts +12 -0
  399. package/dist/telemetry/session-metrics.js +35 -1
  400. package/dist/telemetry/telemetry.js +17 -2
  401. package/dist/telemetry/tool-refused.d.ts +3 -1
  402. package/dist/telemetry/tool-refused.js +34 -2
  403. package/dist/telemetry/verification-of.js +2 -2
  404. package/dist/tools/act-capsule.d.ts +10 -0
  405. package/dist/tools/act-capsule.js +8 -2
  406. package/dist/tools/act-danger.d.ts +2 -1
  407. package/dist/tools/act-danger.js +11 -3
  408. package/dist/tools/act-observation.d.ts +41 -0
  409. package/dist/tools/act-observation.js +36 -0
  410. package/dist/tools/act-preflight.d.ts +20 -0
  411. package/dist/tools/act-preflight.js +98 -0
  412. package/dist/tools/act-sequence-retry.d.ts +45 -0
  413. package/dist/tools/act-sequence-retry.js +58 -0
  414. package/dist/tools/act-sequence-tool.d.ts +13 -0
  415. package/dist/tools/act-sequence-tool.js +135 -0
  416. package/dist/tools/act-target.d.ts +14 -0
  417. package/dist/tools/act-target.js +47 -0
  418. package/dist/tools/act-tools.d.ts +21 -1
  419. package/dist/tools/act-tools.js +196 -204
  420. package/dist/tools/assert-source.d.ts +22 -0
  421. package/dist/tools/assert-source.js +53 -0
  422. package/dist/tools/assert-verdict.d.ts +20 -3
  423. package/dist/tools/assert-verdict.js +58 -20
  424. package/dist/tools/browser-tools.js +6 -22
  425. package/dist/tools/complete-snapshot.d.ts +48 -0
  426. package/dist/tools/complete-snapshot.js +75 -0
  427. package/dist/tools/coverage-tools.d.ts +10 -1
  428. package/dist/tools/coverage-tools.js +123 -69
  429. package/dist/tools/dynamic-tools.js +53 -13
  430. package/dist/tools/error-recovery.d.ts +25 -14
  431. package/dist/tools/error-recovery.js +78 -9
  432. package/dist/tools/feedback-tools.d.ts +1 -1
  433. package/dist/tools/feedback-tools.js +2 -2
  434. package/dist/tools/invoke-tool.js +121 -11
  435. package/dist/tools/lease-hint.d.ts +10 -0
  436. package/dist/tools/lease-hint.js +53 -4
  437. package/dist/tools/lease-tools.d.ts +35 -5
  438. package/dist/tools/lease-tools.js +191 -13
  439. package/dist/tools/merged-name-redirect.d.ts +13 -0
  440. package/dist/tools/merged-name-redirect.js +22 -0
  441. package/dist/tools/navigate-arrival.d.ts +0 -2
  442. package/dist/tools/navigate-arrival.js +1 -1
  443. package/dist/tools/numeric-bounds.d.ts +100 -0
  444. package/dist/tools/numeric-bounds.js +125 -0
  445. package/dist/tools/observe-tools.js +109 -65
  446. package/dist/tools/read-tools.js +31 -8
  447. package/dist/tools/real-input-attempt.d.ts +32 -0
  448. package/dist/tools/real-input-attempt.js +212 -2
  449. package/dist/tools/reconcile-tools.js +22 -8
  450. package/dist/tools/resolve-target.d.ts +0 -7
  451. package/dist/tools/sdk-marker-probe.d.ts +29 -0
  452. package/dist/tools/sdk-marker-probe.js +57 -0
  453. package/dist/tools/snapshot-delta.d.ts +1 -1
  454. package/dist/tools/tool-kit.d.ts +24 -0
  455. package/dist/tools/tool-kit.js +21 -0
  456. package/dist/tools/tool-names.d.ts +5 -0
  457. package/dist/tools/tool-names.js +5 -0
  458. package/dist/tools/tool-surface.d.ts +85 -6
  459. package/dist/tools/tool-surface.js +122 -2
  460. package/dist/tools/tools-helpers.d.ts +19 -0
  461. package/dist/tools/tools-helpers.js +46 -0
  462. package/dist/tools/tools.d.ts +2 -0
  463. package/dist/tools/tools.js +78 -12
  464. package/dist/tools/unadvertised-help.js +4 -4
  465. package/dist/tools/verify-next-baton.d.ts +53 -0
  466. package/dist/tools/verify-next-baton.js +52 -0
  467. package/dist/update/reticle-deps.d.ts +9 -0
  468. package/dist/update/reticle-deps.js +27 -0
  469. package/dist/update/sdk-sync.d.ts +1 -2
  470. package/dist/update/sdk-sync.js +1 -21
  471. package/dist/update/update-nudge.d.ts +25 -10
  472. package/dist/update/update-nudge.js +32 -3
  473. package/dist/update/updater.d.ts +1 -1
  474. package/dist/version/peer-announce.js +4 -2
  475. package/dist/version/sdk-fix.d.ts +47 -0
  476. package/dist/version/sdk-fix.js +127 -0
  477. package/dist/version/version-nudge.d.ts +14 -0
  478. package/dist/version/version-nudge.js +21 -0
  479. package/dist/version/version-skew.d.ts +38 -3
  480. package/dist/version/version-skew.js +83 -7
  481. package/dist/visual/visual-store.d.ts +6 -6
  482. package/dist/visual/visual-store.js +18 -16
  483. package/dist/visual/visual-tools.js +57 -12
  484. package/docs/README.md +2 -1
  485. package/docs/cli/cloud.mdx +1 -1
  486. package/docs/cli/doctor.mdx +2 -0
  487. package/docs/cli/serve.mdx +4 -2
  488. package/docs/cli/verify.mdx +4 -5
  489. package/docs/cli.mdx +7 -3
  490. package/docs/desktop.mdx +1 -1
  491. package/docs/docs.json +2 -2
  492. package/docs/gates.md +1 -1
  493. package/docs/getting-started.md +19 -3
  494. package/docs/index.mdx +9 -6
  495. package/docs/install-agentic.mdx +38 -12
  496. package/docs/install-manual.mdx +1 -1
  497. package/docs/packages/browser.mdx +2 -2
  498. package/docs/packages/server.mdx +1 -1
  499. package/docs/packages.mdx +8 -6
  500. package/docs/platform-integration.md +17 -0
  501. package/docs/predicates.mdx +8 -0
  502. package/docs/reticle-manual.md +106 -0
  503. package/docs/skill-file.mdx +3 -3
  504. package/docs/telemetry-contract.md +108 -4
  505. package/docs/tools-act-sequence.mdx +16 -0
  506. package/docs/tools-tools-and-run.mdx +2 -4
  507. package/docs/troubleshooting.mdx +9 -0
  508. package/docs/usage.md +4 -3
  509. package/package.json +4 -3
  510. package/dist/init/cursor.d.ts +0 -24
  511. package/dist/init/cursor.js +0 -80
  512. package/dist/session/session-readiness.d.ts +0 -34
  513. package/dist/session/session-readiness.js +0 -36
@@ -13,7 +13,10 @@
13
13
  export declare const MAX_TESTIDS = 60;
14
14
  /** Every distinct `data-testid` literal in the given sources, in first-seen order. */
15
15
  export declare function scanTestids(sources: readonly string[]): string[];
16
- /** The store libraries this app depends on, as ready-to-uncomment registration lines. */
16
+ /**
17
+ * The store libraries this app depends on AND the running app cannot reveal on its own, as
18
+ * ready-to-uncomment registration lines.
19
+ */
17
20
  export declare function storeHints(deps: ReadonlySet<string>): string[];
18
21
  /** A store instance we found in the app's own source, with everything needed to import and register it. */
19
22
  export interface FoundStore {
@@ -24,8 +27,6 @@ export interface FoundStore {
24
27
  /** Module specifier relative to `src/reticle-dev.ts`. */
25
28
  importPath: string;
26
29
  }
27
- /** Where the generated dev module lives, for Vite. Next passes its own. */
28
- export declare const DEFAULT_DEV_MODULE_DIR = "src";
29
30
  /**
30
31
  * Store instances declared in the app's own source, ready to import and register.
31
32
  *
@@ -49,9 +49,29 @@ const STORE_LIBRARIES = [
49
49
  ['pinia', "registerStore('cart', piniaStore(useCartStore()))"],
50
50
  ['svelte', "registerStore('cart', svelteStore(cartStore))"],
51
51
  ];
52
- /** The store libraries this app depends on, as ready-to-uncomment registration lines. */
52
+ /**
53
+ * Libraries that hand their store to React through a context provider, and therefore need no hint.
54
+ *
55
+ * `<Provider store>` and `<QueryClientProvider client>` put the store instance in the fiber tree as
56
+ * a prop, so the React adapter finds and registers it on the first commit — see `auto-stores.ts` in
57
+ * `@reticlehq/react`. Offering a commented `registerStore` line for these was asking someone to do
58
+ * by hand, and be nagged about, work that is already done by the time they read the report.
59
+ *
60
+ * Everything absent from this set is module-scope (Zustand, Valtio, a MobX singleton) or needs an
61
+ * argument only the source supplies (Jotai atoms, an XState actor). Nothing in the running app
62
+ * points at those, so they still need the app to hand them over, and the hint still earns its place.
63
+ */
64
+ const AUTO_DISCOVERED_DEPS = new Set([
65
+ '@tanstack/react-query',
66
+ '@reduxjs/toolkit',
67
+ 'redux',
68
+ ]);
69
+ /**
70
+ * The store libraries this app depends on AND the running app cannot reveal on its own, as
71
+ * ready-to-uncomment registration lines.
72
+ */
53
73
  export function storeHints(deps) {
54
- return STORE_LIBRARIES.filter(([dep]) => deps.has(dep)).map(([, hint]) => hint);
74
+ return STORE_LIBRARIES.filter(([dep]) => deps.has(dep) && !AUTO_DISCOVERED_DEPS.has(dep)).map(([, hint]) => hint);
55
75
  }
56
76
  /**
57
77
  * Store factories whose EXPORTED result is the store instance itself — the form `registerStore`
@@ -102,7 +122,7 @@ function importPathFor(storePath, fromDir) {
102
122
  return rel.startsWith('.') ? rel : `./${rel}`;
103
123
  }
104
124
  /** Where the generated dev module lives, for Vite. Next passes its own. */
105
- export const DEFAULT_DEV_MODULE_DIR = 'src';
125
+ const DEFAULT_DEV_MODULE_DIR = 'src';
106
126
  /**
107
127
  * Store instances declared in the app's own source, ready to import and register.
108
128
  *
@@ -0,0 +1,36 @@
1
+ /**
2
+ * The last thing `init` prints, and the only part of it a user is asked to act on.
3
+ *
4
+ * Split out of `run.ts` because that file sits exactly at the 1000-line cohesion cap, and because
5
+ * this IS a separate concern: everything else in `run.ts` decides what to write, and this decides
6
+ * what to say afterwards. The two failure modes are different too — a wrong write breaks an
7
+ * install, a wrong sentence loses a user quietly.
8
+ */
9
+ import { Framework } from './detect.js';
10
+ import { StepStatus } from './plan.js';
11
+ /**
12
+ * The standing ask, printed at the end of every `init`.
13
+ *
14
+ * Addressed to the agent as much as the human: whichever of them just ran this command is the one
15
+ * holding the experience, and neither has a Reticle tool surface to file through at this point.
16
+ *
17
+ * Printed by the `runInit` wrapper, NOT by `report()` — see the comment there for why, and for how
18
+ * the workspace redirect is kept from asking twice.
19
+ */
20
+ export declare const FEEDBACK_HINT: string;
21
+ /**
22
+ * The last two lines a user reads, and the order matters.
23
+ *
24
+ * This used to say only "Restart <dev server>, then ask your agent: List Reticle sessions" — and
25
+ * asking the agent was the one thing that could not work yet. `init` registers the MCP server, but
26
+ * an agent client reads its tool list when it STARTS and never re-reads it, so the session that
27
+ * just ran `init` has no `reticle_*` tools however clean the install was. The user follows the
28
+ * instruction, the agent answers "unknown tool", and the obvious conclusion is that the install
29
+ * failed.
30
+ *
31
+ * So the reload is named FIRST, before the sentence that depends on it. Omitted entirely when this
32
+ * run did not register MCP (`--no-mcp`), where it would be advice about something we did not do.
33
+ */
34
+ export declare function restartHint(framework: Framework, mcpStatus: StepStatus | undefined,
35
+ /** The project's own dev command, when package.json named one. */
36
+ devCommand?: string): string;
@@ -0,0 +1,120 @@
1
+ /**
2
+ * The last thing `init` prints, and the only part of it a user is asked to act on.
3
+ *
4
+ * Split out of `run.ts` because that file sits exactly at the 1000-line cohesion cap, and because
5
+ * this IS a separate concern: everything else in `run.ts` decides what to write, and this decides
6
+ * what to say afterwards. The two failure modes are different too — a wrong write breaks an
7
+ * install, a wrong sentence loses a user quietly.
8
+ */
9
+ import { Framework } from './detect.js';
10
+ import { StepStatus } from './plan.js';
11
+ import { wasMcpRegistered } from './mcp-registered.js';
12
+ import { CLI } from './agent-rules.js';
13
+ /**
14
+ * The standing ask, printed at the end of every `init`.
15
+ *
16
+ * Addressed to the agent as much as the human: whichever of them just ran this command is the one
17
+ * holding the experience, and neither has a Reticle tool surface to file through at this point.
18
+ *
19
+ * Printed by the `runInit` wrapper, NOT by `report()` — see the comment there for why, and for how
20
+ * the workspace redirect is kept from asking twice.
21
+ */
22
+ export const FEEDBACK_HINT = 'Anything wrong, missing, or awkward — in this setup or in Reticle itself? Tell us; it is the ' +
23
+ 'one thing that decides what gets fixed:\n' +
24
+ ` ${CLI} feedback --agent --kind <bug|gap|ambiguity|feature_request|improvement> "what happened" (agents)\n` +
25
+ ` ${CLI} feedback "what worked, what didn't" (humans)`;
26
+ /**
27
+ * What to say about the dev server.
28
+ *
29
+ * Names the project's own script when `package.json` has a recognisable one, and otherwise says the
30
+ * THING rather than guessing the command.
31
+ *
32
+ * The guesses that used to live here — `vite`, `next dev`, `astro dev` — were wrong often enough to
33
+ * be worth deleting. Measured on a real app: rowy has no `dev` script at all, so "Restart `vite`"
34
+ * sent the reader to work out what was meant instead of starting a server. Nobody needs the guess:
35
+ * an agent reading this can open package.json, and a human already knows how they start their own
36
+ * app. A wrong command costs more than a missing one.
37
+ */
38
+ function devServerRestart(_framework, devCommand) {
39
+ return devCommand === undefined
40
+ ? 'Restart your dev server'
41
+ : `Restart your dev server (\`${devCommand}\`)`;
42
+ }
43
+ /**
44
+ * The last two lines a user reads, and the order matters.
45
+ *
46
+ * This used to say only "Restart <dev server>, then ask your agent: List Reticle sessions" — and
47
+ * asking the agent was the one thing that could not work yet. `init` registers the MCP server, but
48
+ * an agent client reads its tool list when it STARTS and never re-reads it, so the session that
49
+ * just ran `init` has no `reticle_*` tools however clean the install was. The user follows the
50
+ * instruction, the agent answers "unknown tool", and the obvious conclusion is that the install
51
+ * failed.
52
+ *
53
+ * So the reload is named FIRST, before the sentence that depends on it. Omitted entirely when this
54
+ * run did not register MCP (`--no-mcp`), where it would be advice about something we did not do.
55
+ */
56
+ export function restartHint(framework, mcpStatus,
57
+ /** The project's own dev command, when package.json named one. */
58
+ devCommand) {
59
+ const dev = `${devServerRestart(framework, devCommand)}.`;
60
+ // NAME THE COMMAND THAT PROVES IT, not one that merely asks.
61
+ //
62
+ // `init` writes files and stops; the install is not finished until an app carrying the SDK has
63
+ // actually dialled the daemon, and nothing here confirmed that. The field shape is unambiguous:
64
+ // people complete the agent half, never complete the app half, and keep a daemon running for
65
+ // weeks with nothing to drive — so this is the last instruction most of them read.
66
+ //
67
+ // "Ask your agent: List Reticle sessions" asks a question whose failure is a dead end. `reticle
68
+ // status` ANSWERS it: as of 2.7.0 it reports the session, or says why there is none — no app
69
+ // running, an app running that never dialled us, a tab that closed — with the fix for each.
70
+ // The one thing that works BEFORE the restart, so it goes before it.
71
+ //
72
+ // What comes after the restart, named as a JOB rather than as a capability.
73
+ //
74
+ // This used to point at a `reticle demo` command that opened its own browser and drove one
75
+ // control. It was cut: a demo command is a side show. The thing a user needs to see is THEIR app,
76
+ // instrumented in THEIR codebase, driven by THEIR agent through the tools they just installed —
77
+ // because that is the workflow they are deciding whether to adopt, and a bespoke demo path proves
78
+ // nothing about it.
79
+ //
80
+ // So the close hands the agent the sequence instead. It is deliberately one drive of one real
81
+ // flow ending in a verdict, because an install that ends in "the tools are available" is an
82
+ // install that ends in nothing.
83
+ const demo = 'Then drive one real flow of your app end to end and report the verdict — that is the install ' +
84
+ "proving itself, and it is the agent's job, not a separate command.";
85
+ const prove = 'Then run `npx @reticlehq/server status` — it confirms the app connected, or says exactly why ' +
86
+ 'it has not.';
87
+ // Nothing registered this run (`--no-mcp`, or a client that needs a manual edit): a restart picks
88
+ // up nothing, so advice about one would be advice about something we did not do.
89
+ if (!wasMcpRegistered(mcpStatus))
90
+ return `${dev}\n${demo}\n${prove}`;
91
+ // ALREADY: the tools are reachable RIGHT NOW, and this is the branch that used to lie.
92
+ //
93
+ // `wasMcpRegistered` is true for both APPLY and ALREADY, which is correct for the funnel field it
94
+ // was written for and wrong here, because the two cases have opposite answers to "must anybody
95
+ // restart". Every second project on a machine, and every Claude Code plugin install, took the
96
+ // APPLY text: "restart your agent — the tools only appear after that". An agent reads this AFTER
97
+ // whatever its skill file said, and it describes the output in front of it, so it wins. The agent
98
+ // stops with the project wired and nothing driven, which is the exact failure the install path
99
+ // exists to prevent, caused by the install path itself.
100
+ if (mcpStatus === StepStatus.ALREADY) {
101
+ return (`${dev}\n` +
102
+ `${demo}\n` +
103
+ 'The Reticle MCP server was already registered on this machine, so there is no restart to do ' +
104
+ 'and the tools are available now.\n' +
105
+ `${prove}\n` +
106
+ 'Once it shows a session, drive a flow — that is the install finished. Carry straight on; ' +
107
+ 'nothing here is waiting on a human.');
108
+ }
109
+ return (`${dev}\n` +
110
+ `${demo}\n` +
111
+ 'Then restart your agent so it picks up the new MCP server — restart Claude Code, reload the ' +
112
+ 'window in Cursor, or hit Start in `.vscode/mcp.json` in VS Code.\n' +
113
+ 'The tools only appear after that: your agent read its server list before Reticle existed, ' +
114
+ 'and no slash command re-reads it (`/mcp` manages servers already loaded, so it cannot pick ' +
115
+ 'up a new one). This is once per machine — Reticle is registered globally, so every later ' +
116
+ 'project starts with the tools already there.\n' +
117
+ `${prove}\n` +
118
+ 'Once it shows a session, drive one flow and report the verdict — that is the install ' +
119
+ 'finished. Do it now; nothing here is waiting on a human.');
120
+ }
@@ -19,26 +19,29 @@
19
19
  * keeps today's cost and today's exit behaviour, and blocking never happens where blocking is
20
20
  * wrong. The signal is the standard "am I being piped" one and needs no argument parsing, which
21
21
  * also keeps `init`'s documented flag surface where it is.
22
- * - It never starts anything. A dev server started by a long-lived daemon is invisible to the
23
- * person whose machine it runs on and orphans when the daemon exits, so the daemon stays out of
24
- * it — the AGENT starts one, under the guards in agent-rules.ts, because it is attributable and
25
- * stoppable there. So the honest shape here is: confirm the app if it connects, otherwise name
26
- * the ONE command that is outstanding and the one that proves it worked.
22
+ * - The DAEMON never starts anything. A dev server started by a long-lived daemon is invisible to
23
+ * the person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
24
+ * of it. Note what that reasoning is actually about: attributability, not abstinence. A
25
+ * foreground `init` somebody ran satisfies it — the command is in their transcript, and it stops
26
+ * what it started if setup fails or is interrupted — which is why the runtime phase is allowed
27
+ * to boot one where the daemon is not. This function keeps its own shape either way: confirm the
28
+ * app if it connects, otherwise name the ONE command that is outstanding and the one that proves
29
+ * it worked.
27
30
  */
28
31
  import { InitConfirmation } from '@reticlehq/core';
29
- import type { InitOutcome } from '@reticlehq/core';
30
- /**
31
- * How long a human is asked to wait.
32
- *
33
- * Long enough for a page that is already loading to finish dialling, short enough that somebody who
34
- * has not restarted their dev server yet is not held hostage by a wait that cannot succeed — they
35
- * have not typed the command that would make it succeed, and the message tells them which one.
36
- */
37
- export declare const CONFIRM_WINDOW_MS = 12000;
38
- export declare const CONFIRM_POLL_MS = 500;
32
+ import type { DevServerEntry, InitOutcome } from '@reticlehq/core';
39
33
  export interface ConfirmDeps {
40
34
  /** Session ids connected right now, or null when nothing is listening on the bridge port. */
41
35
  listSessionIds: () => Promise<readonly string[] | null>;
36
+ /**
37
+ * The dev servers that have announced themselves, read at the END of the wait rather than the
38
+ * start: a dev server booting alongside `init` is the common case, and asking before it has
39
+ * finished listening would report the state we are trying to move away from.
40
+ *
41
+ * Optional so every existing construction of these deps — and any embedder's — keeps working and
42
+ * simply gets today's less specific message.
43
+ */
44
+ listDevServers?: () => readonly DevServerEntry[];
42
45
  now: () => number;
43
46
  sleep: (ms: number) => Promise<void>;
44
47
  windowMs?: number;
@@ -77,23 +80,19 @@ export declare function confirmAppConnected(deps: ConfirmDeps): Promise<InitConf
77
80
  * there is a command outstanding. A missing daemon is not a defect in the install — the daemon comes
78
81
  * up when the agent loads the tools — so it is a notice.
79
82
  */
80
- export declare function confirmationMessage(confirmation: InitConfirmation, port: number): string;
81
83
  /**
82
- * What a non-TTY run says instead of waiting.
84
+ * Narrow "no app connected" using what the dev servers themselves announced.
83
85
  *
84
- * `init` deliberately does not block when nobody is at the terminal — a 12-second wait in a script
85
- * is wrong, and an agent driving `init` through a shell is never a TTY. But silence was the wrong
86
- * other half of that decision: the agent path IS the prescribed path (every skill and every README
87
- * block tells an agent to run exactly this command), so the one message joining "init finished" to
88
- * "an app connected" was withheld from most of the people who run it. They were left with files on
89
- * disk, an exit code of 0, and nothing saying the page half had not happened.
86
+ * `confirmAppConnected` can only observe the bridge, so its NO_SESSION covers two situations with
87
+ * OPPOSITE fixes: the dev server is not running Reticle at all, or it is and no page has been
88
+ * opened. An announced entry is proof the plugin is loaded in the process that is actually running
89
+ * — which means the config is right and it has already been restarted.
90
90
  *
91
- * It claims nothing it did not check. It did not look for a session, so it does not say whether one
92
- * exists — a one-shot look would be worse than none, because a daemon is shared across every project
93
- * on the machine and "a session exists" is satisfied by somebody else's app, which is the false
94
- * green `confirmAppConnected` refuses by design.
91
+ * Only the unexplained answer is sharpened. CONNECTED is the finished state and NO_DAEMON is a
92
+ * different fact; neither becomes more true because a dev server is up.
95
93
  */
96
- export declare function unwatchedMessage(port: number): string;
94
+ export declare function sharpenWithDevServers(confirmation: InitConfirmation, running: readonly DevServerEntry[]): InitConfirmation;
95
+ export declare function confirmationMessage(confirmation: InitConfirmation, port: number, running?: readonly DevServerEntry[]): string;
97
96
  /**
98
97
  * Finish `init` on evidence rather than on a write.
99
98
  *
@@ -19,14 +19,21 @@
19
19
  * keeps today's cost and today's exit behaviour, and blocking never happens where blocking is
20
20
  * wrong. The signal is the standard "am I being piped" one and needs no argument parsing, which
21
21
  * also keeps `init`'s documented flag surface where it is.
22
- * - It never starts anything. A dev server started by a long-lived daemon is invisible to the
23
- * person whose machine it runs on and orphans when the daemon exits, so the daemon stays out of
24
- * it — the AGENT starts one, under the guards in agent-rules.ts, because it is attributable and
25
- * stoppable there. So the honest shape here is: confirm the app if it connects, otherwise name
26
- * the ONE command that is outstanding and the one that proves it worked.
22
+ * - The DAEMON never starts anything. A dev server started by a long-lived daemon is invisible to
23
+ * the person whose machine it runs on and orphans when the daemon exits, so the daemon stays out
24
+ * of it. Note what that reasoning is actually about: attributability, not abstinence. A
25
+ * foreground `init` somebody ran satisfies it — the command is in their transcript, and it stops
26
+ * what it started if setup fails or is interrupted — which is why the runtime phase is allowed
27
+ * to boot one where the daemon is not. This function keeps its own shape either way: confirm the
28
+ * app if it connects, otherwise name the ONE command that is outstanding and the one that proves
29
+ * it worked.
27
30
  */
28
31
  import { InitConfirmation, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
29
32
  import { fetchStatus, summarizeStatus } from '../cli/cli-launch.js';
33
+ import { readDevServers } from '../daemon/dev-servers.js';
34
+ import { devServersForProject } from '@reticlehq/core';
35
+ import { readProjectId } from '../cli/cli-port.js';
36
+ import { reticleStateHome } from '../daemon/daemon.js';
30
37
  import { reportInitOutcome } from '../telemetry/init-telemetry.js';
31
38
  /**
32
39
  * How long a human is asked to wait.
@@ -35,8 +42,8 @@ import { reportInitOutcome } from '../telemetry/init-telemetry.js';
35
42
  * has not restarted their dev server yet is not held hostage by a wait that cannot succeed — they
36
43
  * have not typed the command that would make it succeed, and the message tells them which one.
37
44
  */
38
- export const CONFIRM_WINDOW_MS = 12_000;
39
- export const CONFIRM_POLL_MS = 500;
45
+ const CONFIRM_WINDOW_MS = 12_000;
46
+ const CONFIRM_POLL_MS = 500;
40
47
  /**
41
48
  * Poll until an app connects or the window runs out.
42
49
  *
@@ -78,7 +85,23 @@ const PROVE_COMMAND = '`npx @reticlehq/server status`';
78
85
  * there is a command outstanding. A missing daemon is not a defect in the install — the daemon comes
79
86
  * up when the agent loads the tools — so it is a notice.
80
87
  */
81
- export function confirmationMessage(confirmation, port) {
88
+ /**
89
+ * Narrow "no app connected" using what the dev servers themselves announced.
90
+ *
91
+ * `confirmAppConnected` can only observe the bridge, so its NO_SESSION covers two situations with
92
+ * OPPOSITE fixes: the dev server is not running Reticle at all, or it is and no page has been
93
+ * opened. An announced entry is proof the plugin is loaded in the process that is actually running
94
+ * — which means the config is right and it has already been restarted.
95
+ *
96
+ * Only the unexplained answer is sharpened. CONNECTED is the finished state and NO_DAEMON is a
97
+ * different fact; neither becomes more true because a dev server is up.
98
+ */
99
+ export function sharpenWithDevServers(confirmation, running) {
100
+ if (confirmation !== InitConfirmation.NO_SESSION)
101
+ return confirmation;
102
+ return 0 === running.length ? InitConfirmation.NO_SESSION : InitConfirmation.NO_PAGE;
103
+ }
104
+ export function confirmationMessage(confirmation, port, running = []) {
82
105
  if (confirmation === InitConfirmation.CONNECTED) {
83
106
  return (' [✓] an app is connected — that is the install finished, not just written.\n' +
84
107
  ' Ask your agent to drive a flow.');
@@ -89,6 +112,15 @@ export function confirmationMessage(confirmation, port) {
89
112
  ' The daemon starts on its own when your agent loads the Reticle tools. After that, ' +
90
113
  `${PROVE_COMMAND} confirms the app.`);
91
114
  }
115
+ if (confirmation === InitConfirmation.NO_PAGE) {
116
+ // Deliberately never says "restart". The announcement is proof they already did — telling them
117
+ // again is how a correct instruction reads as the tool not knowing what is going on.
118
+ const where = running.map((s) => ` ${s.url}`).join('\n');
119
+ return (' [⚠] your dev server has Reticle loaded, and no page has connected yet — so the only step ' +
120
+ 'left is opening the app.\n' +
121
+ ` Open it in a browser:\n${where}\n` +
122
+ ` ${PROVE_COMMAND} then confirms it.`);
123
+ }
92
124
  return (' [⚠] no app has connected yet — the files are written, the page half of the install is not ' +
93
125
  'done.\n' +
94
126
  ' Restart your dev server and load the app in a browser — or ask your agent to, which it is ' +
@@ -110,7 +142,7 @@ export function confirmationMessage(confirmation, port) {
110
142
  * on the machine and "a session exists" is satisfied by somebody else's app, which is the false
111
143
  * green `confirmAppConnected` refuses by design.
112
144
  */
113
- export function unwatchedMessage(port) {
145
+ function unwatchedMessage(port) {
114
146
  return (' [ℹ] the files are written. An app CONNECTING is what finishes the install, and this run did ' +
115
147
  'not wait to see one.\n' +
116
148
  ' Start the dev server, load the app in a browser, then ' +
@@ -142,13 +174,21 @@ export async function confirmInstall(result, io, deps, report = reportInitOutcom
142
174
  }
143
175
  io.print('');
144
176
  io.print(WATCHING(deps.windowMs ?? CONFIRM_WINDOW_MS));
145
- const confirmation = await confirmAppConnected(deps);
146
- io.print(confirmationMessage(confirmation, deps.port));
177
+ const observed = await confirmAppConnected(deps);
178
+ const running = deps.listDevServers?.() ?? [];
179
+ const confirmation = sharpenWithDevServers(observed, running);
180
+ io.print(confirmationMessage(confirmation, deps.port, running));
147
181
  report({ ...outcome, confirmation });
148
182
  }
149
183
  /** The real deps: the daemon's own status endpoint, and whether a human is watching. */
150
184
  export function nodeConfirmDeps(port = RETICLE_DEFAULT_PORT) {
151
185
  return {
186
+ // Scoped to the project being set up. The registry is machine-wide, so unscoped it reported a
187
+ // sibling app's dev server as this one's — see devServersForProject.
188
+ listDevServers: () => devServersForProject(readDevServers(reticleStateHome()), {
189
+ projectId: readProjectId(process.cwd()),
190
+ root: process.cwd(),
191
+ }),
152
192
  listSessionIds: async () => {
153
193
  const payload = await fetchStatus(port);
154
194
  // `fetchStatus` resolves undefined when nothing answered, which is precisely the "no daemon"
@@ -12,11 +12,32 @@
12
12
  * `REACT_APP_`. So it travels through `.env.development.local`, which is CRA's own documented
13
13
  * mechanism and is gitignored by CRA's own template.
14
14
  */
15
- /** The line added to `src/index.tsx`. Side-effect import: the module guards itself on NODE_ENV. */
15
+ /** The line added to `src/index.tsx` / `src/index.js`. Side-effect import: the module guards itself on NODE_ENV. */
16
16
  export declare const CRA_DEV_MODULE_IMPORT = "import './reticle-dev';";
17
- export declare const CRA_DEV_MODULE_PATH = "src/reticle-dev.ts";
17
+ /**
18
+ * Where the connect module lands — `.ts` only when the app already speaks TypeScript.
19
+ *
20
+ * A JavaScript CRA project has no tsconfig and cannot resolve `.ts` (#675). Emitting `.ts` there
21
+ * makes the first compile after init fail while the plan still reports `[✓]`.
22
+ */
23
+ export declare function craDevModulePath(typescript: boolean): string;
24
+ /** TypeScript default path — prefer `craDevModulePath` when the project's language is known. */
25
+ export declare const CRA_DEV_MODULE_PATH: string;
18
26
  export declare const CRA_ENV_PATH = ".env.development.local";
19
27
  export declare const TOKEN_VAR = "REACT_APP_RETICLE_TOKEN";
28
+ /**
29
+ * The bridge URL, carried through the same channel as the token.
30
+ *
31
+ * CRA is the one supported stack with no build-time hook of ours: no plugin, no config wrapper, no
32
+ * `define`. Vite and Astro re-resolve the daemon every dev-server start and Next does it through
33
+ * `withReticle`; CRA has nowhere to run that code. So the URL goes where the token already goes, and
34
+ * is refreshed by the same `init` step that refreshes the token.
35
+ *
36
+ * That makes `reticle init` the heal rather than the dev server, which is weaker and is stated
37
+ * plainly in the step's own detail. It is still strictly better than a URL frozen into a source file
38
+ * the owner has to hand-edit, and `.env.development.local` is already the per-machine file.
39
+ */
40
+ export declare const URL_VAR = "REACT_APP_RETICLE_URL";
20
41
  /**
21
42
  * What the app itself says when the token is not there.
22
43
  *
@@ -45,6 +66,14 @@ export declare const CRA_TOKEN_PER_MACHINE_NOTICE: string;
45
66
  /** Add the import after the last existing one, or null when it is already present. */
46
67
  export declare function craImportPatch(source: string): string | null;
47
68
  /** Set the token variable, or null when nothing needs to change. */
48
- export declare function craEnvPatch(existing: string | null, token: string): string | null;
49
- /** The dev-only connect module imported from `src/index.tsx`. */
50
- export declare function craDevModuleFile(port: number | undefined, projectId?: string): string;
69
+ export declare function craEnvPatch(existing: string | null, token: string, url?: string): string | null;
70
+ /** Options for the CRA connect module. */
71
+ export interface CraDevModuleOptions {
72
+ /**
73
+ * When false, emit a `.js`-shaped body (no `export {}`). Default true for callers that predate
74
+ * the language branch.
75
+ */
76
+ typescript?: boolean;
77
+ }
78
+ /** The dev-only connect module imported from the app entry. */
79
+ export declare function craDevModuleFile(port: number | undefined, projectId?: string, options?: CraDevModuleOptions): string;
package/dist/init/cra.js CHANGED
@@ -12,12 +12,36 @@
12
12
  * `REACT_APP_`. So it travels through `.env.development.local`, which is CRA's own documented
13
13
  * mechanism and is gitignored by CRA's own template.
14
14
  */
15
+ import { bridgeWsUrl } from '@reticlehq/core';
15
16
  import { CLI } from './agent-rules.js';
16
- /** The line added to `src/index.tsx`. Side-effect import: the module guards itself on NODE_ENV. */
17
+ /** The line added to `src/index.tsx` / `src/index.js`. Side-effect import: the module guards itself on NODE_ENV. */
17
18
  export const CRA_DEV_MODULE_IMPORT = "import './reticle-dev';";
18
- export const CRA_DEV_MODULE_PATH = 'src/reticle-dev.ts';
19
+ /**
20
+ * Where the connect module lands — `.ts` only when the app already speaks TypeScript.
21
+ *
22
+ * A JavaScript CRA project has no tsconfig and cannot resolve `.ts` (#675). Emitting `.ts` there
23
+ * makes the first compile after init fail while the plan still reports `[✓]`.
24
+ */
25
+ export function craDevModulePath(typescript) {
26
+ return typescript ? 'src/reticle-dev.ts' : 'src/reticle-dev.js';
27
+ }
28
+ /** TypeScript default path — prefer `craDevModulePath` when the project's language is known. */
29
+ export const CRA_DEV_MODULE_PATH = craDevModulePath(true);
19
30
  export const CRA_ENV_PATH = '.env.development.local';
20
31
  export const TOKEN_VAR = 'REACT_APP_RETICLE_TOKEN';
32
+ /**
33
+ * The bridge URL, carried through the same channel as the token.
34
+ *
35
+ * CRA is the one supported stack with no build-time hook of ours: no plugin, no config wrapper, no
36
+ * `define`. Vite and Astro re-resolve the daemon every dev-server start and Next does it through
37
+ * `withReticle`; CRA has nowhere to run that code. So the URL goes where the token already goes, and
38
+ * is refreshed by the same `init` step that refreshes the token.
39
+ *
40
+ * That makes `reticle init` the heal rather than the dev server, which is weaker and is stated
41
+ * plainly in the step's own detail. It is still strictly better than a URL frozen into a source file
42
+ * the owner has to hand-edit, and `.env.development.local` is already the per-machine file.
43
+ */
44
+ export const URL_VAR = 'REACT_APP_RETICLE_URL';
21
45
  /**
22
46
  * What the app itself says when the token is not there.
23
47
  *
@@ -64,44 +88,91 @@ export function craImportPatch(source) {
64
88
  return lines.join('\n');
65
89
  }
66
90
  /** Set the token variable, or null when nothing needs to change. */
67
- export function craEnvPatch(existing, token) {
91
+ export function craEnvPatch(existing, token, url) {
68
92
  if ('' === token)
69
93
  return null;
70
- const line = `${TOKEN_VAR}=${token}`;
71
- if (null === existing || '' === existing.trim())
72
- return `${line}\n`;
73
- if (existing.includes(line))
74
- return null;
75
- // Replace rather than append: two assignments of one variable is a silent coin flip on which wins.
76
- if (new RegExp(`^${TOKEN_VAR}=`, 'm').test(existing)) {
77
- return existing.replace(new RegExp(`^${TOKEN_VAR}=.*$`, 'm'), line);
94
+ const pairs = [
95
+ [TOKEN_VAR, token],
96
+ ...(url !== undefined && url.length > 0 ? [[URL_VAR, url]] : []),
97
+ ];
98
+ let next = null === existing || '' === existing.trim() ? '' : existing;
99
+ for (const [name, value] of pairs) {
100
+ const line = `${name}=${value}`;
101
+ if (next.includes(line))
102
+ continue;
103
+ // Replace rather than append: two assignments of one variable is a silent coin flip on which
104
+ // wins, and for the URL that coin decides which daemon the app talks to.
105
+ if (new RegExp(`^${name}=`, 'm').test(next)) {
106
+ next = next.replace(new RegExp(`^${name}=.*$`, 'm'), line);
107
+ }
108
+ else {
109
+ next = `${'' === next || next.endsWith('\n') ? next : `${next}\n`}${line}\n`;
110
+ }
78
111
  }
79
- return `${existing.endsWith('\n') ? existing : `${existing}\n`}${line}\n`;
112
+ return next === (existing ?? '') ? null : next;
80
113
  }
81
- /** The dev-only connect module imported from `src/index.tsx`. */
82
- export function craDevModuleFile(port, projectId) {
114
+ /** The dev-only connect module imported from the app entry. */
115
+ export function craDevModuleFile(port, projectId, options = {}) {
116
+ const typescript = false !== options.typescript;
83
117
  const fields = [];
118
+ // `bridgeWsUrl`, not a hand-written string. This was the only client URL in the product spelling
119
+ // the host as `127.0.0.1` while every other generator said `localhost` — same endpoint, but a
120
+ // difference with no reason behind it is the kind that becomes a real one after somebody edits half
121
+ // of it.
84
122
  if (port !== undefined)
85
- fields.push(`url: 'ws://127.0.0.1:${String(port)}/reticle'`);
123
+ fields.push(`url: '${bridgeWsUrl(port)}'`);
86
124
  if (projectId !== undefined && projectId.length > 0)
87
125
  fields.push(`projectId: '${projectId}'`);
88
- const inline = fields.length > 0 ? `${fields.join(', ')}, ` : '';
126
+ // Multiline on purpose (#684): a single-line connect + console.error fails CRA boilerplate
127
+ // Prettier (printWidth 80) and the project's own lint blocks a clean install.
128
+ const connectFields = [
129
+ ...fields.map((f) => ` ${f},`),
130
+ ' ...(url.length > 0 ? { url } : {}),',
131
+ ' ...(token.length > 0 ? { token } : {}),',
132
+ ].join('\n');
133
+ // Split so every emitted line stays under a CRA boilerplate printWidth of 80 (#684). A single
134
+ // JSON.stringify of the whole note is ~290 characters and fails prettier-as-eslint on install.
135
+ // Chunks are joined with `+` in the emitted file; together they equal `[reticle] ${CRA_TOKEN_MISSING_NOTE}`.
136
+ const missingChunks = [
137
+ `[reticle] ${TOKEN_VAR} is not set, so Reticle `,
138
+ 'cannot pair with the daemon. The pairing token is ',
139
+ `per-machine and ${CRA_ENV_PATH} is gitignored by `,
140
+ "CRA's template, so it does not survive a clone. Run ",
141
+ `\`${CLI} init\` in this project to write it for this `,
142
+ 'machine.',
143
+ ].map((c) => JSON.stringify(c));
144
+ // Eight spaces match the indent inside `console.error(` below.
145
+ const missingExpr = missingChunks.join(' +\n ');
146
+ // `export {}` is a TypeScript empty-module marker. A `.js` file with it is fine under Babel, but
147
+ // the workaround reporters used was to drop it when renaming to `.js` — keep the JS emit clean.
148
+ const trailer = typescript ? '\nexport {};\n' : '\n';
89
149
  return `// Dev-only: connect Reticle. Imported for its side effect from src/index.tsx.
90
150
  //
91
- // CRA's public/index.html is a static template the bundler never processes for modules, so the
92
- // connect cannot live there. The pairing token arrives through REACT_APP_RETICLE_TOKEN because
93
- // REACT_APP_* is the only thing CRA inlines into browser code.
151
+ // CRA's public/index.html is a static template the bundler never processes for
152
+ // modules, so the connect cannot live there. The pairing token arrives through
153
+ // REACT_APP_RETICLE_TOKEN because REACT_APP_* is the only thing CRA inlines
154
+ // into browser code.
94
155
  if (process.env.NODE_ENV === 'development') {
95
156
  void import('@reticlehq/react').then(({ reticle, install }) => {
96
157
  install();
97
158
  const token = process.env.${TOKEN_VAR} ?? '';
98
- // Loud on purpose: without this the only symptom is the bridge's generic auth failure.
99
- if (token.length === 0) console.error(${JSON.stringify(`[reticle] ${CRA_TOKEN_MISSING_NOTE}`)});
159
+ // Written by \`reticle init\` from the daemon that was live when it ran, and
160
+ // refreshed by re-running it. CRA gives us no hook to resolve this at
161
+ // dev-server start, so if the daemon moves, re-run \`reticle init\` rather
162
+ // than editing the url below.
163
+ const url = process.env.${URL_VAR} ?? '';
164
+ // Loud on purpose: without this the only symptom is the bridge's generic
165
+ // auth failure.
166
+ if (token.length === 0) {
167
+ console.error(
168
+ ${missingExpr},
169
+ );
170
+ }
100
171
  // Still attempt it — a bridge running without a token pairs fine.
101
- reticle.connect({ ${inline}...(token.length > 0 ? { token } : {}) });
172
+ reticle.connect({
173
+ ${connectFields}
174
+ });
102
175
  });
103
176
  }
104
-
105
- export {};
106
- `;
177
+ ${trailer}`;
107
178
  }