@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,17 +1,20 @@
1
1
  /**
2
2
  * Lease tools — the agent-facing surface of the BrowserPool.
3
3
  *
4
- * `reticle_lease_acquire` opens a fresh isolated headless context navigated to the app URL and returns
5
- * the sessionId the app's SDK will register (stamped via __reticle_session so the lease and the session
6
- * correlate 1:1). This is the "one of 10 flows" entry point: 10 agents acquire 10 leases, the pool
7
- * keeps them in ONE browser, capped and queued. `reticle_lease_release` frees the slot.
4
+ * `reticle_lease_acquire` opens an isolated headless context navigated to the app URL and returns
5
+ * the sessionId the app's SDK will register. A second acquire on the same origin reuses the live
6
+ * lease rather than minting another tab — that second tab used to poison default session resolution
7
+ * for the rest of the run. The parallel suite still mints via `acquireLeasedSession`, because ten
8
+ * flows on one origin need isolation on purpose.
8
9
  *
9
10
  * Attach-only: the pool drives a browser against an already-running dev server — it never starts one.
10
11
  */
11
12
  import { z } from 'zod';
12
13
  import { leaseNotConnectedHint } from './lease-hint.js';
14
+ import { probeSdkMarker } from './sdk-marker-probe.js';
13
15
  import { readProjectFramework, readProjectId } from '../cli/cli-port.js';
14
16
  import { hasConnectedBefore } from '../session/connection-memory.js';
17
+ import { AGENT_DRIVING_ELSEWHERE, AGENT_DRIVING_HERE_AGAIN, watchersToNotify, } from '../session/lease-visibility.js';
15
18
  import { reticleStateHome } from '../daemon/daemon.js';
