@reticlehq/server 2.2.1 → 2.3.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 (778) hide show
  1. package/README.md +1 -1
  2. package/dist/bridge-security.d.ts +0 -1
  3. package/dist/bridge-security.js +0 -1
  4. package/dist/bridge.d.ts +0 -1
  5. package/dist/bridge.js +60 -10
  6. package/dist/bridge.test-harness.d.ts +0 -1
  7. package/dist/bridge.test-harness.js +0 -1
  8. package/dist/capsule/capsule-store.d.ts +2 -3
  9. package/dist/capsule/capsule-store.js +0 -1
  10. package/dist/capsule/capsule.d.ts +0 -1
  11. package/dist/capsule/capsule.js +0 -1
  12. package/dist/capsule/causal-summary.d.ts +21 -1
  13. package/dist/capsule/causal-summary.js +20 -2
  14. package/dist/capsule/divergence.d.ts +0 -1
  15. package/dist/capsule/divergence.js +0 -1
  16. package/dist/capsule/minimize.d.ts +0 -1
  17. package/dist/capsule/minimize.js +0 -1
  18. package/dist/capsule/predicate-to-links.d.ts +0 -1
  19. package/dist/capsule/predicate-to-links.js +0 -1
  20. package/dist/cli-doctor.d.ts +6 -0
  21. package/dist/cli-doctor.js +60 -0
  22. package/dist/cli-flow-commands.d.ts +0 -1
  23. package/dist/cli-flow-commands.js +0 -1
  24. package/dist/cli-launch.d.ts +0 -1
  25. package/dist/cli-launch.js +7 -3
  26. package/dist/cli-parse.d.ts +34 -2
  27. package/dist/cli-parse.js +107 -1
  28. package/dist/cli-port.d.ts +0 -1
  29. package/dist/cli-port.js +0 -1
  30. package/dist/cli-verify.d.ts +0 -1
  31. package/dist/cli-verify.js +1 -2
  32. package/dist/cli.d.ts +0 -1
  33. package/dist/cli.js +79 -67
  34. package/dist/cloud/cloud-config.d.ts +0 -1
  35. package/dist/cloud/cloud-config.js +0 -1
  36. package/dist/cloud/cloud-sync.d.ts +4 -5
  37. package/dist/cloud/cloud-sync.js +0 -1
  38. package/dist/cloud-cli.d.ts +0 -1
  39. package/dist/cloud-cli.js +9 -2
  40. package/dist/crawl/crawl-tools.d.ts +0 -1
  41. package/dist/crawl/crawl-tools.js +1 -2
  42. package/dist/crawl/crawl.d.ts +17 -3
  43. package/dist/crawl/crawl.js +43 -4
  44. package/dist/daemon-resilience.d.ts +6 -1
  45. package/dist/daemon-resilience.js +63 -1
  46. package/dist/daemon.d.ts +23 -3
  47. package/dist/daemon.js +36 -24
  48. package/dist/domain/domain-model.d.ts +0 -1
  49. package/dist/domain/domain-model.js +1 -2
  50. package/dist/domain/domain-tools.d.ts +0 -7
  51. package/dist/domain/domain-tools.js +21 -4
  52. package/dist/domain/flow-risk.d.ts +0 -1
  53. package/dist/domain/flow-risk.js +0 -1
  54. package/dist/ee/audit-log.d.ts +0 -1
  55. package/dist/ee/audit-log.js +0 -1
  56. package/dist/events/body-failures.d.ts +4 -0
  57. package/dist/events/body-failures.js +113 -0
  58. package/dist/events/contradictions.d.ts +53 -0
  59. package/dist/events/contradictions.js +282 -0
  60. package/dist/events/echo-mismatch.d.ts +4 -0
  61. package/dist/events/echo-mismatch.js +138 -0
  62. package/dist/events/event-filters.d.ts +17 -3
  63. package/dist/events/event-filters.js +13 -3
  64. package/dist/events/json-salvage.d.ts +32 -0
  65. package/dist/events/json-salvage.js +96 -0
  66. package/dist/events/predicate-eval.d.ts +2 -1
  67. package/dist/events/predicate-eval.js +56 -9
  68. package/dist/events/predicate.d.ts +0 -1
  69. package/dist/events/predicate.js +56 -2
  70. package/dist/events/reaction.d.ts +0 -1
  71. package/dist/events/reaction.js +0 -1
  72. package/dist/events/reconcile.d.ts +39 -0
  73. package/dist/events/reconcile.js +211 -0
  74. package/dist/events/ring-buffer.d.ts +0 -1
  75. package/dist/events/ring-buffer.js +0 -1
  76. package/dist/events/stale-response.d.ts +4 -0
  77. package/dist/events/stale-response.js +139 -0
  78. package/dist/events/unit-mismatch.d.ts +16 -0
  79. package/dist/events/unit-mismatch.js +167 -0
  80. package/dist/flows/affected-tools.d.ts +18 -0
  81. package/dist/flows/affected-tools.js +52 -0
  82. package/dist/flows/affected.d.ts +0 -1
  83. package/dist/flows/affected.js +0 -1
  84. package/dist/flows/annotate-tools.d.ts +0 -1
  85. package/dist/flows/annotate-tools.js +21 -3
  86. package/dist/flows/annotate.d.ts +0 -1
  87. package/dist/flows/annotate.js +0 -1
  88. package/dist/flows/annotation-store.d.ts +0 -1
  89. package/dist/flows/annotation-store.js +0 -1
  90. package/dist/flows/assertion-integrity.d.ts +0 -1
  91. package/dist/flows/assertion-integrity.js +0 -1
  92. package/dist/flows/assertion-tiers-store.d.ts +0 -1
  93. package/dist/flows/assertion-tiers-store.js +0 -1
  94. package/dist/flows/buddy-status.d.ts +0 -1
  95. package/dist/flows/buddy-status.js +0 -1
  96. package/dist/flows/coverage.d.ts +0 -1
  97. package/dist/flows/coverage.js +0 -1
  98. package/dist/flows/decision.d.ts +0 -1
  99. package/dist/flows/decision.js +0 -1
  100. package/dist/flows/flake-store.d.ts +0 -1
  101. package/dist/flows/flake-store.js +0 -1
  102. package/dist/flows/flake.d.ts +0 -1
  103. package/dist/flows/flake.js +0 -1
  104. package/dist/flows/flow-classify.d.ts +0 -1
  105. package/dist/flows/flow-classify.js +0 -1
  106. package/dist/flows/flow-replay-run.d.ts +0 -1
  107. package/dist/flows/flow-replay-run.js +2 -3
  108. package/dist/flows/flow-replay.d.ts +20 -4
  109. package/dist/flows/flow-replay.js +9 -43
  110. package/dist/flows/flow-report.d.ts +0 -1
  111. package/dist/flows/flow-report.js +0 -1
  112. package/dist/flows/flow-scope.d.ts +0 -1
  113. package/dist/flows/flow-scope.js +0 -1
  114. package/dist/flows/flow-sources.d.ts +0 -1
  115. package/dist/flows/flow-sources.js +0 -1
  116. package/dist/flows/flow-step-runners.d.ts +23 -0
  117. package/dist/flows/flow-step-runners.js +102 -0
  118. package/dist/flows/flow-success.d.ts +0 -1
  119. package/dist/flows/flow-success.js +0 -1
  120. package/dist/flows/flow-tools.d.ts +0 -1
  121. package/dist/flows/flow-tools.js +30 -8
  122. package/dist/flows/flows.d.ts +6 -2
  123. package/dist/flows/flows.js +15 -2
  124. package/dist/flows/gate.d.ts +0 -1
  125. package/dist/flows/gate.js +0 -1
  126. package/dist/flows/git-changed.d.ts +0 -1
  127. package/dist/flows/git-changed.js +0 -1
  128. package/dist/flows/heal-run.d.ts +0 -1
  129. package/dist/flows/heal-run.js +0 -1
  130. package/dist/flows/heal.d.ts +0 -1
  131. package/dist/flows/heal.js +0 -1
  132. package/dist/flows/parallel-suite.d.ts +0 -1
  133. package/dist/flows/parallel-suite.js +0 -1
  134. package/dist/flows/recordings.d.ts +0 -1
  135. package/dist/flows/recordings.js +0 -1
  136. package/dist/flows/replay.d.ts +0 -1
  137. package/dist/flows/replay.js +71 -4
  138. package/dist/flows/server-verify.d.ts +0 -1
  139. package/dist/flows/server-verify.js +0 -1
  140. package/dist/flows/verify-change-tools.d.ts +2 -0
  141. package/dist/flows/verify-change-tools.js +187 -0
  142. package/dist/flows/watch-batcher.d.ts +0 -1
  143. package/dist/flows/watch-batcher.js +0 -1
  144. package/dist/honesty/accepted-write.d.ts +14 -0
  145. package/dist/honesty/accepted-write.js +17 -0
  146. package/dist/honesty/blind-spots.d.ts +18 -1
  147. package/dist/honesty/blind-spots.js +47 -5
  148. package/dist/honesty/honesty.d.ts +0 -1
  149. package/dist/honesty/honesty.js +0 -1
  150. package/dist/honesty/uncaptured-bodies.d.ts +19 -0
  151. package/dist/honesty/uncaptured-bodies.js +30 -0
  152. package/dist/honesty/unread-outcome.d.ts +2 -0
  153. package/dist/honesty/unread-outcome.js +50 -0
  154. package/dist/honesty/verified.d.ts +40 -0
  155. package/dist/honesty/verified.js +86 -0
  156. package/dist/http-server.d.ts +0 -1
  157. package/dist/http-server.js +5 -1
  158. package/dist/hunt/hunt-report.d.ts +50 -0
  159. package/dist/hunt/hunt-report.js +84 -0
  160. package/dist/idle-shutdown.d.ts +0 -1
  161. package/dist/idle-shutdown.js +0 -1
  162. package/dist/index.d.ts +0 -1
  163. package/dist/index.js +0 -1
  164. package/dist/init/agent-rules.d.ts +0 -1
  165. package/dist/init/agent-rules.js +4 -2
  166. package/dist/init/cursor.d.ts +0 -1
  167. package/dist/init/cursor.js +0 -1
  168. package/dist/init/desktop-doctor.d.ts +40 -0
  169. package/dist/init/desktop-doctor.js +198 -0
  170. package/dist/init/detect.d.ts +0 -1
  171. package/dist/init/detect.js +0 -1
  172. package/dist/init/mcp.d.ts +0 -1
  173. package/dist/init/mcp.js +0 -1
  174. package/dist/init/node-io.d.ts +0 -1
  175. package/dist/init/node-io.js +0 -1
  176. package/dist/init/plan.d.ts +4 -1
  177. package/dist/init/plan.js +23 -5
  178. package/dist/init/project-id.d.ts +0 -1
  179. package/dist/init/project-id.js +0 -1
  180. package/dist/init/run.d.ts +0 -1
  181. package/dist/init/run.js +31 -3
  182. package/dist/init/snippets.d.ts +5 -1
  183. package/dist/init/snippets.js +5 -1
  184. package/dist/init/vite-config.d.ts +0 -1
  185. package/dist/init/vite-config.js +0 -1
  186. package/dist/input/network-detail.d.ts +0 -1
  187. package/dist/input/network-detail.js +0 -1
  188. package/dist/input/network-mock-tools.d.ts +0 -1
  189. package/dist/input/network-mock-tools.js +3 -4
  190. package/dist/input/network-mock.d.ts +0 -1
  191. package/dist/input/network-mock.js +0 -1
  192. package/dist/input/real-input.d.ts +14 -1
  193. package/dist/input/real-input.js +45 -3
  194. package/dist/input/scroll-find.d.ts +0 -1
  195. package/dist/input/scroll-find.js +0 -1
  196. package/dist/input/scroll-tools.d.ts +0 -1
  197. package/dist/input/scroll-tools.js +0 -1
  198. package/dist/input/viewport-tools.d.ts +0 -1
  199. package/dist/input/viewport-tools.js +3 -4
  200. package/dist/journal/ambient-store.d.ts +0 -1
  201. package/dist/journal/ambient-store.js +0 -1
  202. package/dist/journal/ambient.d.ts +0 -1
  203. package/dist/journal/ambient.js +0 -1
  204. package/dist/journal/attach-journal.d.ts +0 -1
  205. package/dist/journal/attach-journal.js +0 -1
  206. package/dist/journal/deviation-report.d.ts +0 -1
  207. package/dist/journal/deviation-report.js +0 -1
  208. package/dist/journal/deviation-service.d.ts +0 -1
  209. package/dist/journal/deviation-service.js +0 -1
  210. package/dist/journal/envelope-store.d.ts +0 -1
  211. package/dist/journal/envelope-store.js +0 -1
  212. package/dist/journal/envelope.d.ts +8 -9
  213. package/dist/journal/envelope.js +0 -1
  214. package/dist/journal/journal-query.d.ts +0 -1
  215. package/dist/journal/journal-query.js +0 -1
  216. package/dist/journal/journal-recorder.d.ts +0 -1
  217. package/dist/journal/journal-recorder.js +0 -1
  218. package/dist/journal/retention.d.ts +0 -1
  219. package/dist/journal/retention.js +0 -1
  220. package/dist/journal/rollups.d.ts +0 -1
  221. package/dist/journal/rollups.js +0 -1
  222. package/dist/journal/session-end.d.ts +0 -1
  223. package/dist/journal/session-end.js +0 -1
  224. package/dist/journal/session-journal.d.ts +0 -1
  225. package/dist/journal/session-journal.js +0 -1
  226. package/dist/license/license.d.ts +0 -1
  227. package/dist/license/license.js +0 -1
  228. package/dist/log.d.ts +0 -1
  229. package/dist/log.js +0 -1
  230. package/dist/mcp-proxy.d.ts +0 -1
  231. package/dist/mcp-proxy.js +0 -1
  232. package/dist/mcp.d.ts +15 -1
  233. package/dist/mcp.js +145 -17
  234. package/dist/oracles/flow-instrument-gaps.d.ts +0 -1
  235. package/dist/oracles/flow-instrument-gaps.js +0 -1
  236. package/dist/oracles/propose-consequences.d.ts +0 -1
  237. package/dist/oracles/propose-consequences.js +0 -1
  238. package/dist/oracles/self-instrument.d.ts +0 -1
  239. package/dist/oracles/self-instrument.js +0 -1
  240. package/dist/pairing-token.d.ts +0 -1
  241. package/dist/pairing-token.js +0 -1
  242. package/dist/phenomena/phenomena.d.ts +0 -1
  243. package/dist/phenomena/phenomena.js +0 -1
  244. package/dist/pool/browser-pool.d.ts +0 -1
  245. package/dist/pool/browser-pool.js +0 -1
  246. package/dist/pool/lease-reaper.d.ts +0 -1
  247. package/dist/pool/lease-reaper.js +0 -1
  248. package/dist/pool/playwright-launcher.d.ts +0 -1
  249. package/dist/pool/playwright-launcher.js +10 -2
  250. package/dist/project/baselines.d.ts +0 -1
  251. package/dist/project/baselines.js +0 -1
  252. package/dist/project/file-lock.d.ts +2 -1
  253. package/dist/project/file-lock.js +12 -2
  254. package/dist/project/fs-port.d.ts +0 -1
  255. package/dist/project/fs-port.js +0 -1
  256. package/dist/project/project-store.d.ts +0 -1
  257. package/dist/project/project-store.js +0 -1
  258. package/dist/project/project-tools.d.ts +0 -1
  259. package/dist/project/project-tools.js +29 -4
  260. package/dist/project/reticle-dir.d.ts +0 -1
  261. package/dist/project/reticle-dir.js +0 -1
  262. package/dist/runs/build-verification-run.d.ts +0 -1
  263. package/dist/runs/build-verification-run.js +0 -1
  264. package/dist/runs/profile-redact.d.ts +0 -1
  265. package/dist/runs/profile-redact.js +0 -1
  266. package/dist/runs/render-report.d.ts +0 -1
  267. package/dist/runs/render-report.js +0 -1
  268. package/dist/runs/repair-prompt.d.ts +0 -1
  269. package/dist/runs/repair-prompt.js +0 -1
  270. package/dist/runs/replay-mapping.d.ts +0 -1
  271. package/dist/runs/replay-mapping.js +0 -1
  272. package/dist/runs/reticle-runner.d.ts +0 -1
  273. package/dist/runs/reticle-runner.js +4 -2
  274. package/dist/runs/risk-classify.d.ts +0 -1
  275. package/dist/runs/risk-classify.js +0 -1
  276. package/dist/runs/run-diff.d.ts +0 -1
  277. package/dist/runs/run-diff.js +0 -1
  278. package/dist/runs/run-store.d.ts +0 -1
  279. package/dist/runs/run-store.js +0 -1
  280. package/dist/runs/run-tools.d.ts +0 -1
  281. package/dist/runs/run-tools.js +0 -1
  282. package/dist/runs/runner-port.d.ts +0 -1
  283. package/dist/runs/runner-port.js +0 -1
  284. package/dist/runs/verification-sync.d.ts +0 -1
  285. package/dist/runs/verification-sync.js +0 -1
  286. package/dist/runs/verify-http.d.ts +0 -1
  287. package/dist/runs/verify-http.js +0 -1
  288. package/dist/runs/verify-server.d.ts +0 -1
  289. package/dist/runs/verify-server.js +0 -1
  290. package/dist/server-version.d.ts +0 -1
  291. package/dist/server-version.js +0 -1
  292. package/dist/session/command-timeout.d.ts +35 -0
  293. package/dist/session/command-timeout.js +41 -0
  294. package/dist/session/control-envelope.d.ts +2 -3
  295. package/dist/session/control-envelope.js +2 -3
  296. package/dist/session/last-act.d.ts +31 -0
  297. package/dist/session/last-act.js +24 -0
  298. package/dist/session/live-control-tools.d.ts +0 -1
  299. package/dist/session/live-control-tools.js +3 -4
  300. package/dist/session/live-control.d.ts +0 -1
  301. package/dist/session/live-control.js +0 -1
  302. package/dist/session/observed-state.d.ts +12 -2
  303. package/dist/session/observed-state.js +29 -2
  304. package/dist/session/output-budget.d.ts +0 -1
  305. package/dist/session/output-budget.js +0 -1
  306. package/dist/session/pending-commands.d.ts +12 -0
  307. package/dist/session/pending-commands.js +36 -0
  308. package/dist/session/presenter-args.d.ts +0 -1
  309. package/dist/session/presenter-args.js +0 -1
  310. package/dist/session/review-store.d.ts +0 -1
  311. package/dist/session/review-store.js +0 -1
  312. package/dist/session/session-health.d.ts +26 -2
  313. package/dist/session/session-health.js +13 -1
  314. package/dist/session/session-info.d.ts +29 -0
  315. package/dist/session/session-info.js +1 -0
  316. package/dist/session/session-lease.d.ts +25 -0
  317. package/dist/session/session-lease.js +14 -0
  318. package/dist/session/session-manager.d.ts +7 -19
  319. package/dist/session/session-manager.js +29 -2
  320. package/dist/session/session-readiness.d.ts +0 -1
  321. package/dist/session/session-readiness.js +3 -4
  322. package/dist/session/session-reaper.d.ts +0 -1
  323. package/dist/session/session-reaper.js +0 -1
  324. package/dist/session/session-recommendation.d.ts +0 -1
  325. package/dist/session/session-recommendation.js +0 -1
  326. package/dist/session/session-tools.d.ts +0 -1
  327. package/dist/session/session-tools.js +2 -3
  328. package/dist/session/session.d.ts +27 -53
  329. package/dist/session/session.js +95 -66
  330. package/dist/session/state-select.d.ts +0 -1
  331. package/dist/session/state-select.js +0 -1
  332. package/dist/telemetry/argument-shape.d.ts +41 -0
  333. package/dist/telemetry/argument-shape.js +87 -0
  334. package/dist/telemetry/bug-found.d.ts +33 -0
  335. package/dist/telemetry/bug-found.js +95 -0
  336. package/dist/telemetry/cli-telemetry.d.ts +13 -0
  337. package/dist/telemetry/cli-telemetry.js +43 -0
  338. package/dist/telemetry/connect-failure.d.ts +16 -0
  339. package/dist/telemetry/connect-failure.js +44 -0
  340. package/dist/telemetry/daemon-telemetry.d.ts +19 -0
  341. package/dist/telemetry/daemon-telemetry.js +76 -0
  342. package/dist/telemetry/dev-repo.d.ts +10 -0
  343. package/dist/telemetry/dev-repo.js +80 -0
  344. package/dist/telemetry/error-fingerprint.d.ts +24 -0
  345. package/dist/telemetry/error-fingerprint.js +88 -0
  346. package/dist/telemetry/feedback-cli.d.ts +31 -0
  347. package/dist/telemetry/feedback-cli.js +102 -0
  348. package/dist/telemetry/feedback-context.d.ts +32 -0
  349. package/dist/telemetry/feedback-context.js +143 -0
  350. package/dist/telemetry/feedback.d.ts +66 -0
  351. package/dist/telemetry/feedback.js +175 -0
  352. package/dist/telemetry/git-facts.d.ts +21 -0
  353. package/dist/telemetry/git-facts.js +109 -0
  354. package/dist/telemetry/identify.d.ts +22 -0
  355. package/dist/telemetry/identify.js +73 -0
  356. package/dist/telemetry/init-telemetry.d.ts +26 -0
  357. package/dist/telemetry/init-telemetry.js +33 -0
  358. package/dist/telemetry/machine-snapshot.d.ts +6 -0
  359. package/dist/telemetry/machine-snapshot.js +39 -0
  360. package/dist/telemetry/mcp-connection.d.ts +5 -0
  361. package/dist/telemetry/mcp-connection.js +44 -0
  362. package/dist/telemetry/project-profile.d.ts +44 -0
  363. package/dist/telemetry/project-profile.js +205 -0
  364. package/dist/telemetry/run-telemetry.d.ts +21 -0
  365. package/dist/telemetry/run-telemetry.js +62 -0
  366. package/dist/telemetry/session-metrics.d.ts +103 -0
  367. package/dist/telemetry/session-metrics.js +329 -0
  368. package/dist/telemetry/telemetry.d.ts +35 -8
  369. package/dist/telemetry/telemetry.js +105 -12
  370. package/dist/token-auth.d.ts +0 -1
  371. package/dist/token-auth.js +0 -1
  372. package/dist/tools/act-capsule.d.ts +23 -0
  373. package/dist/tools/act-capsule.js +47 -0
  374. package/dist/tools/act-danger.d.ts +7 -0
  375. package/dist/tools/act-danger.js +44 -0
  376. package/dist/tools/act-helpers.d.ts +17 -0
  377. package/dist/tools/act-helpers.js +40 -0
  378. package/dist/tools/act-tools.d.ts +8 -1
  379. package/dist/tools/act-tools.js +96 -98
  380. package/dist/tools/act-view.d.ts +7 -1
  381. package/dist/tools/act-view.js +13 -1
  382. package/dist/tools/assert-grade.d.ts +22 -1
  383. package/dist/tools/assert-grade.js +46 -1
  384. package/dist/tools/assert-verdict.d.ts +21 -0
  385. package/dist/tools/assert-verdict.js +62 -0
  386. package/dist/tools/browser-tools.d.ts +0 -1
  387. package/dist/tools/browser-tools.js +2 -2
  388. package/dist/tools/contract-tools.d.ts +0 -1
  389. package/dist/tools/contract-tools.js +0 -1
  390. package/dist/tools/coverage-tools.d.ts +9 -0
  391. package/dist/tools/coverage-tools.js +92 -0
  392. package/dist/tools/dynamic-tools.d.ts +0 -1
  393. package/dist/tools/dynamic-tools.js +21 -2
  394. package/dist/tools/error-recovery.d.ts +18 -2
  395. package/dist/tools/error-recovery.js +42 -7
  396. package/dist/tools/feedback-tools.d.ts +24 -0
  397. package/dist/tools/feedback-tools.js +180 -0
  398. package/dist/tools/invoke-tool.d.ts +0 -1
  399. package/dist/tools/invoke-tool.js +115 -5
  400. package/dist/tools/lease-tools.d.ts +0 -1
  401. package/dist/tools/lease-tools.js +6 -5
  402. package/dist/tools/merge-tools.d.ts +0 -1
  403. package/dist/tools/merge-tools.js +0 -1
  404. package/dist/tools/observe-tools.d.ts +0 -1
  405. package/dist/tools/observe-tools.js +91 -39
  406. package/dist/tools/profiles.d.ts +1 -2
  407. package/dist/tools/profiles.js +43 -16
  408. package/dist/tools/query-paginate.d.ts +0 -1
  409. package/dist/tools/query-paginate.js +0 -1
  410. package/dist/tools/read-tools.d.ts +0 -1
  411. package/dist/tools/read-tools.js +10 -8
  412. package/dist/tools/reconcile-tools.d.ts +2 -0
  413. package/dist/tools/reconcile-tools.js +111 -0
  414. package/dist/tools/snapshot-delta.d.ts +0 -1
  415. package/dist/tools/snapshot-delta.js +0 -0
  416. package/dist/tools/tool-invoker.d.ts +0 -1
  417. package/dist/tools/tool-invoker.js +0 -1
  418. package/dist/tools/tool-kit.d.ts +16 -1
  419. package/dist/tools/tool-kit.js +8 -2
  420. package/dist/tools/tool-names.d.ts +6 -1
  421. package/dist/tools/tool-names.js +6 -1
  422. package/dist/tools/tools-helpers.d.ts +0 -1
  423. package/dist/tools/tools-helpers.js +0 -1
  424. package/dist/tools/tools.d.ts +0 -1
  425. package/dist/tools/tools.js +24 -4
  426. package/dist/update/update-checker.d.ts +0 -1
  427. package/dist/update/update-checker.js +0 -1
  428. package/dist/update/update-nudge.d.ts +20 -0
  429. package/dist/update/update-nudge.js +72 -0
  430. package/dist/update/updater.d.ts +14 -1
  431. package/dist/update/updater.js +33 -2
  432. package/dist/visual/visual-diff.d.ts +0 -1
  433. package/dist/visual/visual-diff.js +0 -1
  434. package/dist/visual/visual-store.d.ts +0 -1
  435. package/dist/visual/visual-store.js +0 -1
  436. package/dist/visual/visual-tools.d.ts +0 -1
  437. package/dist/visual/visual-tools.js +103 -16
  438. package/package.json +2 -2
  439. package/dist/bridge-security.d.ts.map +0 -1
  440. package/dist/bridge-security.js.map +0 -1
  441. package/dist/bridge.d.ts.map +0 -1
  442. package/dist/bridge.js.map +0 -1
  443. package/dist/bridge.test-harness.d.ts.map +0 -1
  444. package/dist/bridge.test-harness.js.map +0 -1
  445. package/dist/capsule/capsule-store.d.ts.map +0 -1
  446. package/dist/capsule/capsule-store.js.map +0 -1
  447. package/dist/capsule/capsule.d.ts.map +0 -1
  448. package/dist/capsule/capsule.js.map +0 -1
  449. package/dist/capsule/causal-summary.d.ts.map +0 -1
  450. package/dist/capsule/causal-summary.js.map +0 -1
  451. package/dist/capsule/divergence.d.ts.map +0 -1
  452. package/dist/capsule/divergence.js.map +0 -1
  453. package/dist/capsule/minimize.d.ts.map +0 -1
  454. package/dist/capsule/minimize.js.map +0 -1
  455. package/dist/capsule/predicate-to-links.d.ts.map +0 -1
  456. package/dist/capsule/predicate-to-links.js.map +0 -1
  457. package/dist/cli-flow-commands.d.ts.map +0 -1
  458. package/dist/cli-flow-commands.js.map +0 -1
  459. package/dist/cli-launch.d.ts.map +0 -1
  460. package/dist/cli-launch.js.map +0 -1
  461. package/dist/cli-parse.d.ts.map +0 -1
  462. package/dist/cli-parse.js.map +0 -1
  463. package/dist/cli-port.d.ts.map +0 -1
  464. package/dist/cli-port.js.map +0 -1
  465. package/dist/cli-verify.d.ts.map +0 -1
  466. package/dist/cli-verify.js.map +0 -1
  467. package/dist/cli.d.ts.map +0 -1
  468. package/dist/cli.js.map +0 -1
  469. package/dist/cloud/cloud-config.d.ts.map +0 -1
  470. package/dist/cloud/cloud-config.js.map +0 -1
  471. package/dist/cloud/cloud-sync.d.ts.map +0 -1
  472. package/dist/cloud/cloud-sync.js.map +0 -1
  473. package/dist/cloud-cli.d.ts.map +0 -1
  474. package/dist/cloud-cli.js.map +0 -1
  475. package/dist/crawl/crawl-tools.d.ts.map +0 -1
  476. package/dist/crawl/crawl-tools.js.map +0 -1
  477. package/dist/crawl/crawl.d.ts.map +0 -1
  478. package/dist/crawl/crawl.js.map +0 -1
  479. package/dist/daemon-resilience.d.ts.map +0 -1
  480. package/dist/daemon-resilience.js.map +0 -1
  481. package/dist/daemon.d.ts.map +0 -1
  482. package/dist/daemon.js.map +0 -1
  483. package/dist/domain/domain-model.d.ts.map +0 -1
  484. package/dist/domain/domain-model.js.map +0 -1
  485. package/dist/domain/domain-tools.d.ts.map +0 -1
  486. package/dist/domain/domain-tools.js.map +0 -1
  487. package/dist/domain/flow-risk.d.ts.map +0 -1
  488. package/dist/domain/flow-risk.js.map +0 -1
  489. package/dist/ee/audit-log.d.ts.map +0 -1
  490. package/dist/ee/audit-log.js.map +0 -1
  491. package/dist/events/event-filters.d.ts.map +0 -1
  492. package/dist/events/event-filters.js.map +0 -1
  493. package/dist/events/predicate-eval.d.ts.map +0 -1
  494. package/dist/events/predicate-eval.js.map +0 -1
  495. package/dist/events/predicate.d.ts.map +0 -1
  496. package/dist/events/predicate.js.map +0 -1
  497. package/dist/events/reaction.d.ts.map +0 -1
  498. package/dist/events/reaction.js.map +0 -1
  499. package/dist/events/ring-buffer.d.ts.map +0 -1
  500. package/dist/events/ring-buffer.js.map +0 -1
  501. package/dist/flows/affected.d.ts.map +0 -1
  502. package/dist/flows/affected.js.map +0 -1
  503. package/dist/flows/annotate-tools.d.ts.map +0 -1
  504. package/dist/flows/annotate-tools.js.map +0 -1
  505. package/dist/flows/annotate.d.ts.map +0 -1
  506. package/dist/flows/annotate.js.map +0 -1
  507. package/dist/flows/annotation-store.d.ts.map +0 -1
  508. package/dist/flows/annotation-store.js.map +0 -1
  509. package/dist/flows/assertion-integrity.d.ts.map +0 -1
  510. package/dist/flows/assertion-integrity.js.map +0 -1
  511. package/dist/flows/assertion-tiers-store.d.ts.map +0 -1
  512. package/dist/flows/assertion-tiers-store.js.map +0 -1
  513. package/dist/flows/buddy-status.d.ts.map +0 -1
  514. package/dist/flows/buddy-status.js.map +0 -1
  515. package/dist/flows/coverage.d.ts.map +0 -1
  516. package/dist/flows/coverage.js.map +0 -1
  517. package/dist/flows/decision.d.ts.map +0 -1
  518. package/dist/flows/decision.js.map +0 -1
  519. package/dist/flows/flake-store.d.ts.map +0 -1
  520. package/dist/flows/flake-store.js.map +0 -1
  521. package/dist/flows/flake.d.ts.map +0 -1
  522. package/dist/flows/flake.js.map +0 -1
  523. package/dist/flows/flow-classify.d.ts.map +0 -1
  524. package/dist/flows/flow-classify.js.map +0 -1
  525. package/dist/flows/flow-replay-run.d.ts.map +0 -1
  526. package/dist/flows/flow-replay-run.js.map +0 -1
  527. package/dist/flows/flow-replay.d.ts.map +0 -1
  528. package/dist/flows/flow-replay.js.map +0 -1
  529. package/dist/flows/flow-report.d.ts.map +0 -1
  530. package/dist/flows/flow-report.js.map +0 -1
  531. package/dist/flows/flow-scope.d.ts.map +0 -1
  532. package/dist/flows/flow-scope.js.map +0 -1
  533. package/dist/flows/flow-sources.d.ts.map +0 -1
  534. package/dist/flows/flow-sources.js.map +0 -1
  535. package/dist/flows/flow-success.d.ts.map +0 -1
  536. package/dist/flows/flow-success.js.map +0 -1
  537. package/dist/flows/flow-tools.d.ts.map +0 -1
  538. package/dist/flows/flow-tools.js.map +0 -1
  539. package/dist/flows/flows.d.ts.map +0 -1
  540. package/dist/flows/flows.js.map +0 -1
  541. package/dist/flows/gate.d.ts.map +0 -1
  542. package/dist/flows/gate.js.map +0 -1
  543. package/dist/flows/git-changed.d.ts.map +0 -1
  544. package/dist/flows/git-changed.js.map +0 -1
  545. package/dist/flows/heal-run.d.ts.map +0 -1
  546. package/dist/flows/heal-run.js.map +0 -1
  547. package/dist/flows/heal.d.ts.map +0 -1
  548. package/dist/flows/heal.js.map +0 -1
  549. package/dist/flows/parallel-suite.d.ts.map +0 -1
  550. package/dist/flows/parallel-suite.js.map +0 -1
  551. package/dist/flows/recordings.d.ts.map +0 -1
  552. package/dist/flows/recordings.js.map +0 -1
  553. package/dist/flows/replay.d.ts.map +0 -1
  554. package/dist/flows/replay.js.map +0 -1
  555. package/dist/flows/server-verify.d.ts.map +0 -1
  556. package/dist/flows/server-verify.js.map +0 -1
  557. package/dist/flows/watch-batcher.d.ts.map +0 -1
  558. package/dist/flows/watch-batcher.js.map +0 -1
  559. package/dist/honesty/blind-spots.d.ts.map +0 -1
  560. package/dist/honesty/blind-spots.js.map +0 -1
  561. package/dist/honesty/honesty.d.ts.map +0 -1
  562. package/dist/honesty/honesty.js.map +0 -1
  563. package/dist/http-server.d.ts.map +0 -1
  564. package/dist/http-server.js.map +0 -1
  565. package/dist/idle-shutdown.d.ts.map +0 -1
  566. package/dist/idle-shutdown.js.map +0 -1
  567. package/dist/index.d.ts.map +0 -1
  568. package/dist/index.js.map +0 -1
  569. package/dist/init/agent-rules.d.ts.map +0 -1
  570. package/dist/init/agent-rules.js.map +0 -1
  571. package/dist/init/cursor.d.ts.map +0 -1
  572. package/dist/init/cursor.js.map +0 -1
  573. package/dist/init/detect.d.ts.map +0 -1
  574. package/dist/init/detect.js.map +0 -1
  575. package/dist/init/mcp.d.ts.map +0 -1
  576. package/dist/init/mcp.js.map +0 -1
  577. package/dist/init/node-io.d.ts.map +0 -1
  578. package/dist/init/node-io.js.map +0 -1
  579. package/dist/init/plan.d.ts.map +0 -1
  580. package/dist/init/plan.js.map +0 -1
  581. package/dist/init/project-id.d.ts.map +0 -1
  582. package/dist/init/project-id.js.map +0 -1
  583. package/dist/init/run.d.ts.map +0 -1
  584. package/dist/init/run.js.map +0 -1
  585. package/dist/init/snippets.d.ts.map +0 -1
  586. package/dist/init/snippets.js.map +0 -1
  587. package/dist/init/vite-config.d.ts.map +0 -1
  588. package/dist/init/vite-config.js.map +0 -1
  589. package/dist/input/network-detail.d.ts.map +0 -1
  590. package/dist/input/network-detail.js.map +0 -1
  591. package/dist/input/network-mock-tools.d.ts.map +0 -1
  592. package/dist/input/network-mock-tools.js.map +0 -1
  593. package/dist/input/network-mock.d.ts.map +0 -1
  594. package/dist/input/network-mock.js.map +0 -1
  595. package/dist/input/real-input.d.ts.map +0 -1
  596. package/dist/input/real-input.js.map +0 -1
  597. package/dist/input/scroll-find.d.ts.map +0 -1
  598. package/dist/input/scroll-find.js.map +0 -1
  599. package/dist/input/scroll-tools.d.ts.map +0 -1
  600. package/dist/input/scroll-tools.js.map +0 -1
  601. package/dist/input/viewport-tools.d.ts.map +0 -1
  602. package/dist/input/viewport-tools.js.map +0 -1
  603. package/dist/journal/ambient-store.d.ts.map +0 -1
  604. package/dist/journal/ambient-store.js.map +0 -1
  605. package/dist/journal/ambient.d.ts.map +0 -1
  606. package/dist/journal/ambient.js.map +0 -1
  607. package/dist/journal/attach-journal.d.ts.map +0 -1
  608. package/dist/journal/attach-journal.js.map +0 -1
  609. package/dist/journal/deviation-report.d.ts.map +0 -1
  610. package/dist/journal/deviation-report.js.map +0 -1
  611. package/dist/journal/deviation-service.d.ts.map +0 -1
  612. package/dist/journal/deviation-service.js.map +0 -1
  613. package/dist/journal/envelope-store.d.ts.map +0 -1
  614. package/dist/journal/envelope-store.js.map +0 -1
  615. package/dist/journal/envelope.d.ts.map +0 -1
  616. package/dist/journal/envelope.js.map +0 -1
  617. package/dist/journal/journal-query.d.ts.map +0 -1
  618. package/dist/journal/journal-query.js.map +0 -1
  619. package/dist/journal/journal-recorder.d.ts.map +0 -1
  620. package/dist/journal/journal-recorder.js.map +0 -1
  621. package/dist/journal/retention.d.ts.map +0 -1
  622. package/dist/journal/retention.js.map +0 -1
  623. package/dist/journal/rollups.d.ts.map +0 -1
  624. package/dist/journal/rollups.js.map +0 -1
  625. package/dist/journal/session-end.d.ts.map +0 -1
  626. package/dist/journal/session-end.js.map +0 -1
  627. package/dist/journal/session-journal.d.ts.map +0 -1
  628. package/dist/journal/session-journal.js.map +0 -1
  629. package/dist/license/license.d.ts.map +0 -1
  630. package/dist/license/license.js.map +0 -1
  631. package/dist/log.d.ts.map +0 -1
  632. package/dist/log.js.map +0 -1
  633. package/dist/mcp-proxy.d.ts.map +0 -1
  634. package/dist/mcp-proxy.js.map +0 -1
  635. package/dist/mcp.d.ts.map +0 -1
  636. package/dist/mcp.js.map +0 -1
  637. package/dist/oracles/flow-instrument-gaps.d.ts.map +0 -1
  638. package/dist/oracles/flow-instrument-gaps.js.map +0 -1
  639. package/dist/oracles/propose-consequences.d.ts.map +0 -1
  640. package/dist/oracles/propose-consequences.js.map +0 -1
  641. package/dist/oracles/self-instrument.d.ts.map +0 -1
  642. package/dist/oracles/self-instrument.js.map +0 -1
  643. package/dist/pairing-token.d.ts.map +0 -1
  644. package/dist/pairing-token.js.map +0 -1
  645. package/dist/phenomena/phenomena.d.ts.map +0 -1
  646. package/dist/phenomena/phenomena.js.map +0 -1
  647. package/dist/pool/browser-pool.d.ts.map +0 -1
  648. package/dist/pool/browser-pool.js.map +0 -1
  649. package/dist/pool/lease-reaper.d.ts.map +0 -1
  650. package/dist/pool/lease-reaper.js.map +0 -1
  651. package/dist/pool/playwright-launcher.d.ts.map +0 -1
  652. package/dist/pool/playwright-launcher.js.map +0 -1
  653. package/dist/project/baselines.d.ts.map +0 -1
  654. package/dist/project/baselines.js.map +0 -1
  655. package/dist/project/file-lock.d.ts.map +0 -1
  656. package/dist/project/file-lock.js.map +0 -1
  657. package/dist/project/fs-port.d.ts.map +0 -1
  658. package/dist/project/fs-port.js.map +0 -1
  659. package/dist/project/project-store.d.ts.map +0 -1
  660. package/dist/project/project-store.js.map +0 -1
  661. package/dist/project/project-tools.d.ts.map +0 -1
  662. package/dist/project/project-tools.js.map +0 -1
  663. package/dist/project/reticle-dir.d.ts.map +0 -1
  664. package/dist/project/reticle-dir.js.map +0 -1
  665. package/dist/runs/build-verification-run.d.ts.map +0 -1
  666. package/dist/runs/build-verification-run.js.map +0 -1
  667. package/dist/runs/profile-redact.d.ts.map +0 -1
  668. package/dist/runs/profile-redact.js.map +0 -1
  669. package/dist/runs/render-report.d.ts.map +0 -1
  670. package/dist/runs/render-report.js.map +0 -1
  671. package/dist/runs/repair-prompt.d.ts.map +0 -1
  672. package/dist/runs/repair-prompt.js.map +0 -1
  673. package/dist/runs/replay-mapping.d.ts.map +0 -1
  674. package/dist/runs/replay-mapping.js.map +0 -1
  675. package/dist/runs/reticle-runner.d.ts.map +0 -1
  676. package/dist/runs/reticle-runner.js.map +0 -1
  677. package/dist/runs/risk-classify.d.ts.map +0 -1
  678. package/dist/runs/risk-classify.js.map +0 -1
  679. package/dist/runs/run-diff.d.ts.map +0 -1
  680. package/dist/runs/run-diff.js.map +0 -1
  681. package/dist/runs/run-store.d.ts.map +0 -1
  682. package/dist/runs/run-store.js.map +0 -1
  683. package/dist/runs/run-tools.d.ts.map +0 -1
  684. package/dist/runs/run-tools.js.map +0 -1
  685. package/dist/runs/runner-port.d.ts.map +0 -1
  686. package/dist/runs/runner-port.js.map +0 -1
  687. package/dist/runs/verification-sync.d.ts.map +0 -1
  688. package/dist/runs/verification-sync.js.map +0 -1
  689. package/dist/runs/verify-http.d.ts.map +0 -1
  690. package/dist/runs/verify-http.js.map +0 -1
  691. package/dist/runs/verify-server.d.ts.map +0 -1
  692. package/dist/runs/verify-server.js.map +0 -1
  693. package/dist/server-version.d.ts.map +0 -1
  694. package/dist/server-version.js.map +0 -1
  695. package/dist/session/control-envelope.d.ts.map +0 -1
  696. package/dist/session/control-envelope.js.map +0 -1
  697. package/dist/session/live-control-tools.d.ts.map +0 -1
  698. package/dist/session/live-control-tools.js.map +0 -1
  699. package/dist/session/live-control.d.ts.map +0 -1
  700. package/dist/session/live-control.js.map +0 -1
  701. package/dist/session/observed-state.d.ts.map +0 -1
  702. package/dist/session/observed-state.js.map +0 -1
  703. package/dist/session/output-budget.d.ts.map +0 -1
  704. package/dist/session/output-budget.js.map +0 -1
  705. package/dist/session/presenter-args.d.ts.map +0 -1
  706. package/dist/session/presenter-args.js.map +0 -1
  707. package/dist/session/review-store.d.ts.map +0 -1
  708. package/dist/session/review-store.js.map +0 -1
  709. package/dist/session/session-health.d.ts.map +0 -1
  710. package/dist/session/session-health.js.map +0 -1
  711. package/dist/session/session-manager.d.ts.map +0 -1
  712. package/dist/session/session-manager.js.map +0 -1
  713. package/dist/session/session-readiness.d.ts.map +0 -1
  714. package/dist/session/session-readiness.js.map +0 -1
  715. package/dist/session/session-reaper.d.ts.map +0 -1
  716. package/dist/session/session-reaper.js.map +0 -1
  717. package/dist/session/session-recommendation.d.ts.map +0 -1
  718. package/dist/session/session-recommendation.js.map +0 -1
  719. package/dist/session/session-tools.d.ts.map +0 -1
  720. package/dist/session/session-tools.js.map +0 -1
  721. package/dist/session/session.d.ts.map +0 -1
  722. package/dist/session/session.js.map +0 -1
  723. package/dist/session/state-select.d.ts.map +0 -1
  724. package/dist/session/state-select.js.map +0 -1
  725. package/dist/telemetry/telemetry.d.ts.map +0 -1
  726. package/dist/telemetry/telemetry.js.map +0 -1
  727. package/dist/token-auth.d.ts.map +0 -1
  728. package/dist/token-auth.js.map +0 -1
  729. package/dist/tools/act-tools.d.ts.map +0 -1
  730. package/dist/tools/act-tools.js.map +0 -1
  731. package/dist/tools/act-view.d.ts.map +0 -1
  732. package/dist/tools/act-view.js.map +0 -1
  733. package/dist/tools/assert-grade.d.ts.map +0 -1
  734. package/dist/tools/assert-grade.js.map +0 -1
  735. package/dist/tools/browser-tools.d.ts.map +0 -1
  736. package/dist/tools/browser-tools.js.map +0 -1
  737. package/dist/tools/contract-tools.d.ts.map +0 -1
  738. package/dist/tools/contract-tools.js.map +0 -1
  739. package/dist/tools/dynamic-tools.d.ts.map +0 -1
  740. package/dist/tools/dynamic-tools.js.map +0 -1
  741. package/dist/tools/error-recovery.d.ts.map +0 -1
  742. package/dist/tools/error-recovery.js.map +0 -1
  743. package/dist/tools/invoke-tool.d.ts.map +0 -1
  744. package/dist/tools/invoke-tool.js.map +0 -1
  745. package/dist/tools/lease-tools.d.ts.map +0 -1
  746. package/dist/tools/lease-tools.js.map +0 -1
  747. package/dist/tools/merge-tools.d.ts.map +0 -1
  748. package/dist/tools/merge-tools.js.map +0 -1
  749. package/dist/tools/observe-tools.d.ts.map +0 -1
  750. package/dist/tools/observe-tools.js.map +0 -1
  751. package/dist/tools/profiles.d.ts.map +0 -1
  752. package/dist/tools/profiles.js.map +0 -1
  753. package/dist/tools/query-paginate.d.ts.map +0 -1
  754. package/dist/tools/query-paginate.js.map +0 -1
  755. package/dist/tools/read-tools.d.ts.map +0 -1
  756. package/dist/tools/read-tools.js.map +0 -1
  757. package/dist/tools/snapshot-delta.d.ts.map +0 -1
  758. package/dist/tools/snapshot-delta.js.map +0 -1
  759. package/dist/tools/tool-invoker.d.ts.map +0 -1
  760. package/dist/tools/tool-invoker.js.map +0 -1
  761. package/dist/tools/tool-kit.d.ts.map +0 -1
  762. package/dist/tools/tool-kit.js.map +0 -1
  763. package/dist/tools/tool-names.d.ts.map +0 -1
  764. package/dist/tools/tool-names.js.map +0 -1
  765. package/dist/tools/tools-helpers.d.ts.map +0 -1
  766. package/dist/tools/tools-helpers.js.map +0 -1
  767. package/dist/tools/tools.d.ts.map +0 -1
  768. package/dist/tools/tools.js.map +0 -1
  769. package/dist/update/update-checker.d.ts.map +0 -1
  770. package/dist/update/update-checker.js.map +0 -1
  771. package/dist/update/updater.d.ts.map +0 -1
  772. package/dist/update/updater.js.map +0 -1
  773. package/dist/visual/visual-diff.d.ts.map +0 -1
  774. package/dist/visual/visual-diff.js.map +0 -1
  775. package/dist/visual/visual-store.d.ts.map +0 -1
  776. package/dist/visual/visual-store.js.map +0 -1
  777. package/dist/visual/visual-tools.d.ts.map +0 -1
  778. package/dist/visual/visual-tools.js.map +0 -1
