@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
@@ -0,0 +1,333 @@
1
+ /**
2
+ * The coding agents `init`'s own MCP registration does not reach, and where their config lives.
3
+ *
4
+ * `init` covers eight clients and only where it already finds them. That leaves real holes: VS
5
+ * Code's USER-scope mcp.json exists on machines today and init only ever writes the project-scope
6
+ * one, so a VS Code user has no tools outside the directory they ran init in. Zed, Warp, Kiro, Amp,
7
+ * Copilot CLI, Amazon Q, Factory Droid, Cline and Roo are not covered at all.
8
+ *
9
+ * Three rules, and the second is what keeps this honest:
10
+ *
11
+ * 1. A path with OFFICIAL documentation is written even when the agent is absent, so a later
12
+ * install finds itself already wired.
13
+ * 2. A path we cannot evidence is REFUSED. Cline's and Roo's live under VS Code globalStorage,
14
+ * which moves under Insiders, portable installs and a custom --user-data-dir; they are written
15
+ * only where the host's standard layout is present. A config file at a guessed location is one
16
+ * nobody reads, which is indistinguishable from success.
17
+ * 3. A format we cannot merge safely is never rewritten. TOML, an existing YAML, JSONC carrying
18
+ * comments: we print the snippet instead. Reformatting somebody's config to add one entry is
19
+ * not ours to do.
20
+ */
21
+ import { posix, win32 } from 'node:path';
22
+ export const AgentConfidence = {
23
+ /** Documented by the vendor. Safe to create before the agent exists. */
24
+ OFFICIAL: 'official',
25
+ /** Community-sourced. Only written where the host's own layout proves the path. */
26
+ COMMUNITY: 'community',
27
+ };
28
+ export const AgentAction = {
29
+ CREATE: 'create',
30
+ CREATE_YAML: 'create-yaml',
31
+ MERGE: 'merge',
32
+ ALREADY: 'already',
33
+ MANUAL: 'manual',
34
+ SKIP: 'skip',
35
+ };
36
+ const NPX = 'npx';
37
+ const SERVER_PACKAGE = '@reticlehq/server';
38
+ const MCP_SUBCOMMAND = 'mcp';
39
+ const RETICLE_KEY = 'reticle';
40
+ /** The stdio entry, in the shape most clients expect. */
41
+ const STDIO = { command: NPX, args: [SERVER_PACKAGE, MCP_SUBCOMMAND] };
42
+ const VSCODE_USER = {
43
+ darwin: 'Library/Application Support/Code/User',
44
+ linux: '.config/Code/User',
45
+ win32: 'AppData/Roaming/Code/User',
46
+ };
47
+ export const AGENT_CLIENTS = [
48
+ {
49
+ id: 'vscode-user',
50
+ name: 'VS Code (user scope)',
51
+ confidence: AgentConfidence.OFFICIAL,
52
+ format: 'json',
53
+ key: 'servers',
54
+ entry: { type: 'stdio', ...STDIO },
55
+ paths: {
56
+ darwin: `${VSCODE_USER.darwin}/mcp.json`,
57
+ linux: `${VSCODE_USER.linux}/mcp.json`,
58
+ win32: `${VSCODE_USER.win32}/mcp.json`,
59
+ },
60
+ marker: VSCODE_USER,
61
+ },
62
+ {
63
+ id: 'zed',
64
+ name: 'Zed',
65
+ confidence: AgentConfidence.OFFICIAL,
66
+ format: 'json',
67
+ // NOT `mcpServers`. Zed calls them context servers, and the wrong key writes a file it ignores.
68
+ key: 'context_servers',
69
+ entry: { ...STDIO, env: {} },
70
+ paths: {
71
+ darwin: '.config/zed/settings.json',
72
+ linux: '.config/zed/settings.json',
73
+ win32: 'AppData/Roaming/Zed/settings.json',
74
+ },
75
+ marker: { darwin: '.config/zed', linux: '.config/zed', win32: 'AppData/Roaming/Zed' },
76
+ skillDir: '.agents/skills/reticle',
77
+ },
78
+ {
79
+ id: 'copilot-cli',
80
+ name: 'GitHub Copilot CLI',
81
+ confidence: AgentConfidence.OFFICIAL,
82
+ format: 'json',
83
+ key: 'mcpServers',
84
+ entry: STDIO,
85
+ paths: {
86
+ darwin: '.copilot/mcp-config.json',
87
+ linux: '.copilot/mcp-config.json',
88
+ win32: '.copilot/mcp-config.json',
89
+ },
90
+ marker: { darwin: '.copilot', linux: '.copilot', win32: '.copilot' },
91
+ },
92
+ {
93
+ id: 'warp',
94
+ name: 'Warp',
95
+ confidence: AgentConfidence.OFFICIAL,
96
+ format: 'json',
97
+ key: 'mcpServers',
98
+ entry: STDIO,
99
+ paths: { darwin: '.warp/.mcp.json', linux: '.warp/.mcp.json', win32: '.warp/.mcp.json' },
100
+ marker: { darwin: '.warp', linux: '.warp', win32: '.warp' },
101
+ },
102
+ {
103
+ id: 'factory-droid',
104
+ name: 'Factory Droid',
105
+ confidence: AgentConfidence.OFFICIAL,
106
+ format: 'json',
107
+ key: 'mcpServers',
108
+ entry: { type: 'stdio', ...STDIO },
109
+ paths: { darwin: '.factory/mcp.json', linux: '.factory/mcp.json', win32: '.factory/mcp.json' },
110
+ marker: { darwin: '.factory', linux: '.factory', win32: '.factory' },
111
+ },
112
+ {
113
+ id: 'kiro',
114
+ name: 'Kiro',
115
+ confidence: AgentConfidence.OFFICIAL,
116
+ format: 'json',
117
+ key: 'mcpServers',
118
+ entry: STDIO,
119
+ paths: {
120
+ darwin: '.kiro/settings/mcp.json',
121
+ linux: '.kiro/settings/mcp.json',
122
+ win32: '.kiro/settings/mcp.json',
123
+ },
124
+ marker: { darwin: '.kiro', linux: '.kiro', win32: '.kiro' },
125
+ skillDir: '.kiro/steering',
126
+ },
127
+ {
128
+ id: 'amazon-q',
129
+ name: 'Amazon Q Developer CLI',
130
+ confidence: AgentConfidence.OFFICIAL,
131
+ format: 'json',
132
+ key: 'mcpServers',
133
+ entry: STDIO,
134
+ paths: {
135
+ darwin: '.aws/amazonq/mcp.json',
136
+ linux: '.aws/amazonq/mcp.json',
137
+ win32: '.aws/amazonq/mcp.json',
138
+ },
139
+ marker: { darwin: '.aws/amazonq', linux: '.aws/amazonq', win32: '.aws/amazonq' },
140
+ },
141
+ {
142
+ id: 'cline-cli',
143
+ name: 'Cline CLI',
144
+ confidence: AgentConfidence.OFFICIAL,
145
+ format: 'json',
146
+ key: 'mcpServers',
147
+ entry: STDIO,
148
+ paths: { darwin: '.cline/mcp.json', linux: '.cline/mcp.json', win32: '.cline/mcp.json' },
149
+ marker: { darwin: '.cline', linux: '.cline', win32: '.cline' },
150
+ },
151
+ {
152
+ id: 'amp',
153
+ name: 'Amp',
154
+ confidence: AgentConfidence.OFFICIAL,
155
+ format: 'json',
156
+ // A DOTTED key at the TOP level, not nested under "amp". Nesting writes a file Amp ignores.
157
+ key: 'amp.mcpServers',
158
+ entry: STDIO,
159
+ paths: {
160
+ darwin: '.config/amp/settings.json',
161
+ linux: '.config/amp/settings.json',
162
+ win32: '.config/amp/settings.json',
163
+ },
164
+ marker: { darwin: '.config/amp', linux: '.config/amp', win32: '.config/amp' },
165
+ },
166
+ {
167
+ id: 'cline',
168
+ name: 'Cline (VS Code extension)',
169
+ confidence: AgentConfidence.COMMUNITY,
170
+ format: 'json',
171
+ key: 'mcpServers',
172
+ entry: STDIO,
173
+ paths: {
174
+ darwin: `${VSCODE_USER.darwin}/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`,
175
+ linux: `${VSCODE_USER.linux}/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`,
176
+ win32: `${VSCODE_USER.win32}/globalStorage/saoudrizwan.claude-dev/settings/cline_mcp_settings.json`,
177
+ },
178
+ marker: {
179
+ darwin: `${VSCODE_USER.darwin}/globalStorage/saoudrizwan.claude-dev`,
180
+ linux: `${VSCODE_USER.linux}/globalStorage/saoudrizwan.claude-dev`,
181
+ win32: `${VSCODE_USER.win32}/globalStorage/saoudrizwan.claude-dev`,
182
+ },
183
+ parentMarker: VSCODE_USER,
184
+ },
185
+ {
186
+ id: 'roo-code',
187
+ name: 'Roo Code',
188
+ confidence: AgentConfidence.COMMUNITY,
189
+ format: 'json',
190
+ key: 'mcpServers',
191
+ entry: STDIO,
192
+ paths: {
193
+ darwin: `${VSCODE_USER.darwin}/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json`,
194
+ linux: `${VSCODE_USER.linux}/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json`,
195
+ win32: `${VSCODE_USER.win32}/globalStorage/rooveterinaryinc.roo-cline/settings/mcp_settings.json`,
196
+ },
197
+ marker: {
198
+ darwin: `${VSCODE_USER.darwin}/globalStorage/rooveterinaryinc.roo-cline`,
199
+ linux: `${VSCODE_USER.linux}/globalStorage/rooveterinaryinc.roo-cline`,
200
+ win32: `${VSCODE_USER.win32}/globalStorage/rooveterinaryinc.roo-cline`,
201
+ },
202
+ parentMarker: VSCODE_USER,
203
+ },
204
+ {
205
+ id: 'continue',
206
+ name: 'Continue',
207
+ confidence: AgentConfidence.OFFICIAL,
208
+ // YAML, whose `mcpServers` is a LIST of named entries. We create one; we never rewrite one.
209
+ format: 'yaml-manual',
210
+ key: 'mcpServers',
211
+ paths: {
212
+ darwin: '.continue/config.yaml',
213
+ linux: '.continue/config.yaml',
214
+ win32: '.continue/config.yaml',
215
+ },
216
+ marker: { darwin: '.continue', linux: '.continue', win32: '.continue' },
217
+ },
218
+ ];
219
+ const forPlatform = (p, os) => p[os];
220
+ /**
221
+ * Join for the platform the CALLER named, never the one this process happens to run on.
222
+ *
223
+ * Every planner here takes `platform` as an argument and claims to be pure over it — the doc below
224
+ * says the Windows rows are "testable from any machine". `node:path`'s bare `join` broke that claim
225
+ * silently in both directions: a mac planning win32 rows emitted `/` separators into paths Windows
226
+ * cannot use, and a Windows host planning linux rows emitted `\`. The second half is what turned
227
+ * the whole Windows CI job red — the pure planners returned `\home\u\.claude\settings.json`,
228
+ * every injected filesystem is keyed by the POSIX path the caller asked for, so every lookup missed
229
+ * and every row came back `absent`/`skip`. Twenty-eight tests failed for a reason that had nothing
230
+ * to do with what they were testing, which left the platform with the most users unwatched.
231
+ *
232
+ * A separator is part of the answer, so it belongs to the platform being planned for.
233
+ */
234
+ export const joinFor = (os) => 'win32' === os ? win32.join : posix.join;
235
+ /**
236
+ * Decide what to do for every client. Pure: the filesystem arrives as two functions, which is what
237
+ * makes the Windows rows testable from any machine.
238
+ */
239
+ export function planAgentConfigs(input) {
240
+ const { home, platform, exists, readFile } = input;
241
+ return AGENT_CLIENTS.map((c) => {
242
+ const join = joinFor(platform);
243
+ const file = join(home, forPlatform(c.paths, platform));
244
+ const detected = exists(join(home, forPlatform(c.marker, platform)));
245
+ // A NEW yaml file has nobody's formatting to destroy. An existing one does: `mcpServers` there
246
+ // is a list of named entries, and a naive rewrite loses comments, anchors and ordering.
247
+ if ('yaml-manual' === c.format) {
248
+ return exists(file)
249
+ ? {
250
+ id: c.id,
251
+ name: c.name,
252
+ file,
253
+ action: AgentAction.MANUAL,
254
+ why: 'its config is YAML and already exists, so rewriting it would lose comments and ordering',
255
+ }
256
+ : {
257
+ id: c.id,
258
+ name: c.name,
259
+ file,
260
+ action: AgentAction.CREATE_YAML,
261
+ why: 'no config yet, so a valid one can be written outright',
262
+ };
263
+ }
264
+ const layoutKnown = c.parentMarker !== undefined && exists(join(home, forPlatform(c.parentMarker, platform)));
265
+ if (!detected && c.confidence === AgentConfidence.COMMUNITY && !layoutKnown) {
266
+ return {
267
+ id: c.id,
268
+ name: c.name,
269
+ file,
270
+ action: AgentAction.SKIP,
271
+ why: "not installed, and without its host's standard layout on this machine its path is a guess: a guessed path creates a file nobody reads",
272
+ };
273
+ }
274
+ if (!exists(file)) {
275
+ return {
276
+ id: c.id,
277
+ name: c.name,
278
+ file,
279
+ action: AgentAction.CREATE,
280
+ key: c.key,
281
+ entry: c.entry,
282
+ why: detected
283
+ ? 'installed, with no config yet'
284
+ : 'a documented path, so a later install finds it already wired',
285
+ };
286
+ }
287
+ let parsed;
288
+ try {
289
+ parsed = JSON.parse(readFile(file));
290
+ }
291
+ catch {
292
+ parsed = undefined;
293
+ }
294
+ if ('object' !== typeof parsed || null === parsed) {
295
+ return {
296
+ id: c.id,
297
+ name: c.name,
298
+ file,
299
+ action: AgentAction.MANUAL,
300
+ key: c.key,
301
+ entry: c.entry,
302
+ why: "the existing config is not plain JSON (comments or trailing commas), and rewriting it would reformat somebody else's file",
303
+ };
304
+ }
305
+ const bucket = parsed[c.key];
306
+ const existing = 'object' === typeof bucket && null !== bucket
307
+ ? bucket[RETICLE_KEY]
308
+ : undefined;
309
+ if (existing !== undefined) {
310
+ const ours = JSON.stringify(existing) === JSON.stringify(c.entry);
311
+ return {
312
+ id: c.id,
313
+ name: c.name,
314
+ file,
315
+ action: ours ? AgentAction.ALREADY : AgentAction.MANUAL,
316
+ key: c.key,
317
+ entry: c.entry,
318
+ why: ours
319
+ ? 'already registered'
320
+ : 'a different `reticle` entry is there, and it is not ours to replace',
321
+ };
322
+ }
323
+ return {
324
+ id: c.id,
325
+ name: c.name,
326
+ file,
327
+ action: AgentAction.MERGE,
328
+ key: c.key,
329
+ entry: c.entry,
330
+ why: 'adding our key beside the servers already there',
331
+ };
332
+ });
333
+ }
@@ -0,0 +1,9 @@
1
+ /**
2
+ * The real filesystem, in the shape the agent writer and the approval grants expect.
3
+ *
4
+ * Its own module so the MCP server can reach it without importing `setup-command`, which would pull
5
+ * the whole drive machinery — child processes, dev-server supervision, page probing — into the
6
+ * startup path of the one process whose latency a user experiences as "Reticle is slow to connect".
7
+ */
8
+ import type { AgentWriterIo } from './agent-writer.js';
9
+ export declare const agentIo: AgentWriterIo;
@@ -0,0 +1,16 @@
1
+ /**
2
+ * The real filesystem, in the shape the agent writer and the approval grants expect.
3
+ *
4
+ * Its own module so the MCP server can reach it without importing `setup-command`, which would pull
5
+ * the whole drive machinery — child processes, dev-server supervision, page probing — into the
6
+ * startup path of the one process whose latency a user experiences as "Reticle is slow to connect".
7
+ */
8
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
9
+ export const agentIo = {
10
+ exists: (path) => existsSync(path),
11
+ readFile: (path) => readFileSync(path, 'utf8'),
12
+ writeFile: (path, contents) => writeFileSync(path, contents),
13
+ mkdirp: (dir) => {
14
+ mkdirSync(dir, { recursive: true });
15
+ },
16
+ };
@@ -0,0 +1,51 @@
1
+ /**
2
+ * Carrying out an agent-config plan.
3
+ *
4
+ * The plan decides; this writes. Kept apart because the deciding is where the judgement is — which
5
+ * paths are evidenced, which formats are safe to touch — and it is worth testing against a pretend
6
+ * filesystem rather than a real one.
7
+ *
8
+ * One rule governs everything here: only our key is ever written. The rest of somebody's config is
9
+ * copied through untouched, and a file we cannot parse is left exactly as it is. A config file is
10
+ * not ours, and the cost of being wrong about that is not a failed install but a broken editor.
11
+ */
12
+ import { AgentAction, type AgentPlanStep, type PlatformPaths } from './agent-configs.js';
13
+ /** The filesystem, injected so the writer is testable without one. */
14
+ export interface AgentWriterIo {
15
+ readonly exists: (path: string) => boolean;
16
+ readonly readFile: (path: string) => string;
17
+ readonly writeFile: (path: string, contents: string) => void;
18
+ readonly mkdirp: (dir: string) => void;
19
+ }
20
+ export interface AgentWriteResult {
21
+ readonly id: string;
22
+ readonly name: string;
23
+ readonly file: string;
24
+ /** What actually happened, which is not always what was planned. */
25
+ readonly action: AgentAction | 'created' | 'merged';
26
+ readonly why: string;
27
+ }
28
+ /**
29
+ * Write what the plan says to write, and nothing else.
30
+ *
31
+ * A step that fails becomes a `manual` result rather than an exception: one unwritable config on a
32
+ * machine with a dozen agents is not a reason to abandon the other eleven, and the user needs to be
33
+ * told which one to do by hand.
34
+ */
35
+ export declare function applyAgentPlan(plan: readonly AgentPlanStep[], io: AgentWriterIo): AgentWriteResult[];
36
+ /** The `/reticle` instruction, for agents that load skills from a directory. */
37
+ export declare const RETICLE_SKILL = "---\nname: reticle\ndescription: Verify a change against the running app, from inside it, before calling it done.\n---\n\nReticle exposes the running app to you as `reticle_*` MCP tools. Look, act, observe, assert.\n\nOnly `reticle_act_and_wait` and `reticle_assert` produce a verdict. Everything else moves or\nreads the app and proves nothing, so a drive that ends without one of those has no result however\nmany tools it used.\n\n`verified: \"unknown\"` is not a pass: it means Reticle could not tell what happened.\n`verified: \"no-fault\"` is not a pass either, because nothing was declared to prove. Never weaken a\ncheck to make it pass.\n\nThe cheapest path that answers the question:\n\n- \"did my edit break anything?\" -> `reticle_run({ tool: \"reticle_verify\", args: { action: \"change\", files: [...] } })`\n- \"does this known journey still work?\" -> `reticle_run({ tool: \"reticle_flow_replay\", args: { flowName: \"...\" } })`\n- \"does this new behaviour work?\" -> `reticle_act_sequence` for the setup, then ONE `reticle_act_and_wait`\n";
38
+ export interface SkillWriteResult {
39
+ readonly id: string;
40
+ readonly file: string;
41
+ }
42
+ /**
43
+ * Write the skill for agents that have somewhere to put it, and only where they are installed.
44
+ *
45
+ * Scaffolding a skills tree for software somebody does not have is litter, and unlike a config file
46
+ * it is not even inert: it is a directory that appears in their home for no reason they can trace.
47
+ */
48
+ export declare function applyAgentSkills(io: AgentWriterIo, where: {
49
+ readonly home: string;
50
+ readonly platform: keyof PlatformPaths;
51
+ }): SkillWriteResult[];
@@ -0,0 +1,115 @@
1
+ /**
2
+ * Carrying out an agent-config plan.
3
+ *
4
+ * The plan decides; this writes. Kept apart because the deciding is where the judgement is — which
5
+ * paths are evidenced, which formats are safe to touch — and it is worth testing against a pretend
6
+ * filesystem rather than a real one.
7
+ *
8
+ * One rule governs everything here: only our key is ever written. The rest of somebody's config is
9
+ * copied through untouched, and a file we cannot parse is left exactly as it is. A config file is
10
+ * not ours, and the cost of being wrong about that is not a failed install but a broken editor.
11
+ */
12
+ import { AgentAction, AGENT_CLIENTS, joinFor, } from './agent-configs.js';
13
+ /** Two spaces, because that is what every one of these files already uses. */
14
+ const INDENT = 2;
15
+ const RETICLE_KEY = 'reticle';
16
+ /** A fresh Continue config. YAML is only ever created, never edited. */
17
+ const CONTINUE_YAML = 'mcpServers:\n - name: reticle\n type: stdio\n command: npx\n args: ["@reticlehq/server", "mcp"]\n';
18
+ const parentOf = (path) => path.slice(0, Math.max(0, path.lastIndexOf('/')));
19
+ /**
20
+ * Write what the plan says to write, and nothing else.
21
+ *
22
+ * A step that fails becomes a `manual` result rather than an exception: one unwritable config on a
23
+ * machine with a dozen agents is not a reason to abandon the other eleven, and the user needs to be
24
+ * told which one to do by hand.
25
+ */
26
+ export function applyAgentPlan(plan, io) {
27
+ return plan.map((step) => {
28
+ const base = { id: step.id, name: step.name, file: step.file, why: step.why };
29
+ if (AgentAction.SKIP === step.action ||
30
+ AgentAction.ALREADY === step.action ||
31
+ AgentAction.MANUAL === step.action) {
32
+ return { ...base, action: step.action };
33
+ }
34
+ try {
35
+ io.mkdirp(parentOf(step.file));
36
+ if (AgentAction.CREATE_YAML === step.action) {
37
+ io.writeFile(step.file, CONTINUE_YAML);
38
+ return { ...base, action: 'created' };
39
+ }
40
+ const key = step.key;
41
+ if (undefined === key || undefined === step.entry) {
42
+ return {
43
+ ...base,
44
+ action: AgentAction.MANUAL,
45
+ why: 'the plan named no key or entry to write',
46
+ };
47
+ }
48
+ // Only our key. Everything else in the file is read and written back untouched.
49
+ const current = AgentAction.MERGE === step.action
50
+ ? JSON.parse(io.readFile(step.file))
51
+ : {};
52
+ const bucket = current[key];
53
+ const servers = 'object' === typeof bucket && null !== bucket ? bucket : {};
54
+ const next = { ...current, [key]: { ...servers, [RETICLE_KEY]: step.entry } };
55
+ io.writeFile(step.file, `${JSON.stringify(next, null, INDENT)}\n`);
56
+ return { ...base, action: AgentAction.MERGE === step.action ? 'merged' : 'created' };
57
+ }
58
+ catch (err) {
59
+ return {
60
+ ...base,
61
+ action: AgentAction.MANUAL,
62
+ why: `could not write it (${String(err?.message ?? err).slice(0, 120)})`,
63
+ };
64
+ }
65
+ });
66
+ }
67
+ /** The `/reticle` instruction, for agents that load skills from a directory. */
68
+ export const RETICLE_SKILL = `---
69
+ name: reticle
70
+ description: Verify a change against the running app, from inside it, before calling it done.
71
+ ---
72
+
73
+ Reticle exposes the running app to you as \`reticle_*\` MCP tools. Look, act, observe, assert.
74
+
75
+ Only \`reticle_act_and_wait\` and \`reticle_assert\` produce a verdict. Everything else moves or
76
+ reads the app and proves nothing, so a drive that ends without one of those has no result however
77
+ many tools it used.
78
+
79
+ \`verified: "unknown"\` is not a pass: it means Reticle could not tell what happened.
80
+ \`verified: "no-fault"\` is not a pass either, because nothing was declared to prove. Never weaken a
81
+ check to make it pass.
82
+
83
+ The cheapest path that answers the question:
84
+
85
+ - "did my edit break anything?" -> \`reticle_run({ tool: "reticle_verify", args: { action: "change", files: [...] } })\`
86
+ - "does this known journey still work?" -> \`reticle_run({ tool: "reticle_flow_replay", args: { flowName: "..." } })\`
87
+ - "does this new behaviour work?" -> \`reticle_act_sequence\` for the setup, then ONE \`reticle_act_and_wait\`
88
+ `;
89
+ /**
90
+ * Write the skill for agents that have somewhere to put it, and only where they are installed.
91
+ *
92
+ * Scaffolding a skills tree for software somebody does not have is litter, and unlike a config file
93
+ * it is not even inert: it is a directory that appears in their home for no reason they can trace.
94
+ */
95
+ export function applyAgentSkills(io, where) {
96
+ const written = [];
97
+ const join = joinFor(where.platform);
98
+ for (const client of AGENT_CLIENTS) {
99
+ const dir = client.skillDir;
100
+ if (undefined === dir)
101
+ continue;
102
+ if (!io.exists(join(where.home, client.marker[where.platform])))
103
+ continue;
104
+ try {
105
+ const target = join(where.home, dir);
106
+ io.mkdirp(target);
107
+ io.writeFile(join(target, 'SKILL.md'), RETICLE_SKILL);
108
+ written.push({ id: client.id, file: join(target, 'SKILL.md') });
109
+ }
110
+ catch {
111
+ /* an unwritable home directory is not a reason to fail an install */
112
+ }
113
+ }
114
+ return written;
115
+ }
@@ -0,0 +1,47 @@
1
+ /**
2
+ * Carrying the pre-approval rules onto a machine that installed Reticle before they existed.
3
+ *
4
+ * The alternative was a command the user has to know to type. Nothing reaches back into an existing
5
+ * install, so `init --files-only` is a real upgrade path but only for somebody who reads a
6
+ * changelog; everyone else keeps clicking Accept on every call forever, which is precisely the
7
+ * thing this was supposed to end.
8
+ *
9
+ * So it runs from `reticle mcp` — the one process every client starts, every session, on the
10
+ * version they actually have. Four properties make that safe to do unattended:
11
+ *
12
+ * 1. **Once per version.** A stamp in the state dir, so it is not a write on every editor launch.
13
+ * 2. **Only where an agent is installed**, and only ever the `reticle` server.
14
+ * 3. **Never a create that supersedes an allowlist we cannot read.** Cursor's file is deferred to an
15
+ * explicit `init` when it does not already exist: a version bump that silently makes somebody's
16
+ * OTHER MCP servers start prompting again is a regression we caused and they cannot trace.
17
+ * 4. **Never throws, never writes to stdout.** This runs inside a stdio MCP server, where a stray
18
+ * byte on stdout corrupts the protocol, and where a crash is experienced as "Reticle is down".
19
+ * 5. **Never runs against a sandboxed state directory.** A gate or a fixture that points Reticle at
20
+ * a temp state dir is not asking to have the real user's editor config rewritten, and every
21
+ * battery in this repo starts MCP servers. The one write in this repo that reached a developer's
22
+ * own home did so from a gate run, which is exactly the shape this rules out.
23
+ */
24
+ import type { AgentWriterIo } from './agent-writer.js';
25
+ import { type PlatformPaths } from './agent-configs.js';
26
+ export declare const APPROVAL_STAMP_FILE = "approvals.json";
27
+ export interface MigrationDeps {
28
+ readonly io: AgentWriterIo;
29
+ readonly home: string;
30
+ readonly platform: keyof PlatformPaths;
31
+ /** The state directory, which is where the once-per-version stamp lives. */
32
+ readonly stateHome: string;
33
+ readonly version: string;
34
+ readonly log: (event: string, data: Record<string, unknown>) => void;
35
+ }
36
+ export interface MigrationResult {
37
+ readonly ran: boolean;
38
+ readonly granted: readonly string[];
39
+ readonly deferred: readonly string[];
40
+ }
41
+ /**
42
+ * Apply the approval rules once for this version, and record that it happened.
43
+ *
44
+ * The stamp is written even when nothing was granted. A machine with no agents installed should not
45
+ * re-scan on every editor launch for the rest of the version's life.
46
+ */
47
+ export declare function migrateApprovals(deps: MigrationDeps): MigrationResult;
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Carrying the pre-approval rules onto a machine that installed Reticle before they existed.
3
+ *
4
+ * The alternative was a command the user has to know to type. Nothing reaches back into an existing
5
+ * install, so `init --files-only` is a real upgrade path but only for somebody who reads a
6
+ * changelog; everyone else keeps clicking Accept on every call forever, which is precisely the
7
+ * thing this was supposed to end.
8
+ *
9
+ * So it runs from `reticle mcp` — the one process every client starts, every session, on the
10
+ * version they actually have. Four properties make that safe to do unattended:
11
+ *
12
+ * 1. **Once per version.** A stamp in the state dir, so it is not a write on every editor launch.
13
+ * 2. **Only where an agent is installed**, and only ever the `reticle` server.
14
+ * 3. **Never a create that supersedes an allowlist we cannot read.** Cursor's file is deferred to an
15
+ * explicit `init` when it does not already exist: a version bump that silently makes somebody's
16
+ * OTHER MCP servers start prompting again is a regression we caused and they cannot trace.
17
+ * 4. **Never throws, never writes to stdout.** This runs inside a stdio MCP server, where a stray
18
+ * byte on stdout corrupts the protocol, and where a crash is experienced as "Reticle is down".
19
+ * 5. **Never runs against a sandboxed state directory.** A gate or a fixture that points Reticle at
20
+ * a temp state dir is not asking to have the real user's editor config rewritten, and every
21
+ * battery in this repo starts MCP servers. The one write in this repo that reached a developer's
22
+ * own home did so from a gate run, which is exactly the shape this rules out.
23
+ */
24
+ import { grantAutoApproval, ApprovalOutcome } from './auto-approve.js';
25
+ import { joinFor } from './agent-configs.js';
26
+ export const APPROVAL_STAMP_FILE = 'approvals.json';
27
+ const NOTHING = { ran: false, granted: [], deferred: [] };
28
+ /**
29
+ * Apply the approval rules once for this version, and record that it happened.
30
+ *
31
+ * The stamp is written even when nothing was granted. A machine with no agents installed should not
32
+ * re-scan on every editor launch for the rest of the version's life.
33
+ */
34
+ export function migrateApprovals(deps) {
35
+ const { io, home, platform, stateHome, version, log } = deps;
36
+ const stamp = joinFor(platform)(stateHome, APPROVAL_STAMP_FILE);
37
+ try {
38
+ if (io.exists(stamp)) {
39
+ const seen = JSON.parse(io.readFile(stamp));
40
+ if (version === seen.version)
41
+ return NOTHING;
42
+ }
43
+ }
44
+ catch {
45
+ // An unreadable stamp means we do not know what has run, and the grants below are idempotent,
46
+ // so the safe reading is "not yet" rather than skipping the migration forever.
47
+ }
48
+ let results = [];
49
+ try {
50
+ results = grantAutoApproval(io, { home, platform }, undefined, { onlyIfNoSupersede: true });
51
+ }
52
+ catch {
53
+ return NOTHING;
54
+ }
55
+ const granted = results.filter((r) => ApprovalOutcome.GRANTED === r.outcome).map((r) => r.name);
56
+ const deferred = results.filter((r) => ApprovalOutcome.DEFERRED === r.outcome).map((r) => r.name);
57
+ try {
58
+ io.mkdirp(stateHome);
59
+ io.writeFile(stamp, `${JSON.stringify({ version }, null, 2)}\n`);
60
+ }
61
+ catch {
62
+ // A stamp we could not write means this runs again next launch. Wasteful, not harmful.
63
+ }
64
+ if (0 < granted.length || 0 < deferred.length) {
65
+ log('reticle_approvals_migrated', { version, granted, deferred });
66
+ }
67
+ return { ran: true, granted, deferred };
68
+ }