@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,9 +1,11 @@
1
1
  import { takeCallSecrets, withCallSecrets } from './tool-kit.js';
2
2
  import { healthEnvelope } from '../../portal/session/session-health.js';
3
+ import { sdkBehindNote } from '../../portal/session/session-info.js';
3
4
  import { logToolCall, toolLogPath } from '../../hooks/tool-log.js';
4
5
  import { nextStep } from './next-step.js';
5
6
  import { currentDrivenBy } from '../../hooks/driven-by.js';
6
- import { runAsAgent } from '../../hooks/coding-agents.js';
7
+ import { agentNameOf, agentSessionOf, runAsAgent } from '../../hooks/coding-agents.js';
8
+ import { recordEpisodeCall } from '../../memory/journal/episode-log.js';
7
9
  import { takeHumanNotes } from './human-notes.js';
8
10
  import { takeDriveNotes } from '../../features/harness/drive-runs.js';
9
11
  import { harnessDriving, msgHarnessHasTheTab } from './harness-tab-guard.js';
@@ -11,6 +13,9 @@ import { sessionRoot, sessionTarget } from '../../memory/project/session-root.js
11
13
  import { ArtifactRootReason } from '../../memory/project/artifact-root.js';
12
14
  import { agentNudge, takePlatformMoment } from './platform-moment.js';
13
15
  import { RESULT_FIELD, trackVerdict } from './reticle-result.js';
16
+ import { endsRun, noteToolResult, runReportField } from './run-report.js';
17
+ import { runLedger } from '../../judgement/runs/run-ledger.js';
18
+ import { readAppNotes } from './agent/app-notes.js';
14
19
  import { forTheAgent } from './agent/for-the-agent.js';
15
20
  import { feedbackAlreadyAsked, noteFeedbackAsked } from './agent/notices.js';
16
21
  import { SKEW_SHORT_WARNING, SKEW_VERDICT_WARNING } from '../../portal/session/session-health.js';
@@ -24,14 +29,14 @@ import { rewriteClosedAsSkew } from '../../command/version/version-skew.js';
24
29
  import { noteToolCall } from '../../command/daemon/lifetime/daemon-usefulness.js';
25
30
  import { bugsInResult, routeOf } from '../../telemetry/bug-found.js';
26
31
  import { noteToolServed, reportToolRefused } from '../../telemetry/tool-refused.js';
27
- import { buildErrorPayload, refusalReasonFor } from './error-recovery.js';
32
+ import { buildErrorPayload, codedRefusalOf, refusalReasonFor } from './error-recovery.js';
28
33
  import { resultIsError } from '../mcp/faults/mcp-is-error.js';
29
34
  import { verificationOf } from '../../telemetry/verification-of.js';
30
35
  import { emitBugFoundHook, emitVerdictHook } from '../../hooks/hook-emit.js';
31
- import { noteActed, noteFirstVerdict, noteOnboardingFirst, noteVerdictProduced, } from '../../telemetry/onboarding-firsts.js';
32
- import { DiscoveryInvite } from '@reticlehq/core';
36
+ import { noteActed, noteFirstVerdict, noteNextCall, noteOnboardingFirst, noteVerdictProduced, } from '../../telemetry/onboarding-firsts.js';
37
+ import { DiscoveryInvite, isPlainRecord as isPlainObject } from '@reticlehq/core';
33
38
  import { SESSION_ID_ARG, sessionIdFromArgs, spentRefFromArgs } from './tools-helpers.js';
34
- import { EnvelopeKey, HOST_STUB_NOTE, STEP_SHOT_TOOLS } from './tool-kit.js';
39
+ import { ACTION_TOOLS, CDP_TOOLS, EnvelopeKey, HOST_STUB_NOTE, REF_MINTING_TOOLS, SESSION_BOUND_TOOLS, STEP_SHOT_TOOLS, } from './tool-kit.js';
35
40
  import { ReticleTool } from '@reticlehq/core';
36
41
  import { takeFeedbackPrompt } from './feedback-tools.js';
37
42
  import { takeFeedbackUndelivered } from '../../telemetry/feedback-delivery.js';
@@ -41,134 +46,6 @@ import { takeStepShot } from '../../features/visual/step-shots.js';
41
46
  import { defectForToolResult, deltaForToolResult, impactSnapshot, initImpact, recordImpact, } from '../../memory/impact/impact-recorder.js';
42
47
  import { FrictionKind, frictionOf, inviteFor } from './feedback-invite.js';
43
48
  import { VACUOUS_BECAUSE } from '@reticlehq/engine/evidence/verified.js';
