@reticlehq/server 2.4.0 → 2.6.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 (472) hide show
  1. package/SKILL.md +719 -0
  2. package/dist/bridge/auth-failure-reason.d.ts +19 -0
  3. package/dist/bridge/auth-failure-reason.js +29 -0
  4. package/dist/{bridge-security.d.ts → bridge/bridge-security.d.ts} +1 -1
  5. package/dist/{bridge-security.js → bridge/bridge-security.js} +1 -1
  6. package/dist/{bridge.d.ts → bridge/bridge.d.ts} +13 -1
  7. package/dist/{bridge.js → bridge/bridge.js} +95 -15
  8. package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +9 -11
  9. package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +18 -10
  10. package/dist/{pairing-token.js → bridge/pairing-token.js} +1 -1
  11. package/dist/capsule/capsule-store.d.ts +8 -3
  12. package/dist/capsule/capsule-store.js +7 -2
  13. package/dist/capsule/capsule.js +3 -3
  14. package/dist/capsule/causal-summary.d.ts +8 -0
  15. package/dist/capsule/causal-summary.js +22 -12
  16. package/dist/capsule/divergence.d.ts +9 -4
  17. package/dist/capsule/divergence.js +8 -8
  18. package/dist/capsule/predicate-to-links.js +11 -8
  19. package/dist/cli/cli-doctor.d.ts +1 -0
  20. package/dist/cli/cli-doctor.js +135 -0
  21. package/dist/{cli-flow-commands.d.ts → cli/cli-flow-commands.d.ts} +2 -2
  22. package/dist/{cli-flow-commands.js → cli/cli-flow-commands.js} +15 -15
  23. package/dist/{cli-launch.d.ts → cli/cli-launch.d.ts} +32 -3
  24. package/dist/cli/cli-launch.js +171 -0
  25. package/dist/cli/cli-parse-feedback.d.ts +31 -0
  26. package/dist/cli/cli-parse-feedback.js +56 -0
  27. package/dist/{cli-parse.d.ts → cli/cli-parse.d.ts} +6 -19
  28. package/dist/{cli-parse.js → cli/cli-parse.js} +118 -81
  29. package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +12 -0
  30. package/dist/{cli-port.js → cli/cli-port.js} +9 -9
  31. package/dist/cli/cli-update-commands.d.ts +4 -0
  32. package/dist/cli/cli-update-commands.js +93 -0
  33. package/dist/{cli-verify.js → cli/cli-verify.js} +14 -14
  34. package/dist/{cloud-cli.js → cli/cloud-cli.js} +29 -24
  35. package/dist/cli/doctor-daemon-line.d.ts +37 -0
  36. package/dist/cli/doctor-daemon-line.js +35 -0
  37. package/dist/cli/port-holder.d.ts +43 -0
  38. package/dist/cli/port-holder.js +99 -0
  39. package/dist/cli.d.ts +2 -2
  40. package/dist/cli.js +302 -100
  41. package/dist/cloud/cloud-config.d.ts +0 -1
  42. package/dist/cloud/cloud-config.js +9 -9
  43. package/dist/cloud/cloud-sync.d.ts +1 -7
  44. package/dist/cloud/cloud-sync.js +12 -12
  45. package/dist/crawl/crawl-empty.d.ts +16 -0
  46. package/dist/crawl/crawl-empty.js +24 -0
  47. package/dist/crawl/crawl-tools.js +4 -1
  48. package/dist/crawl/crawl.js +26 -7
  49. package/dist/daemon/daemon-resilience.d.ts +73 -0
  50. package/dist/daemon/daemon-resilience.js +279 -0
  51. package/dist/daemon/daemon-usefulness.d.ts +61 -0
  52. package/dist/daemon/daemon-usefulness.js +62 -0
  53. package/dist/{daemon.d.ts → daemon/daemon.d.ts} +33 -8
  54. package/dist/{daemon.js → daemon/daemon.js} +105 -48
  55. package/dist/daemon/heartbeat.d.ts +115 -0
  56. package/dist/daemon/heartbeat.js +141 -0
  57. package/dist/daemon/idle-grace.d.ts +32 -0
  58. package/dist/daemon/idle-grace.js +41 -0
  59. package/dist/{idle-shutdown.d.ts → daemon/idle-shutdown.d.ts} +23 -2
  60. package/dist/{idle-shutdown.js → daemon/idle-shutdown.js} +37 -6
  61. package/dist/daemon/port-presence.d.ts +76 -0
  62. package/dist/daemon/port-presence.js +93 -0
  63. package/dist/daemon/state-dir.d.ts +7 -0
  64. package/dist/daemon/state-dir.js +59 -0
  65. package/dist/daemon/unclean-predecessor.d.ts +23 -0
  66. package/dist/daemon/unclean-predecessor.js +27 -0
  67. package/dist/domain/domain-model.js +2 -2
  68. package/dist/events/body-failures.js +8 -8
  69. package/dist/events/contradictions.d.ts +1 -1
  70. package/dist/events/contradictions.js +60 -10
  71. package/dist/events/echo-mismatch.js +10 -10
  72. package/dist/events/event-filters.js +6 -6
  73. package/dist/events/json-salvage.d.ts +2 -1
  74. package/dist/events/json-salvage.js +6 -6
  75. package/dist/events/observed-in-window.d.ts +12 -0
  76. package/dist/events/observed-in-window.js +21 -0
  77. package/dist/events/predicate-eval.d.ts +53 -20
  78. package/dist/events/predicate-eval.js +179 -55
  79. package/dist/events/predicate-parse.d.ts +23 -0
  80. package/dist/events/predicate-parse.js +54 -0
  81. package/dist/events/predicate.d.ts +7 -2
  82. package/dist/events/predicate.js +126 -35
  83. package/dist/events/reconcile.js +5 -5
  84. package/dist/events/ring-buffer.js +2 -17
  85. package/dist/events/stale-response.js +6 -6
  86. package/dist/events/testid-near-miss.d.ts +22 -0
  87. package/dist/events/testid-near-miss.js +33 -0
  88. package/dist/events/unit-mismatch.js +8 -8
  89. package/dist/flows/affected-tools.js +19 -4
  90. package/dist/flows/affected.js +1 -1
  91. package/dist/flows/annotate-target.d.ts +1 -0
  92. package/dist/flows/annotate-target.js +20 -0
  93. package/dist/flows/annotate-tools.js +25 -3
  94. package/dist/flows/annotate.js +17 -4
  95. package/dist/flows/assertion-integrity.d.ts +2 -1
  96. package/dist/flows/assertion-tiers-store.d.ts +3 -66
  97. package/dist/flows/assertion-tiers-store.js +2 -2
  98. package/dist/flows/attributed-failure.d.ts +17 -0
  99. package/dist/flows/attributed-failure.js +20 -0
  100. package/dist/flows/buddy-status.d.ts +2 -1
  101. package/dist/flows/buddy-status.js +2 -2
  102. package/dist/flows/coverage.d.ts +3 -2
  103. package/dist/flows/coverage.js +2 -2
  104. package/dist/flows/decision.js +24 -9
  105. package/dist/flows/empty-flow.d.ts +6 -0
  106. package/dist/flows/empty-flow.js +24 -0
  107. package/dist/flows/flake-store.d.ts +0 -1
  108. package/dist/flows/flake-store.js +1 -1
  109. package/dist/flows/flake.d.ts +2 -1
  110. package/dist/flows/flake.js +2 -2
  111. package/dist/flows/flow-classify.js +12 -0
  112. package/dist/flows/flow-replay-run.js +4 -4
  113. package/dist/flows/flow-replay.d.ts +6 -8
  114. package/dist/flows/flow-replay.js +132 -48
  115. package/dist/flows/flow-report.js +1 -1
  116. package/dist/flows/flow-scope.d.ts +1 -6
  117. package/dist/flows/flow-step-runners.d.ts +26 -6
  118. package/dist/flows/flow-step-runners.js +156 -6
  119. package/dist/flows/flow-success.js +20 -15
  120. package/dist/flows/flow-tools.js +63 -21
  121. package/dist/flows/flows.js +15 -11
  122. package/dist/flows/gate.d.ts +4 -3
  123. package/dist/flows/gate.js +1 -1
  124. package/dist/flows/heal-run.d.ts +0 -8
  125. package/dist/flows/heal-run.js +5 -5
  126. package/dist/flows/heal.js +3 -3
  127. package/dist/flows/predicate-to-expect.d.ts +38 -0
  128. package/dist/flows/predicate-to-expect.js +95 -0
  129. package/dist/flows/replay.d.ts +16 -1
  130. package/dist/flows/replay.js +58 -22
  131. package/dist/flows/role-anchor-nearest.d.ts +6 -0
  132. package/dist/flows/role-anchor-nearest.js +45 -0
  133. package/dist/flows/role-drift-reason.d.ts +20 -0
  134. package/dist/flows/role-drift-reason.js +39 -0
  135. package/dist/flows/server-verify.d.ts +1 -1
  136. package/dist/flows/server-verify.js +5 -5
  137. package/dist/flows/suite-flakes.d.ts +33 -0
  138. package/dist/flows/suite-flakes.js +32 -0
  139. package/dist/flows/verify-change-tools.js +32 -10
  140. package/dist/flows/verify-change-verdict.d.ts +15 -0
  141. package/dist/flows/verify-change-verdict.js +25 -0
  142. package/dist/flows/watch-batcher.d.ts +3 -2
  143. package/dist/honesty/already-true.d.ts +2 -0
  144. package/dist/honesty/already-true.js +31 -0
  145. package/dist/honesty/blind-spots.d.ts +35 -3
  146. package/dist/honesty/blind-spots.js +57 -12
  147. package/dist/honesty/honesty.d.ts +3 -2
  148. package/dist/honesty/honesty.js +4 -4
  149. package/dist/honesty/uncaptured-bodies.js +1 -1
  150. package/dist/honesty/unread-outcome.js +2 -2
  151. package/dist/honesty/verified.d.ts +31 -3
  152. package/dist/honesty/verified.js +64 -8
  153. package/dist/http-server.js +23 -7
  154. package/dist/hunt/hunt-report.d.ts +2 -1
  155. package/dist/hunt/hunt-report.js +2 -2
  156. package/dist/index.d.ts +9 -6
  157. package/dist/index.js +41 -25
  158. package/dist/init/agent-rules.d.ts +20 -1
  159. package/dist/init/agent-rules.js +64 -8
  160. package/dist/init/app-choice.d.ts +20 -0
  161. package/dist/init/app-choice.js +25 -0
  162. package/dist/init/astro-host.d.ts +21 -0
  163. package/dist/init/astro-host.js +27 -0
  164. package/dist/init/astro-patch.d.ts +16 -0
  165. package/dist/init/astro-patch.js +240 -0
  166. package/dist/init/capabilities.js +4 -1
  167. package/dist/init/cra.d.ts +50 -0
  168. package/dist/init/cra.js +106 -0
  169. package/dist/init/cursor.js +39 -4
  170. package/dist/init/desktop-doctor.d.ts +3 -2
  171. package/dist/init/desktop-doctor.js +4 -4
  172. package/dist/init/detect.d.ts +9 -2
  173. package/dist/init/detect.js +24 -5
  174. package/dist/init/mcp-clients.d.ts +81 -0
  175. package/dist/init/mcp-clients.js +248 -0
  176. package/dist/init/mcp-registered.d.ts +12 -0
  177. package/dist/init/mcp-registered.js +14 -0
  178. package/dist/init/mcp.d.ts +27 -2
  179. package/dist/init/mcp.js +40 -4
  180. package/dist/init/next-patch.d.ts +2 -4
  181. package/dist/init/next-patch.js +109 -19
  182. package/dist/init/node-io.js +29 -6
  183. package/dist/init/plan-framework.d.ts +16 -1
  184. package/dist/init/plan-framework.js +166 -8
  185. package/dist/init/plan.d.ts +85 -6
  186. package/dist/init/plan.js +196 -33
  187. package/dist/init/project-id.d.ts +5 -9
  188. package/dist/init/project-id.js +10 -22
  189. package/dist/init/run.d.ts +23 -1
  190. package/dist/init/run.js +338 -47
  191. package/dist/init/slash-command.d.ts +9 -0
  192. package/dist/init/slash-command.js +10 -1
  193. package/dist/init/snippets.d.ts +7 -10
  194. package/dist/init/snippets.js +44 -15
  195. package/dist/init/vite-config.js +1 -1
  196. package/dist/init/windows-quote.d.ts +38 -0
  197. package/dist/init/windows-quote.js +70 -0
  198. package/dist/init/workspace-apps.d.ts +23 -0
  199. package/dist/init/workspace-apps.js +68 -0
  200. package/dist/input/driven-redaction.js +1 -1
  201. package/dist/input/network-detail.js +8 -8
  202. package/dist/input/network-mock-tools.js +2 -2
  203. package/dist/input/network-mock.js +4 -4
  204. package/dist/input/real-input.js +8 -3
  205. package/dist/input/scroll-find.js +2 -2
  206. package/dist/input/scroll-tools.d.ts +0 -5
  207. package/dist/input/scroll-tools.js +11 -4
  208. package/dist/input/viewport-tools.js +2 -2
  209. package/dist/journal/ambient-store.d.ts +0 -2
  210. package/dist/journal/ambient-store.js +1 -1
  211. package/dist/journal/ambient.js +1 -1
  212. package/dist/journal/attach-journal.d.ts +2 -1
  213. package/dist/journal/deviation-report.js +6 -6
  214. package/dist/journal/deviation-service.js +1 -1
  215. package/dist/journal/envelope-store.d.ts +0 -2
  216. package/dist/journal/envelope-store.js +1 -1
  217. package/dist/journal/envelope.d.ts +2 -3
  218. package/dist/journal/envelope.js +3 -3
  219. package/dist/journal/journal-query.js +1 -1
  220. package/dist/journal/journal-recorder.d.ts +2 -1
  221. package/dist/journal/journal-recorder.js +2 -2
  222. package/dist/journal/rollups.js +9 -9
  223. package/dist/journal/session-end.d.ts +2 -1
  224. package/dist/journal/session-journal.js +4 -4
  225. package/dist/license/license.d.ts +0 -14
  226. package/dist/license/license.js +8 -8
  227. package/dist/log.d.ts +10 -0
  228. package/dist/log.js +11 -1
  229. package/dist/mcp/mcp-is-error.d.ts +13 -0
  230. package/dist/mcp/mcp-is-error.js +18 -0
  231. package/dist/mcp/mcp-outage.d.ts +32 -0
  232. package/dist/mcp/mcp-outage.js +55 -0
  233. package/dist/mcp/mcp-proxy.d.ts +134 -0
  234. package/dist/mcp/mcp-proxy.js +720 -0
  235. package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
  236. package/dist/{mcp.js → mcp/mcp.js} +139 -37
  237. package/dist/mcp/proxy-handshake.d.ts +3 -0
  238. package/dist/mcp/proxy-handshake.js +54 -0
  239. package/dist/mcp/proxy-lifecycle.d.ts +64 -0
  240. package/dist/mcp/proxy-lifecycle.js +70 -0
  241. package/dist/mcp/tool-catalog-cache.d.ts +29 -0
  242. package/dist/mcp/tool-catalog-cache.js +55 -0
  243. package/dist/oracles/propose-consequences.d.ts +2 -1
  244. package/dist/oracles/propose-consequences.js +16 -11
  245. package/dist/oracles/self-instrument.d.ts +2 -1
  246. package/dist/oracles/self-instrument.js +1 -1
  247. package/dist/phenomena/phenomena.js +3 -3
  248. package/dist/platform.d.ts +16 -0
  249. package/dist/platform.js +16 -0
  250. package/dist/pool/browser-pool.d.ts +9 -0
  251. package/dist/pool/browser-pool.js +38 -9
  252. package/dist/pool/playwright-launcher.d.ts +15 -2
  253. package/dist/pool/playwright-launcher.js +21 -2
  254. package/dist/project/fs-port.js +1 -1
  255. package/dist/project/project-tools.js +2 -2
  256. package/dist/runs/build-verification-run.js +1 -1
  257. package/dist/runs/repair-prompt.d.ts +0 -6
  258. package/dist/runs/repair-prompt.js +3 -3
  259. package/dist/runs/risk-classify.js +1 -1
  260. package/dist/runs/run-diff.d.ts +0 -2
  261. package/dist/runs/run-diff.js +3 -3
  262. package/dist/runs/run-tools.js +2 -2
  263. package/dist/runs/verification-sync.js +2 -2
  264. package/dist/runs/verify-http.js +1 -1
  265. package/dist/runs/verify-server.js +1 -1
  266. package/dist/session/attachment-history.d.ts +46 -0
  267. package/dist/session/attachment-history.js +65 -0
  268. package/dist/session/command-timeout.d.ts +11 -3
  269. package/dist/session/command-timeout.js +2 -2
  270. package/dist/session/control-envelope.d.ts +6 -0
  271. package/dist/session/control-envelope.js +7 -1
  272. package/dist/session/dev-server-probe.d.ts +13 -0
  273. package/dist/session/dev-server-probe.js +52 -0
  274. package/dist/session/last-act.d.ts +17 -3
  275. package/dist/session/last-act.js +16 -4
  276. package/dist/session/live-control-tools.js +7 -2
  277. package/dist/session/live-control.js +1 -1
  278. package/dist/session/looks-like-dev-server.d.ts +14 -0
  279. package/dist/session/looks-like-dev-server.js +25 -0
  280. package/dist/session/no-session-diagnosis.d.ts +45 -0
  281. package/dist/session/no-session-diagnosis.js +120 -0
  282. package/dist/session/no-session-watch.d.ts +21 -0
  283. package/dist/session/no-session-watch.js +69 -0
  284. package/dist/session/observed-state.d.ts +4 -0
  285. package/dist/session/observed-state.js +19 -1
  286. package/dist/session/output-budget.js +1 -1
  287. package/dist/session/pending-commands.js +1 -0
  288. package/dist/session/session-health.d.ts +8 -1
  289. package/dist/session/session-health.js +8 -7
  290. package/dist/session/session-info.d.ts +43 -8
  291. package/dist/session/session-info.js +46 -1
  292. package/dist/session/session-lease.d.ts +0 -11
  293. package/dist/session/session-lease.js +1 -1
  294. package/dist/session/session-manager.d.ts +6 -0
  295. package/dist/session/session-manager.js +124 -12
  296. package/dist/session/session-readiness.d.ts +1 -1
  297. package/dist/session/session-readiness.js +6 -1
  298. package/dist/session/session-reaper.js +1 -1
  299. package/dist/session/session-reconnect.d.ts +32 -0
  300. package/dist/session/session-reconnect.js +42 -0
  301. package/dist/session/session.d.ts +15 -2
  302. package/dist/session/session.js +77 -26
  303. package/dist/session/state-select.d.ts +1 -1
  304. package/dist/session/state-select.js +1 -1
  305. package/dist/status-payload.d.ts +19 -0
  306. package/dist/status-payload.js +11 -0
  307. package/dist/telemetry/argument-shape.js +10 -1
  308. package/dist/telemetry/browser-mode.d.ts +27 -0
  309. package/dist/telemetry/browser-mode.js +33 -0
  310. package/dist/telemetry/bug-found.d.ts +17 -21
  311. package/dist/telemetry/bug-found.js +120 -8
  312. package/dist/telemetry/cli-telemetry.d.ts +2 -12
  313. package/dist/telemetry/cli-telemetry.js +27 -4
  314. package/dist/telemetry/crash-cause.d.ts +47 -0
  315. package/dist/telemetry/crash-cause.js +104 -0
  316. package/dist/telemetry/daemon-telemetry.d.ts +38 -1
  317. package/dist/telemetry/daemon-telemetry.js +37 -12
  318. package/dist/telemetry/dev-repo.js +4 -4
  319. package/dist/telemetry/error-class.d.ts +26 -0
  320. package/dist/telemetry/error-class.js +52 -0
  321. package/dist/telemetry/error-fingerprint.js +21 -2
  322. package/dist/telemetry/feedback-cli.d.ts +8 -3
  323. package/dist/telemetry/feedback-cli.js +52 -8
  324. package/dist/telemetry/feedback-context.d.ts +23 -6
  325. package/dist/telemetry/feedback-context.js +105 -5
  326. package/dist/telemetry/feedback-delivery.d.ts +20 -0
  327. package/dist/telemetry/feedback-delivery.js +30 -0
  328. package/dist/telemetry/feedback-outbox.d.ts +22 -0
  329. package/dist/telemetry/feedback-outbox.js +87 -0
  330. package/dist/telemetry/feedback.d.ts +22 -1
  331. package/dist/telemetry/feedback.js +67 -8
  332. package/dist/telemetry/git-facts.d.ts +7 -0
  333. package/dist/telemetry/git-facts.js +5 -5
  334. package/dist/telemetry/project-profile.js +2 -1
  335. package/dist/telemetry/session-metrics.d.ts +47 -3
  336. package/dist/telemetry/session-metrics.js +315 -15
  337. package/dist/telemetry/telemetry.d.ts +45 -2
  338. package/dist/telemetry/telemetry.js +150 -37
  339. package/dist/telemetry/verification-of.d.ts +22 -0
  340. package/dist/telemetry/verification-of.js +84 -0
  341. package/dist/tools/act-capsule.js +2 -2
  342. package/dist/tools/act-danger.d.ts +12 -0
  343. package/dist/tools/act-danger.js +20 -3
  344. package/dist/tools/act-helpers.js +4 -4
  345. package/dist/tools/act-tools.d.ts +0 -8
  346. package/dist/tools/act-tools.js +114 -118
  347. package/dist/tools/act-view.js +7 -7
  348. package/dist/tools/alias-args.d.ts +17 -0
  349. package/dist/tools/alias-args.js +25 -0
  350. package/dist/tools/assert-grade.js +9 -9
  351. package/dist/tools/assert-verdict.d.ts +9 -1
  352. package/dist/tools/assert-verdict.js +21 -6
  353. package/dist/tools/browser-tools.js +36 -11
  354. package/dist/tools/contract-tools.d.ts +0 -5
  355. package/dist/tools/contract-tools.js +27 -1
  356. package/dist/tools/coverage-identity.d.ts +34 -0
  357. package/dist/tools/coverage-identity.js +46 -0
  358. package/dist/tools/coverage-tools.js +10 -14
  359. package/dist/tools/dynamic-tools.d.ts +2 -1
  360. package/dist/tools/dynamic-tools.js +96 -19
  361. package/dist/tools/error-recovery.d.ts +34 -2
  362. package/dist/tools/error-recovery.js +255 -4
  363. package/dist/tools/feedback-invite.d.ts +48 -0
  364. package/dist/tools/feedback-invite.js +71 -0
  365. package/dist/tools/feedback-tools.d.ts +12 -1
  366. package/dist/tools/feedback-tools.js +28 -5
  367. package/dist/tools/invoke-tool.d.ts +0 -12
  368. package/dist/tools/invoke-tool.js +126 -33
  369. package/dist/tools/lease-hint.d.ts +17 -0
  370. package/dist/tools/lease-hint.js +24 -0
  371. package/dist/tools/lease-tools.js +6 -5
  372. package/dist/tools/merge-tools.d.ts +10 -1
  373. package/dist/tools/merge-tools.js +9 -3
  374. package/dist/tools/merged-name-redirect.d.ts +13 -0
  375. package/dist/tools/merged-name-redirect.js +55 -0
  376. package/dist/tools/navigate-arrival.d.ts +26 -0
  377. package/dist/tools/navigate-arrival.js +60 -0
  378. package/dist/tools/navigate-result.d.ts +31 -0
  379. package/dist/tools/navigate-result.js +38 -0
  380. package/dist/tools/observe-tools.js +72 -20
  381. package/dist/tools/observed-nothing.d.ts +25 -0
  382. package/dist/tools/observed-nothing.js +33 -0
  383. package/dist/tools/query-paginate.js +2 -2
  384. package/dist/tools/query-shape.d.ts +18 -0
  385. package/dist/tools/query-shape.js +39 -0
  386. package/dist/tools/read-tools.js +81 -20
  387. package/dist/tools/real-input-attempt.d.ts +28 -0
  388. package/dist/tools/real-input-attempt.js +93 -0
  389. package/dist/tools/reconcile-tools.js +7 -7
  390. package/dist/tools/reload-result.d.ts +14 -0
  391. package/dist/tools/reload-result.js +29 -0
  392. package/dist/tools/snapshot-delta.d.ts +4 -5
  393. package/dist/tools/snapshot-delta.js +0 -0
  394. package/dist/tools/tool-kit.d.ts +16 -0
  395. package/dist/tools/tool-surface.d.ts +83 -0
  396. package/dist/tools/tool-surface.js +217 -0
  397. package/dist/tools/tools-helpers.js +6 -6
  398. package/dist/tools/tools.d.ts +15 -0
  399. package/dist/tools/tools.js +53 -17
  400. package/dist/tools/unadvertised-help.d.ts +5 -0
  401. package/dist/tools/unadvertised-help.js +39 -0
  402. package/dist/trace.d.ts +69 -0
  403. package/dist/trace.js +150 -0
  404. package/dist/update/nudge-credit.d.ts +4 -0
  405. package/dist/update/nudge-credit.js +53 -0
  406. package/dist/update/sdk-sync.d.ts +21 -0
  407. package/dist/update/sdk-sync.js +42 -0
  408. package/dist/update/update-checker.js +3 -3
  409. package/dist/update/update-nudge.d.ts +63 -6
  410. package/dist/update/update-nudge.js +128 -15
  411. package/dist/update/updater.d.ts +1 -9
  412. package/dist/update/updater.js +13 -8
  413. package/dist/version/peer-announce.d.ts +4 -0
  414. package/dist/version/peer-announce.js +30 -0
  415. package/dist/{server-version.js → version/server-version.js} +5 -1
  416. package/dist/version/version-nudge.d.ts +28 -0
  417. package/dist/version/version-nudge.js +40 -0
  418. package/dist/version/version-skew.d.ts +66 -0
  419. package/dist/version/version-skew.js +71 -0
  420. package/dist/visual/visual-diff.js +2 -2
  421. package/dist/visual/visual-tools.js +4 -4
  422. package/docs/README.md +55 -0
  423. package/docs/agent-cheatsheet.md +85 -0
  424. package/docs/architecture.md +113 -0
  425. package/docs/benchmarks.md +255 -0
  426. package/docs/debugging.md +102 -0
  427. package/docs/deploy-checks.md +69 -0
  428. package/docs/desktop-apps.md +256 -0
  429. package/docs/enterprise.md +62 -0
  430. package/docs/fixtures-dispatch-receiver.yml +76 -0
  431. package/docs/fixtures.md +45 -0
  432. package/docs/flows.md +166 -0
  433. package/docs/gate-plan.md +98 -0
  434. package/docs/gates.md +117 -0
  435. package/docs/getting-started.md +469 -0
  436. package/docs/human-control.md +63 -0
  437. package/docs/integration-patterns.md +171 -0
  438. package/docs/local-registry.md +126 -0
  439. package/docs/matrix/2.5.0/claude-code-machine.json +19 -0
  440. package/docs/matrix/2.5.0/codex-machine.json +20 -0
  441. package/docs/matrix/2.5.0/cursor-machine.json +22 -0
  442. package/docs/matrix/2.5.0/gemini-machine.json +22 -0
  443. package/docs/matrix/2.5.0/opencode-machine.json +22 -0
  444. package/docs/matrix/2.5.0/vscode-machine.json +22 -0
  445. package/docs/matrix/2.5.0/windsurf-machine.json +22 -0
  446. package/docs/matrix/MATRIX.md +26 -0
  447. package/docs/matrix/README.md +59 -0
  448. package/docs/mint.json +61 -0
  449. package/docs/multi-agent-testing.md +55 -0
  450. package/docs/platform-integration.md +122 -0
  451. package/docs/system-map.md +152 -0
  452. package/docs/telemetry-contract.md +214 -0
  453. package/docs/telemetry.md +191 -0
  454. package/docs/testing.md +82 -0
  455. package/docs/token-efficiency.md +80 -0
  456. package/docs/usage.md +1046 -0
  457. package/package.json +8 -5
  458. package/dist/cli-doctor.d.ts +0 -6
  459. package/dist/cli-doctor.js +0 -60
  460. package/dist/cli-launch.js +0 -112
  461. package/dist/daemon-resilience.d.ts +0 -22
  462. package/dist/daemon-resilience.js +0 -85
  463. package/dist/mcp-proxy.d.ts +0 -67
  464. package/dist/mcp-proxy.js +0 -337
  465. package/dist/tools/profiles.d.ts +0 -37
  466. package/dist/tools/profiles.js +0 -139
  467. /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
  468. /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
  469. /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
  470. /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
  471. /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
  472. /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
