@reticlehq/server 3.6.0 → 3.7.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 (614) hide show
  1. package/SKILL.md +122 -123
  2. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  3. package/dist/command/cli/adhoc-suite.js +42 -7
  4. package/dist/command/cli/adhoc-verdict.d.ts +18 -2
  5. package/dist/command/cli/adhoc-verdict.js +70 -6
  6. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  7. package/dist/command/cli/answers/gate-exit.js +45 -0
  8. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  9. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  10. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  11. package/dist/command/cli/auth/device-flow.js +17 -0
  12. package/dist/command/cli/cli-doctor.js +14 -0
  13. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  14. package/dist/command/cli/cli-flow-commands.js +28 -105
  15. package/dist/command/cli/cli-kill.js +3 -2
  16. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  17. package/dist/command/cli/cli-parse-grammar.js +75 -0
  18. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  19. package/dist/command/cli/cli-parse-verify.js +18 -0
  20. package/dist/command/cli/cli-parse.d.ts +19 -28
  21. package/dist/command/cli/cli-parse.js +82 -182
  22. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  23. package/dist/command/cli/cli-update-commands.js +61 -9
  24. package/dist/command/cli/cli-usage.d.ts +33 -0
  25. package/dist/command/cli/cli-usage.js +287 -0
  26. package/dist/command/cli/cli-verify.d.ts +34 -4
  27. package/dist/command/cli/cli-verify.js +81 -12
  28. package/dist/command/cli/cloud-cli.d.ts +13 -0
  29. package/dist/command/cli/cloud-cli.js +145 -333
  30. package/dist/command/cli/cloud-kit.d.ts +12 -0
  31. package/dist/command/cli/cloud-kit.js +41 -2
  32. package/dist/command/cli/cloud-link.d.ts +57 -0
  33. package/dist/command/cli/cloud-link.js +308 -0
  34. package/dist/command/cli/cloud-login.d.ts +15 -1
  35. package/dist/command/cli/cloud-login.js +67 -13
  36. package/dist/command/cli/context-command.d.ts +1 -0
  37. package/dist/command/cli/context-command.js +33 -0
  38. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  39. package/dist/command/cli/daemon-start-options.js +24 -3
  40. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  41. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  42. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  43. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  44. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  45. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  46. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  47. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  48. package/dist/command/cli/known-regression.d.ts +13 -0
  49. package/dist/command/cli/known-regression.js +34 -0
  50. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  51. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  52. package/dist/command/cli/lifecycle/daemon-lifecycle.js +11 -2
  53. package/dist/command/cli/mcp-command.d.ts +6 -0
  54. package/dist/command/cli/mcp-command.js +13 -5
  55. package/dist/command/cli/ports/port-holder.js +1 -1
  56. package/dist/command/cli/project-name.d.ts +29 -1
  57. package/dist/command/cli/project-name.js +107 -2
  58. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  59. package/dist/command/cli/setup-mcp-cli.js +29 -8
  60. package/dist/command/cli/status/status-lines.d.ts +1 -0
  61. package/dist/command/cli/status/status-lines.js +47 -2
  62. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  63. package/dist/command/cli/status/workspace-links.js +29 -0
  64. package/dist/command/cli/try-command.d.ts +96 -0
  65. package/dist/command/cli/try-command.js +362 -0
  66. package/dist/command/cli/tutorial.d.ts +0 -100
  67. package/dist/command/cli/tutorial.js +0 -178
  68. package/dist/command/cli/verify-results.d.ts +19 -0
  69. package/dist/command/cli/verify-results.js +29 -0
  70. package/dist/command/cli-onboarding.d.ts +0 -11
  71. package/dist/command/cli-onboarding.js +0 -15
  72. package/dist/command/cli.d.ts +14 -0
  73. package/dist/command/cli.js +103 -83
  74. package/dist/command/daemon/daemon-resilience.js +4 -4
  75. package/dist/command/daemon/daemon-resolve.d.ts +9 -1
  76. package/dist/command/daemon/daemon-resolve.js +49 -10
  77. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  78. package/dist/command/setup/bringup/bridge-port.js +13 -3
  79. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  80. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  81. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  82. package/dist/command/setup/init/agent-restart.js +28 -0
  83. package/dist/command/setup/init/init-port.d.ts +10 -1
  84. package/dist/command/setup/init/init-port.js +22 -2
  85. package/dist/command/setup/init/init-runtime.d.ts +12 -2
  86. package/dist/command/setup/init/init-runtime.js +96 -37
  87. package/dist/command/setup/node-effects.d.ts +2 -0
  88. package/dist/command/setup/node-effects.js +36 -8
  89. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  90. package/dist/command/setup/probe/existing-app.js +14 -0
  91. package/dist/command/setup/remaining-steps.js +1 -1
  92. package/dist/command/setup/run-setup.d.ts +29 -9
  93. package/dist/command/setup/run-setup.js +34 -28
  94. package/dist/command/setup/setup-command.d.ts +23 -0
  95. package/dist/command/setup/setup-command.js +57 -4
  96. package/dist/command/setup/setup-mcp.js +25 -2
  97. package/dist/command/setup/tauri-signing.d.ts +19 -0
  98. package/dist/command/setup/tauri-signing.js +79 -0
  99. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  100. package/dist/command/setup/terminal/listeners.js +37 -6
  101. package/dist/command/update/update-nudge.d.ts +9 -0
  102. package/dist/command/update/update-nudge.js +1 -1
  103. package/dist/command/update/updater.js +11 -15
  104. package/dist/command/version/version-nudge.js +3 -0
  105. package/dist/command/version/version-skew.d.ts +20 -1
  106. package/dist/command/version/version-skew.js +38 -2
  107. package/dist/features/crawl/crawl.js +14 -1
  108. package/dist/features/exhaust/ledger.d.ts +14 -14
  109. package/dist/features/harness/drive-report.d.ts +39 -5
  110. package/dist/features/harness/drive-report.js +271 -54
  111. package/dist/features/harness/drive-runs.d.ts +120 -0
  112. package/dist/features/harness/drive-runs.js +289 -0
  113. package/dist/features/harness/drivers.d.ts +1 -1
  114. package/dist/features/harness/drivers.js +1 -1
  115. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  116. package/dist/features/harness/explore/console-pages.js +146 -0
  117. package/dist/features/harness/explore/disparity.d.ts +19 -0
  118. package/dist/features/harness/explore/disparity.js +71 -0
  119. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  120. package/dist/features/harness/explore/fake-app.js +49 -0
  121. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  122. package/dist/features/harness/explore/goal-search.js +144 -0
  123. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  124. package/dist/features/harness/explore/page-tree.js +148 -0
  125. package/dist/features/harness/explore/site-map.d.ts +34 -0
  126. package/dist/features/harness/explore/site-map.js +150 -0
  127. package/dist/features/harness/goals.d.ts +68 -7
  128. package/dist/features/harness/goals.js +289 -36
  129. package/dist/features/harness/harness.d.ts +30 -1
  130. package/dist/features/harness/harness.js +141 -7
  131. package/dist/features/harness/platform/local-apps.d.ts +36 -3
  132. package/dist/features/harness/platform/local-apps.js +81 -5
  133. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  134. package/dist/features/harness/platform/persona-credentials.js +69 -0
  135. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  136. package/dist/features/harness/platform/platform-drives.js +114 -0
  137. package/dist/features/harness/platform/refusal.d.ts +52 -0
  138. package/dist/features/harness/platform/refusal.js +71 -0
  139. package/dist/features/harness/platform/remote-drive.d.ts +8 -2
  140. package/dist/features/harness/platform/remote-drive.js +22 -9
  141. package/dist/features/harness/platform/script.d.ts +57 -11
  142. package/dist/features/harness/platform/script.js +144 -12
  143. package/dist/features/harness/platform/server-driver.d.ts +17 -4
  144. package/dist/features/harness/platform/server-driver.js +29 -26
  145. package/dist/features/harness/platform-config.d.ts +38 -5
  146. package/dist/features/harness/platform-config.js +93 -8
  147. package/dist/features/harness/route-guess.d.ts +13 -0
  148. package/dist/features/harness/route-guess.js +49 -0
  149. package/dist/features/harness/script/script-run.d.ts +30 -1
  150. package/dist/features/harness/script/script-run.js +355 -48
  151. package/dist/features/license/license.d.ts +2 -2
  152. package/dist/features/visual/step-shots.d.ts +31 -0
  153. package/dist/features/visual/step-shots.js +231 -0
  154. package/dist/features/visual/visual-tools.js +22 -14
  155. package/dist/hooks/client-directory.d.ts +18 -0
  156. package/dist/hooks/client-directory.js +57 -0
  157. package/dist/hooks/coding-agents.d.ts +34 -0
  158. package/dist/hooks/coding-agents.js +117 -0
  159. package/dist/hooks/driven-by.d.ts +21 -2
  160. package/dist/hooks/driven-by.js +42 -2
  161. package/dist/hooks/hook-bus.d.ts +4 -0
  162. package/dist/hooks/hook-bus.js +18 -0
  163. package/dist/index.d.ts +1 -0
  164. package/dist/index.js +26 -183
  165. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  166. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  167. package/dist/judgement/capsule/causal-summary.js +33 -0
  168. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  169. package/dist/judgement/runs/artifact/build-verification-run.js +20 -4
  170. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  171. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  172. package/dist/judgement/runs/artifact/replay-mapping.js +25 -9
  173. package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
  174. package/dist/judgement/runs/artifact/run-store.js +175 -8
  175. package/dist/judgement/runs/context-tools.js +59 -1
  176. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  177. package/dist/judgement/runs/default-run-id.js +16 -0
  178. package/dist/judgement/runs/drive-run.d.ts +53 -5
  179. package/dist/judgement/runs/drive-run.js +234 -20
  180. package/dist/judgement/runs/resume.d.ts +44 -0
  181. package/dist/judgement/runs/resume.js +137 -0
  182. package/dist/judgement/runs/reticle-runner.js +5 -2
  183. package/dist/judgement/runs/runner-port.d.ts +5 -1
  184. package/dist/judgement/runs/runner-port.js +8 -2
  185. package/dist/judgement/runs/verification-sync.d.ts +2 -0
  186. package/dist/judgement/runs/verification-sync.js +36 -15
  187. package/dist/language/flows/decision.js +2 -1
  188. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  189. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  190. package/dist/language/flows/flow-anchor.d.ts +7 -2
  191. package/dist/language/flows/flow-anchor.js +10 -3
  192. package/dist/language/flows/flow-intent.d.ts +1 -0
  193. package/dist/language/flows/flow-journey.d.ts +6 -0
  194. package/dist/language/flows/flow-journey.js +20 -0
  195. package/dist/language/flows/flow-learning.d.ts +4 -0
  196. package/dist/language/flows/flow-learning.js +37 -3
  197. package/dist/language/flows/flow-replay-run.js +16 -18
  198. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  199. package/dist/language/flows/flow-replay.d.ts +18 -1
  200. package/dist/language/flows/flow-replay.js +22 -7
  201. package/dist/language/flows/flow-result.d.ts +22 -1
  202. package/dist/language/flows/flow-result.js +47 -2
  203. package/dist/language/flows/flow-step-runners.d.ts +2 -0
  204. package/dist/language/flows/flow-step-runners.js +12 -6
  205. package/dist/language/flows/flow-store-for-session.js +5 -1
  206. package/dist/language/flows/flow-tools.d.ts +10 -0
  207. package/dist/language/flows/flow-tools.js +61 -62
  208. package/dist/language/flows/flows.d.ts +16 -1
  209. package/dist/language/flows/flows.js +69 -10
  210. package/dist/language/flows/narrow-write.d.ts +7 -0
  211. package/dist/language/flows/narrow-write.js +36 -1
  212. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  213. package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
  214. package/dist/language/flows/recording/tape/recordings.js +60 -10
  215. package/dist/language/flows/replay.js +29 -6
  216. package/dist/language/flows/single-replay.d.ts +7 -0
  217. package/dist/language/flows/single-replay.js +26 -0
  218. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  219. package/dist/language/flows/verify-change-tools.js +200 -193
  220. package/dist/memory/cloud/cloud-config.d.ts +10 -1
  221. package/dist/memory/cloud/cloud-config.js +19 -5
  222. package/dist/memory/cloud/cloud-sync.js +3 -3
  223. package/dist/memory/cloud/harness-config.d.ts +49 -0
  224. package/dist/memory/cloud/harness-config.js +16 -20
  225. package/dist/memory/cloud/memory-scope.d.ts +17 -0
  226. package/dist/memory/cloud/memory-scope.js +22 -0
  227. package/dist/memory/cloud/sync-cycle.d.ts +32 -4
  228. package/dist/memory/cloud/sync-cycle.js +113 -12
  229. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  230. package/dist/memory/cloud/sync-daemon.js +114 -4
  231. package/dist/memory/cloud/sync-disk.js +26 -2
  232. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  233. package/dist/memory/cloud/sync-screenshots.js +105 -0
  234. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  235. package/dist/memory/cloud/unsynced-roots.js +166 -0
  236. package/dist/memory/impact/account-watch.d.ts +16 -1
  237. package/dist/memory/impact/account-watch.js +26 -1
  238. package/dist/memory/impact/impact-store.d.ts +1 -4
  239. package/dist/memory/impact/impact-store.js +32 -42
  240. package/dist/memory/intent/inline-intent.d.ts +1 -0
  241. package/dist/memory/intent/intent-shard-store.js +16 -4
  242. package/dist/memory/intent/intent-shard.d.ts +12 -0
  243. package/dist/memory/intent/intent-store.d.ts +1 -0
  244. package/dist/memory/intent/intent-tools.js +42 -2
  245. package/dist/memory/intent/open-intents.d.ts +6 -0
  246. package/dist/memory/intent/open-intents.js +10 -1
  247. package/dist/memory/intent/settled-words.d.ts +24 -0
  248. package/dist/memory/intent/settled-words.js +130 -0
  249. package/dist/memory/journal/drive-flow.d.ts +16 -0
  250. package/dist/memory/journal/drive-flow.js +34 -2
  251. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  252. package/dist/memory/journal/drive-run-flush.js +20 -5
  253. package/dist/memory/journal/journal-recorder.js +46 -3
  254. package/dist/memory/journal/on-disk/retention.d.ts +5 -0
  255. package/dist/memory/journal/on-disk/retention.js +27 -2
  256. package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
  257. package/dist/memory/journal/session-end.d.ts +15 -1
  258. package/dist/memory/journal/session-end.js +38 -7
  259. package/dist/memory/project/artifact-root-resolver.js +33 -5
  260. package/dist/memory/project/artifact-root.d.ts +4 -3
  261. package/dist/memory/project/artifact-root.js +2 -2
  262. package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
  263. package/dist/memory/project/dir/reticle-dir.js +23 -2
  264. package/dist/memory/project/link-directory.d.ts +15 -0
  265. package/dist/memory/project/link-directory.js +44 -0
  266. package/dist/memory/project/root-claims.d.ts +6 -0
  267. package/dist/memory/project/root-claims.js +39 -0
  268. package/dist/memory/project/session-root.d.ts +2 -0
  269. package/dist/memory/project/session-root.js +9 -1
  270. package/dist/memory/project/sync-status.d.ts +46 -0
  271. package/dist/memory/project/sync-status.js +135 -1
  272. package/dist/memory/recall/memory-tools.js +46 -3
  273. package/dist/memory/recall/platform-memory.d.ts +34 -0
  274. package/dist/memory/recall/platform-memory.js +139 -0
  275. package/dist/memory/recall/project-memory.js +36 -8
  276. package/dist/portal/bridge/bridge.d.ts +9 -5
  277. package/dist/portal/bridge/bridge.js +66 -23
  278. package/dist/portal/bridge/harness-request.d.ts +23 -0
  279. package/dist/portal/bridge/harness-request.js +27 -0
  280. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  281. package/dist/portal/bridge/wrong-path.js +35 -0
  282. package/dist/portal/input/network-mock-tools.js +11 -2
  283. package/dist/portal/input/real-input.d.ts +2 -0
  284. package/dist/portal/input/real-input.js +13 -10
  285. package/dist/portal/pool/browser-pool.d.ts +48 -0
  286. package/dist/portal/pool/browser-pool.js +120 -2
  287. package/dist/portal/pool/context-permissions.d.ts +33 -0
  288. package/dist/portal/pool/context-permissions.js +33 -0
  289. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  290. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  291. package/dist/portal/pool/playwright-launcher.d.ts +27 -5
  292. package/dist/portal/pool/playwright-launcher.js +59 -14
  293. package/dist/portal/pool/pool-contract.d.ts +21 -1
  294. package/dist/portal/session/agent-link.d.ts +8 -0
  295. package/dist/portal/session/agent-link.js +17 -0
  296. package/dist/portal/session/command-payload.js +6 -1
  297. package/dist/portal/session/daemon-answers.d.ts +3 -3
  298. package/dist/portal/session/daemon-answers.js +4 -2
  299. package/dist/portal/session/dev-server/dev-command.d.ts +9 -0
  300. package/dist/portal/session/dev-server/dev-command.js +27 -1
  301. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  302. package/dist/portal/session/facts/observed-state.js +46 -3
  303. package/dist/portal/session/human/live-control.d.ts +9 -2
  304. package/dist/portal/session/human/live-control.js +12 -3
  305. package/dist/portal/session/live-control-tools.js +82 -13
  306. package/dist/portal/session/narration-args.d.ts +5 -0
  307. package/dist/portal/session/narration-args.js +17 -0
  308. package/dist/portal/session/no-session-diagnosis.d.ts +1 -1
  309. package/dist/portal/session/no-session-diagnosis.js +31 -9
  310. package/dist/portal/session/no-session-next-action.d.ts +20 -0
  311. package/dist/portal/session/no-session-next-action.js +134 -61
  312. package/dist/portal/session/no-session-watch.js +179 -22
  313. package/dist/portal/session/presence/session-lease.js +1 -1
  314. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  315. package/dist/portal/session/recorded-gaps.js +251 -0
  316. package/dist/portal/session/session-health.d.ts +11 -0
  317. package/dist/portal/session/session-health.js +3 -1
  318. package/dist/portal/session/session-info.js +2 -1
  319. package/dist/portal/session/session-manager.d.ts +18 -0
  320. package/dist/portal/session/session-manager.js +54 -3
  321. package/dist/portal/session/session-successor.d.ts +8 -0
  322. package/dist/portal/session/session-successor.js +1 -1
  323. package/dist/portal/session/session.d.ts +15 -28
  324. package/dist/portal/session/session.js +60 -61
  325. package/dist/portal/session/timing/command-timeout.js +25 -1
  326. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  327. package/dist/portal/session/timing/wall-clock.js +1 -1
  328. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  329. package/dist/portal/session/zero-install-first-call.js +88 -0
  330. package/dist/start-options.d.ts +7 -1
  331. package/dist/start-wiring.d.ts +63 -0
  332. package/dist/start-wiring.js +169 -0
  333. package/dist/status-payload.d.ts +13 -1
  334. package/dist/status-payload.js +13 -1
  335. package/dist/surface/http-server.js +7 -1
  336. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  337. package/dist/surface/mcp/attach-memory.js +12 -1
  338. package/dist/surface/mcp/mcp-proxy.d.ts +4 -0
  339. package/dist/surface/mcp/mcp-proxy.js +29 -8
  340. package/dist/surface/mcp/mcp.d.ts +23 -0
  341. package/dist/surface/mcp/mcp.js +34 -4
  342. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  343. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  344. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  345. package/dist/surface/mcp/server-instructions.js +22 -14
  346. package/dist/surface/mcp/shared-params.js +1 -1
  347. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  348. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  349. package/dist/surface/tools/account-tool.d.ts +22 -0
  350. package/dist/surface/tools/account-tool.js +157 -0
  351. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  352. package/dist/surface/tools/act/act-danger.js +38 -1
  353. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  354. package/dist/surface/tools/act/act-observation.js +57 -0
  355. package/dist/surface/tools/act/act-preflight.js +25 -2
  356. package/dist/surface/tools/act/act-target.js +8 -3
  357. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  358. package/dist/surface/tools/act/resolve-target.js +18 -3
  359. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  360. package/dist/surface/tools/act/screen-request.js +113 -0
  361. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  362. package/dist/surface/tools/act/sequence-grade.js +13 -2
  363. package/dist/surface/tools/act-sequence-tool.js +136 -27
  364. package/dist/surface/tools/act-tools.d.ts +0 -9
  365. package/dist/surface/tools/act-tools.js +48 -34
  366. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  367. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  368. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  369. package/dist/surface/tools/agent/app-notes.js +48 -0
  370. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  371. package/dist/surface/tools/agent/build-staleness.js +62 -0
  372. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  373. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  374. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  375. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  376. package/dist/surface/tools/agent/notices.d.ts +50 -0
  377. package/dist/surface/tools/agent/notices.js +152 -0
  378. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  379. package/dist/surface/tools/agent/reteach.js +50 -0
  380. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  381. package/dist/surface/tools/args/alias-args.js +10 -0
  382. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  383. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  384. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  385. package/dist/surface/tools/assert/assert-source.js +40 -0
  386. package/dist/surface/tools/assert/assert-verdict.js +25 -15
  387. package/dist/surface/tools/browser-tools.js +43 -1
  388. package/dist/surface/tools/chat-drives.d.ts +75 -0
  389. package/dist/surface/tools/chat-drives.js +265 -21
  390. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  391. package/dist/surface/tools/coverage-tools.js +2 -53
  392. package/dist/surface/tools/dynamic-tools.js +29 -1
  393. package/dist/surface/tools/empty-session-list.d.ts +10 -0
  394. package/dist/surface/tools/empty-session-list.js +45 -5
  395. package/dist/surface/tools/error-recovery.d.ts +8 -0
  396. package/dist/surface/tools/error-recovery.js +69 -5
  397. package/dist/surface/tools/explore-tools.d.ts +23 -2
  398. package/dist/surface/tools/explore-tools.js +377 -74
  399. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  400. package/dist/surface/tools/feedback-tools.js +4 -3
  401. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  402. package/dist/surface/tools/gap-novelty.js +8 -1
  403. package/dist/surface/tools/harness-explore.d.ts +52 -73
  404. package/dist/surface/tools/harness-explore.js +177 -146
  405. package/dist/surface/tools/harness-gate.d.ts +88 -0
  406. package/dist/surface/tools/harness-gate.js +235 -0
  407. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  408. package/dist/surface/tools/harness-hunt.js +215 -0
  409. package/dist/surface/tools/harness-plan.d.ts +5 -0
  410. package/dist/surface/tools/harness-plan.js +7 -0
  411. package/dist/surface/tools/harness-script.d.ts +22 -0
  412. package/dist/surface/tools/harness-script.js +256 -38
  413. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  414. package/dist/surface/tools/harness-tab-guard.js +27 -0
  415. package/dist/surface/tools/harness-toolset.d.ts +8 -0
  416. package/dist/surface/tools/harness-toolset.js +27 -4
  417. package/dist/surface/tools/human-notes.d.ts +16 -0
  418. package/dist/surface/tools/human-notes.js +27 -0
  419. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  420. package/dist/surface/tools/invoke-tool.js +220 -93
  421. package/dist/surface/tools/lease-hint.js +26 -5
  422. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  423. package/dist/surface/tools/lease-permissions.js +73 -0
  424. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  425. package/dist/surface/tools/lease-readiness.js +57 -0
  426. package/dist/surface/tools/lease-seed.d.ts +20 -0
  427. package/dist/surface/tools/lease-seed.js +45 -1
  428. package/dist/surface/tools/lease-tools.d.ts +10 -1
  429. package/dist/surface/tools/lease-tools.js +119 -69
  430. package/dist/surface/tools/live-call-text.js +2 -2
  431. package/dist/surface/tools/merge-tools.js +42 -2
  432. package/dist/surface/tools/merged-name-redirect.js +4 -0
  433. package/dist/surface/tools/next-step.d.ts +11 -1
  434. package/dist/surface/tools/next-step.js +73 -18
  435. package/dist/surface/tools/observe-tools.js +43 -5
  436. package/dist/surface/tools/platform-moment.d.ts +60 -0
  437. package/dist/surface/tools/platform-moment.js +132 -4
  438. package/dist/surface/tools/read-tools.js +65 -14
  439. package/dist/surface/tools/reticle-result.d.ts +120 -0
  440. package/dist/surface/tools/reticle-result.js +364 -0
  441. package/dist/surface/tools/tool-kit.d.ts +68 -2
  442. package/dist/surface/tools/tool-kit.js +73 -1
  443. package/dist/surface/tools/tools.js +25 -13
  444. package/dist/telemetry/account-envelope.d.ts +7 -0
  445. package/dist/telemetry/account-envelope.js +61 -0
  446. package/dist/telemetry/agent-client.d.ts +15 -0
  447. package/dist/telemetry/agent-client.js +57 -0
  448. package/dist/telemetry/app-instrumented.js +9 -2
  449. package/dist/telemetry/argument-shape.d.ts +7 -0
  450. package/dist/telemetry/argument-shape.js +86 -1
  451. package/dist/telemetry/automation-hint.d.ts +2 -3
  452. package/dist/telemetry/automation-hint.js +33 -8
  453. package/dist/telemetry/cli-telemetry.js +7 -2
  454. package/dist/telemetry/daemon-telemetry.js +3 -0
  455. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  456. package/dist/telemetry/error-fingerprint.js +61 -5
  457. package/dist/telemetry/feedback-cli.d.ts +0 -13
  458. package/dist/telemetry/feedback-cli.js +0 -77
  459. package/dist/telemetry/feedback.d.ts +13 -0
  460. package/dist/telemetry/feedback.js +183 -17
  461. package/dist/telemetry/harness-run.d.ts +18 -0
  462. package/dist/telemetry/harness-run.js +80 -0
  463. package/dist/telemetry/hud-events.d.ts +16 -0
  464. package/dist/telemetry/hud-events.js +27 -0
  465. package/dist/telemetry/hud-metrics.d.ts +27 -6
  466. package/dist/telemetry/hud-metrics.js +99 -25
  467. package/dist/telemetry/init-telemetry.js +2 -2
  468. package/dist/telemetry/install-source.d.ts +13 -25
  469. package/dist/telemetry/install-source.js +44 -3
  470. package/dist/telemetry/mcp-connection.d.ts +0 -14
  471. package/dist/telemetry/mcp-connection.js +5 -1
  472. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  473. package/dist/telemetry/onboarding-firsts.js +81 -6
  474. package/dist/telemetry/platform-linked.d.ts +5 -0
  475. package/dist/telemetry/platform-linked.js +32 -0
  476. package/dist/telemetry/project-profile.js +5 -3
  477. package/dist/telemetry/proxy-telemetry.js +4 -1
  478. package/dist/telemetry/session-metrics.d.ts +15 -4
  479. package/dist/telemetry/session-metrics.js +88 -52
  480. package/dist/telemetry/telemetry.d.ts +26 -2
  481. package/dist/telemetry/telemetry.js +102 -21
  482. package/dist/telemetry/verification-of.d.ts +3 -1
  483. package/dist/telemetry/verification-of.js +12 -4
  484. package/dist/wire-journal.d.ts +2 -2
  485. package/dist/wire-journal.js +16 -5
  486. package/docs/README.md +2 -2
  487. package/docs/actions.mdx +6 -3
  488. package/docs/adapters.md +1 -1
  489. package/docs/agent-cheatsheet.md +24 -27
  490. package/docs/architecture.md +5 -5
  491. package/docs/autodrive.md +13 -12
  492. package/docs/benchmarks.md +5 -5
  493. package/docs/best-practices.mdx +27 -9
  494. package/docs/capabilities.mdx +14 -16
  495. package/docs/cli/affected.mdx +1 -1
  496. package/docs/cli/cloud.mdx +54 -75
  497. package/docs/cli/doctor.mdx +8 -3
  498. package/docs/cli/drive.mdx +12 -12
  499. package/docs/cli/feedback.mdx +3 -3
  500. package/docs/cli/gate.mdx +7 -2
  501. package/docs/cli/help.mdx +50 -55
  502. package/docs/cli/init.mdx +32 -15
  503. package/docs/cli/license.mdx +12 -8
  504. package/docs/cli/mcp.mdx +4 -4
  505. package/docs/cli/open.mdx +3 -3
  506. package/docs/cli/report.mdx +4 -2
  507. package/docs/cli/restart.mdx +2 -2
  508. package/docs/cli/rollback.mdx +14 -8
  509. package/docs/cli/serve.mdx +4 -4
  510. package/docs/cli/setup.mdx +23 -0
  511. package/docs/cli/status.mdx +13 -4
  512. package/docs/cli/stop.mdx +67 -8
  513. package/docs/cli/try.mdx +62 -0
  514. package/docs/cli/update.mdx +4 -3
  515. package/docs/cli/verify.mdx +17 -6
  516. package/docs/cli/version.mdx +3 -2
  517. package/docs/cli.mdx +110 -41
  518. package/docs/debugging.md +3 -3
  519. package/docs/deploy-checks.md +1 -1
  520. package/docs/desktop.mdx +5 -3
  521. package/docs/enterprise.md +11 -10
  522. package/docs/environment.mdx +5 -2
  523. package/docs/faq.mdx +3 -3
  524. package/docs/first-drive.md +5 -4
  525. package/docs/flows.md +35 -27
  526. package/docs/for-agents.md +4 -5
  527. package/docs/frameworks.mdx +32 -21
  528. package/docs/getting-started.md +66 -64
  529. package/docs/human-control.md +15 -14
  530. package/docs/index.mdx +15 -43
  531. package/docs/install-agentic.mdx +22 -37
  532. package/docs/install-manual.mdx +22 -12
  533. package/docs/instrumentation.mdx +5 -3
  534. package/docs/integration-patterns.md +7 -7
  535. package/docs/license-activation.mdx +1 -1
  536. package/docs/multi-agent-testing.md +24 -6
  537. package/docs/packages/babel-plugin.mdx +4 -2
  538. package/docs/packages/browser.mdx +16 -10
  539. package/docs/packages/core.mdx +12 -5
  540. package/docs/packages/electron.mdx +3 -2
  541. package/docs/packages/engine.mdx +1 -1
  542. package/docs/packages/eslint-plugin.mdx +18 -12
  543. package/docs/packages/next.mdx +8 -7
  544. package/docs/packages/open-verification.mdx +1 -1
  545. package/docs/packages/server.mdx +5 -5
  546. package/docs/packages/tauri.mdx +8 -8
  547. package/docs/packages/test.mdx +4 -10
  548. package/docs/packages/vite-plugin.mdx +11 -4
  549. package/docs/packages.mdx +11 -15
  550. package/docs/platform-integration.md +6 -5
  551. package/docs/predicates.mdx +40 -24
  552. package/docs/quickstart.mdx +58 -29
  553. package/docs/required-checks.md +8 -7
  554. package/docs/reticle-manual.md +15 -5
  555. package/docs/skill-file.mdx +17 -79
  556. package/docs/skill-setup.md +9 -9
  557. package/docs/skill.md +200 -0
  558. package/docs/system-map.md +7 -7
  559. package/docs/telemetry.md +22 -24
  560. package/docs/testing.md +4 -4
  561. package/docs/token-efficiency.md +12 -12
  562. package/docs/tools/act-and-wait.mdx +9 -2
  563. package/docs/tools/act-sequence.mdx +6 -7
  564. package/docs/tools/act.mdx +2 -2
  565. package/docs/tools/assert.mdx +18 -17
  566. package/docs/tools/console.mdx +9 -9
  567. package/docs/tools/inspect.mdx +16 -7
  568. package/docs/tools/look.mdx +24 -0
  569. package/docs/tools/navigate.mdx +5 -3
  570. package/docs/tools/network.mdx +2 -2
  571. package/docs/tools/observe.mdx +6 -6
  572. package/docs/tools/overview.mdx +34 -33
  573. package/docs/tools/query.mdx +5 -5
  574. package/docs/tools/session-and-feedback.mdx +13 -4
  575. package/docs/tools/sessions.mdx +8 -8
  576. package/docs/tools/snapshot.mdx +6 -5
  577. package/docs/tools/state.mdx +9 -9
  578. package/docs/tools/tools-and-run.mdx +26 -24
  579. package/docs/tools/verify.mdx +28 -0
  580. package/docs/tools/wait-for.mdx +8 -4
  581. package/docs/troubleshooting.mdx +21 -6
  582. package/docs/usage.md +51 -45
  583. package/docs/use-cases.mdx +3 -3
  584. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  585. package/docs/vs-playwright-mcp.mdx +3 -1
  586. package/docs/what-is-recorded.md +7 -5
  587. package/docs/what-is-reticle.mdx +2 -2
  588. package/docs/why-reticle.mdx +1 -1
  589. package/package.json +6 -5
  590. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  591. package/dist/command/cli/demo/demo-page.js +0 -249
  592. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  593. package/dist/command/cli/demo/demo-run.js +0 -138
  594. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  595. package/dist/judgement/hunt/hunt-report.js +0 -84
  596. package/dist/language/flows/buddy-status.d.ts +0 -25
  597. package/dist/language/flows/buddy-status.js +0 -32
  598. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  599. package/dist/language/flows/change/watch-batcher.js +0 -19
  600. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  601. package/dist/memory/cloud/harness-offer.js +0 -145
  602. package/dist/surface/tools/feature-capture.d.ts +0 -151
  603. package/dist/surface/tools/feature-capture.js +0 -235
  604. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  605. package/dist/surface/tools/tool-hit-rate.js +0 -90
  606. package/dist/telemetry/harness-drive.d.ts +0 -4
  607. package/dist/telemetry/harness-drive.js +0 -35
  608. package/dist/telemetry/identify.d.ts +0 -22
  609. package/dist/telemetry/identify.js +0 -73
  610. package/docs/cli/capsules.mdx +0 -70
  611. package/docs/cli/hunt.mdx +0 -73
  612. package/docs/cli/identify.mdx +0 -76
  613. package/docs/cli/kill.mdx +0 -91
  614. package/docs/cli/watch.mdx +0 -62
