@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
@@ -1,7 +1,8 @@
1
1
  import { z } from 'zod';
2
- import { ReticleCommand, RETICLE_CAPTURE_FILE_PREFIX, VISUAL_NO_PROVIDER_RECOMMENDATION, VisualReason, } from '@reticlehq/core';
2
+ import { AppRuntime, ReticleCommand, RETICLE_CAPTURE_FILE_PREFIX, VISUAL_NO_PROVIDER_RECOMMENDATION, VisualReason, } from '@reticlehq/core';
3
3
  import { ReticleTool } from '../tools/tool-names.js';
4
4
  import { sessionIdShape } from '../tools/tool-kit.js';
5
+ import { ratioSchema } from '../tools/numeric-bounds.js';
5
6
  import { asNumber, asRecord, asString } from '../tools/tools-helpers.js';
6
7
  import { diffPng } from './visual-diff.js';
7
8
  import { VisualStore } from './visual-store.js';
@@ -148,19 +149,51 @@ function isCompletePng(bytes) {
148
149
  * `full-page-unsupported` — a viewport image returned as though it were the whole scroll height is a
149
150
  * baseline that says nothing about the content below the fold, and a later diff would call it green.
150
151
  */
152
+ /**
153
+ * Which runtime this session is, for scoping a visual artifact.
154
+ *
155
+ * Undefined when the session cannot be resolved or its SDK never reported one — and undefined means
156
+ * the flat legacy path, so a baseline captured before any of this keeps matching.
157
+ */
158
+ function runtimeOf(deps, sessionId) {
159
+ try {
160
+ return deps.sessions.resolve(sessionId).runtime;
161
+ }
162
+ catch {
163
+ return undefined;
164
+ }
165
+ }
151
166
  async function capture(deps, sessionId, args) {
152
167
  const provider = screenshotProvider(deps);
153
168
  if (provider !== undefined) {
154
169
  const session = deps.sessions.resolve(sessionId);
155
170
  const png = await provider.screenshot(session.url, await buildOpts(deps, sessionId, args));
171
+ // A driven browser renders the session's URL in a BROWSER — so the pixels are web even when the
172
+ // session named is a desktop window. Scoping those under the desktop runtime would corrupt that
173
+ // runtime's baseline with a picture of a different renderer.
156
174
  if (png !== undefined)
157
- return { png };
175
+ return { png, runtime: AppRuntime.WEB };
158
176
  }
177
+ // The window's own backing store, via the Electron/Tauri adapter — the only route whose pixels
178
+ // really are the desktop app.
159
179
  const desktop = await desktopCapture(deps, sessionId, true === args['fullPage']);
160
180
  if (desktop.png !== undefined)
161
- return { png: desktop.png };
181
+ return { png: desktop.png, runtime: runtimeOf(deps, sessionId) };
162
182
  if (desktop.reason !== undefined)
163
183
  return { reason: desktop.reason };
184
+ /*
185
+ * A LEASED page is a real browser page, so the pixels were always there — the visual tools simply
186
+ * had no route to them. Without this, `reticle_screenshot` answered "no provider" for every context
187
+ * an agent can actually acquire, which made visual regression impossible on exactly the isolated
188
+ * contexts the pool exists to hand out. Tried last: a CDP provider, when there is one, is driving
189
+ * the page the caller means, and a lease is the fallback rather than a competitor.
190
+ */
191
+ const leased = sessionId === undefined
192
+ ? undefined
193
+ : await deps.pool?.screenshotLease(sessionId, { fullPage: true === args['fullPage'] });
194
+ // A leased page is a real browser page, whatever the session is.
195
+ if (leased !== undefined)
196
+ return { png: leased, runtime: AppRuntime.WEB };
164
197
  return {
165
198
  reason: provider === undefined ? VisualReason.NO_PROVIDER : VisualReason.CAPTURE_FAILED,
166
199
  };
@@ -215,13 +248,16 @@ export const VISUAL_TOOLS = [
215
248
  },
216
249
  handler: async (deps, args) => {
217
250
  const sessionId = asString(args['sessionId']);
218
- const { png, reason } = await capture(deps, sessionId, args);
251
+ const { png, reason, runtime } = await capture(deps, sessionId, args);
219
252
  if (png === undefined) {
220
253
  return reason === VisualReason.NO_PROVIDER ? noProvider : { ok: false, reason };
221
254
  }
222
255
  const name = asString(args['name']) ?? 'default';
223
256
  const store = new VisualStore(deps.fs, deps.reticleRoot);
224
- const path = await store.saveBaseline(name, png);
257
+ // Scoped to the runtime that produced it: an Electron window, a Tauri webview and a browser
258
+ // tab do not render the same url the same way, and one shared baseline makes every
259
+ // cross-runtime diff wrong. See visualDir.
260
+ const path = await store.saveBaseline(name, png, runtime);
225
261
  return { ok: true, saved: true, name, path, bytes: png.length };
226
262
  },
227
263
  },
@@ -237,8 +273,10 @@ export const VISUAL_TOOLS = [
237
273
  ref: z.string().optional(),
238
274
  clip: rectShape.optional(),
239
275
  masks: z.array(rectShape).optional(),
240
- maxRatio: z.number().optional(),
241
- threshold: z.number().optional().describe('Pixel difference threshold (0–1). Default: 0.01.'),
276
+ maxRatio: ratioSchema.optional(),
277
+ threshold: ratioSchema
278
+ .optional()
279
+ .describe('Pixel difference threshold (0–1). Default: 0.01.'),
242
280
  ...sessionIdShape,
243
281
  },
244
282
  outputSchema: {
@@ -255,14 +293,21 @@ export const VISUAL_TOOLS = [
255
293
  handler: async (deps, args) => {
256
294
  const baseline = asString(args['baseline']) ?? '';
257
295
  const store = new VisualStore(deps.fs, deps.reticleRoot);
258
- const baselineBytes = await store.readBaseline(baseline);
259
- if (baselineBytes === undefined)
260
- return { ok: false, reason: VisualReason.BASELINE_MISSING };
296
+ // Capture FIRST, then fetch the baseline for the runtime that produced these pixels. Reading it
297
+ // by the session's runtime looked equivalent and is not: the route decides the renderer, so a
298
+ // desktop session captured through a driven browser must be compared against the WEB baseline,
299
+ // not the desktop one. Comparing across renderers is a confident wrong diff in one direction
300
+ // and a silently overwritten baseline in the other.
261
301
  const sessionId = asString(args['sessionId']);
262
- const { png: current, reason } = await capture(deps, sessionId, args);
302
+ const { png: current, reason, runtime } = await capture(deps, sessionId, args);
263
303
  if (current === undefined) {
264
304
  return reason === VisualReason.NO_PROVIDER ? noProvider : { ok: false, reason };
265
305
  }
306
+ // A baseline from another runtime is not missing by accident — it is a different rendering, and
307
+ // "no baseline for this one" is the honest answer.
308
+ const baselineBytes = await store.readBaseline(baseline, runtime);
309
+ if (baselineBytes === undefined)
310
+ return { ok: false, reason: VisualReason.BASELINE_MISSING };
266
311
  const masks = rectsFrom(args['masks']);
267
312
  const threshold = asNumber(args['threshold']);
268
313
  const maxRatio = asNumber(args['maxRatio']);
@@ -276,7 +321,7 @@ export const VISUAL_TOOLS = [
276
321
  if (diffBytes === undefined) {
277
322
  return { ok: false, ...verdict, reason: VisualReason.DIMENSION_MISMATCH };
278
323
  }
279
- const diffPath = await store.saveDiff(baseline, diffBytes);
324
+ const diffPath = await store.saveDiff(baseline, diffBytes, runtime);
280
325
  return { ok: true, ...verdict, diffPath };
281
326
  },
282
327
  },
package/docs/README.md CHANGED
@@ -26,7 +26,7 @@ Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `d
26
26
  | [faq.mdx](faq.mdx) | production, frameworks, comparisons, and the honest limits |
27
27
  | [tools-overview.mdx](tools-overview.mdx) | the 18 advertised tools, the 30 in the cold tail, and why |
28
28
  | [tools-snapshot.mdx](tools-snapshot.mdx) | `reticle_snapshot`: three modes, from full tree to a 25-token route check |
29
- | [tools-query.mdx](tools-query.mdx) | `reticle_query` finds elements by testing-library semantics |
29
+ | [tools-query.mdx](tools-query.mdx) | `reticle_query` finds elements by their reported roles, names and labels |
30
30
  | [tools-inspect.mdx](tools-inspect.mdx) | `reticle_inspect`: one element, down to source and design tokens |
31
31
  | [tools-navigate.mdx](tools-navigate.mdx) | `reticle_navigate`, and why `ok` does not mean the page arrived |
32
32
  | [tools-act.mdx](tools-act.mdx) | `reticle_act` acts, proves nothing, and says so |
@@ -46,6 +46,7 @@ Everything here is published to [docs.reticle.sh](https://docs.reticle.sh) by `d
46
46
  | [best-practices.mdx](best-practices.mdx) | the habits that make a verdict worth trusting |
47
47
  | [skill-file.mdx](skill-file.mdx) | the paste-one-URL skill that teaches an agent Reticle |
48
48
  | [agent-cheatsheet.md](agent-cheatsheet.md) | the condensed version an agent keeps in context |
49
+ | [reticle-manual.md](reticle-manual.md) | GENERATED: what each tool actually returned when it was called, per argument shape |
49
50
  | [for-agents.md](for-agents.md) | how to fetch these docs as Markdown or `llms.txt` |
50
51
  | [architecture.md](architecture.md) | how it works, and why it is built this way |
51
52
  | [platform-integration.md](platform-integration.md) | Vite, Next, Remix, Astro, plain HTML |
@@ -20,7 +20,7 @@ These are thin clients over the `/v1` API. The moat is the server, not the verbs
20
20
  | `~/.reticle/credentials.json` | Project-scoped API keys from `reticle link`, keyed by `projectId` | Yes |
21
21
  | `<repo>/.reticle/cloud.json` | `{ projectId, projectName, url, sync, verify }`. The non-secret binding | No, commit it |
22
22
 
23
- Auth for any command is `RETICLE_CLOUD_KEY` from the environment (the agent path) if set, otherwise the login token. `RETICLE_CLOUD_URL` overrides the endpoint; the default is `http://localhost:8890`.
23
+ Auth for any command is `RETICLE_CLOUD_KEY` from the environment (the agent path) if set, otherwise the login token. `RETICLE_CLOUD_URL` overrides the endpoint; the default is `http://localhost:8890`. When a command falls back to that default without `RETICLE_CLOUD_URL` (or a saved session URL), it prints a one-line notice on stderr; stdout stays pure JSON for agents.
24
24
 
25
25
  ## The commands
26
26
 
@@ -51,8 +51,10 @@ When nothing has connected, the `sessions` line fails and the daemon's own diagn
51
51
  | `chromium` | Whether the exact Chromium revision the bundled Playwright wants is on disk. The most common silent failure |
52
52
  | `daemon` | Whether the port holds a Reticle daemon, a foreign process (named where possible), or nothing. Adds a `version` line when the daemon's version or contract fingerprint disagrees with the CLI's |
53
53
  | `sessions` | Whether any page has actually connected. Zero is a FAILING check rather than a neutral note, because it is the state the setup most often stalls in: wired correctly, daemon up, nothing dialled in. When it is zero the daemon's own no-session diagnosis prints below the checklist |
54
+ | `agent link` | Whether an MCP client has listed Reticle's tools on this port **and actually called one**. Every other row here checks a component; this one checks the hop between your agent and the daemon. It is possible for the SDK to be injected, a session to be live, and your client to show every tool enabled, while no request has ever crossed from the agent. That state passes every other check and is the one people lose hours to |
54
55
  | `bridge port` | The port your app must dial, spelled out because mixing it up with the dev server port is the most common setup failure |
55
56
  | `port check` | Only when your project's configured port disagrees with the one the daemon is on. Prints the mismatch rather than leaving you to spot it across two lines |
57
+ | `sibling` | Only when a well-known Reticle port other than this daemon's has a listener. An observation, not a diagnosis: that listener may or may not be related |
56
58
  | `daemon log` | Where the structured daemon log lives |
57
59
  | `tracing` | How to turn that log into a per-stage trace |
58
60
  | `desktop` | Only on a desktop project. Every Electron and Tauri misconfiguration here fails silently, so it is diagnosed explicitly |
@@ -21,8 +21,10 @@ Most people never type this. Your agent runs [`reticle mcp`](/cli/mcp), which st
21
21
  | `--headless` | boolean | `true` for `serve` | Hide the browser |
22
22
  | `--headed` | boolean | `false` | Show it. `serve` owns the pooled browser behind leases, which is batch work, so it hides by default |
23
23
  | `--http` | boolean | `false` | Also expose the HTTP verify endpoint |
24
- | `--http-port N` | number | unset | Port for that endpoint |
25
- | `--http-token T` | string | unset | Bearer token the endpoint requires |
24
+ | `--http-port N` | number | unset (`7331`) | Port for that endpoint. Requires `--http`. |
25
+ | `--http-token T` | string | unset | Bearer token the endpoint requires. Requires `--http`. |
26
+
27
+ The HTTP flags are honoured or refused, never silently dropped: against an already-running daemon that does not serve the requested verify port, `serve --http` exits 1 and names both ports. A running daemon keeps the flags it was started with, so `reticle stop`, then serve again. A verify port that cannot be bound fails the daemon start with a `reticle_daemon_start_failed` line naming that port.
26
28
 
27
29
  ## What it prints
28
30
 
@@ -50,11 +50,10 @@ Call log:
50
50
 
51
51
  <Warning>
52
52
  `verify` binds the bridge port itself and has **no `--port` flag**: passing one is rejected as
53
- `unknown argument '--port'`. If a daemon is already on the port, `verify` dies with a raw `Error:
54
- listen EADDRINUSE: address already in use 127.0.0.1:4400` stack trace before it drives anything.
55
- Stop the daemon first, or move `verify` with the `RETICLE_PORT` environment variable. This bites
56
- most often on a developer machine, where an agent has usually left a daemon running; in CI the
57
- port is normally free.
53
+ `unknown argument '--port'`. If a daemon is already on the port, `verify` does not start a second
54
+ one: it prints three ways out (ask the running daemon via `reticle_run`, stop it, or move with
55
+ `RETICLE_PORT`) rather than a raw listen error. This bites most often on a developer machine,
56
+ where an agent has usually left a daemon running; in CI the port is normally free.
58
57
  </Warning>
59
58
 
60
59
  ## Exit codes
package/docs/cli.mdx CHANGED
@@ -4,7 +4,7 @@ description: Every reticle command. What it does, what it prints, and what it ex
4
4
  icon: terminal
5
5
  ---
6
6
 
7
- The `reticle` CLI wires Reticle into a project (`init`), runs and diagnoses the daemon your app connects to (`serve`, `status`, `doctor`, `kill`, `restart`), and gates a build on verification in CI (`verify`, `affected`, `gate`). This page is the index; each command has its own page with real captured output and measured exit codes.
7
+ The `reticle` CLI installs Reticle into a project and proves the install works (`init`), runs and diagnoses the daemon your app connects to (`serve`, `status`, `doctor`, `kill`, `restart`), and gates a build on verification in CI (`verify`, `affected`, `gate`). This page is the index; each command has its own page with real captured output and measured exit codes.
8
8
 
9
9
  The CLI is mostly for you, not your agent. Your agent talks MCP; you use these to set things up, work out why nothing connected, and wire verification into CI.
10
10
 
@@ -32,12 +32,16 @@ npx @reticlehq/server <command>
32
32
 
33
33
  ### `reticle init`
34
34
 
35
- Wires Reticle into the project in the current directory.
35
+ Wires Reticle into the project in the current directory, then boots the app, proves a session connected and drives one flow to a verdict. It exits non-zero if no verdict was produced, and prints what is left to do.
36
36
 
37
37
  ```
38
- reticle init [--dry-run] [--port N] [--no-mcp] [--no-install] [--app <dir>]
38
+ reticle init [--flow "<what to drive>"] [--env KEY=VALUE]... [--app <dir>] [--license <key>]
39
+ [--json] [--files-only] [--no-open] [--no-drive] [--dry-run]
40
+ [--port N] [--no-mcp] [--no-install] [--timeout S] [--drive-model M]
39
41
  ```
40
42
 
43
+ `--flow`, `--env` and `--app` are the answers the command cannot work out for itself: which journey proves what you care about, what the app needs to reach a usable state, and which app in a monorepo. `--files-only` is what `init` did before it learned to boot the app: it still registers the MCP server and pre-approves Reticle's tools, so it doubles as the upgrade path for an existing install.
44
+
41
45
  <Card title="Full walkthrough with real output" icon="wand-magic-sparkles" href="/install-agentic">
42
46
  What it writes, and how to read its four status marks.
43
47
  </Card>
package/docs/desktop.mdx CHANGED
@@ -214,7 +214,7 @@ Alternatively, since an Electron renderer _is_ Chromium, `--remote-debugging-por
214
214
 
215
215
  ```toml
216
216
  [dependencies]
217
- reticle-tauri = "0.1"
217
+ reticle-tauri = "2.13"
218
218
  ```
219
219
 
220
220
  ```rust
package/docs/docs.json CHANGED
@@ -32,7 +32,7 @@
32
32
  "navigation": {
33
33
  "versions": [
34
34
  {
35
- "version": "2.11.0",
35
+ "version": "2.13.0",
36
36
  "default": true,
37
37
  "tabs": [
38
38
  {
@@ -153,7 +153,7 @@
153
153
  },
154
154
  {
155
155
  "group": "Long form",
156
- "pages": ["agent-cheatsheet", "usage", "faq"]
156
+ "pages": ["agent-cheatsheet", "reticle-manual", "usage", "faq"]
157
157
  }
158
158
  ]
159
159
  },
package/docs/gates.md CHANGED
@@ -69,7 +69,7 @@ Each gate exists because the ones above it are blind to something. That blindnes
69
69
  | **Integration** | `pnpm test:integration` | real headless Chromium: browser pool, crash isolation, framework adapters, `withReticle` | the MCP surface, the daemon | `e2e` |
70
70
  | **Web e2e battery** | `pnpm test:e2e` | 32 specs against 3 booted servers and a real browser (the tool surface, the daemon lifecycle, transport faults, telemetry, trace shape), plus the soak | desktop runtimes; the install | `e2e` |
71
71
  | **Desktop battery** | `pnpm test:e2e:desktop` | a real Electron main process and a **packaged** Tauri binary, driven headless | web-only paths | `desktop-e2e` |
72
- | **Install gate** | `pnpm gate:install` | scaffolds 3 pristine apps, publishes this checkout to a local Verdaccio, lets `init` install itself, boots each app in a real browser, polls for a session | install _complexity_; see [`fixtures.md`](./fixtures.md) | `install-gate` |
72
+ | **Install gate** | `pnpm gate:install` | scaffolds 3 pristine apps, publishes this checkout to a local Verdaccio, lets `init` install itself, boots each app in a real browser, polls for a session that advertised capabilities | install _complexity_; see [`fixtures.md`](./fixtures.md) | `install-gate` |
73
73
  | **Matrix records** | `pnpm matrix:validate` | every submitted client-compat record is well-formed | whether the client actually works | `matrix-records` |
74
74
  | **Windows** | (CI only) | that the code runs at all on the majority platform | e2e; Windows is unit-only | `windows` |
75
75
  | **Rust** | `cargo fmt/clippy/check` | `packages/tauri` compiles and lints on Linux, macOS, and cross-checks Windows | everything JS | `rust`, `rust-macos` |
@@ -4,7 +4,7 @@ description: 'Zero to your agent verifying your real app, step by step, with wor
4
4
  icon: rocket
5
5
  ---
6
6
 
7
- **To get started with Reticle: run `npx @reticlehq/server init` in your project root, restart your dev server, restart your coding agent, then open your app in a browser and ask the agent to drive a flow.** Reticle is a verification layer that embeds a dev-only SDK in your running web app so an AI coding agent can prove a change works instead of guessing. It needs Node 20 or newer, an app you run locally, and an agent that speaks MCP.
7
+ **To get started with Reticle: run `npx @reticlehq/server init --flow "<the journey worth proving>"` in your project root.** That one command wires your project, starts your dev server, opens the app, waits for it to connect, and drives that flow to a verdict. You do not restart anything and you do not drive it yourself. Reticle is a verification layer that embeds a dev-only SDK in your running web app so an AI coding agent can prove a change works instead of guessing. It needs Node 20 or newer, an app you run locally, and an agent that speaks MCP.
8
8
 
9
9
  > **Looking for the fast path?** [Quickstart](/quickstart) gets you to a real verdict in five minutes, and every response on it was captured live. [Agentic install](/install-agentic) and [Manual install](/install-manual) cover setup in detail, per agent and per framework.
10
10
  >
@@ -76,7 +76,19 @@ It detects your framework, package manager, and React version, then:
76
76
 
77
77
  The bridge + MCP server is a single process that serves all your projects, so it's registered at **user scope**, not in a per-project `.mcp.json`. Only the SDK (the `reticle()` plugin / connect call) is added per project.
78
78
 
79
- Re-running is safe (already-registered/already-patched steps are skipped). Preview without writing via `npx @reticlehq/server init --dry-run`. Flags: `--dry-run`, `--port N`, `--no-mcp`, `--no-install`, `--app <dir>`.
79
+ Re-running is safe: already-registered and already-patched steps are skipped, and on a wired project it goes straight to proving the app still works. Preview without writing via `npx @reticlehq/server init --dry-run`.
80
+
81
+ `init` does not stop at writing files. It starts your dev server (restarting one whose bundle predates the config edit), opens the app, waits for a session to connect from inside it, and drives one flow to a verdict, which it saves so later checks are a single call with no model involved. It exits non-zero if no verdict was produced and prints what is left to do.
82
+
83
+ Three flags carry what the command cannot work out for itself:
84
+
85
+ | Flag | What only you know |
86
+ | --- | --- |
87
+ | `--flow "<what>"` | Which journey proves the thing you care about. It can list the buttons on your page; it cannot know that checkout matters and the theme toggle does not. |
88
+ | `--env KEY=VALUE` | What your app needs to reach a usable state: the key from `.env.example`, the mock backend, the variable that skips an auth wall. Repeatable. |
89
+ | `--app <dir>` | Which app in a monorepo. It finds the servable ones; only you know which you are working in. |
90
+
91
+ The rest are dials: `--license <key>` (writes it to `.env` and keeps `.env` out of git), `--json` (one object for an agent to read), `--files-only` (write, register, pre-approve, and stop, which is what `init` did before it learned to boot the app, and what an existing install re-runs to pick up new wiring), `--no-open`, `--no-drive`, `--dry-run`, `--port N`, `--no-mcp`, `--no-install`.
80
92
 
81
93
  Then restart your dev server and skip to [Step 4](#step-4-run-it-and-verify-the-connection). The manual steps below explain what `init` sets up, if you prefer to wire it yourself.
82
94
 
@@ -310,6 +322,8 @@ export default defineConfig({
310
322
 
311
323
  ## Step 4: Run it and verify the connection
312
324
 
325
+ > `reticle init` does this for you: it starts the dev server, opens the app and waits for the session. Read on only if you are wiring by hand, or if it told you it could not.
326
+
313
327
  1. Start your app's dev server as usual (`npm run dev`).
314
328
  2. Open it in the browser (the SDK connects when the page loads).
315
329
  3. In your agent, ask it to confirm the connection:
@@ -328,6 +342,8 @@ If the list is empty, see [Troubleshooting](#troubleshooting).
328
342
 
329
343
  ## Step 5: Your first verification
330
344
 
345
+ > `reticle init --flow "<what>"` drives this for you and saves the flow. This section is what it does, for when you want to do it yourself.
346
+
331
347
  Now just talk to your agent in plain language. For example:
332
348
 
333
349
  > "Add a 'Refresh' button to the header that re-fetches the dashboard data, then use Reticle to verify clicking it fires `GET /api/dashboard` and shows no console errors."
@@ -490,7 +506,7 @@ pnpm add @reticlehq/next
490
506
 
491
507
  ### What exactly does `reticle init` change in my project?
492
508
 
493
- Four things, and none of them are mysterious: a `.reticle.json` project config, your build config (the `reticle()` Vite plugin, or `withReticle` in `next.config`), a dev-only capabilities file at `src/reticle-dev.ts` (or `app/reticle-dev.tsx` on Next.js), and your agent's rule files. It also registers the MCP server globally, which is a once-per-machine step rather than a per-project one. Run `npx @reticlehq/server init --dry-run` first to see the exact plan before anything is written.
509
+ Four files, and none of them are mysterious: a `.reticle.json` project config, your build config (the `reticle()` Vite plugin, or `withReticle` in `next.config`), a dev-only capabilities file at `src/reticle-dev.ts` (or `app/reticle-dev.tsx` on Next.js), and your agent's rule files. It then starts your dev server, opens the app and drives one flow, none of which changes your source: the dev server is left running for you afterwards, and the only file the drive may edit is the capabilities file, and only when your app registers none. It also registers the MCP server globally, which is a once-per-machine step rather than a per-project one. Run `npx @reticlehq/server init --dry-run` first to see the exact plan before anything is written.
494
510
 
495
511
  ### Do I have to re-register the MCP server for every project?
496
512
 
package/docs/index.mdx CHANGED
@@ -14,7 +14,7 @@ It answers the only question that matters: did the change actually work? On Reac
14
14
 
15
15
  ## Install it: paste this into your coding agent
16
16
 
17
- You do not install Reticle by hand. Copy the block below into Claude Code, Cursor, Copilot, Codex, Windsurf, OpenCode, or any MCP agent, and let the agent wire its own workspace. It ends with the only definition of "installed" that counts: one real flow driven, one real verdict returned.
17
+ You do not install Reticle by hand, and neither does your agent: it runs one command that does the whole thing. Copy the block below into Claude Code, Cursor, Copilot, Codex, Windsurf, OpenCode, or any MCP agent, and let it wire its own workspace. It ends with the only definition of "installed" that counts: one real flow driven, one real verdict returned.
18
18
 
19
19
  ```text
20
20
  Reticle is the proof layer for AI coding agents. It runs a dev-only SDK inside my
@@ -30,12 +30,15 @@ silent 500.
30
30
 
31
31
  Install it now:
32
32
 
33
- RETICLE_INSTALL_SOURCE=docs_site npx @reticlehq/server@latest init
33
+ RETICLE_INSTALL_SOURCE=docs_site npx @reticlehq/server@latest init \
34
+ --flow "<pick the journey that matters in my app and name it here>"
34
35
 
35
- Then follow https://docs.reticle.sh/install-agentic.md and, if anything needs a
36
- manual edit, https://docs.reticle.sh/install-manual.md. Do not stop until you have
37
- driven one real flow in my app and produced a verdict. That, not a config file, is
38
- what "installed" means.
36
+ That one command wires the project, starts the dev server, opens the app, waits
37
+ for it to connect and drives that flow to a verdict. Do not walk it by hand: read
38
+ what it prints, do anything it says is outstanding, and re-run it, which is safe.
39
+ It exits non-zero until a verdict exists, and that, not a config file, is what
40
+ "installed" means. Only if it could not run at all, follow
41
+ https://docs.reticle.sh/install-manual.md.
39
42
 
40
43
  Afterwards, use it whenever you change any user-facing behaviour.
41
44
  ```
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  title: 'Agentic install: let the agent do it'
3
3
  sidebarTitle: Agentic install
4
- description: Run npx @reticlehq/server init and let your coding agent wire Reticle into the project. What it changes, what it asks, and how to read its report.
4
+ description: One command wires Reticle into your project, boots the app, proves a session connected and drives one flow to a verdict. What it changes, what you pass it, and how to read what it returns.
5
5
  icon: wand-magic-sparkles
6
6
  ---
7
7
 
@@ -195,21 +195,47 @@ reticle init [--dry-run] [--port N] [--no-mcp] [--no-install] [--app <dir>]
195
195
  only make sense once the tools are reachable.
196
196
  ```
197
197
 
198
- | Flag | When you want it |
199
- | -------------- | -------------------------------------------------------------------------- |
200
- | `--dry-run` | Always, the first time. |
201
- | `--app <dir>` | Monorepos. Without it, `init` finds several apps and asks which you meant. |
202
- | `--no-mcp` | Your MCP config is managed elsewhere (dotfiles, a team template). |
203
- | `--no-install` | You want to add the dependencies yourself, at your own versions. |
204
- | `--port N` | Something else already owns the default port. |
198
+ Three of these are answers only the caller has. `init` reads your repository; it cannot read your request, and these live only there.
205
199
 
206
- ## Then restart two things
200
+ | Flag | When you want it |
201
+ | --- | --- |
202
+ | `--flow "<what>"` | **Name the journey worth proving.** `init` can list the buttons on a page; it cannot know that checkout matters and the theme toggle does not. Naming it is the difference between a drive that finishes and one that spends its budget looking for something to do. |
203
+ | `--env KEY=VALUE` | What the app needs to reach a usable state: the key from `.env.example`, the mock backend, the variable that skips an auth wall. Repeatable, and a value may contain spaces and equals signs. Without it a real app sits on a login screen and there is no flow to drive. |
204
+ | `--app <dir>` | Monorepos. `init` can find the apps that are servable; only your request says which one you are working in. |
205
+ | `--license <key>` | Writes `RETICLE_LICENSE_KEY` to `.env` and keeps `.env` out of git. Do not do those two by hand. |
206
+ | `--json` | One object on stdout: what was wired, what connected, the verdict, and an `agentTodo` array. For agents. |
207
+ | `--files-only` | Write the files, register the MCP server with every agent on the machine, pre-approve Reticle's tools, and stop: no dev server, no drive. What `init` did before it learned to boot the app, and the upgrade path for a machine that installed Reticle on an earlier version. |
208
+ | `--no-open` | Do not open a browser: CI, a container, an SSH session, or a tab you already have. |
209
+ | `--no-drive` | Stop once a session connects and leave the verdict to you. The only honest way to skip it. |
210
+ | `--dry-run` | See the plan before anything is written. |
211
+ | `--no-mcp` | Your MCP config is managed elsewhere (dotfiles, a team template). |
212
+ | `--no-install` | You want to add the dependencies yourself, at your own versions. |
213
+ | `--port N` | Something else already owns the bridge port. Not the dev server's port. |
207
214
 
208
- This trips up almost everyone, so `init` says it twice and so will we.
215
+ ## Already installed? Mostly automatic
209
216
 
210
- **Restart your dev server.** The Vite plugin is new; the running process doesn't have it.
217
+ The first time `reticle mcp` starts on a new version it applies the pre-approval rules for the agents it finds, once, and records that it did. You get that by upgrading. There is nothing to type.
211
218
 
212
- **Restart your agent.** Claude Code, or reload the window in Cursor, or hit Start in `.vscode/mcp.json` in VS Code. Your agent read its server list at startup, before Reticle existed, and no slash command re-reads it. `/mcp` manages servers already loaded, so it cannot pick up a new one. This is a once-per-machine annoyance: Reticle registers globally, so every later project starts with the tools already there.
219
+ One case is deliberately left out. Creating Cursor's `permissions.json` when you do not already have one supersedes whatever you approved inside Cursor itself, so a version bump doing it silently would make your OTHER MCP servers start prompting again, with nothing to connect that to us. Reticle defers it and waits to be asked:
220
+
221
+ ```bash
222
+ npx @reticlehq/server@latest init --files-only
223
+ ```
224
+
225
+ That writes the files, registers the MCP server with every agent it finds, pre-approves Reticle's tools so the per-call Accept dialog stops, and stops there: no dev server, no browser, no drive. Every step is idempotent, so a repo that is already wired reports "already" and changes nothing.
226
+
227
+ Two things to know afterwards:
228
+
229
+ - **A GUI client reads its config at startup.** Cursor, Antigravity, Claude Desktop and VS Code need a window reload before the new rules take effect. The CLIs pick them up on their next run.
230
+ - **The pre-approval is scoped to `reticle` alone**, never a blanket rule for every MCP server, and never a global auto-run switch. If a client's approval file did not exist before, `init` says so in a line, because in Cursor's case that file supersedes what you had approved inside the app.
231
+
232
+ Drop `--files-only` to get the full run: boot the app, drive a flow, return a verdict.
233
+
234
+ ## The two restarts you no longer have to think about
235
+
236
+ **Your dev server: `init` handles it.** A dev server that was already running read your build config before `init` edited it, so it keeps serving the old bundle and nothing connects. `init` restarts it and waits for the port to answer, rather than telling you to.
237
+
238
+ **Your agent: not on the critical path any more.** Your agent read its MCP server list at startup, before Reticle existed, and no slash command re-reads it. `/mcp` manages servers already loaded, so it cannot pick up a new one. That used to mean stopping the install to restart. It does not now: the flow is driven by a child agent process started after registration, which reads the list `init` just wrote. Your own session picks the tools up whenever you next start it, and nothing is waiting on that. This is a once-per-machine annoyance in any case, because Reticle registers globally.
213
239
 
214
240
  ## Confirm it worked
215
241
 
@@ -159,7 +159,7 @@ Screenshots and headless mode need the Rust crate, which is versioned independen
159
159
 
160
160
  ```toml
161
161
  [dependencies]
162
- reticle-tauri = "0.1"
162
+ reticle-tauri = "2.13"
163
163
  ```
164
164
 
165
165
  ```rust
@@ -6,13 +6,13 @@ icon: window
6
6
 
7
7
  `@reticlehq/browser` is the Reticle SDK that runs inside your page. It installs the observers, builds semantic snapshots, executes actions, and talks to the bridge. Install it directly only if you are **not** on React or want to call `connect()` yourself, because [`@reticlehq/react`](/packages/react) already re-exports all of it.
8
8
 
9
- **Apache 2.0. Depends on `@reticlehq/core` and `@testing-library/dom`.**
9
+ **Apache 2.0. Depends on `@reticlehq/core`.**
10
10
 
11
11
  ## Why it exists
12
12
 
13
13
  This is what makes Reticle different from a browser-automation tool. Because it runs _inside_ the app rather than driving it from outside, it can see a state mutation and a fired signal, not just a rendered pixel. It never imports a Node API; that boundary is enforced by the dependency graph.
14
14
 
15
- `@testing-library/dom` is why [`reticle_query`](/tools-query) speaks role, label and testid instead of CSS selectors.
15
+ [`reticle_query`](/tools-query) speaks role, label and testid instead of CSS selectors through its own local accessibility engine: one engine computes both what elements are called and what they match by, so a reported identity always round-trips.
16
16
 
17
17
  ## When you need it directly
18
18
 
@@ -64,7 +64,7 @@ await server.close();
64
64
  | `reticleRoot` | `string` | `cwd()/.reticle` |
65
65
  | `pairingTokenDir` | `string` | `~/.reticle` |
66
66
  | `now` | `() => number` | `Date.now` |
67
- | `toolProfile` | `string` | `RETICLE_TOOL_PROFILE`, else `full`. `core` serves the lean surface |
67
+ | `toolProfile` | `string` | retired names (`core`/`full`/…) still map. Live switch is `RETICLE_ADVERTISE_ALL_TOOLS=1`. Default is the lean surface |
68
68
  | `httpVerify` | `boolean` | `false` |
69
69
  | `httpVerifyPort` | `number` | `RETICLE_VERIFY_DEFAULT_PORT` (`7331`) |
70
70
  | `httpVerifyToken` | `string` | `RETICLE_VERIFY_TOKEN` |
package/docs/packages.mdx CHANGED
@@ -8,9 +8,11 @@ icon: cubes
8
8
  Reticle is eleven packages, and most people install two. This page exists so you can tell which two, and so that the ones you skip stop looking mysterious.
9
9
 
10
10
  <Note>
11
- The ten npm packages ship together at one version: whatever `npm view @reticlehq/core version`
12
- says, every other `@reticlehq/*` package says too. The Rust crate `reticle-tauri` is versioned
13
- **independently**. That is deliberate, not drift.
11
+ Everything ships together at one version: whatever `npm view @reticlehq/core version` says, every
12
+ other `@reticlehq/*` package says too, and so does the `reticle-tauri` crate on crates.io.
13
+
14
+ It was versioned independently until 2.12.0, and that turned out to mean _stuck_: the crate sat at `0.1.0` from the day it was written, the publish job skipped it every release because that version already existed, and no Rust-side fix reached anybody. Lockstep costs one line in the bump script and cannot fail that way.
15
+
14
16
  </Note>
15
17
 
16
18
  ## Which ones do I need?
@@ -70,7 +72,7 @@ Those rules are why the browser SDK cannot accidentally pull in a filesystem cal
70
72
 
71
73
  **Why it exists:** this is the part that makes Reticle different from a browser-automation tool. Because it runs _inside_ the app rather than driving it from outside, it can see a state mutation and a fired signal, not just a rendered pixel.
72
74
 
73
- **Depends on:** `@reticlehq/core`, `@testing-library/dom`. The latter is why [`reticle_query`](/tools-query) speaks role, label and testid rather than CSS selectors.
75
+ **Depends on:** `@reticlehq/core`. [`reticle_query`](/tools-query) speaks role, label and testid rather than CSS selectors through its own local accessibility engine, so what a snapshot reports is exactly what a query matches.
74
76
 
75
77
  **Install it directly when** you are not on React, or you want `connect()` under your own control:
76
78
 
@@ -199,13 +201,13 @@ A lint rule makes the signal layer self-enforcing, which is the only way a conve
199
201
 
200
202
  ## reticle-tauri
201
203
 
202
- **The Rust crate**, on crates.io. Versioned independently of the npm packages.
204
+ **The Rust crate**, on crates.io. Versioned in lockstep with the npm packages, so `2.11` here and `2.11` there mean the same release.
203
205
 
204
206
  **Why it exists:** Tauri IPC observation needs nothing on the Rust side; an `invoke('load_todos')` already reaches Reticle as `ipc://load_todos`. You only need this crate for screenshots and headless mode.
205
207
 
206
208
  ```toml
207
209
  [dependencies]
208
- reticle-tauri = "0.1"
210
+ reticle-tauri = "2.13"
209
211
  ```
210
212
 
211
213
  <Warning>
@@ -93,6 +93,23 @@ Live, clickable demo of each: `apps/vibe-builder-demo/` (set `BUG_MODE=…`). Pr
93
93
 
94
94
  ---
95
95
 
96
+ ## The minimal attach contract (for a harness or MCP host)
97
+
98
+ Reticle is a stdio MCP server. A host that wires it correctly does four things, and each one is a step Reticle can see:
99
+
100
+ 1. **Spawn it.** `npx @reticlehq/server mcp`, over stdio, one process per host. That process is the proxy: it starts the local daemon on demand, reconnects on its own when the stream drops, and answers from cache while a daemon comes back.
101
+ 2. **Complete `initialize`.** Reticle answers the handshake itself when the daemon is slow, so a host that waits for a reply gets one either way.
102
+ 3. **Send `tools/list`, and send it again on `notifications/tools/list_changed`.** This is the step hosts skip. Registering a server is not the same as enumerating it: a host can register Reticle and never ask for the tool list until the client is restarted, and the model then has no Reticle tools at all while the install looks healthy from every other angle. Reticle declares `tools.listChanged` so a host that honours the notification recovers without a restart.
103
+ 4. **Call the tools.** `tools/call`, with the tool name and its arguments.
104
+
105
+ `reticle status` reports how far a host has got. `mcpClient: "never-attached"` means no client has started the server on this port. `mcpClient: "never-enumerated"` means one started it and never asked for the tool list, which is the state a client restart fixes. `mcpClient: "enumerated"` means the client side is done, and anything still missing is the app rather than the host. The record is per port rather than per client, and it begins the first time a client starts a Reticle version that keeps it, so `status` says both of those out loud instead of naming a client it cannot see.
106
+
107
+ ### Hosts that cap the number of tools
108
+
109
+ Some editors cap the total tool count across every MCP server, which is why Reticle advertises a small surface instead of everything it can do. Nothing is out of reach: `reticle_tools { names: [...] }` lists the tools and returns the full argument grammar for the ones you name, and `reticle_run { tool, args }` invokes any of them, advertised or not. A host that is short on tool slots pays for the advertised handful and still reaches the whole surface through that pair. See [`reticle_tools` and `reticle_run`](/tools-tools-and-run).
110
+
111
+ ---
112
+
96
113
  ## Exact steps per platform
97
114
 
98
115
  The shape is identical (in-app SDK in the template → verify in the sandbox → act on the verdict); the specifics differ by where each platform runs the preview.
@@ -115,6 +115,14 @@ A passing route verdict quotes the transition itself:
115
115
 
116
116
  The app emitted a named signal via `reticle.signal()`. `dataMatches` is shallow JSON matching, and `*` means "present, any value".
117
117
 
118
+ `count` works here exactly as it does on `net`:
119
+
120
+ ```json
121
+ { "kind": "signal", "name": "order:placed", "count": 1 }
122
+ ```
123
+
124
+ **Exactly once.** A handler wired twice fires the signal twice and leaves the store in the right shape either way, so every state-only check stays green. `count: 0` is a claim of its own (the signal never fired) and is not the same as leaving `count` out, which asserts presence.
125
+
118
126
  Nothing outranks this. A `200` proves the server was reachable; a rendered row proves React ran. A signal is the application itself saying the thing succeeded. See [instrumentation](/instrumentation) for how to emit them.
119
127
 
120
128
  ### state