@reticlehq/server 3.2.0 → 3.4.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 (437) hide show
  1. package/LICENSE-ENTERPRISE +1 -1
  2. package/README.md +3 -3
  3. package/SKILL.md +23 -22
  4. package/dist/chromium-launch-options.d.ts +4 -3
  5. package/dist/chromium-launch-options.js +6 -2
  6. package/dist/command/cli/adhoc-suite.d.ts +41 -0
  7. package/dist/command/cli/adhoc-suite.js +159 -0
  8. package/dist/command/cli/adhoc-verdict.d.ts +58 -2
  9. package/dist/command/cli/adhoc-verdict.js +108 -13
  10. package/dist/command/cli/answers/gate-hook-message.d.ts +6 -0
  11. package/dist/command/cli/answers/gate-hook-message.js +6 -0
  12. package/dist/command/cli/auth/cloud-keystore.d.ts +0 -2
  13. package/dist/command/cli/auth/cloud-keystore.js +0 -3
  14. package/dist/command/cli/auth/cloud-session.d.ts +4 -0
  15. package/dist/command/cli/auth/cloud-session.js +2 -0
  16. package/dist/command/cli/cli-doctor.js +30 -8
  17. package/dist/command/cli/cli-flow-commands.d.ts +3 -6
  18. package/dist/command/cli/cli-flow-commands.js +67 -4
  19. package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
  20. package/dist/command/cli/cli-parse-grammar.js +7 -0
  21. package/dist/command/cli/cli-parse-verify.d.ts +2 -5
  22. package/dist/command/cli/cli-parse-verify.js +86 -13
  23. package/dist/command/cli/cli-parse.d.ts +14 -1
  24. package/dist/command/cli/cli-parse.js +54 -8
  25. package/dist/command/cli/cli-update-commands.js +8 -1
  26. package/dist/command/cli/cli-verify.d.ts +80 -0
  27. package/dist/command/cli/cli-verify.js +181 -26
  28. package/dist/command/cli/cloud-cli.js +5 -2
  29. package/dist/command/cli/cloud-kit.d.ts +0 -2
  30. package/dist/command/cli/cloud-kit.js +3 -5
  31. package/dist/command/cli/cloud-login.js +21 -3
  32. package/dist/command/cli/demo/demo-page.js +6 -3
  33. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +5 -0
  34. package/dist/command/cli/doctor/browser/chromium-hint.js +5 -0
  35. package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
  36. package/dist/command/cli/launch/cli-launch.d.ts +9 -29
  37. package/dist/command/cli/launch/cli-launch.js +27 -49
  38. package/dist/command/cli/launch/sdk-version-match.d.ts +84 -0
  39. package/dist/command/cli/launch/sdk-version-match.js +206 -0
  40. package/dist/command/cli/lifecycle/daemon-lifecycle.js +2 -16
  41. package/dist/command/cli/ports/resolve/cli-port.d.ts +38 -0
  42. package/dist/command/cli/ports/resolve/cli-port.js +169 -15
  43. package/dist/command/cli/report-command.d.ts +16 -0
  44. package/dist/command/cli/report-command.js +97 -0
  45. package/dist/command/cli/setup-mcp-cli.js +13 -13
  46. package/dist/command/cli/tutorial.d.ts +2 -2
  47. package/dist/command/cli/tutorial.js +21 -7
  48. package/dist/command/cli.js +67 -10
  49. package/dist/command/daemon/binding/daemon-status-probe.d.ts +44 -2
  50. package/dist/command/daemon/binding/daemon-status-probe.js +79 -6
  51. package/dist/command/daemon/binding/port-presence.d.ts +1 -1
  52. package/dist/command/daemon/daemon-resolve.d.ts +9 -0
  53. package/dist/command/daemon/daemon-resolve.js +1 -1
  54. package/dist/command/daemon/idle-shutdown.d.ts +2 -1
  55. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +7 -1
  56. package/dist/command/daemon/lifetime/daemon-usefulness.js +30 -7
  57. package/dist/command/dev/stale-issue-guard.d.ts +3 -4
  58. package/dist/command/dev/stale-issue-guard.js +8 -8
  59. package/dist/command/setup/bringup/connect-lease.d.ts +17 -0
  60. package/dist/command/setup/bringup/connect-lease.js +38 -0
  61. package/dist/command/setup/bringup/dev-server-files.d.ts +68 -0
  62. package/dist/command/setup/bringup/dev-server-files.js +131 -0
  63. package/dist/command/setup/bringup/dev-server-log-cap.d.ts +35 -0
  64. package/dist/command/setup/bringup/dev-server-log-cap.js +121 -0
  65. package/dist/command/setup/bringup/ensure-daemon.d.ts +65 -4
  66. package/dist/command/setup/bringup/ensure-daemon.js +135 -16
  67. package/dist/command/setup/bringup/static-page-server.d.ts +35 -0
  68. package/dist/command/setup/bringup/static-page-server.js +151 -0
  69. package/dist/command/setup/desktop-shape.d.ts +4 -0
  70. package/dist/command/setup/desktop-shape.js +18 -2
  71. package/dist/command/setup/init/init-host.js +8 -0
  72. package/dist/command/setup/init/init-port.d.ts +15 -0
  73. package/dist/command/setup/init/init-port.js +44 -0
  74. package/dist/command/setup/init/init-runtime.d.ts +1 -1
  75. package/dist/command/setup/init/init-runtime.js +39 -2
  76. package/dist/command/setup/node-effects.d.ts +27 -14
  77. package/dist/command/setup/node-effects.js +80 -44
  78. package/dist/command/setup/probe/loopback-probe-urls.d.ts +7 -0
  79. package/dist/command/setup/probe/loopback-probe-urls.js +40 -0
  80. package/dist/command/setup/probe/page-probe.d.ts +13 -2
  81. package/dist/command/setup/probe/page-probe.js +18 -3
  82. package/dist/command/setup/run-setup.d.ts +26 -1
  83. package/dist/command/setup/run-setup.js +96 -13
  84. package/dist/command/setup/session-pick.d.ts +13 -0
  85. package/dist/command/setup/session-pick.js +20 -0
  86. package/dist/command/setup/setup-command.d.ts +2 -14
  87. package/dist/command/setup/setup-command.js +105 -31
  88. package/dist/command/setup/setup-mcp.js +3 -3
  89. package/dist/command/setup/terminal/wait-progress.d.ts +8 -0
  90. package/dist/command/setup/terminal/wait-progress.js +17 -0
  91. package/dist/features/crawl/crawl-empty.js +1 -1
  92. package/dist/features/crawl/crawl-tools.d.ts +6 -0
  93. package/dist/features/crawl/crawl-tools.js +57 -0
  94. package/dist/features/crawl/crawl.d.ts +2 -0
  95. package/dist/features/crawl/crawl.js +171 -156
  96. package/dist/features/exhaust/app-coverage.d.ts +33 -0
  97. package/dist/features/exhaust/app-coverage.js +31 -0
  98. package/dist/features/exhaust/code-coverage.d.ts +47 -0
  99. package/dist/features/exhaust/code-coverage.js +77 -0
  100. package/dist/features/exhaust/exhaust-run.d.ts +33 -0
  101. package/dist/features/exhaust/exhaust-run.js +82 -0
  102. package/dist/features/exhaust/explorer.d.ts +103 -0
  103. package/dist/features/exhaust/explorer.js +195 -0
  104. package/dist/features/exhaust/failure-branches.d.ts +33 -0
  105. package/dist/features/exhaust/failure-branches.js +92 -0
  106. package/dist/features/exhaust/ledger.d.ts +202 -0
  107. package/dist/features/exhaust/ledger.js +252 -0
  108. package/dist/features/exhaust/session-fold.d.ts +31 -0
  109. package/dist/features/exhaust/session-fold.js +79 -0
  110. package/dist/features/exhaust/session-port.d.ts +36 -0
  111. package/dist/features/exhaust/session-port.js +102 -0
  112. package/dist/features/harness/drive-report.d.ts +0 -9
  113. package/dist/features/harness/drive-report.js +18 -0
  114. package/dist/features/harness/driver.js +4 -7
  115. package/dist/features/harness/fill-values.d.ts +6 -0
  116. package/dist/features/harness/fill-values.js +3 -0
  117. package/dist/features/harness/jev-driver.js +36 -22
  118. package/dist/features/harness/openai-driver.js +4 -7
  119. package/dist/features/harness/platform-config.d.ts +10 -0
  120. package/dist/features/harness/platform-config.js +13 -6
  121. package/dist/index.d.ts +10 -1
  122. package/dist/index.js +78 -104
  123. package/dist/judgement/capsule/capsule-store.d.ts +31 -2
  124. package/dist/judgement/capsule/capsule-store.js +58 -6
  125. package/dist/judgement/capsule/capsule.js +5 -0
  126. package/dist/judgement/capsule/causal-summary.d.ts +13 -1
  127. package/dist/judgement/capsule/causal-summary.js +7 -0
  128. package/dist/judgement/domain/domain-model.js +40 -9
  129. package/dist/judgement/oracles/self-instrument.js +4 -2
  130. package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
  131. package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
  132. package/dist/judgement/runs/artifact/gap-report.js +46 -0
  133. package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
  134. package/dist/judgement/runs/artifact/gap-summary.js +85 -0
  135. package/dist/judgement/runs/artifact/render-report.js +4 -1
  136. package/dist/judgement/runs/artifact/replay-mapping.d.ts +2 -2
  137. package/dist/judgement/runs/artifact/replay-mapping.js +44 -9
  138. package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
  139. package/dist/judgement/runs/artifact/to-artifact.js +1 -1
  140. package/dist/judgement/runs/context-tools.js +21 -3
  141. package/dist/judgement/runs/drive-run.js +7 -2
  142. package/dist/judgement/runs/verification-sync.d.ts +3 -1
  143. package/dist/judgement/runs/verification-sync.js +1 -1
  144. package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
  145. package/dist/language/flows/annotate-notes/annotate.js +66 -18
  146. package/dist/language/flows/change/affected.d.ts +9 -0
  147. package/dist/language/flows/change/affected.js +35 -0
  148. package/dist/language/flows/change/gate.d.ts +20 -0
  149. package/dist/language/flows/change/gate.js +12 -1
  150. package/dist/language/flows/flow-anchor.d.ts +12 -0
  151. package/dist/language/flows/flow-anchor.js +20 -0
  152. package/dist/language/flows/flow-author.d.ts +7 -0
  153. package/dist/language/flows/flow-author.js +19 -0
  154. package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
  155. package/dist/language/flows/flow-expect-grammar.js +92 -11
  156. package/dist/language/flows/flow-intent.js +1 -1
  157. package/dist/language/flows/flow-journey.d.ts +54 -0
  158. package/dist/language/flows/flow-journey.js +119 -0
  159. package/dist/language/flows/flow-learning.d.ts +3 -0
  160. package/dist/language/flows/flow-learning.js +39 -8
  161. package/dist/language/flows/flow-replay-run.d.ts +33 -12
  162. package/dist/language/flows/flow-replay-run.js +131 -52
  163. package/dist/language/flows/flow-replay-types.d.ts +9 -0
  164. package/dist/language/flows/flow-replay.d.ts +27 -12
  165. package/dist/language/flows/flow-replay.js +127 -111
  166. package/dist/language/flows/flow-result.d.ts +2 -0
  167. package/dist/language/flows/flow-result.js +25 -0
  168. package/dist/language/flows/flow-step-runners.d.ts +26 -10
  169. package/dist/language/flows/flow-step-runners.js +20 -4
  170. package/dist/language/flows/flow-success.d.ts +21 -6
  171. package/dist/language/flows/flow-success.js +50 -138
  172. package/dist/language/flows/flow-tools.js +17 -5
  173. package/dist/language/flows/flows.d.ts +18 -5
  174. package/dist/language/flows/flows.js +101 -16
  175. package/dist/language/flows/heal.d.ts +9 -1
  176. package/dist/language/flows/heal.js +24 -2
  177. package/dist/language/flows/learned-sources.d.ts +21 -0
  178. package/dist/language/flows/learned-sources.js +84 -0
  179. package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
  180. package/dist/language/flows/recording/recording-backtrack.js +1 -1
  181. package/dist/language/flows/recording/replay-halt.d.ts +2 -1
  182. package/dist/language/flows/recording/replay-halt.js +3 -1
  183. package/dist/language/flows/recording/tape/recordings.d.ts +31 -2
  184. package/dist/language/flows/recording/tape/recordings.js +55 -1
  185. package/dist/language/flows/replay.d.ts +19 -0
  186. package/dist/language/flows/replay.js +53 -13
  187. package/dist/language/flows/stores/annotation-store.d.ts +5 -5
  188. package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
  189. package/dist/language/flows/stores/flake-store.js +2 -3
  190. package/dist/language/flows/suite/coverage.d.ts +1 -1
  191. package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
  192. package/dist/language/flows/verify-change-tools.js +19 -2
  193. package/dist/launch-chromium.d.ts +80 -0
  194. package/dist/launch-chromium.js +218 -0
  195. package/dist/memory/cloud/cloud-config.d.ts +11 -2
  196. package/dist/memory/cloud/cloud-config.js +47 -7
  197. package/dist/memory/cloud/cloud-sync.d.ts +4 -3
  198. package/dist/memory/cloud/cloud-sync.js +7 -10
  199. package/dist/memory/cloud/harness-config.d.ts +2 -0
  200. package/dist/memory/cloud/harness-offer.js +5 -6
  201. package/dist/memory/cloud/harness-switch.js +5 -6
  202. package/dist/memory/cloud/sync-cycle.d.ts +78 -1
  203. package/dist/memory/cloud/sync-cycle.js +321 -53
  204. package/dist/memory/cloud/sync-daemon.d.ts +13 -0
  205. package/dist/memory/cloud/sync-daemon.js +45 -20
  206. package/dist/memory/cloud/sync-disk.js +27 -8
  207. package/dist/memory/impact/impact-store.js +6 -0
  208. package/dist/memory/intent/inline-intent.js +8 -3
  209. package/dist/memory/intent/intent-shard-store.d.ts +33 -47
  210. package/dist/memory/intent/intent-shard-store.js +252 -140
  211. package/dist/memory/intent/intent-shard.d.ts +0 -23
  212. package/dist/memory/intent/intent-shard.js +1 -11
  213. package/dist/memory/intent/intent-store.d.ts +13 -8
  214. package/dist/memory/intent/intent-store.js +46 -90
  215. package/dist/memory/intent/intent-tools.js +34 -23
  216. package/dist/memory/journal/ambient-store.js +2 -3
  217. package/dist/memory/journal/deviation-report.js +4 -1
  218. package/dist/memory/journal/deviation-service.js +10 -2
  219. package/dist/memory/journal/drive-flow.d.ts +19 -14
  220. package/dist/memory/journal/drive-flow.js +65 -48
  221. package/dist/memory/journal/envelope-store.js +2 -3
  222. package/dist/memory/journal/journal-recorder.d.ts +21 -0
  223. package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
  224. package/dist/memory/journal/on-disk/retain-policy.js +44 -0
  225. package/dist/memory/journal/on-disk/retention.d.ts +14 -10
  226. package/dist/memory/journal/on-disk/retention.js +13 -12
  227. package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
  228. package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
  229. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -11
  230. package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -45
  231. package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
  232. package/dist/memory/journal/on-disk/workspace-tiers.js +90 -0
  233. package/dist/memory/journal/route-template.d.ts +22 -0
  234. package/dist/memory/journal/route-template.js +44 -0
  235. package/dist/memory/journal/session-end.d.ts +13 -2
  236. package/dist/memory/journal/session-end.js +88 -18
  237. package/dist/memory/journal/session-journal.d.ts +8 -1
  238. package/dist/memory/journal/session-journal.js +10 -0
  239. package/dist/memory/project/baselines.d.ts +1 -1
  240. package/dist/memory/project/dir/reticle-dir.d.ts +3 -1
  241. package/dist/memory/project/dir/reticle-dir.js +1 -0
  242. package/dist/memory/project/fs/fs-port.js +44 -5
  243. package/dist/memory/project/fs/write-atomic.d.ts +26 -0
  244. package/dist/memory/project/fs/write-atomic.js +48 -0
  245. package/dist/memory/project/project-tools.js +3 -1
  246. package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
  247. package/dist/memory/recall/prior/connection-memory.js +8 -0
  248. package/dist/memory/recall/registered-projects.d.ts +2 -1
  249. package/dist/portal/bridge/auth-failure-reason.d.ts +1 -1
  250. package/dist/portal/bridge/auth-failure-reason.js +9 -4
  251. package/dist/portal/bridge/bridge.d.ts +8 -0
  252. package/dist/portal/bridge/bridge.js +43 -2
  253. package/dist/portal/input/js-coverage.d.ts +25 -0
  254. package/dist/portal/input/js-coverage.js +30 -0
  255. package/dist/portal/input/real-input.d.ts +11 -0
  256. package/dist/portal/input/real-input.js +31 -5
  257. package/dist/portal/pool/browser-pool.d.ts +10 -0
  258. package/dist/portal/pool/browser-pool.js +10 -0
  259. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  260. package/dist/portal/pool/playwright-launcher.js +21 -13
  261. package/dist/portal/pool/pool-contract.d.ts +2 -0
  262. package/dist/portal/pool/storage-seed.d.ts +2 -1
  263. package/dist/portal/pool/zero-install.d.ts +27 -0
  264. package/dist/portal/pool/zero-install.js +54 -0
  265. package/dist/portal/realm/web-realm.js +6 -0
  266. package/dist/portal/session/dev-server/dev-command.d.ts +2 -2
  267. package/dist/portal/session/dev-server/dev-command.js +30 -12
  268. package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
  269. package/dist/portal/session/dev-server/dev-server-probe.js +17 -1
  270. package/dist/portal/session/dev-server/route-status-probe.d.ts +24 -0
  271. package/dist/portal/session/dev-server/route-status-probe.js +57 -0
  272. package/dist/portal/session/dev-server/served-document.d.ts +21 -0
  273. package/dist/portal/session/dev-server/served-document.js +57 -0
  274. package/dist/portal/session/facts/background-traffic.d.ts +9 -0
  275. package/dist/portal/session/facts/background-traffic.js +25 -0
  276. package/dist/portal/session/facts/observed-state.d.ts +11 -0
  277. package/dist/portal/session/facts/observed-state.js +34 -0
  278. package/dist/portal/session/live-control-tools.js +48 -3
  279. package/dist/portal/session/no-session-diagnosis.d.ts +29 -0
  280. package/dist/portal/session/no-session-diagnosis.js +62 -5
  281. package/dist/portal/session/no-session-next-action.d.ts +13 -0
  282. package/dist/portal/session/no-session-next-action.js +48 -9
  283. package/dist/portal/session/no-session-watch.d.ts +18 -0
  284. package/dist/portal/session/no-session-watch.js +88 -2
  285. package/dist/portal/session/presence/attachment-history.d.ts +13 -2
  286. package/dist/portal/session/session-health.d.ts +61 -0
  287. package/dist/portal/session/session-health.js +43 -3
  288. package/dist/portal/session/session-info.d.ts +6 -0
  289. package/dist/portal/session/session-manager.d.ts +29 -6
  290. package/dist/portal/session/session-manager.js +42 -5
  291. package/dist/portal/session/session-reaper.d.ts +28 -0
  292. package/dist/portal/session/session-reaper.js +49 -1
  293. package/dist/portal/session/session-successor.d.ts +11 -0
  294. package/dist/portal/session/session-successor.js +14 -1
  295. package/dist/portal/session/session-verdict-facts.d.ts +28 -0
  296. package/dist/portal/session/session-verdict-facts.js +15 -0
  297. package/dist/portal/session/session.d.ts +10 -0
  298. package/dist/portal/session/session.js +34 -26
  299. package/dist/surface/http-server.d.ts +2 -1
  300. package/dist/surface/http-server.js +4 -2
  301. package/dist/surface/mcp/mcp-proxy.d.ts +2 -2
  302. package/dist/surface/mcp/mcp-proxy.js +5 -5
  303. package/dist/surface/mcp/mcp.js +4 -2
  304. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +13 -1
  305. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +27 -2
  306. package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
  307. package/dist/surface/mcp/server-instructions.js +21 -8
  308. package/dist/surface/tools/act/after-match.d.ts +17 -0
  309. package/dist/surface/tools/act/after-match.js +30 -0
  310. package/dist/surface/tools/act/already-true.d.ts +40 -0
  311. package/dist/surface/tools/act/already-true.js +36 -0
  312. package/dist/surface/tools/act/durable.d.ts +69 -0
  313. package/dist/surface/tools/act/durable.js +139 -0
  314. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +19 -6
  315. package/dist/surface/tools/act/navigation/navigate-arrival.js +60 -10
  316. package/dist/surface/tools/act/navigation/navigate-result.d.ts +1 -12
  317. package/dist/surface/tools/act/navigation/navigate-result.js +21 -3
  318. package/dist/surface/tools/act/proved-controls.d.ts +9 -0
  319. package/dist/surface/tools/act/proved-controls.js +11 -0
  320. package/dist/surface/tools/act/sequence-grade.d.ts +5 -0
  321. package/dist/surface/tools/act/sequence-grade.js +32 -1
  322. package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
  323. package/dist/surface/tools/act/settle-in-flight.js +29 -6
  324. package/dist/surface/tools/act-capsule.d.ts +7 -0
  325. package/dist/surface/tools/act-capsule.js +68 -8
  326. package/dist/surface/tools/act-sequence-tool.js +25 -8
  327. package/dist/surface/tools/act-tools.js +51 -74
  328. package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
  329. package/dist/surface/tools/args/numeric-bounds.js +30 -3
  330. package/dist/surface/tools/assert/assert-grade.js +26 -3
  331. package/dist/surface/tools/assert/assert-verdict.js +32 -6
  332. package/dist/surface/tools/browser-tools.js +17 -4
  333. package/dist/surface/tools/coverage-tools.js +27 -1
  334. package/dist/surface/tools/dynamic-tools.js +6 -0
  335. package/dist/surface/tools/error-recovery.js +4 -4
  336. package/dist/surface/tools/feedback-invite.js +6 -4
  337. package/dist/surface/tools/feedback-tools.d.ts +2 -1
  338. package/dist/surface/tools/feedback-tools.js +1 -1
  339. package/dist/surface/tools/harness-explore.d.ts +3 -2
  340. package/dist/surface/tools/harness-explore.js +7 -6
  341. package/dist/surface/tools/invoke-tool.js +17 -4
  342. package/dist/surface/tools/lease-hint.d.ts +8 -0
  343. package/dist/surface/tools/lease-hint.js +10 -0
  344. package/dist/surface/tools/lease-tools.d.ts +16 -28
  345. package/dist/surface/tools/lease-tools.js +68 -11
  346. package/dist/surface/tools/lineage-tools.js +1 -1
  347. package/dist/surface/tools/live-call-text.js +4 -1
  348. package/dist/surface/tools/observe-tools.js +23 -7
  349. package/dist/surface/tools/real-input-attempt.d.ts +0 -5
  350. package/dist/surface/tools/real-input-attempt.js +1 -1
  351. package/dist/surface/tools/tool-kit.d.ts +5 -0
  352. package/dist/surface/tools/tool-kit.js +6 -1
  353. package/dist/surface/tools/tool-surface.js +17 -5
  354. package/dist/surface/tools/tools.js +68 -29
  355. package/dist/telemetry/argument-shape.d.ts +0 -2
  356. package/dist/telemetry/argument-shape.js +0 -4
  357. package/dist/telemetry/error-class.d.ts +2 -3
  358. package/dist/telemetry/error-class.js +2 -3
  359. package/dist/telemetry/feedback-local.d.ts +1 -0
  360. package/dist/telemetry/feedback-local.js +1 -3
  361. package/dist/telemetry/feedback.d.ts +1 -1
  362. package/dist/telemetry/harness-drive.d.ts +0 -2
  363. package/dist/telemetry/harness-drive.js +0 -4
  364. package/dist/telemetry/hud-metrics.d.ts +32 -0
  365. package/dist/telemetry/hud-metrics.js +95 -0
  366. package/dist/telemetry/session-metrics.d.ts +5 -0
  367. package/dist/telemetry/session-metrics.js +15 -1
  368. package/dist/wire-journal.d.ts +34 -0
  369. package/dist/wire-journal.js +104 -0
  370. package/dist/workspace-packages.d.ts +0 -2
  371. package/dist/workspace-packages.js +1 -9
  372. package/docs/README.md +5 -2
  373. package/docs/actions.mdx +3 -3
  374. package/docs/agent-cheatsheet.md +4 -4
  375. package/docs/architecture.md +6 -6
  376. package/docs/best-practices.mdx +1 -1
  377. package/docs/capabilities.mdx +32 -1
  378. package/docs/cli/cloud.mdx +21 -9
  379. package/docs/cli/doctor.mdx +4 -0
  380. package/docs/cli/feedback.mdx +2 -2
  381. package/docs/cli/gate.mdx +9 -4
  382. package/docs/cli/init.mdx +1 -0
  383. package/docs/cli/report.mdx +44 -0
  384. package/docs/cli/update.mdx +10 -0
  385. package/docs/cli.mdx +9 -0
  386. package/docs/desktop.mdx +14 -10
  387. package/docs/environment.mdx +87 -0
  388. package/docs/faq.mdx +18 -16
  389. package/docs/first-drive.md +5 -13
  390. package/docs/flows.md +32 -2
  391. package/docs/frameworks.mdx +140 -9
  392. package/docs/getting-started.md +3 -3
  393. package/docs/http-transport.md +6 -3
  394. package/docs/human-control.md +2 -2
  395. package/docs/index.mdx +16 -6
  396. package/docs/install-agentic.mdx +37 -1
  397. package/docs/install-manual.mdx +1 -1
  398. package/docs/integration-patterns.md +3 -3
  399. package/docs/multi-agent-testing.md +1 -1
  400. package/docs/packages/babel-plugin.mdx +1 -1
  401. package/docs/packages/browser.mdx +2 -2
  402. package/docs/packages/react.mdx +2 -2
  403. package/docs/packages/tauri.mdx +1 -1
  404. package/docs/packages/vite-plugin.mdx +2 -2
  405. package/docs/packages.mdx +9 -9
  406. package/docs/predicates.mdx +176 -7
  407. package/docs/quickstart.mdx +2 -2
  408. package/docs/recipes.mdx +2 -2
  409. package/docs/state-management.mdx +2 -2
  410. package/docs/system-map.md +1 -1
  411. package/docs/telemetry.md +1 -1
  412. package/docs/token-efficiency.md +3 -3
  413. package/docs/tools/act-and-wait.mdx +1 -0
  414. package/docs/tools/act-sequence.mdx +1 -1
  415. package/docs/tools/console.mdx +1 -1
  416. package/docs/tools/inspect.mdx +1 -1
  417. package/docs/tools/network.mdx +1 -1
  418. package/docs/tools/query.mdx +11 -11
  419. package/docs/tools/sessions.mdx +1 -1
  420. package/docs/tools/snapshot.mdx +1 -1
  421. package/docs/tools/state.mdx +1 -1
  422. package/docs/tools/wait-for.mdx +1 -1
  423. package/docs/usage.md +8 -7
  424. package/docs/use-cases.mdx +157 -0
  425. package/docs/vs-screenshots.mdx +3 -3
  426. package/docs/what-is-recorded.md +62 -0
  427. package/docs/what-is-reticle.mdx +17 -20
  428. package/docs/why-reticle.mdx +14 -21
  429. package/package.json +11 -10
  430. package/dist/judgement/capsule/minimize.d.ts +0 -12
  431. package/dist/judgement/capsule/minimize.js +0 -22
  432. package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
  433. package/dist/judgement/outcome/predicate-to-expect.js +0 -148
  434. package/dist/judgement/phenomena/phenomena.d.ts +0 -26
  435. package/dist/judgement/phenomena/phenomena.js +0 -101
  436. package/dist/language/flows/flow-report.d.ts +0 -22
  437. package/dist/language/flows/flow-report.js +0 -106
