@reticlehq/server 2.13.0 → 2.14.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 (451) hide show
  1. package/SKILL.md +8 -18
  2. package/bin/reticle.js +3 -0
  3. package/dist/bridge/auth-failure-reason.js +12 -1
  4. package/dist/bridge/bridge-security.d.ts +8 -0
  5. package/dist/bridge/bridge-security.js +6 -1
  6. package/dist/bridge/bridge.d.ts +3 -0
  7. package/dist/bridge/bridge.js +23 -1
  8. package/dist/bridge/bridge.test-harness.d.ts +10 -1
  9. package/dist/bridge/bridge.test-harness.js +7 -1
  10. package/dist/bridge/pairing-token.d.ts +17 -0
  11. package/dist/bridge/pairing-token.js +26 -0
  12. package/dist/bridge/token-auth.d.ts +7 -0
  13. package/dist/bridge/token-auth.js +7 -1
  14. package/dist/capsule/capsule-store.d.ts +4 -4
  15. package/dist/capsule/capsule.d.ts +1 -1
  16. package/dist/capsule/capsule.js +3 -3
  17. package/dist/capsule/causal-summary.d.ts +21 -1
  18. package/dist/capsule/causal-summary.js +8 -6
  19. package/dist/capsule/divergence.d.ts +1 -1
  20. package/dist/capsule/divergence.js +26 -10
  21. package/dist/chromium-launch-options.d.ts +2 -1
  22. package/dist/cli/adhoc-verdict.d.ts +58 -0
  23. package/dist/cli/adhoc-verdict.js +115 -0
  24. package/dist/cli/chromium-hint.d.ts +18 -4
  25. package/dist/cli/chromium-hint.js +54 -6
  26. package/dist/cli/cli-doctor.js +1 -2
  27. package/dist/cli/cli-flow-commands.d.ts +16 -2
  28. package/dist/cli/cli-flow-commands.js +28 -9
  29. package/dist/cli/cli-parse-feedback.js +1 -1
  30. package/dist/cli/cli-parse.d.ts +2 -1
  31. package/dist/cli/cli-parse.js +38 -0
  32. package/dist/cli/cli-port.d.ts +5 -13
  33. package/dist/cli/cli-port.js +5 -38
  34. package/dist/cli/cli-update-commands.js +4 -4
  35. package/dist/cli/cli-verify.d.ts +24 -7
  36. package/dist/cli/cli-verify.js +87 -13
  37. package/dist/cli/cloud-keystore.d.ts +2 -1
  38. package/dist/cli/cloud-login.d.ts +2 -1
  39. package/dist/cli/cloud-session.d.ts +2 -1
  40. package/dist/cli/cloud-session.js +1 -1
  41. package/dist/cli/daemon-start-options.d.ts +2 -1
  42. package/dist/cli/device-flow.d.ts +2 -2
  43. package/dist/cli/doctor-daemon-line.d.ts +2 -1
  44. package/dist/cli/doctor-project-line.d.ts +2 -1
  45. package/dist/cli/doctor-rows.d.ts +2 -1
  46. package/dist/cli/drive-attach.d.ts +4 -3
  47. package/dist/cli/gate-hook-message.d.ts +2 -1
  48. package/dist/cli/status-next-action.js +10 -11
  49. package/dist/cli.d.ts +1 -0
  50. package/dist/cli.js +21 -9
  51. package/dist/cloud/account-state.d.ts +20 -0
  52. package/dist/cloud/account-state.js +65 -0
  53. package/dist/cloud/cloud-sync.d.ts +46 -3
  54. package/dist/cloud/cloud-sync.js +116 -0
  55. package/dist/cloud/sync-cycle.d.ts +5 -4
  56. package/dist/cloud/sync-cycle.js +1 -1
  57. package/dist/cloud/sync-daemon.d.ts +3 -19
  58. package/dist/cloud/sync-daemon.js +2 -2
  59. package/dist/crawl/crawl-tools.js +1 -1
  60. package/dist/crawl/crawl.d.ts +5 -5
  61. package/dist/crawl/crawl.js +138 -4
  62. package/dist/daemon/daemon-resilience.d.ts +3 -2
  63. package/dist/daemon/daemon-resilience.js +43 -4
  64. package/dist/daemon/daemon-resolve.d.ts +0 -9
  65. package/dist/daemon/daemon-resolve.js +2 -2
  66. package/dist/daemon/dev-servers.d.ts +1 -1
  67. package/dist/daemon/dev-servers.js +1 -1
  68. package/dist/daemon/loopback-alias.d.ts +2 -1
  69. package/dist/daemon/startup-failure.d.ts +11 -0
  70. package/dist/daemon/startup-failure.js +46 -0
  71. package/dist/events/contradictions.d.ts +10 -16
  72. package/dist/events/contradictions.js +149 -17
  73. package/dist/events/declared.d.ts +13 -1
  74. package/dist/events/declared.js +59 -3
  75. package/dist/events/echo-mismatch.js +75 -6
  76. package/dist/events/lineage.d.ts +52 -0
  77. package/dist/events/lineage.js +122 -0
  78. package/dist/events/net-evidence.d.ts +21 -0
  79. package/dist/events/net-evidence.js +81 -0
  80. package/dist/events/predicate-console.d.ts +13 -0
  81. package/dist/events/predicate-console.js +138 -0
  82. package/dist/events/predicate-element.d.ts +13 -0
  83. package/dist/events/predicate-element.js +214 -0
  84. package/dist/events/predicate-eval.d.ts +15 -3
  85. package/dist/events/predicate-eval.js +128 -110
  86. package/dist/events/predicate-parse.js +34 -1
  87. package/dist/events/predicate-request-body.d.ts +50 -0
  88. package/dist/events/predicate-request-body.js +120 -0
  89. package/dist/events/predicate-route.d.ts +21 -1
  90. package/dist/events/predicate-route.js +149 -21
  91. package/dist/events/predicate-schema.d.ts +8 -1
  92. package/dist/events/predicate-schema.js +34 -0
  93. package/dist/events/predicate.d.ts +2 -0
  94. package/dist/events/predicate.js +52 -159
  95. package/dist/events/split-text-miss.d.ts +6 -4
  96. package/dist/events/split-text-miss.js +12 -5
  97. package/dist/flows/affected-tools.js +22 -9
  98. package/dist/flows/annotate.d.ts +2 -1
  99. package/dist/flows/annotate.js +19 -1
  100. package/dist/flows/coverage.d.ts +2 -2
  101. package/dist/flows/flake.d.ts +3 -3
  102. package/dist/flows/flow-expect-grammar.d.ts +33 -0
  103. package/dist/flows/flow-expect-grammar.js +155 -0
  104. package/dist/flows/flow-replay-run.d.ts +1 -1
  105. package/dist/flows/flow-replay-run.js +28 -15
  106. package/dist/flows/flow-replay.d.ts +10 -0
  107. package/dist/flows/flow-replay.js +57 -22
  108. package/dist/flows/flow-secret-field.d.ts +14 -0
  109. package/dist/flows/flow-secret-field.js +22 -0
  110. package/dist/flows/flow-step-runners.d.ts +1 -0
  111. package/dist/flows/flow-step-runners.js +91 -34
  112. package/dist/flows/flow-success.js +22 -0
  113. package/dist/flows/flow-tools.js +27 -8
  114. package/dist/flows/flow-upload-resolve.d.ts +23 -0
  115. package/dist/flows/flow-upload-resolve.js +46 -0
  116. package/dist/flows/flows.d.ts +15 -0
  117. package/dist/flows/flows.js +17 -14
  118. package/dist/flows/git-changed.d.ts +23 -4
  119. package/dist/flows/git-changed.js +32 -6
  120. package/dist/flows/heal-run.js +2 -2
  121. package/dist/flows/predicate-to-expect.d.ts +3 -2
  122. package/dist/flows/predicate-to-expect.js +11 -5
  123. package/dist/flows/recording-backtrack.d.ts +24 -0
  124. package/dist/flows/recording-backtrack.js +73 -0
  125. package/dist/flows/recordings.d.ts +6 -0
  126. package/dist/flows/replay-halt.d.ts +26 -0
  127. package/dist/flows/replay-halt.js +30 -0
  128. package/dist/flows/replay.d.ts +0 -8
  129. package/dist/flows/replay.js +15 -3
  130. package/dist/flows/suite-flakes.d.ts +2 -1
  131. package/dist/flows/verify-change-tools.js +16 -4
  132. package/dist/honesty/already-true.d.ts +14 -0
  133. package/dist/honesty/already-true.js +47 -4
  134. package/dist/honesty/blind-spots.d.ts +3 -1
  135. package/dist/honesty/blind-spots.js +24 -1
  136. package/dist/honesty/body-capture-remedy.d.ts +42 -0
  137. package/dist/honesty/body-capture-remedy.js +95 -0
  138. package/dist/honesty/feature-capture.d.ts +3 -2
  139. package/dist/honesty/feature-capture.js +1 -1
  140. package/dist/honesty/gap-ledger.d.ts +1 -1
  141. package/dist/honesty/gap-ledger.js +1 -1
  142. package/dist/honesty/instrumentation-gaps.d.ts +8 -1
  143. package/dist/honesty/instrumentation-gaps.js +12 -2
  144. package/dist/honesty/observability.d.ts +4 -3
  145. package/dist/honesty/tool-hit-rate.d.ts +3 -2
  146. package/dist/honesty/uncaptured-bodies.d.ts +3 -1
  147. package/dist/honesty/uncaptured-bodies.js +6 -2
  148. package/dist/honesty/unsettled.d.ts +9 -0
  149. package/dist/honesty/unsettled.js +45 -0
  150. package/dist/honesty/verified.d.ts +32 -1
  151. package/dist/honesty/verified.js +37 -10
  152. package/dist/impact/impact-store.d.ts +5 -14
  153. package/dist/impact/impact-store.js +49 -6
  154. package/dist/index.js +1 -1
  155. package/dist/input/network-detail.d.ts +26 -1
  156. package/dist/input/network-detail.js +44 -12
  157. package/dist/input/network-mock-tools.js +24 -17
  158. package/dist/input/real-input.js +1 -1
  159. package/dist/input/viewport-tools.js +25 -13
  160. package/dist/intent/inline-intent.d.ts +0 -10
  161. package/dist/intent/inline-intent.js +1 -1
  162. package/dist/intent/intent-shard-store.d.ts +3 -2
  163. package/dist/intent/intent-shard-store.js +1 -1
  164. package/dist/intent/intent-shard.d.ts +14 -14
  165. package/dist/intent/intent-shard.js +4 -4
  166. package/dist/intent/intent-store.d.ts +1 -1
  167. package/dist/intent/intent-store.js +1 -1
  168. package/dist/intent/intent-subject.d.ts +2 -1
  169. package/dist/intent/open-intents.d.ts +3 -2
  170. package/dist/license/license.d.ts +4 -4
  171. package/dist/license/license.js +1 -1
  172. package/dist/mcp/attach-memory.d.ts +2 -1
  173. package/dist/mcp/client-identity.d.ts +2 -1
  174. package/dist/mcp/mcp-outage.d.ts +1 -1
  175. package/dist/mcp/mcp-outage.js +1 -1
  176. package/dist/mcp/mcp-proxy.d.ts +3 -1
  177. package/dist/mcp/mcp-proxy.js +32 -7
  178. package/dist/mcp/mcp.js +3 -1
  179. package/dist/mcp/proxy-handshake.d.ts +2 -1
  180. package/dist/mcp/proxy-idle-exit.d.ts +45 -0
  181. package/dist/mcp/proxy-idle-exit.js +94 -0
  182. package/dist/mcp/server-instructions.d.ts +2 -1
  183. package/dist/memory/project-memory.d.ts +2 -3
  184. package/dist/memory/project-memory.js +1 -1
  185. package/dist/oracles/propose-consequences.js +5 -5
  186. package/dist/oracles/self-instrument.d.ts +2 -2
  187. package/dist/oracles/self-instrument.js +1 -1
  188. package/dist/platform.d.ts +3 -5
  189. package/dist/platform.js +3 -5
  190. package/dist/pool/browser-pool.d.ts +92 -0
  191. package/dist/pool/browser-pool.js +119 -5
  192. package/dist/pool/playwright-launcher.js +29 -2
  193. package/dist/pool/storage-seed.d.ts +23 -0
  194. package/dist/pool/storage-seed.js +198 -0
  195. package/dist/project/artifact-root.d.ts +2 -1
  196. package/dist/project/memory-fs.d.ts +2 -1
  197. package/dist/project/reticle-dir.js +1 -1
  198. package/dist/project/session-root.d.ts +8 -0
  199. package/dist/project/session-root.js +9 -2
  200. package/dist/runs/reticle-runner.d.ts +14 -1
  201. package/dist/runs/reticle-runner.js +39 -2
  202. package/dist/session/attachment-history.d.ts +2 -1
  203. package/dist/session/fake-session.d.ts +37 -0
  204. package/dist/session/fake-session.js +81 -0
  205. package/dist/session/lease-visibility.d.ts +2 -1
  206. package/dist/session/live-control-tools.js +6 -0
  207. package/dist/session/no-session-diagnosis.d.ts +17 -1
  208. package/dist/session/no-session-diagnosis.js +32 -6
  209. package/dist/session/no-session-next-action.d.ts +14 -0
  210. package/dist/session/no-session-next-action.js +18 -0
  211. package/dist/session/no-session-watch.js +46 -3
  212. package/dist/session/registered-projects.d.ts +54 -0
  213. package/dist/session/registered-projects.js +73 -0
  214. package/dist/session/review-store.d.ts +2 -1
  215. package/dist/session/session-health.d.ts +62 -1
  216. package/dist/session/session-health.js +82 -2
  217. package/dist/session/session-manager.d.ts +11 -1
  218. package/dist/session/session-manager.js +18 -3
  219. package/dist/session/session-replaced.d.ts +24 -0
  220. package/dist/session/session-replaced.js +29 -0
  221. package/dist/session/session-successor.js +20 -4
  222. package/dist/session/session.d.ts +13 -5
  223. package/dist/session/session.js +31 -23
  224. package/dist/setup/agent-configs.d.ts +3 -2
  225. package/dist/setup/agent-writer.d.ts +3 -2
  226. package/dist/setup/approval-migration.d.ts +2 -1
  227. package/dist/setup/approval-migration.js +1 -1
  228. package/dist/setup/auto-approve.d.ts +11 -19
  229. package/dist/setup/auto-approve.js +15 -12
  230. package/dist/{init → setup}/confirm.js +1 -1
  231. package/dist/setup/desktop-shape.d.ts +3 -2
  232. package/dist/setup/dev-server-wait.d.ts +8 -0
  233. package/dist/setup/dev-server-wait.js +3 -1
  234. package/dist/setup/drive-agent.d.ts +2 -3
  235. package/dist/setup/drive-agent.js +1 -1
  236. package/dist/setup/drive-plan.d.ts +3 -2
  237. package/dist/setup/ensure-daemon.d.ts +2 -1
  238. package/dist/setup/existing-app.d.ts +12 -0
  239. package/dist/setup/existing-app.js +13 -0
  240. package/dist/setup/init-host.d.ts +11 -0
  241. package/dist/setup/init-host.js +26 -0
  242. package/dist/setup/init-runtime.d.ts +4 -10
  243. package/dist/setup/init-runtime.js +23 -16
  244. package/dist/setup/license-key.d.ts +2 -1
  245. package/dist/setup/listeners.d.ts +2 -1
  246. package/dist/setup/loopback-probe-urls.d.ts +18 -0
  247. package/dist/setup/loopback-probe-urls.js +52 -0
  248. package/dist/setup/node-effects.d.ts +3 -0
  249. package/dist/setup/node-effects.js +26 -11
  250. package/dist/setup/page-probe.d.ts +5 -0
  251. package/dist/setup/relaunch.d.ts +2 -1
  252. package/dist/setup/run-setup.d.ts +5 -1
  253. package/dist/setup/run-setup.js +155 -48
  254. package/dist/setup/setup-command.d.ts +3 -2
  255. package/dist/setup/setup-command.js +8 -0
  256. package/dist/setup/setup-options.d.ts +5 -3
  257. package/dist/setup/setup-options.js +3 -2
  258. package/dist/setup/wait-progress.d.ts +28 -0
  259. package/dist/setup/wait-progress.js +43 -0
  260. package/dist/telemetry/app-instrumented.d.ts +2 -1
  261. package/dist/telemetry/app-instrumented.js +1 -1
  262. package/dist/telemetry/automation-hint.d.ts +1 -1
  263. package/dist/telemetry/automation-hint.js +1 -1
  264. package/dist/telemetry/cli-telemetry.js +1 -1
  265. package/dist/telemetry/connect-failure.d.ts +1 -1
  266. package/dist/telemetry/connect-failure.js +1 -1
  267. package/dist/telemetry/crash-cause.d.ts +3 -2
  268. package/dist/telemetry/crash-cause.js +1 -1
  269. package/dist/telemetry/daemon-telemetry.d.ts +3 -2
  270. package/dist/telemetry/daemon-telemetry.js +1 -1
  271. package/dist/telemetry/error-class.d.ts +3 -2
  272. package/dist/telemetry/error-class.js +1 -1
  273. package/dist/telemetry/feedback-cli.js +1 -1
  274. package/dist/telemetry/feedback-context.d.ts +3 -2
  275. package/dist/telemetry/feedback-context.js +5 -4
  276. package/dist/telemetry/feedback-local.d.ts +3 -2
  277. package/dist/telemetry/feedback.d.ts +4 -3
  278. package/dist/telemetry/feedback.js +1 -1
  279. package/dist/telemetry/git-facts.d.ts +2 -2
  280. package/dist/telemetry/git-facts.js +1 -1
  281. package/dist/telemetry/identify.d.ts +1 -1
  282. package/dist/telemetry/identify.js +1 -1
  283. package/dist/telemetry/init-telemetry.d.ts +2 -14
  284. package/dist/telemetry/init-telemetry.js +4 -13
  285. package/dist/telemetry/install-source.d.ts +7 -13
  286. package/dist/telemetry/install-source.js +7 -29
  287. package/dist/telemetry/license-activation.d.ts +3 -2
  288. package/dist/telemetry/license-activation.js +1 -1
  289. package/dist/telemetry/machine-snapshot.d.ts +1 -1
  290. package/dist/telemetry/mcp-connection.js +1 -1
  291. package/dist/telemetry/project-profile.d.ts +0 -14
  292. package/dist/telemetry/project-profile.js +1 -1
  293. package/dist/telemetry/proxy-telemetry.js +1 -1
  294. package/dist/telemetry/session-metrics.d.ts +1 -1
  295. package/dist/telemetry/session-metrics.js +1 -1
  296. package/dist/telemetry/telemetry.d.ts +1 -17
  297. package/dist/telemetry/telemetry.js +4 -4
  298. package/dist/telemetry/tool-refused.d.ts +1 -1
  299. package/dist/telemetry/tool-refused.js +1 -1
  300. package/dist/tools/act-observation.d.ts +3 -2
  301. package/dist/tools/act-preflight.js +8 -3
  302. package/dist/tools/act-target.d.ts +4 -0
  303. package/dist/tools/act-target.js +14 -5
  304. package/dist/tools/act-tools.d.ts +0 -2
  305. package/dist/tools/act-tools.js +45 -15
  306. package/dist/tools/assert-source.d.ts +30 -0
  307. package/dist/tools/assert-source.js +21 -0
  308. package/dist/tools/assert-verdict.d.ts +1 -1
  309. package/dist/tools/assert-verdict.js +14 -4
  310. package/dist/tools/browser-tools.js +28 -8
  311. package/dist/tools/complete-snapshot.d.ts +3 -2
  312. package/dist/tools/dynamic-tools.js +8 -0
  313. package/dist/tools/error-recovery.d.ts +10 -0
  314. package/dist/tools/error-recovery.js +23 -0
  315. package/dist/tools/feedback-tools.js +1 -1
  316. package/dist/tools/invoke-tool.js +2 -0
  317. package/dist/tools/lease-tools.d.ts +48 -20
  318. package/dist/tools/lease-tools.js +311 -76
  319. package/dist/tools/lineage-tools.d.ts +14 -0
  320. package/dist/tools/lineage-tools.js +64 -0
  321. package/dist/tools/merge-tools.js +1 -3
  322. package/dist/tools/navigate-arrival.d.ts +45 -1
  323. package/dist/tools/navigate-arrival.js +39 -6
  324. package/dist/tools/navigate-result.d.ts +8 -1
  325. package/dist/tools/navigate-result.js +14 -4
  326. package/dist/tools/numeric-bounds.d.ts +0 -11
  327. package/dist/tools/numeric-bounds.js +4 -4
  328. package/dist/tools/observe-tools.js +22 -26
  329. package/dist/tools/observed-nothing.d.ts +9 -0
  330. package/dist/tools/observed-nothing.js +2 -1
  331. package/dist/tools/read-tools.js +12 -17
  332. package/dist/tools/real-input-attempt.d.ts +14 -6
  333. package/dist/tools/real-input-attempt.js +75 -18
  334. package/dist/tools/reconcile-tools.js +2 -1
  335. package/dist/tools/reload-result.d.ts +6 -1
  336. package/dist/tools/reload-result.js +7 -2
  337. package/dist/tools/resolve-target.d.ts +7 -1
  338. package/dist/tools/resolve-target.js +72 -9
  339. package/dist/tools/settle-in-flight.d.ts +1 -1
  340. package/dist/tools/settle-in-flight.js +9 -2
  341. package/dist/tools/snapshot-delta.d.ts +24 -1
  342. package/dist/tools/snapshot-delta.js +66 -7
  343. package/dist/tools/tool-names.d.ts +1 -0
  344. package/dist/tools/tool-names.js +1 -0
  345. package/dist/tools/tool-surface.js +20 -2
  346. package/dist/tools/tools.js +120 -11
  347. package/dist/tools/verify-next-baton.d.ts +2 -1
  348. package/dist/update/sdk-sync.d.ts +1 -1
  349. package/dist/update/sdk-sync.js +1 -1
  350. package/dist/update/updater.js +1 -1
  351. package/dist/version/sdk-fix.d.ts +2 -1
  352. package/dist/version/version-skew.d.ts +0 -8
  353. package/dist/version/version-skew.js +1 -1
  354. package/docs/README.md +8 -6
  355. package/docs/actions.mdx +1 -1
  356. package/docs/agent-cheatsheet.md +4 -2
  357. package/docs/architecture.md +1 -1
  358. package/docs/cli/mcp.mdx +3 -1
  359. package/docs/cli/watch.mdx +1 -1
  360. package/docs/cli.mdx +1 -1
  361. package/docs/desktop.mdx +1 -1
  362. package/docs/docs.json +8 -3
  363. package/docs/faq.mdx +9 -0
  364. package/docs/first-drive.md +136 -0
  365. package/docs/frameworks.mdx +29 -7
  366. package/docs/gate-plan.md +2 -2
  367. package/docs/gates.md +19 -11
  368. package/docs/getting-started.md +7 -1
  369. package/docs/http-transport.md +164 -0
  370. package/docs/index.mdx +5 -3
  371. package/docs/install-manual.mdx +1 -1
  372. package/docs/packages/tauri.mdx +1 -1
  373. package/docs/packages.mdx +15 -3
  374. package/docs/platform-integration.md +1 -1
  375. package/docs/predicates.mdx +2 -0
  376. package/docs/system-map.md +2 -2
  377. package/docs/telemetry-contract.md +4 -4
  378. package/docs/telemetry-events.mdx +1 -1
  379. package/docs/telemetry.md +3 -3
  380. package/docs/tools-navigate.mdx +14 -6
  381. package/docs/usage.md +4 -4
  382. package/package.json +7 -4
  383. package/dist/init/agent-rules.d.ts +0 -116
  384. package/dist/init/agent-rules.js +0 -279
  385. package/dist/init/app-choice.d.ts +0 -20
  386. package/dist/init/app-choice.js +0 -25
  387. package/dist/init/astro-host.d.ts +0 -21
  388. package/dist/init/astro-host.js +0 -27
  389. package/dist/init/astro-patch.d.ts +0 -33
  390. package/dist/init/astro-patch.js +0 -300
  391. package/dist/init/capabilities.d.ts +0 -40
  392. package/dist/init/capabilities.js +0 -150
  393. package/dist/init/closing-hint.d.ts +0 -36
  394. package/dist/init/closing-hint.js +0 -120
  395. package/dist/init/connect-steps.d.ts +0 -2
  396. package/dist/init/connect-steps.js +0 -50
  397. package/dist/init/cra.d.ts +0 -79
  398. package/dist/init/cra.js +0 -178
  399. package/dist/init/csp-check.d.ts +0 -38
  400. package/dist/init/csp-check.js +0 -107
  401. package/dist/init/csp-doctor.d.ts +0 -32
  402. package/dist/init/csp-doctor.js +0 -54
  403. package/dist/init/desktop-doctor.d.ts +0 -41
  404. package/dist/init/desktop-doctor.js +0 -198
  405. package/dist/init/detect.d.ts +0 -96
  406. package/dist/init/detect.js +0 -209
  407. package/dist/init/dev-script.d.ts +0 -50
  408. package/dist/init/dev-script.js +0 -66
  409. package/dist/init/format-generated.d.ts +0 -18
  410. package/dist/init/format-generated.js +0 -39
  411. package/dist/init/install-hint.d.ts +0 -9
  412. package/dist/init/install-hint.js +0 -29
  413. package/dist/init/mcp-clients.d.ts +0 -89
  414. package/dist/init/mcp-clients.js +0 -299
  415. package/dist/init/mcp-registered.d.ts +0 -12
  416. package/dist/init/mcp-registered.js +0 -14
  417. package/dist/init/mcp.d.ts +0 -89
  418. package/dist/init/mcp.js +0 -129
  419. package/dist/init/next-patch.d.ts +0 -39
  420. package/dist/init/next-patch.js +0 -196
  421. package/dist/init/node-io.d.ts +0 -7
  422. package/dist/init/node-io.js +0 -117
  423. package/dist/init/non-js-project.d.ts +0 -27
  424. package/dist/init/non-js-project.js +0 -84
  425. package/dist/init/patch-kind.d.ts +0 -20
  426. package/dist/init/patch-kind.js +0 -10
  427. package/dist/init/plan-framework.d.ts +0 -64
  428. package/dist/init/plan-framework.js +0 -565
  429. package/dist/init/plan.d.ts +0 -242
  430. package/dist/init/plan.js +0 -703
  431. package/dist/init/preflight.d.ts +0 -28
  432. package/dist/init/preflight.js +0 -38
  433. package/dist/init/project-id.d.ts +0 -12
  434. package/dist/init/project-id.js +0 -25
  435. package/dist/init/refresh-rules.d.ts +0 -39
  436. package/dist/init/refresh-rules.js +0 -51
  437. package/dist/init/run.d.ts +0 -117
  438. package/dist/init/run.js +0 -806
  439. package/dist/init/slash-command.d.ts +0 -27
  440. package/dist/init/slash-command.js +0 -132
  441. package/dist/init/snippets.d.ts +0 -134
  442. package/dist/init/snippets.js +0 -572
  443. package/dist/init/vite-config.d.ts +0 -18
  444. package/dist/init/vite-config.js +0 -114
  445. package/dist/init/windows-quote.d.ts +0 -38
  446. package/dist/init/windows-quote.js +0 -70
  447. package/dist/init/workspace-apps.d.ts +0 -30
  448. package/dist/init/workspace-apps.js +0 -178
  449. package/dist/project/remember-project.d.ts +0 -24
  450. package/dist/project/remember-project.js +0 -40
  451. /package/dist/{init → setup}/confirm.d.ts +0 -0
