@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
package/dist/cli-parse.js CHANGED
@@ -21,6 +21,9 @@ export const CLI_USAGE = `usage:
21
21
  reticle rollback (restore the previous server version and restart)
22
22
  reticle license (show enterprise license status: active | eval | missing)
23
23
  reticle telemetry [status|enable|disable] (anonymous usage metrics — status shows what's sent + the policy)
24
+ reticle feedback [--rating 1-5] [--bug] "message" (tell us what worked and what didn't — prints exactly what it sends)
25
+ reticle identify --context company|side_project|open_source|learning [--company N] [--email E] [--forget]
26
+ (OPT-IN: tell us who you are, e.g. for support or an enterprise trial)
24
27
 
25
28
  Cloud (link this project to Reticle Cloud — runs/flows recorded on the dashboard):
26
29
  reticle login --email <e> [--code <c>] [--org <n>] (sign in: mails a code, then exchanges it)
@@ -38,6 +41,7 @@ const OPEN_COMMAND = 'open';
38
41
  const DRIVE_COMMAND = 'drive';
39
42
  const VERIFY_COMMAND = 'verify';
40
43
  const AFFECTED_COMMAND = 'affected';
44
+ const HUNT_COMMAND = 'hunt';
41
45
  const CAPSULES_COMMAND = 'capsules';
42
46
  const GATE_COMMAND = 'gate';
43
47
  const WATCH_COMMAND = 'watch';
@@ -47,6 +51,15 @@ const MCP_COMMAND = 'mcp';
47
51
  const LICENSE_COMMAND = 'license';
48
52
  const VERSION_COMMAND = 'version';
49
53
  const TELEMETRY_COMMAND = 'telemetry';
54
+ const FEEDBACK_COMMAND = 'feedback';
55
+ const IDENTIFY_COMMAND = 'identify';
56
+ export const COMPANY_FLAG = '--company';
57
+ export const EMAIL_FLAG = '--email';
58
+ export const CONTEXT_FLAG = '--context';
59
+ export const FORGET_FLAG = '--forget';
60
+ /** `reticle feedback --rating 4 "the words"` — the human half of the channel. */
61
+ export const RATING_FLAG = '--rating';
62
+ export const BUG_FLAG = '--bug';
50
63
  /** The `reticle telemetry` sub-actions. Bare `reticle telemetry` means `status`. */
51
64
  export const TelemetryAction = {
52
65
  STATUS: 'status',
@@ -54,6 +67,58 @@ export const TelemetryAction = {
54
67
  DISABLE: 'disable',
55
68
  };
56
69
  export const DAEMON_INNER_COMMAND = '_daemon';
70
+ /**
71
+ * Every subcommand a person can type, as one closed vocabulary. Telemetry reports which one ran, and
72
+ * this is what keeps that property low-cardinality and non-identifying: an argument we do not
73
+ * recognize reports as `unknown` rather than being echoed, so a typo — which may be a path, a URL, or
74
+ * a flow name — can never reach the wire just because someone misspelled `status`.
75
+ *
76
+ * Lives here rather than in the telemetry module because this is where the command names are already
77
+ * defined; a second list somewhere else would drift the first time a command is added.
78
+ */
79
+ export const UNKNOWN_COMMAND = 'unknown';
80
+ const KNOWN_COMMANDS = new Set([
81
+ INIT_COMMAND,
82
+ SERVE_COMMAND,
83
+ STOP_COMMAND,
84
+ STATUS_COMMAND,
85
+ OPEN_COMMAND,
86
+ DRIVE_COMMAND,
87
+ VERIFY_COMMAND,
88
+ AFFECTED_COMMAND,
89
+ HUNT_COMMAND,
90
+ CAPSULES_COMMAND,
91
+ GATE_COMMAND,
92
+ WATCH_COMMAND,
93
+ UPDATE_COMMAND,
94
+ ROLLBACK_COMMAND,
95
+ MCP_COMMAND,
96
+ LICENSE_COMMAND,
97
+ VERSION_COMMAND,
98
+ TELEMETRY_COMMAND,
99
+ FEEDBACK_COMMAND,
100
+ IDENTIFY_COMMAND,
101
+ DAEMON_INNER_COMMAND,
102
+ // Cloud subcommands dispatch before the local parser but are still commands a human ran.
103
+ 'login',
104
+ 'logout',
105
+ 'whoami',
106
+ 'link',
107
+ 'project',
108
+ 'config',
109
+ 'push',
110
+ 'runs',
111
+ 'regression',
112
+ 'share',
113
+ 'doctor',
114
+ 'help',
115
+ ]);
116
+ /** The subcommand name if we recognize it, else `unknown`. Bare `reticle` reports `help`. */
117
+ export function knownCommand(arg) {
118
+ if (arg === undefined || arg === '')
119
+ return 'help';
120
+ return KNOWN_COMMANDS.has(arg) ? arg : UNKNOWN_COMMAND;
121
+ }
57
122
  export const HEADED_FLAG = '--headed';
58
123
  export const PORT_FLAG = '--port';
59
124
  export const DRIVE_FLAG = '--drive';
@@ -328,6 +393,42 @@ export function parseCliArgs(argv, defaultPort) {
328
393
  }
329
394
  return { kind: 'telemetry', action };
330
395
  }
396
+ case IDENTIFY_COMMAND: {
397
+ const flag = (name) => {
398
+ const at = rest.indexOf(name);
399
+ return at === -1 ? undefined : rest[at + 1];
400
+ };
401
+ const context = flag(CONTEXT_FLAG);
402
+ const company = flag(COMPANY_FLAG);
403
+ const email = flag(EMAIL_FLAG);
404
+ return {
405
+ kind: 'identify',
406
+ ...(context !== undefined ? { context } : {}),
407
+ ...(company !== undefined ? { company } : {}),
408
+ ...(email !== undefined ? { email } : {}),
409
+ forget: rest.includes(FORGET_FLAG),
410
+ };
411
+ }
412
+ case FEEDBACK_COMMAND: {
413
+ const ratingAt = rest.indexOf(RATING_FLAG);
414
+ const rating = ratingAt === -1 ? undefined : Number(rest[ratingAt + 1]);
415
+ if (rating !== undefined && (!Number.isInteger(rating) || rating < 1 || rating > 5)) {
416
+ return { kind: 'error', message: `${RATING_FLAG} takes a whole number from 1 to 5` };
417
+ }
418
+ // Everything that is not a flag or the rating's value is the message. Quoting is the user's
419
+ // job for shell reasons, but joining the remainder means an unquoted sentence still works.
420
+ const consumed = new Set(ratingAt === -1 ? [] : [ratingAt, ratingAt + 1]);
421
+ const text = rest
422
+ .filter((arg, i) => !consumed.has(i) && !arg.startsWith('--'))
423
+ .join(' ')
424
+ .trim();
425
+ return {
426
+ kind: 'feedback',
427
+ text,
428
+ ...(rating !== undefined ? { rating } : {}),
429
+ bug: rest.includes(BUG_FLAG),
430
+ };
431
+ }
331
432
  case OPEN_COMMAND: {
332
433
  const port = parsePortFlag(rest, defaultPort);
333
434
  // The first non-flag arg is the url (optional — omitting reuses a connected tab).
@@ -368,6 +469,12 @@ export function parseCliArgs(argv, defaultPort) {
368
469
  }
369
470
  case CAPSULES_COMMAND:
370
471
  return { kind: 'capsules' };
472
+ case HUNT_COMMAND: {
473
+ const dir = rest.find((a) => !a.startsWith('-'));
474
+ return dir === undefined
475
+ ? { kind: 'error', message: 'usage: reticle hunt <dir-of-crawl-reports>' }
476
+ : { kind: 'hunt', dir };
477
+ }
371
478
  case AFFECTED_COMMAND: {
372
479
  const t = parseTargetArgs(rest);
373
480
  if (t.files.length === 0 && t.since === undefined) {
@@ -413,4 +520,3 @@ export function parseCliArgs(argv, defaultPort) {
413
520
  return { kind: 'error', message: CLI_USAGE };
414
521
  }
415
522
  }
416
- //# sourceMappingURL=cli-parse.js.map
@@ -29,4 +29,3 @@ export declare function readJournalEnabled(cwd: string, env: string | undefined)
29
29
  * Pass `portFlag` when the user explicitly supplied --port; pass `undefined` to fall through.
30
30
  */
31
31
  export declare function resolvePort(portFlag: number | undefined, envPort: number | undefined, projectPort: number | undefined, defaultPort: number): number;
32
- //# sourceMappingURL=cli-port.d.ts.map
package/dist/cli-port.js CHANGED
@@ -80,4 +80,3 @@ export function readJournalEnabled(cwd, env) {
80
80
  export function resolvePort(portFlag, envPort, projectPort, defaultPort) {
81
81
  return portFlag ?? envPort ?? projectPort ?? defaultPort;
82
82
  }
83
- //# sourceMappingURL=cli-port.js.map
@@ -45,4 +45,3 @@ export declare function handleVerify(parsed: {
45
45
  port?: number;
46
46
  }): void;
47
47
  export {};
48
- //# sourceMappingURL=cli-verify.d.ts.map
@@ -34,7 +34,7 @@ const MSG_NO_SESSION = 'No app connected — Reticle drove the URL but no @retic
34
34
  ' Make sure the SDK is in the build and reticle.connect() runs on the preview page' +
35
35
  ' (for a non-localhost preview: allowNonLocalhost + a pairing token).';
36
36
  const MSG_NO_FLOWS = 'No saved flows to verify (.reticle/flows is empty) — refusing to report a pass for verifying nothing.\n' +
37
- ' Flows are recorded interactively by an agent (reticle_record_start → act → reticle_flow_save via the\n' +
37
+ ' Flows are recorded interactively by an agent (reticle_record{action:"start"} → act → reticle_flow_save via the\n' +
38
38
  ' MCP tools), then committed to .reticle/flows/. In CI, check those files in and re-run `reticle verify`.';
39
39
  const MSG_VERIFY_PREFIX = 'verify failed: ';
40
40
  function errMessage(error) {
@@ -219,4 +219,3 @@ export function handleVerify(parsed) {
219
219
  };
220
220
  void runVerify({ url: parsed.url, timeoutMs: parsed.timeoutMs ?? DEFAULT_SESSION_TIMEOUT_MS }, ports);
221
221
  }
222
- //# sourceMappingURL=cli-verify.js.map
package/dist/cli.d.ts CHANGED
@@ -2,4 +2,3 @@
2
2
  import { parseCliArgs, CLI_USAGE } from './cli-parse.js';
3
3
  export { parseCliArgs, CLI_USAGE };
4
4
  export type { CliResult } from './cli-parse.js';
5
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.js CHANGED
@@ -1,9 +1,10 @@
1
1
  #!/usr/bin/env node
2
2
  import { pathToFileURL } from 'node:url';
3
- import { realpathSync, existsSync } from 'node:fs';
3
+ import { realpathSync } from 'node:fs';
4
4
  import { join } from 'node:path';
5
5
  import { handleWatch, handleCapsules, handleGate, loadNamedFlows, resolveChangedFiles, } from './cli-flow-commands.js';
6
6
  import { RETICLE_DEFAULT_PORT, ReticleDir, ReticleEnv } from '@reticlehq/core';
7
+ import { loadDotEnv } from './telemetry/dev-repo.js';
7
8
  import { createNodeFileSystem } from './project/fs-port.js';
8
9
  import { affectedSavedFlows } from './flows/flow-sources.js';
9
10
  import { checkForUpdate } from './update/update-checker.js';
@@ -11,7 +12,6 @@ import { applyUpdate, rollback } from './update/updater.js';
11
12
  import { start, startDaemon } from './index.js';
12
13
  import { isCloudCommand, runCloudCommand } from './cloud-cli.js';
13
14
  import { SERVER_VERSION } from './server-version.js';
14
- import { getTelemetry, TelemetryEventKind, describeTelemetry, setTelemetryEnabled, } from './telemetry/telemetry.js';
15
15
  import { log } from './log.js';
16
16
  import { readPid, isAlive, isRunning, removePid, spawnDaemon, discoverDaemonPort, writeDaemonRegistry, } from './daemon.js';
17
17
  import { waitForDaemon, startMcpProxy, probeDaemon } from './mcp-proxy.js';
@@ -19,11 +19,16 @@ import { installDaemonResilience } from './daemon-resilience.js';
19
19
  import { IdleShutdown, resolveIdleShutdownMs } from './idle-shutdown.js';
20
20
  import { fetchStatus, summarizeStatus, decideOpen, openInBrowser } from './cli-launch.js';
21
21
  import { handleVerify } from './cli-verify.js';
22
+ import { summarizeHunt } from './hunt/hunt-report.js';
22
23
  import { runInit } from './init/run.js';
24
+ import { handleDoctor } from './cli-doctor.js';
23
25
  import { buildNodeIo } from './init/node-io.js';
24
26
  import { describeLicense } from './license/license.js';
25
27
  import { readProjectPort, readProjectId } from './cli-port.js';
26
- import { DAEMON_INNER_COMMAND, PORT_FLAG, DRIVE_FLAG, HEADED_FLAG, HTTP_FLAG, HTTP_PORT_FLAG, HTTP_TOKEN_FLAG, parseCliArgs, CLI_USAGE, TelemetryAction, } from './cli-parse.js';
28
+ import { DAEMON_INNER_COMMAND, PORT_FLAG, DRIVE_FLAG, HEADED_FLAG, HTTP_FLAG, HTTP_PORT_FLAG, HTTP_TOKEN_FLAG, parseCliArgs, CLI_USAGE, } from './cli-parse.js';
29
+ import { handleFeedback, handleIdentify, handleTelemetry } from './telemetry/feedback-cli.js';
30
+ import { installDaemonTelemetry } from './telemetry/daemon-telemetry.js';
31
+ import { reportCliRun } from './telemetry/cli-telemetry.js';
27
32
  // Re-exported so existing imports (and the CLI tests) keep resolving from './cli.js'.
28
33
  export { parseCliArgs, CLI_USAGE };
29
34
  function handleInit(parsed) {
@@ -100,36 +105,6 @@ function handleStatus(port) {
100
105
  log('reticle_status', { port, running: true, pid, ...summarizeStatus(payload) });
101
106
  });
102
107
  }
103
- /**
104
- * `reticle doctor` — collapse the ~6 independent first-run failure modes into one command. Checks the
105
- * Chromium install (the #1 silent failure), whether a daemon is up on the resolved bridge port, and
106
- * reminds the user which port the app must dial. Human-readable to stdout (not the JSON log).
107
- */
108
- async function handleDoctor(port) {
109
- const line = (s) => {
110
- process.stdout.write(`${s}\n`);
111
- };
112
- line('reticle doctor');
113
- line(` node ${process.version}`);
114
- try {
115
- const { chromium } = await import('playwright');
116
- const path = chromium.executablePath();
117
- line(existsSync(path)
118
- ? ' chromium ✓ installed'
119
- : ' chromium ✗ missing — run: npx playwright install chromium');
120
- }
121
- catch {
122
- line(' chromium ✗ missing — run: npx playwright install chromium');
123
- }
124
- const pid = readPid(port);
125
- if (pid !== null && isAlive(pid)) {
126
- line(` daemon ✓ running on :${port} (pid ${pid})`);
127
- }
128
- else {
129
- line(` daemon ✗ not running on :${port} — your agent runs \`reticle mcp\` (or \`reticle serve\`)`);
130
- }
131
- line(` bridge port ${port} (your app must dial THIS port — not your dev-server port)`);
132
- }
133
108
  /** Print the running package version (resolved once in server-version.ts). */