16
19
  import { RETICLE_URL_PARAM, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
17
20
  import { ReticleTool } from './tool-names.js';
@@ -24,19 +27,42 @@ import { chromiumHint } from '../cli/chromium-hint.js';
24
27
  * printed a static differential over the top of it — telling one agent in `reticle_sessions` that
25
28
  * the wiring was proven correct and telling it seconds later that the port was probably wrong.
26
29
  */
27
- function leaseEvidence(deps, port) {
30
+ /**
31
+ * Async only for the marker probe, which is the piece that decides whether this app ships an SDK at
32
+ * all — the difference between the diagnosis a new user needs and four causes that all assume the
33
+ * install already happened. It is one localhost GET on a path that has already failed and is about
34
+ * to print a paragraph, and it can only ever add a sentence: the probe returns `undefined` on any
35
+ * doubt and the hint then says nothing about markers.
36
+ */
37
+ async function leaseEvidence(deps, port, url) {
28
38
  const cwd = process.cwd();
29
39
  const projectId = readProjectId(cwd);
30
40
  const refusal = deps.sessions.lastClosure()?.reason;
31
41
  const framework = readProjectFramework(cwd);
42
+ const sdkMarker = await probeSdkMarker(url);
32
43
  return {
33
44
  ...(refusal === undefined ? {} : { refusal }),
34
45
  ...(framework === undefined ? {} : { framework }),
46
+ ...(sdkMarker === undefined ? {} : { sdkMarker }),
35
47
  previouslyConnected: hasConnectedBefore(reticleStateHome(), port, projectId),
36
48
  initialized: projectId !== undefined,
37
49
  };
38
50
  }
39
51
  const POOL_UNAVAILABLE = 'browser pool unavailable — the lease tools need the daemon-managed pool (start Reticle via `reticle mcp`).';
52
+ /** The origin of a URL, or undefined when it does not parse. */
53
+ export function originOf(url) {
54
+ try {
55
+ return new URL(url).origin;
56
+ }
57
+ catch {
58
+ return undefined;
59
+ }
60
+ }
61
+ const ALREADY_HELD_LEASE = 'you already hold a lease on this origin';
62
+ function alreadyHeldHint(sessionId, origin) {
63
+ return (`${ALREADY_HELD_LEASE} (${origin}): ${sessionId} — reused it rather than opening a second ` +
64
+ 'tab, which would make every later call require sessionId. Release first if you want a fresh one.');
65
+ }
40
66
  /**
41
67
  * Append Reticle identity params (__reticle_session, optional __reticle_project) to a URL so the app's own SDK
42
68
  * adopts them on connect. Pure; falls back to plain concatenation if the URL can't be parsed.
@@ -105,6 +131,39 @@ export function resolveLeasedSessionId(sessions, leaseId) {
105
131
  return leaseId;
106
132
  return sessions.all().find((s) => sessionParamOf(s.url) === leaseId)?.id;
107
133
  }
134
+ /**
135
+ * Carry a claimed identity across a navigation.
136
+ *
137
+ * A LEASED tab is addressed by `__reticle_session` in its URL: that param is how the pool finds the
138
+ * context it opened, and — since succession was tightened — it is also the ONLY thing that lets the
139
+ * reconnecting document inherit the lease. `reticle_navigate` sent the caller's raw URL, so the very
140
+ * first navigation stripped the marker, the tab re-announced as an ordinary anonymous session, and
141
+ * the lease was orphaned: "no sessions are connected at all", with a browser window still open on
142
+ * screen. A leased browser that cannot survive being navigated is not a usable one.
143
+ *
144
+ * A tab that claims nothing is left exactly as it was — this must never bolt Reticle's params onto
145
+ * a human's own URL.
146
+ */
147
+ export function carryReticleIdentity(fromUrl, toUrl) {
148
+ const session = sessionParamOf(fromUrl);
149
+ if (session === undefined)
150
+ return toUrl;
151
+ // Already addressed (a caller passing the stamped URL back) — appending would be a no-op at best.
152
+ if (sessionParamOf(toUrl) !== undefined)
153
+ return toUrl;
154
+ const projectId = projectParamOf(fromUrl);
155
+ return appendReticleParams(toUrl, session, projectId);
156
+ }
157
+ function projectParamOf(url) {
158
+ if (url === undefined)
159
+ return undefined;
160
+ try {
161
+ return new URL(url).searchParams.get(RETICLE_URL_PARAM.PROJECT) ?? undefined;
162
+ }
163
+ catch {
164
+ return undefined;
165
+ }
166
+ }
108
167
  function sessionParamOf(url) {
109
168
  if (url === undefined)
110
169
  return undefined;
@@ -163,7 +222,7 @@ export async function waitForLeasedSession(isConnected, sleeper = sleep, attempt
163
222
  */
164
223
  export const LEASE_ACQUIRE_TOOL = {
165
224
  name: ReticleTool.LEASE_ACQUIRE,
166
- description: 'Lease a fresh isolated headless browser context from the shared pool and navigate it to the app URL (the app must already be running and embed @reticlehq/core). Returns the sessionId the leased tab registers — pass it to other tools. The pool keeps all leases in ONE browser and caps concurrency; if at capacity this waits for a free slot. Release with reticle_lease{action:"release"} when the flow is done.',
225
+ description: 'Lease a fresh isolated headless browser context from the shared pool and navigate it to the app URL (the app must already be running and embed @reticlehq/core). If this origin is already leased and still connected, this returns THAT session rather than minting a second tab — a second acquire on the same origin poisons default session resolution. Returns the sessionId the leased tab registers — pass it to other tools. The pool keeps all leases in ONE browser and caps concurrency; if at capacity this waits for a free slot. Release with reticle_lease{action:"release"} when the flow is done. PREFER AN ALREADY-OPEN TAB: if reticle_sessions lists a non-leased session for this app, drive THAT instead — a lease is invisible to the person watching the app, whose HUD lives in their own tab, and a tab flagged hidden/throttled is often still driveable. Lease for isolation you actually need (a second identity, a clean context, parallel flows) or when driving the open tab has failed — this call answers with `preferExisting` when a live tab was available.',
167
226
  inputSchema: {
168
227
  url: z
169
228
  .string()
@@ -184,7 +243,21 @@ export const LEASE_ACQUIRE_TOOL = {
184
243
  .describe('Milliseconds until this lease expires if untouched. Each tool call that targets this session resets the clock. Plan your work to finish or re-acquire before this runs out.'),
185
244
  leased: z.number().describe('How many contexts are currently leased from the pool.'),
186
245
  queued: z.number().describe('How many acquires are waiting for a free slot.'),
246
+ preferExisting: z
247
+ .object({ sessionId: z.string(), note: z.string() })
248
+ .optional()
249
+ .describe('Present when a live NON-leased tab for this app was already connected. That tab is the one a human can see; this lease is not. Release this lease and drive that sessionId unless you specifically need an isolated context.'),
250
+ reused: z
251
+ .boolean()
252
+ .optional()
253
+ .describe('True when this acquire returned an existing live lease on the same origin rather than minting a second context.'),
187
254
  hint: z.string().optional(),
255
+ versionSkew: z
256
+ .string()
257
+ .optional()
258
+ .describe("Present when the leased tab's SDK disagrees with this daemon. ready is still true — the " +
259
+ 'page dialled in — but CDP-backed tools (screenshot, viewport, real input, network_mock) ' +
260
+ 'will fail until the versions match. Same sentence as reticle_sessions.versionSkew.'),
188
261
  },
189
262
  handler: async (deps, args) => {
190
263
  const pool = deps.pool;
@@ -205,6 +278,33 @@ export const LEASE_ACQUIRE_TOOL = {
205
278
  }
206
279
  }
207
280
  const projectId = asString(args['projectId']);
281
+ // Sampled BEFORE acquiring: afterwards this lease is itself a session, and the point is to name
282
+ // a tab that already existed. A human's open tab is the one they can watch, so if one is here
283
+ // the agent should be told at the moment it is choosing — not after it has gone dark on them.
284
+ const alreadyOpen = liveTabFor(deps, projectId);
285
+ const origin = originOf(url);
286
+ const existing = origin === undefined ? undefined : pool.leaseIdOnOrigin?.(origin);
287
+ if (existing !== undefined && origin !== undefined) {
288
+ if (deps.sessions.get(existing) !== undefined) {
289
+ pool.touch(existing);
290
+ return {
291
+ sessionId: existing,
292
+ url,
293
+ ready: true,
294
+ reused: true,
295
+ expiresInMs: pool.leaseTtlMs(),
296
+ leased: pool.activeCount(),
297
+ queued: pool.queuedCount(),
298
+ hint: alreadyHeldHint(existing, origin),
299
+ ...(alreadyOpen === undefined
300
+ ? {}
301
+ : { preferExisting: { sessionId: alreadyOpen, note: PREFER_EXISTING_NOTE } }),
302
+ };
303
+ }
304
+ // The lease is still held but the tab has gone — a reload dropped the session. Free the
305
+ // slot and mint, rather than handing back a dead id or leaving both contexts occupied.
306
+ await pool.release(existing);
307
+ }
208
308
  const sessionId = newLeaseId();
209
309
  const navUrl = appendReticleParams(url, sessionId, projectId);
210
310
  let lease;
@@ -230,6 +330,11 @@ export const LEASE_ACQUIRE_TOOL = {
230
330
  // reaper closes the context mid-flow. See BrowserPool.alias and #157.
231
331
  if (registeredId !== undefined)
232
332
  pool.alias(registeredId, lease.sessionId);
333
+ // The lease now exists, so any HUD a human is watching has just gone dark. Say so.
334
+ tellWatchers(deps, projectId, AGENT_DRIVING_ELSEWHERE);
335
+ // ready means the SDK dialled in — not that contracts match. Carry the skew warning on acquire
336
+ // so the agent does not learn it only after a CDP tool invents a closed page (#688).
337
+ const versionSkew = registeredId === undefined ? undefined : deps.sessions.get(registeredId)?.versionSkew;
233
338
  return {
234
339
  sessionId: registeredId ?? lease.sessionId,
235
340
  url,
@@ -237,18 +342,31 @@ export const LEASE_ACQUIRE_TOOL = {
237
342
  expiresInMs: pool.leaseTtlMs(),
238
343
  leased: pool.activeCount(),
239
344
  queued: pool.queuedCount(),
345
+ ...(alreadyOpen === undefined
346
+ ? {}
347
+ : {
348
+ preferExisting: {
349
+ sessionId: alreadyOpen,
350
+ note: PREFER_EXISTING_NOTE,
351
+ },
352
+ }),
353
+ ...(versionSkew === undefined ? {} : { versionSkew }),
240
354
  ...(ready
241
355
  ? {}
242
- : (() => {
243
- const bridgePort = deps.bridgePort ?? RETICLE_DEFAULT_PORT;
244
- return {
245
- hint: leaseNotConnectedHint(url, bridgePort, leaseEvidence(deps, bridgePort)),
246
- };
247
- })()),
356
+ : { hint: await notConnectedHint(deps, url, pool.dialFailureUrl?.(lease.sessionId)) }),
248
357
  };
249
358
  },
250
359
  };
251
- export const LEASE_RELEASE_TOOL = {
360
+ /** The whole not-connected diagnosis, gathered and worded. Split out so the acquire path stays flat. */
361
+ async function notConnectedHint(deps, url, dialledUrl) {
362
+ const bridgePort = deps.bridgePort ?? RETICLE_DEFAULT_PORT;
363
+ const evidence = await leaseEvidence(deps, bridgePort, url);
364
+ return leaseNotConnectedHint(url, bridgePort, {
365
+ ...evidence,
366
+ ...(dialledUrl === undefined ? {} : { dialledUrl }),
367
+ });
368
+ }
369
+ const LEASE_RELEASE_TOOL = {
252
370
  name: ReticleTool.LEASE_RELEASE,
253
371
  description: 'Release a leased browser context by sessionId, closing it and freeing the pool slot for a queued acquire. Call this when a flow finishes so the pool stays within its concurrency cap.',
254
372
  inputSchema: {
@@ -268,8 +386,68 @@ export const LEASE_RELEASE_TOOL = {
268
386
  if (sessionId === undefined || 0 === sessionId.length) {
269
387
  throw new Error('reticle_lease{action:"release"} requires a sessionId');
270
388
  }
389
+ // Read the project BEFORE releasing: afterwards the session is gone and there is nothing to
390
+ // ask which project it belonged to.
391
+ const projectId = deps.sessions.get(sessionId)?.projectId;
271
392
  await pool.release(sessionId);
393
+ // Only once the LAST lease is gone. Announcing "live again" while another lease still drives
394
+ // would be a lie, and a HUD that says the wrong thing is worse than one that says nothing.
395
+ if (0 === pool.activeCount())
396
+ tellWatchers(deps, projectId, AGENT_DRIVING_HERE_AGAIN);
272
397
  return { released: true, leased: pool.activeCount() };
273
398
  },
274
399
  };
400
+ /**
401
+ * What to say when a lease was taken while a real tab was already open.
402
+ *
403
+ * Not a refusal. Leases are the highest-value path for autonomous work and an agent that genuinely
404
+ * needs isolation must still get one — but a human watching their own tab cannot see a lease, so
405
+ * when both exist the visible one is the better default and the agent should hear that here, where
406
+ * it is choosing, rather than discover it when somebody asks why nothing is happening.
407
+ */
408
+ export const PREFER_EXISTING_NOTE = 'a non-leased tab for this app was already connected — that is the one a human can see, and this lease is not. Unless you need an isolated context (a second identity, a clean profile, parallel flows), release this lease and drive that sessionId instead.';
409
+ /**
410
+ * The first live non-leased session for this project, if any.
411
+ *
412
+ * Reuses the watcher selector rather than re-deriving "which sessions belong to a human": one rule
413
+ * for one question, so the tab we announce to and the tab we recommend can never disagree.
414
+ */
415
+ function liveTabFor(deps, projectId) {
416
+ const pool = deps.pool;
417
+ if (pool === undefined)
418
+ return undefined;
419
+ try {
420
+ const candidates = deps.sessions
421
+ .all()
422
+ .map((session) => ({ id: session.id, projectId: session.projectId }));
423
+ return watchersToNotify(candidates, pool.leasedSessionIds(), projectId)[0];
424
+ }
425
+ catch {
426
+ return undefined;
427
+ }
428
+ }
429
+ /**
430
+ * Tell the tabs a human is watching that the agent has gone somewhere they cannot see.
431
+ *
432
+ * Fire-and-forget, and deliberately never able to fail the tool: this is a courtesy to a person, and
433
+ * a lease that succeeded must not be reported as failed because a narration could not be posted to
434
+ * some unrelated tab. `pushNarration` is already fire-and-forget; the try/catch covers a session
435
+ * that disconnects between listing it and posting to it.
436
+ */
437
+ function tellWatchers(deps, projectId, text) {
438
+ const pool = deps.pool;
439
+ if (pool === undefined)
440
+ return;
441
+ try {
442
+ const candidates = deps.sessions
443
+ .all()
444
+ .map((session) => ({ id: session.id, projectId: session.projectId }));
445
+ for (const id of watchersToNotify(candidates, pool.leasedSessionIds(), projectId)) {
446
+ deps.sessions.get(id)?.pushNarration(text);
447
+ }
448
+ }
449
+ catch {
450
+ // A HUD that missed one line is a smaller problem than a lease reported as broken.
451
+ }
452
+ }
275
453
  export const LEASE_TOOLS = [LEASE_ACQUIRE_TOOL, LEASE_RELEASE_TOOL];
@@ -8,6 +8,19 @@ interface MergedNameRedirect {
8
8
  }
9
9
  /** Where `name` went, or undefined when it is a live tool or not ours. */
10
10
  export declare function mergedNameRedirect(name: string): MergedNameRedirect | undefined;
11
+ /**
12
+ * Every retired name against the call that replaces it — the tombstones, as one block.
13
+ *
14
+ * The redirect above answers an agent that already guessed the old name. This answers the one that
15
+ * is reading the surface to find out what exists, and is the case a redirect cannot reach: nothing
16
+ * in the catalogue says `reticle_crawl` became `reticle_verify { action: "crawl" }`, so instructions
17
+ * written against an earlier release lead either to an error string or to nothing at all.
18
+ *
19
+ * Derived from the same two declarations as `BY_OLD_NAME`, for the same reason: a hand-written
20
+ * migration list is one merge away from being wrong, and wrong is worse than absent here — the agent
21
+ * retries into it.
22
+ */
23
+ export declare function retiredToolNames(): Readonly<Record<string, string>>;
11
24
  /** The sentence handed to an agent that called `name`. */
12
25
  export declare function mergedNameMessage(name: string, redirect: MergedNameRedirect): string;
13
26
  export {};
@@ -46,6 +46,28 @@ const BY_OLD_NAME = (() => {
46
46
  export function mergedNameRedirect(name) {
47
47
  return BY_OLD_NAME.get(name);
48
48
  }
49
+ /**
50
+ * Every retired name against the call that replaces it — the tombstones, as one block.
51
+ *
52
+ * The redirect above answers an agent that already guessed the old name. This answers the one that
53
+ * is reading the surface to find out what exists, and is the case a redirect cannot reach: nothing
54
+ * in the catalogue says `reticle_crawl` became `reticle_verify { action: "crawl" }`, so instructions
55
+ * written against an earlier release lead either to an error string or to nothing at all.
56
+ *
57
+ * Derived from the same two declarations as `BY_OLD_NAME`, for the same reason: a hand-written
58
+ * migration list is one merge away from being wrong, and wrong is worse than absent here — the agent
59
+ * retries into it.
60
+ */
61
+ export function retiredToolNames() {
62
+ const tombstones = {};
63
+ for (const [old, redirect] of BY_OLD_NAME) {
64
+ tombstones[old] =
65
+ redirect.action === undefined
66
+ ? `retired; ${redirect.note ?? `use ${redirect.tool}`}`
67
+ : `retired; use ${redirect.tool} { action: "${redirect.action}" }`;
68
+ }
69
+ return tombstones;
70
+ }
49
71
  /** The sentence handed to an agent that called `name`. */
50
72
  export function mergedNameMessage(name, redirect) {
51
73
  return redirect.action === undefined
@@ -13,8 +13,6 @@
13
13
  */
14
14
  import type { SessionManager } from '../session/session-manager.js';
15
15
  import type { NavigateArrival } from './navigate-result.js';
16
- /** Long enough for a dev server to serve a page and the SDK to dial back; short enough to not hang. */
17
- export declare const ARRIVAL_TIMEOUT_MS = 5000;
18
16
  export interface ArrivalClock {
19
17
  now: () => number;
20
18
  sleep: (ms: number) => Promise<void>;
@@ -12,7 +12,7 @@
12
12
  * the sleep are injected so this is testable without waiting on a real one.
13
13
  */
14
14
  /** Long enough for a dev server to serve a page and the SDK to dial back; short enough to not hang. */
15
- export const ARRIVAL_TIMEOUT_MS = 5_000;
15
+ const ARRIVAL_TIMEOUT_MS = 5_000;
16
16
  const POLL_MS = 100;
17
17
  /**
18
18
  * Compare only origin + pathname.
@@ -0,0 +1,100 @@
1
+ /**
2
+ * Shared bounds for numeric TOOL INPUTS.
3
+ *
4
+ * An unknown parameter is refused with "They were NOT applied — a result computed without them
5
+ * would look like an answer." A known parameter carrying a value the code cannot honour is the
6
+ * same failure: `reticle_state { depth: -5 }` used to return the full unscoped store, because
7
+ * `capDepth` treats a negative budget as "no cap". The agent cannot tell a bound it asked for
8
+ * from a bound that was dropped.
9
+ *
10
+ * A single rule for every number would be wrong (`since: 0` is a real cursor; `timeout_ms: 0`
11
+ * on assert means evaluate now; `threshold` is a 0–1 ratio). Each helper below is one policy,
12
+ * with the sentence for why that bound and not another.
13
+ */
14
+ import { z } from 'zod';
15
+ /**
16
+ * Hard cap on "return the first N". The ring buffer holds this many events; asking for a billion
17
+ * cannot be honoured from memory we do not keep, and would look like a complete listing.
18
+ */
19
+ export declare const MAX_RESULT_COUNT: 2000;
20
+ /**
21
+ * Hard cap on a numeric millisecond argument that does NOT block the caller's request.
22
+ * `timeout_ms: 0` stays legal — it means evaluate once, do not wait.
23
+ */
24
+ export declare const MAX_TIMEOUT_MS = 120000;
25
+ export declare const MAX_BLOCKING_WAIT_MS: number;
26
+ /**
27
+ * `capDepth` at this many levels is already past any store an agent can read.
28
+ *
29
+ * Not lower: `numeric-args-are-bounded.test.ts` pins depth 50 as legal, because a large depth is a
30
+ * SCOPE choice and not an error. A ceiling that refuses it would turn a working call into a refusal
31
+ * in the name of bounding one that never worked.
32
+ */
33
+ export declare const MAX_STATE_DEPTH = 256;
34
+ /** A crawl that clicks forever is not a bound. */
35
+ export declare const MAX_CRAWL_STEPS = 500;
36
+ /** Scroll-to-find steps. Default is 20; hundreds is searching, thousands is a hang. */
37
+ export declare const MAX_SCROLLS = 200;
38
+ /** Fake-clock jump. One day of timers is a test; a billion ms is not. */
39
+ export declare const MAX_ADVANCE_MS = 86400000;
40
+ /** Presenter idle window. One hour is a slow app; larger values never fire. */
41
+ export declare const MAX_IDLE_MS = 3600000;
42
+ /** Viewport CSS px — matches the clamp the handler already applied, now as a refusal. */
43
+ export declare const MIN_VIEWPORT_PX = 64;
44
+ export declare const MAX_VIEWPORT_PX = 10000;
45
+ /**
46
+ * A page cursor. 0 is the start of the buffer, so `.positive()` would refuse a legitimate first
47
+ * page. Negative is not a cursor.
48
+ */
49
+ export declare const cursorSchema: z.ZodNumber;
50
+ /**
51
+ * A wait budget in ms. 0 means evaluate now (documented on assert). Negative cannot be honoured.
52
+ */
53
+ export declare const timeoutMsSchema: z.ZodNumber;
54
+ /**
55
+ * A count / cap. 0 means "return none", which is a real request. Negative is not.
56
+ * Capped at the ring-buffer size so a `limit: 1e9` cannot pretend the buffer is larger than it is.
57
+ */
58
+ export declare const countSchema: z.ZodNumber;
59
+ /**
60
+ * Store projection depth. Negative used to mean "no cap" inside `capDepth`, which is how
61
+ * `depth: -5` silently returned the full store — that is the defect this bound closes.
62
+ *
63
+ * 0 stays REFUSED, which is the policy already on the surface (a zero-level read is not a read).
64
+ * `capDepth(v, 0)` does return a size marker, so accepting it would be defensible — but that is a
65
+ * change to what the tool answers, not a bound on what it cannot honour, and it belongs in its own
66
+ * change with its own reason.
67
+ */
68
+ export declare const depthSchema: z.ZodNumber;
69
+ /**
70
+ * Pixel-diff ratios (`threshold`, `maxRatio`). pixelmatch's threshold and our pass ratio are both
71
+ * 0..1; `.int()` would refuse 0.01.
72
+ */
73
+ export declare const ratioSchema: z.ZodNumber;
74
+ /** HTTP status on a mock or a filter. */
75
+ export declare const httpStatusSchema: z.ZodNumber;
76
+ /** Viewport CSS px. `.int()` alone still accepted 5 and 999999, then the handler silently clamped. */
77
+ export declare const viewportPxSchema: z.ZodNumber;
78
+ /** Crawl / scroll step budgets. 0 is a documented no-op on crawl ("raise it to crawl at all"). */
79
+ export declare const stepCountSchema: z.ZodNumber;
80
+ export declare const scrollCountSchema: z.ZodNumber;
81
+ export declare const advanceMsSchema: z.ZodNumber;
82
+ export declare const idleMsSchema: z.ZodNumber;
83
+ /** Delay before a mocked response. 0 is immediate. */
84
+ export declare const delayMsSchema: z.ZodNumber;
85
+ /**
86
+ * Observe lookback. Must be > 0 — a non-positive window used to mint a FUTURE cursor, so the
87
+ * tool returned zero events and looked like a quiet page. Capped so `window_ms: 1e12` cannot hang.
88
+ */
89
+ export declare const windowMsSchema: z.ZodNumber;
90
+ /**
91
+ * Parallelism for suite replay. 0 (and omit) means sequential. Capped at the session/pool ceiling;
92
+ * asking for a thousand workers cannot be honoured.
93
+ */
94
+ export declare const workerCountSchema: z.ZodNumber;
95
+ /**
96
+ * A row index / list length in a virtualized table. Those lists are large on purpose; the ring
97
+ * buffer's 2000 is the wrong ceiling. A billion-row claim is not a list, it is a hang.
98
+ */
99
+ export declare const MAX_LIST_INDEX = 1000000;
100
+ export declare const listIndexSchema: z.ZodNumber;
@@ -0,0 +1,125 @@
1
+ /**
2
+ * Shared bounds for numeric TOOL INPUTS.
3
+ *
4
+ * An unknown parameter is refused with "They were NOT applied — a result computed without them
5
+ * would look like an answer." A known parameter carrying a value the code cannot honour is the
6
+ * same failure: `reticle_state { depth: -5 }` used to return the full unscoped store, because
7
+ * `capDepth` treats a negative budget as "no cap". The agent cannot tell a bound it asked for
8
+ * from a bound that was dropped.
9
+ *
10
+ * A single rule for every number would be wrong (`since: 0` is a real cursor; `timeout_ms: 0`
11
+ * on assert means evaluate now; `threshold` is a 0–1 ratio). Each helper below is one policy,
12
+ * with the sentence for why that bound and not another.
13
+ */
14
+ import { z } from 'zod';
15
+ import { RING_BUFFER_DEFAULTS, TRANSPORT_LIMITS } from '@reticlehq/core';
16
+ /**
17
+ * Hard cap on "return the first N". The ring buffer holds this many events; asking for a billion
18
+ * cannot be honoured from memory we do not keep, and would look like a complete listing.
19
+ */
20
+ export const MAX_RESULT_COUNT = RING_BUFFER_DEFAULTS.MAX_EVENTS;
21
+ /**
22
+ * Hard cap on a numeric millisecond argument that does NOT block the caller's request.
23
+ * `timeout_ms: 0` stays legal — it means evaluate once, do not wait.
24
+ */
25
+ export const MAX_TIMEOUT_MS = 120_000;
26
+ /**
27
+ * Hard cap on a wait the CALLER BLOCKS ON, which is a different ceiling from the one above.
28
+ *
29
+ * A blocking wait is bounded by the client's patience, not by ours. The MCP SDK's default request
30
+ * timeout is 60s and clients configure it lower; we advertised 120s. A caller who believed the
31
+ * advertised bound and asked for 90s got a TRANSPORT error at 60s — not a Reticle verdict, not a
32
+ * near-miss diagnosis, nothing to act on. The wait was honoured right up to the point where the
33
+ * only thing that could report it had gone.
34
+ *
35
+ * So the ceiling is set below the SDK default rather than at it: the margin is what lets Reticle's
36
+ * own "timed out, here is the near miss" answer beat the client's abort. A refused argument is a
37
+ * bad ceiling costing one round trip; an accepted one that cannot be delivered costs the drive.
38
+ *
39
+ * This does not make long waits possible, and is not meant to — it makes the ADVERTISED bound one
40
+ * that can actually be honoured. A caller that genuinely needs to outlast this polls: several short
41
+ * waits, each of which returns a verdict. See #601 for the bounded-wait cursor that would let one
42
+ * call do it properly.
43
+ */
44
+ const MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS = 60_000;
45
+ export const MAX_BLOCKING_WAIT_MS = MCP_SDK_DEFAULT_REQUEST_TIMEOUT_MS - 5_000;
46
+ /**
47
+ * `capDepth` at this many levels is already past any store an agent can read.
48
+ *
49
+ * Not lower: `numeric-args-are-bounded.test.ts` pins depth 50 as legal, because a large depth is a
50
+ * SCOPE choice and not an error. A ceiling that refuses it would turn a working call into a refusal
51
+ * in the name of bounding one that never worked.
52
+ */
53
+ export const MAX_STATE_DEPTH = 256;
54
+ /** A crawl that clicks forever is not a bound. */
55
+ export const MAX_CRAWL_STEPS = 500;
56
+ /** Scroll-to-find steps. Default is 20; hundreds is searching, thousands is a hang. */
57
+ export const MAX_SCROLLS = 200;
58
+ /** Fake-clock jump. One day of timers is a test; a billion ms is not. */
59
+ export const MAX_ADVANCE_MS = 86_400_000;
60
+ /** Presenter idle window. One hour is a slow app; larger values never fire. */
61
+ export const MAX_IDLE_MS = 3_600_000;
62
+ /** Viewport CSS px — matches the clamp the handler already applied, now as a refusal. */
63
+ export const MIN_VIEWPORT_PX = 64;
64
+ export const MAX_VIEWPORT_PX = 10_000;
65
+ /**
66
+ * A page cursor. 0 is the start of the buffer, so `.positive()` would refuse a legitimate first
67
+ * page. Negative is not a cursor.
68
+ */
69
+ export const cursorSchema = z.number().finite().int().nonnegative();
70
+ /**
71
+ * A wait budget in ms. 0 means evaluate now (documented on assert). Negative cannot be honoured.
72
+ */
73
+ export const timeoutMsSchema = z.number().finite().int().nonnegative().max(MAX_BLOCKING_WAIT_MS);
74
+ /**
75
+ * A count / cap. 0 means "return none", which is a real request. Negative is not.
76
+ * Capped at the ring-buffer size so a `limit: 1e9` cannot pretend the buffer is larger than it is.
77
+ */
78
+ export const countSchema = z.number().finite().int().nonnegative().max(MAX_RESULT_COUNT);
79
+ /**
80
+ * Store projection depth. Negative used to mean "no cap" inside `capDepth`, which is how
81
+ * `depth: -5` silently returned the full store — that is the defect this bound closes.
82
+ *
83
+ * 0 stays REFUSED, which is the policy already on the surface (a zero-level read is not a read).
84
+ * `capDepth(v, 0)` does return a size marker, so accepting it would be defensible — but that is a
85
+ * change to what the tool answers, not a bound on what it cannot honour, and it belongs in its own
86
+ * change with its own reason.
87
+ */
88
+ export const depthSchema = z.number().finite().int().positive().max(MAX_STATE_DEPTH);
89
+ /**
90
+ * Pixel-diff ratios (`threshold`, `maxRatio`). pixelmatch's threshold and our pass ratio are both
91
+ * 0..1; `.int()` would refuse 0.01.
92
+ */
93
+ export const ratioSchema = z.number().finite().min(0).max(1);
94
+ /** HTTP status on a mock or a filter. */
95
+ export const httpStatusSchema = z.number().finite().int().min(100).max(599);
96
+ /** Viewport CSS px. `.int()` alone still accepted 5 and 999999, then the handler silently clamped. */
97
+ export const viewportPxSchema = z.number().finite().int().min(MIN_VIEWPORT_PX).max(MAX_VIEWPORT_PX);
98
+ /** Crawl / scroll step budgets. 0 is a documented no-op on crawl ("raise it to crawl at all"). */
99
+ export const stepCountSchema = z.number().finite().int().nonnegative().max(MAX_CRAWL_STEPS);
100
+ export const scrollCountSchema = z.number().finite().int().nonnegative().max(MAX_SCROLLS);
101
+ export const advanceMsSchema = z.number().finite().int().nonnegative().max(MAX_ADVANCE_MS);
102
+ export const idleMsSchema = z.number().finite().int().nonnegative().max(MAX_IDLE_MS);
103
+ /** Delay before a mocked response. 0 is immediate. */
104
+ export const delayMsSchema = z.number().finite().int().nonnegative().max(MAX_TIMEOUT_MS);
105
+ /**
106
+ * Observe lookback. Must be > 0 — a non-positive window used to mint a FUTURE cursor, so the
107
+ * tool returned zero events and looked like a quiet page. Capped so `window_ms: 1e12` cannot hang.
108
+ */
109
+ export const windowMsSchema = z.number().finite().int().positive().max(MAX_TIMEOUT_MS);
110
+ /**
111
+ * Parallelism for suite replay. 0 (and omit) means sequential. Capped at the session/pool ceiling;
112
+ * asking for a thousand workers cannot be honoured.
113
+ */
114
+ export const workerCountSchema = z
115
+ .number()
116
+ .finite()
117
+ .int()
118
+ .nonnegative()
119
+ .max(TRANSPORT_LIMITS.MAX_SESSIONS);
120
+ /**
121
+ * A row index / list length in a virtualized table. Those lists are large on purpose; the ring
122
+ * buffer's 2000 is the wrong ceiling. A billion-row claim is not a list, it is a hang.
123
+ */
124
+ export const MAX_LIST_INDEX = 1_000_000;
125
+ export const listIndexSchema = z.number().finite().int().nonnegative().max(MAX_LIST_INDEX);