@@ -11,6 +11,7 @@
11
11
  */
12
12
  /** The minimal page surface the pool drives. Real Playwright `Page` satisfies this. */
13
13
  import { unreachableUrlIn } from '@reticlehq/core';
14
+ import { seedStorageInto } from './storage-seed.js';
14
15
  /** Default lease time-to-live: a lease untouched for this long is presumed orphaned and reclaimed. */
15
16
  export const DEFAULT_LEASE_TTL_MS = 5 * 60_000;
16
17
  /** Default cap on how long a lease's initial navigation may take before it fails (frees the slot). */
@@ -147,7 +148,26 @@ export class BrowserPool {
147
148
  return;
148
149
  this.#aliases.set(registeredId, leaseId);
149
150
  }
150
- /** The lease this id refers to: itself, or whatever it is an alias for. */
151
+ /**
152
+ * The lease this id refers to: itself, or whatever it is an alias for.
153
+ *
154
+ * EVERY AGENT-FACING LOOKUP MUST GO THROUGH THIS. A leased page runs the SDK, which dials and
155
+ * registers under its OWN session id, so the id `reticle_sessions` shows an agent is routinely the
156
+ * alias rather than the lease key. Four capabilities used the raw map instead — screenshots,
157
+ * hover, network mocks and the dial-failure diagnostic — and every one of them refused for a
158
+ * lease that was alive and working, addressed by the only id the agent had been given.
159
+ *
160
+ * `reticle_network_mock` is where that surfaced: it reported `no-cdp-provider` in every
161
+ * configuration a reporter could reach, including after `reticle drive`, and the recommendation it
162
+ * printed ("start with `reticle drive <url>`") could not fix it because the provider was never the
163
+ * problem. Their conclusion was that error-path verification was impossible without shipping
164
+ * failure-injection code inside the application — which is exactly what an external mock exists to
165
+ * avoid.
166
+ *
167
+ * `acquire` and `#release` are the two exceptions and must stay raw: the first is registering the
168
+ * lease key itself before any alias can exist, and the second must delete that key rather than
169
+ * whatever it points at.
170
+ */
151
171
  #leaseIdOf(sessionId) {