@@ -0,0 +1,92 @@
1
+ import { z } from 'zod';
2
+ import { ReticleCommand, SnapshotMode } from '@reticlehq/core';
3
+ import { ReticleTool } from './tool-names.js';
4
+ import { asString } from './tools-helpers.js';
5
+ import { commandOrThrow, sessionIdShape } from './tool-kit.js';
6
+ /**
7
+ * `reticle_coverage` — which interactive controls this session has driven, and which it has not.
8
+ *
9
+ * Every other read here answers a question the agent already thought to ask, which bounds
10
+ * verification by the agent's imagination — the documented weak link. This answers the one question
11
+ * that tells the agent whether to STOP: an agent that exercised 4 of 17 controls and believes it
12
+ * verified the page is exactly the confident-and-wrong case Reticle exists to prevent, and nothing
13
+ * in the tool surface previously contradicted it.
14
+ *
15
+ * Note this is NOT the existing `blindSpots` coverage, which is about what the layer could not SEE
16
+ * (closed shadow roots, cross-origin frames). This is about what the agent did not TOUCH. Both are
17
+ * honesty signals; they answer different questions and neither substitutes for the other.
18
+ *
19
+ * Unadvertised by every profile: it costs nothing per turn and is reached through `reticle_run`.
20
+ */
21
+ /** Refs as the snapshot tree spells them: `(ref=e12)`. The tree format is ours, so this is exact. */
22
+ const REF_IN_TREE = /\(ref=(e\d+)\)/g;
23
+ /** The label a tree line carries before its ref, e.g. `- button "Archive" (ref=e9)`. */
24
+ const LINE_WITH_REF = /^\s*-\s*(.+?)\s*\(ref=(e\d+)\)/;
25
+ /** Parse the interactive snapshot into {ref,label} controls, preserving document order. */
26
+ export function parseControls(tree) {
27
+ const controls = [];
28
+ const seen = new Set();
29
+ for (const line of tree.split('\n')) {
30
+ const match = LINE_WITH_REF.exec(line);
31
+ if (match === null)
32
+ continue;
33
+ const [, label, ref] = match;
34
+ if (label === undefined || ref === undefined || seen.has(ref))
35
+ continue;
36
+ seen.add(ref);
37
+ controls.push({ ref, label });
38
+ }
39
+ // A ref can appear on a line this regex does not shape (nested formatting); count it regardless,
40
+ // because under-reporting the denominator would overstate coverage — the one direction that lies.
41
+ for (const match of tree.matchAll(REF_IN_TREE)) {
42
+ const ref = match[1];
43
+ if (ref !== undefined && !seen.has(ref)) {
44
+ seen.add(ref);
45
+ controls.push({ ref, label: '' });
46
+ }
47
+ }
48
+ return controls;
49
+ }
50
+ export const COVERAGE_TOOLS = [
51
+ {
52
+ name: ReticleTool.COVERAGE,
53
+ description: 'Which interactive controls you have driven this session, and which you have NOT. Returns { total, exercised, untouched:[{ref,label}], alsoDroveGone? } over the controls currently on the page. Use it to decide whether verification is finished: an untouched list that still holds the controls your change affects means you are not done. This is about what you did not TOUCH — distinct from the `coverage` field on an action result, which reports what the layer could not SEE.',
54
+ example: {},
55
+ inputSchema: { ...sessionIdShape },
56
+ outputSchema: {
57
+ total: z.number(),
58
+ exercised: z.number(),
59
+ untouched: z.array(z.object({ ref: z.string(), label: z.string() })),
60
+ alsoDroveGone: z
61
+ .number()
62
+ .optional()
63
+ .describe('Controls you drove that are no longer on the page — usually because the action SUCCEEDED and removed them (archive/delete/submit/navigate). Counted separately so `exercised: 0` never appears immediately after real work.'),
64
+ },
65
+ handler: async (deps, args) => {
66
+ const sessionId = asString(args['sessionId']);
67
+ const session = deps.sessions.resolve(sessionId);
68
+ // INTERACTIVE mode is already the "controls only" view, so the denominator is the page's own
69
+ // notion of what can be driven rather than a second, drifting definition maintained here.
70
+ const result = await commandOrThrow(deps, sessionId, ReticleCommand.SNAPSHOT, {
71
+ mode: SnapshotMode.INTERACTIVE,
72
+ });
73
+ const tree = asString(result['tree']) ?? '';
74
+ const acted = session.actedRefs();
75
+ const controls = parseControls(tree);
76
+ const present = new Set(controls.map((control) => control.ref));
77
+ const untouched = controls.filter((control) => !acted.has(control.ref));
78
+ // Drives that landed on controls no longer in the DOM. Without this the number is biased
79
+ // against the actions that WORKED: archive, delete, submit and navigate all remove their own
80
+ // control, so clicking one and asking again reported `exercised: 0` — measured on the Electron
81
+ // demo right after a successful archive. An agent reading "0" concludes it has done nothing
82
+ // and re-drives ground it already covered.
83
+ const drovenGone = [...acted].filter((ref) => !present.has(ref)).length;
84
+ return {
85
+ total: controls.length,
86
+ exercised: controls.length - untouched.length,
87
+ untouched,
88
+ ...(drovenGone > 0 ? { alsoDroveGone: drovenGone } : {}),
89
+ };
90
+ },
91
+ },
92
+ ];
@@ -4,4 +4,3 @@ import type { ToolDef } from './tools.js';
4
4
  * `runTool` chokepoint as a direct call, so session-health splicing and every other invariant hold.
