@reticlehq/server 3.7.0 → 3.8.1

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 (578) hide show
  1. package/SKILL.md +59 -68
  2. package/bin/reticle.js +9 -2
  3. package/dist/command/cli/adhoc-suite.js +1 -1
  4. package/dist/command/cli/adhoc-verdict.d.ts +12 -0
  5. package/dist/command/cli/adhoc-verdict.js +62 -4
  6. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  7. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  8. package/dist/command/cli/auth/cloud-session.d.ts +11 -19
  9. package/dist/command/cli/auth/cloud-session.js +23 -0
  10. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  11. package/dist/command/cli/cli-doctor.js +66 -21
  12. package/dist/command/cli/cli-flow-commands.js +53 -11
  13. package/dist/command/cli/cli-kill.d.ts +8 -0
  14. package/dist/command/cli/cli-kill.js +43 -3
  15. package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
  16. package/dist/command/cli/cli-parse-feedback.js +13 -1
  17. package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
  18. package/dist/command/cli/cli-parse-grammar.js +1 -6
  19. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  20. package/dist/command/cli/cli-parse-serve.js +124 -0
  21. package/dist/command/cli/cli-parse.d.ts +12 -11
  22. package/dist/command/cli/cli-parse.js +100 -123
  23. package/dist/command/cli/cli-usage.d.ts +0 -11
  24. package/dist/command/cli/cli-usage.js +43 -16
  25. package/dist/command/cli/cli-verify.d.ts +1 -1
  26. package/dist/command/cli/cli-verify.js +29 -14
  27. package/dist/command/cli/cloud-cli.js +27 -9
  28. package/dist/command/cli/cloud-kit.js +3 -3
  29. package/dist/command/cli/cloud-link.d.ts +1 -20
  30. package/dist/command/cli/cloud-link.js +2 -0
  31. package/dist/command/cli/cloud-login.d.ts +6 -2
  32. package/dist/command/cli/cloud-login.js +13 -41
  33. package/dist/command/cli/config/checkout.d.ts +10 -0
  34. package/dist/command/cli/config/checkout.js +78 -0
  35. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  36. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  37. package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
  38. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  39. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  40. package/dist/command/cli/drive/drive-attach.d.ts +5 -0
  41. package/dist/command/cli/drive/drive-attach.js +21 -1
  42. package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
  43. package/dist/command/cli/hook/codex-transcript.js +224 -0
  44. package/dist/command/cli/hook/episode-structure.d.ts +24 -0
  45. package/dist/command/cli/hook/episode-structure.js +138 -0
  46. package/dist/command/cli/hook/hook-command.d.ts +9 -0
  47. package/dist/command/cli/hook/hook-command.js +211 -0
  48. package/dist/command/cli/hook/hook-fast.d.ts +31 -0
  49. package/dist/command/cli/hook/hook-fast.js +136 -0
  50. package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
  51. package/dist/command/cli/hook/prompt-hook.js +199 -0
  52. package/dist/command/cli/hook/tool-hook.d.ts +21 -0
  53. package/dist/command/cli/hook/tool-hook.js +259 -0
  54. package/dist/command/cli/launch/cli-launch.d.ts +2 -0
  55. package/dist/command/cli/launch/cli-launch.js +22 -2
  56. package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
  57. package/dist/command/cli/mcp-command.d.ts +9 -0
  58. package/dist/command/cli/mcp-command.js +127 -41
  59. package/dist/command/cli/open-navigate.d.ts +43 -0
  60. package/dist/command/cli/open-navigate.js +85 -0
  61. package/dist/command/cli/ports/port-holder.d.ts +16 -4
  62. package/dist/command/cli/ports/port-holder.js +58 -12
  63. package/dist/command/cli/ports/resolve/cli-port.js +18 -2
  64. package/dist/command/cli/project-name.d.ts +1 -7
  65. package/dist/command/cli/project-name.js +1 -0
  66. package/dist/command/cli/report-command.d.ts +8 -2
  67. package/dist/command/cli/report-command.js +95 -18
  68. package/dist/command/cli/status-fields.d.ts +9 -2
  69. package/dist/command/cli/status-fields.js +148 -4
  70. package/dist/command/cli/try-command.d.ts +3 -4
  71. package/dist/command/cli/try-command.js +6 -11
  72. package/dist/command/cli/verify-results.d.ts +4 -1
  73. package/dist/command/cli/verify-results.js +3 -1
  74. package/dist/command/cli.d.ts +1 -7
  75. package/dist/command/cli.js +79 -160
  76. package/dist/command/daemon/daemon-resilience.d.ts +6 -1
  77. package/dist/command/daemon/daemon-resilience.js +31 -18
  78. package/dist/command/daemon/daemon.d.ts +11 -0
  79. package/dist/command/daemon/daemon.js +70 -2
  80. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
  81. package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
  82. package/dist/command/daemon/wake-decision.js +4 -2
  83. package/dist/command/daemon/win32-escape.d.ts +32 -0
  84. package/dist/command/daemon/win32-escape.js +119 -0
  85. package/dist/command/setup/agent-configs.d.ts +9 -0
  86. package/dist/command/setup/agent-configs.js +9 -0
  87. package/dist/command/setup/auto-approve.d.ts +10 -3
  88. package/dist/command/setup/auto-approve.js +51 -3
  89. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  90. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  91. package/dist/command/setup/bringup/ensure-daemon.js +4 -7
  92. package/dist/command/setup/init/init-host.js +6 -0
  93. package/dist/command/setup/init/init-port.js +5 -4
  94. package/dist/command/setup/init/init-runtime.js +7 -1
  95. package/dist/command/setup/node-effects.d.ts +8 -0
  96. package/dist/command/setup/node-effects.js +36 -4
  97. package/dist/command/setup/probe/dev-port.d.ts +26 -0
  98. package/dist/command/setup/probe/dev-port.js +117 -0
  99. package/dist/command/setup/probe/page-probe.d.ts +1 -1
  100. package/dist/command/setup/probe/page-probe.js +11 -3
  101. package/dist/command/setup/remaining-steps.d.ts +0 -7
  102. package/dist/command/setup/remaining-steps.js +3 -2
  103. package/dist/command/setup/run-setup.d.ts +11 -0
  104. package/dist/command/setup/run-setup.js +33 -5
  105. package/dist/command/setup/setup-command.d.ts +2 -0
  106. package/dist/command/setup/setup-command.js +22 -4
  107. package/dist/command/update/updater.d.ts +1 -6
  108. package/dist/command/update/updater.js +4 -5
  109. package/dist/command/update/version-seen.d.ts +24 -0
  110. package/dist/command/update/version-seen.js +65 -0
  111. package/dist/command/version/peer-announce.d.ts +9 -1
  112. package/dist/command/version/peer-announce.js +25 -2
  113. package/dist/command/version/sdk-fix.d.ts +5 -6
  114. package/dist/command/version/sdk-fix.js +17 -32
  115. package/dist/command/version/version-skew.d.ts +16 -1
  116. package/dist/command/version/version-skew.js +84 -10
  117. package/dist/features/crawl/crawl-tools.js +2 -2
  118. package/dist/features/crawl/crawl.js +2 -0
  119. package/dist/features/exhaust/ledger.d.ts +15 -96
  120. package/dist/features/exhaust/ledger.js +3 -3
  121. package/dist/features/harness/drive-runs.d.ts +28 -4
  122. package/dist/features/harness/drive-runs.js +99 -7
  123. package/dist/features/harness/drivers.d.ts +1 -1
  124. package/dist/features/harness/drivers.js +1 -1
  125. package/dist/features/harness/harness.d.ts +5 -0
  126. package/dist/features/harness/harness.js +24 -12
  127. package/dist/features/harness/platform/platform-drives.d.ts +7 -1
  128. package/dist/features/harness/platform/platform-drives.js +12 -7
  129. package/dist/features/harness/platform/refusal.d.ts +1 -1
  130. package/dist/features/harness/platform/refusal.js +4 -4
  131. package/dist/features/harness/platform/remote-drive.js +70 -28
  132. package/dist/features/harness/platform/server-driver.js +22 -1
  133. package/dist/features/harness/platform-config.d.ts +1 -10
  134. package/dist/features/harness/platform-config.js +0 -20
  135. package/dist/features/license/license.d.ts +2 -14
  136. package/dist/features/visual/step-shots.d.ts +33 -1
  137. package/dist/features/visual/step-shots.js +155 -1
  138. package/dist/features/visual/visual-tools.js +12 -4
  139. package/dist/hooks/coding-agents.d.ts +6 -0
  140. package/dist/hooks/coding-agents.js +24 -3
  141. package/dist/hooks/episode-stamp.d.ts +32 -0
  142. package/dist/hooks/episode-stamp.js +61 -0
  143. package/dist/hooks/hook-commands.js +19 -9
  144. package/dist/index.d.ts +5 -1
  145. package/dist/index.js +66 -24
  146. package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
  147. package/dist/judgement/app-graph/journal-steps.js +92 -0
  148. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  149. package/dist/judgement/domain/domain-model.js +1 -10
  150. package/dist/judgement/domain/domain-tools.js +4 -2
  151. package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
  152. package/dist/judgement/runs/artifact/run-store.js +153 -28
  153. package/dist/judgement/runs/default-run-id.d.ts +3 -1
  154. package/dist/judgement/runs/default-run-id.js +15 -3
  155. package/dist/judgement/runs/drive-run.d.ts +3 -3
  156. package/dist/judgement/runs/drive-run.js +11 -7
  157. package/dist/judgement/runs/run-ledger.d.ts +21 -0
  158. package/dist/judgement/runs/run-ledger.js +143 -0
  159. package/dist/judgement/runs/runner-port.d.ts +1 -1
  160. package/dist/judgement/runs/runner-port.js +8 -2
  161. package/dist/judgement/runs/verification-sync.d.ts +4 -3
  162. package/dist/judgement/runs/verification-sync.js +27 -5
  163. package/dist/language/flows/affected-tools.js +2 -1
  164. package/dist/language/flows/annotate-notes/annotate.js +8 -3
  165. package/dist/language/flows/annotate-tools.js +1 -1
  166. package/dist/language/flows/change/affected.d.ts +8 -0
  167. package/dist/language/flows/change/affected.js +20 -7
  168. package/dist/language/flows/decision.js +19 -4
  169. package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
  170. package/dist/language/flows/fields/flow-secret-field.js +67 -5
  171. package/dist/language/flows/flow-anchor.d.ts +5 -0
  172. package/dist/language/flows/flow-anchor.js +4 -0
  173. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  174. package/dist/language/flows/flow-cross-step.js +9 -0
  175. package/dist/language/flows/flow-expect-grammar.js +15 -10
  176. package/dist/language/flows/flow-intent.js +6 -1
  177. package/dist/language/flows/flow-journey.d.ts +8 -0
  178. package/dist/language/flows/flow-journey.js +13 -0
  179. package/dist/language/flows/flow-lease.d.ts +27 -0
  180. package/dist/language/flows/flow-lease.js +59 -0
  181. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  182. package/dist/language/flows/flow-replay-run.js +111 -310
  183. package/dist/language/flows/flow-replay.js +21 -19
  184. package/dist/language/flows/flow-replayable.d.ts +38 -0
  185. package/dist/language/flows/flow-replayable.js +179 -0
  186. package/dist/language/flows/flow-start-path.d.ts +108 -0
  187. package/dist/language/flows/flow-start-path.js +313 -0
  188. package/dist/language/flows/flow-step-runners.d.ts +23 -2
  189. package/dist/language/flows/flow-step-runners.js +191 -32
  190. package/dist/language/flows/flow-store-for-session.d.ts +8 -1
  191. package/dist/language/flows/flow-store-for-session.js +6 -0
  192. package/dist/language/flows/flow-tools.d.ts +2 -23
  193. package/dist/language/flows/flow-tools.js +63 -113
  194. package/dist/language/flows/flows.d.ts +4 -6
  195. package/dist/language/flows/flows.js +90 -15
  196. package/dist/language/flows/heal-run.d.ts +10 -4
  197. package/dist/language/flows/heal-run.js +26 -9
  198. package/dist/language/flows/recording/flake.d.ts +3 -27
  199. package/dist/language/flows/recording/flake.js +1 -1
  200. package/dist/language/flows/recording/recording-backtrack.js +1 -4
  201. package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
  202. package/dist/language/flows/recording/tape/recordings.js +9 -3
  203. package/dist/language/flows/replay.d.ts +25 -5
  204. package/dist/language/flows/replay.js +83 -16
  205. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  206. package/dist/language/flows/suite/coverage.d.ts +9 -0
  207. package/dist/language/flows/suite/coverage.js +12 -1
  208. package/dist/language/flows/suite-selection.d.ts +25 -0
  209. package/dist/language/flows/suite-selection.js +41 -9
  210. package/dist/machine/git-tracks.d.ts +6 -0
  211. package/dist/machine/git-tracks.js +36 -0
  212. package/dist/memory/cloud/background-sync.d.ts +25 -0
  213. package/dist/memory/cloud/background-sync.js +79 -0
  214. package/dist/memory/cloud/cloud-config.d.ts +12 -1
  215. package/dist/memory/cloud/cloud-config.js +39 -13
  216. package/dist/memory/cloud/cloud-sync.d.ts +3 -24
  217. package/dist/memory/cloud/cloud-sync.js +5 -2
  218. package/dist/memory/cloud/harness-config.d.ts +0 -7
  219. package/dist/memory/cloud/memory-scope.d.ts +19 -0
  220. package/dist/memory/cloud/memory-scope.js +48 -0
  221. package/dist/memory/cloud/sync-answer.d.ts +43 -0
  222. package/dist/memory/cloud/sync-answer.js +42 -0
  223. package/dist/memory/cloud/sync-cycle.d.ts +40 -10
  224. package/dist/memory/cloud/sync-cycle.js +97 -144
  225. package/dist/memory/cloud/sync-daemon.d.ts +50 -3
  226. package/dist/memory/cloud/sync-daemon.js +473 -83
  227. package/dist/memory/cloud/sync-describe.d.ts +28 -0
  228. package/dist/memory/cloud/sync-describe.js +92 -0
  229. package/dist/memory/cloud/sync-disk.d.ts +9 -1
  230. package/dist/memory/cloud/sync-disk.js +137 -33
  231. package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
  232. package/dist/memory/cloud/sync-flow-versions.js +42 -0
  233. package/dist/memory/impact/impact-store.js +32 -15
  234. package/dist/memory/intent/intent-shard.d.ts +41 -266
  235. package/dist/memory/intent/intent-tools.js +20 -61
  236. package/dist/memory/intent/record-request.d.ts +27 -0
  237. package/dist/memory/intent/record-request.js +88 -0
  238. package/dist/memory/intent/settled-words.js +9 -1
  239. package/dist/memory/journal/drive-flow.d.ts +3 -0
  240. package/dist/memory/journal/drive-flow.js +11 -41
  241. package/dist/memory/journal/envelope-store.js +1 -1
  242. package/dist/memory/journal/envelope.d.ts +6 -154
  243. package/dist/memory/journal/episode-log.d.ts +107 -0
  244. package/dist/memory/journal/episode-log.js +302 -0
  245. package/dist/memory/journal/journal-recorder.d.ts +7 -0
  246. package/dist/memory/journal/journal-recorder.js +22 -9
  247. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  248. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  249. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
  250. package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
  251. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
  252. package/dist/memory/journal/self-observation.js +3 -1
  253. package/dist/memory/journal/session-end.js +23 -9
  254. package/dist/memory/journal/session-journal.js +39 -20
  255. package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
  256. package/dist/memory/project/artifact-root-resolver.js +68 -23
  257. package/dist/memory/project/artifact-root.d.ts +17 -3
  258. package/dist/memory/project/artifact-root.js +47 -9
  259. package/dist/memory/project/fs/fs-port.d.ts +5 -0
  260. package/dist/memory/project/fs/fs-port.js +13 -0
  261. package/dist/memory/project/learned-routes.d.ts +3 -4
  262. package/dist/memory/project/learned-routes.js +3 -11
  263. package/dist/memory/project/link-directory.js +5 -2
  264. package/dist/memory/project/root-claims.d.ts +3 -1
  265. package/dist/memory/project/root-claims.js +41 -7
  266. package/dist/memory/project/session-root.d.ts +1 -1
  267. package/dist/memory/project/session-root.js +1 -15
  268. package/dist/memory/project/sync-status.js +5 -6
  269. package/dist/memory/recall/memory-tools.js +2 -2
  270. package/dist/memory/recall/platform-memory.d.ts +3 -1
  271. package/dist/memory/recall/platform-memory.js +9 -1
  272. package/dist/memory/recall/project-memory.js +15 -19
  273. package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
  274. package/dist/portal/bridge/auth-failure-reason.js +19 -0
  275. package/dist/portal/bridge/bridge.d.ts +19 -4
  276. package/dist/portal/bridge/bridge.js +150 -177
  277. package/dist/portal/bridge/harness-request.d.ts +15 -0
  278. package/dist/portal/bridge/harness-request.js +19 -0
  279. package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
  280. package/dist/portal/bridge/origin/origin-follow.js +110 -0
  281. package/dist/portal/bridge/pairing-token.d.ts +6 -0
  282. package/dist/portal/bridge/pairing-token.js +47 -16
  283. package/dist/portal/bridge/protocol-skew.d.ts +27 -2
  284. package/dist/portal/bridge/protocol-skew.js +66 -2
  285. package/dist/portal/bridge/session-nonces.d.ts +46 -0
  286. package/dist/portal/bridge/session-nonces.js +72 -0
  287. package/dist/portal/input/viewport-tools.d.ts +31 -0
  288. package/dist/portal/input/viewport-tools.js +106 -15
  289. package/dist/portal/pool/bounded-close.d.ts +23 -0
  290. package/dist/portal/pool/bounded-close.js +38 -0
  291. package/dist/portal/pool/browser-pool.d.ts +44 -39
  292. package/dist/portal/pool/browser-pool.js +247 -95
  293. package/dist/portal/pool/context-permissions.d.ts +9 -1
  294. package/dist/portal/pool/context-permissions.js +26 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +37 -0
  296. package/dist/portal/pool/lease-emulation.js +29 -0
  297. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  298. package/dist/portal/pool/playwright-launcher.js +74 -7
  299. package/dist/portal/pool/pool-contract.d.ts +23 -1
  300. package/dist/portal/pool/pool-lease.d.ts +128 -0
  301. package/dist/portal/pool/pool-lease.js +49 -0
  302. package/dist/portal/pool/zero-install.d.ts +8 -1
  303. package/dist/portal/pool/zero-install.js +24 -2
  304. package/dist/portal/production/production-activation.d.ts +136 -0
  305. package/dist/portal/production/production-activation.js +173 -0
  306. package/dist/portal/production/production-drive.d.ts +52 -0
  307. package/dist/portal/production/production-drive.js +301 -0
  308. package/dist/portal/production/production-hello.d.ts +23 -0
  309. package/dist/portal/production/production-hello.js +23 -0
  310. package/dist/portal/realm/web-realm.js +42 -15
  311. package/dist/portal/session/control-envelope.d.ts +1 -1
  312. package/dist/portal/session/dev-server/served-document.d.ts +0 -5
  313. package/dist/portal/session/dev-server/served-document.js +6 -8
  314. package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
  315. package/dist/portal/session/first-run-wiring.d.ts +3 -36
  316. package/dist/portal/session/first-run-wiring.js +10 -103
  317. package/dist/portal/session/live-control-tools.js +61 -19
  318. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  319. package/dist/portal/session/no-session-next-action.js +40 -15
  320. package/dist/portal/session/no-session-watch.d.ts +7 -0
  321. package/dist/portal/session/no-session-watch.js +67 -23
  322. package/dist/portal/session/output-budget.d.ts +10 -0
  323. package/dist/portal/session/output-budget.js +16 -0
  324. package/dist/portal/session/presence/session-lease.d.ts +2 -0
  325. package/dist/portal/session/presence/session-lease.js +8 -0
  326. package/dist/portal/session/recorded-gaps.d.ts +15 -11
  327. package/dist/portal/session/recorded-gaps.js +39 -18
  328. package/dist/portal/session/serving-directory.d.ts +24 -2
  329. package/dist/portal/session/serving-directory.js +93 -5
  330. package/dist/portal/session/session-info.d.ts +26 -0
  331. package/dist/portal/session/session-info.js +20 -0
  332. package/dist/portal/session/session-manager.d.ts +35 -3
  333. package/dist/portal/session/session-manager.js +69 -14
  334. package/dist/portal/session/session-successor.js +1 -9
  335. package/dist/portal/session/session-tools.js +22 -4
  336. package/dist/portal/session/session.d.ts +10 -10
  337. package/dist/portal/session/session.js +37 -29
  338. package/dist/portal/session/zero-install-first-call.d.ts +7 -2
  339. package/dist/portal/session/zero-install-first-call.js +43 -20
  340. package/dist/start-wiring.d.ts +2 -2
  341. package/dist/start-wiring.js +17 -3
  342. package/dist/status-payload.d.ts +11 -1
  343. package/dist/status-payload.js +7 -1
  344. package/dist/surface/agent-presence-grace.d.ts +11 -0
  345. package/dist/surface/agent-presence-grace.js +34 -0
  346. package/dist/surface/http-server.d.ts +12 -1
  347. package/dist/surface/http-server.js +64 -15
  348. package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
  349. package/dist/surface/mcp/faults/mcp-outage.js +19 -1
  350. package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
  351. package/dist/surface/mcp/mcp-proxy.js +194 -267
  352. package/dist/surface/mcp/mcp.d.ts +20 -3
  353. package/dist/surface/mcp/mcp.js +88 -25
  354. package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
  355. package/dist/surface/mcp/proxy/drive-calls.js +114 -5
  356. package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
  357. package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
  358. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
  359. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
  360. package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
  361. package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
  362. package/dist/surface/mcp/server-instructions.js +35 -16
  363. package/dist/surface/mcp/shared-params.d.ts +8 -0
  364. package/dist/surface/mcp/shared-params.js +15 -1
  365. package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
  366. package/dist/surface/mcp/sse-frame-parser.js +18 -0
  367. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  368. package/dist/surface/mcp/surface-vocabulary.js +13 -0
  369. package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
  370. package/dist/surface/mcp/tool-catalog-cache.js +14 -4
  371. package/dist/surface/tools/account-tool.d.ts +4 -3
  372. package/dist/surface/tools/account-tool.js +20 -31
  373. package/dist/surface/tools/act/act-danger.d.ts +2 -0
  374. package/dist/surface/tools/act/act-danger.js +41 -14
  375. package/dist/surface/tools/act/act-observation.d.ts +11 -0
  376. package/dist/surface/tools/act/act-observation.js +33 -0
  377. package/dist/surface/tools/act/act-preflight.js +10 -3
  378. package/dist/surface/tools/act/act-sequence-retry.js +2 -1
  379. package/dist/surface/tools/act/act-target.js +19 -5
  380. package/dist/surface/tools/act/durable.js +1 -1
  381. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
  382. package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
  383. package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
  384. package/dist/surface/tools/act/unsettled-find.js +71 -0
  385. package/dist/surface/tools/act-sequence-tool.js +53 -24
  386. package/dist/surface/tools/act-tools.d.ts +2 -3
  387. package/dist/surface/tools/act-tools.js +49 -47
  388. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  389. package/dist/surface/tools/agent/for-the-agent.js +41 -3
  390. package/dist/surface/tools/assert/assert-grade.js +8 -3
  391. package/dist/surface/tools/assert/assert-verdict.js +4 -2
  392. package/dist/surface/tools/browser-tools.js +7 -4
  393. package/dist/surface/tools/chat-drives.js +50 -25
  394. package/dist/surface/tools/coverage-tools.js +1 -1
  395. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  396. package/dist/surface/tools/dynamic-tools.js +89 -34
  397. package/dist/surface/tools/empty-session-list.d.ts +18 -25
  398. package/dist/surface/tools/empty-session-list.js +67 -38
  399. package/dist/surface/tools/error-recovery.d.ts +17 -7
  400. package/dist/surface/tools/error-recovery.js +53 -20
  401. package/dist/surface/tools/explore-tools.d.ts +10 -0
  402. package/dist/surface/tools/explore-tools.js +72 -19
  403. package/dist/surface/tools/feedback-tools.js +23 -2
  404. package/dist/surface/tools/gap-novelty.d.ts +6 -0
  405. package/dist/surface/tools/gap-novelty.js +9 -0
  406. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  407. package/dist/surface/tools/harness-explore.d.ts +1 -1
  408. package/dist/surface/tools/harness-explore.js +6 -4
  409. package/dist/surface/tools/harness-gate.d.ts +43 -21
  410. package/dist/surface/tools/harness-gate.js +55 -81
  411. package/dist/surface/tools/harness-script.d.ts +2 -0
  412. package/dist/surface/tools/harness-script.js +11 -6
  413. package/dist/surface/tools/harness-toolset.js +3 -4
  414. package/dist/surface/tools/invoke-tool.d.ts +0 -8
  415. package/dist/surface/tools/invoke-tool.js +164 -178
  416. package/dist/surface/tools/lease-hint.d.ts +9 -0
  417. package/dist/surface/tools/lease-hint.js +22 -3
  418. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  419. package/dist/surface/tools/lease-readiness.d.ts +55 -0
  420. package/dist/surface/tools/lease-readiness.js +150 -2
  421. package/dist/surface/tools/lease-tools.d.ts +3 -75
  422. package/dist/surface/tools/lease-tools.js +124 -188
  423. package/dist/surface/tools/map-tools.d.ts +20 -0
  424. package/dist/surface/tools/map-tools.js +145 -0
  425. package/dist/surface/tools/merge-tools.js +11 -7
  426. package/dist/surface/tools/next-step.js +6 -3
  427. package/dist/surface/tools/observe-tools.js +46 -35
  428. package/dist/surface/tools/platform-moment.d.ts +3 -12
  429. package/dist/surface/tools/platform-moment.js +12 -24
  430. package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
  431. package/dist/surface/tools/read/complete-snapshot.js +13 -2
  432. package/dist/surface/tools/read/query-paginate.js +6 -0
  433. package/dist/surface/tools/read/query-shape.d.ts +9 -0
  434. package/dist/surface/tools/read/query-shape.js +15 -0
  435. package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
  436. package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
  437. package/dist/surface/tools/read-tools.js +5 -5
  438. package/dist/surface/tools/real-input-attempt.d.ts +11 -0
  439. package/dist/surface/tools/real-input-attempt.js +206 -38
  440. package/dist/surface/tools/reconcile-tools.js +21 -8
  441. package/dist/surface/tools/reticle-result.d.ts +3 -0
  442. package/dist/surface/tools/reticle-result.js +8 -1
  443. package/dist/surface/tools/run-report.d.ts +22 -0
  444. package/dist/surface/tools/run-report.js +141 -0
  445. package/dist/surface/tools/session-ports.d.ts +57 -0
  446. package/dist/surface/tools/session-ports.js +102 -0
  447. package/dist/surface/tools/tool-kit.d.ts +58 -4
  448. package/dist/surface/tools/tool-kit.js +140 -6
  449. package/dist/surface/tools/tool-surface.d.ts +2 -0
  450. package/dist/surface/tools/tool-surface.js +45 -0
  451. package/dist/surface/tools/tools.js +49 -87
  452. package/dist/telemetry/automation-hint.d.ts +5 -0
  453. package/dist/telemetry/automation-hint.js +7 -0
  454. package/dist/telemetry/cli-telemetry.d.ts +22 -0
  455. package/dist/telemetry/cli-telemetry.js +80 -11
  456. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  457. package/dist/telemetry/daemon-telemetry.js +9 -2
  458. package/dist/telemetry/feedback-cli.d.ts +1 -1
  459. package/dist/telemetry/feedback-cli.js +8 -3
  460. package/dist/telemetry/feedback.d.ts +1 -1
  461. package/dist/telemetry/feedback.js +51 -4
  462. package/dist/telemetry/harness-run.d.ts +3 -3
  463. package/dist/telemetry/harness-run.js +18 -7
  464. package/dist/telemetry/hud-events.d.ts +1 -1
  465. package/dist/telemetry/hud-metrics.d.ts +6 -3
  466. package/dist/telemetry/hud-metrics.js +20 -8
  467. package/dist/telemetry/install-source.js +1 -1
  468. package/dist/telemetry/mcp-connection.d.ts +1 -1
  469. package/dist/telemetry/mcp-connection.js +21 -2
  470. package/dist/telemetry/onboarding-firsts.d.ts +6 -1
  471. package/dist/telemetry/onboarding-firsts.js +41 -1
  472. package/dist/telemetry/proxy-telemetry.d.ts +42 -0
  473. package/dist/telemetry/proxy-telemetry.js +70 -1
  474. package/dist/telemetry/session-metrics.d.ts +1 -3
  475. package/dist/telemetry/session-metrics.js +16 -12
  476. package/dist/telemetry/telemetry.d.ts +9 -1
  477. package/dist/telemetry/telemetry.js +16 -1
  478. package/dist/telemetry/verification-of.d.ts +3 -1
  479. package/dist/telemetry/verification-of.js +7 -1
  480. package/dist/wire-journal.js +12 -2
  481. package/docs/README.md +4 -2
  482. package/docs/actions.mdx +7 -6
  483. package/docs/adapters.md +2 -1
  484. package/docs/agent-cheatsheet.md +19 -5
  485. package/docs/architecture.md +13 -10
  486. package/docs/autodrive.md +6 -5
  487. package/docs/benchmarks.md +2 -2
  488. package/docs/capabilities.mdx +1 -1
  489. package/docs/cli/affected.mdx +1 -1
  490. package/docs/cli/cloud.mdx +6 -6
  491. package/docs/cli/doctor.mdx +3 -1
  492. package/docs/cli/feedback.mdx +11 -7
  493. package/docs/cli/gate.mdx +1 -1
  494. package/docs/cli/help.mdx +1 -1
  495. package/docs/cli/init.mdx +20 -16
  496. package/docs/cli/mcp.mdx +5 -2
  497. package/docs/cli/open.mdx +5 -2
  498. package/docs/cli/report.mdx +1 -1
  499. package/docs/cli/restart.mdx +1 -1
  500. package/docs/cli/rollback.mdx +4 -4
  501. package/docs/cli/serve.mdx +7 -5
  502. package/docs/cli/setup.mdx +1 -1
  503. package/docs/cli/status.mdx +6 -2
  504. package/docs/cli/stop.mdx +3 -3
  505. package/docs/cli/telemetry.mdx +5 -1
  506. package/docs/cli/try.mdx +8 -8
  507. package/docs/cli/update.mdx +8 -5
  508. package/docs/cli/verify.mdx +12 -5
  509. package/docs/cli/version.mdx +1 -1
  510. package/docs/cli.mdx +10 -6
  511. package/docs/debugging.md +1 -1
  512. package/docs/deploy-checks.md +8 -6
  513. package/docs/desktop.mdx +14 -18
  514. package/docs/enterprise.md +6 -6
  515. package/docs/environment.mdx +5 -3
  516. package/docs/faq.mdx +9 -6
  517. package/docs/first-drive.md +19 -9
  518. package/docs/flows.md +3 -4
  519. package/docs/for-agents.md +1 -1
  520. package/docs/frameworks.mdx +34 -11
  521. package/docs/getting-started.md +46 -29
  522. package/docs/http-transport.md +2 -2
  523. package/docs/human-control.md +8 -8
  524. package/docs/index.mdx +2 -2
  525. package/docs/install-agentic.mdx +18 -19
  526. package/docs/install-manual.mdx +8 -4
  527. package/docs/integration-patterns.md +5 -5
  528. package/docs/multi-agent-testing.md +7 -5
  529. package/docs/packages/browser.mdx +34 -2
  530. package/docs/packages/core.mdx +2 -1
  531. package/docs/packages/electron.mdx +15 -3
  532. package/docs/packages/eslint-plugin.mdx +1 -1
  533. package/docs/packages/next.mdx +17 -5
  534. package/docs/packages/react.mdx +8 -1
  535. package/docs/packages/server.mdx +3 -3
  536. package/docs/packages/tauri.mdx +3 -3
  537. package/docs/packages/vite-plugin.mdx +1 -1
  538. package/docs/packages.mdx +19 -6
  539. package/docs/platform-integration.md +12 -4
  540. package/docs/predicates.mdx +18 -7
  541. package/docs/production-mode.md +108 -0
  542. package/docs/prompt-capture.md +99 -0
  543. package/docs/quickstart.mdx +14 -12
  544. package/docs/recipes.mdx +9 -8
  545. package/docs/required-checks.md +3 -2
  546. package/docs/skill-file.mdx +4 -3
  547. package/docs/skill-setup.md +2 -2
  548. package/docs/skill.md +62 -70
  549. package/docs/state-files.md +1 -0
  550. package/docs/state-management.mdx +11 -9
  551. package/docs/system-map.md +14 -13
  552. package/docs/telemetry.md +32 -24
  553. package/docs/testing.md +9 -5
  554. package/docs/tools/act-and-wait.mdx +17 -13
  555. package/docs/tools/act-sequence.mdx +40 -66
  556. package/docs/tools/act.mdx +7 -5
  557. package/docs/tools/assert.mdx +1 -1
  558. package/docs/tools/look.mdx +1 -1
  559. package/docs/tools/navigate.mdx +1 -1
  560. package/docs/tools/network.mdx +13 -11
  561. package/docs/tools/overview.mdx +3 -3
  562. package/docs/tools/query.mdx +3 -3
  563. package/docs/tools/session-and-feedback.mdx +9 -6
  564. package/docs/tools/sessions.mdx +7 -0
  565. package/docs/tools/snapshot.mdx +9 -7
  566. package/docs/tools/tools-and-run.mdx +11 -10
  567. package/docs/tools/verify.mdx +1 -1
  568. package/docs/troubleshooting.mdx +21 -9
  569. package/docs/usage.md +58 -43
  570. package/docs/use-cases.mdx +2 -2
  571. package/docs/vs-chrome-devtools-mcp.mdx +5 -5
  572. package/docs/vs-playwright-mcp.mdx +5 -4
  573. package/docs/what-is-recorded.md +12 -7
  574. package/docs/what-is-reticle.mdx +2 -2
  575. package/docs/why-reticle.mdx +1 -1
  576. package/package.json +9 -12
  577. package/dist/command/dev/stale-issue-guard.d.ts +0 -34
  578. package/dist/command/dev/stale-issue-guard.js +0 -69