44
- /**
45
- * The live-session tools whose result MUST carry the
46
- * session-health envelope. Owned in ONE place — not retrofitted per handler — so a throttled tab
47
- * can never return a healthy-looking result from any of these. `runTool` is the single choke point
48
- * (mcp.ts + tool-invoker.ts) that splices health on; the guard test asserts the set is exhaustive.
49
- */
50
- /**
51
- * Tools that DRIVE the page. An action with no verdict after it is the signature of the loop
52
- * breaking mid-task — see `abandonedActions`. `act_and_wait` is one of these AND a verification, so
53
- * it settles its own action, which is exactly right: it is the tool that does both.
54
- */
55
- const ACTION_TOOLS = new Set([
56
- ReticleTool.ACT,
57
- ReticleTool.ACT_SEQUENCE,
58
- ReticleTool.ACT_AND_WAIT,
59
- ]);
60
- /**
61
- * Tools that go through Playwright CDP rather than the page SDK.
62
- *
63
- * Under version skew these fail with "Target page, context or browser has been closed" while every
64
- * DOM tool against the same tab still works (#688). They are session-EXEMPT (own result contracts),
65
- * so the bound-tool resolve above never runs for them — resolve again here so we can refuse with
66
- * the skew sentence before Playwright lies about a closed page.
67
- */
68
- const CDP_TOOLS = new Set([
69
- ReticleTool.SCREENSHOT,
70
- ReticleTool.VISUAL_DIFF,
71
- ReticleTool.NETWORK_MOCK,
72
- ReticleTool.VIEWPORT,
73
- // Breaks a request through the same Playwright route `reticle_network_mock` uses, so it fails the
74
- // same way under version skew and must be refused with the same sentence.
75
- ReticleTool.FLOW_MUTATE,
76
- ]);
77
- /**
78
- * Tools whose result hands the agent refs. The tab they were minted in is remembered, so the call
79
- * that spends one cannot be routed to a different tab without saying so — see ref-provenance.ts.
80
- *
81
- * Over-inclusion is the safe direction here and under-inclusion is not dangerous either: both ends
82
- * produce a REFUSAL naming the two tabs, never a silent drive against the wrong one.
83
- */
84
- const REF_MINTING_TOOLS = new Set([
85
- ReticleTool.SNAPSHOT,
86
- ReticleTool.QUERY,
87
- ReticleTool.INSPECT,
88
- // The same three merged, on the `merged` surface. Its `state` action mints nothing, and
89
- // over-inclusion is the safe direction here: the worst case is a refusal naming two tabs.
90
- ReticleTool.LOOK,
91
- ReticleTool.EXPLORE,
92
- // `crawl` mints refs for the controls it drives and `coverage` for the ones it reports untouched.
93
- // Both are actions on the merged verify tool now.
94
- ReticleTool.VERIFY,
95
- ]);
96
- export const SESSION_BOUND_TOOLS = new Set([
97
- // Resolves a session and reads its event window (`session.eventsSince`), exactly as OBSERVE and
98
- // NETWORK do. Without this it runs with no session and answers from nothing.
99
- ReticleTool.SNAPSHOT,
100
- ReticleTool.QUERY,
101
- ReticleTool.INSPECT,
102
- // All four merged. Every member here is session-bound, so unlike `verify` there is no split to
103
- // adjudicate — the merged tool inherits the only answer its members ever gave.
104
- ReticleTool.LOOK,
105
- // Merged change/flows/affected/coverage/crawl. Its members were SPLIT across bound and exempt —
106
- // coverage/change/crawl bound, flow_verify exempt because it returns its own suite contract — and
107
- // a merged tool has to be one or the other. Bound is the right side: `crawl` drives the app
108
- // itself, so a throttled or event-dropping tab is exactly the condition its verdict depends on,
109
- // and dropping the health disclosure there to protect a sibling's output shape would trade an
110
- // honesty signal for a formatting preference.
111
- ReticleTool.VERIFY,
112
- ReticleTool.ACT,
113
- ReticleTool.ACT_SEQUENCE,
114
- ReticleTool.ACT_AND_WAIT,
115
- ReticleTool.OBSERVE,
116
- ReticleTool.WAIT_FOR,
117
- ReticleTool.ASSERT,
118
- // Reads the live page as well as the event window, so a throttled tab can make it compare a stale
119
- // render against fresh data — exactly the case the health envelope exists to disclose.
120
- ReticleTool.RECONCILE,
121
- ReticleTool.NETWORK,
122
- ReticleTool.CONSOLE,
123
- ReticleTool.ANIMATIONS,
124
- ReticleTool.BASELINE, // merged save/list/diff — save+diff are live reads
125
- ReticleTool.RECORD, // merged start/stop — both live
126
- ReticleTool.REPLAY,
127
- ReticleTool.CLOCK,
128
- ReticleTool.STATE,
129
- ReticleTool.STORAGE,
130
- ReticleTool.EXPLORE,
131
- ReticleTool.SCROLL_TO,
132
- ReticleTool.NAVIGATE,
133
- ]);
134
- /**
135
- * Tools that carry a `sessionId` arg but are NOT live-session-health tools — they read/write
136
- * disk (capabilities/contract/flow/project), drain a buffer, or steer session lifecycle. They are
137
- * exempt from the health splice ON PURPOSE. Kept explicit so the guard test can force every new
138
- * `sessionId`-bearing tool to be classified into exactly one set (bound XOR exempt).
139
- */
140
- export const SESSION_EXEMPT_TOOLS = new Set([
141
- ReticleTool.CAPABILITIES, // has a fromDisk mode with no live session
142
- ReticleTool.CONTRACT_SAVE, // persists the registry to disk
143
- ReticleTool.FLOW_SAVE, // sessionId only scopes the write to the app's flow subdir; disk-side
144
- ReticleTool.FLOW, // merged list/load/delete — sessionId only scopes the project; all disk-side
145
- ReticleTool.FLOW_REPLAY, // returns its own FlowReplayResult contract (+ auto-records a run)
146
- ReticleTool.FLOW_SAVE_RECORDED, // reads the recording buffer, writes disk
147
- // FLOW_HEAL is no longer a name runTool ever sees: it became `reticle_verify {action:"heal"}`,
148
- // and VERIFY is already listed here, so the exemption is inherited from the parent. Left as a
149
- // dangling name it would be a lie this file's own test 6 is written to catch.
150
- ReticleTool.INTENT, // reads/writes .reticle/intent/; sessionId only picks the project
151
- ReticleTool.CONTEXT, // folds the journal + intent ledger; must still answer when nothing is connected
152
- ReticleTool.PROJECT, // reads .reticle/project.json
153
- // Reads the team's shared memory over HTTP; sessionId only resolves WHICH project's link file to
154
- // use. It must answer with no tab connected — "what does this project know?" is a question an
155
- // agent asks before it has opened anything.
156
- ReticleTool.MEMORY,
157
- ReticleTool.RUN_EXPORT, // reads .reticle/runs/<id>.json (verification-run artifact)
158
- ReticleTool.SESSION, // merged lifecycle/human-channel family (tune/yield/end/resume/messages/review/narrate)
159
- ReticleTool.SCREENSHOT, // own contract; provider-driven, not a live-DOM-health read
160
- ReticleTool.VISUAL_DIFF, // own contract (matched/ratio/region)
161
- ReticleTool.NETWORK_MOCK, // own contract (applied/count); provider-driven, not a live-DOM read
162
- ReticleTool.VIEWPORT, // own contract (applied/width/height); provider-driven, not a live-DOM read
163
- ReticleTool.ANNOTATE, // annotates a recording's steps; pure disk-side metadata, no live DOM read
164
- ReticleTool.LEASE, // merged acquire/release — its sessionId is a pool lease id, not a live session
165
- // Its sessionId only enriches the report with the tab's runtime/engine, and it must stay callable
166
- // when NO session exists — "nothing ever connected" is feedback we especially want.
167
- ReticleTool.FEEDBACK,
168
- ]);
169
- function isPlainObject(value) {
170
- return 'object' === typeof value && value !== null && !Array.isArray(value);
171
- }
172
49
  /**
173
50
  * Emit `verification_completed` when a verification tool produced a verdict.
174
51
  *
@@ -179,10 +56,11 @@ function isPlainObject(value) {
179
56
  *
180
57
  * The RULE itself lives in verification-of.ts, because getting it wrong fails silently.
181
58
  */