@@ -0,0 +1,29 @@
1
+ /**
2
+ * `reticle verify --results-json <file>`: the run, one line per journey, for a machine to read.
3
+ *
4
+ * The rendered report is for a person, and a CI step that has to post per-journey verdicts somewhere
5
+ * else would otherwise scrape it. Three words only, the engine's own: a skipped flow is `unknown`,
6
+ * never rounded up to `yes`, and the run is `yes` only when every journey is.
7
+ */
8
+ import { RunFlowStatus, VerdictStatus, Verified, } from '@reticlehq/core';
9
+ function journeyVerdict(status) {
10
+ if (RunFlowStatus.FAIL === status)
11
+ return Verified.NO;
12
+ // A heal is consequence-verified before it is reported, so it proves as much as a pass.
13
+ if (RunFlowStatus.PASS === status || RunFlowStatus.HEALED === status)
14
+ return Verified.YES;
15
+ return Verified.UNKNOWN;
16
+ }
17
+ export function verifyResults(run) {
18
+ const results = run.flows.map((flow) => ({
19
+ journey: flow.name,
20
+ verdict: journeyVerdict(flow.status),
21
+ ...(flow.failureReason === undefined ? {} : { reason: flow.failureReason }),
22
+ }));
23
+ const verdict = results.some((r) => Verified.NO === r.verdict)
24
+ ? Verified.NO
25
+ : VerdictStatus.PASS === run.verdict.status && results.every((r) => Verified.YES === r.verdict)
26
+ ? Verified.YES
27
+ : Verified.UNKNOWN;
28
+ return { verdict, results };
29
+ }
@@ -8,14 +8,3 @@ import type { OnboardingStep } from '@reticlehq/core/telemetry';
8
8
  * reporter is built here and handed down to every command that needs one.