@@ -9,22 +9,25 @@ import { existsSync, readFileSync, writeFileSync } from 'node:fs';
9
9
  import { homedir } from 'node:os';
10
10
  import { join } from 'node:path';
11
11
  import { planAgentConfigs } from './agent-configs.js';
12
- import { AppShape, readShape } from './desktop-shape.js';
12
+ import { AppShape, describeShape, readShape } from './desktop-shape.js';
13
13
  import { stopOnInterrupt } from './terminal/interrupt.js';
14
14
  import { stopOnCrash, crashSentence } from './terminal/crash.js';
15
15
  import { applyAgentPlan, applyAgentSkills } from './agent-writer.js';
16
16
  import { ApprovalOutcome, grantAutoApproval } from './auto-approve.js';
17
17
  import { agentIo } from './agent-io.js';
18
- import { EnsureDaemon, ensureDaemon, nodeEnsureDaemonDeps } from './bringup/ensure-daemon.js';
18
+ import { EnsureDaemon, ensureDaemon, holdDaemon, nodeEnsureDaemonDeps, nodeRetireDeps, retireMovedDaemons, } from './bringup/ensure-daemon.js';
19
19
  import { openInBrowser } from '../cli/launch/cli-launch.js';
20
+ import { openLeaseFor } from './bringup/connect-lease.js';
20
21
  import { readProjectId } from '../cli/ports/resolve/cli-port.js';