5
5
  */
6
6
  export declare function buildDynamicTools(allTools: ToolDef[]): ToolDef[];
7
- //# sourceMappingURL=dynamic-tools.d.ts.map
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { runTool } from './invoke-tool.js';
3
3
  import { ReticleTool } from './tool-names.js';
4
+ import { getSessionMetrics } from '../telemetry/session-metrics.js';
4
5
  /**
5
6
  * On-demand tool loading for MCP — the answer to the per-turn tool-definition tax.
6
7
  *
@@ -43,7 +44,7 @@ export function buildDynamicTools(allTools) {
43
44
  const byName = new Map(allTools.map((t) => [t.name, t]));
44
45
  const reticleTools = {
45
46
  name: ReticleTool.TOOLS,
46
- description: 'Discover Reticle tools on demand. Call with no arguments to list every tool (name + one-line summary); call with names:["reticle_network", …] to load full descriptions and parameters for specific tools. Then invoke them with reticle_run. This avoids paying for every tool definition on every turn. To make a verification REUSABLE (record once, replay free forever), the flow workflow lives here: reticle_record_start → act → reticle_flow_save → reticle_flow_verify (and reticle_flow_heal on drift). Load those names when you want to save or re-run a flow.',
47
+ description: 'Discover Reticle tools on demand. Call with no arguments to list every tool (name + one-line summary); call with names:["reticle_network", …] to load full descriptions and parameters for specific tools. Then invoke them with reticle_run. This avoids paying for every tool definition on every turn. To make a verification REUSABLE (record once, replay free forever), the flow workflow lives here: reticle_record{action:"start"} → act → reticle_flow_save → reticle_flow_verify (and reticle_flow_heal on drift). Load those names when you want to save or re-run a flow.',
47
48
  inputSchema: {
48
49
  names: z
49
50
  .array(z.string())
@@ -84,8 +85,27 @@ export function buildDynamicTools(allTools) {
84
85
  : {};
85
86
  const target = byName.get(name);
86
87
  if (target === undefined) {
88
+ // A non-zero count here means our advertised surface is confusing the agent — it reached for
89
+ // something it believed existed. That is a docs/naming defect, and it was invisible.
90
+ getSessionMetrics().recordUnknownTool();
87
91
  return { error: `unknown tool '${name}'`, available: allTools.map((t) => t.name) };
88
92
  }
93
+ // The escape hatch is where a typo is MOST likely, because an unadvertised tool's parameters
94
+ // are not in front of the agent at all — and it is the one path the SDK's own validation never
95
+ // sees, since `reticle_run`'s own args (`tool`, `args`) are perfectly valid. Left unchecked,
96
+ // `reticle_run { tool: "reticle_clock", args: { action: "freeze" } }` returned
97
+ // `{"frozen":false}`: a well-formed answer to a question nobody asked.
98
+ const declared = new Set(Object.keys(target.inputSchema));
99
+ const unknown = Object.keys(callArgs).filter((key) => !declared.has(key));
100
+ if (unknown.length > 0) {
101
+ return {
102
+ error: `unknown ${unknown.length === 1 ? 'parameter' : 'parameters'} for ${name}: ${unknown.join(', ')} — NOT applied, so any result would be an answer to a different question`,
103
+ tool: name,
104
+ params: paramInfo(target.inputSchema),
105
+ ...(target.example === undefined ? {} : { example: target.example }),
106
+ hint: 'fix the arguments and call reticle_run again',
107
+ };
108
+ }
89
109
  try {
90
110
  return await runTool(target, deps, callArgs);
91
111
  }
@@ -101,4 +121,3 @@ export function buildDynamicTools(allTools) {
101
121
  };
102
122
  return [reticleTools, reticleRun];
103
123
  }
104
- //# sourceMappingURL=dynamic-tools.js.map
@@ -16,16 +16,32 @@ export declare const RECOVERY: {
16
16
  readonly THROTTLED: string;
17
17
  readonly MISSING_BASELINE: string;
18
18
  readonly MISSING_RECORDING: string;
19
+ readonly STALE_REF: string;
20
+ readonly BAD_ARGUMENTS: string;
19
21
  readonly TOKEN_REQUIRED: string;
20
22
  };
21
23
  /** The actionable next move for a known error message, or undefined when none is recognized. */
