@reticlehq/server 3.2.0 → 3.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (437) hide show
  1. package/LICENSE-ENTERPRISE +1 -1
  2. package/README.md +3 -3
  3. package/SKILL.md +23 -22
  4. package/dist/chromium-launch-options.d.ts +4 -3
  5. package/dist/chromium-launch-options.js +6 -2
  6. package/dist/command/cli/adhoc-suite.d.ts +41 -0
  7. package/dist/command/cli/adhoc-suite.js +159 -0
  8. package/dist/command/cli/adhoc-verdict.d.ts +58 -2
  9. package/dist/command/cli/adhoc-verdict.js +108 -13
  10. package/dist/command/cli/answers/gate-hook-message.d.ts +6 -0
  11. package/dist/command/cli/answers/gate-hook-message.js +6 -0
  12. package/dist/command/cli/auth/cloud-keystore.d.ts +0 -2
  13. package/dist/command/cli/auth/cloud-keystore.js +0 -3
  14. package/dist/command/cli/auth/cloud-session.d.ts +4 -0
  15. package/dist/command/cli/auth/cloud-session.js +2 -0
  16. package/dist/command/cli/cli-doctor.js +30 -8
  17. package/dist/command/cli/cli-flow-commands.d.ts +3 -6
  18. package/dist/command/cli/cli-flow-commands.js +67 -4
  19. package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
  20. package/dist/command/cli/cli-parse-grammar.js +7 -0
  21. package/dist/command/cli/cli-parse-verify.d.ts +2 -5
  22. package/dist/command/cli/cli-parse-verify.js +86 -13
  23. package/dist/command/cli/cli-parse.d.ts +14 -1
  24. package/dist/command/cli/cli-parse.js +54 -8
  25. package/dist/command/cli/cli-update-commands.js +8 -1
  26. package/dist/command/cli/cli-verify.d.ts +80 -0
  27. package/dist/command/cli/cli-verify.js +181 -26
  28. package/dist/command/cli/cloud-cli.js +5 -2
  29. package/dist/command/cli/cloud-kit.d.ts +0 -2
  30. package/dist/command/cli/cloud-kit.js +3 -5
  31. package/dist/command/cli/cloud-login.js +21 -3
  32. package/dist/command/cli/demo/demo-page.js +6 -3
  33. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +5 -0
  34. package/dist/command/cli/doctor/browser/chromium-hint.js +5 -0
  35. package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
  36. package/dist/command/cli/launch/cli-launch.d.ts +9 -29
  37. package/dist/command/cli/launch/cli-launch.js +27 -49
  38. package/dist/command/cli/launch/sdk-version-match.d.ts +84 -0
  39. package/dist/command/cli/launch/sdk-version-match.js +206 -0
  40. package/dist/command/cli/lifecycle/daemon-lifecycle.js +2 -16
  41. package/dist/command/cli/ports/resolve/cli-port.d.ts +38 -0
  42. package/dist/command/cli/ports/resolve/cli-port.js +169 -15
  43. package/dist/command/cli/report-command.d.ts +16 -0
  44. package/dist/command/cli/report-command.js +97 -0
  45. package/dist/command/cli/setup-mcp-cli.js +13 -13
  46. package/dist/command/cli/tutorial.d.ts +2 -2
  47. package/dist/command/cli/tutorial.js +21 -7
  48. package/dist/command/cli.js +67 -10
  49. package/dist/command/daemon/binding/daemon-status-probe.d.ts +44 -2
  50. package/dist/command/daemon/binding/daemon-status-probe.js +79 -6
  51. package/dist/command/daemon/binding/port-presence.d.ts +1 -1
  52. package/dist/command/daemon/daemon-resolve.d.ts +9 -0
  53. package/dist/command/daemon/daemon-resolve.js +1 -1
  54. package/dist/command/daemon/idle-shutdown.d.ts +2 -1
  55. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +7 -1
  56. package/dist/command/daemon/lifetime/daemon-usefulness.js +30 -7
  57. package/dist/command/dev/stale-issue-guard.d.ts +3 -4
  58. package/dist/command/dev/stale-issue-guard.js +8 -8
  59. package/dist/command/setup/bringup/connect-lease.d.ts +17 -0
  60. package/dist/command/setup/bringup/connect-lease.js +38 -0
  61. package/dist/command/setup/bringup/dev-server-files.d.ts +68 -0
  62. package/dist/command/setup/bringup/dev-server-files.js +131 -0
  63. package/dist/command/setup/bringup/dev-server-log-cap.d.ts +35 -0
  64. package/dist/command/setup/bringup/dev-server-log-cap.js +121 -0
  65. package/dist/command/setup/bringup/ensure-daemon.d.ts +65 -4
  66. package/dist/command/setup/bringup/ensure-daemon.js +135 -16
  67. package/dist/command/setup/bringup/static-page-server.d.ts +35 -0
  68. package/dist/command/setup/bringup/static-page-server.js +151 -0
  69. package/dist/command/setup/desktop-shape.d.ts +4 -0
  70. package/dist/command/setup/desktop-shape.js +18 -2
  71. package/dist/command/setup/init/init-host.js +8 -0
  72. package/dist/command/setup/init/init-port.d.ts +15 -0
  73. package/dist/command/setup/init/init-port.js +44 -0
  74. package/dist/command/setup/init/init-runtime.d.ts +1 -1
  75. package/dist/command/setup/init/init-runtime.js +39 -2
  76. package/dist/command/setup/node-effects.d.ts +27 -14
  77. package/dist/command/setup/node-effects.js +80 -44
  78. package/dist/command/setup/probe/loopback-probe-urls.d.ts +7 -0
  79. package/dist/command/setup/probe/loopback-probe-urls.js +40 -0
  80. package/dist/command/setup/probe/page-probe.d.ts +13 -2
  81. package/dist/command/setup/probe/page-probe.js +18 -3
  82. package/dist/command/setup/run-setup.d.ts +26 -1
  83. package/dist/command/setup/run-setup.js +96 -13
  84. package/dist/command/setup/session-pick.d.ts +13 -0
  85. package/dist/command/setup/session-pick.js +20 -0
  86. package/dist/command/setup/setup-command.d.ts +2 -14
  87. package/dist/command/setup/setup-command.js +105 -31
  88. package/dist/command/setup/setup-mcp.js +3 -3
  89. package/dist/command/setup/terminal/wait-progress.d.ts +8 -0
  90. package/dist/command/setup/terminal/wait-progress.js +17 -0
  91. package/dist/features/crawl/crawl-empty.js +1 -1
  92. package/dist/features/crawl/crawl-tools.d.ts +6 -0
  93. package/dist/features/crawl/crawl-tools.js +57 -0
  94. package/dist/features/crawl/crawl.d.ts +2 -0
  95. package/dist/features/crawl/crawl.js +171 -156
  96. package/dist/features/exhaust/app-coverage.d.ts +33 -0
  97. package/dist/features/exhaust/app-coverage.js +31 -0
  98. package/dist/features/exhaust/code-coverage.d.ts +47 -0
  99. package/dist/features/exhaust/code-coverage.js +77 -0
  100. package/dist/features/exhaust/exhaust-run.d.ts +33 -0
  101. package/dist/features/exhaust/exhaust-run.js +82 -0
  102. package/dist/features/exhaust/explorer.d.ts +103 -0
  103. package/dist/features/exhaust/explorer.js +195 -0
  104. package/dist/features/exhaust/failure-branches.d.ts +33 -0
  105. package/dist/features/exhaust/failure-branches.js +92 -0
  106. package/dist/features/exhaust/ledger.d.ts +202 -0
  107. package/dist/features/exhaust/ledger.js +252 -0
  108. package/dist/features/exhaust/session-fold.d.ts +31 -0
  109. package/dist/features/exhaust/session-fold.js +79 -0
  110. package/dist/features/exhaust/session-port.d.ts +36 -0
  111. package/dist/features/exhaust/session-port.js +102 -0
  112. package/dist/features/harness/drive-report.d.ts +0 -9
  113. package/dist/features/harness/drive-report.js +18 -0
  114. package/dist/features/harness/driver.js +4 -7
  115. package/dist/features/harness/fill-values.d.ts +6 -0
  116. package/dist/features/harness/fill-values.js +3 -0
  117. package/dist/features/harness/jev-driver.js +36 -22
  118. package/dist/features/harness/openai-driver.js +4 -7
  119. package/dist/features/harness/platform-config.d.ts +10 -0
  120. package/dist/features/harness/platform-config.js +13 -6
  121. package/dist/index.d.ts +10 -1
  122. package/dist/index.js +78 -104
  123. package/dist/judgement/capsule/capsule-store.d.ts +31 -2
  124. package/dist/judgement/capsule/capsule-store.js +58 -6
  125. package/dist/judgement/capsule/capsule.js +5 -0
  126. package/dist/judgement/capsule/causal-summary.d.ts +13 -1
  127. package/dist/judgement/capsule/causal-summary.js +7 -0
  128. package/dist/judgement/domain/domain-model.js +40 -9
  129. package/dist/judgement/oracles/self-instrument.js +4 -2
  130. package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
  131. package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
  132. package/dist/judgement/runs/artifact/gap-report.js +46 -0
  133. package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
  134. package/dist/judgement/runs/artifact/gap-summary.js +85 -0
  135. package/dist/judgement/runs/artifact/render-report.js +4 -1
  136. package/dist/judgement/runs/artifact/replay-mapping.d.ts +2 -2
  137. package/dist/judgement/runs/artifact/replay-mapping.js +44 -9
  138. package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
  139. package/dist/judgement/runs/artifact/to-artifact.js +1 -1
  140. package/dist/judgement/runs/context-tools.js +21 -3
  141. package/dist/judgement/runs/drive-run.js +7 -2
  142. package/dist/judgement/runs/verification-sync.d.ts +3 -1
  143. package/dist/judgement/runs/verification-sync.js +1 -1
  144. package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
  145. package/dist/language/flows/annotate-notes/annotate.js +66 -18
  146. package/dist/language/flows/change/affected.d.ts +9 -0
  147. package/dist/language/flows/change/affected.js +35 -0
  148. package/dist/language/flows/change/gate.d.ts +20 -0
  149. package/dist/language/flows/change/gate.js +12 -1
  150. package/dist/language/flows/flow-anchor.d.ts +12 -0
  151. package/dist/language/flows/flow-anchor.js +20 -0
  152. package/dist/language/flows/flow-author.d.ts +7 -0
  153. package/dist/language/flows/flow-author.js +19 -0
  154. package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
  155. package/dist/language/flows/flow-expect-grammar.js +92 -11
  156. package/dist/language/flows/flow-intent.js +1 -1
  157. package/dist/language/flows/flow-journey.d.ts +54 -0
  158. package/dist/language/flows/flow-journey.js +119 -0
  159. package/dist/language/flows/flow-learning.d.ts +3 -0
  160. package/dist/language/flows/flow-learning.js +39 -8
  161. package/dist/language/flows/flow-replay-run.d.ts +33 -12
  162. package/dist/language/flows/flow-replay-run.js +131 -52
  163. package/dist/language/flows/flow-replay-types.d.ts +9 -0
  164. package/dist/language/flows/flow-replay.d.ts +27 -12
  165. package/dist/language/flows/flow-replay.js +127 -111
  166. package/dist/language/flows/flow-result.d.ts +2 -0
  167. package/dist/language/flows/flow-result.js +25 -0
  168. package/dist/language/flows/flow-step-runners.d.ts +26 -10
  169. package/dist/language/flows/flow-step-runners.js +20 -4
  170. package/dist/language/flows/flow-success.d.ts +21 -6
  171. package/dist/language/flows/flow-success.js +50 -138
  172. package/dist/language/flows/flow-tools.js +17 -5
  173. package/dist/language/flows/flows.d.ts +18 -5
  174. package/dist/language/flows/flows.js +101 -16
  175. package/dist/language/flows/heal.d.ts +9 -1
  176. package/dist/language/flows/heal.js +24 -2
  177. package/dist/language/flows/learned-sources.d.ts +21 -0
  178. package/dist/language/flows/learned-sources.js +84 -0
  179. package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
  180. package/dist/language/flows/recording/recording-backtrack.js +1 -1
  181. package/dist/language/flows/recording/replay-halt.d.ts +2 -1
  182. package/dist/language/flows/recording/replay-halt.js +3 -1
  183. package/dist/language/flows/recording/tape/recordings.d.ts +31 -2
  184. package/dist/language/flows/recording/tape/recordings.js +55 -1
  185. package/dist/language/flows/replay.d.ts +19 -0
  186. package/dist/language/flows/replay.js +53 -13
  187. package/dist/language/flows/stores/annotation-store.d.ts +5 -5
  188. package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
  189. package/dist/language/flows/stores/flake-store.js +2 -3
  190. package/dist/language/flows/suite/coverage.d.ts +1 -1
  191. package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
  192. package/dist/language/flows/verify-change-tools.js +19 -2
  193. package/dist/launch-chromium.d.ts +80 -0
  194. package/dist/launch-chromium.js +218 -0
  195. package/dist/memory/cloud/cloud-config.d.ts +11 -2
  196. package/dist/memory/cloud/cloud-config.js +47 -7
  197. package/dist/memory/cloud/cloud-sync.d.ts +4 -3
  198. package/dist/memory/cloud/cloud-sync.js +7 -10
  199. package/dist/memory/cloud/harness-config.d.ts +2 -0
  200. package/dist/memory/cloud/harness-offer.js +5 -6
  201. package/dist/memory/cloud/harness-switch.js +5 -6
  202. package/dist/memory/cloud/sync-cycle.d.ts +78 -1
  203. package/dist/memory/cloud/sync-cycle.js +321 -53
  204. package/dist/memory/cloud/sync-daemon.d.ts +13 -0
  205. package/dist/memory/cloud/sync-daemon.js +45 -20
  206. package/dist/memory/cloud/sync-disk.js +27 -8
  207. package/dist/memory/impact/impact-store.js +6 -0
  208. package/dist/memory/intent/inline-intent.js +8 -3
  209. package/dist/memory/intent/intent-shard-store.d.ts +33 -47
  210. package/dist/memory/intent/intent-shard-store.js +252 -140
  211. package/dist/memory/intent/intent-shard.d.ts +0 -23
  212. package/dist/memory/intent/intent-shard.js +1 -11
  213. package/dist/memory/intent/intent-store.d.ts +13 -8
  214. package/dist/memory/intent/intent-store.js +46 -90
  215. package/dist/memory/intent/intent-tools.js +34 -23
  216. package/dist/memory/journal/ambient-store.js +2 -3
  217. package/dist/memory/journal/deviation-report.js +4 -1
  218. package/dist/memory/journal/deviation-service.js +10 -2
  219. package/dist/memory/journal/drive-flow.d.ts +19 -14
  220. package/dist/memory/journal/drive-flow.js +65 -48
  221. package/dist/memory/journal/envelope-store.js +2 -3
  222. package/dist/memory/journal/journal-recorder.d.ts +21 -0
  223. package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
  224. package/dist/memory/journal/on-disk/retain-policy.js +44 -0
  225. package/dist/memory/journal/on-disk/retention.d.ts +14 -10
  226. package/dist/memory/journal/on-disk/retention.js +13 -12
  227. package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
  228. package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
  229. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -11
  230. package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -45
  231. package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
  232. package/dist/memory/journal/on-disk/workspace-tiers.js +90 -0
  233. package/dist/memory/journal/route-template.d.ts +22 -0
  234. package/dist/memory/journal/route-template.js +44 -0
  235. package/dist/memory/journal/session-end.d.ts +13 -2
  236. package/dist/memory/journal/session-end.js +88 -18
  237. package/dist/memory/journal/session-journal.d.ts +8 -1
  238. package/dist/memory/journal/session-journal.js +10 -0
  239. package/dist/memory/project/baselines.d.ts +1 -1
  240. package/dist/memory/project/dir/reticle-dir.d.ts +3 -1
  241. package/dist/memory/project/dir/reticle-dir.js +1 -0
  242. package/dist/memory/project/fs/fs-port.js +44 -5
  243. package/dist/memory/project/fs/write-atomic.d.ts +26 -0
  244. package/dist/memory/project/fs/write-atomic.js +48 -0
  245. package/dist/memory/project/project-tools.js +3 -1
  246. package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
  247. package/dist/memory/recall/prior/connection-memory.js +8 -0
  248. package/dist/memory/recall/registered-projects.d.ts +2 -1
  249. package/dist/portal/bridge/auth-failure-reason.d.ts +1 -1
  250. package/dist/portal/bridge/auth-failure-reason.js +9 -4
  251. package/dist/portal/bridge/bridge.d.ts +8 -0
  252. package/dist/portal/bridge/bridge.js +43 -2
  253. package/dist/portal/input/js-coverage.d.ts +25 -0
  254. package/dist/portal/input/js-coverage.js +30 -0
  255. package/dist/portal/input/real-input.d.ts +11 -0
  256. package/dist/portal/input/real-input.js +31 -5
  257. package/dist/portal/pool/browser-pool.d.ts +10 -0
  258. package/dist/portal/pool/browser-pool.js +10 -0
  259. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  260. package/dist/portal/pool/playwright-launcher.js +21 -13
  261. package/dist/portal/pool/pool-contract.d.ts +2 -0
  262. package/dist/portal/pool/storage-seed.d.ts +2 -1
  263. package/dist/portal/pool/zero-install.d.ts +27 -0
  264. package/dist/portal/pool/zero-install.js +54 -0
  265. package/dist/portal/realm/web-realm.js +6 -0
  266. package/dist/portal/session/dev-server/dev-command.d.ts +2 -2
  267. package/dist/portal/session/dev-server/dev-command.js +30 -12
  268. package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
  269. package/dist/portal/session/dev-server/dev-server-probe.js +17 -1
  270. package/dist/portal/session/dev-server/route-status-probe.d.ts +24 -0
  271. package/dist/portal/session/dev-server/route-status-probe.js +57 -0
  272. package/dist/portal/session/dev-server/served-document.d.ts +21 -0
  273. package/dist/portal/session/dev-server/served-document.js +57 -0
  274. package/dist/portal/session/facts/background-traffic.d.ts +9 -0
  275. package/dist/portal/session/facts/background-traffic.js +25 -0
  276. package/dist/portal/session/facts/observed-state.d.ts +11 -0
  277. package/dist/portal/session/facts/observed-state.js +34 -0
  278. package/dist/portal/session/live-control-tools.js +48 -3
  279. package/dist/portal/session/no-session-diagnosis.d.ts +29 -0
  280. package/dist/portal/session/no-session-diagnosis.js +62 -5
  281. package/dist/portal/session/no-session-next-action.d.ts +13 -0
  282. package/dist/portal/session/no-session-next-action.js +48 -9
  283. package/dist/portal/session/no-session-watch.d.ts +18 -0
  284. package/dist/portal/session/no-session-watch.js +88 -2
  285. package/dist/portal/session/presence/attachment-history.d.ts +13 -2
  286. package/dist/portal/session/session-health.d.ts +61 -0
  287. package/dist/portal/session/session-health.js +43 -3
  288. package/dist/portal/session/session-info.d.ts +6 -0
  289. package/dist/portal/session/session-manager.d.ts +29 -6
  290. package/dist/portal/session/session-manager.js +42 -5
  291. package/dist/portal/session/session-reaper.d.ts +28 -0
  292. package/dist/portal/session/session-reaper.js +49 -1
  293. package/dist/portal/session/session-successor.d.ts +11 -0
  294. package/dist/portal/session/session-successor.js +14 -1
  295. package/dist/portal/session/session-verdict-facts.d.ts +28 -0
  296. package/dist/portal/session/session-verdict-facts.js +15 -0
  297. package/dist/portal/session/session.d.ts +10 -0
  298. package/dist/portal/session/session.js +34 -26
  299. package/dist/surface/http-server.d.ts +2 -1
  300. package/dist/surface/http-server.js +4 -2
  301. package/dist/surface/mcp/mcp-proxy.d.ts +2 -2
  302. package/dist/surface/mcp/mcp-proxy.js +5 -5
  303. package/dist/surface/mcp/mcp.js +4 -2
  304. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +13 -1
  305. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +27 -2
  306. package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
  307. package/dist/surface/mcp/server-instructions.js +21 -8
  308. package/dist/surface/tools/act/after-match.d.ts +17 -0
  309. package/dist/surface/tools/act/after-match.js +30 -0
  310. package/dist/surface/tools/act/already-true.d.ts +40 -0
  311. package/dist/surface/tools/act/already-true.js +36 -0
  312. package/dist/surface/tools/act/durable.d.ts +69 -0
  313. package/dist/surface/tools/act/durable.js +139 -0
  314. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +19 -6
  315. package/dist/surface/tools/act/navigation/navigate-arrival.js +60 -10
  316. package/dist/surface/tools/act/navigation/navigate-result.d.ts +1 -12
  317. package/dist/surface/tools/act/navigation/navigate-result.js +21 -3
  318. package/dist/surface/tools/act/proved-controls.d.ts +9 -0
  319. package/dist/surface/tools/act/proved-controls.js +11 -0
  320. package/dist/surface/tools/act/sequence-grade.d.ts +5 -0
  321. package/dist/surface/tools/act/sequence-grade.js +32 -1
  322. package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
  323. package/dist/surface/tools/act/settle-in-flight.js +29 -6
  324. package/dist/surface/tools/act-capsule.d.ts +7 -0
  325. package/dist/surface/tools/act-capsule.js +68 -8
  326. package/dist/surface/tools/act-sequence-tool.js +25 -8
  327. package/dist/surface/tools/act-tools.js +51 -74
  328. package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
  329. package/dist/surface/tools/args/numeric-bounds.js +30 -3
  330. package/dist/surface/tools/assert/assert-grade.js +26 -3
  331. package/dist/surface/tools/assert/assert-verdict.js +32 -6
  332. package/dist/surface/tools/browser-tools.js +17 -4
  333. package/dist/surface/tools/coverage-tools.js +27 -1
  334. package/dist/surface/tools/dynamic-tools.js +6 -0
  335. package/dist/surface/tools/error-recovery.js +4 -4
  336. package/dist/surface/tools/feedback-invite.js +6 -4
  337. package/dist/surface/tools/feedback-tools.d.ts +2 -1
  338. package/dist/surface/tools/feedback-tools.js +1 -1
  339. package/dist/surface/tools/harness-explore.d.ts +3 -2
  340. package/dist/surface/tools/harness-explore.js +7 -6
  341. package/dist/surface/tools/invoke-tool.js +17 -4
  342. package/dist/surface/tools/lease-hint.d.ts +8 -0
  343. package/dist/surface/tools/lease-hint.js +10 -0
  344. package/dist/surface/tools/lease-tools.d.ts +16 -28
  345. package/dist/surface/tools/lease-tools.js +68 -11
  346. package/dist/surface/tools/lineage-tools.js +1 -1
  347. package/dist/surface/tools/live-call-text.js +4 -1
  348. package/dist/surface/tools/observe-tools.js +23 -7
  349. package/dist/surface/tools/real-input-attempt.d.ts +0 -5
  350. package/dist/surface/tools/real-input-attempt.js +1 -1
  351. package/dist/surface/tools/tool-kit.d.ts +5 -0
  352. package/dist/surface/tools/tool-kit.js +6 -1
  353. package/dist/surface/tools/tool-surface.js +17 -5
  354. package/dist/surface/tools/tools.js +68 -29
  355. package/dist/telemetry/argument-shape.d.ts +0 -2
  356. package/dist/telemetry/argument-shape.js +0 -4
  357. package/dist/telemetry/error-class.d.ts +2 -3
  358. package/dist/telemetry/error-class.js +2 -3
  359. package/dist/telemetry/feedback-local.d.ts +1 -0
  360. package/dist/telemetry/feedback-local.js +1 -3
  361. package/dist/telemetry/feedback.d.ts +1 -1
  362. package/dist/telemetry/harness-drive.d.ts +0 -2
  363. package/dist/telemetry/harness-drive.js +0 -4
  364. package/dist/telemetry/hud-metrics.d.ts +32 -0
  365. package/dist/telemetry/hud-metrics.js +95 -0
  366. package/dist/telemetry/session-metrics.d.ts +5 -0
  367. package/dist/telemetry/session-metrics.js +15 -1
  368. package/dist/wire-journal.d.ts +34 -0
  369. package/dist/wire-journal.js +104 -0
  370. package/dist/workspace-packages.d.ts +0 -2
  371. package/dist/workspace-packages.js +1 -9
  372. package/docs/README.md +5 -2
  373. package/docs/actions.mdx +3 -3
  374. package/docs/agent-cheatsheet.md +4 -4
  375. package/docs/architecture.md +6 -6
  376. package/docs/best-practices.mdx +1 -1
  377. package/docs/capabilities.mdx +32 -1
  378. package/docs/cli/cloud.mdx +21 -9
  379. package/docs/cli/doctor.mdx +4 -0
  380. package/docs/cli/feedback.mdx +2 -2
  381. package/docs/cli/gate.mdx +9 -4
  382. package/docs/cli/init.mdx +1 -0
  383. package/docs/cli/report.mdx +44 -0
  384. package/docs/cli/update.mdx +10 -0
  385. package/docs/cli.mdx +9 -0
  386. package/docs/desktop.mdx +14 -10
  387. package/docs/environment.mdx +87 -0
  388. package/docs/faq.mdx +18 -16
  389. package/docs/first-drive.md +5 -13
  390. package/docs/flows.md +32 -2
  391. package/docs/frameworks.mdx +140 -9
  392. package/docs/getting-started.md +3 -3
  393. package/docs/http-transport.md +6 -3
  394. package/docs/human-control.md +2 -2
  395. package/docs/index.mdx +16 -6
  396. package/docs/install-agentic.mdx +37 -1
  397. package/docs/install-manual.mdx +1 -1
  398. package/docs/integration-patterns.md +3 -3
  399. package/docs/multi-agent-testing.md +1 -1
  400. package/docs/packages/babel-plugin.mdx +1 -1
  401. package/docs/packages/browser.mdx +2 -2
  402. package/docs/packages/react.mdx +2 -2
  403. package/docs/packages/tauri.mdx +1 -1
  404. package/docs/packages/vite-plugin.mdx +2 -2
  405. package/docs/packages.mdx +9 -9
  406. package/docs/predicates.mdx +176 -7
  407. package/docs/quickstart.mdx +2 -2
  408. package/docs/recipes.mdx +2 -2
  409. package/docs/state-management.mdx +2 -2
  410. package/docs/system-map.md +1 -1
  411. package/docs/telemetry.md +1 -1
  412. package/docs/token-efficiency.md +3 -3
  413. package/docs/tools/act-and-wait.mdx +1 -0
  414. package/docs/tools/act-sequence.mdx +1 -1
  415. package/docs/tools/console.mdx +1 -1
  416. package/docs/tools/inspect.mdx +1 -1
  417. package/docs/tools/network.mdx +1 -1
  418. package/docs/tools/query.mdx +11 -11
  419. package/docs/tools/sessions.mdx +1 -1
  420. package/docs/tools/snapshot.mdx +1 -1
  421. package/docs/tools/state.mdx +1 -1
  422. package/docs/tools/wait-for.mdx +1 -1
  423. package/docs/usage.md +8 -7
  424. package/docs/use-cases.mdx +157 -0
  425. package/docs/vs-screenshots.mdx +3 -3
  426. package/docs/what-is-recorded.md +62 -0
  427. package/docs/what-is-reticle.mdx +17 -20
  428. package/docs/why-reticle.mdx +14 -21
  429. package/package.json +11 -10
  430. package/dist/judgement/capsule/minimize.d.ts +0 -12
  431. package/dist/judgement/capsule/minimize.js +0 -22
  432. package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
  433. package/dist/judgement/outcome/predicate-to-expect.js +0 -148
  434. package/dist/judgement/phenomena/phenomena.d.ts +0 -26
  435. package/dist/judgement/phenomena/phenomena.js +0 -101
  436. package/dist/language/flows/flow-report.d.ts +0 -22
  437. package/dist/language/flows/flow-report.js +0 -106