21
- import { reticleStateHome } from '../daemon/daemon.js';
22
+ import { spawnSync } from 'node:child_process';
23
+ import { isAlive, reticleStateHome } from '../daemon/daemon.js';
22
24
  import { readDevServers } from '../daemon/dev-servers.js';
23
25
  import { urlOfExistingApp } from './probe/existing-app.js';
26
+ import { handedOverUrl, stopHandedOver } from './bringup/dev-server-files.js';
24
27
  import { listSessions, OwnedDevServer, probePage } from './node-effects.js';
25
28
  import { fetchStatus } from '../daemon/binding/daemon-status-probe.js';
26
- import { summarizeStatus } from '../cli/launch/cli-launch.js';
27
- import { runSetupPhases, } from './run-setup.js';
29
+ import { daemonSkew, summarizeStatus } from '../cli/launch/cli-launch.js';
30
+ import { runSetupPhases, SetupPhase, } from './run-setup.js';
28
31
  import { noticeKey, readSaid, rememberSaid, unsaidNotices } from './agent-notice-memory.js';
29
32
  /**
30
33
  * The dev server a crash should take with it, if one is running right now.
@@ -84,13 +87,15 @@ function hasElectronDependency(dir) {
84
87
  * scope unwritten — it exists on machines today, and init only ever writes the project-scope file,
85
88
  * so a VS Code user has no tools outside the directory they ran init in.
86
89
  */
