@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
@@ -6,20 +6,29 @@
6
6
  * app, and keeping them together is what stops a drive attached to one app landing in another that
7
7
  * happens to be on the same port. See `local-apps.ts` and `remote-drive.ts` for each half.
8
8
  */
9
- import { basename, join } from 'node:path';
9
+ import { isUnmatchedRoot } from '../../memory/project/dir/reticle-dir.js';
10
+ import { readProjectId } from '../../command/cli/ports/resolve/cli-port.js';
11
+ import { basename, dirname, join } from 'node:path';
10
12
  import { homedir, hostname } from 'node:os';
11
- import { LinkCapability, ReticleTool, asRecord } from '@reticlehq/core';
13
+ import { LinkCapability, ReticleDir, ReticleTool, asRecord, } from '@reticlehq/core';
12
14
  import { prepareDrive } from '../../features/harness/platform/drive-target.js';
13
15
  import { reticleToolset } from './harness-toolset.js';
14
- import { projectDirFor } from '../../memory/project/session-root.js';
16
+ import { projectDirFor, sessionRoot } from '../../memory/project/session-root.js';
17
+ import { readDashboardUrl } from '../../memory/project/sync-status.js';
15
18
  import { driveFrame } from '../../features/visual/visual-tools.js';
16
19
  import { LEASE_ACQUIRE_TOOL } from './lease-tools.js';
17
20
  import { REMOTE_DRIVE_JPEG_QUALITY, endDrivenTab, pickOwnDriveSession, startRemoteDrives, } from '../../features/harness/platform/remote-drive.js';
18
- import { appKeyOf, appsByPlatform, machineOf, mayOpen, NOT_AN_APP_ADDRESS, nameFromProjectId, pickAppTab, startAppReports, } from '../../features/harness/platform/local-apps.js';
21
+ import { appKeyOf, appsByPlatform, homeRelative, machineOf, mayOpen, NOT_AN_APP_ADDRESS, nameFromProjectId, pickAppTab, startAppReports, withoutMarks, } from '../../features/harness/platform/local-apps.js';
19
22
  import { serverOptionsFromEnv } from '../../features/harness/platform/server-driver.js';
20
- import { driveForChat } from './explore-tools.js';
21
- import { withLinkedCredential } from './harness-explore.js';
23
+ import { EXPLORE_TOOLS, driveForChat } from './explore-tools.js';
24
+ import { MSG_NO_HARNESS_KEY, harnessLockRefusal, withLinkedCredential } from './harness-explore.js';
22
25
  import { runTool } from './invoke-tool.js';
26
+ import { announcedChannels, probeMarkers, notApplicableOf, recordedGaps, } from '../../portal/session/recorded-gaps.js';
27
+ import { probeDevServers } from '../../portal/session/dev-server/dev-server-probe.js';
28
+ import { DriveOrigin, onDriveChange, onDriveStep, runningDrive, stopDrive, } from '../../features/harness/drive-runs.js';
29
+ import { FreeDriveKind, planUrl, requestFreeDrive, } from '../../features/harness/platform/platform-drives.js';
30
+ import { HumanControlKind } from '@reticlehq/core';
31
+ import { onAgentsChange } from '../../hooks/coding-agents.js';
23
32
  /** Why a platform drive with no tab of its own runs no tool. */
24
33
  const NO_DRIVEN_TAB = 'No tab was picked for this drive, so no tool runs.';
25
34
  /** What this daemon does for the platform's chat. Each one is listed only once it is built. */
@@ -48,6 +57,31 @@ const nameOf = async (fs, dir, projectId) => {
48
57
  return nameFromProjectId(projectId);
49
58
  return basename(dir) || dir;
50
59
  };