134
109
  function handleVersion() {
135
110
  log('reticle_version', { version: SERVER_VERSION });
@@ -138,24 +113,6 @@ function handleVersion() {
138
113
  function handleLicense() {
139
114
  log('reticle_license', { ...describeLicense(Date.now()) });
140
115
  }
141
- /**
142
- * `reticle telemetry [status|enable|disable]` — the user-facing control for anonymous usage metrics.
143
- * `disable` persists a machine-wide opt-out (survives shells, unlike RETICLE_TELEMETRY=0); `status`
144
- * says what's on, why, and where the full policy lives. Human-readable to stdout, like `doctor`.
145
- */
146
- function handleTelemetry(action) {
147
- const line = (s) => {
148
- process.stdout.write(`${s}\n`);
149
- };
150
- if (action !== TelemetryAction.STATUS) {
151
- setTelemetryEnabled(action === TelemetryAction.ENABLE);
152
- }
153
- const state = describeTelemetry();
154
- line(`telemetry ${state.enabled ? 'enabled' : 'disabled'} (${state.reason})`);
155
- line(`policy ${state.policyUrl}`);
156
- if (state.enabled)
157
- line('opt out reticle telemetry disable (or RETICLE_TELEMETRY=0 / DO_NOT_TRACK=1)');
158
- }
159
116
  /**
160
117
  * `reticle affected <file...>` — print which saved flows must re-verify for the given changed files.
161
118
  * Environment-side (costs the agent nothing per turn); the foundation of watch/gate. Never throws:
@@ -179,6 +136,42 @@ async function handleAffected(files, since) {
179
136
  });
180
137
  }
181
138
  }
139
+ /**
140
+ * `reticle hunt <dir>` — aggregate crawl reports from many checkouts into one number.
141
+ *
142
+ * Detection already exists (`reticle_crawl`). This is the arithmetic that turns a pile of runs into
143
+ * the claim worth making: over N already-merged, already-green changes, how many carried a candidate
144
+ * false green? No control arm is needed, because those changes SHIPPED — the counterfactual is
145
+ * already established, which is what makes this the cheapest credible evidence available.
146
+ *
147
+ * Each file in <dir> is one crawl result. Producing them is a shell loop over a commit range:
148
+ * check out, boot the app, `reticle_crawl`, write the JSON here.
149
+ */
150
+ async function handleHunt(dir) {
151
+ try {
152
+ const fs = createNodeFileSystem();
153
+ const names = await fs.readdir(dir);
154
+ const runs = [];
155
+ for (const name of names.filter((n) => n.endsWith('.json'))) {
156
+ const raw = await fs.readFile(join(dir, name));
157
+ if (raw === undefined)
158
+ continue;
159
+ const parsed = JSON.parse(raw);
160
+ const report = parsed;
161
+ runs.push({
162
+ label: report.label ?? name.replace(/\.json$/, ''),
163
+ anomalies: report.anomalies ?? [],
164
+ ...(report.stepsRun === undefined ? {} : { stepsRun: report.stepsRun }),
165
+ });
166
+ }
167
+ log('reticle_hunt', { ...summarizeHunt(runs) });
168
+ }
169
+ catch (error) {
170
+ log('reticle_hunt_failed', {
171
+ error: error instanceof Error ? error.message : String(error),
172
+ });
173
+ }
174
+ }
182
175
  /** `reticle update` — install the latest server version and restart (moved off the MCP surface). */
183
176
  async function handleUpdate() {
184
177
  try {
@@ -237,7 +230,11 @@ function handleOpen(requestedPort, url) {
237
230
  const { sessions } = summarizeStatus(await fetchStatus(port));
238
231
  const decision = decideOpen(sessions, url);
239
232
  if (decision.action === 'need-url') {
240
- log('reticle_open', { port, error: 'no app connected — pass a url: reticle open <url>' });
233
+ log('reticle_open', {
234
+ port,
235
+ error: 'no app connected — pass a url: reticle open <url>. Desktop app (Electron/Tauri)? ' +
236
+ 'There is no url to open: start it as you normally would and it connects to this bridge itself.',
237
+ });
241
238
  return;
242
239
  }
243
240
  if (decision.action === 'reuse') {
@@ -269,10 +266,9 @@ function handleDaemonInner(parsed) {
269
266
  startDaemon(options)
270
267
  .then((server) => {
271
268
  log('reticle_daemon_ready', { port: parsed.port, pid: process.pid });
272
- // A live daemon IS an active session (the numerator of "active sessions" + DAU/WAU/MAU). Pair the
273
- // START here with an END (carrying duration) on any clean shutdown below — best-effort, non-blocking.
274
- const sessionStartedAt = Date.now();
275
- void getTelemetry().emit(TelemetryEventKind.SESSION_START);
269
+ // Daemon lifecycle telemetry: started, a one-shot project profile, the periodic counter flush,
270
+ // and the rich summary on shutdown. All of it lives in one module — see daemon-telemetry.ts.
271
+ const daemonTelemetry = installDaemonTelemetry(process.cwd());
276
272
  // Publish to the discovery registry so a build plugin can find this daemon by projectId — no
277
273
  // hand-reconciled port. Written from the child (only it knows its cwd); removePid drops it.
278
274
  const registryProjectId = readProjectId(process.cwd());
@@ -289,11 +285,12 @@ function handleDaemonInner(parsed) {
289
285
  process.exit(1);
290
286
  });
291
287
  const shutdown = () => {
292
- void getTelemetry().emit(TelemetryEventKind.SESSION_END, {
293
- sessionMs: Date.now() - sessionStartedAt,
294
- });
295
- server
296
- .close()
288
+ // Awaited before the close/exit chain: `process.exit(0)` kills an in-flight POST, and this is
289
+ // the one event carrying the whole session. A failed send resolves anyway (emit swallows its
290
+ // own errors), so this can delay the exit by at most the send timeout, never prevent it.
291
+ void daemonTelemetry
292
+ .shutdown()
293
+ .then(() => server.close())
297
294
  .then(() => {
298
295
  removePid(parsed.port);
299
296
  process.exit(0);
@@ -392,14 +389,21 @@ function handleLegacyDrive(parsed) {
392
389
  });
393
390
  }
394
391
  function main() {
392
+ // Before anything reads process.env — notably the telemetry gate and the bridge's security
393
+ // options — fold in a project-local `.env`. Values already in the environment always win.
394
+ loadDotEnv(process.cwd());
395
395
  const argv = process.argv.slice(2);
396
396
  // Every invocation passes through here — the single chokepoint for the "how often is it used / how
397
397
  // many distinct machines + projects" metrics. Fire-and-forget: a metric must never delay or fail a run.
398
- const telemetry = getTelemetry();
399
- // `detach` so a quick command (`version`/`gate`) exits immediately instead of waiting out the POST.
400
- if (telemetry.firstRun)
401
- void telemetry.emit(TelemetryEventKind.INSTALL, { detach: true });
402
- void telemetry.emit(TelemetryEventKind.INVOKE, { detach: true });
398
+ //
399
+ // `_daemon` is EXCLUDED, and that exclusion is the whole point of this branch. `reticle mcp` and
400
+ // `reticle serve` start the daemon by re-running this very binary, so the child re-entered main()
401
+ // and emitted a second event for what a person experienced as one action. The old `invoke` metric
402
+ // was therefore inflated ~2x — and inflated worst on the agent-driven sessions that matter most,
403
+ // while one-shot commands like `version` counted once. That skewed the RATIO between commands, not
404
+ // just the scale, which is the kind of error you cannot correct for after the fact. The daemon's
405
+ // own lifecycle is already reported by `daemon_started` / `daemon_stopped`; it is not a CLI run.
406
+ reportCliRun(argv);
403
407
  // Cloud subcommands (login/link/project/config/push) are a distinct family with their own async client;
404
408
  // handle them before the local typed parser so `reticle login` etc. work as one tool.
405
409
  if (isCloudCommand(argv[0])) {
@@ -434,6 +438,12 @@ function main() {
434
438
  case 'telemetry':
435
439
  handleTelemetry(parsed.action);
436
440
  break;
441
+ case 'feedback':
442
+ void handleFeedback(parsed.text, parsed.rating, parsed.bug);
443
+ break;
444
+ case 'identify':
445
+ void handleIdentify(parsed);
446
+ break;
437
447
  case 'version':
438
448
  handleVersion();
439
449
  break;
@@ -458,6 +468,9 @@ function main() {
458
468
  case 'affected':
459
469
  void handleAffected(parsed.files, parsed.since);
460
470
  break;
471
+ case 'hunt':
472
+ void handleHunt(parsed.dir);
473
+ break;
461
474
  case 'gate':
462
475
  void handleGate(parsed.files, parsed.since);
463
476
  break;
@@ -500,4 +513,3 @@ function isEntryPoint() {
500
513
  if (isEntryPoint()) {
501
514
  main();
502
515
  }
503
- //# sourceMappingURL=cli.js.map
@@ -34,4 +34,3 @@ export interface ProjectCloud {
34
34
  * so the single-project / CI flow is unchanged. `homeDir` is injected (testable; `os.homedir()` at call).
35
35
  */
36
36
  export declare function resolveProjectCloud(fs: FileSystemPort, reticleRoot: string, homeDir: string, env: NodeJS.ProcessEnv): Promise<ProjectCloud>;
37
- //# sourceMappingURL=cloud-config.d.ts.map
@@ -84,4 +84,3 @@ export async function resolveProjectCloud(fs, reticleRoot, homeDir, env) {
84
84
  const config = key !== null ? { url: link.url.replace(/\/+$/, ''), apiKey: key } : null;
85
85
  return { config, policy, verify: link.verify, projectId: link.projectId };
86
86
  }
87
- //# sourceMappingURL=cloud-config.js.map
@@ -110,20 +110,20 @@ declare const ServerVerificationSchema: z.ZodObject<{
110
110
  }>, "many">;
111
111
  summary: z.ZodString;
112
112
  }, "strip", z.ZodTypeAny, {
113
- verificationId: string;
114
- verdict: string | null;
115
113
  flows: {
116
114
  status: string;
117
115
  name: string;
118
116
  }[];
119
- summary: string;
120
- }, {
121
117
  verificationId: string;
122
118
  verdict: string | null;
119
+ summary: string;
120
+ }, {
123
121
  flows: {
124
122
  status: string;
125
123
  name: string;
126
124
  }[];
125
+ verificationId: string;
126
+ verdict: string | null;
127
127
  summary: string;
128
128
  }>;
129
129
  export type ServerVerification = z.infer<typeof ServerVerificationSchema>;
@@ -140,4 +140,3 @@ export declare function submitServerVerification(body: {
140
140
  source: string;
141
141
  }, config: CloudConfig | null, fetchImpl: FetchPostJsonLike): Promise<ServerVerification | null>;
142
142
  export {};
143
- //# sourceMappingURL=cloud-sync.d.ts.map
@@ -173,4 +173,3 @@ export async function submitServerVerification(body, config, fetchImpl) {
173
173
  return null;
174
174
  }
175
175
  }
176
- //# sourceMappingURL=cloud-sync.js.map
@@ -1,4 +1,3 @@
1
1
  export declare const isCloudCommand: (cmd: string | undefined) => boolean;
2
2
  /** Dispatch a cloud subcommand. Returns the process exit code. */
3
3
  export declare const runCloudCommand: (argv: readonly string[]) => Promise<number>;
4
- //# sourceMappingURL=cloud-cli.d.ts.map
package/dist/cloud-cli.js CHANGED
@@ -102,7 +102,15 @@ const api = async (method, url, token, body) => {
102
102
  init.body = JSON.stringify(body);
103
103
  const res = await fetch(url, init);
104
104
  const text = await res.text();
105
- const json = text.length > 0 ? JSON.parse(text) : null;
105
+ let json = null;
106
+ if (text.length > 0) {
107
+ try {
108
+ json = JSON.parse(text);
109
+ }
110
+ catch {
111
+ throw new Error(`expected JSON from ${method} ${url} but got: ${text.slice(0, 120)}`);
112
+ }
113
+ }
106
114
  if (!res.ok) {
107
115
  const parsed = z.object({ error: z.object({ message: z.string() }) }).safeParse(json);
108
116
  throw new Error(parsed.success ? parsed.data.error.message : `${res.status} ${res.statusText}`);
@@ -504,4 +512,3 @@ export const runCloudCommand = async (argv) => {
504
512
  return 1;
505
513
  }
506
514
  };
507
- //# sourceMappingURL=cloud-cli.js.map
@@ -5,4 +5,3 @@ import type { ToolDef } from '../tools/tools.js';
5
5
  * it drives the app — so it's an explicit, bounded tool, never part of a passive read.
6
6
  */
7
7
  export declare const CRAWL_TOOLS: ToolDef[];
8
- //# sourceMappingURL=crawl-tools.d.ts.map
@@ -11,7 +11,7 @@ const nodeSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
11
11
  export const CRAWL_TOOLS = [
12
12
  {
13
13
  name: ReticleTool.CRAWL,
14
- description: 'Autonomously click every reachable interactive control (bounded by maxSteps, default 25) and report anomalies WITHOUT a script: console errors, failed requests (status ≥ 400), and DEAD controls (dispatched but the app did nothing). DESTRUCTIVE — it really clicks (may navigate/mutate state); use reticle_explore first for a non-destructive list. Returns { interactiveFound, stepsRun, anomalies[{kind,ref,desc,detail}], counts, visited, truncated }.',
14
+ description: 'Autonomously click every reachable interactive control (bounded by maxSteps, default 25) and report anomalies WITHOUT a script. Two classes: single-channel faults (console errors, failed requests ≥400, DEAD controls that dispatched but did nothing) and CONTRADICTIONS — two channels disagreeing about the same click, e.g. the UI advanced while its write failed, a success signal fired over a failed request, a write succeeded and nothing changed, the same write fired twice, or the UI moved on over an in-flight request. Contradictions are the false greens a human cannot see, because a human watches one channel (the screen) and it looks correct. DESTRUCTIVE — it really clicks (may navigate/mutate state); use reticle_explore first for a non-destructive list. Returns { interactiveFound, stepsRun, anomalies[{kind,ref,desc,detail}], counts, visited, truncated }.',
15
15
  inputSchema: {
16
16
  maxSteps: z.number().optional().describe('Maximum number of controls to click. Default: 25.'),
17
17
  settleMs: z
@@ -70,4 +70,3 @@ export const CRAWL_TOOLS = [
70
70
  },
71
71
  },
72
72
  ];
73
- //# sourceMappingURL=crawl-tools.js.map
@@ -1,4 +1,4 @@
1
- import { CrawlAnomalyKind, type CommandResult, type ReticleEvent } from '@reticlehq/core';
1
+ import { CrawlAnomalyKind, ContradictionKind, type CommandResult, type ReticleEvent } from '@reticlehq/core';
2
2
  /** The slice of Session the crawler needs — so tests inject a fake without a live browser. */
3
3
  export interface CrawlSession {
4
4
  command(name: string, args?: Record<string, unknown>): Promise<CommandResult>;
@@ -16,7 +16,13 @@ export interface CrawlSession {
16
16
  }
17
17
  type CrawlSleep = (ms: number) => Promise<void>;
18
18
  export interface CrawlAnomaly {
19
- kind: CrawlAnomalyKind;
19
+ /**
20
+ * A single-channel fault (something bad in one stream) or a CONTRADICTION (two channels
21
+ * disagreeing about the same click). The second kind is why an autonomous crawl is worth more
22
+ * than a human clicking the same buttons: a person sees only the screen, so a UI that advanced
23
+ * while its write failed looks like success to them and always will.
24
+ */
25
+ kind: CrawlAnomalyKind | ContradictionKind;
20
26
  /** The control that triggered it. */
21
27
  ref: string;
22
28
  desc: string;
@@ -41,6 +47,7 @@ export interface CrawlReport {
41
47
  consoleErrors: number;
42
48
  failedRequests: number;
43
49
  deadControls: number;
50
+ contradictions: number;
44
51
  };
45
52
  /** Descriptions of the controls actually clicked. */
46
53
  visited: string[];
@@ -62,6 +69,13 @@ export interface CrawlOptions {
62
69
  * orchestration over a CrawlSession: no browser/Node imports, fully unit-testable with a fake.
63
70
  * Single-pass by design (no re-discovery) so it always terminates and never explodes on navigation.
64
71
  */
72
+ /**
73
+ * Controls whose correct behaviour IS to do nothing when clicked.
74
+ *
75
+ * Read off the same descriptor the crawler already has, so no extra round trip: `[disabled]` is inert
76
+ * by definition, an already `[checked]` radio/checkbox is idempotent, and clicking a text field
77
+ * focuses it rather than changing anything.
78
+ */
79
+ export declare function legitimatelyInert(desc: string): boolean;
65
80
  export declare function crawl(session: CrawlSession, opts: CrawlOptions, sleep: CrawlSleep): Promise<CrawlReport>;
66
81
  export {};
67
- //# sourceMappingURL=crawl.d.ts.map
@@ -1,6 +1,7 @@
1
- import { ActionType, CRAWL_DEFAULTS, CrawlAnomalyKind, DANGEROUS_ACTION_CONFIRM_ARG, EventType, ReticleCommand, } from '@reticlehq/core';
1
+ import { ActionType, CRAWL_DEFAULTS, CrawlAnomalyKind, ContradictionKind, DANGEROUS_ACTION_CONFIRM_ARG, EventType, ReticleCommand, } from '@reticlehq/core';
2
2
  import { parseInteractive, asRecord, asNumber, asString, sourceOf, } from '../tools/tools-helpers.js';
3
3
  import { ReticleTool } from '../tools/tool-names.js';
4
+ import { findContradictions } from '../events/contradictions.js';
4
5
  /** Said out loud when the page was larger than one snapshot, so a clean sweep cannot mean "all clear". */
5
6
  export const CAPPED_SNAPSHOT_NOTE = 'the page exceeded one snapshot, so controls past the cap were never seen — interactiveFound is a floor, not a total; re-run with a narrower `scope` to cover the rest';
6
7
  /** Any buffer event that proves the app reacted to a click (vs a dead/no-op control). */
@@ -33,6 +34,20 @@ function failedRequests(events, floor) {
33
34
  * orchestration over a CrawlSession: no browser/Node imports, fully unit-testable with a fake.
34
35
  * Single-pass by design (no re-discovery) so it always terminates and never explodes on navigation.
35
36
  */
37
+ /**
38
+ * Controls whose correct behaviour IS to do nothing when clicked.
39
+ *
40
+ * Read off the same descriptor the crawler already has, so no extra round trip: `[disabled]` is inert
41
+ * by definition, an already `[checked]` radio/checkbox is idempotent, and clicking a text field
42
+ * focuses it rather than changing anything.
43
+ */
44
+ export function legitimatelyInert(desc) {
45
+ if (desc.includes('[disabled]'))
46
+ return true;
47
+ if (desc.includes('[checked]'))
48
+ return true;
49
+ return /\b(textbox|searchbox|combobox|spinbutton)\b/.test(desc);
50
+ }
36
51
  export async function crawl(session, opts, sleep) {
37
52
  const maxSteps = opts.maxSteps ?? CRAWL_DEFAULTS.MAX_STEPS;
38
53
  const settleMs = opts.settleMs ?? CRAWL_DEFAULTS.SETTLE_MS;
@@ -50,7 +65,7 @@ export async function crawl(session, opts, sleep) {
50
65
  const coverageCapped = snapshot.truncated === true;
51
66
  const anomalies = [];
52
67
  const visited = [];
53
- const counts = { consoleErrors: 0, failedRequests: 0, deadControls: 0 };
68
+ const counts = { consoleErrors: 0, failedRequests: 0, deadControls: 0, contradictions: 0 };
54
69
  const seen = new Set();
55
70
  let stepsRun = 0;
56
71
  for (const item of items) {
@@ -107,9 +122,34 @@ export async function crawl(session, opts, sleep) {
107
122
  ...source,
108
123
  });
109
124
  }
125
+ // CONTRADICTIONS: the channels disagree about what this click did. Reported per control, so a
126
+ // crawl of an unknown app surfaces its false greens without anyone knowing where to look.
127
+ for (const c of findContradictions(events)) {
128
+ counts.contradictions += 1;
129
+ anomalies.push({
130
+ kind: c.kind,
131
+ ref: item.ref,
132
+ desc: item.desc,
133
+ detail: `${c.claim}, but ${c.counter} — ${c.detail}`,
134
+ ...source,
135
+ });
136
+ }
110
137
  // DEAD: the click dispatched but the app produced no activity and no error to explain it.
138
+ //
139
+ // Unless the control is SUPPOSED to be inert. Measured on a shipments console: every one of the
140
+ // crawler's three anomalies was a control behaving correctly — a `[disabled]` button, an already
141
+ // `[checked]` radio, and a text input (a click focuses it; mutating would be the surprise). An
142
+ // anomaly list that is 100% false on a real app is worse than no anomaly list, because the agent
143
+ // spends its budget disproving it and learns to skip the field.
144
+ //
145
+ // Deliberately NOT fixed by counting focus as activity: focus moving is not the app reacting, and
146
+ // treating it as such would make a genuinely dead button that takes focus look alive — trading
147
+ // noise for the false negative this check exists to catch.
111
148
  const dispatched = asRecord(act.result)['dispatched'] !== false && act.ok;
112
- if (dispatched && errs.length === 0 && !events.some(isActivity)) {
149
+ if (dispatched &&
150
+ errs.length === 0 &&
151
+ !events.some(isActivity) &&
152
+ !legitimatelyInert(item.desc)) {
113
153
  counts.deadControls += 1;
114
154
  anomalies.push({
115
155
  kind: CrawlAnomalyKind.DEAD_CONTROL,
@@ -133,4 +173,3 @@ export async function crawl(session, opts, sleep) {
133
173
  ...(coverageCapped ? { coverageNote: CAPPED_SNAPSHOT_NOTE } : {}),
134
174
  };
135
175
  }
136
- //# sourceMappingURL=crawl.js.map