90
+ /** `agent`, `agents`. */
91
+ const agentWord = (n) => (1 === n ? 'agent' : 'agents');
87
92
  export function registerOtherAgents(print) {
88
93
  const platform = process.platform;
89
94
  const home = homedir();
90
95
  const results = applyAgentPlan(planAgentConfigs({ home, platform, exists: agentIo.exists, readFile: agentIo.readFile }), agentIo);
91
96
  const wrote = results.filter((r) => 'created' === r.action || 'merged' === r.action);
92
97
  if (0 < wrote.length) {
93
- print(`registered the MCP server with ${wrote.length} more agent(s): ${wrote.map((r) => r.name).join(', ')}`);
98
+ print(` ✓ ${String(wrote.length)} more ${agentWord(wrote.length)}: ${wrote.map((r) => r.name).join(', ')}`);
94
99
  }
95
100
  // A format we will not rewrite is somebody's to edit, so it has to be said rather than skipped --
96
101
  // but said ONCE. Two commands call this function by design, so a `curl | sh` followed by
@@ -103,21 +108,21 @@ export function registerOtherAgents(print) {
103
108
  .map((r) => ({ name: r.name, file: r.file, why: r.why }));
104
109
  const fresh = unsaidNotices(readSaid(stateHome), manual);
105
110
  for (const notice of fresh) {
106
- print(`${notice.name}: ${notice.why} — add the reticle entry to ${notice.file} by hand.`);
111
+ print(` ⚠ ${notice.name}: ${notice.why} — add the reticle entry to ${notice.file} by hand.`);
107
112
  }
108
113
  rememberSaid(stateHome, fresh.map((n) => noticeKey(n)));
109
114
  const skills = applyAgentSkills(agentIo, { home, platform });
110
115
  if (0 < skills.length)
111
- print(`wrote the /reticle skill for ${skills.length} agent(s)`);
116
+ print(` ✓ the /reticle skill, for ${String(skills.length)} ${agentWord(skills.length)}`);
112
117
  // Registration alone still leaves an Accept dialog in front of every call, and a verification run
113
118
  // makes dozens of them: the loop is only autonomous once the tools are pre-approved.
114
119
  const approvals = grantAutoApproval(agentIo, { home, platform });
115
120
  const granted = approvals.filter((a) => ApprovalOutcome.GRANTED === a.outcome);
116
121
  if (0 < granted.length) {
117
- print(`pre-approved the reticle tools in ${granted.map((a) => a.name).join(', ')} — no Accept prompt per call`);
122
+ print(` ✓ tools pre-approved in ${granted.map((a) => a.name).join(', ')}, so no Accept prompt per call`);
118
123
  }
119
124
  for (const noted of approvals.filter((a) => undefined !== a.warn)) {
120
- print(`${noted.name}: ${String(noted.warn)}`);
125
+ print(` ⚠ ${noted.name}: ${String(noted.warn)}`);
121
126
  }
122
127
  }
123
128
  /**
@@ -127,13 +132,70 @@ export function registerOtherAgents(print) {
127
132
  * instrumented app they can watch is the deliverable, and killing it would leave them with config
128
133
  * files and a dead tab.
129
134
  */
135
+ /** How long a stopped dev server gets to let go of its port before the new one is started. */
136
+ const HANDED_OVER_EXIT_MS = 10_000;
137
+ const HANDED_OVER_EXIT_POLL_MS = 100;
138
+ /** Stop the server a previous init handed over for `appDir`, and wait (bounded) for it to exit. */
139
+ async function restartHandedOverServer(appDir) {
140
+ let stoppedPid;
141
+ const stopped = stopHandedOver(reticleStateHome(), appDir, {
142
+ alive: isAlive,
143
+ kill: (pid) => {
144
+ stoppedPid = pid;
145
+ try {
146
+ // Its own process group (it was spawned detached), so what it started goes with it.
147
+ if ('win32' === process.platform) {
148
+ spawnSync('taskkill', ['/PID', String(pid), '/T', '/F']);
149
+ }
150
+ else {
151
+ process.kill(-pid, 'SIGTERM');
152
+ }
153
+ }
154
+ catch {
155
+ /* already gone */
156
+ }
157
+ },
158
+ });
159
+ const deadline = Date.now() + HANDED_OVER_EXIT_MS;
160
+ while (undefined !== stoppedPid && isAlive(stoppedPid) && Date.now() < deadline) {
161
+ await new Promise((done) => setTimeout(done, HANDED_OVER_EXIT_POLL_MS));
162
+ }
163
+ return stopped;
164
+ }
130
165
  export async function runSetupCommand(input, print) {
131
166
  if (input.registerAgents)
132
167
  registerOtherAgents(print);
168
+ // A moved port first: this project's daemon on the OLD port would otherwise be the one the page
169
+ // finds and dials, while everything below waits on the new one.
170
+ const retired = await retireMovedDaemons(readProjectId(input.appDir), input.bridgePort, nodeRetireDeps());
171
+ for (const port of retired) {
172
+ print(`stopped this project's Reticle daemon on port ${String(port)}: the project now uses ` +
173
+ `${String(input.bridgePort)}, and the page would have kept dialling the old one.`);
174
+ }
175
+ // And the dev server a previous init left running, which may have read the old port once at
176
+ // startup (Next does) — so the attach below would keep a page dialling the daemon just stopped.
177
+ if (0 < retired.length && (await restartHandedOverServer(input.appDir))) {
178
+ print(`stopped the dev server a previous init started, so it restarts on port ${String(input.bridgePort)}.`);
179
+ }
133
180
  // Before the app is booted, because the app's whole job from here is to dial this port. Without
134
181
  // it the phases wait out their budget and then report the SDK as the thing that failed.
135
- const daemon = await ensureDaemon(input.bridgePort, nodeEnsureDaemonDeps());
136
- if (EnsureDaemon.UNAVAILABLE === daemon) {
182
+ const daemon = await ensureDaemon(input.bridgePort, nodeEnsureDaemonDeps((status) => undefined !== daemonSkew(status)));
183
+ if (undefined !== daemon.message)
184
+ print(daemon.message);
185
+ if (EnsureDaemon.SKEWED_IN_USE === daemon.state) {
186
+ // Stop here: every hello from the page would be refused, and waiting out the connect budget
187
+ // only to blame the page is the run this exists to prevent.
188
+ return {
189
+ ok: false,
190
+ reachedPhase: SetupPhase.DEV_SERVER,
191
+ flowSaved: false,
192
+ notes: undefined === daemon.message ? [] : [daemon.message],
193
+ fallback: [
194
+ `Once those sessions are done, free the port with \`npx @reticlehq/server kill --port ${String(input.bridgePort)}\` and re-run init.`,
195
+ ],
196
+ };
197
+ }
198
+ if (EnsureDaemon.UNAVAILABLE === daemon.state) {
137
199
  print(`could not start the Reticle daemon on port ${String(input.bridgePort)}, so nothing is listening for the app to connect to. Run \`npx @reticlehq/server serve --port ${String(input.bridgePort)}\` and try again.`);
138
200
  }
139
201
  // Which shell this is decides three things the phases would otherwise get wrong: opening a
@@ -145,7 +207,7 @@ export async function runSetupCommand(input, print) {
145
207
  hasElectronDep: hasElectronDependency(input.appDir),
146
208
  });
147
209
  if (AppShape.WEB !== shape)
148
- print(`detected a ${shape} app`);
210
+ print(`detected ${describeShape(shape)}`);
149
211
  const server = new OwnedDevServer();
150
212
  const effects = {
151
213
  startDevServer: (command, cwd) => {
@@ -153,10 +215,16 @@ export async function runSetupCommand(input, print) {
153
215
  server.start(command, cwd, input.env);
154
216
  return Promise.resolve();
155
217
  },
156
- existingAppUrl: () => Promise.resolve(urlOfExistingApp(readDevServers(reticleStateHome()), {
218
+ // The server the plugin announced (Vite), or failing that the one a previous init handed over
219
+ // and recorded — the only way to know a Next or Angular server on the port is this project's own.
220
+ existingAppUrl: async () => urlOfExistingApp(readDevServers(reticleStateHome()), {
157
221
  projectId: readProjectId(input.appDir),
158
222
  root: input.appDir,
159
- })),
223
+ }) ??
224
+ (await handedOverUrl(reticleStateHome(), input.appDir, {
225
+ alive: isAlive,
226
+ answers: async (url) => (await probePage(url)).served,
227
+ })),
160
228
  devServerOutput: () => server.output(),
161
229
  devServerExited: () => server.exited(),
162
230
  devServerQuietForMs: () => server.quietForMs(),
@@ -164,20 +232,16 @@ export async function runSetupCommand(input, print) {
164
232
  probePage,
165
233
  openBrowser: async (url) => {
166
234
  const failure = await openInBrowser(url);
167
- if (null !== failure) {
168
- print(`could not open a browser (${failure}). Nothing was opened, and nothing else here will ` +
169
- // Three wordings have been wrong in a row, each naming a way out that does not exist on
170
- // the machine being spoken to. It said `reticle_run({ tool: "reticle_lease", ... })`:
171
- // the default surface advertises neither name and ships no hatch to reach the second.
172
- // It then said `reticle open <url>`, which asks the OS to launch the default browser --
173
- // the very thing that just failed -- so it returned the reader to the same wall.
174
- // This one names no command: the missing piece is a browser, and the honest sentence
175
- // says which url needs one rather than inventing a Reticle that can conjure it.
176
- `open one: this asks the OS for your default browser, and it is a machine with none — ` +
177
- `CI, a container, an SSH session, WSL with no host browser. Point any browser that can ` +
178
- `reach it at ${url}; the session appears within a second of the page loading.`);
179
- }
235
+ if (null === failure)
236
+ return undefined;
237
+ // It used to end "nothing else here will open one", which stopped being true once a
238
+ // Reticle-owned browser could always launch: run-setup opens a lease on this failure, so the
239
+ // reader is told what happens next rather than sent to find a browser by hand.
240
+ print(`could not open a browser (${failure}), so the connect proof will come from a ` +
241
+ `Reticle-owned headless browser instead. To use the app yourself, point any browser at ${url}.`);
242
+ return failure;
180
243
  },
244
+ openLease: (url) => openLeaseFor(input.bridgePort, url, input.pairingToken),
181
245
  listSessions: () => listSessions(input.bridgePort),
182
246
  // `summarizeStatus` already narrows this payload for `reticle status`; reusing it here keeps one
183
247
  // reader of the wire shape rather than two that can disagree about which key carries the reason.
@@ -207,16 +271,26 @@ export async function runSetupCommand(input, print) {
207
271
  activeDevServerStop = () => {
208
272
  server.stop();
209
273
  };
274
+ // Hold the daemon for as long as this run waits on it. Its idle rule counted none of this as
275
+ // activity, and on a slow desktop build the daemon init had just started idled out mid-wait.
276
+ const releaseDaemon = holdDaemon(input.bridgePort);
210
277
  try {
211
- const outcome = await runSetupPhases({ ...input, shape }, effects);
278
+ const outcome = await runSetupPhases({ ...input, shape, projectId: readProjectId(input.appDir) }, effects);
212
279
  // The app stays up only when there is something worth watching.
213
- if (outcome.ok)
214
- server.handOver();
280
+ if (outcome.ok) {
281
+ server.handOver(outcome.url);
282
+ // Its output is on a file now, not this terminal, so say where: a compile error that used to
283
+ // scroll past here is the first thing somebody will look for.
284
+ const log = server.logPath();
285
+ if (undefined !== log)
286
+ print(`The dev server keeps running; its output goes to ${log}`);
287
+ }
215
288
  return {
216
289
  ...outcome,
217
290
  };
218
291
  }
219
292
  finally {
293
+ releaseDaemon();
220
294
  releaseSignals();
221
295
  activeDevServerStop = null;
222
296
  server.stop();
@@ -1,4 +1,4 @@
1
- import { McpClient, MCP_CLIENTS, claudeAddCommand, claudeAvailableProbe, claudeExistsProbe, detectMcpClients, mergeClientConfig, clientSpec, ClientMergeStatus, } from '@reticlehq/init';
1
+ import { McpClient, MCP_CLIENTS, claudeAddCommand, claudeAvailableProbe, claudeHasReticle, detectMcpClients, mergeClientConfig, clientSpec, ClientMergeStatus, } from '@reticlehq/init';
2
2
  import { OnboardingPhase, OnboardingStepStatus, } from '@reticlehq/core/telemetry';
3
3
  export function setupMcp(io) {
4
4
  const detected = [];
@@ -22,8 +22,8 @@ export function setupMcp(io) {
22
22
  const available = claudeAvailableProbe();
23
23
  if (io.runCli(available.command, available.args)) {
24
24
  detected.push(McpClient.CLAUDE_CODE);
25
- const already = claudeExistsProbe();
26
- if (io.runCli(already.command, already.args)) {
25
+ // Read from Claude's config: `claude mcp get` health-checks by launching the server.
26
+ if (claudeHasReticle(io, undefined)) {
27
27
  alreadyThere.push(McpClient.CLAUDE_CODE);
28
28
  }
29
29
  else {
@@ -26,3 +26,11 @@ export declare const WAIT_PROGRESS_EVERY_MS = 15000;
26
26
  * without a line per poll burying the output it exists to explain.
27
27
  */
28
28
  export declare function waitProgressLine(elapsedMs: number, watching: string | undefined, lastSpokeAtMs: number | undefined): string | undefined;
29
+ /**
30
+ * The same, for the wait on a session after the app is up.
31
+ *
32
+ * That wait was silent as well: a desktop init printed "Waiting for the app to launch and dial in."
33
+ * and then nothing for the whole of its budget. Naming what is awaited and how long remains is what
34
+ * lets somebody tell a slow start from a wedged one — and when to stop waiting themselves.
35
+ */
36
+ export declare function connectProgressLine(elapsedMs: number, lastSpokeAtMs: number | undefined, budgetMs: number, awaiting: string): string | undefined;
@@ -41,3 +41,20 @@ export function waitProgressLine(elapsedMs, watching, lastSpokeAtMs) {
41
41
  return (`Waiting ${seconds} for the dev server — watching ${watching}. If the app is already up ` +
42
42
  `somewhere else, that url is the thing to check first.`);
43
43
  }
44
+ /**
45
+ * The same, for the wait on a session after the app is up.
46
+ *
47
+ * That wait was silent as well: a desktop init printed "Waiting for the app to launch and dial in."
48
+ * and then nothing for the whole of its budget. Naming what is awaited and how long remains is what
49
+ * lets somebody tell a slow start from a wedged one — and when to stop waiting themselves.
50
+ */
51
+ export function connectProgressLine(elapsedMs, lastSpokeAtMs, budgetMs, awaiting) {
52
+ if (elapsedMs < WAIT_PROGRESS_EVERY_MS)
53
+ return undefined;
54
+ if (lastSpokeAtMs !== undefined && elapsedMs - lastSpokeAtMs < WAIT_PROGRESS_EVERY_MS) {
55
+ return undefined;
56
+ }
57
+ const seconds = (ms) => `${String(Math.max(0, Math.floor(ms / 1000)))}s`;
58
+ return (`Still waiting for ${awaiting} to connect: ${seconds(elapsedMs)} so far, giving up in ` +
59
+ `${seconds(budgetMs - elapsedMs)}.`);
60
+ }
@@ -19,6 +19,6 @@ export function crawlEmptyNote(outcome) {
19
19
  return `no interactive controls were found on this page, so nothing was clicked — the crawl ran and found none, which is a result rather than a failure.${capped}`;
20
20
  }
21
21
  return (`${String(outcome.interactiveFound)} interactive controls were found and none of them were clicked. ` +
22
- `That is not an empty page, so something stopped the loop — report it with reticle_feedback, ` +
22
+ `That is not an empty page, so something stopped the loop — report it with reticle_session { action: "feedback" }, ` +
23
23
  `including this page's URL and one control's ref.`);
24
24
  }
@@ -1,4 +1,10 @@
1
1
  import type { ToolDef } from '../../surface/tools/tool-kit.js';
2
+ /**
3
+ * The configured secret for a field, only on the origin the crawl started on. The field name comes
4
+ * from whatever page is on screen, so without the check a page on another origin could name an
5
+ * empty textbox after a secret and have the crawl type it in.
6
+ */
7
+ export declare function crawlSecret(startUrl: string, env: Readonly<Record<string, string | undefined>>): (name: string, pageUrl: string) => string | undefined;
2
8
  /**
3
9
  * The autonomous "smart monkey" tool. Builds on reticle_explore (which only LISTS) by
4
10
  * actually clicking each reachable control and classifying the reaction. DESTRUCTIVE by nature —
@@ -5,8 +5,29 @@ import { ReticleTool } from '@reticlehq/core';
5
5
  import { asNumber, asString } from '@reticlehq/core';
6
6
  import { stepCountSchema, timeoutMsSchema } from '../../surface/tools/args/numeric-bounds.js';
7
7
  import { crawl } from './crawl.js';
8
+ import { EXHAUST_DEFAULT_ACTIONS, runExhaustive } from '../exhaust/exhaust-run.js';
9
+ import { heuristicFillValue } from '../harness/fill-values.js';
10
+ import { secretEnvKey } from '../../language/flows/flows.js';
11
+ import { CRAWL_DEFAULTS } from '@reticlehq/core';
8
12
  import { routeFromUrl, routesFromEvents } from '../../memory/project/learned-routes.js';
9
13
  const nodeSleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
14
+ /**
15
+ * The configured secret for a field, only on the origin the crawl started on. The field name comes
16
+ * from whatever page is on screen, so without the check a page on another origin could name an
17
+ * empty textbox after a secret and have the crawl type it in.
18
+ */
19
+ export function crawlSecret(startUrl, env) {
20
+ const originOf = (url) => {
21
+ try {
22
+ return new URL(url).origin;
23
+ }
24
+ catch {
25
+ return undefined;
26
+ }
27
+ };
28
+ const home = originOf(startUrl);
29
+ return (name, pageUrl) => home !== undefined && home === originOf(pageUrl) ? env[secretEnvKey(name)] : undefined;
30
+ }
10
31
  /**
11
32
  * The autonomous "smart monkey" tool. Builds on reticle_explore (which only LISTS) by
12
33
  * actually clicking each reachable control and classifying the reaction. DESTRUCTIVE by nature —
@@ -27,6 +48,10 @@ export const CRAWL_TOOLS = [
27
48
  .string()
28
49
  .optional()
29
50
  .describe('CSS selector or element ref to restrict crawling to a subtree.'),
51
+ exhaustive: z
52
+ .boolean()
53
+ .optional()
54
+ .describe("Walk every state it can tell apart, drive each write's failure path, fold into the coverage ledger."),
30
55
  confirmDangerous: z
31
56
  .boolean()
32
57
  .optional()
@@ -62,6 +87,8 @@ export const CRAWL_TOOLS = [
62
87
  .optional()
63
88
  .describe('Present only when the page exceeded one snapshot, so controls past the cap were never listed. When present, a zero-anomaly result does NOT mean the app is clean.'),
64
89
  truncated: z.boolean(),
90
+ // Only on `exhaustive` — see features/exhaust/exhaust-run.ts. Loose: it carries the levels.
91
+ exhaustive: z.record(z.unknown()).optional(),
65
92
  },
66
93
  handler: async (deps, args) => {
67
94
  const session = deps.sessions.resolve(asString(args['sessionId']));
@@ -76,6 +103,36 @@ export const CRAWL_TOOLS = [
76
103
  ...(scope !== undefined ? { scope } : {}),
77
104
  ...(true === args['confirmDangerous'] ? { confirmDangerous: true } : {}),
78
105
  };
106
+ if (true === args['exhaustive']) {
107
+ // Starts code-coverage collection, so the drive below is measured. See takeCodeCoverage.
108
+ await deps.realInput?.takeCodeCoverage?.(session.url);
109
+ const secret = crawlSecret(session.url, process.env);
110
+ return runExhaustive({
111
+ sessions: deps.sessions,
112
+ session,
113
+ startUrl: session.url,
114
+ maxActions: maxSteps ?? EXHAUST_DEFAULT_ACTIONS,
115
+ settleMs: settleMs ?? CRAWL_DEFAULTS.SETTLE_MS,
116
+ fillValue: (label, pageUrl) => {
117
+ const name = /"([^"]*)"/.exec(label)?.[1] ?? label;
118
+ return secret(name, pageUrl) ?? heuristicFillValue(name);
119
+ },
120
+ now: deps.now,
121
+ sleep: nodeSleep,
122
+ ...(deps.realInput?.setMocks === undefined
123
+ ? {}
124
+ : {
125
+ setMocks: (url, rules) => deps.realInput?.setMocks?.(url, rules) ?? Promise.resolve(false),
126
+ }),
127
+ ...(deps.realInput?.takeCodeCoverage === undefined
128
+ ? {}
129
+ : {
130
+ takeCode: (url) => deps.realInput?.takeCodeCoverage?.(url) ?? Promise.resolve(undefined),
131
+ }),
132
+ fs: deps.fs,
133
+ reticleRoot: sessionRoot(deps, session.id),
134
+ });
135
+ }
79
136
  const report = await crawl(session, opts, nodeSleep);
80
137
  const routes = [
81
138
  ...(initialRoute === undefined ? [] : [initialRoute]),
@@ -16,6 +16,8 @@ export interface CrawlSession {
16
16
  /** The page under test, so a third-party beacon cannot be reported against a control. Optional
17
17
  * for the same reason `currentDocumentId` is. */
18
18
  readonly url?: string | undefined;
19
+ /** Same-origin endpoints the project declared as background. Optional like `url`. */
20
+ readonly background?: readonly string[] | undefined;
19
21
  /**
20
22
  * Is the page BACKGROUNDED? A hidden tab has its rAF clamped and the DOM observer flushes on rAF,
21
23
  * so real renders emit nothing and every absence-derived contradiction reads that silence as a