9
9
  */
10
10
  export declare const reportStepFromCli: (step: OnboardingStep) => void;
11
- /**
12
- * The two ONBOARD steps `reticle tutorial` can honestly answer.
13
- *
14
- * Asking for the tour is a fact here, and so is having been shown what Reticle is. Whether the
15
- * reader then looked, acted or proved is not — even on `tutorial --run`, which drives the demo: those
16
- * three are reported by the daemon at the first look / act / verdict it actually witnesses, through
17
- * the dispatch chokepoint, because that is the only place they are observations rather than claims.
18
- * Reporting them from here would turn "the tour reached step four" into "somebody verified something",
19
- * which is the same substitution the fourth step of the tour exists to warn about.
20
- */
21
- export declare function reportTutorialShown(): void;
@@ -1,5 +1,4 @@
1
1
  import { reportOnboardingStep } from '../telemetry/onboarding-funnel.js';
2
- import { tutorialShownSteps } from './cli/tutorial.js';
3
2
  /**
4
3
  * The CLI's half of the setup funnel.
5
4
  *
@@ -11,17 +10,3 @@ import { tutorialShownSteps } from './cli/tutorial.js';
11
10
  export const reportStepFromCli = (step) => {
12
11
  void reportOnboardingStep(step);
13
12
  };
14
- /**
15
- * The two ONBOARD steps `reticle tutorial` can honestly answer.
16
- *
17
- * Asking for the tour is a fact here, and so is having been shown what Reticle is. Whether the
18
- * reader then looked, acted or proved is not — even on `tutorial --run`, which drives the demo: those
19
- * three are reported by the daemon at the first look / act / verdict it actually witnesses, through
20
- * the dispatch chokepoint, because that is the only place they are observations rather than claims.
21
- * Reporting them from here would turn "the tour reached step four" into "somebody verified something",
22
- * which is the same substitution the fourth step of the tour exists to warn about.
23
- */
24
- export function reportTutorialShown() {
25
- for (const step of tutorialShownSteps())
26
- reportStepFromCli(step);
27
- }
@@ -2,6 +2,20 @@
2
2
  import { parseCliArgs, CLI_USAGE } from './cli/cli-parse.js';
