@reticlehq/server 3.8.2 → 3.10.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 (477) hide show
  1. package/LICENSE +201 -104
  2. package/NOTICE +5 -0
  3. package/README.md +1 -1
  4. package/SKILL.md +13 -12
  5. package/bin/launch.js +13 -0
  6. package/bin/package.json +3 -0
  7. package/bin/reticle.js +66 -8
  8. package/dist/chromium-launch-options.d.ts +25 -0
  9. package/dist/chromium-launch-options.js +21 -1
  10. package/dist/command/cli/adhoc-suite.js +2 -0
  11. package/dist/command/cli/adhoc-verdict.d.ts +2 -43
  12. package/dist/command/cli/adhoc-verdict.js +50 -160
  13. package/dist/command/cli/answers/gate-exit.d.ts +6 -2
  14. package/dist/command/cli/answers/gate-exit.js +12 -2
  15. package/dist/command/cli/answers/mcp-connection-hint.d.ts +2 -0
  16. package/dist/command/cli/answers/mcp-connection-hint.js +6 -0
  17. package/dist/command/cli/ci-hint.d.ts +44 -0
  18. package/dist/command/cli/ci-hint.js +72 -0
  19. package/dist/command/cli/cli-doctor.d.ts +6 -1
  20. package/dist/command/cli/cli-doctor.js +46 -5
  21. package/dist/command/cli/cli-flow-commands.d.ts +7 -1
  22. package/dist/command/cli/cli-flow-commands.js +39 -24
  23. package/dist/command/cli/cli-kill.d.ts +21 -0
  24. package/dist/command/cli/cli-kill.js +47 -4
  25. package/dist/command/cli/cli-parse-compare.d.ts +22 -0
  26. package/dist/command/cli/cli-parse-compare.js +75 -0
  27. package/dist/command/cli/cli-parse-grade.d.ts +36 -0
  28. package/dist/command/cli/cli-parse-grade.js +75 -0
  29. package/dist/command/cli/cli-parse-grammar.d.ts +2 -0
  30. package/dist/command/cli/cli-parse-grammar.js +18 -20
  31. package/dist/command/cli/cli-parse-verify.d.ts +10 -0
  32. package/dist/command/cli/cli-parse-verify.js +63 -14
  33. package/dist/command/cli/cli-parse.d.ts +22 -17
  34. package/dist/command/cli/cli-parse.js +54 -32
  35. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  36. package/dist/command/cli/cli-update-commands.js +29 -20
  37. package/dist/command/cli/cli-usage.js +61 -31
  38. package/dist/command/cli/cli-verify.d.ts +17 -3
  39. package/dist/command/cli/cli-verify.js +59 -21
  40. package/dist/command/cli/cloud-cli.js +2 -119
  41. package/dist/command/cli/daemon-link/daemon-client.d.ts +45 -0
  42. package/dist/command/cli/daemon-link/daemon-client.js +205 -0
  43. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +6 -1
  44. package/dist/command/cli/doctor/browser/chromium-hint.js +11 -5
  45. package/dist/command/cli/doctor/doctor-daemon-line.js +6 -3
  46. package/dist/command/cli/doctor/doctor-fix.d.ts +44 -0
  47. package/dist/command/cli/doctor/doctor-fix.js +89 -0
  48. package/dist/command/cli/doctor/doctor-launcher-line.d.ts +23 -0
  49. package/dist/command/cli/doctor/doctor-launcher-line.js +60 -0
  50. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  51. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  52. package/dist/command/cli/doctor-repairs.d.ts +64 -0
  53. package/dist/command/cli/doctor-repairs.js +214 -0
  54. package/dist/command/cli/drive/drive-command.js +3 -7
  55. package/dist/command/cli/ensure-daemon.d.ts +26 -0
  56. package/dist/command/cli/ensure-daemon.js +57 -0
  57. package/dist/command/cli/finished-run/grade-command.d.ts +23 -0
  58. package/dist/command/cli/finished-run/grade-command.js +180 -0
  59. package/dist/command/cli/first-use-checks.d.ts +41 -0
  60. package/dist/command/cli/first-use-checks.js +127 -0
  61. package/dist/command/cli/first-verdict-node.d.ts +3 -0
  62. package/dist/command/cli/first-verdict-node.js +189 -0
  63. package/dist/command/cli/first-verdict.d.ts +126 -0
  64. package/dist/command/cli/first-verdict.js +267 -0
  65. package/dist/command/cli/launch/sdk-version-match.d.ts +3 -2
  66. package/dist/command/cli/launch/sdk-version-match.js +3 -2
  67. package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +1 -1
  68. package/dist/command/cli/lifecycle/daemon-lifecycle.js +7 -6
  69. package/dist/command/cli/mcp-command.js +13 -4
  70. package/dist/command/cli/ports/port-holder.d.ts +11 -0
  71. package/dist/command/cli/ports/port-holder.js +36 -4
  72. package/dist/command/cli/setup-mcp-cli.d.ts +27 -1
  73. package/dist/command/cli/setup-mcp-cli.js +98 -23
  74. package/dist/command/cli/status/status-lines.d.ts +2 -0
  75. package/dist/command/cli/status/status-lines.js +72 -17
  76. package/dist/command/cli/status-fields.d.ts +5 -1
  77. package/dist/command/cli/status-fields.js +24 -6
  78. package/dist/command/cli/try-command.d.ts +7 -0
  79. package/dist/command/cli/try-command.js +11 -3
  80. package/dist/command/cli/two-builds/compare-command.d.ts +48 -0
  81. package/dist/command/cli/two-builds/compare-command.js +314 -0
  82. package/dist/command/cli/verify-against.d.ts +61 -0
  83. package/dist/command/cli/verify-against.js +187 -0
  84. package/dist/command/cli/verify-no-session.d.ts +2 -0
  85. package/dist/command/cli/verify-no-session.js +13 -0
  86. package/dist/command/cli/verify-results.d.ts +35 -2
  87. package/dist/command/cli/verify-results.js +76 -10
  88. package/dist/command/cli.js +112 -70
  89. package/dist/command/daemon/binding/daemon-status-probe.d.ts +3 -1
  90. package/dist/command/daemon/binding/daemon-status-probe.js +4 -2
  91. package/dist/command/daemon/daemon-argv.d.ts +9 -0
  92. package/dist/command/daemon/daemon-argv.js +11 -0
  93. package/dist/command/daemon/daemon-resolve.d.ts +8 -1
  94. package/dist/command/daemon/daemon-resolve.js +27 -1
  95. package/dist/command/daemon/daemon.d.ts +22 -4
  96. package/dist/command/daemon/daemon.js +52 -10
  97. package/dist/command/daemon/lifetime/daemon-exit.d.ts +24 -0
  98. package/dist/command/daemon/lifetime/daemon-exit.js +39 -0
  99. package/dist/command/daemon/lifetime/death-cause.d.ts +15 -0
  100. package/dist/command/daemon/lifetime/death-cause.js +149 -0
  101. package/dist/command/daemon/lifetime/heartbeat.d.ts +7 -15
  102. package/dist/command/daemon/lifetime/heartbeat.js +11 -15
  103. package/dist/command/daemon/lifetime/startup-failure.d.ts +29 -0
  104. package/dist/command/daemon/lifetime/startup-failure.js +62 -0
  105. package/dist/command/daemon/port-state.d.ts +14 -0
  106. package/dist/command/daemon/port-state.js +31 -0
  107. package/dist/command/setup/agent-configs.d.ts +2 -0
  108. package/dist/command/setup/agent-configs.js +42 -15
  109. package/dist/command/setup/agent-next-steps.d.ts +77 -0
  110. package/dist/command/setup/agent-next-steps.js +284 -0
  111. package/dist/command/setup/agent-writer.js +11 -6
  112. package/dist/command/setup/bringup/dev-server-files.d.ts +9 -0
  113. package/dist/command/setup/bringup/dev-server-files.js +17 -0
  114. package/dist/command/setup/bringup/static-page-server.d.ts +14 -2
  115. package/dist/command/setup/bringup/static-page-server.js +43 -9
  116. package/dist/command/setup/init/init-host.js +2 -0
  117. package/dist/command/setup/init/init-runtime.d.ts +6 -1
  118. package/dist/command/setup/init/init-runtime.js +63 -21
  119. package/dist/command/setup/mcp-launcher.d.ts +3 -0
  120. package/dist/command/setup/mcp-launcher.js +11 -0
  121. package/dist/command/setup/node-effects.d.ts +3 -2
  122. package/dist/command/setup/node-effects.js +9 -3
  123. package/dist/command/setup/remaining-steps.d.ts +8 -0
  124. package/dist/command/setup/remaining-steps.js +10 -0
  125. package/dist/command/setup/run-setup.d.ts +2 -0
  126. package/dist/command/setup/run-setup.js +9 -1
  127. package/dist/command/setup/setup-command.js +36 -15
  128. package/dist/command/setup/setup-mcp.d.ts +8 -0
  129. package/dist/command/setup/setup-mcp.js +47 -20
  130. package/dist/command/setup/start-dev-server.d.ts +8 -0
  131. package/dist/command/setup/start-dev-server.js +43 -0
  132. package/dist/command/update/updater.js +6 -0
  133. package/dist/command/version/identity/server-version.d.ts +2 -0
  134. package/dist/command/version/identity/server-version.js +2 -0
  135. package/dist/command/version/version-skew.d.ts +7 -0
  136. package/dist/command/version/version-skew.js +14 -3
  137. package/dist/features/compare/action-plan.d.ts +260 -0
  138. package/dist/features/compare/action-plan.js +543 -0
  139. package/dist/features/compare/behaviour-compare.d.ts +24 -0
  140. package/dist/features/compare/behaviour-compare.js +85 -0
  141. package/dist/features/compare/behaviour-diff.d.ts +97 -0
  142. package/dist/features/compare/behaviour-diff.js +202 -0
  143. package/dist/features/compare/behaviour-report.d.ts +40 -0
  144. package/dist/features/compare/behaviour-report.js +128 -0
  145. package/dist/features/compare/build-readings.d.ts +106 -0
  146. package/dist/features/compare/build-readings.js +250 -0
  147. package/dist/features/compare/compare-diff.d.ts +62 -0
  148. package/dist/features/compare/compare-diff.js +177 -0
  149. package/dist/features/compare/compare-report-html.d.ts +6 -0
  150. package/dist/features/compare/compare-report-html.js +102 -0
  151. package/dist/features/compare/compare-report.d.ts +15 -0
  152. package/dist/features/compare/compare-report.js +73 -0
  153. package/dist/features/compare/compare-run.d.ts +60 -0
  154. package/dist/features/compare/compare-run.js +123 -0
  155. package/dist/features/compare/outside/effect-lines.d.ts +26 -0
  156. package/dist/features/compare/outside/effect-lines.js +103 -0
  157. package/dist/features/compare/outside/state-sources.d.ts +76 -0
  158. package/dist/features/compare/outside/state-sources.js +164 -0
  159. package/dist/features/compare/outside/value-dictionary.d.ts +51 -0
  160. package/dist/features/compare/outside/value-dictionary.js +227 -0
  161. package/dist/features/compare/visible-content.d.ts +20 -0
  162. package/dist/features/compare/visible-content.js +125 -0
  163. package/dist/features/crawl/crawl-empty.js +2 -1
  164. package/dist/features/crawl/crawl-exhaustive.d.ts +55 -0
  165. package/dist/features/crawl/crawl-exhaustive.js +138 -0
  166. package/dist/features/crawl/crawl-tools.d.ts +9 -2
  167. package/dist/features/crawl/crawl-tools.js +28 -12
  168. package/dist/features/crawl/crawl.d.ts +8 -9
  169. package/dist/features/crawl/crawl.js +61 -65
  170. package/dist/features/exhaust/app-coverage.d.ts +5 -1
  171. package/dist/features/exhaust/app-coverage.js +3 -1
  172. package/dist/features/exhaust/code-coverage.js +8 -4
  173. package/dist/features/exhaust/edge-cases.d.ts +133 -0
  174. package/dist/features/exhaust/edge-cases.js +310 -0
  175. package/dist/features/exhaust/edges/edge-drive.d.ts +42 -0
  176. package/dist/features/exhaust/edges/edge-drive.js +364 -0
  177. package/dist/features/exhaust/edges/edge-run.d.ts +59 -0
  178. package/dist/features/exhaust/edges/edge-run.js +169 -0
  179. package/dist/features/exhaust/explorer.d.ts +87 -14
  180. package/dist/features/exhaust/explorer.js +159 -25
  181. package/dist/features/exhaust/failure-branches.d.ts +5 -0
  182. package/dist/features/exhaust/failure-branches.js +29 -11
  183. package/dist/features/exhaust/invariants.d.ts +112 -0
  184. package/dist/features/exhaust/invariants.js +188 -0
  185. package/dist/features/exhaust/ledger.d.ts +68 -0
  186. package/dist/features/exhaust/ledger.js +121 -13
  187. package/dist/features/exhaust/session-fold.d.ts +10 -0
  188. package/dist/features/exhaust/session-fold.js +46 -3
  189. package/dist/features/exhaust/session-port.d.ts +3 -1
  190. package/dist/features/exhaust/session-port.js +97 -28
  191. package/dist/features/grade/grade-answer.d.ts +99 -0
  192. package/dist/features/grade/grade-answer.js +112 -0
  193. package/dist/features/grade/grade-noise.d.ts +27 -0
  194. package/dist/features/grade/grade-noise.js +55 -0
  195. package/dist/features/grade/grade-renumber.d.ts +12 -0
  196. package/dist/features/grade/grade-renumber.js +86 -0
  197. package/dist/features/grade/grade-state.d.ts +50 -0
  198. package/dist/features/grade/grade-state.js +93 -0
  199. package/dist/features/grade/grade-suggest.d.ts +33 -0
  200. package/dist/features/grade/grade-suggest.js +98 -0
  201. package/dist/features/license/license.d.ts +11 -71
  202. package/dist/features/license/license.js +43 -136
  203. package/dist/features/visual/desktop-capture.d.ts +33 -0
  204. package/dist/features/visual/desktop-capture.js +94 -0
  205. package/dist/features/visual/step-shots.js +139 -35
  206. package/dist/features/visual/visual-tools.d.ts +0 -18
  207. package/dist/features/visual/visual-tools.js +67 -99
  208. package/dist/import-graph.js +5 -6
  209. package/dist/index.d.ts +3 -1
  210. package/dist/index.js +19 -7
  211. package/dist/judgement/capsule/causal-summary.js +9 -2
  212. package/dist/judgement/runs/artifact/replay-mapping.d.ts +13 -1
  213. package/dist/judgement/runs/artifact/replay-mapping.js +1 -1
  214. package/dist/judgement/runs/reticle-runner.js +16 -2
  215. package/dist/judgement/runs/run-ledger.d.ts +7 -5
  216. package/dist/judgement/runs/run-ledger.js +98 -69
  217. package/dist/judgement/runs/runner-port.d.ts +2 -0
  218. package/dist/judgement/runs/runner-port.js +23 -5
  219. package/dist/judgement/runs/verification-sync.d.ts +6 -3
  220. package/dist/judgement/runs/verification-sync.js +21 -10
  221. package/dist/language/flows/affected-tools.d.ts +1 -1
  222. package/dist/language/flows/affected-tools.js +49 -30
  223. package/dist/language/flows/change/git-changed.d.ts +2 -1
  224. package/dist/language/flows/change/git-changed.js +19 -2
  225. package/dist/language/flows/fields/flow-secret-field.d.ts +1 -13
  226. package/dist/language/flows/fields/flow-secret-field.js +77 -21
  227. package/dist/language/flows/flow-anchor.d.ts +60 -2
  228. package/dist/language/flows/flow-anchor.js +125 -20
  229. package/dist/language/flows/flow-classify.d.ts +20 -0
  230. package/dist/language/flows/flow-classify.js +90 -12
  231. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  232. package/dist/language/flows/flow-cross-step.js +25 -1
  233. package/dist/language/flows/flow-journey.d.ts +38 -4
  234. package/dist/language/flows/flow-journey.js +138 -8
  235. package/dist/language/flows/flow-replay-run.d.ts +0 -16
  236. package/dist/language/flows/flow-replay-run.js +76 -14
  237. package/dist/language/flows/flow-replay-types.d.ts +4 -2
  238. package/dist/language/flows/flow-replay.d.ts +19 -1
  239. package/dist/language/flows/flow-replay.js +169 -52
  240. package/dist/language/flows/flow-replayable.js +7 -1
  241. package/dist/language/flows/flow-start-path.d.ts +34 -5
  242. package/dist/language/flows/flow-start-path.js +202 -15
  243. package/dist/language/flows/flow-step-runners.d.ts +14 -13
  244. package/dist/language/flows/flow-step-runners.js +184 -109
  245. package/dist/language/flows/flow-store-for-session.d.ts +26 -25
  246. package/dist/language/flows/flow-store-for-session.js +51 -5
  247. package/dist/language/flows/flow-tools.js +46 -33
  248. package/dist/language/flows/flows.js +176 -76
  249. package/dist/language/flows/recording/tape/recordings.d.ts +21 -16
  250. package/dist/language/flows/recording/tape/recordings.js +112 -49
  251. package/dist/language/flows/replay.d.ts +36 -12
  252. package/dist/language/flows/replay.js +193 -50
  253. package/dist/language/flows/steps/page-steps.d.ts +68 -0
  254. package/dist/language/flows/steps/page-steps.js +198 -0
  255. package/dist/language/flows/suite/sequential-run.d.ts +68 -0
  256. package/dist/language/flows/suite/sequential-run.js +96 -0
  257. package/dist/language/flows/verify-change-tools.js +26 -15
  258. package/dist/launch-chromium.d.ts +1 -0
  259. package/dist/launch-chromium.js +49 -12
  260. package/dist/memory/cloud/background-sync.d.ts +13 -0
  261. package/dist/memory/cloud/background-sync.js +24 -3
  262. package/dist/memory/cloud/sync-daemon.js +26 -27
  263. package/dist/memory/cloud/sync-screenshots.js +6 -1
  264. package/dist/memory/journal/attach-journal.js +2 -1
  265. package/dist/memory/journal/drive-flow.d.ts +7 -0
  266. package/dist/memory/journal/drive-flow.js +44 -13
  267. package/dist/memory/journal/journal-recorder.d.ts +4 -2
  268. package/dist/memory/journal/session-journal.d.ts +7 -0
  269. package/dist/memory/journal/session-journal.js +58 -10
  270. package/dist/memory/project/root-claims.d.ts +9 -0
  271. package/dist/memory/project/root-claims.js +9 -4
  272. package/dist/portal/bridge/bridge.d.ts +13 -4
  273. package/dist/portal/bridge/bridge.js +10 -9
  274. package/dist/portal/input/download-capture.d.ts +7 -0
  275. package/dist/portal/input/download-capture.js +92 -0
  276. package/dist/portal/input/network-detail.d.ts +6 -0
  277. package/dist/portal/input/network-detail.js +12 -1
  278. package/dist/portal/input/network-mock-tools.js +49 -13
  279. package/dist/portal/input/network-mock.d.ts +8 -0
  280. package/dist/portal/input/network-mock.js +30 -10
  281. package/dist/portal/input/page-capture.d.ts +24 -0
  282. package/dist/portal/input/page-capture.js +33 -0
  283. package/dist/portal/input/real-input.d.ts +35 -18
  284. package/dist/portal/input/real-input.js +99 -33
  285. package/dist/portal/input/viewport-tools.d.ts +8 -0
  286. package/dist/portal/input/viewport-tools.js +81 -21
  287. package/dist/portal/pool/browser-pool.d.ts +16 -30
  288. package/dist/portal/pool/browser-pool.js +64 -52
  289. package/dist/portal/pool/context-permissions.d.ts +34 -17
  290. package/dist/portal/pool/context-permissions.js +94 -1
  291. package/dist/portal/pool/csp-widen.d.ts +62 -0
  292. package/dist/portal/pool/csp-widen.js +132 -0
  293. package/dist/portal/pool/determinism.d.ts +52 -0
  294. package/dist/portal/pool/determinism.js +259 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +34 -1
  296. package/dist/portal/pool/lease-emulation.js +18 -0
  297. package/dist/portal/pool/lease-marker-stamp.d.ts +6 -0
  298. package/dist/portal/pool/lease-marker-stamp.js +15 -1
  299. package/dist/portal/pool/lease-page-error.d.ts +56 -0
  300. package/dist/portal/pool/lease-page-error.js +160 -0
  301. package/dist/portal/pool/page-error-journal.d.ts +63 -0
  302. package/dist/portal/pool/page-error-journal.js +208 -0
  303. package/dist/portal/pool/playwright-launcher.js +71 -15
  304. package/dist/portal/pool/pool-contract.d.ts +49 -1
  305. package/dist/portal/pool/pool-lease.d.ts +70 -2
  306. package/dist/portal/pool/pool-lease.js +23 -0
  307. package/dist/portal/pool/zero-install.d.ts +8 -0
  308. package/dist/portal/pool/zero-install.js +91 -1
  309. package/dist/portal/session/dev-server/dev-command.d.ts +11 -2
  310. package/dist/portal/session/dev-server/dev-command.js +110 -16
  311. package/dist/portal/session/dev-server/dev-server-probe.d.ts +7 -0
  312. package/dist/portal/session/dev-server/dev-server-probe.js +9 -0
  313. package/dist/portal/session/dev-server/project-ports.d.ts +21 -0
  314. package/dist/portal/session/dev-server/project-ports.js +62 -0
  315. package/dist/portal/session/facts/departed-network.d.ts +66 -0
  316. package/dist/portal/session/facts/departed-network.js +142 -0
  317. package/dist/portal/session/no-session-diagnosis.d.ts +9 -0
  318. package/dist/portal/session/no-session-diagnosis.js +76 -27
  319. package/dist/portal/session/no-session-next-action.d.ts +14 -0
  320. package/dist/portal/session/no-session-next-action.js +56 -7
  321. package/dist/portal/session/no-session-watch.d.ts +6 -0
  322. package/dist/portal/session/no-session-watch.js +41 -4
  323. package/dist/portal/session/page-commands/undeclared-command.d.ts +9 -3
  324. package/dist/portal/session/page-commands/undeclared-command.js +16 -7
  325. package/dist/portal/session/recorded-gaps.d.ts +1 -1
  326. package/dist/portal/session/recorded-gaps.js +5 -2
  327. package/dist/portal/session/serving-directory.d.ts +10 -0
  328. package/dist/portal/session/serving-directory.js +39 -8
  329. package/dist/portal/session/session-manager.d.ts +10 -0
  330. package/dist/portal/session/session-manager.js +211 -81
  331. package/dist/portal/session/session.js +4 -3
  332. package/dist/portal/session/zero-install-first-call.d.ts +20 -1
  333. package/dist/portal/session/zero-install-first-call.js +34 -2
  334. package/dist/start-wiring.d.ts +30 -2
  335. package/dist/start-wiring.js +74 -9
  336. package/dist/surface/mcp/mcp-proxy.js +10 -2
  337. package/dist/surface/mcp/mcp.js +8 -5
  338. package/dist/surface/mcp/peer/agents-connected.d.ts +6 -0
  339. package/dist/surface/mcp/peer/agents-connected.js +58 -0
  340. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +17 -5
  341. package/dist/surface/mcp/shared-params.d.ts +2 -0
  342. package/dist/surface/mcp/shared-params.js +31 -0
  343. package/dist/surface/tools/act/act-observation.d.ts +40 -2
  344. package/dist/surface/tools/act/act-observation.js +118 -12
  345. package/dist/surface/tools/act/act-preflight.js +38 -18
  346. package/dist/surface/tools/act/act-sequence-retry.d.ts +23 -2
  347. package/dist/surface/tools/act/act-sequence-retry.js +61 -5
  348. package/dist/surface/tools/act/act-target.js +3 -1
  349. package/dist/surface/tools/act/after-match.d.ts +10 -0
  350. package/dist/surface/tools/act/after-match.js +40 -0
  351. package/dist/surface/tools/act/already-true.js +1 -1
  352. package/dist/surface/tools/act/navigation/reload-result.d.ts +12 -1
  353. package/dist/surface/tools/act/navigation/reload-result.js +25 -2
  354. package/dist/surface/tools/act/resolve-target.d.ts +17 -1
  355. package/dist/surface/tools/act/resolve-target.js +59 -9
  356. package/dist/surface/tools/act/sequence-grade.d.ts +15 -1
  357. package/dist/surface/tools/act/sequence-grade.js +45 -27
  358. package/dist/surface/tools/act/settle-in-flight.js +27 -15
  359. package/dist/surface/tools/act-command.d.ts +23 -0
  360. package/dist/surface/tools/act-command.js +50 -0
  361. package/dist/surface/tools/act-sequence-tool.js +81 -50
  362. package/dist/surface/tools/act-tools.d.ts +1 -13
  363. package/dist/surface/tools/act-tools.js +83 -95
  364. package/dist/surface/tools/agent/build-staleness.d.ts +1 -1
  365. package/dist/surface/tools/agent/build-staleness.js +1 -1
  366. package/dist/surface/tools/assert/assert-verdict.js +18 -12
  367. package/dist/surface/tools/browser-tools.js +87 -13
  368. package/dist/surface/tools/compare-tools.d.ts +11 -0
  369. package/dist/surface/tools/compare-tools.js +94 -0
  370. package/dist/surface/tools/coverage-tools.js +1 -1
  371. package/dist/surface/tools/dynamic-tools.js +11 -3
  372. package/dist/surface/tools/empty-session-list.d.ts +2 -0
  373. package/dist/surface/tools/empty-session-list.js +4 -2
  374. package/dist/surface/tools/error-recovery.d.ts +12 -1
  375. package/dist/surface/tools/error-recovery.js +131 -40
  376. package/dist/surface/tools/explore-tools.js +1 -1
  377. package/dist/surface/tools/invoke-tool.js +29 -21
  378. package/dist/surface/tools/lease-coverage-tools.d.ts +49 -0
  379. package/dist/surface/tools/lease-coverage-tools.js +128 -0
  380. package/dist/surface/tools/lease-hint.d.ts +42 -1
  381. package/dist/surface/tools/lease-hint.js +52 -3
  382. package/dist/surface/tools/lease-readiness.d.ts +47 -0
  383. package/dist/surface/tools/lease-readiness.js +126 -0
  384. package/dist/surface/tools/lease-seed.d.ts +16 -1
  385. package/dist/surface/tools/lease-seed.js +37 -4
  386. package/dist/surface/tools/lease-tools.d.ts +3 -41
  387. package/dist/surface/tools/lease-tools.js +104 -124
  388. package/dist/surface/tools/lease-url-identity.d.ts +46 -0
  389. package/dist/surface/tools/lease-url-identity.js +97 -0
  390. package/dist/surface/tools/merge-tools.js +99 -2
  391. package/dist/surface/tools/merged-name-redirect.js +5 -1
  392. package/dist/surface/tools/observe-tools.js +15 -9
  393. package/dist/surface/tools/read/console-pre-attach.d.ts +19 -0
  394. package/dist/surface/tools/read/console-pre-attach.js +23 -0
  395. package/dist/surface/tools/read-tools.js +33 -30
  396. package/dist/surface/tools/real-input-attempt.d.ts +0 -8
  397. package/dist/surface/tools/real-input-attempt.js +143 -28
  398. package/dist/surface/tools/repeat-hint.d.ts +40 -0
  399. package/dist/surface/tools/repeat-hint.js +171 -0
  400. package/dist/surface/tools/run-report.d.ts +2 -2
  401. package/dist/surface/tools/run-report.js +27 -15
  402. package/dist/surface/tools/session-ports.d.ts +14 -0
  403. package/dist/surface/tools/session-ports.js +53 -0
  404. package/dist/surface/tools/tool-kit.d.ts +18 -0
  405. package/dist/surface/tools/tool-kit.js +9 -3
  406. package/dist/surface/tools/tool-surface.js +0 -1
  407. package/dist/surface/tools/tools.js +54 -18
  408. package/dist/surface/tools/type-spelling.d.ts +13 -0
  409. package/dist/surface/tools/type-spelling.js +36 -0
  410. package/dist/telemetry/agent-client.d.ts +6 -0
  411. package/dist/telemetry/agent-client.js +10 -0
  412. package/dist/telemetry/argument-shape.js +17 -7
  413. package/dist/telemetry/cli-telemetry.d.ts +10 -1
  414. package/dist/telemetry/cli-telemetry.js +15 -0
  415. package/dist/telemetry/init-telemetry.d.ts +2 -1
  416. package/dist/telemetry/init-telemetry.js +47 -2
  417. package/dist/telemetry/install-trace.js +23 -4
  418. package/dist/telemetry/onboarding-funnel.d.ts +19 -2
  419. package/dist/telemetry/onboarding-funnel.js +25 -3
  420. package/dist/telemetry/proxy-telemetry.d.ts +2 -1
  421. package/dist/telemetry/proxy-telemetry.js +2 -2
  422. package/dist/telemetry/session-metrics.d.ts +1 -1
  423. package/dist/telemetry/session-metrics.js +67 -27
  424. package/dist/telemetry/telemetry.d.ts +3 -1
  425. package/dist/telemetry/telemetry.js +60 -28
  426. package/dist/telemetry/tool-refused.d.ts +6 -3
  427. package/dist/telemetry/tool-refused.js +15 -3
  428. package/docs/actions.mdx +3 -3
  429. package/docs/agent-cheatsheet.md +1 -1
  430. package/docs/architecture.md +3 -6
  431. package/docs/capabilities.mdx +61 -1
  432. package/docs/cli/affected.mdx +9 -7
  433. package/docs/cli/cloud.mdx +3 -3
  434. package/docs/cli/compare.mdx +94 -0
  435. package/docs/cli/doctor.mdx +41 -2
  436. package/docs/cli/grade.mdx +97 -0
  437. package/docs/cli/help.mdx +4 -2
  438. package/docs/cli/license.mdx +13 -12
  439. package/docs/cli/restart.mdx +7 -5
  440. package/docs/cli/rollback.mdx +5 -5
  441. package/docs/cli/setup.mdx +13 -2
  442. package/docs/cli/status.mdx +4 -0
  443. package/docs/cli/stop.mdx +3 -3
  444. package/docs/cli/update.mdx +2 -2
  445. package/docs/cli/verify.mdx +23 -1
  446. package/docs/cli.mdx +34 -24
  447. package/docs/deploy-checks.md +25 -0
  448. package/docs/desktop.mdx +1 -1
  449. package/docs/enterprise.md +17 -22
  450. package/docs/environment.mdx +1 -0
  451. package/docs/first-drive.md +1 -1
  452. package/docs/flows.md +11 -1
  453. package/docs/frameworks.mdx +9 -9
  454. package/docs/getting-started.md +1 -1
  455. package/docs/install-manual.mdx +16 -1
  456. package/docs/license-activation.mdx +3 -3
  457. package/docs/packages/engine.mdx +1 -1
  458. package/docs/packages/server.mdx +1 -1
  459. package/docs/packages/tauri.mdx +1 -1
  460. package/docs/packages/test.mdx +1 -1
  461. package/docs/packages.mdx +1 -1
  462. package/docs/platform-integration.md +1 -1
  463. package/docs/predicates.mdx +1 -1
  464. package/docs/quickstart.mdx +68 -49
  465. package/docs/skill-setup.md +1 -1
  466. package/docs/skill.md +14 -13
  467. package/docs/telemetry.md +6 -4
  468. package/docs/tools/navigate.mdx +1 -1
  469. package/docs/tools/verify.mdx +4 -1
  470. package/docs/troubleshooting.mdx +1 -1
  471. package/docs/usage.md +17 -14
  472. package/package.json +18 -14
  473. package/LICENSE-ENTERPRISE +0 -37
  474. package/dist/features/ee/audit-log.d.ts +0 -14
  475. package/dist/features/ee/audit-log.js +0 -11
  476. package/dist/features/exhaust/exhaust-run.d.ts +0 -33
  477. package/dist/features/exhaust/exhaust-run.js +0 -82