182
- function recordVerification(toolName, result, durationMs, brand, sessionId) {
183
- const verification = verificationOf(toolName, result, durationMs, brand, currentDrivenBy() !== undefined);
184
- if (verification === undefined)
185
- return;
59
+ function recordVerification(toolName, result, durationMs, brand, sessionId, sdkVersion) {
60
+ const verification = verificationOf(toolName, result, durationMs, brand, currentDrivenBy() !== undefined, sdkVersion);
61
+ if (verification === undefined) {
62
+ return false;
63
+ }
186
64
  getSessionMetrics().recordVerification();
187
65
  void getTelemetry().emit(TelemetryEventKind.VERIFICATION_COMPLETED, {
188
66
  actor: TelemetryActor.AGENT,
@@ -201,6 +79,7 @@ function recordVerification(toolName, result, durationMs, brand, sessionId) {
201
79
  noteFirstVerdict();
202
80
  // The FIRST_RUN rung: once per machine + project, not once per verdict.
203
81
  noteVerdictProduced(durationMs);
82
+ return true;
204
83
  }
205
84
  /**
206
85
  * Emit one `bug_found` per defect in a tool result, and count it into the session.
@@ -211,8 +90,9 @@ function recordVerification(toolName, result, durationMs, brand, sessionId) {
211
90
  */
212
91
  function reportBugsFound(toolName, result, sessionId) {
213
92
  const bugs = bugsInResult(toolName, result);
214
- if (0 === bugs.length)
93
+ if (0 === bugs.length) {
215
94
  return;
95
+ }
216
96
  const metrics = getSessionMetrics();
217
97
  const route = routeOf(result);
218
98
  for (const bug of bugs) {
@@ -254,10 +134,11 @@ function reportBugsFound(toolName, result, sessionId) {
254
134
  * tool's name, and then hands the same failure back out to be reported a second time as
255
135
  * `reticle_run`. A count that doubles because of HOW a tool was reached is not a measurement.
256
136
  */
257
- function reportRefusal(toolName, message) {
258
- if (toolName === ReticleTool.RUN)
137
+ function reportRefusal(toolName, message, error) {
138
+ if (toolName === ReticleTool.RUN) {
259
139
  return;
260
- reportToolRefused(toolName, refusalReasonFor(message));
140
+ }
141
+ reportToolRefused(toolName, refusalReasonFor(message, codedRefusalOf(error)));
261
142
  }
262
143
  /**
263
144
  * Which friction this result represents, counting the invitation if there is one.
@@ -273,8 +154,9 @@ function reportRefusal(toolName, message) {
273
154
  * feedback rate read half.
274
155
  */
275
156
  function frictionInviteFor(toolName, raw) {
276
- if (!isPlainObject(raw) || toolName === ReticleTool.RUN)
157
+ if (!isPlainObject(raw) || toolName === ReticleTool.RUN) {
277
158
  return undefined;
159
+ }
278
160
  const friction = frictionOf({
279
161
  unknownTool: false,
280
162
  // A vacuous unknown is the caller's: it asserted nothing real (a bare `settled` wait, which the
@@ -286,8 +168,9 @@ function frictionInviteFor(toolName, raw) {
286
168
  // loop this release exists to encourage — get told they are stuck.
287
169
  producedVerdict: 'verified' in raw,
288
170
  });
289
- if (friction !== undefined)
171
+ if (friction !== undefined) {
290
172
  getSessionMetrics().recordFeedbackPrompt();
173
+ }
291
174
  return friction;
292
175
  }
293
176
  /**
@@ -306,12 +189,14 @@ function frictionInviteFor(toolName, raw) {
306
189
  function firstOversizedArg(args) {
307
190
  const tooLong = (value) => 'string' === typeof value && value.length > TRANSPORT_LIMITS.MAX_STRING_LENGTH;
308
191
  for (const [key, value] of Object.entries(args)) {
309
- if (tooLong(value))
192
+ if (tooLong(value)) {
310
193
  return key;
194
+ }
311
195
  if ('object' === typeof value && null !== value && !Array.isArray(value)) {
312
196
  for (const [inner, nested] of Object.entries(value)) {
313
- if (tooLong(nested))
197
+ if (tooLong(nested)) {
314
198
  return `${key}.${inner}`;
199
+ }
315
200
  }
316
201
  }
317
202
  }
@@ -341,8 +226,9 @@ function firstOversizedArg(args) {
341
226
  * unscoped, so it answers as it always did.
342
227
  */
343
228
  function pinnedArgs(args, explicitSessionId, session) {
344
- if (explicitSessionId !== undefined || session === undefined)
229
+ if (explicitSessionId !== undefined || session === undefined) {
345
230
  return args;
231
+ }
346
232
  return { ...args, [SESSION_ID_ARG]: session.id };
347
233
  }
348
234
  export async function runTool(tool, deps, given, call) {
@@ -352,12 +238,51 @@ export async function runTool(tool, deps, given, call) {
352
238
  // A verdict still being decided is waited for by a session end (`trackVerdict`); the result is
353
239
  // compacted for the agent last, after telemetry and the tool log have read the full result.
354
240
  return trackVerdict(tool.name, withCallSecrets(secrets, async () => {
355
- const result = await loggedTool(tool, deps, args, call);
241
+ // The agent's own calls make its run; `reticle_run` is counted once, as the tool it reached.
242
+ // A host that wires no clock (an embedding, a test double) gets no report, never an error.
243
+ const agentCall = currentDrivenBy() === undefined &&
244
+ deps.attachId !== undefined &&
245
+ ReticleTool.RUN !== tool.name &&
246
+ 'function' === typeof deps.now;
247
+ // Closes the offer of an earlier first session call: did the agent do the offered step?
248
+ if (agentCall) {
249
+ noteNextCall(tool.name, args);
250
+ }
251
+ const ends = endsRun(tool.name, args);
252
+ // A call that only ends a run starts none: a second yield in a row carries no empty report.
253
+ if (agentCall && !ends && deps.attachId !== undefined) {
254
+ runLedger.begin(deps.now(), deps.attachId);
255
+ }
256
+ // The project of the session a call ends, read while the session still exists: releasing a
257
+ // tab removes it, and an unreadable project lost an unlinked user's cloud line.
258
+ const endedIn = agentCall && ends ? safeRoot(() => sessionRoot(deps, sessionIdFromArgs(args))) : undefined;
259
+ const raw = await loggedTool(tool, deps, args, call);
356
260
  const attach = currentDrivenBy() === undefined ? deps.attachId : undefined;
357
261
  const root = attach === undefined
358
262
  ? undefined
359
263
  : safeRoot(() => sessionRoot(deps, sessionIdFromArgs(args)));
360
- return forTheAgent({ name: tool.name, args, result, attach, root, fold: NOTICE_FOLD });
264
+ // The app notes before this call, so a note it learns counts as memory written.
265
+ const notesBefore = agentCall && root !== undefined ? readAppNotes(root) : [];
266
+ const answer = forTheAgent({
267
+ name: tool.name,
268
+ args,
269
+ result: raw,
270
+ attach,
271
+ root,
272
+ fold: NOTICE_FOLD,
273
+ });
274
+ if (!agentCall) {
275
+ return answer;
276
+ }
277
+ runLedger.after(deps.now());
278
+ noteToolResult(runLedger, tool.name, args, raw);
279
+ const notesAfter = root === undefined ? [] : readAppNotes(root);
280
+ runLedger.memoryWritten(notesAfter.filter((note) => !notesBefore.includes(note)).length);
281
+ runLedger.memoryRead(notesBefore);
282
+ if (!ends || null === answer || 'object' !== typeof answer) {
283
+ return answer;
284
+ }
285
+ return { ...answer, ...runReportField(runLedger, endedIn ?? root, process.env, deps.now()) };
361
286
  }));
362
287
  }
363
288
  /** Advisories that become once-per-session notice lines. See agent/notices.ts. */
@@ -386,21 +311,51 @@ export const NOTICE_FOLD = {
386
311
  };
387
312
  async function loggedTool(tool, deps, args, call) {
388
313
  const logPath = toolLogPath();
389
- if (logPath === undefined)
390
- return dispatchTool(tool, deps, args, call);
391
- const at = deps.now();
314
+ const at = Date.now();
315
+ // The tab this call drove, and where its events start: the call's effect on the page.
316
+ const seen = {};
317
+ const episode = (outcome) => {
318
+ // A record that cannot be built never fails the call it describes.
319
+ safeRoot(() => {
320
+ const from = seen.from;
321
+ const effect = seen.session === undefined || from === undefined
322
+ ? undefined
323
+ : seen.session.eventsSince(from);
324
+ const drivenBy = currentDrivenBy();
325
+ const agent = agentNameOf(deps.attachId);
326
+ const agentSession = agentSessionOf(deps.attachId);
327
+ recordEpisodeCall(seen.session?.artifactRoot ?? deps.reticleRoot, deps.attachId, Date.now, {
328
+ tool: tool.name,
329
+ args,
330
+ startedAt: at,
331
+ endedAt: Date.now(),
332
+ ...outcome,
333
+ ...(seen.session === undefined ? {} : { sessionId: seen.session.id }),
334
+ ...(agent === undefined ? {} : { agent }),
335
+ ...(agentSession === undefined ? {} : { agentSession }),
336
+ ...(drivenBy === undefined ? {} : { drivenBy }),
337
+ ...(effect === undefined ? {} : { effect }),
338
+ });
339
+ });
340
+ };
392
341
  try {
393
- const result = await dispatchTool(tool, deps, args, call);
394
- logToolCall(logPath, { tool: tool.name, args, at, ms: deps.now() - at, result });
342
+ const result = await dispatchTool(tool, deps, args, call, seen);
343
+ if (logPath !== undefined) {
344
+ logToolCall(logPath, { tool: tool.name, args, at, ms: Date.now() - at, result });
345
+ }
346
+ episode({ result });
395
347
  return result;
396
348
  }
397
349
  catch (error) {
398
350
  const message = error instanceof Error ? error.message : String(error);
399
- logToolCall(logPath, { tool: tool.name, args, at, ms: deps.now() - at, error: message });
351
+ if (logPath !== undefined) {
352
+ logToolCall(logPath, { tool: tool.name, args, at, ms: Date.now() - at, error: message });
353
+ }
354
+ episode({ error: message });
400
355
  throw error;
401
356
  }
402
357
  }
403
- async function dispatchTool(tool, deps, args, call) {
358
+ async function dispatchTool(tool, deps, args, call, seen = {}) {
404
359
  // Both dispatch paths (MCP + programmatic) pass through here — the one place "which tool is mostly
405
360
  // used" can be counted. This used to EMIT an event per call; it now increments an in-process counter
406
361
  // that leaves once, with the session summary. A verification loop is 50–200 calls, and PostHog bills
@@ -516,11 +471,16 @@ async function dispatchTool(tool, deps, args, call) {
516
471
  }
517
472
  }
518
473
  const leaseId = session?.id ?? rawSessionId;
519
- if (leaseId !== undefined)
474
+ if (leaseId !== undefined) {
520
475
  deps.pool?.touch(leaseId);
476
+ }
521
477
  // One identity for the whole call: the handler drives the session everything above is attributed
522
478
  // to, rather than resolving again against a registry that can have changed underneath it.
523
479
  const dispatchArgs = pinnedArgs(args, rawSessionId, session);
480
+ if (session !== undefined) {
481
+ seen.session = session;
482
+ seen.from = safeRoot(() => session?.elapsed());
483
+ }
524
484
  let raw;
525
485
  try {
526
486
  // The one dispatch point every tool call passes through, so it is where the trace's root span
@@ -556,12 +516,13 @@ async function dispatchTool(tool, deps, args, call) {
556
516
  const rewritten = rewriteClosedAsSkew(error, skewText);
557
517
  const toThrow = rewritten ?? error;
558
518
  const message = toThrow instanceof Error ? toThrow.message : String(toThrow);
559
- reportRefusal(tool.name, message);
519
+ reportRefusal(tool.name, message, toThrow);
560
520
  // The invitation on THIS path is the one `buildErrorPayload` attaches when it does not recognise
561
521
  // the error, and it was never counted — so the denominator excluded the commonest friction there
562
522
  // is. Gated on the payload actually carrying the ask, because a recognised error gets a recovery
563
523
  // instead and counting an invitation nobody was shown breaks the ratio in the other direction.
564
- if (tool.name !== ReticleTool.RUN && buildErrorPayload(message).feedback !== undefined) {
524
+ const payload = buildErrorPayload(message, codedRefusalOf(toThrow));
525
+ if (tool.name !== ReticleTool.RUN && payload.feedback !== undefined) {
565
526
  getSessionMetrics().recordFeedbackPrompt();
566
527
  }
567
528
  throw toThrow;
@@ -580,18 +541,20 @@ async function dispatchTool(tool, deps, args, call) {
580
541
  const acted = raw['dispatched'] !== false &&
581
542
  (!isPlainObject(effect) || effect['dispatched'] !== false) &&
582
543
  (tool.name !== ReticleTool.ACT_AND_WAIT || isPlainObject(effect));
583
- if (ACTION_TOOLS.has(tool.name) && acted)
544
+ if (ACTION_TOOLS.has(tool.name) && acted) {
584
545
  noteActed(args);
546
+ }
585
547
  }
586
548
  // The human-feedback ask rides out on the first VERIFICATION that completes — the one moment the
587
549
  // experience is fresh and there is something concrete to react to. It is spliced BEFORE the
588
550
  // session-bound early return, because two of the four verification tools (flow_verify,
589
551
  // verify_change) are session-EXEMPT and would otherwise never carry it.
552
+ let verdict = false;
590
553
  if (isPlainObject(raw)) {
591
554
  // The brand comes from the session's own PAGE_HEALTH report, so it is present for the four
592
555
  // session-bound verification tools and absent for flow_verify (session-exempt) — which replays
593
556
  // into a browser Reticle launched, where `browser` already says what happened.
594
- recordVerification(tool.name, raw, Date.now() - startedAt, session?.brand, session?.id);
557
+ verdict = recordVerification(tool.name, raw, Date.now() - startedAt, session?.brand, session?.id, session?.sdkVersion);
595
558
  reportBugsFound(tool.name, raw, session?.id);
596
559
  }
597
560
  // The other half of the refusal surface. A top-level `error` string IS this codebase's refusal
@@ -616,19 +579,22 @@ async function dispatchTool(tool, deps, args, call) {
616
579
  // Bound to THIS session's root: a tab must be shown its own project's numbers, not whichever
617
580
  // project the daemon was started in.
618
581
  session?.pushImpact?.(() => impactSnapshot(artifactRoot));
619
- if (resultIsError(raw))
582
+ if (resultIsError(raw)) {
620
583
  reportRefusal(tool.name, raw.error);
584
+ }
621
585
  else {
622
586
  noteToolServed();
623
587
  // Which tab these refs belong to. Recorded on the way OUT, so the next call that spends one is
624
588
  // measured against the tab that actually produced it.
625
- if (session !== undefined && REF_MINTING_TOOLS.has(tool.name))
589
+ if (session !== undefined && REF_MINTING_TOOLS.has(tool.name)) {
626
590
  noteRefsMinted(session.id);
591
+ }
627
592
  }
628
593
  // The feedback family is asked at most once per agent session (agent/notices.ts): gated here, at
629
594
  // the take, so a suppressed ask is never counted as one that was made.
630
595
  const asked = feedbackAlreadyAsked(currentDrivenBy() === undefined ? deps.attachId : undefined);
631
- const prompt = isPlainObject(raw) && !asked ? takeFeedbackPrompt(tool.name) : undefined;
596
+ // Only a call that produced a verdict asks: `reticle_act` is a verdict tool for its `steps` form.
597
+ const prompt = verdict && !asked ? takeFeedbackPrompt(tool.name) : undefined;
632
598
  // Same one-shot channel as the feedback ask: the agent is mid-task, so anything it would have to go
633
599
  // and ASK for is something it will never ask for. Spliced on ANY tool result, not just a
634
600
  // verification, because an out-of-date install is worth mentioning whatever the agent is doing.
@@ -654,8 +620,9 @@ async function dispatchTool(tool, deps, args, call) {
654
620
  // RETURN an error. So the denominator was counting a small, unrepresentative slice of the
655
621
  // invitations and reading near-empty, which looks identical to a nudge that never fires.
656
622
  const friction = asked || prompt !== undefined ? undefined : frictionInviteFor(tool.name, raw);
657
- if (prompt !== undefined || friction !== undefined)
623
+ if (prompt !== undefined || friction !== undefined) {
658
624
  noteFeedbackAsked(currentDrivenBy() === undefined ? deps.attachId : undefined);
625
+ }
659
626
  // Once per project, on a proved verdict, when the runs live only on this machine. Not on a result
660
627
  // whose `reticleResult` already ends with the platform line: once per result, never twice.
661
628
  const platform = isPlainObject(raw) && !(RESULT_FIELD in raw)
@@ -688,7 +655,6 @@ async function dispatchTool(tool, deps, args, call) {
688
655
  tool: tool.name,
689
656
  raw: answer,
690
657
  isError: resultIsError(answer),
691
- tab: session,
692
658
  root: safeRoot(() => sessionRoot(deps, rawSessionId)),
693
659
  harnessOn: () => impactSnapshot(artifactRoot)?.harnessConfig?.harnessEnabled,
694
660
  })
@@ -738,8 +704,9 @@ async function dispatchTool(tool, deps, args, call) {
738
704
  }
739
705
  : {}),
740
706
  };
741
- if (!bound || !isPlainObject(result))
707
+ if (!bound || !isPlainObject(result)) {
742
708
  return result;
709
+ }
743
710
  // Reuse the session resolved above so the health envelope describes the SAME session the handler
744
711
  // drove; only re-resolve if the up-front attempt failed but the handler somehow succeeded.
745
712
  // A handler that answered with no tab to resolve (a Harness drive polled by runId after a daemon
@@ -767,9 +734,14 @@ async function dispatchTool(tool, deps, args, call) {
767
734
  if (true === deps.pool?.stubInstalled?.(resolved.id)) {
768
735
  envelope[EnvelopeKey.HOST_STUB] = HOST_STUB_NOTE;
769
736
  }
737
+ const behind = sdkBehindNote(resolved);
738
+ if (behind !== undefined && 'verified' in result) {
739
+ envelope[EnvelopeKey.SDK_BEHIND] = behind;
740
+ }
770
741
  // The health block is idempotent: add it only when the handler didn't already include a `session`.
771
- if (!('session' in result))
742
+ if (!('session' in result)) {
772
743
  Object.assign(envelope, healthEnvelope(resolved));
744
+ }
773
745
  // Lease + age-warning are INDEPENDENT of the health block. Previously the `'session' in result`
774
746
  // early-return skipped them whenever a handler returned its own health (which a throttled tab always
775
747
  // does) — so a long-running backgrounded session, the case most likely to leak, never got the
@@ -780,11 +752,13 @@ async function dispatchTool(tool, deps, args, call) {
780
752
  if (lease !== undefined && process.env['CI'] === undefined) {
781
753
  envelope[EnvelopeKey.SESSION_LEASE] = lease;
782
754
  }
783
- if (opened !== undefined)
755
+ if (opened !== undefined) {
784
756
  envelope[EnvelopeKey.ZERO_INSTALL] = opened.notice;
757
+ }
785
758
  const warning = resolved.ageWarning();
786
- if (warning !== undefined)
759
+ if (warning !== undefined) {
787
760
  envelope[EnvelopeKey.SESSION_AGE_WARNING] = warning;
761
+ }
788
762
  // Ask for a verdict when the agent has driven the page and not asked for one: a session that never
789
763
  // calls a verdict-producing tool proves nothing, however many tools it used. One-shot per
790
764
  // abandoned run, same discipline as the pool lease — a hint on every call is noise that gets tuned
@@ -806,11 +780,13 @@ async function dispatchTool(tool, deps, args, call) {
806
780
  // that translation is where agents were already going wrong — `until` omitted, action arguments
807
781
  // flat instead of nested under `args`. `ref` and `action` come from the act that actually
808
782
  // dispatched, so the suggestion is about the element the agent touched. See verify-next-baton.
809
- if (unverified !== undefined && !suppressBaton)
810
- // `lastAct` read defensively: this envelope is built on EVERY tool call, so a session shape
811
- // without it would turn a missing field into a crash on the whole surface rather than a missing
812
- // suggestion. The baton degrades to prose, which is what it carried before.
783
+ if (unverified !== undefined && !suppressBaton)
784
+ // `lastAct` read defensively: this envelope is built on EVERY tool call, so a session shape
785
+ // without it would turn a missing field into a crash on the whole surface rather than a missing
786
+ // suggestion. The baton degrades to prose, which is what it carried before.
787
+ {
813
788
  envelope[EnvelopeKey.VERIFY_NEXT] = verifyNextBaton(unverified, resolved.lastAct?.effect() ?? {});
789
+ }
814
790
  return Object.keys(envelope).length > 0 ? { ...result, ...envelope } : result;
815
791
  }
816
792
  /**
@@ -819,13 +795,16 @@ async function dispatchTool(tool, deps, args, call) {
819
795
  * navigation can land the page under a new id, so the id the result reports wins.
820
796
  */
821
797
  async function withStepShot(name, deps, args, raw, sessionId) {
822
- if (!STEP_SHOT_TOOLS.has(name) || Array.isArray(args['steps']))
798
+ if (!STEP_SHOT_TOOLS.has(name) || Array.isArray(args['steps'])) {
823
799
  return raw;
824
- if (!isPlainObject(raw) || resultIsError(raw) || true === raw['paused'])
800
+ }
801
+ if (!isPlainObject(raw) || resultIsError(raw) || true === raw['paused']) {
825
802
  return raw;
803
+ }
826
804
  const tab = 'string' === typeof raw['sessionId'] ? raw['sessionId'] : sessionId;
827
- if (tab === undefined)
805
+ if (tab === undefined) {
828
806
  return raw;
807
+ }
829
808
  // Paired with its check when the run is written: the n-th verdict picture is the n-th check.
830
809
  const verdict = 'verified' in raw && (ReticleTool.ACT_AND_WAIT === name || ReticleTool.ASSERT === name);
831
810
  return { ...raw, [EnvelopeKey.SCREENSHOT]: await takeStepShot(deps, tab, name, { verdict }) };
@@ -846,11 +825,18 @@ function safeRoot(get) {
846
825
  function unmatchedRootOf(deps, sessionId) {
847
826
  try {
848
827
  const target = sessionTarget(deps, sessionId);
828
+ // A lease that claimed a root writes there. The page's unmatched bucket is not where this
829
+ // run goes, so naming it would send the agent to fix a folder the run never touches.
830
+ if (target.claimedRoot !== undefined) {
831
+ return undefined;
832
+ }
849
833
  const resolved = deps.artifactRootFor?.(target.projectId, target.origin);
850
- if (resolved === undefined || ArtifactRootReason.MATCHED_PROJECT === resolved.reason)
834
+ if (resolved === undefined || ArtifactRootReason.MATCHED_PROJECT === resolved.reason) {
851
835
  return undefined;
852
- if (resolved.root === deps.reticleRoot)
836
+ }
837
+ if (resolved.root === deps.reticleRoot) {
853
838
  return undefined;
839
+ }
854
840
  return {
855
841
  root: resolved.root,
856
842
  contenders: resolved.candidates ?? [],
@@ -17,6 +17,7 @@
17
17
  * So: rank by what the daemon actually knows, and fall back to the differential only when it knows
18
18
  * nothing. A cause we hold positive evidence against is not printed at all.
19
19
  */
20
+ import type { LeaseReaderFailure } from './lease-readiness.js';
20
21
  /** What the daemon can say for certain at the moment a lease comes back unconnected. */
21
22
  export interface LeaseEvidence {
22
23
  /** A dial WAS made and turned away, with the reason. The only certain cause there is. */
@@ -56,3 +57,11 @@ export interface LeaseEvidence {
56
57
  dialledUrl?: string;
57
58
  }
58
59
  export declare function leaseNotConnectedHint(url: string, port: number, evidence?: LeaseEvidence): string;
60
+ /**
61
+ * The leased page was still loading when the wait ran out, so nothing has failed yet: a slow first
62
+ * dev compile (Angular, a cold Vite) holds the document and its SDK dials in once it finishes.
63
+ * Saying "never dialled" here sent agents off debugging an install that works (#1555).
64
+ */
65
+ export declare function leaseStillLoadingHint(url: string, waitedMs: number): string;
66
+ /** The hint for a lease whose zero-install reader did not run (#1701). The lease is already released. */
67
+ export declare function leaseReaderFailedHint(url: string, failure: LeaseReaderFailure): string;
@@ -17,7 +17,8 @@
17
17
  * So: rank by what the daemon actually knows, and fall back to the differential only when it knows
18
18
  * nothing. A cause we hold positive evidence against is not printed at all.
19
19
  */
20
- import { isLoopbackHostname } from '@reticlehq/core';
20
+ import { isLoopbackHostname, LeaseNotReadyReason } from '@reticlehq/core';
21
+ import { INIT_COMMAND } from '../../portal/session/no-session-next-action.js';
21
22
  const NUXT = 'nuxt';
22
23
  const PORT_DIFFERENTIAL = "The usual cause is a PORT MISMATCH: the app's SDK connects to the port it was BUILT with, so a " +
23
24
  "daemon on a different port never hears from it — check the app's reticle port (`.reticle.json`, " +
@@ -128,7 +129,7 @@ export function leaseNotConnectedHint(url, port, evidence = {}) {
128
129
  const notThisApp = true === evidence.sdkMarker
129
130
  ? ''
130
131
  : ' That may have been a DIFFERENT app, though: this one may carry no Reticle SDK at all, ' +
131
- 'in which case run `reticle init` in ITS directory first — every cause below assumes the ' +
132
+ `in which case ask the user, then run \`${INIT_COMMAND}\` in ITS directory — every cause below assumes the ` +
132
133
  'SDK is already installed.';
133
134
  // Never beside a marker that WAS found: "it ships the SDK" and "the build stripped it" cannot
134
135
  // both be the story.
@@ -150,7 +151,25 @@ export function leaseNotConnectedHint(url, port, evidence = {}) {
150
151
  // was not seen; a production build is the other way to serve a page without it.
151
152
  const noSdk = true === evidence.sdkMarker
152
153
  ? ''
153
- : ' If the app carries no Reticle SDK at all, run `reticle init` in it first.' +
154
+ : ` If the app carries no Reticle SDK at all, ask the user, then run \`${INIT_COMMAND}\` in it.` +
154
155
  (false === evidence.sdkMarker || isRemoteUrl(url) ? PRODUCTION_STUB : '');
155
156
  return `${opening}${nuxt}${marker} ${PORT_DIFFERENTIAL}${noSdk} ${REAL_CAUSES} ${RELEASE}`;
156
157
  }
158
+ /**
159
+ * The leased page was still loading when the wait ran out, so nothing has failed yet: a slow first
160
+ * dev compile (Angular, a cold Vite) holds the document and its SDK dials in once it finishes.
161
+ * Saying "never dialled" here sent agents off debugging an install that works (#1555).
162
+ */
163
+ export function leaseStillLoadingHint(url, waitedMs) {
164
+ const seconds = Math.round(waitedMs / 1000);
165
+ return (`${url} was still loading after ${seconds}s. Its SDK did not have time to connect. ` +
166
+ 'Check reticle_session { action: "list" } again soon, or release and acquire again after the dev server compiles.');
167
+ }
168
+ /** The hint for a lease whose zero-install reader did not run (#1701). The lease is already released. */
169
+ export function leaseReaderFailedHint(url, failure) {
170
+ return failure.reason === LeaseNotReadyReason.NOT_HTML_DOCUMENT
171
+ ? `${url} is not an HTML page, so no SDK can connect to it. The lease is released. ` +
172
+ 'Acquire an HTML page of the app instead.'
173
+ : `The zero-install reader failed on ${url}: ${failure.cause}. The lease is released. ` +
174
+ 'If the tab closed during setup, acquire again.';
175
+ }