22
24
  export declare function recoveryFor(message: string): string | undefined;
25
+ /**
26
+ * The ask attached to errors we do NOT recognize. An unrecognized error is, by definition, the case
27
+ * where Reticle failed in a way nobody anticipated — the single highest-value moment to hear from the
28
+ * agent, and until now the moment where the agent worked around us in silence and we learned nothing.
29
+ *
30
+ * Deliberately NOT attached when a recovery hint matched: there the agent has a concrete next move,
31
+ * and diverting it into filing a report about a failure we already understand costs a turn and tells
32
+ * us nothing new.
33
+ */
34
+ export declare const FEEDBACK_ASK: string;
23
35
  /** The error envelope sent to the agent: the message, plus a recovery hint when one is known. */
24
36
  interface ErrorPayload {
25
37
  error: string;
26
38
  recovery?: string;
39
+ feedback?: string;
27
40
  }
28
- /** Build the tool-error payload spliced at the MCP boundary — `recovery` is added only when known. */
41
+ /**
42
+ * Build the tool-error payload spliced at the MCP boundary. `recovery` is added when the error is
43
+ * known; the feedback ask is added when it is NOT — the two are mutually exclusive by design, so the
44
+ * agent always gets exactly one next move.
45
+ */
29
46
  export declare function buildErrorPayload(message: string): ErrorPayload;