@@ -1,142 +1,171 @@
1
1
  /**
2
- * The run ledger: what one agent run checked, saved and read, kept until its report is taken.
2
+ * The run ledger: what each agent run checked, saved and read, kept until its report is taken.
3
3
  *
4
- * A run is the agent's calls from its first Reticle call to the call that ends it (a session end, a
4
+ * A run is one agent's calls from its first Reticle call to the call that ends it (a session end, a
5
5
  * yield, a released tab). The verdicts come from the journal records the agent's own calls wrote;
6
- * the Harness's are never counted. Taking the report empties the ledger, so the next run starts at
7
- * zero.
6
+ * the Harness's are never counted. Taking the report ends that run, so the agent's next run starts
7
+ * at zero.
8
8
  *
9
- * A call from another agent (another MCP attach id) starts a new run. An agent that stops without a
10
- * call that ends its run then does not leak its claims into the next agent's report.
9
+ * The ledger keeps one run for each MCP attach id. Two agents on one daemon (two worktrees of one
10
+ * project) call in turn. When the ledger kept one run, each call restarted the other agent's run,
11
+ * and a released lease reported the other agent's claims and none of its own. A record goes to the
12
+ * run of the connection that wrote it, and a call that ends a run takes the caller's run (#1900).
11
13
  *
12
- * ponytail: one ledger for each daemon, not for each agent. Two agents that call at the same time
13
- * restart each other's run. Key the ledger by attach id when that happens.
14
+ * A record from no connection (the HUD, the CLI, an agent record that ends outside its call
15
+ * context) goes to the run of the agent that called last. An agent that stops without a call that
16
+ * ends its run leaves its run here. That run is dropped when it is idle for `RUN_IDLE_LIMIT_MS`.
14
17
  */