3
3
  export { parseCliArgs, CLI_USAGE };
4
4
  export type { CliResult } from './cli/cli-parse.js';
5
+ /**
6
+ * Said last, when the account is linked and the one thing left is installing a dependency. Exit 0:
7
+ * connect's job — signing in and linking — is done, and a non-zero exit read as a failed connect.
8
+ */
9
+ export declare const MSG_CONNECTED_DEPS_PENDING: string;
10
+ /**
11
+ * How `reticle connect` exits: the cloud step's code when linking failed; 0 when it linked and setup
12
+ * finished or left only the dependency install (said in `note`); 1 when setup stopped for anything
13
+ * else. `initUnfinished` is why init's setup did not finish, or undefined when it did.
14
+ */
15
+ export declare function connectExit(cloudCode: number, initUnfinished: string | undefined): {
16
+ code: number;
17
+ note?: string;
18
+ };
5
19
  /**
6
20
  * Report status to the terminal. `--json` writes one structured line to STDOUT so it can be piped
7
21
  * into `jq`; the human-readable block goes to stdout too. `log()` stays on stderr (the MCP
@@ -1,9 +1,8 @@
1
1
  #!/usr/bin/env node
2
+ import { PlatformLinkVia } from '@reticlehq/core/telemetry';
2
3
  import { hudSignIn } from './cli/cloud-login.js';
3
4
  import { handleSetupMcp, handleSetupInstall } from './cli/setup-mcp-cli.js';
4
- import { reportStepFromCli, reportTutorialShown } from './cli-onboarding.js';
5
- import { runDemoTour } from './cli/demo/demo-run.js';
6
- import { renderTutorial } from './cli/tutorial.js';
5
+ import { reportStepFromCli } from './cli-onboarding.js';
7
6
  import { pathToFileURL } from 'node:url';
8
7
  import { openFailureNote, openLaunchFailureNote } from './cli/answers/open-note.js';
9
8
  import { realpathSync } from 'node:fs';
@@ -16,21 +15,24 @@ import { splitBrainFields, withNextAction } from './cli/status-fields.js';
16
15
  import { reticleStateHome } from './daemon/daemon.js';
17
16
  import { handleMcp } from './cli/mcp-command.js';
18
17
  import { handleReport } from './cli/report-command.js';
18
+ import { handleContext } from './cli/context-command.js';
19
19
  import { daemonProjectAt, readDaemonRegistry, resolveDaemonForProject, } from './daemon/daemon-resolve.js';
20
20
  import { pickDaemonPortToBind } from './daemon/binding/free-port.js';
21
21
  import { isSameOrAbove, portForInit, portFromEnv } from './setup/init/init-port.js';
22
22
  import { daemonStartOptions } from './cli/daemon-start-options.js';
23
- import { handleWatch, handleCapsules, handleGate, loadNamedFlows, resolveChangedFiles, } from './cli/cli-flow-commands.js';
23
+ import { handleGate, loadNamedFlows, resolveChangedFiles } from './cli/cli-flow-commands.js';
24
24
  import { RETICLE_DEFAULT_PORT, ReticleDir, ReticleEnv, devServersForProject, } from '@reticlehq/core';
25
25
  import { loadDotEnv } from '../telemetry/dev-repo.js';
26
26
  import { licenseKeyFromEnvFiles } from '../features/license/license-env.js';
27
27
  import { LICENSE_KEY_ENV } from '../features/license/license.js';
28
28
  import { createNodeFileSystem } from '../memory/project/fs/fs-port.js';
29
+ import { localLinkOf, workspaceAppLinks } from './cli/status/workspace-links.js';
29
30
  import { affectedSavedFlows } from '../language/flows/change/flow-sources.js';
30
31
  import { availableUpdate } from './update/update-nudge.js';
31
32
  import { handleUpdate, handleRollback } from './cli/cli-update-commands.js';
33
+ import { headlessByDefault } from './cli/daemon-start-options.js';
32
34
  import { startDaemon } from '../index.js';
33
- import { isCloudCommand, runCloudCommand } from './cli/cloud-cli.js';
35
+ import { accountStatusFields, cmdLink, connectInstalls, isCloudCommand, runCloudCommand, } from './cli/cloud-cli.js';
34
36
  import { SERVER_VERSION } from './version/identity/server-version.js';
35
37
  import { log } from '../log.js';
36
38
  import { readPid, isAlive, removePid, spawnDaemon, discoverDaemonPort, writeDaemonRegistry, } from './daemon/daemon.js';
@@ -46,20 +48,46 @@ import { fetchStatus } from './daemon/binding/daemon-status-probe.js';
46
48
  import { handleDrive } from './cli/drive/drive-command.js';
47
49
  import { handleVerify } from './cli/cli-verify.js';
48
50
  import { runKill } from './cli/cli-kill.js';
49
- import { summarizeHunt } from '../judgement/hunt/hunt-report.js';
50
- import { runInit, buildNodeIo } from '@reticlehq/init';
51
+ import { runInit, buildNodeIo, InitFailure } from '@reticlehq/init';
51
52
  import { continueAfterInit } from './setup/init/init-runtime.js';
53
+ import { initFirstFlow } from './cli/try-command.js';
52
54
  import { handleDoctor } from './cli/cli-doctor.js';
53
55
  import { serverInitHost } from './setup/init/init-host.js';
54
56
  import { describeLicense } from '../features/license/license.js';
55
57
  import { isLikelyDevServerPort, devServerPortWarning, readProjectPort, readProjectId, workspacePortConflict, projectDirOf, } from './cli/ports/resolve/cli-port.js';
56
- import { nodeSpawner, readTextFile, reexecAtVersion, versionMatchNote, versionToMatch, } from './cli/launch/sdk-version-match.js';
58
+ import { helpRunsAt, helpVersionNote, nodeSpawner, readTextFile, reexecAtVersion, versionMatchNote, versionToMatch, } from './cli/launch/sdk-version-match.js';
57
59
  import { DAEMON_INNER_COMMAND, PORT_FLAG, parseCliArgs, CLI_USAGE, dialsTheDaemon, } from './cli/cli-parse.js';
58
- import { handleFeedback, handleIdentify, handleTelemetry } from '../telemetry/feedback-cli.js';
60
+ import { renderHelp } from './cli/cli-usage.js';
61
+ import { RENAMED_COMMANDS, renamedCommandFor, renamedNote } from './cli/cli-parse-grammar.js';
62
+ import { handleFeedback, handleTelemetry } from '../telemetry/feedback-cli.js';
59
63
  import { installDaemonTelemetry } from '../telemetry/daemon-telemetry.js';
60
64
  import { reportCliRun } from '../telemetry/cli-telemetry.js';
61
65
  // Re-exported so existing imports (and the CLI tests) keep resolving from '@/cli.js'.
62
66
  export { parseCliArgs, CLI_USAGE };
67
+ /** Said when `connect` carries on past an init whose setup did not finish. */
68
+ const MSG_CONNECT_AFTER_UNFINISHED_INIT = 'Setup did not finish (above) — signing in and linking anyway. Fix what it names, then run ' +
69
+ '`reticle init` again.';
70
+ /**
71
+ * Said last, when the account is linked and the one thing left is installing a dependency. Exit 0:
72
+ * connect's job — signing in and linking — is done, and a non-zero exit read as a failed connect.
73
+ */
74
+ export const MSG_CONNECTED_DEPS_PENDING = '⚠ Connected, but the dependency install did not finish (see above). Run the install it names, ' +
75
+ 'then `reticle init` to wire the app.';
76
+ /**
77
+ * How `reticle connect` exits: the cloud step's code when linking failed; 0 when it linked and setup
78
+ * finished or left only the dependency install (said in `note`); 1 when setup stopped for anything
79
+ * else. `initUnfinished` is why init's setup did not finish, or undefined when it did.
80
+ */
81
+ export function connectExit(cloudCode, initUnfinished) {
82
+ if (0 !== cloudCode)
83
+ return { code: cloudCode };
84
+ if (initUnfinished === undefined)
85
+ return { code: 0 };
86
+ if (InitFailure.DEPENDENCY_INSTALL === initUnfinished) {
87
+ return { code: 0, note: MSG_CONNECTED_DEPS_PENDING };
88
+ }
89
+ return { code: 1 };
90
+ }
63
91
  async function handleInit(parsed) {
64
92
  const cwd = process.cwd();
65
93
  // RETICLE_PORT counts as explicit, as it does for every other command: resolved once here, so the
@@ -83,7 +111,7 @@ async function handleInit(parsed) {
83
111
  const started = readDaemonRegistry(reticleStateHome()).find((e) => e.port === p)?.cwd;
84
112
  return started !== undefined && isSameOrAbove(started, cwd);
85
113
  },
86
- });
114
+ }, cwd);
87
115
  const io = buildNodeIo(cwd, serverInitHost(), { stderr: true === parsed.json });