30
47
  export {};
31
- //# sourceMappingURL=error-recovery.d.ts.map
@@ -19,10 +19,18 @@ export const RECOVERY = {
19
19
  UNKNOWN_SESSION: 'That sessionId is not connected. Call reticle_sessions for the current ids and retry with a valid one.',
20
20
  THROTTLED: 'The target tab is backgrounded/throttled, so actions may silently no-op. Ask the human to bring ' +
21
21
  'the tab to the front, or run `reticle drive <url>` for a guaranteed scriptable context.',
22
- MISSING_BASELINE: 'That baseline does not exist yet. Call reticle_baseline_list to see saved names, or reticle_baseline_save ' +
23
- 'to capture one before diffing against it.',
24
- MISSING_RECORDING: 'No recording by that name is in progress. Start one with reticle_record_start before annotating, ' +
25
- 'stopping, or saving it.',
22
+ MISSING_BASELINE: 'That baseline does not exist yet. Call reticle_baseline { action: "list" } to see saved names, or ' +
23
+ 'reticle_baseline { action: "save", name } to capture one before diffing against it.',
24
+ MISSING_RECORDING: 'No recording by that name is in progress. Start one with reticle_record { action: "start", name } ' +
25
+ 'before annotating, stopping, or saving it.',
26
+ STALE_REF: 'That ref is stale: refs are invalidated whenever the DOM re-renders, so any action that ' +
27
+ 'navigated, opened a modal, re-sorted a list or changed the page invalidates every ref taken ' +
28
+ 'before it. Reticle refuses here rather than clicking whatever now occupies that slot. Call ' +
29
+ 'reticle_query again for a fresh ref and retry the action — and prefer reticle_act_and_wait ' +
30
+ '{ until } when an action changes the page, so the next ref is taken after it settles.',
31
+ BAD_ARGUMENTS: "That call did not match the tool's schema — the message above names the tool and the exact " +
32
+ "argument it wanted. Re-read that tool's parameters and retry with the missing or corrected " +
33
+ 'argument. This is an invalid call, not a Reticle defect: there is nothing to report.',
26
34
  TOKEN_REQUIRED: 'The bridge binds beyond localhost and requires a pairing token. Set the same token in the SDK ' +
27
35
  'init (@reticlehq/core) and the Reticle server config, then reconnect.',
28
36
  };