@@ -1,3 +1,4 @@
1
+ import { noteOwnReload, notePageLoaded } from '../../features/harness/drive-runs.js';
1
2
  import { asProjectId } from '@reticlehq/core';
2
3
  import { narrationArgs } from './narration-args.js';
3
4
  import { refusedResult } from './page-commands/undeclared-command.js';
@@ -15,7 +16,7 @@ const IMPACT_PUSH_DEBOUNCE_MS = 700;
15
16
  import { PendingCommands, CommandTimeoutError } from './page-commands/pending-commands.js';
16
17
  import { span } from '../../trace.js';
17
18
  import { keepCallerContextInDaemon, noteToDaemonLog } from './daemon-answers.js';
18
- import { isKnownRealm, EventType, HumanControlDataSchema, HumanControlKind, HumanMarkDataSchema, HudUseDataSchema, ReticleCommand, parseEventPayload, PresenterTone, SESSION_HEALTH, SESSION_LEASE, SESSION_LIFECYCLE, SessionState, } from '@reticlehq/core';
19
+ import { isKnownRealm, EventType, HumanControlDataSchema, HumanControlKind, HumanMarkDataSchema, HudUseDataSchema, ReticleCommand, parseEventPayload, PresenterTone, SESSION_HEALTH, SESSION_LIFECYCLE, SessionState, } from '@reticlehq/core';
19
20
  import { RingBuffer } from '@reticlehq/engine/window/ring-buffer.js';