88
116
  const result = runInit({
89
117
  cwd,
@@ -102,7 +130,8 @@ async function handleInit(parsed) {
102
130
  deferOutcome: true,
103
131
  continuesToRuntime: true !== parsed.filesOnly && true !== parsed.dryRun,
104
132
  }, io);
105
- await continueAfterInit({ ...parsed, port }, result, io, cwd);
133
+ await continueAfterInit({ ...parsed, port }, result, io, cwd, initFirstFlow);
134
+ return result;
106
135
  }
107
136
  // `serve`, `stop` and `restart` live in `cli/lifecycle/daemon-lifecycle.ts`: one idea, and the
108
137
  // largest group this file could give up without splitting something that belongs together.
@@ -126,7 +155,15 @@ export function reportStatus(fields, json) {
126
155
  process.stdout.write(`${statusLines(fields).join('\n')}\n`);
127
156
  }
128
157
  export async function handleStatus(port, json = false) {
129
- const report = (fields) => reportStatus(fields, json);
158
+ // A broken session file must not cost the reader the rest of the status.
159
+ const account = await accountStatusFields().catch(() => ({}));
160
+ // At a workspace root that is no app of its own, each app and its link: "not linked" named none.
161
+ const linked = account.linkedProject;
162
+ if ('string' !== typeof linked && readProjectId(process.cwd()) === undefined)
163
+ Object.assign(account, {
164
+ workspaceApps: await workspaceAppLinks(process.cwd(), localLinkOf).catch(() => []),
165
+ });
166
+ const report = (fields) => reportStatus({ ...fields, ...account }, json);
130
167
  const pid = readPid(port);
131
168
  // Durable, so it survives the daemon idling out — which is the state `status` is most often run in.
132
169
  const projectId = readProjectId(process.cwd());
@@ -269,42 +306,6 @@ async function handleAffected(files, since) {
269
306
  });