@@ -35,6 +43,16 @@ const RULES = [
35
43
  { match: /no baseline named/i, hint: RECOVERY.MISSING_BASELINE },
36
44
  { match: /no (?:active|compiled) recording named/i, hint: RECOVERY.MISSING_RECORDING },
37
45
  { match: /pairing token is required/i, hint: RECOVERY.TOKEN_REQUIRED },
46
+ // The commonest post-action condition there is. Unmatched, it fell through to FEEDBACK_ASK and
47
+ // told the agent a successful click's aftermath might be a bug in Reticle.
48
+ { match: /no longer resolves to an element/i, hint: RECOVERY.STALE_REF },
49
+ // A message naming a `reticle_*` tool is one WE authored about our own API — an invalid call, not
50
+ // an unanticipated failure. Left unmatched it collected the feedback ask, which pushed agents to
51
+ // file reports about their own bad arguments. Kept LAST so a specific rule above always wins.
52
+ {
53
+ match: /reticle_[a-z_]+\s*\{[^}]*\}.*\b(requires|must|expected)\b/i,
54
+ hint: RECOVERY.BAD_ARGUMENTS,
55
+ },
38
56
  ];
39
57
  /** The actionable next move for a known error message, or undefined when none is recognized. */
40
58
  export function recoveryFor(message) {
@@ -44,9 +62,26 @@ export function recoveryFor(message) {
44
62
  }
45
63
  return undefined;
46
64
  }
47
- /** Build the tool-error payload spliced at the MCP boundary — `recovery` is added only when known. */
65
+ /**
66
+ * The ask attached to errors we do NOT recognize. An unrecognized error is, by definition, the case
67
+ * where Reticle failed in a way nobody anticipated — the single highest-value moment to hear from the
68
+ * agent, and until now the moment where the agent worked around us in silence and we learned nothing.
69
+ *
70
+ * Deliberately NOT attached when a recovery hint matched: there the agent has a concrete next move,
71
+ * and diverting it into filing a report about a failure we already understand costs a turn and tells
72
+ * us nothing new.
73
+ */
74
+ export const FEEDBACK_ASK = 'This error is not one Reticle recognizes, which means it may be a defect in Reticle rather than in ' +
75
+ 'the app. If you believe Reticle misbehaved, call reticle_feedback with a root-cause analysis and ' +
76
+ 'the call trace before moving on — that report is the only way this gets fixed.';
77
+ /**
78
+ * Build the tool-error payload spliced at the MCP boundary. `recovery` is added when the error is
79
+ * known; the feedback ask is added when it is NOT — the two are mutually exclusive by design, so the
80
+ * agent always gets exactly one next move.
81
+ */
48
82
  export function buildErrorPayload(message) {
49
83
  const recovery = recoveryFor(message);
50
- return recovery !== undefined ? { error: message, recovery } : { error: message };
84
+ return recovery !== undefined
85
+ ? { error: message, recovery }
86
+ : { error: message, feedback: FEEDBACK_ASK };
51
87
  }