15
18
  import { supersededChecks } from '@reticlehq/engine/evidence/superseded-checks.js';
16
19
  import { JournalVerdictEffectSchema, ReticleTool, Verified, } from '@reticlehq/core';
20
+ import { callingAttachId } from '../../hooks/coding-agents.js';
17
21
  const SAW = 'saw ';
18
22
  const FLOW = 'flow ';
23
+ /** A run with no agent call for this long is dropped. A working agent calls much more often. */
24
+ export const RUN_IDLE_LIMIT_MS = 6 * 60 * 60 * 1000;
19
25
  /** One piece of evidence for a claim: what the check saw, else the source line it drove. */
20
26
  function evidenceOf(effect) {
21
- if (effect.observed !== undefined)
27
+ if (effect.observed !== undefined) {
22
28
  return `${SAW}${effect.observed}`;
29
+ }
23
30
  return effect.source;
24
31
  }
25
32
  /** `no` when anything failed, `yes` only when something held and nothing was undecided. */
26
33
  function runVerified(all) {
27
- if (all.includes(Verified.NO))
34
+ if (all.includes(Verified.NO)) {
28
35
  return Verified.NO;
29
- if (0 === all.length || all.some((v) => Verified.YES !== v))
36
+ }
37
+ if (0 === all.length || all.some((v) => Verified.YES !== v)) {
30
38
  return Verified.UNKNOWN;
39
+ }
31
40
  return Verified.YES;
32
41
  }