60
+ /** How often the localhost dev-server scan may run: never more than this, however often we report. */
61
+ const DEV_SERVER_SCAN_EVERY_MS = 30_000;
62
+ /**
63
+ * Dev servers listening on localhost with no connected Reticle page — an app that is up and not
64
+ * instrumented, or not dialling. The same probe `doctor` and the no-session diagnosis use, cached.
65
+ */
66
+ function devServerScan(connectedUrls, now) {
67
+ let last;
68
+ return async () => {
69
+ if (last === undefined || now() - last.at >= DEV_SERVER_SCAN_EVERY_MS)
70
+ last = { at: now(), ports: await probeDevServers() };
71
+ const connected = new Set(connectedUrls().map((url) => {
72
+ try {
73
+ return Number(new URL(url).port);
74
+ }
75
+ catch {
76
+ return 0;
77
+ }
78
+ }));
79
+ return last.ports
80
+ .filter((port) => !connected.has(port))
81
+ .map((port) => ({ url: `http://${LOCALHOST_HOST}:${String(port)}`, port }));
82
+ };
83
+ }
84
+ const LOCALHOST_HOST = 'localhost';
51
85
  export function startChatDrives(deps, sessions, fs, cloud, log) {
52
86
  const env = process.env;
53
87
  const machine = machineOf(hostname(), homedir());
@@ -69,13 +103,36 @@ export function startChatDrives(deps, sessions, fs, cloud, log) {
69
103
  if (!mayOpen(url, sessions.list().map((tab) => tab.url)))
70
104
  throw new Error(NOT_AN_APP_ADDRESS);
71
105
  };
72
- const open = async (url) => {
106
+ /**
107
+ * The `.reticle` each reported app writes into, learned from its tabs. A tab the chat opens for an
108
+ * app is leased into that root: resolved from the page alone, an app with no project id would land
109
+ * in `unmatched/`, which nothing syncs.
110
+ */
111
+ const rootByApp = new Map();
112
+ /**
113
+ * The root AND the project a tab the daemon opens for an app is stamped with. Stamped with the
114
+ * root alone, a page that reports no project of its own opened as nobody's: its run fell to
115
+ * `unmatched/` and the drive answered a linked project "run reticle connect".
116
+ */
117
+ const claimFor = (appKey) => (appKey === undefined ? undefined : rootByApp.get(appKey)) ?? {};
118
+ /** Where each credential's project was last open on this machine, from the reports. */
119
+ const lastUrlByKey = new Map();
120
+ /** Lease the app a credential's project was last open at, for a drive no tab of it can take. */
121
+ const reopenFor = async (key) => {
122
+ const last = lastUrlByKey.get(key);
123
+ if (last === undefined)
124
+ return undefined;
125
+ openable(last.url);
126
+ const id = asRecord(await runTool(LEASE_ACQUIRE_TOOL, deps, { ...last }))['sessionId'];
127
+ return 'string' === typeof id ? id : undefined;
128
+ };
129
+ const open = async (url, appKey) => {
73
130
  openable(url);
74
- await runTool(LEASE_ACQUIRE_TOOL, deps, { url });
131
+ await runTool(LEASE_ACQUIRE_TOOL, deps, { url, ...claimFor(appKey) });
75
132
  };
76
133
  const pick = (goal, key, app) => undefined === app
77
- ? pickOwnDriveSession(sessions.list(), goal, key, sessionKey)
78
- : pickAppTab(app, goal, () => sessions.list(), appOf, open).then(async (id) =>
134
+ ? pickOwnDriveSession(sessions.list(), goal, key, sessionKey, () => reopenFor(key))
135
+ : pickAppTab(app, goal, () => sessions.list(), appOf, (url) => open(url, app.key)).then(async (id) =>
79
136
  // The app the platform named must be one this credential's project owns.
80
137
  'string' === typeof id && (await sessionKey(id)) !== key ? null : id);
81
138
  const drives = startRemoteDrives({
@@ -91,6 +148,7 @@ export function startChatDrives(deps, sessions, fs, cloud, log) {
91
148
  url,
92
149
  ...(headed ? { headed } : {}),
93
150
  ...(hud === undefined ? {} : { hud }),
151
+ ...claimFor(app?.key),
94
152
  }));
95
153
  const id = lease['sessionId'];
96
154
  if ('string' !== typeof id)
@@ -110,9 +168,9 @@ export function startChatDrives(deps, sessions, fs, cloud, log) {
110
168
  const tools = reticleToolset(deps, { sessionId, locked: true });
111
169
  return { tools: tools.tools, invoke: (tool, args) => tools.invoke(tool, args) };
112
170
  },
113
- drive: async (goal, sessionId) => {
171
+ drive: async (goal, sessionId, spec) => {
114
172
  const url = sessions.list().find((tab) => tab.sessionId === sessionId)?.url;
115
- const outcome = await driveForChat(deps, goal, sessionId);
173
+ const outcome = await driveForChat(deps, goal, sessionId, spec?.plan, spec?.confirmDangerous);
116
174
  return url === undefined ? outcome : { ...outcome, url };
117
175
  },
118
176
  // The leased tab, or a desktop window's own capture. A web tab only the SDK reaches has no camera.
@@ -122,22 +180,80 @@ export function startChatDrives(deps, sessions, fs, cloud, log) {
122
180
  settle: (id, outcome) => endDrivenTab(id === undefined ? undefined : sessions.get(id), outcome),
123
181
  log,
124
182
  });
183
+ const scanDevServers = devServerScan(() => sessions.list().map((tab) => tab.url), () => Date.now());
125
184
  const reports = startAppReports({
126
185
  machine,
127
186
  version: cloud.version,
128
187
  capabilities: CHAT_CAPABILITIES,
129
- apps: async () => appsByPlatform(sessions.list(), serverOptionsFromEnv(await withLinkedCredential(deps, env)), machine.id, async (tab) => {
130
- const dir = projectDirFor(deps, tab.sessionId);
131
- const platform = await sessionCloud(tab.sessionId);
188
+ apps: async () => {
189
+ // The setup score the dashboard shows is what the app's pages carry, asked of each page
190
+ // until its app has shown both markers: never only what an act happened to reach.
191
+ await probeMarkers(sessions.list().flatMap((tab) => {
192
+ const live = sessions.get(tab.sessionId);
193
+ const command = live?.command?.bind(live);
194
+ return command === undefined
195
+ ? []
196
+ : [{ id: tab.sessionId, url: tab.url, projectId: tab.projectId, command }];
197
+ }));
198
+ return appsByPlatform(sessions.list().map((tab) => {
199
+ const live = sessions.get(tab.sessionId);
200
+ const sdkVersion = live?.sdkVersion;
201
+ // What the page announced plus the gaps its verdicts paid for: what the dashboard's
202
+ // coverage line and coding-agent prompt are built from.
203
+ const channels = announcedChannels({
204
+ id: tab.sessionId,
205
+ url: tab.url,
206
+ projectId: tab.projectId,
207
+ channels: live?.channels,
208
+ sourceMapping: live?.sourceMapping,
209
+ });
210
+ const gaps = recordedGaps(tab.sessionId).map(({ kind, missing, fix, seenAt }) => ({
211
+ kind,
212
+ missing,
213
+ fix,
214
+ seenAt,
215
+ }));
216
+ return {
217
+ ...tab,
218
+ ...(sdkVersion === undefined ? {} : { sdkVersion }),
219
+ ...(0 === channels.length ? {} : { channels }),
220
+ gaps,
221
+ notApplicable: notApplicableOf({
222
+ id: tab.sessionId,
223
+ url: tab.url,
224
+ projectId: tab.projectId,
225
+ }),
226
+ };
227
+ }), serverOptionsFromEnv(await withLinkedCredential(deps, env)), machine.id, async (tab) => {
228
+ const root = sessionRoot(deps, tab.sessionId);
229
+ const dir = dirname(root);
230
+ const projectId = tab.projectId ?? readProjectId(dir);
231
+ const stamp = { root, ...(projectId === undefined ? {} : { projectId }) };
232
+ rootByApp.set(appKeyOf(machine.id, dir, tab.projectId), stamp);
233
+ const platform = await sessionCloud(tab.sessionId);
234
+ if (undefined !== platform)
235
+ lastUrlByKey.set(platform.apiKey, { url: withoutMarks(tab.url), ...stamp });
236
+ return {
237
+ dir,
238
+ name: await nameOf(fs, dir, tab.projectId),
239
+ ...(undefined === platform
240
+ ? {}
241
+ : { platform: { url: platform.url.replace(/\/+$/, ''), apiKey: platform.apiKey } }),
242
+ };
243
+ });
244
+ },
245
+ open,
246
+ extras: async () => {
247
+ const closure = sessions.lastClosure?.();
248
+ const unsynced = cloud.unsynced?.();
132
249
  return {
133
- dir,
134
- name: await nameOf(fs, dir, tab.projectId),
135
- ...(undefined === platform
250
+ devServers: await scanDevServers(),
251
+ ...(closure === undefined
136
252
  ? {}
137
- : { platform: { url: platform.url.replace(/\/+$/, ''), apiKey: platform.apiKey } }),
253
+ : { helloFailure: { reason: closure.reason, at: closure.at } }),
254
+ ...unsyncedReport(unsynced, homedir()),
138
255
  };
139
- }),
140
- open,
256
+ },
141
257
  drivePending: (platform) => void drives.tick(platform),
142
258
  // What the platform wants the person told: in the daemon's log, and on the HUD of each open tab
143
259
  // of that project, so somebody who never reads the log still sees "update Reticle".
@@ -163,3 +279,131 @@ export function startChatDrives(deps, sessions, fs, cloud, log) {
163
279
  },
164
280
  };
165
281
  }
282
+ /** The dashboard the tab's project is linked to, when its link names one. */
283
+ function dashboardOf(deps, sessionId) {
284
+ try {
285
+ return readDashboardUrl(sessionRoot(deps, sessionId));
286
+ }
287
+ catch {
288
+ return undefined;
289
+ }
290
+ }
291
+ /** Said on the HUD when Link this project ends. */
292
+ const MSG_LINKED = 'Linked. This project now reports to your dashboard.';
293
+ const MSG_LINK_FAILED = 'Could not link this project. Run `reticle connect` in its folder.';
294
+ /** A page with no projectId: linking it would bind a hash-named project nothing here reads. */
295
+ const MSG_LINK_NEEDS_PROJECT = 'This page did not say which project it is, so there is nothing to link yet. Run `npx @reticlehq/server init` in your app (or pass `projectId` to `connect()`), then Link.';
296
+ const MSG_LINK_UNAVAILABLE = 'This Reticle cannot link from the panel. Run `reticle connect` in the project folder.';
297
+ /** Said on the HUD when Stop finds nothing to stop. */
298
+ const MSG_NOTHING_DRIVING = 'No Harness drive is running in this tab.';
299
+ const msgStartTrial = (url) => `Start your trial: ${url}`;
300
+ /**
301
+ * The panel's Harness controls. The switch is the platform's autonomous mode, unchanged. Run Harness
302
+ * and Stop drive. A run asks the platform for the drive's grant, then starts it
303
+ * through the same explore an agent calls (counted, recorded, polled the same way); its lines and
304
+ * steps reach the HUD log as the drive narrates them. A refused grant says why, and where to start
305
+ * a trial when it wants a card.
306
+ */
307
+ export async function hudDrive(deps, sessionId,
308
+ /** The panel's control, as the bridge narrowed it (`harness-request.ts`). */
309
+ request,
310
+ /** The autonomous switch: written through to the platform, which the daemon owns. */
311
+ applySwitch, grant = (platform) => requestFreeDrive(platform, FreeDriveKind.EXPLORE)) {
312
+ if (HumanControlKind.HARNESS === request.kind)
313
+ return applySwitch(request.enabled);
314
+ // What the panel's Run and Stop answer belongs in the Harness log, and in the Agent Log as a summary.
315
+ const say = (text) => deps.sessions.get?.(sessionId)?.pushNarration(text, true, { harness: true, summary: true });
316
+ if (HumanControlKind.HARNESS_STOP === request.kind) {
317
+ const running = runningDrive(sessionId);
318
+ if (running === undefined || !stopDrive(running.harnessRun))
319
+ say(MSG_NOTHING_DRIVING);
320
+ return;
321
+ }
322
+ // Before the grant: a drive the gate refuses must not take one. The panel shows the prompt.
323
+ const env = await withLinkedCredential(deps, process.env, { sessionId });
324
+ const locked = await harnessLockRefusal(deps, sessionId, env);
325
+ if (locked !== undefined)
326
+ return say(locked.split('\n')[0] ?? locked);
327
+ const platform = serverOptionsFromEnv(env);
328
+ if (platform === undefined)
329
+ return say(MSG_NO_HARNESS_KEY);
330
+ const granted = await grant(platform);
331
+ if (!granted.granted) {
332
+ say(granted.message);
333
+ // At the console's origin (the tab's link names it), never the API's, which 404s when split.
334
+ if (granted.needsCard)
335
+ say(msgStartTrial(planUrl(dashboardOf(deps, sessionId) ?? platform.url)));
336
+ return;
337
+ }
338
+ const explore = EXPLORE_TOOLS.find((tool) => ReticleTool.VERIFY_EXPLORE === tool.name);
339
+ if (explore === undefined)
340
+ return;
341
+ try {
342
+ await runTool(explore, deps, {
343
+ sessionId,
344
+ driveId: granted.driveId,
345
+ origin: DriveOrigin.HUD,
346
+ wait: 0,
347
+ ...(request.persona === undefined ? {} : { persona: request.persona }),
348
+ });
349
+ }
350
+ catch (error) {
351
+ say(error instanceof Error ? error.message : String(error));
352
+ }
353
+ }
354
+ /**
355
+ * The link a panel sign-in makes once it lands: the tab's project, never a page that did not say
356
+ * which project it is (that would bind a hash-named project nothing here reads).
357
+ */
358
+ export function projectLinkOnly(link) {
359
+ return link === undefined
360
+ ? undefined
361
+ : (root) => (isUnmatchedRoot(root) ? Promise.resolve(0) : link(root));
362
+ }
363
+ /**
364
+ * The panel's Harness controls on a bridge: the switch writes through to the platform, so console
365
+ * and panel cannot disagree; Run and Stop drive, in the project of the tab that asked.
366
+ */
367
+ export function attachHudHarness(bridge, daemon, applySwitch,
368
+ /** Link this project: what `reticle connect` does from that folder. Absent: the button says so. */
369
+ link) {
370
+ bridge.attachHarnessRequest((request, s) => {
371
+ const root = s.artifactRoot ?? daemon.root;
372
+ if (HumanControlKind.HARNESS_LINK === request.kind) {
373
+ const say = (text) => daemon.deps().sessions.get?.(s.id)?.pushNarration(text);
374
+ if (link === undefined)
375
+ return say(MSG_LINK_UNAVAILABLE);
376
+ if (isUnmatchedRoot(root))
377
+ return say(MSG_LINK_NEEDS_PROJECT);
378
+ void link(root)
379
+ .then((code) => say(0 === code ? MSG_LINKED : MSG_LINK_FAILED))
380
+ .catch(() => say(MSG_LINK_FAILED))
381
+ .finally(daemon.repaint);
382
+ return;
383
+ }
384
+ void hudDrive(daemon.deps(), s.id, request, (on) => applySwitch(root, on));
385
+ });
386
+ onDriveChange(daemon.repaint);
387
+ // Each step too, so the panel's "N steps so far" counts up instead of sitting at zero.
388
+ onDriveStep(daemon.repaint);
389
+ // And "Connected: Claude Code" follows an agent attaching or leaving.
390
+ onAgentsChange(daemon.repaint);
391
+ }
392
+ /**
393
+ * The `unsynced` field of a report. Sent empty too, once this daemon has counted: the platform reads
394
+ * an absent list as "no news" and kept a "never sent" banner for runs that had long been sent.
395
+ */
396
+ export function unsyncedReport(unsynced, home) {
397
+ if (unsynced === undefined)
398
+ return {};
399
+ return {
400
+ // A folder no project claimed cannot be connected, so no board should tell anyone to.
401
+ unsynced: unsynced
402
+ .filter((u) => !isUnmatchedRoot(u.root))
403
+ .map((u) => ({
404
+ ...u,
405
+ // The project, not its `.reticle`: the dashboard tells the person to run a command there.
406
+ root: homeRelative(ReticleDir.ROOT === basename(u.root) ? dirname(u.root) : u.root, home),
407
+ })),
408
+ };
409
+ }
@@ -5,14 +5,6 @@ interface Control {
5
5
  }
6
6
  /** Parse the interactive snapshot into {ref,label} controls, preserving document order. */
7
7
  export declare function parseControls(tree: string): Control[];
8
- /**
9
- * Build the coverage tool over the dispatchable tool table.
10
- *
11
- * The table arrives as a thunk rather than an import: `tools.ts` assembles it FROM this module, so
12
- * importing it back would close a cycle whose failure mode is a load-order-dependent crash rather
13
- * than an error anyone sees while writing it. The thunk is called inside the handler, long after the
14
- * table exists. It carries the merged names — the ones `reticle_run` will actually accept — because
15
- * a tool that merged into a parent is not something an agent can call or a maintainer can cut.
16
- */
17
- export declare function buildCoverageTools(toolNames: () => readonly string[]): ToolDef[];
8
+ /** Build the coverage tool. */
9
+ export declare function buildCoverageTools(): ToolDef[];
18
10
  export {};
@@ -2,9 +2,6 @@ import { z } from 'zod';
2
2
  import { sessionRoot } from '../../memory/project/session-root.js';
3
3
  import { projectForRoot } from '../../memory/project/project-for-root.js';
4
4
  import { coverageRegressed, observabilityOf } from '@reticlehq/engine/evidence/observability.js';
5
- import { foldFeatureCapture } from './feature-capture.js';
6
- import { foldToolHitRate } from './tool-hit-rate.js';
7
- import { allSessionIntents } from '../../memory/intent/open-intents.js';
8
5
  import { ReticleCommand, SnapshotMode } from '@reticlehq/core';
9
6
  import { ReticleTool } from '@reticlehq/core';
10
7
  import { asString } from '@reticlehq/core';
@@ -55,16 +52,8 @@ export function parseControls(tree) {
55
52
  }
56
53
  return controls;
57
54
  }
58
- /**
59
- * Build the coverage tool over the dispatchable tool table.
60
- *
61
- * The table arrives as a thunk rather than an import: `tools.ts` assembles it FROM this module, so
62
- * importing it back would close a cycle whose failure mode is a load-order-dependent crash rather
63
- * than an error anyone sees while writing it. The thunk is called inside the handler, long after the
64
- * table exists. It carries the merged names — the ones `reticle_run` will actually accept — because
65
- * a tool that merged into a parent is not something an agent can call or a maintainer can cut.
66
- */
67
- export function buildCoverageTools(toolNames) {
55
+ /** Build the coverage tool. */
56
+ export function buildCoverageTools() {
68
57
  return [
69
58
  {
70
59
  name: ReticleTool.COVERAGE,
@@ -100,25 +89,6 @@ export function buildCoverageTools(toolNames) {
100
89
  .object({ driven: z.number(), observable: z.number(), percent: z.number().optional() })
101
90
  .optional()
102
91
  .describe('Of the controls you DROVE, how many Reticle could fully observe. `untouched` above is work left for you; this is work left in the APP, and driving more controls does not move it. `percent` is OMITTED when nothing was driven, because 0/0 is not 100%.'),
103
- featureUse: z
104
- .object({
105
- observed: z.boolean(),
106
- truncated: z.boolean().optional(),
107
- context: z.unknown().optional(),
108
- intents: z.unknown().optional(),
109
- missed: z.unknown().optional(),
110
- })
111
- .optional()
112
- .describe('Whether this session used `reticle_context` and `reticle_intent` at all, and what it cost when it did not: `context` counts the calls and what followed each one, `intents` the ledger, `missed` the verdicts drawn against an empty ledger and the reads that re-fetched a fact already established. `observed:false` means nothing was recorded for this session — NOT that nothing was used. An instrument for deciding whether those two features earn their place; nothing here is a fault of yours.'),
113
- toolHitRate: z
114
- .object({
115
- observed: z.boolean(),
116
- cells: z.unknown().optional(),
117
- called: z.unknown().optional(),
118
- neverCalled: z.unknown().optional(),
119
- })
120
- .optional()
121
- .describe('Which Reticle tools THIS session called, and how reachable each one was: `called` lists every tool with its call count, `neverCalled` the rest of the table, and both carry a `tier` — `default` (advertised to every agent), `extended` (advertised only on the full surface) or `run-only` (reachable solely by naming it to reticle_run). `cells` counts each tier on both sides. `observed:false` means nothing was recorded for this session, NOT that nothing was called. THREE LIMITS, all load-bearing: this is ONE session, so it is evidence about this run and is not a hit rate — a hit rate is a distribution over many sessions. A never-called tool is not a useless tool; one used once a month in an emergency looks identical here to one nobody has ever called, so frequency alone cannot decide a cut. And the counts describe how this run went, never how it should have gone — nothing here is a fault of yours.'),
122
92
  observabilityRegressed: z
123
93
  .object({ was: z.number(), now: z.number() })
124
94
  .optional()
@@ -143,25 +113,6 @@ export function buildCoverageTools(toolNames) {
143
113
  // first without the second is how an agent finishes a pass believing it verified something the
144
114
  // app was never able to confirm.
145
115
  const gaps = session.gaps?.open() ?? [];
146
- // Folded here rather than given a tool of its own: this is already the "am I done, and what is
147
- // this verdict worth" read, and a number nobody has a reason to ask for separately is one
148
- // nobody ever sees. It is a fold over the journal and the intent ledger plus the one thing
149
- // neither records — see surface/tools/feature-capture.ts.
150
- const featureUse = foldFeatureCapture({
151
- calls: session.capture.calls(),
152
- dropped: session.capture.dropped,
153
- actions: await session.readJournalActions(),
154
- intents: await allSessionIntents(deps, sessionId),
155
- finalActions: session.actionCount,
156
- });
157
- // Same fold, same reason, one level out: which of the whole tool table this session reached
158
- // for, crossed with how reachable each name was. See surface/tools/tool-hit-rate.ts for what it can
159
- // and cannot establish — the limits matter more than usual, because this is the number a
160
- // decision to DELETE tools would be made on.
161
- const toolHitRate = foldToolHitRate({
162
- calls: session.capture?.toolCalls(),
163
- allTools: toolNames(),
164
- });
165
116
  // The number, and the floor under it, together. A coverage figure that can only ever be
166
117
  // reported and never contradicted is one an agent learns to satisfy rather than to earn.
167
118
  const observability = observabilityOf(session.actedRefs(), gaps);
@@ -179,8 +130,6 @@ export function buildCoverageTools(toolNames) {
179
130
  ...(gaps.length > 0 ? { instrumentationGaps: gaps, unproven: true } : {}),
180
131
  observability,
181
132
  ...(regressed === undefined ? {} : { observabilityRegressed: regressed }),
182
- featureUse,
183
- toolHitRate,
184
133
  ...(true === args['app']
185
134
  ? {
186
135
  app: await foldAppCoverage({
@@ -8,13 +8,41 @@ import { ReticleTool } from '@reticlehq/core';
8
8
  import { ADVERTISE_ALL_ENV } from './tool-surface.js';
9
9
  import { getSessionMetrics } from '../../telemetry/session-metrics.js';
10
10
  import { isPredicateParam, predicateGrammar, } from '@reticlehq/engine/question/predicate/predicate-eval.js';
11
+ /**
12
+ * A numeric parameter's enforced bounds, read off the schema that enforces them (#1537).
13
+ *
14
+ * The descriptions name a default and rarely a ceiling, so `timeout_ms: 60000` on act_and_wait was
15
+ * refused and the agent learned the 55000 cap from the error. Read here rather than written into
16
+ * prose, so the number shown is the number checked and cannot drift from it.
17
+ */
18
+ function boundsOf(schema) {
19
+ let inner = schema;
20
+ for (;;) {
21
+ if (inner instanceof z.ZodOptional || inner instanceof z.ZodNullable) {
22
+ inner = inner.unwrap();
23
+ }
24
+ else if (inner instanceof z.ZodDefault) {
25
+ inner = inner.removeDefault();
26
+ }
27
+ else if (inner instanceof z.ZodEffects) {
28
+ inner = inner.innerType();
29
+ }
30
+ else
31
+ break;
32
+ }
33
+ if (!(inner instanceof z.ZodNumber))
34
+ return {};
35
+ const { minValue: min, maxValue: max } = inner;
36
+ return { ...(null === min ? {} : { min }), ...(null === max ? {} : { max }) };
37
+ }
11
38
  /** Compact param list from a tool's zod shape — name/required/description (the description already
12
- * carries the type and any enum hints, so no JSON-Schema machinery is needed). */
39
+ * carries the type and any enum hints, so no JSON-Schema machinery is needed), plus numeric bounds. */
13
40
  function paramInfo(shape) {
14
41
  return Object.entries(shape).map(([name, schema]) => ({
15
42
  name,
16
43
  required: !schema.isOptional(),
17
44
  description: schema.description ?? '',
45
+ ...boundsOf(schema),
18
46
  }));
19
47
  }
20
48
  /**
@@ -38,4 +38,14 @@ export declare const EMPTY_SESSION_LIST_OUTPUT: {
38
38
  url: string;
39
39
  }>>;
40
40
  };
41
+ /**
42
+ * Wire the calling project when another project's tab is the one currently connected.
43
+ *
44
+ * The list handler only used to reach {@link emptySessionList} when the daemon's whole list was
45
+ * empty. A live tab in project A then answered project B's first call with A's sessions, and B
46
+ * was never wired.
47
+ */
48
+ export declare function wireCallerBesideLiveSessions(deps: ToolDeps, sessions: readonly {
49
+ projectId?: string;
50
+ }[]): Promise<unknown>;
41
51
  export declare function emptySessionList(deps: ToolDeps, sessions: unknown[]): Promise<Record<string, unknown>>;
@@ -9,6 +9,8 @@
9
9
  import { dirname } from 'node:path';
10
10
  import { z } from 'zod';
11
11
  import { DiscoveryInvite, NoSessionAction } from '@reticlehq/core';
12
+ import { readProjectId } from '../../command/cli/ports/resolve/cli-port.js';
13
+ import { callingClientDirectory } from '../../hooks/client-directory.js';
12
14
  /** The answers that mean "this app is not set up yet", which a first run can settle by wiring it. */
13
15
  const FIRST_RUN_ACTIONS = new Set([
14
16
  NoSessionAction.RUN_INIT,
@@ -46,18 +48,56 @@ export const EMPTY_SESSION_LIST_OUTPUT = {
46
48
  .optional()
47
49
  .describe('Present ONLY when `sessions` is empty AND a tab was connected to this daemon earlier: the last sessionId and URL that tab was on when it disappeared. A route that 500s tears the page down and the SDK never reconnects — this is the last thing we knew, not a route-500 verdict. An empty list with no lastKnown is a tab that never arrived.'),
48
50
  };
51
+ /**
52
+ * Wire the calling project when another project's tab is the one currently connected.
53
+ *
54
+ * The list handler only used to reach {@link emptySessionList} when the daemon's whole list was
55
+ * empty. A live tab in project A then answered project B's first call with A's sessions, and B
56
+ * was never wired.
57
+ */
58
+ export async function wireCallerBesideLiveSessions(deps, sessions) {
59
+ const dir = callingClientDirectory();
60
+ if (dir === undefined)
61
+ return undefined;
62
+ const projectId = readProjectId(dir);
63
+ if (projectId !== undefined && sessions.some((session) => session.projectId === projectId)) {
64
+ return undefined;
65
+ }
66
+ const next = deps.sessions.noSessionNextAction();
67
+ const target = next !== undefined && FIRST_RUN_ACTIONS.has(next.action)
68
+ ? deps.firstRun?.projectDirectory(dir)
69
+ : undefined;
70
+ if (target === undefined || deps.firstRun === undefined)
71
+ return undefined;
72
+ return deps.firstRun.wire(target);
73
+ }
74
+ /** The departed tab for this call: the caller's own project when it named one, else the daemon's newest. */
75
+ function departedForCaller(deps) {
76
+ const dir = callingClientDirectory();
77
+ if (dir === undefined)
78
+ return deps.sessions.lastKnown?.();
79
+ const projectId = readProjectId(dir);
80
+ if (projectId === undefined)
81
+ return undefined;
82
+ return deps.sessions.lastKnownFor?.(projectId);
83
+ }
49
84
  export async function emptySessionList(deps, sessions) {
50
- const why = deps.sessions.noSessionHint();
85
+ // The lead and its next action: the full differential (~3 KB of ranked causes) read as
86
+ // speculation on the call an agent makes first. Optional-call: test stubs predate the lead.
87
+ const why = deps.sessions.noSessionLead?.() ?? deps.sessions.noSessionHint();
51
88
  // The executable half. `why` is for the human reading the transcript; this is the one the
52
89
  // agent acts on, so it never has to parse a paragraph to find a command inside it.
53
90
  const next = deps.sessions.noSessionNextAction();
54
- // The first run wires the app, not the installation: the daemon runs init itself, once,
55
- // in its own project, and says what it changed. A daemon outside any project asks instead.
91
+ // The first run wires the app the client is in, not the directory the daemon was started in.
92
+ // One daemon serves every project; the proxy names its cwd on the call. With no caller (an
93
+ // embed, a test) it is still the daemon's own project. A daemon outside any project asks instead.
94
+ // ponytail: cwd, not an MCP roots/list round trip. A proxy started outside the project still
95
+ // answers run_init; roots are the upgrade when a client launches there but names the project.
56
96
  // Not only on `run_init`: an unwired app whose dev server is not running yet answers
57
97
  // `start_dev_server`, which is the commonest first run of all, and init starts that server itself.
58
98
  // `projectDirectory` refuses a project that is already wired, so a wired app is never re-run.
59
99
  const dir = next !== undefined && FIRST_RUN_ACTIONS.has(next.action)
60
- ? deps.firstRun?.projectDirectory(dirname(deps.reticleRoot))
100
+ ? deps.firstRun?.projectDirectory(callingClientDirectory() ?? dirname(deps.reticleRoot))
61
101
  : undefined;
62
102
  if (dir !== undefined && deps.firstRun !== undefined) {
63
103
  const wired = await deps.firstRun.wire(dir);
@@ -67,7 +107,7 @@ export async function emptySessionList(deps, sessions) {
67
107
  return { sessions, wired, ...(why === undefined ? {} : { why }) };
68
108
  }
69
109
  // The last tab, when one was here. Optional-call: test stubs of SessionManager predate it.
70
- const known = deps.sessions.lastKnown?.();
110
+ const known = departedForCaller(deps);
71
111
  const lastKnown = undefined === known ? undefined : { sessionId: known.id, url: known.url };
72
112
  return {
73
113
  sessions,
@@ -18,6 +18,7 @@ export declare const RECOVERY: {
18
18
  readonly MISSING_BASELINE: string;
19
19
  readonly MISSING_RECORDING: string;
20
20
  readonly STALE_REF: string;
21
+ readonly UNISSUED_REF: string;
21
22
  readonly STALE_REF_AFTER_EDIT: string;
22
23
  readonly INVALID_NAME: string;
23
24
  /**
@@ -78,6 +79,13 @@ export declare const RECOVERY: {
78
79
  * who deliberately switched the harness off gets a bug report filed about their own decision.
79
80
  */
80
81
  readonly HARNESS_OFF: string;
82
+ /**
83
+ * The Harness asked for on a project that is not linked to the platform. The call was valid, and
84
+ * the refusal names reticle_act_and_wait as the alternative, which the catch-all below read as an
85
+ * agent's malformed call: it was then told to fix arguments that were never wrong.
86
+ */
87
+ readonly HARNESS_LOCKED: string;
88
+ readonly HARNESS_NOT_LINKED: string;
81
89
  };
82
90
  /**
83
91
  * The actionable next move for a known error message, or undefined when none is recognized.