52
- //# sourceMappingURL=error-recovery.js.map
@@ -0,0 +1,24 @@
1
+ import type { ToolDef } from './tools.js';
2
+ export declare const FEEDBACK_TOOLS: ToolDef[];
3
+ /**
4
+ * The human-facing prompt, delivered to the agent so it can relay the ask at the natural moment —
5
+ * right after a verification lands, when the experience is fresh. MCP has no channel from the server
6
+ * to the person, so the agent is the channel.
7
+ *
8
+ * Delivered ONCE per server process. A prompt on every verification would be nagging, and a nagged
9
+ * user opts out of telemetry entirely, which costs us the counters too.
10
+ */
11
+ export declare const FEEDBACK_PROMPT: {
12
+ readonly ask: "Ask the human, in your own words and only once: how did this verification go, and what would have made Reticle more useful? If they answer, file it with `reticle feedback` (they run it) or relay it yourself.";
13
+ readonly command: "reticle feedback";
14
+ };
15
+ /** Tools whose completion means "a verification just happened" — the only moment worth asking at. */
16
+ export declare const VERIFICATION_TOOLS: ReadonlySet<string>;
17
+ /**
18
+ * The human prompt, when one is due. Resettable for tests.
19
+ *
20
+ * Silent when the channel is off. Asking someone for feedback we have already been told not to
21
+ * collect is worse than not asking: it spends their attention on a message with nowhere to go.
22
+ */
23
+ export declare function takeFeedbackPrompt(toolName: string): typeof FEEDBACK_PROMPT | undefined;
24
+ export declare function resetFeedbackPrompt(): void;
@@ -0,0 +1,180 @@
1
+ /**
2
+ * `reticle_feedback` — the agent's return path.
3
+ *
4
+ * Reticle is built for agents, but the agent has always been the one party that knows a verification
5
+ * went wrong and has had no way to say so. It sees the tool that returned nonsense, the observer that
6
+ * missed the event, the verdict it could not act on — and then that context is discarded at the end of
7
+ * the turn. This tool is where that knowledge goes instead.
8
+ *
9
+ * It is deliberately shaped to demand an RCA rather than a complaint. `text` asks what the agent
10
+ * expected, what it got, and why it believes Reticle is at fault; `trace` asks for the call trail that
11
+ * proves it. A report we cannot reproduce is a report we cannot fix, so the description spends its
12
+ * tokens on that and not on politeness.
13
+ */
14
+ import { z } from 'zod';
15
+ import { FeedbackKind, FeedbackSource } from '@reticlehq/core';
16
+ import { ReticleTool } from './tool-names.js';
17
+ import { asString } from './tools-helpers.js';
18
+ import { submitFeedback, feedbackDisabled } from '../telemetry/feedback.js';
19
+ import { getTelemetry } from '../telemetry/telemetry.js';
20
+ /** One optional string arg, present only when the agent actually supplied it. */
21
+ function optionalText(args, key) {
22
+ const value = asString(args[key]);
23
+ return value !== undefined && value !== '' ? { [key]: value } : {};
24
+ }
25
+ /** Read the connected session's self-reported facts, or nothing when no app is attached. */
26
+ function sessionFacts(deps, sessionId) {
27
+ const driven = deps.realInput !== undefined;
28
+ try {
29
+ const session = deps.sessions.resolve(sessionId);
30
+ return {
31
+ ...(session.runtime !== undefined ? { runtime: session.runtime } : {}),
32
+ ...(session.engine !== undefined ? { engine: session.engine } : {}),
33
+ driven,
34
+ };
35
+ }
36
+ catch {
37
+ // Feedback about "no session could ever connect" is some of the most valuable feedback there is.
38
+ // Refusing to file it without a session would silence exactly the failure we most need to hear.
39
+ return { driven };
40
+ }
41
+ }
42
+ export const FEEDBACK_TOOLS = [
43
+ {
44
+ name: ReticleTool.FEEDBACK,
45
+ description: "Tell the Reticle maintainers something — a failure, OR a feature you wish existed. Reticle is built FOR agents, so your experience is the one that decides what gets built, and this is the only channel that reaches us. File a `bug` when a tool returned something wrong, a `gap` when Reticle could not observe what you needed, an `ambiguity` when a verdict was not decidable, a `feature_request` when you thought 'I wish Reticle could do X', or an `improvement` when something works but is awkward (too many calls, a confusing shape, a slow path). Do not save these up or judge them as too minor — file it the moment you notice, then carry on with your task. For a failure, write `text` as a root-cause analysis (what you called, expected, got). For a request, write what you want and use `need` for the GOAL behind it, `impact` for what gets better, and `currentApproach` for how you are working around it today — that workaround is usually the most useful thing in the report. Set `model` to the model you are running. Never include app source, secrets, user data, or customer records. Do NOT use this for bugs you found in the app under test — that is a successful verification, which is Reticle working.",
46
+ inputSchema: {
47
+ kind: z
48
+ .enum([
49
+ FeedbackKind.BUG,
50
+ FeedbackKind.GAP,
51
+ FeedbackKind.AMBIGUITY,
52
+ FeedbackKind.FEATURE_REQUEST,
53
+ FeedbackKind.IMPROVEMENT,
54
+ ])
55
+ .describe('bug = a Reticle tool returned a wrong or broken result; gap = Reticle could not observe something you needed at all; ambiguity = the verification ran but you could not tell pass from fail; feature_request = something that does not exist and would have helped; improvement = something that exists but is awkward or inefficient.'),
56
+ text: z
57
+ .string()
58
+ .min(1)
59
+ .describe('For a failure: the root-cause analysis — the call you made, what you expected, what you got, and why Reticle is at fault. For a request: what you want, in your own words.'),
60
+ need: z
61
+ .string()
62
+ .optional()
63
+ .describe('The GOAL behind a request, not the request itself. "I need to know the page stopped changing before I assert" is a requirement we can solve; "add a waitForIdle tool" is a guess at the solution that may already have an answer.'),
64
+ impact: z
65
+ .string()
66
+ .optional()
67
+ .describe('What measurably improves — fewer tool calls, fewer retries, a verdict that stops being ambiguous, a flow you currently cannot verify at all.'),
68
+ currentApproach: z
69
+ .string()
70
+ .optional()
71
+ .describe('How you work around it TODAY. Usually the most useful field in the report: it proves the need is real, and often shows a cheaper fix than the feature being asked for.'),
72
+ model: z
73
+ .string()
74
+ .optional()
75
+ .describe('The model you are running (e.g. "claude-opus-4", "gpt-5"). We cannot detect this — MCP tells us the client name but has no concept of a model — and it changes how a report is read: a limitation that blocks a smaller model is often a docs problem, while the same one from a frontier model means the surface is genuinely short.'),
76
+ trace: z
77
+ .string()
78
+ .optional()
79
+ .describe('The literal tool calls and responses that led here, so the failure can be reproduced without guessing.'),
80
+ sessionId: z
81
+ .string()
82
+ .optional()
83
+ .describe('Only to attach a specific tab s runtime/engine context. Omit it — a report about a session that never connected is still worth filing.'),
84
+ },
85
+ outputSchema: {
86
+ sent: z.boolean(),
87
+ reason: z.string().optional(),
88
+ redacted: z.array(z.string()),
89
+ context: z.unknown(),
90
+ note: z.string(),
91
+ },
92
+ example: {
93
+ kind: FeedbackKind.FEATURE_REQUEST,
94
+ text: 'A way to assert that no request fired at all during an action.',
95
+ need: 'Verifying that a debounced search does NOT call the API on every keystroke.',
96
+ currentApproach: 'Calling reticle_network before and after and diffing the counts by hand.',
97
+ model: 'claude-opus-4',
98
+ },
99
+ handler: async (deps, args) => {
100
+ const receipt = await submitFeedback({
101
+ source: FeedbackSource.AGENT,
102
+ kind: asString(args['kind']),
103
+ text: asString(args['text']) ?? '',
104
+ ...optionalText(args, 'trace'),
105
+ ...optionalText(args, 'need'),
106
+ ...optionalText(args, 'impact'),
107
+ ...optionalText(args, 'currentApproach'),
108
+ ...optionalText(args, 'model'),
109
+ }, { session: sessionFacts(deps, asString(args['sessionId'])) });
110
+ return {
111
+ ...receipt,
112
+ note: receipt.sent
113
+ ? 'Filed — thank you. Continue your task; do not retry a failing call just to re-report it.'
114
+ : 'NOT sent (see reason). Tell the human what you found so it is not lost.',
115
+ };
116
+ },
117
+ },
118
+ ];
119
+ /**
120
+ * The human-facing prompt, delivered to the agent so it can relay the ask at the natural moment —
121
+ * right after a verification lands, when the experience is fresh. MCP has no channel from the server
122
+ * to the person, so the agent is the channel.
123
+ *
124
+ * Delivered ONCE per server process. A prompt on every verification would be nagging, and a nagged
125
+ * user opts out of telemetry entirely, which costs us the counters too.
126
+ */
127
+ export const FEEDBACK_PROMPT = {
128
+ ask: 'Ask the human, in your own words and only once: how did this verification go, and what would have made Reticle more useful? If they answer, file it with `reticle feedback` (they run it) or relay it yourself.',
129
+ command: 'reticle feedback',
130
+ };
131
+ /** Tools whose completion means "a verification just happened" — the only moment worth asking at. */
132
+ export const VERIFICATION_TOOLS = new Set([
133
+ ReticleTool.ASSERT,
134
+ ReticleTool.FLOW_VERIFY,
135
+ ReticleTool.VERIFY_CHANGE,
136
+ ReticleTool.RECONCILE,
137
+ ]);
138
+ /**
139
+ * Verifications between re-offers of the prompt, and how many times we will ever offer it.
140
+ *
141
+ * Strictly-once was the first design and it was too fragile. A daemon lives for days; the prompt
142
+ * lands on the FIRST verification, which is often several hours before the human is in a position to
143
+ * answer, and if the agent does not relay it in that turn it is gone for the rest of the process.
144
+ * The signal quietly went to zero and nothing would have told us.
145
+ *
146
+ * Re-arming after a run of verifications fixes that without becoming nagging, and the hard cap is
147
+ * what keeps it honest: at most three asks per daemon, ever. A tool that pesters gets muted, and a
148
+ * muted tool collects nothing — the same outcome as never asking, reached more annoyingly.
149
+ */
150
+ const PROMPT_REARM_AFTER_VERIFICATIONS = 25;
151
+ const MAX_PROMPTS_PER_PROCESS = 3;
152
+ let promptsDelivered = 0;
153
+ let verificationsSincePrompt = 0;
154
+ /**
155
+ * The human prompt, when one is due. Resettable for tests.
156
+ *
157
+ * Silent when the channel is off. Asking someone for feedback we have already been told not to
158
+ * collect is worse than not asking: it spends their attention on a message with nowhere to go.
159
+ */
160
+ export function takeFeedbackPrompt(toolName) {
161
+ if (!VERIFICATION_TOOLS.has(toolName))
162
+ return undefined;
163
+ if (feedbackDisabled() || !getTelemetry().enabled)
164
+ return undefined;
165
+ if (promptsDelivered >= MAX_PROMPTS_PER_PROCESS)
166
+ return undefined;
167
+ // The very first verification asks immediately; later ones only after another run of work, so the
168
+ // ask always arrives attached to something the human just saw happen.
169
+ if (promptsDelivered > 0 && verificationsSincePrompt < PROMPT_REARM_AFTER_VERIFICATIONS) {
170
+ verificationsSincePrompt += 1;
171
+ return undefined;
172
+ }
173
+ promptsDelivered += 1;
174
+ verificationsSincePrompt = 0;
175
+ return FEEDBACK_PROMPT;
176
+ }
177
+ export function resetFeedbackPrompt() {
178
+ promptsDelivered = 0;
179
+ verificationsSincePrompt = 0;
180
+ }
@@ -20,4 +20,3 @@ export declare const SESSION_EXEMPT_TOOLS: ReadonlySet<string>;
20
20
  * (handlers that already add health are left untouched) and never alters non-object results.