package/dist/mcp-proxy.js DELETED
@@ -1,337 +0,0 @@
1
- import * as http from 'node:http';
2
- import * as net from 'node:net';
3
- import { appendFileSync, mkdirSync } from 'node:fs';
4
- import { homedir } from 'node:os';
5
- import { join } from 'node:path';
6
- import { LOOPBACK_HOST, MCP_SSE_PATH, ReticleDir } from '@reticlehq/core';
7
- import { log } from './log.js';
8
- const DEFAULT_DAEMON_READY_TIMEOUT_MS = 10_000;
9
- /**
10
- * How long to wait for the spawned daemon's port to accept connections before giving up. The default
11
- * suits a normal machine; a slow CI/VM (heavy headless-browser launch) can raise it via the
12
- * RETICLE_DAEMON_READY_TIMEOUT_MS env var. Invalid/absent values fall back to the default.
13
- */
14
- const envDaemonReadyTimeoutMs = Number(process.env['RETICLE_DAEMON_READY_TIMEOUT_MS']);
15
- const DAEMON_READY_TIMEOUT_MS = Number.isFinite(envDaemonReadyTimeoutMs) && envDaemonReadyTimeoutMs > 0
16
- ? envDaemonReadyTimeoutMs
17
- : DEFAULT_DAEMON_READY_TIMEOUT_MS;
18
- const DAEMON_POLL_INTERVAL_MS = 100;
19
- function delay(ms) {
20
- return new Promise((resolve) => setTimeout(resolve, ms));
21
- }
22
- /** Reconnect backoff: linear, capped, so a briefly-restarting daemon is picked up fast. */
23
- const RECONNECT_BASE_MS = 250;
24
- const RECONNECT_CAP_MS = 5_000;
25
- /**
26
- * How many consecutive failed reconnects before the proxy gives up and exits. At the capped backoff
27
- * this is a few minutes — long enough to ride out a daemon restart, short enough that a genuinely
28
- * dead daemon lets the agent host respawn the proxy (which spawns a fresh daemon) instead of hanging.
29
- */
30
- export const MAX_RECONNECT_ATTEMPTS = 60;
31
- export function reconnectDelayMs(attempt) {
32
- return Math.min(RECONNECT_BASE_MS * attempt, RECONNECT_CAP_MS);
33
- }
34
- /** JSON-RPC id the proxy uses for its own replayed `initialize` — never one the client could send. */
35
- export const RECONNECT_INITIALIZE_ID = '__reticle_proxy_reinit';
36
- /** The proxy's own log file, so a silent drop leaves a readable trace the agent can go read. */
37
- export function proxyLogPath() {
38
- return join(homedir(), ReticleDir.ROOT, 'mcp-proxy.log');
39
- }
40
- /**
41
- * Log to stderr (which the agent host usually swallows) AND to ~/.reticle/mcp-proxy.log, which it
42
- * does not. A dropped MCP connection is invisible from the agent's side — no message, no exit code —
43
- * so the one thing that makes it diagnosable at all is a file somebody can read afterwards.
44
- */
45
- function proxyLog(event, fields = {}) {
46
- log(event, fields);
47
- try {
48
- const dir = join(homedir(), ReticleDir.ROOT);
49
- mkdirSync(dir, { recursive: true });
50
- appendFileSync(proxyLogPath(), `${JSON.stringify({ event, ...fields })}\n`, 'utf8');
51
- }
52
- catch {
53
- // Logging must never be the thing that kills the proxy.
54
- }
55
- }
56
- function parseJsonRpc(line) {
57
- try {
58
- const parsed = JSON.parse(line);
59
- return typeof parsed === 'object' && parsed !== null ? parsed : null;
60
- }
61
- catch {
62
- return null;
63
- }
64
- }
65
- const INITIALIZE_METHOD = 'initialize';
66
- const INITIALIZED_METHOD = 'notifications/initialized';
67
- /**
68
- * Makes a reconnect invisible to the client.
69
- *
70
- * The daemon builds a FRESH `McpServer` per SSE connection, so a reconnected session has never seen
71
- * the client's `initialize` — every subsequent `tools/call` would hit an uninitialized server. The
72
- * proxy therefore remembers the handshake the client sent once and replays it into each new session.
73
- * The replay is re-issued under a reserved id so the daemon's response to it can be dropped rather
74
- * than reaching the client's stdout, where a duplicate JSON-RPC id would be a protocol violation.
75
- */
76
- export class HandshakeReplay {
77
- #initialize = null;
78
- #initialized = null;
79
- #pendingReplayId = null;
80
- /** Record one outbound client line. Cheap enough to call for every stdin message. */
81
- observeOutbound(line) {
82
- const msg = parseJsonRpc(line);
83
- if (msg === null)
84
- return;
85
- // The first initialize is the session's identity; a client re-issuing one does not change it.
86
- if (msg.method === INITIALIZE_METHOD && this.#initialize === null)
87
- this.#initialize = line;
88
- else if (msg.method === INITIALIZED_METHOD)
89
- this.#initialized = line;
90
- }
91
- /** Lines to POST into a freshly-established session, before any queued client traffic. */
92
- replayLines() {
93
- if (this.#initialize === null)
94
- return [];
95
- const msg = parseJsonRpc(this.#initialize);
96
- if (msg === null)
97
- return [];
98
- this.#pendingReplayId = RECONNECT_INITIALIZE_ID;
99
- const reinit = { ...msg, id: RECONNECT_INITIALIZE_ID };
100
- return this.#initialized === null
101
- ? [JSON.stringify(reinit)]
102
- : [JSON.stringify(reinit), this.#initialized];
103
- }
104
- /** True when this inbound daemon line is the echo of our replayed handshake and must not be forwarded. */
105
- shouldSuppressInbound(line) {
106
- if (this.#pendingReplayId === null)
107
- return false;
108
- const msg = parseJsonRpc(line);
109
- if (msg === null || msg.id !== this.#pendingReplayId)
110
- return false;
111
- this.#pendingReplayId = null; // one response per replay — anything later is not ours to swallow
112
- return true;
113
- }
114
- }
115
- /**
116
- * Incremental SSE frame parser for the MCP front door.
117
- *
118
- * A single SSE field can split across TCP reads (`da` in one chunk, `ta: {...}` in the next), and a
119
- * server may send CRLF or bare CR line endings — so the framing is stateful and edge-case-prone, yet it
120
- * carried every MCP message the agent sends and was only ever exercised end-to-end. Pulled out of the
121
- * socket handler as a pure, chunk-fed parser so those boundaries are unit-testable: feed raw chunks,
122
- * get back each complete frame (a blank line terminates a frame; `event:` names it, `data:` lines
123
- * accumulate newline-joined; `id:`/`retry:`/comments are ignored — not needed for the bridge).
124
- */
125
- export class SseFrameParser {
126
- #buffer = '';
127
- #event = '';
128
- #data = '';
129
- push(chunk) {
130
- this.#buffer += chunk;
131
- // Normalise CRLF/CR so the splitter only handles \n, then hold the trailing partial line for the
132
- // next chunk (it may complete later).
133
- const normalised = this.#buffer.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
134
- const lines = normalised.split('\n');
135
- this.#buffer = lines.pop() ?? '';
136
- const frames = [];
137
- for (const line of lines) {
138
- if (line === '') {
139
- if (this.#data !== '') {
140
- frames.push({ event: this.#event !== '' ? this.#event : 'message', data: this.#data });
141
- }
142
- this.#event = '';
143
- this.#data = '';
144
- }
145
- else if (line.startsWith('event:')) {
146
- this.#event = line.slice(6).trim();
147
- }
148
- else if (line.startsWith('data:')) {
149
- const val = line.slice(5).trim();
150
- this.#data = this.#data !== '' ? `${this.#data}\n${val}` : val;
151
- }
152
- }
153
- return frames;
154
- }
155
- }
156
- /**
157
- * Returns true if something is already listening on the reticle port.
158
- * Uses a plain TCP probe so we don't create a side-effectful SSE session
159
- * inside the daemon just to check reachability.
160
- */
161
- export function probeDaemon(port) {
162
- return new Promise((resolve) => {
163
- const socket = new net.Socket();
164
- socket.setTimeout(500);
165
- socket.on('connect', () => {
166
- socket.destroy();
167
- resolve(true);
168
- });
169
- socket.on('error', () => resolve(false));
170
- socket.on('timeout', () => {
171
- socket.destroy();
172
- resolve(false);
173
- });
174
- socket.connect(port, LOOPBACK_HOST);
175
- });
176
- }
177
- /** Poll until the daemon's HTTP port accepts connections or the deadline is reached. */
178
- export async function waitForDaemon(port) {
179
- const deadline = Date.now() + DAEMON_READY_TIMEOUT_MS;
180
- while (Date.now() < deadline) {
181
- const reachable = await probeDaemon(port);
182
- if (reachable)
183
- return;
184
- await delay(DAEMON_POLL_INTERVAL_MS);
185
- }
186
- throw new Error(`reticle daemon did not become ready on port ${port} within ${DAEMON_READY_TIMEOUT_MS}ms`);
187
- }
188
- function postToSession(url, body) {
189
- return new Promise((resolve) => {
190
- const parsed = new URL(url);
191
- const bodyBuf = Buffer.from(body, 'utf8');
192
- const options = {
193
- host: parsed.hostname,
194
- port: parsed.port !== '' ? parseInt(parsed.port, 10) : 80,
195
- path: `${parsed.pathname}${parsed.search}`,
196
- method: 'POST',
197
- headers: {
198
- 'Content-Type': 'application/json',
199
- 'Content-Length': bodyBuf.byteLength,
200
- },
201
- };
202
- const req = http.request(options, (res) => {
203
- const status = res.statusCode ?? 0;
204
- if (status < 200 || status >= 300) {
205
- // A non-2xx from the daemon MCP endpoint used to be swallowed, hanging the JSON-RPC call
206
- // client-side with no diagnostic. Surface it (the forward is still fire-and-forget).
207
- log('reticle_mcp_proxy_post_non2xx', { status, path: options.path });
208
- }
209
- res.resume(); // drain so the socket is reused
210
- resolve();
211
- });
212
- req.on('error', (err) => {
213
- log('reticle_mcp_proxy_post_error', { error: err.message });
214
- resolve();
215
- });
216
- req.write(bodyBuf);
217
- req.end();
218
- });
219
- }
220
- export function buildSessionUrl(rawData, port) {
221
- return rawData.startsWith('/') ? `http://${LOOPBACK_HOST}:${port}${rawData}` : rawData;
222
- }
223
- /**
224
- * Bridge stdio ↔ SSE: connects to the running daemon's MCP endpoint and forwards
225
- * Claude Code's stdin/stdout JSON-RPC through it. Never resolves — runs until stdin closes.
226
- *
227
- * A dropped SSE stream used to exit the process, which is what made the agent's `reticle_*` tools
228
- * vanish mid-session with no message and no way for the agent to get them back — only a human running
229
- * `/mcp` could. The daemon demonstrably stays up across these drops, so the stream ending is a
230
- * transport event, not a shutdown: reconnect to it and replay the handshake instead of dying.
231
- */
232
- export function startMcpProxy(port) {
233
- return new Promise((_resolve, reject) => {
234
- let postUrl = null;
235
- const stdinQueue = [];
236
- const replay = new HandshakeReplay();
237
- let stopped = false;
238
- let attempts = 0;
239
- function onSseEvent(event, data, p) {
240
- if (event === 'endpoint') {
241
- const url = buildSessionUrl(data, p);
242
- postUrl = url;
243
- // The new session's McpServer has never seen the client's initialize — replay it first, then
244
- // flush whatever the client sent while we were reconnecting.
245
- for (const line of replay.replayLines())
246
- void postToSession(url, line);
247
- for (const queued of stdinQueue.splice(0))
248
- void postToSession(url, queued);
249
- return;
250
- }
251
- if (event === 'message' && !replay.shouldSuppressInbound(data)) {
252
- process.stdout.write(`${data}\n`);
253
- }
254
- }
255
- function scheduleReconnect(reason, detail) {
256
- if (stopped)
257
- return;
258
- postUrl = null;
259
- attempts++;
260
- if (attempts > MAX_RECONNECT_ATTEMPTS) {
261
- proxyLog('reticle_mcp_proxy_gave_up', {
262
- port,
263
- reason,
264
- attempts,
265
- ...(detail !== undefined ? { detail } : {}),
266
- });
267
- process.exit(1);
268
- }
269
- const wait = reconnectDelayMs(attempts);
270
- proxyLog('reticle_mcp_proxy_reconnecting', {
271
- port,
272
- reason,
273
- attempt: attempts,
274
- retryInMs: wait,
275
- ...(detail !== undefined ? { detail } : {}),
276
- });
277
- setTimeout(() => connect(false), wait).unref();
278
- }
279
- function connect(first) {
280
- const req = http.get({ host: LOOPBACK_HOST, port, path: MCP_SSE_PATH }, (res) => {
281
- attempts = 0; // a stream we actually established resets the budget
282
- if (!first)
283
- proxyLog('reticle_mcp_proxy_reconnected', { port });
284
- res.setEncoding('utf8');
285
- // `end` and `error` can both fire on one response; only the first should drive a reconnect.
286
- let settled = false;
287
- const drop = (reason, detail) => {
288
- if (settled)
289
- return;
290
- settled = true;
291
- scheduleReconnect(reason, detail);
292
- };
293
- const sse = new SseFrameParser();
294
- res.on('data', (chunk) => {
295
- for (const frame of sse.push(chunk))
296
- onSseEvent(frame.event, frame.data, port);
297
- });
298
- res.on('end', () => drop('sse_ended'));
299
- res.on('error', (err) => drop('sse_error', err.message));
300
- // A socket dying under us (daemon killed, network stack reset) emits NEITHER `end` nor
301
- // `error` — only `aborted`/`close`. Listening for just the first two is why the proxy sat
302
- // there afterwards holding a dead stream. `settled` keeps the clean case single-fire.
303
- res.on('aborted', () => drop('sse_aborted'));
304
- res.on('close', () => drop('sse_closed'));
305
- });
306
- // The very first connect failing means there is no daemon to talk to — that is a startup
307
- // failure the caller handles. Later ones are just the daemon bouncing: keep retrying.
308
- req.on('error', (err) => (first ? reject(err) : scheduleReconnect('connect_error', err.message)));
309
- }
310
- connect(true);
311
- // ── stdin reader ─────────────────────────────────────────────────────────
312
- process.stdin.setEncoding('utf8');
313
- let stdinBuffer = '';
314
- process.stdin.on('data', (chunk) => {
315
- stdinBuffer += chunk;
316
- const lines = stdinBuffer.split('\n');
317
- stdinBuffer = lines.pop() ?? '';
318
- for (const line of lines) {
319
- const trimmed = line.trim();
320
- if (trimmed === '')
321
- continue;
322
- replay.observeOutbound(trimmed);
323
- if (postUrl === null) {
324
- stdinQueue.push(trimmed);
325
- }
326
- else {
327
- void postToSession(postUrl, trimmed);
328
- }
329
- }
330
- });
331
- // The client going away is the one clean shutdown — stop reconnecting and exit.
332
- process.stdin.on('end', () => {
333
- stopped = true;
334
- process.exit(0);
335
- });
336
- });
337
- }
@@ -1,37 +0,0 @@
1
- import type { ToolDef } from './tools.js';
2
- /**
3
- * Which MCP tool surface to expose. The advertised tool DEFINITIONS are re-sent to the model on
4
- * every turn, so a smaller surface is a per-turn token saving that compounds across a loop. Fewer
5
- * tools also makes the model wander less (fewer turns, higher accuracy). See bench/agent-loop-and-replay.md.
6
- *
7
- * MEASURED surface sizes (assert them with profile-reachability.test.ts rather than trusting prose —
8
- * every count previously written here was wrong, and the token figures below derive from those counts):
9
- * core 15 · standard 32 · hybrid 15 · full 43 · dynamic 2
10
- * core and hybrid are both 14 because a trimmed profile now also advertises the two meta-tools, which
11
- * is what keeps an un-advertised tool reachable through reticle_run.
12
- *
13
- * core — the verify loop a coding agent actually needs: navigate→look→act→observe→assert,
14
- * WITH direct network + console + state observability (the highest-signal checks).
15
- * The recommended profile for agent-driven verification.
16
- * standard — core + common extras (inspect, sequences, animations, flows, session lifecycle,
17
- * scroll, baselines, …). For agents that need more than the bare loop.
18
- * hybrid — THE DEFAULT: core verify+oracle tools advertised directly + 2 meta-tools for on-demand
19
- * reach to everything else. Core accuracy/detection at ~64% less schema tax than full.
20
- * full — all tools advertised directly. Opt in via RETICLE_TOOL_PROFILE=full for hard-call scripts.
21
- */
22
- export declare const TOOL_PROFILE: {
23
- /** dynamic — advertise only 2 meta-tools (reticle_tools + reticle_run); load real tools on demand.
24
- * Fixed ~hundreds of tokens/turn regardless of how many tools exist. See dynamic-tools.ts. */
25
- readonly DYNAMIC: "dynamic";
26
- /** hybrid — the core verify tools advertised directly (so the agent acts reliably) PLUS the 2
27
- * meta-tools for on-demand reach to every other tool. Core accuracy + full reach at ~core cost. */
28
- readonly HYBRID: "hybrid";
29
- readonly CORE: "core";
30
- readonly STANDARD: "standard";
31
- readonly FULL: "full";
32
- };
33
- export type ToolProfile = (typeof TOOL_PROFILE)[keyof typeof TOOL_PROFILE];
34
- export declare const TOOL_PROFILE_ENV = "RETICLE_TOOL_PROFILE";
35
- export declare const CORE_TOOL_NAMES: ReadonlySet<string>;
36
- export declare function resolveToolProfile(explicit?: string): ToolProfile;
37
- export declare function filterTools(tools: ToolDef[], profile: ToolProfile): ToolDef[];
@@ -1,139 +0,0 @@
1
- import { ReticleTool } from './tool-names.js';
2
- /**
3
- * Which MCP tool surface to expose. The advertised tool DEFINITIONS are re-sent to the model on
4
- * every turn, so a smaller surface is a per-turn token saving that compounds across a loop. Fewer
5
- * tools also makes the model wander less (fewer turns, higher accuracy). See bench/agent-loop-and-replay.md.
6
- *
7
- * MEASURED surface sizes (assert them with profile-reachability.test.ts rather than trusting prose —
8
- * every count previously written here was wrong, and the token figures below derive from those counts):
9
- * core 15 · standard 32 · hybrid 15 · full 43 · dynamic 2
10
- * core and hybrid are both 14 because a trimmed profile now also advertises the two meta-tools, which
11
- * is what keeps an un-advertised tool reachable through reticle_run.
12
- *
13
- * core — the verify loop a coding agent actually needs: navigate→look→act→observe→assert,
14
- * WITH direct network + console + state observability (the highest-signal checks).
15
- * The recommended profile for agent-driven verification.
16
- * standard — core + common extras (inspect, sequences, animations, flows, session lifecycle,
17
- * scroll, baselines, …). For agents that need more than the bare loop.
18
- * hybrid — THE DEFAULT: core verify+oracle tools advertised directly + 2 meta-tools for on-demand
19
- * reach to everything else. Core accuracy/detection at ~64% less schema tax than full.
20
- * full — all tools advertised directly. Opt in via RETICLE_TOOL_PROFILE=full for hard-call scripts.
21
- */
22
- export const TOOL_PROFILE = {
23
- /** dynamic — advertise only 2 meta-tools (reticle_tools + reticle_run); load real tools on demand.
24
- * Fixed ~hundreds of tokens/turn regardless of how many tools exist. See dynamic-tools.ts. */
25
- DYNAMIC: 'dynamic',
26
- /** hybrid — the core verify tools advertised directly (so the agent acts reliably) PLUS the 2
27
- * meta-tools for on-demand reach to every other tool. Core accuracy + full reach at ~core cost. */
28
- HYBRID: 'hybrid',
29
- CORE: 'core',
30
- STANDARD: 'standard',
31
- FULL: 'full',
32
- };
33
- export const TOOL_PROFILE_ENV = 'RETICLE_TOOL_PROFILE';
34
- // The set an agent needs to verify a change end-to-end. Tool DEFINITIONS are re-sent every turn, so a
35
- // smaller surface compounds.
36
- //
37
- // MEASURED per-turn `tools/list` cost — the bytes an MCP client re-sends EVERY turn — taken off the
38
- // real wire (spawn `mcp`, read tools/list, measure the serialized result), not estimated:
39
- //
40
- // dynamic 2 tools 1,531 B ~383 tok/turn
41
- // core 15 tools 14,104 B ~3,526 tok/turn
42
- // hybrid 15 tools 14,104 B ~3,526 tok/turn
43
- // standard 32 tools 26,769 B ~6,692 tok/turn
44
- // full 43 tools 105,061 B ~26,265 tok/turn
45
- //
46
- // These REPLACE the previous figures (core 6,479 / standard 13,951 / full 20,441), which the comment
47
- // itself flagged as stale. Two of the three moved in opposite directions, which is why re-measuring
48
- // mattered: the lean profiles got much CHEAPER because they now drop the advertised outputSchema,
49
- // while `full` got much more EXPENSIVE because it still carries it — the gap between lean and full is
50
- // 7.4x, not the ~3x the old numbers implied.
51
- //
52
- // Where the remaining cost sits, on the hybrid default: inputSchema is 76% of the payload (parameter
53
- // descriptions are half of that), tool descriptions are 12%, and outputSchema is already ~0. So the
54
- // next real saving is in parameter prose, not in dropping more tools.
55
- //
56
- // There is a floor, though: an 8-tool cut (dropping act/navigate/wait_for/sessions) was MEASURED to
57
- // regress real-agent accuracy 5/5 -> 3/5, because the model loses scaffolding and wanders on harder
58
- // flows. Direct network/console stay (far more discoverable than observe-with-filters -> fewer turns,
59
- // better verdicts).
60
- //
61
- // Evidence status: the 5/5 figure came from a single gpt-4o run and is STALE as a justification.
62
- // Current-model evidence is indirect but real — the cost-delta run (bench/fix-loop/COST-DELTA.md)
63
- // drove this hybrid default on a current model and fixed 4/4 cells with ~25% FEWER tool calls than
64
- // the baseline. A formal core-vs-hybrid A/B on a current model is still UNRUN; do not quote the 5/5
65
- // number as if it were current. See bench/agent-loop-and-replay.md.
66
- export const CORE_TOOL_NAMES = new Set([
67
- ReticleTool.SESSIONS,
68
- ReticleTool.NAVIGATE,
69
- ReticleTool.SNAPSHOT,
70
- ReticleTool.QUERY,
71
- ReticleTool.ACT,
72
- ReticleTool.ACT_AND_WAIT,
73
- ReticleTool.OBSERVE,
74
- ReticleTool.NETWORK,
75
- ReticleTool.CONSOLE,
76
- ReticleTool.WAIT_FOR,
77
- ReticleTool.ASSERT,
78
- ReticleTool.STATE,
79
- // INSPECT is what turns a finding into an EDIT: it maps a DOM node to `src/App.tsx:104`. Finding a
80
- // bug is half the job; knowing which file to open is the half that makes the agent useful, and it
81
- // is the one capability here with no substitute in any other verification tool. It sat in
82
- // `standard`, so under the default profile an agent had to already know it existed and reach it
83
- // through reticle_run — which, observed over a full 43-tool drive, means it never gets called.
84
- // The measured floor that justifies a lean core was about CUTTING to 8 (accuracy 5/5 → 3/5), not
85
- // about holding at 12; one tool of schema tax to close the find→fix loop is the right trade.
86
- ReticleTool.INSPECT,
87
- // FEEDBACK is in every profile for the same reason INSPECT is: a tool an agent has to already know
88
- // about, and reach through reticle_run, is a tool that never gets called. That is fatal here in a way
89
- // it is not elsewhere — an unadvertised feedback channel collects nothing, which is indistinguishable
90
- // from not having built one. It is also the cheapest tool on the surface to carry (three params) and
91
- // the only one whose whole purpose is telling us which of the other fifteen are failing.
92
- ReticleTool.FEEDBACK,
93
- ]);
94
- const STANDARD_TOOL_NAMES = new Set([
95
- ...CORE_TOOL_NAMES,
96
- ReticleTool.ACT_SEQUENCE,
97
- ReticleTool.NETWORK,
98
- ReticleTool.CONSOLE,
99
- ReticleTool.ANIMATIONS,
100
- ReticleTool.FLOW_SAVE,
101
- ReticleTool.FLOW_REPLAY,
102
- ReticleTool.FLOW_VERIFY,
103
- ReticleTool.FLOW_HEAL,
104
- ReticleTool.SESSION, // merged lifecycle/human-channel family
105
- ReticleTool.FLOW, // merged flow list/load/delete
106
- ReticleTool.RECORD, // merged record start/stop
107
- ReticleTool.BASELINE, // merged baseline save/list/diff
108
- ReticleTool.SCROLL_TO,
109
- ReticleTool.CRAWL,
110
- ReticleTool.REPLAY,
111
- ReticleTool.EXPLORE,
112
- ReticleTool.CONTRACT_SAVE,
113
- ReticleTool.NETWORK_MOCK,
114
- ReticleTool.VIEWPORT,
115
- ]);
116
- export function resolveToolProfile(explicit) {
117
- const raw = explicit ?? process.env[TOOL_PROFILE_ENV];
118
- if (raw === TOOL_PROFILE.DYNAMIC)
119
- return TOOL_PROFILE.DYNAMIC;
120
- if (raw === TOOL_PROFILE.HYBRID)
121
- return TOOL_PROFILE.HYBRID;
122
- if (raw === TOOL_PROFILE.CORE)
123
- return TOOL_PROFILE.CORE;
124
- if (raw === TOOL_PROFILE.STANDARD)
125
- return TOOL_PROFILE.STANDARD;
126
- if (raw === TOOL_PROFILE.FULL)
127
- return TOOL_PROFILE.FULL;
128
- // Default: hybrid — the core verify+oracle tools advertised directly (no detection loss, verified
129
- // 10/10 on the regression bench) PLUS the 2 meta-tools for on-demand reach to every other tool. ~64%
130
- // less per-turn schema than `full` at the same accuracy. Explicit `full` still opts into all tools.
131
- return TOOL_PROFILE.HYBRID;
132
- }
133
- export function filterTools(tools, profile) {
134
- if (profile === TOOL_PROFILE.CORE)
135
- return tools.filter((t) => CORE_TOOL_NAMES.has(t.name));
136
- if (profile === TOOL_PROFILE.STANDARD)
137
- return tools.filter((t) => STANDARD_TOOL_NAMES.has(t.name));
138
- return tools;
139
- }
File without changes
File without changes
File without changes