@@ -0,0 +1,151 @@
1
+ /**
2
+ * The dev server `init` starts for a plain HTML page that has none of its own.
3
+ *
4
+ * A directory holding only `index.html` (and a script or two) used to be wired correctly — init
5
+ * writes the connect snippet into the page — and then stop at "No dev command … start the app
6
+ * yourself and pass --url". The one thing left between that user and a connected session was a web
7
+ * server, which is the one thing a page like that never had. So init starts this one, the same way it
8
+ * starts `npm run dev`, and the rest of setup (wait, open, prove the connect) runs unchanged.
9
+ *
10
+ * It is run as its own process (`node static-page-server.js --dir <app>`), not inside init, because it
11
+ * has to outlive init exactly like any handed-over dev server. It imports nothing but Node, so the
12
+ * built file runs on its own.
13
+ *
14
+ * Loopback only, on both families: a page served to the LAN would publish the pairing token the
15
+ * snippet carries.
16
+ */
17
+ import { existsSync, readFile, statSync } from 'node:fs';
18
+ import { createServer } from 'node:http';
19
+ import { extname, join, resolve, sep } from 'node:path';
20
+ import { fileURLToPath, pathToFileURL } from 'node:url';
21
+ export const STATIC_PAGE_INDEX = 'index.html';
22
+ /** Where the search for a free port starts when none is given — clear of Vite's 5173 run. */
23
+ export const STATIC_PAGE_FIRST_PORT = 5500;
24
+ const PORT_SEARCH_SPAN = 50;
25
+ const DIR_FLAG = '--dir';
26
+ const PORT_FLAG = '--port';
27
+ const LOOPBACK_V4 = '127.0.0.1';
28
+ const LOOPBACK_V6 = '::1';
29
+ const ANNOUNCED_HOST = 'localhost';
30
+ const CONTENT_TYPES = {
31
+ '.html': 'text/html; charset=utf-8',
32
+ '.js': 'text/javascript; charset=utf-8',
33
+ '.mjs': 'text/javascript; charset=utf-8',
34
+ '.css': 'text/css; charset=utf-8',
35
+ '.json': 'application/json; charset=utf-8',
36
+ '.svg': 'image/svg+xml',
37
+ '.png': 'image/png',
38
+ '.jpg': 'image/jpeg',
39
+ '.jpeg': 'image/jpeg',
40
+ '.gif': 'image/gif',
41
+ '.webp': 'image/webp',
42
+ '.ico': 'image/x-icon',
43
+ '.woff2': 'font/woff2',
44
+ '.txt': 'text/plain; charset=utf-8',
45
+ };
46
+ const FALLBACK_TYPE = 'application/octet-stream';
47
+ /** The file a request names, or null when it is missing or outside `root`. */
48
+ function fileFor(root, rawUrl) {
49
+ let path;
50
+ try {
51
+ path = decodeURIComponent(new URL(rawUrl, 'http://x').pathname);
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ const target = resolve(root, `.${path}`);
57
+ if (target !== root && !target.startsWith(`${root}${sep}`))
58
+ return null;
59
+ const file = path.endsWith('/') ? join(target, STATIC_PAGE_INDEX) : target;
60
+ try {
61
+ return statSync(file).isFile() ? file : null;
62
+ }
63
+ catch {
64
+ return null;
65
+ }
66
+ }
67
+ function listen(server, port, host) {
68
+ return new Promise((ok, fail) => {
69
+ server.once('error', fail);
70
+ server.listen(port, host, () => {
71
+ server.off('error', fail);
72
+ ok();
73
+ });
74
+ });
75
+ }
76
+ function closeServer(server) {
77
+ return new Promise((done) => server.close(() => done()));
78
+ }
79
+ export async function startStaticPageServer(opts) {
80
+ const root = resolve(opts.root);
81
+ const handler = (req, res) => {
82
+ const file = fileFor(root, req.url ?? '/');
83
+ if (null === file) {
84
+ res.writeHead(404).end();
85
+ return;
86
+ }
87
+ readFile(file, (err, body) => {
88
+ if (null !== err) {
89
+ res.writeHead(404).end();
90
+ return;
91
+ }
92
+ res.writeHead(200, {
93
+ 'content-type': CONTENT_TYPES[extname(file).toLowerCase()] ?? FALLBACK_TYPE,
94
+ 'cache-control': 'no-store',
95
+ });
96
+ res.end(body);
97
+ });
98
+ };
99
+ const v4 = createServer(handler);
100
+ // Port 0 means "any": the v4 bind picks it, and the v6 listener joins the same number.
101
+ const candidates = 0 === opts.port ? [0] : Array.from({ length: PORT_SEARCH_SPAN }, (_, i) => opts.port + i);
102
+ let bound;
103
+ for (const port of candidates) {
104
+ try {
105
+ await listen(v4, port, LOOPBACK_V4);
106
+ bound = v4.address().port;
107
+ break;
108
+ }
109
+ catch {
110
+ /* taken: try the next one */
111
+ }
112
+ }
113
+ if (undefined === bound) {
114
+ throw new Error(`no free port in ${String(opts.port)}–${String(opts.port + PORT_SEARCH_SPAN)}`);
115
+ }
116
+ // `localhost` resolves to ::1 first on macOS, so the page must answer there too. A machine with
117
+ // no IPv6 loopback just keeps the v4 listener.
118
+ const v6 = createServer(handler);
119
+ const hasV6 = await listen(v6, bound, LOOPBACK_V6).then(() => true, () => false);
120
+ return {
121
+ url: `http://${ANNOUNCED_HOST}:${String(bound)}/`,
122
+ close: async () => {
123
+ await closeServer(v4);
124
+ if (hasV6)
125
+ await closeServer(v6);
126
+ },
127
+ };
128
+ }
129
+ /**
130
+ * The command setup runs for a page with no dev server of its own, or undefined when this is not
131
+ * that page. Quoted so an app path with a space survives the shell.
132
+ */
133
+ export function staticPageDevCommand(opts) {
134
+ if (!opts.isStaticPage || !existsSync(join(opts.appDir, STATIC_PAGE_INDEX)))
135
+ return undefined;
136
+ const script = fileURLToPath(import.meta.url).replace(/\.ts$/, '.js');
137
+ return `"${process.execPath}" "${script}" ${DIR_FLAG} "${opts.appDir}"`;
138
+ }
139
+ function flag(argv, name) {
140
+ const at = argv.indexOf(name);
141
+ return -1 === at ? undefined : argv[at + 1];
142
+ }
143
+ // Run as a script: serve until killed, printing the url the setup wait reads.
144
+ if (undefined !== process.argv[1] && import.meta.url === pathToFileURL(process.argv[1]).href) {
145
+ const dir = flag(process.argv, DIR_FLAG) ?? process.cwd();
146
+ const port = Number(flag(process.argv, PORT_FLAG) ?? STATIC_PAGE_FIRST_PORT);
147
+ startStaticPageServer({ root: dir, port }).then((server) => process.stdout.write(`serving ${dir}\n Local: ${server.url}\n`), (err) => {
148
+ process.stderr.write(`static page server: ${String(err)}\n`);
149
+ process.exit(1);
150
+ });
151
+ }
@@ -53,6 +53,10 @@ interface ShapePolicy {
53
53
  readonly connectBudgetMs: number;
54
54
  /** Said out loud, because a desktop run looks stuck if nobody explains the wait. */
55
55
  readonly note: string | undefined;
56
+ /** What the connect wait is waiting on, for the progress lines it prints while it waits. */
57
+ readonly awaiting: string;
56
58
  }
59
+ /** "a Tauri app", "an Electron app": printed when the shape is detected. */
60
+ export declare function describeShape(shape: AppShape): string;
57
61
  export declare function policyFor(shape: AppShape): ShapePolicy;
58
62
  export {};
@@ -42,7 +42,21 @@ export function isDesktopOrigin(url) {
42
42
  }
43
43
  const WEB_CONNECT_MS = 120_000;
44
44
  /** A cold `tauri dev` compiles the Rust side before a window exists. */
45
- const DESKTOP_CONNECT_MS = 10 * 60_000;
45
+ const TAURI_CONNECT_MS = 10 * 60_000;
46
+ /**
47
+ * Electron has no compile step of that size: its window is a Node process loading a dev server that
48
+ * is already up. It was given Tauri's ten minutes, so a run whose window was never going to dial in
49
+ * sat silent for all of them — longer than the daemon it was waiting on stayed alive.
50
+ */
51
+ const ELECTRON_CONNECT_MS = 3 * 60_000;
52
+ /** "a Tauri app", "an Electron app": printed when the shape is detected. */
53
+ export function describeShape(shape) {
54
+ if (AppShape.ELECTRON === shape)
55
+ return 'an Electron app';
56
+ if (AppShape.TAURI === shape)
57
+ return 'a Tauri app';
58
+ return 'a web app';
59
+ }
46
60
  export function policyFor(shape) {
47
61
  if (AppShape.WEB === shape) {
48
62
  return {
@@ -50,12 +64,14 @@ export function policyFor(shape) {
50
64
  requireHttpReady: true,
51
65
  connectBudgetMs: WEB_CONNECT_MS,
52
66
  note: undefined,
67
+ awaiting: 'the page',
53
68
  };
54
69
  }
55
70
  return {
56
71
  openBrowser: false,
57
72
  requireHttpReady: false,
58
- connectBudgetMs: DESKTOP_CONNECT_MS,
73
+ connectBudgetMs: AppShape.TAURI === shape ? TAURI_CONNECT_MS : ELECTRON_CONNECT_MS,
74
+ awaiting: AppShape.TAURI === shape ? 'the Tauri window' : 'the Electron window',
59
75
  note: AppShape.TAURI === shape
60
76
  ? 'Tauri app: not opening a browser, because its own window is the client. A cold `tauri dev` builds the Rust side first, so the window can take minutes to appear.'
61
77
  : 'Electron app: not opening a browser, because its own window is the client. Waiting for the app to launch and dial in.',
@@ -3,6 +3,9 @@ import { reportInitOutcome } from '../../../telemetry/init-telemetry.js';
3
3
  import { reportOnboardingStep } from '../../../telemetry/onboarding-funnel.js';
4
4
  import { defaultPairingTokenDir, readOrCreatePairingTokenSync, } from '../../../portal/bridge/pairing-token.js';
5
5
  import { declaredInstallSource } from '../../../telemetry/install-source.js';
6
+ /** The variable Claude Code sets on every process it spawns, and the value it sets it to. */
7
+ const CLAUDE_CODE_MARKER_ENV = 'CLAUDECODE';
8
+ const CLAUDE_CODE_MARKER_VALUE = '1';
6
9
  export function serverInitHost() {
7
10
  return {
8
11
  span(name, fields, fn) {
@@ -33,5 +36,10 @@ export function serverInitHost() {
33
36
  installSource() {
34
37
  return declaredInstallSource();
35
38
  },
39
+ // Claude Code marks every process it spawns. If the marker ever changes, init falls back to the
40
+ // notice it printed before, which is the safe direction.
41
+ insideClaudeCode() {
42
+ return CLAUDE_CODE_MARKER_VALUE === process.env[CLAUDE_CODE_MARKER_ENV];
43
+ },
36
44
  };
37
45
  }
@@ -0,0 +1,15 @@
1
+ /**
2
+ * `RETICLE_PORT`, when it names a port. The one reader of it for the CLI, `init` included.
3
+ *
4
+ * `init` took only `--port`, so a shell that exported RETICLE_PORT got a project wired, and a daemon
5
+ * started, on the default port while every other command it ran dialled the exported one. Fed to
6
+ * `portForInit` as the explicit port, so the files phase writes it into `.reticle.json` and the
7
+ * runtime phase binds it: the two halves of `init` cannot disagree.
8
+ */
9
+ export declare function portFromEnv(env: Readonly<Record<string, string | undefined>>): number | undefined;
10
+ export declare function portForInit(explicit: number | undefined, configured: number | undefined, projectId: string | undefined, deps: {
11
+ /** The projects the daemon on `port` belongs to or is serving right now. */
12
+ daemonProjects: (port: number) => Promise<readonly string[]>;
13
+ daemonPresent: (port: number) => Promise<boolean>;
14
+ pickPort: (preferred: number) => Promise<number>;
15
+ }): Promise<number | undefined>;
@@ -0,0 +1,44 @@
1
+ /**
2
+ * The daemon port `reticle init` wires a project to.
3
+ *
4
+ * Init used to leave this unset, so every project on a machine was wired to the default port. The
5
+ * second one to run was connected to the first one's daemon, and the bridge refused its app. When a
6
+ * daemon for another project already holds the default, the new project gets its own port, and init
7
+ * records it in `.reticle.json`, where the CLI and the build plugins both read it.
8
+ *
9
+ * Undefined means the default.
10
+ */
11
+ import { RETICLE_DEFAULT_PORT, ReticleEnv } from '@reticlehq/core';
12
+ const MAX_PORT = 65_535;
13
+ /**
14
+ * `RETICLE_PORT`, when it names a port. The one reader of it for the CLI, `init` included.
15
+ *
16
+ * `init` took only `--port`, so a shell that exported RETICLE_PORT got a project wired, and a daemon
17
+ * started, on the default port while every other command it ran dialled the exported one. Fed to
18
+ * `portForInit` as the explicit port, so the files phase writes it into `.reticle.json` and the
19
+ * runtime phase binds it: the two halves of `init` cannot disagree.
20
+ */
21
+ export function portFromEnv(env) {
22
+ const raw = env[ReticleEnv.PORT];
23
+ if (undefined === raw || !/^\d+$/.test(raw))
24
+ return undefined;
25
+ const port = Number(raw);
26
+ return 0 < port && port <= MAX_PORT ? port : undefined;
27
+ }
28
+ export async function portForInit(explicit, configured, projectId, deps) {
29
+ if (explicit !== undefined)
30
+ return explicit;
31
+ if (configured !== undefined)
32
+ return configured;
33
+ // Undefined, not the default's number: an explicit default would be written into every generated
34
+ // config as a `port` nobody chose.
35
+ if (!(await deps.daemonPresent(RETICLE_DEFAULT_PORT)))
36
+ return undefined;
37
+ // The bridge's own rule: it refuses a page only when it has served exactly ONE other project. A
38
+ // daemon serving nobody, several projects, or ours accepts this one. A project that has never
39
+ // been through init has no id yet, so a single named holder is somebody else.
40
+ const holders = await deps.daemonProjects(RETICLE_DEFAULT_PORT);
41
+ if (1 !== holders.length || holders[0] === projectId)
42
+ return undefined;
43
+ return deps.pickPort(RETICLE_DEFAULT_PORT + 1);
44
+ }
@@ -5,7 +5,7 @@
5
5
  * cli.ts is a dispatcher: a command that grew a second half should not make the file that routes
6
6
  * every command harder to read.
7
7
  */
8
- import type { InitResult } from '@reticlehq/init';
8
+ import { type InitResult } from '@reticlehq/init';
9
9
  /** Just enough of the parsed command to decide and run. */
10
10
  interface InitRuntimeArgs {
11
11
  readonly port: number | undefined;
@@ -7,18 +7,27 @@
7
7
  */
8
8
  import { existsSync, readFileSync, writeFileSync } from 'node:fs';
9
9
  import { RETICLE_DEFAULT_PORT } from '@reticlehq/core';
10
+ import { FEEDBACK_HINT, Framework } from '@reticlehq/init';
10
11
  import { confirmInstall, nodeConfirmDeps } from '../terminal/confirm.js';
11
12
  import { writeLicenseKey } from '../license-key.js';
12
13
  import { registerOtherAgents, runSetupCommand } from '../setup-command.js';
13
14
  import { bridgeOccupied } from '../bringup/bridge-port.js';
15
+ import { defaultPairingTokenDir, readOrCreatePairingTokenSync, } from '../../../portal/bridge/pairing-token.js';
14
16
  import { relaunchDecision } from '../bringup/relaunch.js';
15
17
  import { claudeTranscriptExists, codexSessionFor } from '../terminal/transcripts.js';
16
18
  import { probePresence } from '../../daemon/binding/port-presence.js';
17
19
  import { probeDaemon } from '../../../surface/mcp/proxy/proxy-daemon-probe.js';
18
20
  import { fetchStatus } from '../../daemon/binding/daemon-status-probe.js';
19
21
  import { collectEnv, DEFAULT_PHASE_TIMEOUT_MS } from '../setup-options.js';
22
+ import { staticPageDevCommand } from '../bringup/static-page-server.js';
20
23
  /** How often the runtime phases look again: fast enough not to be the wait, slow enough to be free. */
21
24
  const POLL_MS = 250;
25
+ /**
26
+ * The shapes whose served HTML carries the SDK marker: Vite injects it into index.html, and a plain
27
+ * HTML page has the snippet pasted in. Everything else connects from the JS bundle, where a fetch
28
+ * of the document can never see it. See `htmlCarriesSdk` in run-setup.ts.
29
+ */
30
+ const HTML_CARRIES_SDK = new Set([Framework.VITE, Framework.HTML]);
22
31
  /** Registration is global MCP wiring, so both flags that disown it are read here. */
23
32
  function wantsAgents(parsed) {
24
33
  return false !== parsed.agents && false !== parsed.mcp;
@@ -77,9 +86,16 @@ export async function continueAfterInit(parsed, result, io, cwd) {
77
86
  process.exit(1);
78
87
  });
79
88
  }
89
+ // From here on init left the ask to us, so it is the last thing on every exit below.
90
+ const ask = (spaced = true) => {
91
+ if (spaced)
92
+ io.print('');
93
+ io.print(FEEDBACK_HINT);
94
+ };
80
95
  const context = result.context;
81
96
  if (context === undefined) {
82
97
  // Nothing was established, so there is nothing to run against. init has already said why.
98
+ ask();
83
99
  process.exit(1);
84
100
  }
85
101
  // A PENDING connect step is not a reason to skip the runtime phase, and treating it as one made
@@ -100,12 +116,16 @@ export async function continueAfterInit(parsed, result, io, cwd) {
100
116
  const refusal = bridgeOccupied(await probePresence(port, { tcpOpen: probeDaemon, status: fetchStatus }), port);
101
117
  if (refusal !== undefined) {
102
118
  io.print(refusal);
119
+ ask();
103
120
  process.exit(1);
104
121
  }
105
122
  return runSetupCommand({
106
123
  appDir: context.appDir,
107
124
  invokedAt: cwd,
108
125
  bridgePort: port,
126
+ // Read here because this is the layer that already owns the bridge: setup opens a lease over
127
+ // the daemon's MCP transport for `--no-open`, and that transport is gated on this token.
128
+ pairingToken: readOrCreatePairingTokenSync(defaultPairingTokenDir()),
109
129
  env: collectEnv(parsed.env ?? []),
110
130
  openBrowser: false !== parsed.open,
111
131
  registerAgents: wantsAgents(parsed),
@@ -118,7 +138,19 @@ export async function continueAfterInit(parsed, result, io, cwd) {
118
138
  ? {}
119
139
  : { connectBudgetMs: parsed.timeoutSeconds * 1000 }),
120
140
  pollMs: POLL_MS,
121
- ...(undefined === context.devCommand ? {} : { devCommand: context.devCommand }),
141
+ htmlCarriesSdk: HTML_CARRIES_SDK.has(context.framework),
142
+ // A plain page with no dev script gets Reticle's own static server, so the page is actually
143
+ // served and the connect can be proved, instead of stopping at "start the app yourself".
144
+ ...(() => {
145
+ const devCommand = context.devCommand ??
146
+ (undefined === parsed.url
147
+ ? staticPageDevCommand({
148
+ appDir: context.appDir,
149
+ isStaticPage: Framework.HTML === context.framework,
150
+ })
151
+ : undefined);
152
+ return undefined === devCommand ? {} : { devCommand };
153
+ })(),
122
154
  ...(undefined === parsed.url ? {} : { suppliedUrl: parsed.url }),
123
155
  }, (line) => io.print(line)).then((outcome) => {
124
156
  // One object, so an agent reads a result instead of interpreting a report.
@@ -145,9 +177,12 @@ export async function continueAfterInit(parsed, result, io, cwd) {
145
177
  // Success, and no flow. Saying "a flow was driven" here would replace a wrong exit code with
146
178
  // a wrong sentence, which is the worse of the two: the exit code is read by CI and the
147
179
  // sentence is read by a person deciding whether their app is verified. It is not.
148
- io.print(`✓ ${outcome.url ?? 'the app'} is instrumented and connected — but NOT verified.`);
180
+ // The connect already said "connected, nothing verified yet" and listed what to do next;
181
+ // repeating it here was the same sentence twice, three lines apart.
149
182
  for (const [i, step] of outcome.fallback.entries())
150
183
  io.print(` ${String(i + 1)}. ${step}`);
184
+ // Already spaced by the blank line above when nothing was listed.
185
+ ask(0 < outcome.fallback.length);
151
186
  return;
152
187
  }
153
188
  if (outcome.ok) {
@@ -156,6 +191,7 @@ export async function continueAfterInit(parsed, result, io, cwd) {
156
191
  // themselves, and it deserves a line of its own rather than a paragraph that gets skimmed.
157
192
  io.print(' Read the FINDINGS above before moving on: a flow can pass with a failed request or a ' +
158
193
  'console error behind it, and that is the app, not the check.');
194
+ ask();
159
195
  return;
160
196
  }
161
197
  // A run that produced no verdict did not succeed, and the exit code is the one place a caller
@@ -163,6 +199,7 @@ export async function continueAfterInit(parsed, result, io, cwd) {
163
199
  io.print('⚠ setup did not finish. To carry on from here:');
164
200
  for (const [i, step] of outcome.fallback.entries())
165
201
  io.print(` ${i + 1}. ${step}`);
202
+ ask();
166
203
  process.exit(1);
167
204
  });
168
205
  }
@@ -15,31 +15,42 @@ import type { CandidateSession } from './session-pick.js';
15
15
  import type { PageProbe } from './probe/page-probe.js';
16
16
  /** The dev server this process started, and the only one it will ever stop. */
17
17
  export declare class OwnedDevServer {
18
+ private readonly logDir;
18
19
  private child;
19
- private buffer;
20
- private lastOutputAt;
20
+ private log;
21
+ private cwd;
22
+ private startedAt;
21
23
  private handedOver;
24
+ constructor(logDir?: string);
25
+ /**
26
+ * Start it with its output going to a bounded log, through a supervisor that outlives `init`.
27
+ *
28
+ * Not a pipe into THIS process. A pipe's read end belonged to `init`; once it exited nobody held
29
+ * it, and the server's next write (a compile error, an HMR line, SvelteKit's first warning) was an
30
+ * EPIPE that killed it: "it connected, then the app went away". And not a bare file either, which
31
+ * has no ceiling: an upstream echo loop grew one to 2.9 GB in five minutes. The supervisor reads
32
+ * the server's pipes for as long as they are open and rotates the file past a cap — see
33
+ * dev-server-log-cap.ts. It is the process group leader, so `pid()` and `stop()` cover both.
34
+ */
22
35
  start(command: string, cwd: string, env: Readonly<Record<string, string>>): void;
36
+ /** Where the server's output goes, for the line that hands it over. */
37
+ logPath(): string | undefined;
23
38
  /** The process group leader, for a caller that has to clean up what it handed over. */
24
39
  pid(): number | undefined;
25
40
  output(): string;
26
41
  exited(): boolean;
42
+ /** Since the log last grew, which is since the server last printed anything. */
27
43
  quietForMs(): number;
28
44
  /** Ports anything in this server's process tree is listening on. */
29
45
  listeningPorts(): number[];
30
- /** Hand the running server to the user. After this, `stop()` does nothing. */
31
46
  /**
32
- * Leave the server running and stop holding it.
33
- *
34
- * `unref` on the child is NOT enough: its stdout and stderr are pipes owned by this process, and
35
- * an open pipe keeps the event loop alive on its own. So `init` printed "setup complete" and then
36
- * hung until something killed it, turning a successful run into a non-zero exit — which is
37
- * exactly what the install gate reported, on a run whose every other assertion passed.
47
+ * Leave the server running and stop holding it. After this, `stop()` does nothing.
38
48
  *
39
- * The streams are unref'd rather than destroyed: the server is still writing to them, and
40
- * destroying the read end of a live pipe risks an EPIPE in somebody else's dev server.
49
+ * Only `unref` is needed: the output is the supervisor's, so no pipe of ours holds the event loop
50
+ * (`init` once printed "setup complete" and hung on one). `url` is recorded beside the log, so the
51
+ * next `init` attaches to this server rather than starting a second one beside it.
41
52
  */
42
- handOver(): void;
53
+ handOver(url?: string): void;
43
54
  stop(): void;
44
55
  }
45
56
  /**
@@ -50,9 +61,11 @@ export declare class OwnedDevServer {
50
61
  * server that is already running.
51
62
  *
52
63
  * On loopback, the announced host is tried first and the other loopback families follow when it
53
- * misses — so an IPv6-only Vite that printed `127.0.0.1` still counts as served (#884).
64
+ * is REFUSED — so an IPv6-only Vite that printed `127.0.0.1` still counts as served (#884). Only
65
+ * refused: a timeout means the right server is slow, and the caller polls again on the same host.
66
+ * See `isAddressMiss` for the Next 16 first run that hopping on a timeout broke.
54
67
  */
55
- export declare function probePage(url: string): Promise<PageProbe>;
68
+ export declare function probePage(url: string, timeoutMs?: number): Promise<PageProbe>;
56
69
  /** Sessions the daemon is holding, in the shape the picker reads. */
57
70
  export declare function listSessions(port: number): Promise<CandidateSession[]>;
58
71
  /** Whether this project has a saved flow, wherever the project keeps one. */