21
21
  */
22
22
  export declare function runTool(tool: ToolDef, deps: ToolDeps, args: Record<string, unknown>): Promise<unknown>;
23
- //# sourceMappingURL=invoke-tool.d.ts.map
@@ -1,7 +1,13 @@
1
1
  import { healthEnvelope } from '../session/session-health.js';
2
- import { getTelemetry, TelemetryEventKind } from '../telemetry/telemetry.js';
2
+ import { TelemetryActor, TelemetryEventKind } from '@reticlehq/core';
3
+ import { getSessionMetrics } from '../telemetry/session-metrics.js';
4
+ import { getTelemetry } from '../telemetry/telemetry.js';
5
+ import { VERIFICATION_TOOLS } from './feedback-tools.js';
6
+ import { takeUpdateNudge } from '../update/update-nudge.js';
7
+ import { bugsInResult } from '../telemetry/bug-found.js';
3
8
  import { asString } from './tools-helpers.js';
4
9
  import { ReticleTool } from './tool-names.js';
10
+ import { takeFeedbackPrompt } from './feedback-tools.js';
5
11
  /**
6
12
  * The live-session tools whose result MUST carry the
7
13
  * session-health envelope. Owned in ONE place — not retrofitted per handler — so a throttled tab
@@ -12,12 +18,17 @@ export const SESSION_BOUND_TOOLS = new Set([
12
18
  ReticleTool.SNAPSHOT,
13
19
  ReticleTool.QUERY,
14
20
  ReticleTool.INSPECT,
21
+ ReticleTool.COVERAGE,
22
+ ReticleTool.VERIFY_CHANGE,
15
23
  ReticleTool.ACT,
16
24
  ReticleTool.ACT_SEQUENCE,
17
25
  ReticleTool.ACT_AND_WAIT,
18
26
  ReticleTool.OBSERVE,
19
27
  ReticleTool.WAIT_FOR,
20
28
  ReticleTool.ASSERT,
29
+ // Reads the live page as well as the event window, so a throttled tab can make it compare a stale
30
+ // render against fresh data — exactly the case the health envelope exists to disclose.
31
+ ReticleTool.RECONCILE,
21
32
  ReticleTool.NETWORK,
22
33
  ReticleTool.CONSOLE,
23
34
  ReticleTool.ANIMATIONS,
@@ -56,10 +67,74 @@ export const SESSION_EXEMPT_TOOLS = new Set([
56
67
  ReticleTool.VIEWPORT, // own contract (applied/width/height); provider-driven, not a live-DOM read
57
68
  ReticleTool.ANNOTATE, // annotates a recording's steps; pure disk-side metadata, no live DOM read
58
69
  ReticleTool.LEASE, // merged acquire/release — its sessionId is a pool lease id, not a live session
70
+ // Its sessionId only enriches the report with the tab's runtime/engine, and it must stay callable
71
+ // when NO session exists — "nothing ever connected" is feedback we especially want.
72
+ ReticleTool.FEEDBACK,
59
73
  ]);
60
74
  function isPlainObject(value) {
61
75
  return typeof value === 'object' && value !== null && !Array.isArray(value);
62
76
  }
77
+ /**
78
+ * Emit `verification_completed` when a verification tool produced a verdict.
79
+ *
80
+ * Read off the RESULT here rather than emitted from `decideVerified`, which is where the verdict is
81
+ * actually decided: that function is pure, and the repo's rules keep clocks, IO and side effects out
82
+ * of pure logic for good reason. Reading the result also means all four verification tools are covered
83
+ * by one site instead of four handler edits, and a fifth is covered the moment it joins the set.
84
+ *
85
+ * `falseGreenCaught` is the one that matters: the assertion PASSED and Reticle still refused to call
86
+ * it verified. That is the product's entire thesis reduced to a boolean, and it is the number worth
87
+ * putting in front of an investor — not "tools were called" but "this many greens were caught lying".
88
+ */
89
+ function recordVerification(toolName, result, durationMs) {
90
+ if (!VERIFICATION_TOOLS.has(toolName))
91
+ return;
92
+ const verified = typeof result['verified'] === 'string' ? result['verified'] : undefined;
93
+ // flow_verify reports `status: pass|fail`; assert reports a boolean `pass`. Accept either shape so
94
+ // the whole family is covered without normalizing four tools' contracts for a metric's convenience.
95
+ const passed = typeof result['pass'] === 'boolean'
96
+ ? result['pass']
97
+ : result['status'] === 'pass'
98
+ ? true
99
+ : undefined;
100
+ if (verified === undefined && passed === undefined)
101
+ return; // not a verdict-bearing result
102
+ const metrics = getSessionMetrics();
103
+ metrics.recordVerification();
104
+ void getTelemetry().emit(TelemetryEventKind.VERIFICATION_COMPLETED, {
105
+ actor: TelemetryActor.AGENT,
106
+ verification: {
107
+ via: toolName,
108
+ verified: verified ?? (passed === true ? 'yes' : 'no'),
109
+ passed: passed ?? verified === 'yes',
110
+ falseGreenCaught: passed === true && verified === 'no',
111
+ durationMs,
112
+ },
113
+ });
114
+ }
115
+ /**
116
+ * Emit one `bug_found` per defect in a tool result, and count it into the session.
117
+ *
118
+ * The outcome metric: everything else measures whether Reticle is used, this measures whether it
119
+ * works. Discrete events rather than only a counter, because the KIND distribution is the argument —
120
+ * "we found 4,000 bugs" is a claim, "1,200 were greens that lied" is evidence.
121
+ */
122
+ function reportBugsFound(toolName, result) {
123
+ const bugs = bugsInResult(toolName, result);
124
+ if (bugs.length === 0)
125
+ return;
126
+ const metrics = getSessionMetrics();
127
+ for (const bug of bugs) {
128
+ // `recordBug` answers whether this kind is new to the session, which is the only thing that
129
+ // separates "another defect" from "the same defect again". Counting instances as defects is how
130
+ // a published number inflates itself.
131
+ const first = metrics.recordBug(bug.kind);
132
+ void getTelemetry().emit(TelemetryEventKind.BUG_FOUND, {
133
+ actor: TelemetryActor.AGENT,
134
+ bug: { ...bug, repeat: !first },
135
+ });
136
+ }
137
+ }
63
138
  /**
64
139
  * The single entry point both the MCP server and the programmatic invoker call instead of
65
140
  * `tool.handler` directly. Runs the handler, then — for a live-session tool returning a plain
@@ -68,8 +143,16 @@ function isPlainObject(value) {
68
143
  */
69
144
  export async function runTool(tool, deps, args) {
70
145
  // Both dispatch paths (MCP + programmatic) pass through here — the one place "which tool is mostly
71
- // used" can be counted. Fire-and-forget: telemetry never delays or fails a tool call.
72
- void getTelemetry().emit(TelemetryEventKind.TOOL, { tool: tool.name });
146
+ // used" can be counted. This used to EMIT an event per call; it now increments an in-process counter
147
+ // that leaves once, with the session summary. A verification loop is 50–200 calls, and PostHog bills
148
+ // per event — so the old design made the telemetry bill scale with how hard people used the product,
149
+ // to answer a question the histogram answers better. Counting is also free: no network, no promise,
150
+ // nothing to fail on a tool call's hot path.
151
+ // Started/settled as a pair rather than a bare counter: several agents can be inside runTool at
152
+ // once, so a single "last start" field would attribute one tool's duration to another. The returned
153
+ // closure carries this call's own identity, which is also what makes peak-concurrency measurable.
154
+ const settleTiming = getSessionMetrics().startToolCall(tool.name, args);
155
+ const startedAt = Date.now();
73
156
  const rawSessionId = asString(args['sessionId']);
74
157
  const bound = SESSION_BOUND_TOOLS.has(tool.name);
75
158
  // Resolve the session identity ONCE, up front, for a live-session tool. The lease heartbeat must
@@ -90,7 +173,35 @@ export async function runTool(tool, deps, args) {
90
173
  const leaseId = session?.id ?? rawSessionId;
91
174
  if (leaseId !== undefined)
92
175
  deps.pool?.touch(leaseId);
93
- const result = await tool.handler(deps, args);
176
+ let raw;
177
+ try {
178
+ raw = await tool.handler(deps, args);
179
+ }
180
+ finally {
181
+ // In a `finally` so a THROWN call still settles: otherwise every failing tool would leak a
182
+ // concurrency slot and peakConcurrentTools would climb forever on an unhealthy session.
183
+ settleTiming(Date.now() - startedAt);
184
+ }
185
+ // The human-feedback ask rides out on the first VERIFICATION that completes — the one moment the
186
+ // experience is fresh and there is something concrete to react to. It is spliced BEFORE the
187
+ // session-bound early return, because two of the four verification tools (flow_verify,
188
+ // verify_change) are session-EXEMPT and would otherwise never carry it.
189
+ if (isPlainObject(raw)) {
190
+ recordVerification(tool.name, raw, Date.now() - startedAt);
191
+ reportBugsFound(tool.name, raw);
192
+ }
193
+ const prompt = isPlainObject(raw) ? takeFeedbackPrompt(tool.name) : undefined;
194
+ // Same one-shot channel as the feedback ask: the agent is mid-task, so anything it would have to go
195
+ // and ASK for is something it will never ask for. Spliced on ANY tool result, not just a
196
+ // verification, because an out-of-date install is worth mentioning whatever the agent is doing.
197
+ const update = isPlainObject(raw) ? takeUpdateNudge() : undefined;
198
+ const result = prompt === undefined && update === undefined
199
+ ? raw
200
+ : {
201
+ ...raw,
202
+ ...(prompt !== undefined ? { feedback_prompt: prompt } : {}),
203
+ ...(update !== undefined ? { update_available: update } : {}),
204
+ };
94
205
  if (!bound || !isPlainObject(result))
95
206
  return result;
96
207
  // Reuse the session resolved above so the health envelope describes the SAME session the handler
@@ -112,4 +223,3 @@ export async function runTool(tool, deps, args) {
112
223
  envelope['session_age_warning'] = warning;
113
224
  return Object.keys(envelope).length > 0 ? { ...result, ...envelope } : result;
114
225
  }
115
- //# sourceMappingURL=invoke-tool.js.map
@@ -44,4 +44,3 @@ export declare function acquireLeasedSession(pool: {
44
44
  }>;
45
45
  export declare function waitForLeasedSession(isConnected: () => boolean, sleeper?: (ms: number) => Promise<void>, attempts?: number, pollMs?: number): Promise<boolean>;
46
46
  export declare const LEASE_TOOLS: ToolDef[];
47
- //# sourceMappingURL=lease-tools.d.ts.map