152
172
  return this.#active.has(sessionId) ? sessionId : (this.#aliases.get(sessionId) ?? sessionId);
153
173
  }
@@ -172,7 +192,7 @@ export class BrowserPool {
172
192
  * reaper take it out from under a diff.
173
193
  */
174
194
  async screenshotLease(sessionId, opts = {}) {
175
- const lease = this.#active.get(sessionId);
195
+ const lease = this.#active.get(this.#leaseIdOf(sessionId));
176
196
  if (lease === undefined || lease.page.screenshot === undefined)
177
197
  return undefined;
178
198
  this.touch(sessionId);
@@ -193,7 +213,7 @@ export class BrowserPool {
193
213
  * Touches the lease like any other tool call, so hovering keeps it alive.
194
214
  */
195
215
  async hoverLease(sessionId, x, y) {
196
- const lease = this.#active.get(sessionId);
216
+ const lease = this.#active.get(this.#leaseIdOf(sessionId));
197
217
  if (lease === undefined || lease.page.hover === undefined)
198
218
  return false;
199
219
  this.touch(sessionId);
@@ -205,6 +225,46 @@ export class BrowserPool {
205
225
  return false;
206
226
  }
207
227
  }
228
+ /**
229
+ * Install network mocks on a leased page, or false when this session is not a lease or cannot
230
+ * intercept. Same optional-capability contract as screenshotLease: absence must read as "could not
231
+ * mock", never as a stub that applied to nothing.
232
+ *
233
+ * Touches the lease like any other tool call, so mocking keeps it alive.
234
+ */
235
+ /**
236
+ * Resize a leased page's viewport, or report that this page cannot be resized.
237
+ *
238
+ * Alias-resolved like every other agent-facing capability — see `#leaseIdOf`.
239
+ *
240
+ * Touches the lease like any other tool call, so resizing keeps it alive.
241
+ */
242
+ async setViewportLease(sessionId, size) {
243
+ const lease = this.#active.get(this.#leaseIdOf(sessionId));
244
+ if (lease === undefined || lease.page.setViewport === undefined)
245
+ return false;
246
+ this.touch(sessionId);
247
+ try {
248
+ await lease.page.setViewport(size);
249
+ return true;
250
+ }
251
+ catch {
252
+ return false;
253
+ }
254
+ }
255
+ async setMocksLease(sessionId, rules) {
256
+ const lease = this.#active.get(this.#leaseIdOf(sessionId));
257
+ if (lease === undefined || lease.page.installMocks === undefined)
258
+ return false;
259
+ this.touch(sessionId);
260
+ try {
261
+ await lease.page.installMocks(rules);
262
+ return true;
263
+ }
264
+ catch {
265
+ return false;
266
+ }
267
+ }
208
268
  async sweepExpired() {
209
269
  const now = this.#now();
210
270
  const expired = [...this.#active.entries()]
@@ -259,6 +319,7 @@ export class BrowserPool {
259
319
  const sessionId = opts.sessionId ?? this.#genId();
260
320
  let context;
261
321
  let pending;
322
+ let pendingDialogMessage;
262
323
  try {
263
324
  const browser = await this.#ensureBrowser();
264
325
  context = await browser.newContext();
@@ -281,23 +342,69 @@ export class BrowserPool {
281
342
  else
282
343
  pending = dialled; // logged during goto, before the lease is registered below
283
344
  });
284
- await page.goto(url, { timeoutMs: this.#navTimeout });
345
+ // Same "listen before goto" reasoning as onConsole above: a dialog opened during the initial
346
+ // navigation (an app that confirms something in an onload handler) must still be dismissed, not
347
+ // just ones opened after the lease is registered.
348
+ page.onDialog?.((dialog) => {
349
+ const active = this.#active.get(sessionId);
350
+ if (active !== undefined)
351
+ active.lastDialogMessage = dialog.message;
352
+ else
353
+ pendingDialogMessage = dialog.message;
354
+ void dialog.dismiss();
355
+ });
356
+ let seedHandle;
357
+ let checkSeedError;
358
+ if (opts.seedStorage !== undefined) {
359
+ const seedResult = await seedStorageInto(context, page, url, opts.seedStorage);
360
+ seedHandle = seedResult?.handle;
361
+ checkSeedError = seedResult?.checkError;
362
+ }
363
+ let navRes;
364
+ try {
365
+ navRes = await page.goto(url, { timeoutMs: this.#navTimeout });
366
+ checkSeedError?.();
367
+ }
368
+ finally {
369
+ if (seedHandle !== undefined) {
370
+ await seedHandle.dispose().catch(() => undefined);
371
+ }
372
+ }
285
373
  // The browser can crash WHILE goto is resolving; #onCrash then clears #active and zeroes
286
374
  // #occupied. Registering the lease now would resurrect a dead entry against a crashed browser with
287
375
  // the slot count out of sync (drifting below #active.size, eventually exceeding the cap). If we're
288
376
  // no longer the live browser, bail — the catch below closes the context and returns the slot.
289
377
  if (this.#browser !== browser)
290
378
  throw new Error('browser crashed during navigation');
379
+ let navStatus;
380
+ if (null !== navRes && 'object' === typeof navRes && 'status' in navRes) {
381
+ const s = navRes.status;
382
+ if ('function' === typeof s) {
383
+ try {
384
+ const code = s.call(navRes);
385
+ if ('number' === typeof code)
386
+ navStatus = code;
387
+ }
388
+ catch {
389
+ // ignore
390
+ }
391
+ }
392
+ else if ('number' === typeof s) {
393
+ navStatus = s;
394
+ }
395
+ }
291
396
  this.#active.set(sessionId, {
292
397
  context,
293
398
  page,
294
399
  url,
295
400
  touchedAt: this.#now(),
296
401
  ...(pending === undefined ? {} : { dialFailureUrl: pending }),
402
+ ...(pendingDialogMessage === undefined ? {} : { lastDialogMessage: pendingDialogMessage }),
297
403
  });
298
404
  return {
299
405
  sessionId,
300
406
  url,
407
+ ...(navStatus !== undefined ? { navStatus } : {}),
301
408
  release: () => this.#release(sessionId),
302
409
  };
303
410
  }
@@ -316,7 +423,14 @@ export class BrowserPool {
316
423
  * Undefined means the page said nothing — never that it dialled the right place.
317
424
  */
318
425
  dialFailureUrl(sessionId) {
319
- return this.#active.get(sessionId)?.dialFailureUrl;
426
+ return this.#active.get(this.#leaseIdOf(sessionId))?.dialFailureUrl;
427
+ }
428
+ /**
429
+ * The message of the most recent native dialog (`confirm`/`alert`/`prompt`) auto-dismissed on this
430
+ * lease, if any. Diagnostic only — the dialog itself is already gone by the time this is readable.
431
+ */
432
+ lastDialogMessage(sessionId) {
433
+ return this.#active.get(this.#leaseIdOf(sessionId))?.lastDialogMessage;
320
434
  }
321
435
  /** Close every context and the browser. Pending waiters are rejected (the pool is terminal now). */
322
436
  async shutdown() {
@@ -5,11 +5,12 @@
5
5
  *
6
6
  * Headless by default — the pool exists for fault-tolerant headless multi-agent testing.
7
7
  */
8
- import { BrowserLaunchKind } from '@reticlehq/core';
8
+ import { BrowserLaunchKind } from '@reticlehq/core/telemetry';
9
9
  import { chromiumLaunchOptions } from '../chromium-launch-options.js';
10
10
  import { getSessionMetrics } from '../telemetry/session-metrics.js';
11
11
  import { classifyConnectFailure } from '../telemetry/connect-failure.js';
12
- import { chromiumInstallCommand, bundledPlaywrightVersion } from '../cli/chromium-hint.js';
12
+ import { chromiumInstallCommand, chromiumInstallDepsCommand, bundledPlaywrightVersion, } from '../cli/chromium-hint.js';
13
+ import { installNetworkMocks } from '../input/network-mock.js';
13
14
  /**
14
15
  * How a leased tab navigates. Pure, and exported, because the decision in it is worth a test while
15
16
  * the rest of this file needs a real Chromium.
@@ -49,10 +50,22 @@ function wrapBrowser(browser) {
49
50
  await page.mouse.move(x + 1, y);
50
51
  await page.mouse.move(x, y);
51
52
  },
53
+ installMocks: (rules) => installNetworkMocks(page, [...rules]),
54
+ setViewport: (size) => page.setViewportSize(size),
52
55
  onCrash: (handler) => page.on('crash', handler),
53
56
  onConsole: (handler) => page.on('console', (msg) => handler(msg.text())),
57
+ onDialog: (handler) => page.on('dialog', (dialog) => handler({ message: dialog.message(), dismiss: () => dialog.dismiss() })),
58
+ addInitScript: async (script, arg) => {
59
+ const handle = (await page.addInitScript(script, arg));
60
+ const dispose = handle?.dispose;
61
+ if ('function' !== typeof dispose) {
62
+ throw new Error('Storage seeding failed: Playwright page.addInitScript did not return a disposable handle');
63
+ }
64
+ return { dispose: () => dispose() };
65
+ },
54
66
  };
55
67
  },
68
+ addCookies: (cookies) => context.addCookies(cookies),
56
69
  close: () => context.close(),
57
70
  };
58
71
  },
@@ -69,6 +82,14 @@ function wrapBrowser(browser) {
69
82
  * two cannot suggest different commands for the same missing browser.
70
83
  */
71
84
  const CHROMIUM_MISSING_HINT = `Chromium is not installed for Playwright. Run: ${chromiumInstallCommand(bundledPlaywrightVersion())}`;
85
+ /**
86
+ * A DIFFERENT first-run failure from the one above: the browser binary is already there, but the
87
+ * host is missing the OS-level shared libraries (e.g. `libnspr4.so`) Playwright's own
88
+ * host-requirement check refuses to launch without. `npx playwright install chromium` does nothing
89
+ * for this — it re-downloads a binary that was never the problem — so this needs its own hint
90
+ * pointing at `install-deps`, pinned the same way and for the same reason as the one above.
91
+ */
92
+ const CHROMIUM_MISSING_DEPS_HINT = `Chromium is installed, but the host system is missing shared-library dependencies it needs. Run: ${chromiumInstallDepsCommand(bundledPlaywrightVersion())}`;
72
93
  /** A Launcher that boots a real headless Chromium and adapts it to the pool's interface. */
73
94
  export function playwrightLauncher(opts = {}) {
74
95
  const headless = opts.headless ?? true;
@@ -91,6 +112,12 @@ export function playwrightLauncher(opts = {}) {
91
112
  settle(classifyConnectFailure(err));
92
113
  // Turn Playwright's raw "Executable doesn't exist" into the one command that fixes it.
93
114
  const msg = err instanceof Error ? err.message : String(err);
115
+ // Checked FIRST: Playwright's host-requirement validation error also contains
116
+ // "browserType.launch", so the generic check below would otherwise misdiagnose it as a
117
+ // missing binary and send the user through a fix that changes nothing.
118
+ if (/host system is missing dependencies/i.test(msg)) {
119
+ throw new Error(CHROMIUM_MISSING_DEPS_HINT);
120
+ }
94
121
  if (/executable doesn.?t exist|playwright install|browsertype\.launch/i.test(msg)) {
95
122
  throw new Error(CHROMIUM_MISSING_HINT);
96
123
  }
@@ -0,0 +1,23 @@
1
+ import { type SeedStorage } from '@reticlehq/core';
2
+ import type { InitScriptHandle, PooledContext, PooledCookie, PooledPage } from './browser-pool.js';
3
+ export declare function targetOriginOf(navUrl: string): string | undefined;
4
+ export declare function normalizeCookies(cookies: SeedStorage['cookies'], navUrl: string): PooledCookie[];
5
+ export interface StorageSeedResult {
6
+ handle?: InitScriptHandle;
7
+ checkError?: () => void;
8
+ }
9
+ /**
10
+ * Seed initial storage state (cookies, localStorage, sessionStorage) into a leased context and page
11
+ * before the first navigation happens.
12
+ *
13
+ * Cookies are injected into the BrowserContext cookie jar so the initial HTTP GET to the target URL
14
+ * already carries the Cookie header (including httpOnly session cookies).
15
+ *
16
+ * Local and session storage are injected via an init script evaluated after document creation but
17
+ * before any inline or bundled application scripts run. The init script is scoped strictly to the
18
+ * top-level target origin document (not child iframes or external redirect origins).
19
+ *
20
+ * Returns a handle that allows the caller to dispose of the init script once the initial navigation
21
+ * has resolved, ensuring one-time semantics (reloads or future navigations do not reapply the seed).
22
+ */
23
+ export declare function seedStorageInto(context: PooledContext, page: PooledPage, targetUrl: string, seed: SeedStorage): Promise<StorageSeedResult | void>;
@@ -0,0 +1,198 @@
1
+ import { REDACTED_VALUE, scrubKnownSecrets } from '@reticlehq/core';
2
+ export function targetOriginOf(navUrl) {
3
+ try {
4
+ const origin = new URL(navUrl).origin;
5
+ return origin !== 'null' ? origin : undefined;
6
+ }
7
+ catch {
8
+ return undefined;
9
+ }
10
+ }
11
+ export function normalizeCookies(cookies, navUrl) {
12
+ if (cookies === undefined)
13
+ return [];
14
+ let baseUrl;
15
+ try {
16
+ const u = new URL(navUrl);
17
+ baseUrl = `${u.protocol}//${u.host}/`;
18
+ }
19
+ catch {
20
+ baseUrl = undefined;
21
+ }
22
+ const out = [];
23
+ if (Array.isArray(cookies)) {
24
+ for (const c of cookies) {
25
+ const cookieObj = {
26
+ name: c.name,
27
+ value: c.value,
28
+ };
29
+ if (c.domain !== undefined)
30
+ cookieObj.domain = c.domain;
31
+ if (c.path !== undefined) {
32
+ cookieObj.path = c.path;
33
+ }
34
+ else if (c.domain !== undefined && c.url === undefined) {
35
+ cookieObj.path = '/';
36
+ }
37
+ if (c.url !== undefined) {
38
+ cookieObj.url = c.url;
39
+ }
40
+ else if (c.domain === undefined && baseUrl !== undefined) {
41
+ cookieObj.url = baseUrl;
42
+ }
43
+ if (c.httpOnly !== undefined)
44
+ cookieObj.httpOnly = c.httpOnly;
45
+ if (c.secure !== undefined)
46
+ cookieObj.secure = c.secure;
47
+ if (c.sameSite !== undefined)
48
+ cookieObj.sameSite = c.sameSite;
49
+ if (c.expires !== undefined)
50
+ cookieObj.expires = c.expires;
51
+ out.push(cookieObj);
52
+ }
53
+ }
54
+ else if ('object' === typeof cookies && null !== cookies) {
55
+ for (const [name, value] of Object.entries(cookies)) {
56
+ const cookieObj = {
57
+ name,
58
+ value,
59
+ };
60
+ if (baseUrl !== undefined) {
61
+ cookieObj.url = baseUrl;
62
+ }
63
+ else {
64
+ cookieObj.path = '/';
65
+ }
66
+ out.push(cookieObj);
67
+ }
68
+ }
69
+ return out;
70
+ }
71
+ /**
72
+ * Seed initial storage state (cookies, localStorage, sessionStorage) into a leased context and page
73
+ * before the first navigation happens.
74
+ *
75
+ * Cookies are injected into the BrowserContext cookie jar so the initial HTTP GET to the target URL
76
+ * already carries the Cookie header (including httpOnly session cookies).
77
+ *
78
+ * Local and session storage are injected via an init script evaluated after document creation but
79
+ * before any inline or bundled application scripts run. The init script is scoped strictly to the
80
+ * top-level target origin document (not child iframes or external redirect origins).
81
+ *
82
+ * Returns a handle that allows the caller to dispose of the init script once the initial navigation
83
+ * has resolved, ensuring one-time semantics (reloads or future navigations do not reapply the seed).
84
+ */
85
+ export async function seedStorageInto(context, page, targetUrl, seed) {
86
+ const hasCookies = seed.cookies !== undefined &&
87
+ (Array.isArray(seed.cookies) ? seed.cookies.length > 0 : Object.keys(seed.cookies).length > 0);
88
+ const hasLocal = seed.local !== undefined && Object.keys(seed.local).length > 0;
89
+ const hasSession = seed.session !== undefined && Object.keys(seed.session).length > 0;
90
+ if (hasCookies && context.addCookies === undefined) {
91
+ throw new Error('Storage seeding failed: browser context does not support cookie seeding');
92
+ }
93
+ if ((hasLocal || hasSession) && page.addInitScript === undefined) {
94
+ throw new Error('Storage seeding failed: page does not support storage seeding via init script');
95
+ }
96
+ if (hasCookies && context.addCookies !== undefined) {
97
+ const cookiesToSet = normalizeCookies(seed.cookies, targetUrl);
98
+ if (cookiesToSet.length > 0) {
99
+ try {
100
+ await context.addCookies(cookiesToSet);
101
+ }
102
+ catch (err) {
103
+ let rawMsg = err instanceof Error ? err.message : String(err);
104
+ for (const c of cookiesToSet) {
105
+ if (undefined !== c.value && 'string' === typeof c.value && 0 !== c.value.length) {
106
+ const escaped = c.value.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
107
+ rawMsg = rawMsg.replace(new RegExp(`(^|[^a-zA-Z0-9])${escaped}(?=$|[^a-zA-Z0-9])`, 'g'), `$1${REDACTED_VALUE}`);
108
+ }
109
+ }
110
+ rawMsg = scrubKnownSecrets(rawMsg);
111
+ throw new Error(`Storage seeding failed: cookie injection failed (${rawMsg})`);
112
+ }
113
+ }
114
+ }
115
+ let handle;
116
+ let capturedError;
117
+ if (hasLocal || hasSession) {
118
+ page.onConsole?.((text) => {
119
+ if (text.startsWith('__reticle_seed_error:')) {
120
+ capturedError = text.slice('__reticle_seed_error:'.length);
121
+ }
122
+ });
123
+ const targetOrigin = targetOriginOf(targetUrl);
124
+ const added = await page.addInitScript?.(({ local, session, targetOrigin, }) => {
125
+ const win = (globalThis.window ??
126
+ globalThis);
127
+ // Only seed the top-level document frame
128
+ if (win.top !== win)
129
+ return;
130
+ // Only seed when the page is at the intended target origin
131
+ if (undefined !== targetOrigin && win.location?.origin !== targetOrigin)
132
+ return;
133
+ let seedError;
134
+ if (undefined !== local) {
135
+ try {
136
+ const storage = win.localStorage;
137
+ if (!storage) {
138
+ seedError = 'localStorage is not available';
139
+ }
140
+ else {
141
+ for (const [k, v] of Object.entries(local)) {
142
+ storage.setItem(k, v);
143
+ }
144
+ }
145
+ }
146
+ catch (err) {
147
+ let errName = 'write error';
148
+ if (null !== err && 'object' === typeof err && 'name' in err) {
149
+ const name = err.name;
150
+ if ('string' === typeof name) {
151
+ errName = name;
152
+ }
153
+ }
154
+ seedError = `localStorage write failed: ${errName}`;
155
+ }
156
+ }
157
+ if (undefined === seedError && undefined !== session) {
158
+ try {
159
+ const storage = win.sessionStorage;
160
+ if (!storage) {
161
+ seedError = 'sessionStorage is not available';
162
+ }
163
+ else {
164
+ for (const [k, v] of Object.entries(session)) {
165
+ storage.setItem(k, v);
166
+ }
167
+ }
168
+ }
169
+ catch (err) {
170
+ let errName = 'write error';
171
+ if (null !== err && 'object' === typeof err && 'name' in err) {
172
+ const name = err.name;
173
+ if ('string' === typeof name) {
174
+ errName = name;
175
+ }
176
+ }
177
+ seedError = `sessionStorage write failed: ${errName}`;
178
+ }
179
+ }
180
+ if (undefined !== seedError) {
181
+ console.error(`__reticle_seed_error:${seedError}`);
182
+ }
183
+ }, { local: seed.local, session: seed.session, targetOrigin });
184
+ if (undefined === added || 'function' !== typeof added.dispose) {
185
+ throw new Error('Storage seeding failed: init script disposal is not supported by page');
186
+ }
187
+ handle = added;
188
+ }
189
+ const checkError = () => {
190
+ if (capturedError !== undefined) {
191
+ throw new Error(`Storage seeding failed: ${capturedError}`);
192
+ }
193
+ };
194
+ return {
195
+ ...(handle !== undefined ? { handle } : {}),
196
+ checkError,
197
+ };
198
+ }
@@ -48,7 +48,7 @@ export declare const ArtifactRootReason: {
48
48
  readonly AMBIGUOUS: "ambiguous";
49
49
  };
50
50
  export type ArtifactRootReason = (typeof ArtifactRootReason)[keyof typeof ArtifactRootReason];
51
- export interface ArtifactRootQuery {
51
+ interface ArtifactRootQuery {
52
52
  /** The connected session's HELLO projectId, when it sent one. */
53
53
  projectId: string | undefined;
54
54
  /** Every project this machine knows about. Supplied, not gathered here — this stays pure. */
@@ -81,3 +81,4 @@ export declare function resolveArtifactRoot(query: ArtifactRootQuery): ArtifactR
81
81
  * the one confirmed a moment ago is the better survivor.
82
82
  */
83
83
  export declare function projectCandidatesFrom(discovery: ConfigDiscovery, registry: ProjectRegistry): ProjectCandidate[];
84
+ export {};
@@ -1,5 +1,5 @@
1
1
  import type { FileSystemPort } from './fs-port.js';
2
- export interface MemoryFs {
2
+ interface MemoryFs {
3
3
  fs: FileSystemPort;
4
4
  /** Every file written, keyed by normalised absolute path. */
5
5
  written: Map<string, string>;
@@ -7,3 +7,4 @@ export interface MemoryFs {
7
7
  dirs: Set<string>;
8
8
  }
9
9
  export declare function createMemoryFs(): MemoryFs;
10
+ export {};
@@ -1,5 +1,5 @@
1
1
  import { join } from 'node:path';
2
- import { AppRuntime } from '@reticlehq/core';
2
+ import { AppRuntime } from '@reticlehq/core/telemetry';
3
3
  import { CONTRACT_FILE_VERSION, ContractFileSchema, ContractReadError, FLOW_NAME_PATTERN, ReticleDir, } from '@reticlehq/core';
4
4
  export function reticleDirPaths(root) {
5
5
  return {
@@ -13,3 +13,11 @@ import type { ToolDeps } from '../tools/tool-kit.js';
13
13
  * behaviour every call site had before the resolver existed.
14
14
  */
15
15
  export declare function sessionRoot(deps: ToolDeps, sessionId: string | undefined): string;
16
+ /**
17
+ * The connected session's projectId, or undefined when there is no session to ask.
18
+ *
19
+ * `sessions.resolve` throws when nothing is connected, when the id names no session, and when
20
+ * several are connected and none was named. All three mean the same thing here — we cannot tell
21
+ * which project this call is about — and none of them is a reason to fail the caller's tool.
22
+ */
23
+ export declare function sessionProjectId(deps: ToolDeps, sessionId: string | undefined): string | undefined;
@@ -12,7 +12,7 @@
12
12
  * behaviour every call site had before the resolver existed.
13
13
  */
14
14
  export function sessionRoot(deps, sessionId) {
15
- return deps.artifactRootFor?.(sessionProjectIdOf(deps, sessionId)).root ?? deps.reticleRoot;
15
+ return deps.artifactRootFor?.(sessionProjectId(deps, sessionId)).root ?? deps.reticleRoot;
16
16
  }
17
17
  /**
18
18
  * The connected session's projectId, or undefined when there is no session to ask.
@@ -21,7 +21,14 @@ export function sessionRoot(deps, sessionId) {
21
21
  * several are connected and none was named. All three mean the same thing here — we cannot tell
22
22
  * which project this call is about — and none of them is a reason to fail the caller's tool.
23
23
  */
24
- function sessionProjectIdOf(deps, sessionId) {
24
+ /*
25
+ * Exported alongside `sessionRoot`, and that is the point rather than a convenience. A caller that
26
+ * takes the ROOT from the session and the PROJECT ID from somewhere else has resolved half an
27
+ * address, which is the defect the comment above predicted and `loadNamedFlows` then shipped: it
28
+ * read the id from `readProjectId(process.cwd())` while its root came from here. Both halves come
29
+ * from this file so they cannot disagree again.
30
+ */
31
+ export function sessionProjectId(deps, sessionId) {
25
32
  try {
26
33
  return deps.sessions.resolve(sessionId).projectId;
27
34
  }
@@ -9,7 +9,7 @@
9
9
  * top of this — the orchestration and the verdict live here so the MCP path and the API produce the
10
10
  * same artifact byte-for-byte.
11
11
  */
12
- import type { FlowReplayResult, ReticleVerificationRun, RunId } from '@reticlehq/core';
12
+ import { type FlowReplayResult, type ReticleVerificationRun, type RunId, type VerifyProgressEvent } from '@reticlehq/core';
13
13
  import { type VerificationRunInput } from './build-verification-run.js';
14
14
  import { type ChangedFileInput, type RiskPolicy } from './risk-classify.js';
15
15
  /** The live capabilities ReticleRunner needs. Injected so tests pass fakes (no CDP, no session). */
@@ -23,6 +23,14 @@ export interface RunnerPort {
23
23
  /** Injected run-id generator (no Math.random in logic) — the live adapter supplies a branded uuid. */
24
24
  newRunId(): RunId;
25
25
  }
26
+ /**
27
+ * Narration for a run in flight. Optional, and never load-bearing.
28
+ *
29
+ * A verification is silent for its whole duration, so anything watching from outside cannot tell a
30
+ * run that is working from one that has died. This is the seam that makes the difference visible.
31
+ * It reports what is HAPPENING; the artifact remains the only record of what was PROVED.
32
+ */
33
+ export type VerifyProgressListener = (event: VerifyProgressEvent) => void;
26
34
  /** Run metadata the caller supplies; flows + verdict are produced by verify. */
27
35
  export interface VerifyOptions {
28
36
  names?: string[];
@@ -34,6 +42,11 @@ export interface VerifyOptions {
34
42
  changedFiles?: ChangedFileInput[];
35
43
  /** Which touched surfaces block the verdict (require human confirmation). */
36
44
  policy?: RiskPolicy;
45
+ /**
46
+ * Called as each flow starts and finishes. Best-effort by contract: a listener that throws is
47
+ * swallowed, because a REPORTER must never be able to fail the thing it is reporting on.
48
+ */
49
+ onProgress?: VerifyProgressListener;
37
50
  }
38
51
  export declare class ReticleRunner {
39
52
  #private;
@@ -10,6 +10,7 @@
10
10
  * same artifact byte-for-byte.
11
11
  */
12
12
  import { reportRunTelemetry } from '../telemetry/run-telemetry.js';
13
+ import { boundFlowName, RunFlowStatus, VerifyPhase, } from '@reticlehq/core';
13
14
  import { buildVerificationRun } from './build-verification-run.js';
14
15
  import { mapReplayToFlowResult } from './replay-mapping.js';
15
16
  import { buildRepairPackets } from './repair-prompt.js';
@@ -26,14 +27,50 @@ export class ReticleRunner {
26
27
  */
27
28
  async verify(opts) {
28
29
  const names = opts.names ?? (await this.#port.listFlows());
30
+ /*
31
+ * Emitting NEVER throws into the run. A dashboard, a log or an editor is watching, and none of
32
+ * them is worth failing a verification for — so a listener that blows up is dropped here rather
33
+ * than unwinding a suite somebody is waiting on.
34
+ */
35
+ const emit = (event) => {
36
+ try {
37
+ opts.onProgress?.(event);
38
+ }
39
+ catch {
40
+ /* a reporter cannot fail the thing it reports on */
41
+ }
42
+ };
43
+ const total = names.length;
44
+ // Announced BEFORE the loop: "step 3" without "of 12" does not answer the only question a
45
+ // person watching is actually asking, which is whether to keep waiting.
46
+ emit({ phase: VerifyPhase.FLOWS_FOUND, total, at: this.#port.now() });
29
47
  const replays = [];
30
48
  const flows = [];
31
- for (const name of names) {
49
+ for (const [index, name] of names.entries()) {
32
50
  const start = this.#port.now();
51
+ emit({
52
+ phase: VerifyPhase.FLOW_STARTED,
53
+ index,
54
+ total,
55
+ name: boundFlowName(name),
56
+ at: start,
57
+ });
33
58
  const replay = await this.#port.replayFlow(name);
34
59
  replays.push(replay);
35
- flows.push(mapReplayToFlowResult(replay, this.#port.now() - start));
60
+ const mapped = mapReplayToFlowResult(replay, this.#port.now() - start);
61
+ flows.push(mapped);
62
+ emit({
63
+ phase: VerifyPhase.FLOW_FINISHED,
64
+ index,
65
+ total,
66
+ name: boundFlowName(name),
67
+ // A convenience for colouring a row while the run is live. The VERDICT is computed from the
68
+ // graded artifact below and never from this.
69
+ ok: mapped.status === RunFlowStatus.PASS,
70
+ at: this.#port.now(),
71
+ });
36
72
  }
73
+ emit({ phase: VerifyPhase.GRADING, total, at: this.#port.now() });
37
74
  const changedFiles = classifyChangedFiles(opts.changedFiles ?? []);
38
75
  const risks = buildRisks(changedFiles, opts.policy);
39
76
  const failurePackets = buildRepairPackets(replays);
@@ -16,7 +16,7 @@
16
16
  * needs to wait four seconds to check a four-second gap is a test nobody runs.
17
17
  */
18
18
  /** What an agent needs to know about the continuity of one session. */
19
- export interface Attachment {
19
+ interface Attachment {
20
20
  /** How long THIS attachment has lasted. Resets on reconnect — it is not the session's lifetime. */
21
21
  connectedSinceMs: number;
22
22
  /** How many times this session dropped and came back. Zero means it never left. */
@@ -44,3 +44,4 @@ export declare class AttachmentHistory {
44
44
  */
45
45
  of(sessionId: string): Attachment | undefined;
46
46
  }
47
+ export {};