270
307
  }
271
308
  }
272
- /**
273
- * `reticle hunt <dir>` — aggregate crawl reports from many checkouts into one number.
274
- *
275
- * Detection already exists (`reticle_crawl`). This is the arithmetic that turns a pile of runs into
276
- * the claim worth making: over N already-merged, already-green changes, how many carried a candidate
277
- * false green? No control arm is needed, because those changes SHIPPED — the counterfactual is
278
- * already established, which is what makes this the cheapest credible evidence available.
279
- *
280
- * Each file in <dir> is one crawl result. Producing them is a shell loop over a commit range:
281
- * check out, boot the app, `reticle_crawl`, write the JSON here.
282
- */
283
- async function handleHunt(dir) {
284
- try {
285
- const fs = createNodeFileSystem();
286
- const names = await fs.readdir(dir);
287
- const runs = [];
288
- for (const name of names.filter((n) => n.endsWith('.json'))) {
289
- const raw = await fs.readFile(join(dir, name));
290
- if (raw === undefined)
291
- continue;
292
- const parsed = JSON.parse(raw);
293
- const report = parsed;
294
- runs.push({
295
- label: report.label ?? name.replace(/\.json$/, ''),
296
- anomalies: report.anomalies ?? [],
297
- ...(report.stepsRun === undefined ? {} : { stepsRun: report.stepsRun }),
298
- });
299
- }
300
- log('reticle_hunt', { ...summarizeHunt(runs) });
301
- }
302
- catch (error) {
303
- log('reticle_hunt_failed', {
304
- error: error instanceof Error ? error.message : String(error),
305
- });
306
- }
307
- }
308
309
  /** Ensure a daemon is reachable on `port` (probe the real port; spawn + wait only if nothing's there). */