42
+ const openRun = (now) => ({
43
+ startedAt: now,
44
+ lastAt: now,
45
+ firstVerdictAt: undefined,
46
+ verdicts: [],
47
+ saved: new Set(),
48
+ replayed: new Map(),
49
+ written: 0,
50
+ read: new Set(),
51
+ });
33
52
  export class RunLedger {
34
- #owner;
35
- #startedAt;
36
- #firstVerdictAt;
37
- #verdicts = [];
38
- #saved = new Set();
39
- #replayed = new Map();
40
- #written = 0;
41
- #read = new Set();
42
- /** An agent call starts. The first one starts the run, and a call from another agent starts a new one. */
53
+ #runs = new Map();
54
+ #last;
55
+ /** An agent call starts. The agent's first call starts its run. A run idle too long is dropped. */
43
56
  begin(now, owner) {
44
- if (this.#owner !== owner)
45
- this.#reset();
46
- this.#owner = owner;
47
- this.#startedAt ??= now;
57
+ for (const [id, run] of this.#runs) {
58
+ if (now - run.lastAt > RUN_IDLE_LIMIT_MS) {
59
+ this.#runs.delete(id);
60
+ }
61
+ }
62
+ const run = this.#runs.get(owner) ?? openRun(now);
63
+ run.lastAt = now;
64
+ this.#runs.set(owner, run);
65
+ this.#last = owner;
48
66
  }
49
67
  /** An agent call ended. The first one that left a verdict sets the time to the first verdict. */
50
- after(now) {
51
- if (0 < this.#verdicts.length || 0 < this.#replayed.size)
52
- this.#firstVerdictAt ??= now;
68
+ after(now, owner) {
69
+ const run = this.#run(owner);
70
+ if (run === undefined) {
71
+ return;
72
+ }
73
+ run.lastAt = Math.max(run.lastAt, now);
74
+ if (0 < run.verdicts.length || 0 < run.replayed.size) {
75
+ run.firstVerdictAt ??= now;
76
+ }
53
77
  }
54
78
  /** A journal record from the agent's own call. A record with no verdict is not a claim. */
55
79
  verdict(action) {
56
- if (this.#idle() || action.drivenBy !== undefined)
80
+ const run = this.#run();
81
+ if (run === undefined || action.drivenBy !== undefined) {
57
82
  return;
83
+ }
58
84
  // A replay is counted once, as a flow, decided as its run decides it (`replayed`). Its journal
59
85
  // record said `unknown` where the run said `no`, and one report gave both answers.
60
- if (ReticleTool.FLOW_REPLAY === action.tool)
86
+ if (ReticleTool.FLOW_REPLAY === action.tool) {
61
87
  return;
88
+ }
62
89
  const parsed = JournalVerdictEffectSchema.safeParse(action.effect);
63
- if (parsed.success)
64
- this.#verdicts.push(parsed.data);
90
+ if (parsed.success) {
91
+ run.verdicts.push(parsed.data);
92
+ }
65
93
  }
66
94
  flowSaved(name) {
67
- if (!this.#idle())
68
- this.#saved.add(name);
95
+ this.#run()?.saved.add(name);
69
96
  }
70
97
  /** The last replay of a flow in this run is its verdict. */
71
98
  replayed(name, verified) {
72
- if (!this.#idle())
73
- this.#replayed.set(name, verified);
99
+ this.#run()?.replayed.set(name, verified);
74
100
  }
75
101
  memoryWritten(count = 1) {
76
- if (!this.#idle())
77
- this.#written += count;
102
+ const run = this.#run();
103
+ if (run !== undefined) {
104
+ run.written += count;
105
+ }
78
106
  }
79
107
  /** Notes given to the agent. Each one counts once, however often it is shown. */
80
108
  memoryRead(notes) {
81
- if (this.#idle())
109
+ const run = this.#run();
110
+ if (run === undefined) {
82
111
  return;
83
- for (const note of notes)
84
- this.#read.add(note);
112
+ }
113
+ for (const note of notes) {
114
+ run.read.add(note);
115
+ }
116
+ }
117
+ isEmpty(owner) {
118
+ return this.#run(owner) === undefined;
85
119
  }
86
- isEmpty() {
87
- return this.#idle();
120
+ /** The named owner, else the calling connection, else the agent that called last. */
121
+ #owner(owner) {
122
+ return owner ?? callingAttachId() ?? this.#last;
88
123
  }
89
124
  /**
90
- * No agent run is open. A CLI `reticle verify` replays through the same code, and what it did is
91
- * not the next agent's run, so nothing is kept until an agent call begins one.
125
+ * The run a record belongs to. None while no agent call has begun one: a CLI `reticle verify`
126
+ * replays through the same code, and what it did is not the next agent's run.
92
127
  */
93
- #idle() {
94
- return this.#startedAt === undefined;
128
+ #run(owner) {
129
+ const id = this.#owner(owner);
130
+ return id === undefined ? undefined : this.#runs.get(id);
95
131
  }
96
- /** The report, without the cloud line (the caller knows the project). Empties the ledger. */
97
- take(now) {
98
- const started = this.#startedAt ?? now;
132
+ /** The owner's report, without the cloud line (the caller knows the project). Ends that run. */
133
+ take(now, owner) {
134
+ const id = this.#owner(owner);
135
+ const run = this.#run(owner) ?? openRun(now);
136
+ if (id !== undefined) {
137
+ this.#runs.delete(id);
138
+ }
139
+ const started = run.startedAt;
99
140
  // A passive check that read too early is not counted: the rule every fold applies.
100
- const superseded = supersededChecks(this.#verdicts.map((v) => ({
141
+ const superseded = supersededChecks(run.verdicts.map((v) => ({
101
142
  key: v.claim,
102
143
  passive: false === v.declaredBeforeActing,
103
144
  held: Verified.YES === v.verified,
104
145
  failed: Verified.NO === v.verified,
105
146
  })));
106
- const counted = this.#verdicts.filter((_, at) => !superseded.has(at));
147
+ const counted = run.verdicts.filter((_, at) => !superseded.has(at));
107
148
  const claims = counted.map((v) => {
108
149
  const evidence = evidenceOf(v);
109
150
  return evidence === undefined
110
151
  ? { claim: v.claim, verified: v.verified }
111
152
  : { claim: v.claim, verified: v.verified, evidence };
112
153
  });
113
- const replayed = [...this.#replayed].map(([name, verified]) => ({ name, verified }));
114
- const report = {
154
+ const replayed = [...run.replayed].map(([name, verified]) => ({ name, verified }));
155
+ return {
115
156
  verified: runVerified([...claims.map((c) => c.verified), ...replayed.map((r) => r.verified)]),
116
157
  claims,
117
158
  caught: [
118
159
  ...claims.filter((c) => Verified.NO === c.verified).map((c) => c.claim),
119
160
  ...replayed.filter((r) => Verified.NO === r.verified).map((r) => `${FLOW}${r.name}`),
120
161
  ],
121
- flows: { saved: [...this.#saved], replayed },
122
- memory: { written: this.#written, read: this.#read.size },
162
+ flows: { saved: [...run.saved], replayed },
163
+ memory: { written: run.written, read: run.read.size },
123
164
  wallMs: Math.max(0, now - started),
124
- ...(this.#firstVerdictAt === undefined
165
+ ...(run.firstVerdictAt === undefined
125
166
  ? {}
126
- : { firstVerdictMs: Math.max(0, this.#firstVerdictAt - started) }),
167
+ : { firstVerdictMs: Math.max(0, run.firstVerdictAt - started) }),
127
168
  };
128
- this.#reset();
129
- return report;
130
- }
131
- #reset() {
132
- this.#owner = undefined;
133
- this.#startedAt = undefined;
134
- this.#firstVerdictAt = undefined;
135
- this.#verdicts = [];
136
- this.#saved = new Set();
137
- this.#replayed = new Map();
138
- this.#written = 0;
139
- this.#read = new Set();
140
169
  }
141
170
  }
142
171
  /** The daemon's ledger. */
@@ -12,4 +12,6 @@ export declare function createRunnerPort(deps: ToolDeps, sessionId?: string,
12
12
  /** `reticle verify --confirm-dangerous`: this run acknowledges the steps held as destructive. */
13
13
  opts?: {
14
14
  confirmDangerous?: boolean;
15
+ requireStartControl?: boolean;
16
+ sweep?: boolean;
15
17
  }): RunnerPort;
@@ -4,7 +4,10 @@
4
4
  * and a uuid generator. The ReticleRunner core (tested with a fake port) holds all the orchestration and
5
5
  * verdict logic, so this layer carries no decisions.
6
6
  */
7
+ import { ReplayStatus } from '@reticlehq/core';
7
8
  import { replayAndLearn } from '../../language/flows/flow-learning.js';
9
+ import { sessionUrlOf } from '../../language/flows/flow-lease.js';
10
+ import { flowStartState } from '../../surface/tools/session-ports.js';
8
11
  import { flowsForSession } from '../../language/flows/flow-store-for-session.js';
9
12
  import { safeSessionTarget } from '../../memory/project/session-root.js';
10
13
  import { defaultRunId } from './default-run-id.js';
@@ -13,17 +16,32 @@ export { defaultRunId } from './default-run-id.js';
13
16
  export function createRunnerPort(deps, sessionId,
14
17
  /** `reticle verify --confirm-dangerous`: this run acknowledges the steps held as destructive. */
15
18
  opts = {}) {
19
+ // Each flow starts from the state the run started in, so one that signs out cannot fail the rest.
20
+ const startState = flowStartState(deps.realInput, () => sessionUrlOf(deps, sessionId));
16
21
  return {
17
22
  // Resolved as replay resolves it, so every listed name is one replay can load.
18
23
  listFlows: () => {
19
24
  const target = safeSessionTarget(deps, sessionId);
20
25
  return flowsForSession(deps, target).flows.list(target.projectId);
21
26
  },
22
- replayFlow: (name) => replayAndLearn(deps, {
23
- flowName: name,
24
- ...(sessionId === undefined ? {} : { sessionId }),
25
- ...(true === opts.confirmDangerous ? { confirmDangerous: true } : {}),
26
- }),
27
+ replayFlow: async (name) => {
28
+ const cannotStart = await startState();
29
+ if (cannotStart !== undefined) {
30
+ return {
31
+ name,
32
+ status: ReplayStatus.UNVERIFIABLE,
33
+ steps: [],
34
+ unverifiable: { reason: cannotStart },
35
+ };
36
+ }
37
+ return await replayAndLearn(deps, {
38
+ flowName: name,
39
+ ...(sessionId === undefined ? {} : { sessionId }),
40
+ ...(true === opts.confirmDangerous ? { confirmDangerous: true } : {}),
41
+ ...(true === opts.requireStartControl ? { requireStartControl: true } : {}),
42
+ ...(true === opts.sweep ? { sweep: true } : {}),
43
+ });
44
+ },
27
45
  now: () => deps.now(),
28
46
  newRunId: defaultRunId,
29
47
  };
@@ -1,5 +1,6 @@
1
1
  import { type FlowFile, type FlowReplayResult } from '@reticlehq/core';
2
2
  import { type VerificationRunInput } from './artifact/build-verification-run.js';
3
+ import { AutomationHint } from '@reticlehq/core/telemetry';
3
4
  import { type ProjectTarget } from '../../memory/project/session-root.js';
4
5
  import type { ToolDeps } from '../../surface/tools/tool-kit.js';
5
6
  /** A replay plus the wall-clock time it took — the shape the verify handler already collects. */
@@ -12,8 +13,10 @@ export interface TimedReplay {
12
13
  /** The MCP client name `reticle verify` (the command line, CI's path) connects to a daemon as. */
13
14
  export declare const CLI_CLIENT_NAME = "reticle-cli";
14
15
  /**
15
- * Who ran the command line, and why. On a CI runner it is the pipeline; anywhere else it is the
16
- * person who holds the key, so the cloud credits them and the run does not read as CI.
16
+ * Who ran the command line, and why. Off CI it is the person who holds the key, so the cloud
17
+ * credits them. On CI the `automation` hint says which kind: a CI vendor runner is the pipeline,
18
+ * trigger `ci`; a coding-agent sandbox is a coding agent. A container, or `CI` with no vendor,
19
+ * keeps trigger `oem`, because the cloud has no value for either yet.
17
20
  */
18
- export declare function cliRunAuthor(env: NodeJS.ProcessEnv): Pick<VerificationRunInput, 'agent' | 'trigger'>;
21
+ export declare function cliRunAuthor(env: NodeJS.ProcessEnv, automation?: AutomationHint | undefined): Pick<VerificationRunInput, 'agent' | 'trigger'>;
19
22
  export declare function persistAndSyncVerificationRun(deps: ToolDeps, timed: TimedReplay[], target: ProjectTarget): Promise<string | undefined>;
@@ -21,26 +21,37 @@ import { RunStore } from './artifact/run-store.js';
21
21
  import { cloudFetch, syncRunToCloud, SyncOutcome } from '../../memory/cloud/cloud-sync.js';
22
22
  import { resolveProjectCloud } from '../../memory/cloud/cloud-config.js';
23
23
  import { log } from '../../log.js';
24
- import { isCiEnv } from '../../telemetry/automation-hint.js';
24
+ import { currentAutomationHint, isCiEnv } from '../../telemetry/automation-hint.js';
25
+ import { AutomationHint } from '@reticlehq/core/telemetry';
25
26
  import { rootForTarget } from '../../memory/project/session-root.js';
26
27
  /** The author of record when no MCP peer introduced itself — a CLI run, or a client that skipped the handshake. */
27
28
  const RETICLE_MCP_AGENT_ID = 'reticle-mcp';
28
29
  /** The MCP client name `reticle verify` (the command line, CI's path) connects to a daemon as. */
29
30
  export const CLI_CLIENT_NAME = 'reticle-cli';
30
31
  /**
31
- * Who ran the command line, and why. On a CI runner it is the pipeline; anywhere else it is the
32
- * person who holds the key, so the cloud credits them and the run does not read as CI.
32
+ * Who ran the command line, and why. Off CI it is the person who holds the key, so the cloud
33
+ * credits them. On CI the `automation` hint says which kind: a CI vendor runner is the pipeline,
34
+ * trigger `ci`; a coding-agent sandbox is a coding agent. A container, or `CI` with no vendor,
35
+ * keeps trigger `oem`, because the cloud has no value for either yet.
33
36
  */
34
- export function cliRunAuthor(env) {
35
- return isCiEnv(env)
36
- ? {
37
- agent: { id: CLI_CLIENT_NAME, kind: RunAgentKind.OEM_PIPELINE },
38
- trigger: { kind: RunTrigger.OEM },
39
- }
40
- : {
37
+ export function cliRunAuthor(env, automation = currentAutomationHint(env)) {
38
+ if (!isCiEnv(env)) {
39
+ return {
41
40
  agent: { id: CLI_CLIENT_NAME, kind: RunAgentKind.HUMAN },
42
41
  trigger: { kind: RunTrigger.MANUAL },
43
42
  };
43
+ }
44
+ if (AutomationHint.AGENT_SANDBOX === automation) {
45
+ return {
46
+ agent: { id: CLI_CLIENT_NAME, kind: RunAgentKind.CODING_AGENT },
47
+ trigger: { kind: RunTrigger.MANUAL },
48
+ };
49
+ }
50
+ const trigger = AutomationHint.CI_RUNNER === automation ? RunTrigger.CI : RunTrigger.OEM;
51
+ return {
52
+ agent: { id: CLI_CLIENT_NAME, kind: RunAgentKind.OEM_PIPELINE },
53
+ trigger: { kind: trigger },
54
+ };
44
55
  }
45
56
  /** Who ran a suite, and why: the command line by `cliRunAuthor`, any other client as a coding agent. */
46
57
  function agentAndTrigger(client) {
@@ -1,4 +1,4 @@
1
- import type { ToolDef } from '../../surface/tools/tool-kit.js';
1
+ import { type ToolDef } from '../../surface/tools/tool-kit.js';
2
2
  /**
3
3
  * `reticle_affected` — which saved flows must re-verify for a set of changed files.
4
4
  *
@@ -1,10 +1,40 @@
1
1
  import { z } from 'zod';
2
- import { ReticleTool } from '@reticlehq/core';
3
- import { loadNamedFlows, resolveChangedFiles } from '../../command/cli/cli-flow-commands.js';
4
- import { projectDirFor } from '../../memory/project/session-root.js';
5
- import { sessionRoot, sessionProjectId } from '../../memory/project/session-root.js';
2
+ import { asString, ReticleTool } from '@reticlehq/core';
3
+ import { sessionIdShape } from '../../surface/tools/tool-kit.js';
4
+ import { resolveChangedFiles } from '../../command/cli/cli-flow-commands.js';
5
+ import { namedFlowsForSession } from './flow-store-for-session.js';
6
6
  import { affectedSavedFlows } from './change/flow-sources.js';
7
7
  import { RECORD_A_FLOW } from './suite/coverage.js';
8
+ /**
9
+ * Why the answer is empty, when that needs saying.
10
+ *
11
+ * Several situations produced the same empty answer: no files changed, no flows saved, and a git
12
+ * ref that resolved to nothing. Only the first means "nothing to re-verify". The others mean the
13
+ * question could not be answered, and re-running nothing on that basis is how a regression ships.
14
+ */
15
+ function emptyAnswerReason(facts) {
16
+ const { changed, since, fileCount, flowCount, changedCount, unmatchedRoot } = facts;
17
+ // No folder declares this project, so nothing here is about a checkout (#1550).
18
+ if (unmatchedRoot !== undefined) {
19
+ return `no flows here: no folder on disk declares this project, so its evidence goes to ${unmatchedRoot}. Run \`reticle init\` in the app's folder, or lease the tab from there.`;
20
+ }
21
+ // A git failure OUTRANKS every other explanation: the others describe a question that was
22
+ // answered, and this one is a question that was not. Reporting "nothing changed" over a mistyped
23
+ // ref or a shallow clone is how a regression ships past the tool meant to catch it.
24
+ if (true === changed.failed) {
25
+ return `could not read the diff for \`${String(since)}\`, so NOTHING was compared and this result proves nothing: ${changed.reason ?? 'git failed'}`;
26
+ }
27
+ if (0 === flowCount) {
28
+ return `no saved flows exist yet, so nothing COULD be affected. ${RECORD_A_FLOW}`;
29
+ }
30
+ if (0 !== changedCount) {
31
+ return undefined;
32
+ }
33
+ if (since === undefined && 0 === fileCount) {
34
+ return 'no files were given and no `since` ref was passed, so nothing was compared — pass the files you edited, or a git ref';
35
+ }
36
+ return 'nothing changed against that input, so no saved flow needs re-verifying';
37
+ }
8
38
  /**
9
39
  * `reticle_affected` — which saved flows must re-verify for a set of changed files.
10
40
  *
@@ -27,6 +57,7 @@ export const AFFECTED_TOOLS = [
27
57
  description: 'Which saved flows must re-verify for a set of changed files. Pass the files you edited (and/or `since` for a git ref to diff against). Returns { changedFiles, affected, unknownProvenance } — `affected` is what to re-run, and `unknownProvenance` are flows included only because Reticle cannot tell which sources they cover, so they are re-verified by default rather than silently skipped.',
28
58
  example: { files: ['src/App.tsx'] },
29
59
  inputSchema: {
60
+ ...sessionIdShape,
30
61
  files: z
31
62
  .array(z.string())
32
63
  .optional()
@@ -46,34 +77,22 @@ export const AFFECTED_TOOLS = [
46
77
  ? args['files'].filter((f) => 'string' === typeof f)
47
78
  : [];
48
79
  const since = 'string' === typeof args['since'] ? args['since'] : undefined;
49
- // Same address as verify_change, resolved the same way. `deps.reticleRoot` is NOT the project
50
- // directory this line used to claim it was — it is the daemon's `.reticle` subdirectory, in
51
- // whichever tree the MCP host was started in. `undefined` here resolves the single connected
52
- // session, which is the same rule the flow lookup below already follows.
53
- const changed = await resolveChangedFiles(files, since, projectDirFor(deps, undefined));
80
+ // The project of the tab being driven, not the folder the daemon started in (#1550). The flows
81
+ // come from the store `flows` replays from, so a flow named here can be replayed by that name
82
+ // (#1996). `git diff` runs in the project directory that holds that store.
83
+ const { flows, projectDir, unmatchedRoot } = await namedFlowsForSession(deps, asString(args['sessionId']));
84
+ // A bucket of evidence is not a tree, so a `since` has nothing to diff against.
85
+ const changed = await resolveChangedFiles(files, unmatchedRoot === undefined ? since : undefined, projectDir);
54
86
  const changedFiles = changed.files;
55
- // No `sessionId` on this tool's surface, and it does not need one: passing `undefined`
56
- // resolves the single connected session, and falls back exactly as before when it cannot.
57
- // Adding an argument here would be a surface change to fix an addressing bug.
58
- const flows = await loadNamedFlows(deps.fs, sessionRoot(deps, undefined), sessionProjectId(deps, undefined));
59
87
  const result = affectedSavedFlows(flows, changedFiles);
60
- // Three different situations produced the same empty answer: no files changed, no flows saved,
61
- // and a git ref that resolved to nothing. Only the first means "nothing to re-verify"; the
62
- // others mean the question could not be answered, and re-running nothing on that basis is how a
63
- // regression ships. Say which one it is.
64
- const why =
65
- // A git failure OUTRANKS every other explanation: the others describe a question that was
66
- // answered, and this one is a question that was not. Reporting "nothing changed" over a
67
- // mistyped ref or a shallow clone is how a regression ships past the tool meant to catch it.
68
- changed.failed
69
- ? `could not read the diff for \`${String(since)}\`, so NOTHING was compared and this result proves nothing: ${changed.reason ?? 'git failed'}`
70
- : 0 === flows.length
71
- ? `no saved flows exist yet, so nothing COULD be affected. ${RECORD_A_FLOW}`
72
- : 0 === changedFiles.length
73
- ? since === undefined && 0 === files.length
74
- ? 'no files were given and no `since` ref was passed, so nothing was compared — pass the files you edited, or a git ref'
75
- : 'nothing changed against that input, so no saved flow needs re-verifying'
76
- : undefined;
88
+ const why = emptyAnswerReason({
89
+ changed,
90
+ since,
91
+ fileCount: files.length,
92
+ flowCount: flows.length,
93
+ changedCount: changedFiles.length,
94
+ unmatchedRoot,
95
+ });
77
96
  return {
78
97
  changedFiles,
79
98
  ...result,
@@ -17,7 +17,8 @@ export interface ChangedFiles {
17
17
  }
18
18
  /**
19
19
  * Files changed since a git ref (`git diff --name-only <ref>`), so `reticle gate --since main` works
20
- * from the real diff instead of hand-listed files.
20
+ * from the real diff instead of hand-listed files. Files under Reticle's own directory are left
21
+ * out: a replay writes them, and they are not a change to the app's code.
21
22
  *
22
23
  * Never throws, and never pretends. The CLI gate may still degrade to "no changes" and pass rather
23
24
  * than crash CI — that reasoning was right and is unchanged — but it now has to opt into doing so by
@@ -1,5 +1,6 @@
1
1
  import { execFile } from 'node:child_process';
2
2
  import { promisify } from 'node:util';
3
+ import { ReticleDir } from '@reticlehq/core';
3
4
  const run = promisify(execFile);
4
5
  /** Parse `git diff --name-only` output into a clean file list. Pure; exported for testing. */
5
6
  export function parseGitFiles(output) {
@@ -19,9 +20,22 @@ export function parseGitFiles(output) {
19
20
  function refIsOptionLike(ref) {
20
21
  return ref.startsWith('-');
21
22
  }
23
+ /**
24
+ * True when a diff path sits under Reticle's own project directory.
25
+ *
26
+ * A replay writes intent, impact and episode files into that directory. Those writes are
27
+ * Reticle's output, not a change to the app's code. A flow with no source stamps reads any
28
+ * change as "affected", so counting them marked flows the gate had just proved as uncovered
29
+ * (#2050). The directory can sit below the repo root, so any path segment counts. `git diff`
30
+ * prints paths with `/` on every platform.
31
+ */
32
+ function isReticleOwnPath(path) {
33
+ return path.split('/').includes(ReticleDir.ROOT);
34
+ }
22
35
  /**
23
36
  * Files changed since a git ref (`git diff --name-only <ref>`), so `reticle gate --since main` works
24
- * from the real diff instead of hand-listed files.
37
+ * from the real diff instead of hand-listed files. Files under Reticle's own directory are left
38
+ * out: a replay writes them, and they are not a change to the app's code.
25
39
  *
26
40
  * Never throws, and never pretends. The CLI gate may still degrade to "no changes" and pass rather
27
41
  * than crash CI — that reasoning was right and is unchanged — but it now has to opt into doing so by
@@ -38,7 +52,10 @@ export async function changedFilesSince(ref, cwd) {
38
52
  }
39
53
  try {
40
54
  const { stdout } = await run('git', ['diff', '--name-only', ref], { cwd });
41
- return { files: parseGitFiles(stdout), failed: false };
55
+ return {
56
+ files: parseGitFiles(stdout).filter((file) => !isReticleOwnPath(file)),
57
+ failed: false,
58
+ };
42
59
  }
43
60
  catch (error) {
44
61
  return {
@@ -41,7 +41,7 @@ export declare const SECRET_FIELD_ARG = "secretField";
41
41
  * rules must not be able to drift. It used to sit in `replay.ts`, one import away from the sentence
42
42
  * saying it had to stay together.
43
43
  */
44
- export declare const secretEnvKey: (field: string) => string;
44
+ export declare function secretEnvKey(field: string): string;
45
45
  /** The schema of that argument, shared by every tool that replays a flow. */
46
46
  export { CALL_SECRETS_ARG };
47
47
  export declare const callSecretsArg: z.ZodOptional<z.ZodRecord<z.ZodString, z.ZodString>>;
@@ -59,16 +59,4 @@ export interface UnsuppliedSecret {
59
59
  field: string;
60
60
  envKey: string;
61
61
  }
62
- /**
63
- * Every credential this flow will replay as the literal placeholder.
64
- *
65
- * Checked BEFORE a step runs, because the alternative is what shipped: the placeholder is typed
66
- * into the password box, sign-in fails, and the flow reports that an element further down the
67
- * journey has gone missing -- a `drift` verdict naming a component nobody touched, with an
68
- * invitation to update a flow that was correct.
69
- *
70
- * The emptiness rule matches `replayActionArgs` exactly: it substitutes only for a value of
71
- * non-zero length, so an empty variable leaves the placeholder and must count as unsupplied here.
72
- * Two different answers to "is this supplied" is how the gate would pass and the replay still fail.
73
- */
74
62
  export declare function unsuppliedSecrets(flow: FlowFile, env: Record<string, string | undefined>): UnsuppliedSecret[];