20
21
  import { readJournalWriteLoss, readQueryEvents, windowLost, } from '../../memory/journal/journal-query.js';
21
22
  import {} from '@reticlehq/engine/window/ambient.js';
@@ -28,6 +29,7 @@ import { ReviewStore } from './human/review-store.js';
28
29
  import { buildSessionRecommendation } from './presence/session-recommendation.js';
29
30
  import { buildPresenterArgs } from './human/presenter-args.js';
30
31
  import { buildSessionLease } from './presence/session-lease.js';
32
+ import { sessionAgeWarning } from './presence/session-lease.js';
31
33
  import { buildSessionInfo } from './session-info.js';
32
34
  import { notedAct, probeMarkers, withInstrumentation } from './recorded-gaps.js';
33
35
  import { MAX_SUCCESSOR_HOPS, REBINDABLE_COMMANDS } from './rebind.js';
@@ -56,31 +58,36 @@ export class Session {
56
58
  * MINTED HERE. This is one of the two places a projectId enters the daemon with its provenance
57
59
  * intact: the field is `projectId` on a zod-parsed HELLO, so the page said what it is. Every
58
60
  * downstream reader takes the brand from this property rather than re-blessing a string.
61
+ * Set once more, by `adoptProject`, when a page that said nothing names its project later.
59
62
  */
60
63
  projectId;
64
+ /** Take a later HELLO's project id when the first carried none. A set project is kept. */
65
+ adoptProject(projectId) {
66
+ if (this.projectId !== undefined)
67
+ return false;
68
+ this.projectId = asProjectId(projectId);
69
+ return true;
70
+ }
61
71
  /**
62
72
  * The `.reticle` directory this session's evidence belongs in — impact counters AND capsules.
63
73
  * Stamped once, from the project it declared in HELLO, so every counter agrees where it goes.
64
74
  * Undefined when nothing could name a project: callers fall back to the daemon's own root.
65
75
  */
66
76
  artifactRoot;
67
- /**
68
- * Same-origin endpoints this session's project declared as background (`.reticle.json`
69
- * `background`). Stamped with `artifactRoot`, from the same project. Empty excludes nothing.
70
- */
77
+ /** Same-origin `background` endpoints of this session's project, stamped with `artifactRoot`. */
71
78
  background = [];
72
79
  url;
73
80
  title;
74
81
  adapters;
75
82
  hasCapabilities;
76
- // What the page said about itself at HELLO. `HandshakeFacts` holds the reasoning, including
77
- // the rule that `undefined` means "too old to say" and never "no".
83
+ // What the page said at HELLO. `HandshakeFacts` holds the reasoning (`undefined` is never "no").
78
84
  versionSkew;
79
85
  sdkVersion;
80
86
  captureBodies;
81
87
  channels;
82
88
  commands;
83
89
  sourceMapping;
90
+ instrumentation;
84
91
  redactKeys;
85
92
  #socket;
86
93
  #clock;
@@ -134,6 +141,8 @@ export class Session {
134
141
  */
135
142
  #editEpoch;
136
143
  #departureNote = new DepartureNote();
144
+ /** Set when a production nonce opened this session: every act then passes the production policy. */
145
+ production;
137
146
  constructor(hello, socket, clock) {
138
147
  this.id = hello.sessionId;
139
148
  this.projectId = hello.projectId === undefined ? undefined : asProjectId(hello.projectId);
@@ -142,6 +151,7 @@ export class Session {
142
151
  this.adapters = hello.adapters;
143
152
  this.hasCapabilities = hello.hasCapabilities ?? false;
144
153
  this.sourceMapping = hello.sourceMapping;
154
+ this.instrumentation = hello.instrumentation;
145
155
  this.redactKeys = hello.redactKeys ?? [];
146
156
  this.#socket = socket;
147
157
  this.#clock = clock;
@@ -233,6 +243,7 @@ export class Session {
233
243
  hasCapabilities: this.hasCapabilities,
234
244
  runtime: this.#runtime,
235
245
  versionSkew: this.versionSkew,
246
+ sdkVersion: this.sdkVersion,
236
247
  hidden: this.#hidden,
237
248
  page: this.page,
238
249
  health: () => this.health(),
@@ -288,6 +299,7 @@ export class Session {
288
299
  }
289
300
  if (event.documentId !== undefined)
290
301
  this.#documentId = event.documentId;
302
+ notePageLoaded(this.id, event, this.#clock());
291
303
  if (event.editEpoch !== undefined)
292
304
  this.#editEpoch = event.editEpoch;
293
305
  if (event.type === EventType.PAGE_HEALTH) {
@@ -555,15 +567,19 @@ export class Session {
555
567
  }
556
568
  /** Send a command to the browser and await its reply (or time out). */
557
569
  command(name, args = {}, timeoutMs = DEFAULT_COMMAND_TIMEOUT_MS) {
558
- // Recorded HERE rather than at the tool call sites: this is the one place every driven action
559
- // passes through, so act_sequence and flow replay count too. Doing it per-tool missed both, and
560
- // an under-counted "exercised" reports worse coverage than reality — the safe direction, but
561
- // still wrong, and it made the number depend on which tool the agent happened to use.
562
- if (name === ReticleCommand.ACT) {
563
- const ref = args['ref'];
564
- if ('string' === typeof ref)
565
- this.recordActedRef(ref);
566
- }
570
+ // The production policy decides here, where every driven action passes, and never in the page.
571
+ if (this.production === undefined)
572
+ return this.#dispatch(name, args, timeoutMs);
573
+ return this.production.gate(name, args, (n, a) => this.#dispatch(n, a, timeoutMs));
574
+ }
575
+ #dispatch(name, args, ms) {
576
+ // Recorded here, where every driven action passes (act_sequence and flow replay too). A reload
577
+ // sent from here is ours, so the page coming back is not a person reloading mid-drive.
578
+ const ref = args['ref'];
579
+ if (name === ReticleCommand.ACT && 'string' === typeof ref)
580
+ this.recordActedRef(ref);
581
+ if (name === ReticleCommand.REFRESH)
582
+ noteOwnReload(this.id, this.#clock());
567
583
  // Refused before it is sent, when the page said it does not serve this. The rule, and why
568
584
  // an absent declaration is not an empty list, live in `undeclared-command.ts`.
569
585
  const refused = refusedResult(name, this.commands, `${COMMAND_ID_PREFIX}refused`);
@@ -574,12 +590,12 @@ export class Session {
574
590
  // have made itself after a `reticle_sessions` round trip, minus the round trip.
575
591
  const successor = this.#liveSuccessor();
576
592
  if (successor !== undefined)
577
- return successor.command(name, args, timeoutMs);
593
+ return successor.command(name, args, ms);
578
594
  const id = this.#pending.nextId(COMMAND_ID_PREFIX);
579
595
  const payload = commandPayload(id, this.id, name, args);
580
596
  // The timeout message is built LAZILY: health can change while a command is in flight, and the
581
597
  // diagnosis should describe the page as it was when the command actually gave up.
582
- const awaited = this.#pending.track(id, timeoutMs, () => commandTimeoutMessage(name, timeoutMs, {
598
+ const awaited = this.#pending.track(id, ms, () => commandTimeoutMessage(name, ms, {
583
599
  url: this.url,
584
600
  hidden: this.#hidden,
585
601
  lastSeenMs: this.lastSeenMs(),
@@ -617,7 +633,7 @@ export class Session {
617
633
  // timeout means a caller who granted 8s can wait 16, and across a chain of replacements the
618
634
  // total is unbounded — a wait nobody asked for, on the path that exists to save a round trip.
619
635
  // A budget already spent means there is nothing left to retry into, so the error stands.
620
- const remaining = timeoutMs - (Date.now() - sentAt);
636
+ const remaining = ms - (Date.now() - sentAt);
621
637
  if (remaining <= 0)
622
638
  throw error;
623
639
  return next.command(name, args, remaining);
@@ -806,17 +822,9 @@ export class Session {
806
822
  this.#firstCommandDone = true;
807
823
  return buildSessionLease(this.id, this.#startedAt);
808
824
  }
809
- /**
810
- * Returns a human-readable age warning after SESSION_LEASE.WARN_AFTER_MS (10 min), else undefined.
811
- * Spliced onto every session-bound tool result so the agent is passively reminded to clean up
812
- * without needing an explicit polling loop.
813
- */
825
+ /** The age reminder spliced onto session-bound results, so the agent cleans up without polling. */
814
826
  ageWarning() {
815
- const ageMs = this.#clock() - this.#startedAt;
816
- if (ageMs < SESSION_LEASE.WARN_AFTER_MS)
817
- return undefined;
818
- const minutes = Math.floor(ageMs / 60_000);
819
- return `Session ${this.id} has been open for ${String(minutes)} minutes. If your task is complete, call reticle_session{action:"end"} now.`;
827
+ return sessionAgeWarning(this.id, this.#clock() - this.#startedAt);
820
828
  }
821
829
  /**
822
830
  * The tabs that should SEE what this session is told, supplied by the SessionManager.
@@ -16,16 +16,21 @@ export interface FirstCallOpened {
16
16
  /** One line for the agent: what was opened, what it cannot see, and how to wire it for good. */
17
17
  notice: string;
18
18
  }
19
+ /** Compared both as written and with links resolved: either spelling may be the one lsof used. */
20
+ export declare function within(child: string | undefined, parent: string): boolean;
21
+ /** The caller's running app, for a lease that names no url. */
22
+ export declare function projectAppUrlFinder(io: Pick<FirstCallIo, 'project' | 'serving' | 'servingDirectory'>): () => Promise<string | undefined>;
19
23
  /** One lease per project for the daemon's life: a failure is reported once, never retried. */
20
24
  export declare function firstCallOpener(io: FirstCallIo): () => Promise<FirstCallOpened | undefined>;
21
25
  /**
22
26
  * The daemon's two answers to an app nobody wired, built together because both ask the same
23
- * question first — which unwired web app is this caller in. `firstRun` wires it when the agent
27
+ * question first — which unwired web app is this caller in. `firstRun` names it when the agent
24
28
  * lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call.
25
29
  */
26
- export declare function agentWiring(port: number, sessions: {
30
+ export declare function agentWiring(sessions: {
27
31
  list(): readonly unknown[];
28
32
  }, lease: (url: string) => Promise<unknown>): {
29
33
  firstRun: FirstRunWiring;
30
34
  openUnwiredApp: () => Promise<FirstCallOpened | undefined>;
35
+ projectAppUrl: () => Promise<string | undefined>;
31
36
  };
@@ -11,8 +11,9 @@
11
11
  * browser opened on another repo's app produces a confident verdict about code nobody touched. It
12
12
  * changes nothing in the repo — wiring it for good stays the agent's call, named in the notice.
13
13
  *
14
- * Where the serving process cannot be observed (no `lsof`, so Windows) nothing is opened and the
15
- * no-session answer names the lease and the init command instead.
14
+ * Where the serving process cannot be observed nothing is opened, and the no-session answer names
15
+ * the lease and the init command instead. On Windows the lookup reads the listener's command line
16
+ * (see `findListenerCwd`), so a dev server run from the project's `node_modules` counts.
16
17
  */
17
18
  import { realpathSync } from 'node:fs';
18
19
  import { resolve, sep } from 'node:path';
@@ -21,6 +22,7 @@ import { callingClientDirectory } from '../../hooks/client-directory.js';
21
22
  import { detectDevCommandInProject, initCommandIn } from './dev-server/dev-command.js';
22
23
  import { probeDevServerStates } from './dev-server/dev-server-probe.js';
23
24
  import { firstRunWiring } from './first-run-wiring.js';
25
+ import { wiringConsent } from './no-session-next-action.js';
24
26
  import { servingDirectoryOf } from './serving-directory.js';
25
27
  const LOCALHOST = 'http://localhost';
26
28
  /** The path with symlinks resolved when it exists (lsof reports `/private/tmp`, callers `/tmp`). */
@@ -34,7 +36,7 @@ function real(path) {
34
36
  }
35
37
  const inside = (c, p) => c === p || c.startsWith(`${p}${sep}`);
36
38
  /** Compared both as written and with links resolved: either spelling may be the one lsof used. */
37
- function within(child, parent) {
39
+ export function within(child, parent) {
38
40
  if (child === undefined)
39
41
  return false;
40
42
  return inside(resolve(child), resolve(parent)) || inside(real(child), real(parent));
@@ -42,8 +44,30 @@ function within(child, parent) {
42
44
  function openedNotice(url, init) {
43
45
  return (`This app is not wired for Reticle, so Reticle opened ${url} in its own browser and supplied ` +
44
46
  'the SDK (zero-install: DOM, network, console and routes; no component state and no source ' +
45
- `file:line). To wire it for good, run \`${init}\`, then ` +
46
- 'restart the dev server and reload the page.');
47
+ `file:line). To wire it for good: ${wiringConsent(init)} Then restart the dev server and ` +
48
+ 'reload the page.');
49
+ }
50
+ /**
51
+ * The one dev server that runs in this project's folder, or undefined when there is none or more
52
+ * than one. Two servers in one project is a choice the caller makes, not one Reticle guesses.
53
+ */
54
+ async function projectAppUrlIn(io, dir) {
55
+ const pinned = detectDevCommandInProject(dir)?.port;
56
+ const candidates = new Set(DEV_SERVER_PORTS);
57
+ if (pinned !== undefined) {
58
+ candidates.add(pinned);
59
+ }
60
+ const own = (await io.serving([...candidates]))
61
+ .map((port) => `${LOCALHOST}:${String(port)}`)
62
+ .filter((url) => within(io.servingDirectory(url), dir));
63
+ return 1 === own.length ? own[0] : undefined;
64
+ }
65
+ /** The caller's running app, for a lease that names no url. */
66
+ export function projectAppUrlFinder(io) {
67
+ return async () => {
68
+ const dir = io.project();
69
+ return dir === undefined ? undefined : projectAppUrlIn(io, dir);
70
+ };
47
71
  }
48
72
  /** One lease per project for the daemon's life: a failure is reported once, never retried. */
49
73
  export function firstCallOpener(io) {
@@ -52,16 +76,9 @@ export function firstCallOpener(io) {
52
76
  const dir = io.project();
53
77
  if (dir === undefined || tried.has(dir))
54
78
  return undefined;
55
- const pinned = detectDevCommandInProject(dir)?.port;
56
- const candidates = new Set(DEV_SERVER_PORTS);
57
- if (pinned !== undefined)
58
- candidates.add(pinned);
59
- const own = (await io.serving([...candidates]))
60
- .map((port) => `${LOCALHOST}:${String(port)}`)
61
- .filter((url) => within(io.servingDirectory(url), dir));
62
- const [url] = own;
79
+ const url = await projectAppUrlIn(io, dir);
63
80
  // ponytail: nothing serving yet is not an attempt, so a later call looks again.
64
- if (url === undefined || 1 !== own.length)
81
+ if (url === undefined)
65
82
  return undefined;
66
83
  tried.add(dir);
67
84
  await io.lease(url).catch(() => undefined);
@@ -72,17 +89,23 @@ export function firstCallOpener(io) {
72
89
  }
73
90
  /**
74
91
  * The daemon's two answers to an app nobody wired, built together because both ask the same
75
- * question first — which unwired web app is this caller in. `firstRun` wires it when the agent
92
+ * question first — which unwired web app is this caller in. `firstRun` names it when the agent
76
93
  * lists sessions; `openUnwiredApp` opens it zero-install on a page-needing call.
77
94
  */
78
- export function agentWiring(port, sessions, lease) {
79
- const firstRun = firstRunWiring({ port, cliPath: process.argv[1] ?? '' });
80
- const openUnwiredApp = firstCallOpener({
95
+ export function agentWiring(sessions, lease) {
96
+ const firstRun = firstRunWiring();
97
+ const io = {
81
98
  project: () => firstRun.projectDirectory(callingClientDirectory() ?? process.cwd()),
82
99
  serving: async (ports) => (await probeDevServerStates(ports)).serving,
83
100
  servingDirectory: (url) => servingDirectoryOf(url),
84
101
  lease,
85
102
  connected: () => 0 < sessions.list().length,
86
- });
87
- return { firstRun, openUnwiredApp };
103
+ };
104
+ // Wired or not: a lease that names no url wants the app this caller works in either way.
105
+ const callerFolder = () => callingClientDirectory() ?? process.cwd();
106
+ return {
107
+ firstRun,
108
+ openUnwiredApp: firstCallOpener(io),
109
+ projectAppUrl: projectAppUrlFinder({ ...io, project: callerFolder }),
110
+ };
88
111
  }
@@ -47,8 +47,8 @@ export declare function sdkFixForProject(projectId?: string): string;
47
47
  * from before the project the agent is now driving existed.
48
48
  */
49
49
  /**
50
- * Every `.reticle` root on this machine that sync should consider, from the same two sources the
51
- * artifact resolver uses.
50
+ * Every `.reticle` root on this machine that sync should consider: the sources the artifact resolver
51
+ * uses, plus every root a lease claimed in this process.
52
52
  *
53
53
  * Read on every call rather than snapshotted, for the same reason: `reticle link` can run in
54
54
  * another terminal while this daemon is up, and a startup snapshot would keep that repo silent
@@ -6,13 +6,16 @@
6
6
  * router, and the per-project lookups the daemon closes over. `daemon-parity.test.ts` checks both
7
7
  * entry points still call them.
8
8
  */
9
+ import { existsSync } from 'node:fs';
9
10
  import { join } from 'node:path';
11
+ import { worktreeTwins } from './command/cli/config/checkout.js';
10
12
  import { cpus, homedir } from 'node:os';
11
13
  import { bridgeWsUrl, EventType, ReticleDir, ReticleEnv } from '@reticlehq/core';
12
14
  import { fetchPlatformConfig } from './features/harness/platform-config.js';
13
15
  import { platformEnvPort } from './memory/cloud/cloud-config.js';
14
16
  import { knownProjectCandidates, projectDirectoryFor, } from './memory/project/artifact-root-resolver.js';
15
17
  import { createNodeFileSystem } from './memory/project/fs/fs-port.js';
18
+ import { claimedArtifactRoots } from './memory/project/root-claims.js';
16
19
  import { originOf } from './portal/session/session-manager.js';
17
20
  import { setBrowserMode, BrowserMode } from './telemetry/browser-mode.js';
18
21
  import { sdkFixForDirectory } from './command/version/sdk-fix.js';
@@ -151,8 +154,8 @@ export function sdkFixForProject(projectId) {
151
154
  * from before the project the agent is now driving existed.
152
155
  */
153
156
  /**
154
- * Every `.reticle` root on this machine that sync should consider, from the same two sources the
155
- * artifact resolver uses.
157
+ * Every `.reticle` root on this machine that sync should consider: the sources the artifact resolver
158
+ * uses, plus every root a lease claimed in this process.
156
159
  *
157
160
  * Read on every call rather than snapshotted, for the same reason: `reticle link` can run in
158
161
  * another terminal while this daemon is up, and a startup snapshot would keep that repo silent
@@ -162,7 +165,18 @@ export function sdkFixForProject(projectId) {
162
165
  * not. Deciding that here would mean reading every cloud.json on every tick.
163
166
  */
164
167
  export function knownProjectRoots() {
165
- return [...new Set(knownProjectCandidates().map((c) => join(c.directory, ReticleDir.ROOT)))];
168
+ const directories = knownProjectCandidates().map((c) => c.directory);
169
+ // A page served from a git worktree writes its runs into that worktree's copy of the project.
170
+ const twins = directories
171
+ .flatMap(worktreeTwins)
172
+ .filter((d) => existsSync(join(d, ReticleDir.ROOT)));
173
+ return [
174
+ ...new Set([
175
+ ...[...directories, ...twins].map((d) => join(d, ReticleDir.ROOT)),
176
+ // A lease opened with `root` writes there; without this, that work is never sent.
177
+ ...claimedArtifactRoots(),
178
+ ]),
179
+ ];
166
180
  }
167
181
  /** This project's platform credential (stored, else the env key), as the env the platform readers take. */
168
182
  export const platformEnvFor = (root) => platformEnvPort(createNodeFileSystem(), root ?? join(process.cwd(), ReticleDir.ROOT), homedir(), process.env);
@@ -36,6 +36,11 @@ interface StatusPayload {
36
36
  * a coding agent — what `reticle doctor` prints as its coverage line.
37
37
  */
38
38
  coverage?: TabCoverage[];
39
+ /**
40
+ * SDK version of each connected page, same order as the live tabs.
41
+ * `null` means the page did not report a version. Absent when nothing is connected.
42
+ */
43
+ pageSdkVersions?: readonly (string | null)[];
39
44
  }
40
45
  type TabCoverage = {
41
46
  sessionId: string;
@@ -47,7 +52,12 @@ why?: string, verifyPort?: number,
47
52
  /** The short rendering of the same diagnosis. Absent on a daemon that has no provider wired. */
48
53
  whyLead?: string,
49
54
  /** The live tabs, for their coverage. */
50
- tabs?: readonly InstrumentedTab[]): StatusPayload;
55
+ tabs?: readonly InstrumentedTab[],
56
+ /**
57
+ * SDK version of each connected page. `null` is a page that did not report one.
58
+ * Absent when nothing is connected. A newer CLI reads this to choose skew advice (#1709).
59
+ */
60
+ pageSdkVersions?: readonly (string | null)[]): StatusPayload;
51
61
  /**
52
62
  * Why `serve --http` cannot claim success against an already-running daemon — or undefined when
53
63
  * that daemon already serves the verify HTTP endpoint on the wanted port.
@@ -7,7 +7,12 @@ why, verifyPort,
7
7
  /** The short rendering of the same diagnosis. Absent on a daemon that has no provider wired. */
8
8
  whyLead,
9
9
  /** The live tabs, for their coverage. */
10
- tabs = []) {
10
+ tabs = [],
11
+ /**
12
+ * SDK version of each connected page. `null` is a page that did not report one.
13
+ * Absent when nothing is connected. A newer CLI reads this to choose skew advice (#1709).
14
+ */
15
+ pageSdkVersions = []) {
11
16
  return {
12
17
  running: true,
13
18
  version: SERVER_VERSION,
@@ -28,6 +33,7 @@ tabs = []) {
28
33
  ...instrumentationOf(tab),
29
34
  })),
30
35
  }),
36
+ ...(0 === pageSdkVersions.length ? {} : { pageSdkVersions }),
31
37
  };
32
38
  }
33
39
  /**
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Hold back "the last agent detached" for a short grace.
3
+ *
4
+ * The daemon ends every browser session when the last agent detaches. A proxy that reconnects
5
+ * closes its stream and opens a new one, so a single drop of the link ended the user's session, and
6
+ * the agent's next call found "no connected session". With the grace, an agent that comes back
7
+ * inside it never detached, as far as the sessions can tell.
8
+ */
9
+ /** Run `fn` after `ms`; the return value cancels it. Injected so a test needs no clock. */
10
+ export type Schedule = (fn: () => void, ms: number) => () => void;
11
+ export declare function withDetachGrace(onPresence: (connected: boolean) => void, graceMs: number, schedule?: Schedule): (connected: boolean) => void;
@@ -0,0 +1,34 @@
1
+ /**
2
+ * Hold back "the last agent detached" for a short grace.
3
+ *
4
+ * The daemon ends every browser session when the last agent detaches. A proxy that reconnects
5
+ * closes its stream and opens a new one, so a single drop of the link ended the user's session, and
6
+ * the agent's next call found "no connected session". With the grace, an agent that comes back
7
+ * inside it never detached, as far as the sessions can tell.
8
+ */
9
+ const realSchedule = (fn, ms) => {
10
+ const timer = setTimeout(fn, ms);
11
+ // The grace must never keep a daemon alive that is shutting down.
12
+ timer.unref();
13
+ return () => clearTimeout(timer);
14
+ };
15
+ export function withDetachGrace(onPresence, graceMs, schedule = realSchedule) {
16
+ let cancelDetach;
17
+ return (connected) => {
18
+ if (!connected) {
19
+ cancelDetach?.();
20
+ cancelDetach = schedule(() => {
21
+ cancelDetach = undefined;
22
+ onPresence(false);
23
+ }, graceMs);
24
+ return;
25
+ }
26
+ if (cancelDetach !== undefined) {
27
+ // Back inside the grace: the detach was never reported, so there is no attach to report.
28
+ cancelDetach();
29
+ cancelDetach = undefined;
30
+ return;
31
+ }
32
+ onPresence(true);
33
+ };
34
+ }
@@ -8,7 +8,12 @@ export interface SharedServer {
8
8
  * so each concurrent Claude Code client needs its own McpServer.
9
9
  * Must be called before listen.
10
10
  */
11
- attachMcp(factory: (peerSkew?: string) => McpServer): void;
11
+ attachMcp(factory: (peerSkew?: string, proxyId?: string, agentSession?: string) => McpServer): void;
12
+ /**
13
+ * SDK version of each page connected when an agent attaches.
14
+ * The daemon skew advice reads this so it does not tell the agent to restart over matching pages.
15
+ */
16
+ attachPageSdkVersions(provider: () => readonly (string | undefined)[]): void;
12
17
  /** Register the JSON the daemon returns from GET /status (live sessions + health for `reticle status`). */
13
18
  /** `held`: the request carried STATUS_HOLD_QUERY — a setup run is waiting on this daemon. */
14
19
  attachStatus(provider: (held: boolean) => unknown): void;
@@ -21,6 +26,12 @@ export interface SharedServer {
21
26
  * unattached, the route 404s, which is exactly what a newer CLI needs to hear from an older daemon.
22
27
  */
23
28
  attachDrive(provider: (url: string) => Promise<unknown>): void;
29
+ /**
30
+ * Register the handler behind POST /shutdown: the daemon's normal shutdown path. Only a loopback
31
+ * caller with the pairing token reaches it. Left unattached, the route 404s, and the caller falls
32
+ * back to a signal.
33
+ */
34
+ attachShutdown(handler: () => void): void;
24
35
  /**
25
36
  * Register a callback fired when the AGENT presence changes — true when the first MCP client (any
26
37
  * agent: Codex/OpenCode/Claude/Hermes) connects, false when the last one disconnects. Agent-