309
310
  function ensureDaemon(port) {
310
311
  return probePresence(port, { tcpOpen: probeDaemon, status: fetchStatus }).then(async (presence) => {
@@ -437,7 +438,11 @@ function handleOpen(requestedPort, url) {
437
438
  }
438
439
  function handleDaemonInner(parsed) {
439
440
  // The daemon the CLI starts is the one that can sign in for the panel: it owns ~/.reticle.
440
- const options = { ...daemonStartOptions(parsed), hudSignIn };
441
+ const options = {
442
+ ...daemonStartOptions(parsed),
443
+ hudSignIn: (repaint, link) => hudSignIn(repaint, undefined, undefined, link),
444
+ hudLink: (root) => cmdLink([], root, PlatformLinkVia.HUD),
445
+ };
441
446
  startDaemon(options)
442
447
  .then((server) => {
443
448
  log('reticle_daemon_ready', { port: parsed.port, pid: process.pid });
@@ -555,13 +560,15 @@ export function main() {
555
560
  // `version_skew`, and the unpinned `npx @reticlehq/server` every agent entry uses resolves the
556
561
  // LATEST major whatever the project installed. Hand the same arguments to the matching release and
557
562
  // step aside — it reports its own run. See cli/launch/sdk-version-match.ts.
558
- const matchVersion = versionToMatch({
563
+ // One project lookup for both questions below: it reads config and walks the workspace.
564
+ const versionInput = {
559
565
  argv,
560
566
  cliVersion: SERVER_VERSION,
561
567
  env: process.env,
562
568
  projectDir: projectDirOf(process.cwd()),
563
569
  readFile: readTextFile,
564
- });
570
+ };
571
+ const matchVersion = versionToMatch(versionInput);
565
572
  if (matchVersion !== undefined) {
566
573
  process.stderr.write(`${versionMatchNote(matchVersion, SERVER_VERSION)}\n`);
567
574
  reexecAtVersion(matchVersion, argv, process.env, {
@@ -571,6 +578,11 @@ export function main() {
571
578
  });
572
579
  return;
573
580
  }
581
+ // Help stays on this binary, so say which version the command it describes really runs at (#1378).
582
+ const helpVersion = helpRunsAt(versionInput);
583
+ if (helpVersion !== undefined) {
584
+ process.stdout.write(`${helpVersionNote(helpVersion, SERVER_VERSION)}\n\n`);
585
+ }
574
586
  // Every invocation passes through here — the single chokepoint for the "how often is it used / how
575
587
  // many distinct machines + projects" metrics. Fire-and-forget: a metric must never delay or fail a run.
576
588
  //
@@ -582,6 +594,13 @@ export function main() {
582
594
  // just the scale, which is the kind of error you cannot correct for after the fact. The daemon's
583
595
  // own lifecycle is already reported by `daemon_started` / `daemon_stopped`; it is not a CLI run.
584
596
  reportCliRun(argv);
597
+ // An old name still runs, for one release, and says once what it is called now. Not when the
598
+ // person only asked for help: that answer names the new command itself, on stdout.
599
+ const renamedTo = renamedCommandFor(argv);
600
+ if (renamedTo !== undefined) {
601
+ const colour = true === process.stderr.isTTY && process.env['NO_COLOR'] === undefined;
602
+ process.stderr.write(`${renamedNote(argv[0] ?? '', renamedTo, colour)}\n`);
603
+ }
585
604
  // Cloud subcommands (login/link/project/config/push) are a distinct family with their own async client;
586
605
  // handle them before the local typed parser so `reticle login` etc. work as one tool.
587
606
  if (isCloudCommand(argv[0])) {
@@ -590,17 +609,39 @@ export function main() {
590
609
  // `reticle link --help` used to run the command: it reached for the network and answered
591
610
  // `fetch failed` with exit 1, to somebody who had asked what the command was for.
592
611
  if (argv.some((arg) => '--help' === arg || '-h' === arg)) {
593
- process.stdout.write(`${CLI_USAGE}\n`);
612
+ process.stdout.write(`${renderHelp(argv[0], RENAMED_COMMANDS)}\n`);
594
613
  return;
595
614
  }
596
615
  if ('connect' === argv[0]) {
597
616
  void (async () => {
598
617
  // A fresh project gets the same install, dev-server handover and browser proof as `init`.
599
618
  // Its failure exits non-zero before any cloud binding can claim this repo is ready.
619
+ // A setup that did not finish is said above and still fails the run, but no longer ends it
620
+ // before sign-in: the second identical run was the only way to get signed in.
621
+ let unfinished;
600
622
  if (readProjectId(process.cwd()) === undefined) {
601
- await handleInit({ port: undefined, mcp: true, dryRun: false, install: true });
623
+ const init = await handleInit({
624
+ port: undefined,
625
+ mcp: true,
626
+ dryRun: false,
627
+ install: connectInstalls(argv),
628
+ keepGoing: true,
629
+ });
630
+ if (1 === process.exitCode) {
631
+ // init hands no context over exactly when the dependency install failed (run.ts); its
632
+ // outcome's own reason is unset when the files were all written and the app was not.
633
+ unfinished =
634
+ init.context === undefined && init.outcome !== undefined
635
+ ? InitFailure.DEPENDENCY_INSTALL
636
+ : (init.outcome?.reason ?? InitFailure.OTHER);
637
+ process.exitCode = 0;
638
+ process.stderr.write(`${MSG_CONNECT_AFTER_UNFINISHED_INIT}\n`);
639
+ }
602
640
  }
603
- return runCloudCommand(argv);
641
+ const exit = connectExit(await runCloudCommand(argv), unfinished);
642
+ if (exit.note !== undefined)
643
+ process.stderr.write(`${exit.note}\n`);
644
+ return exit.code;
604
645
  })()
605
646
  .then((code) => process.exit(code))
606
647
  .catch((cause) => {
@@ -641,7 +682,7 @@ export function main() {
641
682
  const defaultPort = envPort ?? projectPort ?? myDaemonPort ?? RETICLE_DEFAULT_PORT;
642
683
  // Headed by default; hidden only where there is no display to be headed on. A run nobody can see
643
684
  // is a run nobody trusts, and every "did it actually do anything?" cost a human round-trip.
644
- const parsed = parseCliArgs(argv, defaultPort, process.env['CI'] !== undefined);
685
+ const parsed = parseCliArgs(argv, defaultPort, headlessByDefault(process.env, process.platform));
645
686
  // The refusal the line above promised. Printing it and carrying on let the default port answer
646
687
  // anyway, for whichever project's daemon owned it.
647
688
  if (portConflict !== undefined && dialsTheDaemon(parsed)) {
@@ -686,14 +727,15 @@ export function main() {
686
727
  case 'feedback':
687
728
  void handleFeedback(parsed.text, parsed.rating, parsed.bug, parsed.feedbackKind, parsed.agent);
688
729
  break;
689
- case 'identify':
690
- void handleIdentify(parsed);
691
- break;
692
730
  case 'version':
693
731
  handleVersion();
694
732
  break;
695
733
  case 'help':
696
- process.stdout.write(`${CLI_USAGE}\n`);
734
+ process.stdout.write(`${renderHelp(parsed.topic, RENAMED_COMMANDS)}\n`);
735
+ break;
736
+ case 'removed':
737
+ process.stderr.write(`${parsed.message}\n`);
738
+ process.exit(1);
697
739
  break;
698
740
  case 'doctor':
699
741
  void handleDoctor(parsed.port);
@@ -708,22 +750,6 @@ export function main() {
708
750
  mcp: parsed.mcp,
709
751
  }, reportStepFromCli);
710
752
  break;
711
- case 'tutorial':
712
- // Reported for BOTH paths, and before either: a run is a tour too, and these two steps are
713
- // about the tour being asked for, which is already true by the time we get here.
714
- reportTutorialShown();
715
- if (parsed.run) {
716
- void runDemoTour({
717
- port: parsed.port,
718
- headless: parsed.headless,
719
- say: (line) => process.stdout.write(`${line}\n`),
720
- }).then((result) => {
721
- process.exit(result.code);
722
- });
723
- break;
724
- }
725
- process.stdout.write(`${renderTutorial(parsed.audience)}\n`);
726
- break;
727
753
  case 'open':
728
754
  handleOpen(parsed.port, parsed.url);
729
755
  break;
@@ -733,23 +759,17 @@ export function main() {
733
759
  case 'verify':
734
760
  handleVerify(parsed);
735
761
  break;
736
- case 'capsules':
737
- void handleCapsules();
738
- break;
739
762
  case 'affected':
740
763
  void handleAffected(parsed.files, parsed.since);
741
764
  break;
742
- case 'hunt':
743
- void handleHunt(parsed.dir);
744
- break;
745
765
  case 'gate':
746
766
  void handleGate(parsed.files, parsed.since, parsed.hook, parsed.acceptCoverage);
747
767
  break;
748
768
  case 'report':
749
769
  void handleReport(parsed.session, parsed.hook);
750
770
  break;
751
- case 'watch':
752
- handleWatch();
771
+ case 'context':
772
+ void handleContext(parsed.session);
753
773
  break;
754
774
  case 'update':
755
775
  void handleUpdate();
@@ -8,7 +8,7 @@
8
8
  * per Node's guidance, so LOG a clear reason and exit cleanly; the next `reticle mcp` respawns a fresh
9
9
  * daemon, which beats crashing silently or limping along corrupt.
10
10
  */
11
- import { RETICLE_DEFAULT_PORT, TelemetryActor, TelemetryEventKind } from '@reticlehq/core';
11
+ import { RETICLE_DEFAULT_PORT, TelemetryEventKind } from '@reticlehq/core';
12
12
  import { errorSkeleton, errorTypeOf, fingerprintCrash, MAX_REPORTED_FRAMES, reticleFrames, } from '../../telemetry/error-fingerprint.js';
13
13
  import { getSessionMetrics } from '../../telemetry/session-metrics.js';
14
14
  import { machineSnapshot } from '../../telemetry/machine-snapshot.js';
@@ -157,9 +157,9 @@ function reportCrash(kind, value) {
157
157
  * gone for months.
158
158
  */
159
159
  detach: true,
160
- // A crash is ALWAYS reached through something the agent asked for — the daemon does nothing on
161
- // its own — so attributing it to the agent is accurate rather than a guess.
162
- actor: TelemetryActor.AGENT,
160
+ // No `actor`. The daemon does plenty on its own (timers, the bridge, a page's SDK, the update
161
+ // check), and the core contract says a crash is neither human nor agent: tagging every one
162
+ // `agent` put the whole crash count on the agent side of every actor split.
163
163
  crash: {
164
164
  kind,
165
165
  errorType,
@@ -112,6 +112,12 @@ export declare function splitBrainNote(myPort: number, elsewhere: readonly numbe
112
112
  * being inspected is the project's own.
113
113
  */
114
114
  export declare function wrongDaemonNote(inspectedPort: number, ownPort: number | undefined): string | undefined;
115
+ /**
116
+ * Why the proxy serves `port` and not the `requested` one, in words a person can act on. It said
117
+ * "the requested port serves a different project" for every move, including the commonest one: this
118
+ * project's own daemon was already running elsewhere (a `connect` started it on the default).
119
+ */
120
+ export declare function relocationReason(requested: number, port: number, projectId: string | undefined, home: string, alive: (pid: number) => boolean): string;
115
121
  /**
116
122
  * The port this agent's MCP proxy should serve, decided BEFORE the proxy starts.
117
123
  *
@@ -133,4 +139,6 @@ export declare function resolveMcpPort(preferred: number, projectId: string | un
133
139
  alive: (pid: number) => boolean;
134
140
  daemonPresent: (port: number) => Promise<boolean>;
135
141
  pickPort: (preferred: number) => Promise<number>;
136
- }): Promise<number>;
142
+ },
143
+ /** The port this project's `.reticle.json` names: the one its app dials. */
144
+ own?: number): Promise<number>;
@@ -19,7 +19,7 @@
19
19
  import { readdirSync, readFileSync } from 'node:fs';
20
20
  import { join } from 'node:path';
21
21
  import { DaemonRegistryEntrySchema, daemonRegistryPort, pickDaemonPort, } from '@reticlehq/core/artifacts';
22
- import { ReticleEnv } from '@reticlehq/core';
22
+ import { ReticleEnv, RETICLE_DEFAULT_PORT } from '@reticlehq/core';
23
23
  const RETICLE_PORT_ENV = ReticleEnv.PORT;
24
24
  /**
25
25
  * Every well-formed registry entry in `home`.
@@ -156,12 +156,17 @@ export function splitBrainNote(myPort, elsewhere) {
156
156
  return undefined;
157
157
  const listed = elsewhere.map((port) => `:${String(port)}`).join(', ');
158
158
  const first = elsewhere[0] ?? myPort;
159
+ // The agent moves, not the app (#1546). The daemon the app is on is a working session this agent
160
+ // did not start, and it may be a person's, another agent's or another project's. Stopping it was
161
+ // the first thing this used to say. It comes last now, with what it costs.
159
162
  return (`this project's app is connected to a DIFFERENT Reticle daemon (${listed}), while this one is ` +
160
163
  `on :${String(myPort)} — two daemons for one project, and the agent is attached to the empty ` +
161
- 'half. Nothing is wrong with the app or the wiring. Stop the other daemon with ' +
162
- `\`reticle stop --port ${String(first)}\` and restart the dev server so the app rediscovers ` +
163
- 'this one, or start the agent and the dev server from the same project directory so both ' +
164
- 'resolve the same daemon.');
164
+ 'half. Nothing is wrong with the app or the wiring. Move the agent to the app: set ' +
165
+ `${RETICLE_PORT_ENV}=${String(first)} in this MCP server's config, or launch the agent from the ` +
166
+ `project directory the dev server runs in, then restart the agent session. Leave :${String(first)} ` +
167
+ 'running. Only if nothing else is using it, `reticle stop --port ' +
168
+ `${String(first)}\` and a dev server restart move the app here instead; that disconnects every ` +
169
+ 'tab and agent on that daemon.');
165
170
  }
166
171
  /**
167
172
  * The other stance on the same split, for a command standing on the port that HAS the app.
@@ -184,6 +189,25 @@ export function wrongDaemonNote(inspectedPort, ownPort) {
184
189
  'be different processes, with both reporting healthy. Stop one of them and restart the dev ' +
185
190
  'server so everything lands on the same port.');
186
191
  }
192
+ /**
193
+ * Why the proxy serves `port` and not the `requested` one, in words a person can act on. It said
194
+ * "the requested port serves a different project" for every move, including the commonest one: this
195
+ * project's own daemon was already running elsewhere (a `connect` started it on the default).
196
+ */
197
+ export function relocationReason(requested, port, projectId, home, alive) {
198
+ const at = `:${String(port)}`;
199
+ if (projectId !== undefined && resolveDaemonForProject(projectId, home, alive) === port)
200
+ return (`this project's daemon is already running on ${at}, so the agent uses it instead of ` +
201
+ `:${String(requested)}. To use :${String(requested)}, run \`reticle stop --port ${String(port)}\` ` +
202
+ 'and reconnect the agent.');
203
+ const holder = daemonProjectAt(requested, home);
204
+ if (holder !== undefined && holder !== projectId)
205
+ return (`:${String(requested)} serves project "${holder}", so this one is served on ${at}. Give this ` +
206
+ 'project its own port (RETICLE_PORT, or `port` in its .reticle.json) and restart the agent.');
207
+ if (projectId === undefined)
208
+ return `no project here, and the one live project daemon is on ${at}: the agent uses it.`;
209
+ return `nothing usable answered on :${String(requested)}, so the agent is served on ${at}.`;
210
+ }
187
211
  /**
188
212
  * The port this agent's MCP proxy should serve, decided BEFORE the proxy starts.
189
213
  *
@@ -201,7 +225,9 @@ export function wrongDaemonNote(inspectedPort, ownPort) {
201
225
  * silent adoption is what made every agent on a machine share one process, one identity and one
202
226
  * blast radius.
203
227
  */
204
- export async function resolveMcpPort(preferred, projectId, home, deps) {
228
+ export async function resolveMcpPort(preferred, projectId, home, deps,
229
+ /** The port this project's `.reticle.json` names: the one its app dials. */
230
+ own) {
205
231
  const mine = resolveDaemonForProject(projectId, home, deps.alive);
206
232
  if (mine !== undefined)
207
233
  return mine;
@@ -209,10 +235,23 @@ export async function resolveMcpPort(preferred, projectId, home, deps) {
209
235
  // A caller outside any project (an editor's user-scope MCP, launched from $HOME) used to dial the
210
236
  // default and never see the one project that had moved off it (#1240). With exactly one project
211
237
  // daemon live, that is the one; with several, the no-session answer names them instead.
212
- const projects = projectId === undefined ? projectDaemonsElsewhere(preferred, home, deps.alive) : [];
238
+ // Only on the DEFAULT port, which is the guess #1240 corrects. A port passed with --port or
239
+ // RETICLE_PORT is a choice: relocating it attached an unwired app to another project's daemon.
240
+ const projects = projectId === undefined && RETICLE_DEFAULT_PORT === preferred
241
+ ? projectDaemonsElsewhere(preferred, home, deps.alive)
242
+ : [];
213
243
  return 1 === projects.length ? (projects[0]?.port ?? preferred) : preferred;
214
244
  }
215
- return adoptable(daemonProjectAt(preferred, home), projectId)
216
- ? preferred
217
- : deps.pickPort(preferred);
245
+ if (adoptable(daemonProjectAt(preferred, home), projectId))
246
+ return preferred;
247
+ // Moved off a port another project holds: to the one this project's app dials, when it is free or
248
+ // already ours. A random port served nobody — the app kept dialling its own, and the agent was
249
+ // told "wired, and a dev server is listening, but no session".
250
+ if (own !== undefined && own !== preferred) {
251
+ if (!(await deps.daemonPresent(own)))
252
+ return own;
253
+ if (adoptable(daemonProjectAt(own, home), projectId))
254
+ return own;
255
+ }
256
+ return deps.pickPort(preferred);
218
257
  }
@@ -12,4 +12,6 @@
12
12
  */
13
13
  import { PortPresence } from '../../daemon/binding/port-presence.js';
14
14
  /** The refusal to print, or undefined when the port is usable. */
15
- export declare function bridgeOccupied(presence: PortPresence, port: number): string | undefined;
15
+ export declare function bridgeOccupied(presence: PortPresence, port: number, freePort?: number): string | undefined;
16
+ /** The first port after `port` that nothing answers on, or undefined within the scan. */
17
+ export declare function freePortAfter(port: number, isOpen: (port: number) => Promise<boolean>): Promise<number | undefined>;
@@ -12,13 +12,23 @@
12
12
  */
13
13
  import { PortPresence } from '../../daemon/binding/port-presence.js';
14
14
  /** The refusal to print, or undefined when the port is usable. */
15
- export function bridgeOccupied(presence, port) {
15
+ export function bridgeOccupied(presence, port, freePort) {
16
16
  // DAEMON is the ordinary case — that is the daemon init is about to use. FREE is fine too: one
17
17
  // gets started. Only a stranger is fatal.
18
18
  if (PortPresence.FOREIGN !== presence)
19
19
  return undefined;
20
20
  return (`port ${String(port)} is held by something that is not a Reticle daemon. That is the bridge — ` +
21
21
  'the channel between the daemon and the SDK in your page — so no session can ever appear while ' +
22
- 'it is occupied, however correct the wiring is. Free it, or re-run with --port <n> and set the ' +
23
- 'same port in .reticle.json.');
22
+ 'it is occupied, however correct the wiring is. Free it, or re-run on another port (init moves ' +
23
+ `the config and the page with it): reticle init --port ${freePort === undefined ? '<n>' : String(freePort)}`);
24
+ }
25
+ /** How many ports past the held one are tried before giving up on a suggestion. */
26
+ const FREE_PORT_SCAN = 20;
27
+ /** The first port after `port` that nothing answers on, or undefined within the scan. */
28
+ export async function freePortAfter(port, isOpen) {
29
+ for (let candidate = port + 1; candidate <= port + FREE_PORT_SCAN; candidate++) {
30
+ if (!(await isOpen(candidate)))
31
+ return candidate;
32
+ }
33
+ return undefined;
24
34
  }
@@ -101,6 +101,8 @@ function main(argv) {
101
101
  const child = spawn(command, {
102
102
  shell: true,
103
103
  stdio: ['ignore', 'pipe', 'pipe'],
104
+ // This supervisor runs detached with no console on Windows, so the shell would open a window.
105
+ windowsHide: true,
104
106
  env: process.env,
105
107
  });
106
108
  child.stdout.on('data', (chunk) => log.write(chunk));