@reticlehq/server 3.6.0 → 3.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (614) hide show
  1. package/SKILL.md +122 -123
  2. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  3. package/dist/command/cli/adhoc-suite.js +42 -7
  4. package/dist/command/cli/adhoc-verdict.d.ts +18 -2
  5. package/dist/command/cli/adhoc-verdict.js +70 -6
  6. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  7. package/dist/command/cli/answers/gate-exit.js +45 -0
  8. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  9. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  10. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  11. package/dist/command/cli/auth/device-flow.js +17 -0
  12. package/dist/command/cli/cli-doctor.js +14 -0
  13. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  14. package/dist/command/cli/cli-flow-commands.js +28 -105
  15. package/dist/command/cli/cli-kill.js +3 -2
  16. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  17. package/dist/command/cli/cli-parse-grammar.js +75 -0
  18. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  19. package/dist/command/cli/cli-parse-verify.js +18 -0
  20. package/dist/command/cli/cli-parse.d.ts +19 -28
  21. package/dist/command/cli/cli-parse.js +82 -182
  22. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  23. package/dist/command/cli/cli-update-commands.js +61 -9
  24. package/dist/command/cli/cli-usage.d.ts +33 -0
  25. package/dist/command/cli/cli-usage.js +287 -0
  26. package/dist/command/cli/cli-verify.d.ts +34 -4
  27. package/dist/command/cli/cli-verify.js +81 -12
  28. package/dist/command/cli/cloud-cli.d.ts +13 -0
  29. package/dist/command/cli/cloud-cli.js +145 -333
  30. package/dist/command/cli/cloud-kit.d.ts +12 -0
  31. package/dist/command/cli/cloud-kit.js +41 -2
  32. package/dist/command/cli/cloud-link.d.ts +57 -0
  33. package/dist/command/cli/cloud-link.js +308 -0
  34. package/dist/command/cli/cloud-login.d.ts +15 -1
  35. package/dist/command/cli/cloud-login.js +67 -13
  36. package/dist/command/cli/context-command.d.ts +1 -0
  37. package/dist/command/cli/context-command.js +33 -0
  38. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  39. package/dist/command/cli/daemon-start-options.js +24 -3
  40. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  41. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  42. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  43. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  44. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  45. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  46. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  47. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  48. package/dist/command/cli/known-regression.d.ts +13 -0
  49. package/dist/command/cli/known-regression.js +34 -0
  50. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  51. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  52. package/dist/command/cli/lifecycle/daemon-lifecycle.js +11 -2
  53. package/dist/command/cli/mcp-command.d.ts +6 -0
  54. package/dist/command/cli/mcp-command.js +13 -5
  55. package/dist/command/cli/ports/port-holder.js +1 -1
  56. package/dist/command/cli/project-name.d.ts +29 -1
  57. package/dist/command/cli/project-name.js +107 -2
  58. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  59. package/dist/command/cli/setup-mcp-cli.js +29 -8
  60. package/dist/command/cli/status/status-lines.d.ts +1 -0
  61. package/dist/command/cli/status/status-lines.js +47 -2
  62. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  63. package/dist/command/cli/status/workspace-links.js +29 -0
  64. package/dist/command/cli/try-command.d.ts +96 -0
  65. package/dist/command/cli/try-command.js +362 -0
  66. package/dist/command/cli/tutorial.d.ts +0 -100
  67. package/dist/command/cli/tutorial.js +0 -178
  68. package/dist/command/cli/verify-results.d.ts +19 -0
  69. package/dist/command/cli/verify-results.js +29 -0
  70. package/dist/command/cli-onboarding.d.ts +0 -11
  71. package/dist/command/cli-onboarding.js +0 -15
  72. package/dist/command/cli.d.ts +14 -0
  73. package/dist/command/cli.js +103 -83
  74. package/dist/command/daemon/daemon-resilience.js +4 -4
  75. package/dist/command/daemon/daemon-resolve.d.ts +9 -1
  76. package/dist/command/daemon/daemon-resolve.js +49 -10
  77. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  78. package/dist/command/setup/bringup/bridge-port.js +13 -3
  79. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  80. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  81. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  82. package/dist/command/setup/init/agent-restart.js +28 -0
  83. package/dist/command/setup/init/init-port.d.ts +10 -1
  84. package/dist/command/setup/init/init-port.js +22 -2
  85. package/dist/command/setup/init/init-runtime.d.ts +12 -2
  86. package/dist/command/setup/init/init-runtime.js +96 -37
  87. package/dist/command/setup/node-effects.d.ts +2 -0
  88. package/dist/command/setup/node-effects.js +36 -8
  89. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  90. package/dist/command/setup/probe/existing-app.js +14 -0
  91. package/dist/command/setup/remaining-steps.js +1 -1
  92. package/dist/command/setup/run-setup.d.ts +29 -9
  93. package/dist/command/setup/run-setup.js +34 -28
  94. package/dist/command/setup/setup-command.d.ts +23 -0
  95. package/dist/command/setup/setup-command.js +57 -4
  96. package/dist/command/setup/setup-mcp.js +25 -2
  97. package/dist/command/setup/tauri-signing.d.ts +19 -0
  98. package/dist/command/setup/tauri-signing.js +79 -0
  99. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  100. package/dist/command/setup/terminal/listeners.js +37 -6
  101. package/dist/command/update/update-nudge.d.ts +9 -0
  102. package/dist/command/update/update-nudge.js +1 -1
  103. package/dist/command/update/updater.js +11 -15
  104. package/dist/command/version/version-nudge.js +3 -0
  105. package/dist/command/version/version-skew.d.ts +20 -1
  106. package/dist/command/version/version-skew.js +38 -2
  107. package/dist/features/crawl/crawl.js +14 -1
  108. package/dist/features/exhaust/ledger.d.ts +14 -14
  109. package/dist/features/harness/drive-report.d.ts +39 -5
  110. package/dist/features/harness/drive-report.js +271 -54
  111. package/dist/features/harness/drive-runs.d.ts +120 -0
  112. package/dist/features/harness/drive-runs.js +289 -0
  113. package/dist/features/harness/drivers.d.ts +1 -1
  114. package/dist/features/harness/drivers.js +1 -1
  115. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  116. package/dist/features/harness/explore/console-pages.js +146 -0
  117. package/dist/features/harness/explore/disparity.d.ts +19 -0
  118. package/dist/features/harness/explore/disparity.js +71 -0
  119. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  120. package/dist/features/harness/explore/fake-app.js +49 -0
  121. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  122. package/dist/features/harness/explore/goal-search.js +144 -0
  123. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  124. package/dist/features/harness/explore/page-tree.js +148 -0
  125. package/dist/features/harness/explore/site-map.d.ts +34 -0
  126. package/dist/features/harness/explore/site-map.js +150 -0
  127. package/dist/features/harness/goals.d.ts +68 -7
  128. package/dist/features/harness/goals.js +289 -36
  129. package/dist/features/harness/harness.d.ts +30 -1
  130. package/dist/features/harness/harness.js +141 -7
  131. package/dist/features/harness/platform/local-apps.d.ts +36 -3
  132. package/dist/features/harness/platform/local-apps.js +81 -5
  133. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  134. package/dist/features/harness/platform/persona-credentials.js +69 -0
  135. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  136. package/dist/features/harness/platform/platform-drives.js +114 -0
  137. package/dist/features/harness/platform/refusal.d.ts +52 -0
  138. package/dist/features/harness/platform/refusal.js +71 -0
  139. package/dist/features/harness/platform/remote-drive.d.ts +8 -2
  140. package/dist/features/harness/platform/remote-drive.js +22 -9
  141. package/dist/features/harness/platform/script.d.ts +57 -11
  142. package/dist/features/harness/platform/script.js +144 -12
  143. package/dist/features/harness/platform/server-driver.d.ts +17 -4
  144. package/dist/features/harness/platform/server-driver.js +29 -26
  145. package/dist/features/harness/platform-config.d.ts +38 -5
  146. package/dist/features/harness/platform-config.js +93 -8
  147. package/dist/features/harness/route-guess.d.ts +13 -0
  148. package/dist/features/harness/route-guess.js +49 -0
  149. package/dist/features/harness/script/script-run.d.ts +30 -1
  150. package/dist/features/harness/script/script-run.js +355 -48
  151. package/dist/features/license/license.d.ts +2 -2
  152. package/dist/features/visual/step-shots.d.ts +31 -0
  153. package/dist/features/visual/step-shots.js +231 -0
  154. package/dist/features/visual/visual-tools.js +22 -14
  155. package/dist/hooks/client-directory.d.ts +18 -0
  156. package/dist/hooks/client-directory.js +57 -0
  157. package/dist/hooks/coding-agents.d.ts +34 -0
  158. package/dist/hooks/coding-agents.js +117 -0
  159. package/dist/hooks/driven-by.d.ts +21 -2
  160. package/dist/hooks/driven-by.js +42 -2
  161. package/dist/hooks/hook-bus.d.ts +4 -0
  162. package/dist/hooks/hook-bus.js +18 -0
  163. package/dist/index.d.ts +1 -0
  164. package/dist/index.js +26 -183
  165. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  166. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  167. package/dist/judgement/capsule/causal-summary.js +33 -0
  168. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  169. package/dist/judgement/runs/artifact/build-verification-run.js +20 -4
  170. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  171. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  172. package/dist/judgement/runs/artifact/replay-mapping.js +25 -9
  173. package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
  174. package/dist/judgement/runs/artifact/run-store.js +175 -8
  175. package/dist/judgement/runs/context-tools.js +59 -1
  176. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  177. package/dist/judgement/runs/default-run-id.js +16 -0
  178. package/dist/judgement/runs/drive-run.d.ts +53 -5
  179. package/dist/judgement/runs/drive-run.js +234 -20
  180. package/dist/judgement/runs/resume.d.ts +44 -0
  181. package/dist/judgement/runs/resume.js +137 -0
  182. package/dist/judgement/runs/reticle-runner.js +5 -2
  183. package/dist/judgement/runs/runner-port.d.ts +5 -1
  184. package/dist/judgement/runs/runner-port.js +8 -2
  185. package/dist/judgement/runs/verification-sync.d.ts +2 -0
  186. package/dist/judgement/runs/verification-sync.js +36 -15
  187. package/dist/language/flows/decision.js +2 -1
  188. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  189. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  190. package/dist/language/flows/flow-anchor.d.ts +7 -2
  191. package/dist/language/flows/flow-anchor.js +10 -3
  192. package/dist/language/flows/flow-intent.d.ts +1 -0
  193. package/dist/language/flows/flow-journey.d.ts +6 -0
  194. package/dist/language/flows/flow-journey.js +20 -0
  195. package/dist/language/flows/flow-learning.d.ts +4 -0
  196. package/dist/language/flows/flow-learning.js +37 -3
  197. package/dist/language/flows/flow-replay-run.js +16 -18
  198. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  199. package/dist/language/flows/flow-replay.d.ts +18 -1
  200. package/dist/language/flows/flow-replay.js +22 -7
  201. package/dist/language/flows/flow-result.d.ts +22 -1
  202. package/dist/language/flows/flow-result.js +47 -2
  203. package/dist/language/flows/flow-step-runners.d.ts +2 -0
  204. package/dist/language/flows/flow-step-runners.js +12 -6
  205. package/dist/language/flows/flow-store-for-session.js +5 -1
  206. package/dist/language/flows/flow-tools.d.ts +10 -0
  207. package/dist/language/flows/flow-tools.js +61 -62
  208. package/dist/language/flows/flows.d.ts +16 -1
  209. package/dist/language/flows/flows.js +69 -10
  210. package/dist/language/flows/narrow-write.d.ts +7 -0
  211. package/dist/language/flows/narrow-write.js +36 -1
  212. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  213. package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
  214. package/dist/language/flows/recording/tape/recordings.js +60 -10
  215. package/dist/language/flows/replay.js +29 -6
  216. package/dist/language/flows/single-replay.d.ts +7 -0
  217. package/dist/language/flows/single-replay.js +26 -0
  218. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  219. package/dist/language/flows/verify-change-tools.js +200 -193
  220. package/dist/memory/cloud/cloud-config.d.ts +10 -1
  221. package/dist/memory/cloud/cloud-config.js +19 -5
  222. package/dist/memory/cloud/cloud-sync.js +3 -3
  223. package/dist/memory/cloud/harness-config.d.ts +49 -0
  224. package/dist/memory/cloud/harness-config.js +16 -20
  225. package/dist/memory/cloud/memory-scope.d.ts +17 -0
  226. package/dist/memory/cloud/memory-scope.js +22 -0
  227. package/dist/memory/cloud/sync-cycle.d.ts +32 -4
  228. package/dist/memory/cloud/sync-cycle.js +113 -12
  229. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  230. package/dist/memory/cloud/sync-daemon.js +114 -4
  231. package/dist/memory/cloud/sync-disk.js +26 -2
  232. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  233. package/dist/memory/cloud/sync-screenshots.js +105 -0
  234. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  235. package/dist/memory/cloud/unsynced-roots.js +166 -0
  236. package/dist/memory/impact/account-watch.d.ts +16 -1
  237. package/dist/memory/impact/account-watch.js +26 -1
  238. package/dist/memory/impact/impact-store.d.ts +1 -4
  239. package/dist/memory/impact/impact-store.js +32 -42
  240. package/dist/memory/intent/inline-intent.d.ts +1 -0
  241. package/dist/memory/intent/intent-shard-store.js +16 -4
  242. package/dist/memory/intent/intent-shard.d.ts +12 -0
  243. package/dist/memory/intent/intent-store.d.ts +1 -0
  244. package/dist/memory/intent/intent-tools.js +42 -2
  245. package/dist/memory/intent/open-intents.d.ts +6 -0
  246. package/dist/memory/intent/open-intents.js +10 -1
  247. package/dist/memory/intent/settled-words.d.ts +24 -0
  248. package/dist/memory/intent/settled-words.js +130 -0
  249. package/dist/memory/journal/drive-flow.d.ts +16 -0
  250. package/dist/memory/journal/drive-flow.js +34 -2
  251. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  252. package/dist/memory/journal/drive-run-flush.js +20 -5
  253. package/dist/memory/journal/journal-recorder.js +46 -3
  254. package/dist/memory/journal/on-disk/retention.d.ts +5 -0
  255. package/dist/memory/journal/on-disk/retention.js +27 -2
  256. package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
  257. package/dist/memory/journal/session-end.d.ts +15 -1
  258. package/dist/memory/journal/session-end.js +38 -7
  259. package/dist/memory/project/artifact-root-resolver.js +33 -5
  260. package/dist/memory/project/artifact-root.d.ts +4 -3
  261. package/dist/memory/project/artifact-root.js +2 -2
  262. package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
  263. package/dist/memory/project/dir/reticle-dir.js +23 -2
  264. package/dist/memory/project/link-directory.d.ts +15 -0
  265. package/dist/memory/project/link-directory.js +44 -0
  266. package/dist/memory/project/root-claims.d.ts +6 -0
  267. package/dist/memory/project/root-claims.js +39 -0
  268. package/dist/memory/project/session-root.d.ts +2 -0
  269. package/dist/memory/project/session-root.js +9 -1
  270. package/dist/memory/project/sync-status.d.ts +46 -0
  271. package/dist/memory/project/sync-status.js +135 -1
  272. package/dist/memory/recall/memory-tools.js +46 -3
  273. package/dist/memory/recall/platform-memory.d.ts +34 -0
  274. package/dist/memory/recall/platform-memory.js +139 -0
  275. package/dist/memory/recall/project-memory.js +36 -8
  276. package/dist/portal/bridge/bridge.d.ts +9 -5
  277. package/dist/portal/bridge/bridge.js +66 -23
  278. package/dist/portal/bridge/harness-request.d.ts +23 -0
  279. package/dist/portal/bridge/harness-request.js +27 -0
  280. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  281. package/dist/portal/bridge/wrong-path.js +35 -0
  282. package/dist/portal/input/network-mock-tools.js +11 -2
  283. package/dist/portal/input/real-input.d.ts +2 -0
  284. package/dist/portal/input/real-input.js +13 -10
  285. package/dist/portal/pool/browser-pool.d.ts +48 -0
  286. package/dist/portal/pool/browser-pool.js +120 -2
  287. package/dist/portal/pool/context-permissions.d.ts +33 -0
  288. package/dist/portal/pool/context-permissions.js +33 -0
  289. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  290. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  291. package/dist/portal/pool/playwright-launcher.d.ts +27 -5
  292. package/dist/portal/pool/playwright-launcher.js +59 -14
  293. package/dist/portal/pool/pool-contract.d.ts +21 -1
  294. package/dist/portal/session/agent-link.d.ts +8 -0
  295. package/dist/portal/session/agent-link.js +17 -0
  296. package/dist/portal/session/command-payload.js +6 -1
  297. package/dist/portal/session/daemon-answers.d.ts +3 -3
  298. package/dist/portal/session/daemon-answers.js +4 -2
  299. package/dist/portal/session/dev-server/dev-command.d.ts +9 -0
  300. package/dist/portal/session/dev-server/dev-command.js +27 -1
  301. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  302. package/dist/portal/session/facts/observed-state.js +46 -3
  303. package/dist/portal/session/human/live-control.d.ts +9 -2
  304. package/dist/portal/session/human/live-control.js +12 -3
  305. package/dist/portal/session/live-control-tools.js +82 -13
  306. package/dist/portal/session/narration-args.d.ts +5 -0
  307. package/dist/portal/session/narration-args.js +17 -0
  308. package/dist/portal/session/no-session-diagnosis.d.ts +1 -1
  309. package/dist/portal/session/no-session-diagnosis.js +31 -9
  310. package/dist/portal/session/no-session-next-action.d.ts +20 -0
  311. package/dist/portal/session/no-session-next-action.js +134 -61
  312. package/dist/portal/session/no-session-watch.js +179 -22
  313. package/dist/portal/session/presence/session-lease.js +1 -1
  314. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  315. package/dist/portal/session/recorded-gaps.js +251 -0
  316. package/dist/portal/session/session-health.d.ts +11 -0
  317. package/dist/portal/session/session-health.js +3 -1
  318. package/dist/portal/session/session-info.js +2 -1
  319. package/dist/portal/session/session-manager.d.ts +18 -0
  320. package/dist/portal/session/session-manager.js +54 -3
  321. package/dist/portal/session/session-successor.d.ts +8 -0
  322. package/dist/portal/session/session-successor.js +1 -1
  323. package/dist/portal/session/session.d.ts +15 -28
  324. package/dist/portal/session/session.js +60 -61
  325. package/dist/portal/session/timing/command-timeout.js +25 -1
  326. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  327. package/dist/portal/session/timing/wall-clock.js +1 -1
  328. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  329. package/dist/portal/session/zero-install-first-call.js +88 -0
  330. package/dist/start-options.d.ts +7 -1
  331. package/dist/start-wiring.d.ts +63 -0
  332. package/dist/start-wiring.js +169 -0
  333. package/dist/status-payload.d.ts +13 -1
  334. package/dist/status-payload.js +13 -1
  335. package/dist/surface/http-server.js +7 -1
  336. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  337. package/dist/surface/mcp/attach-memory.js +12 -1
  338. package/dist/surface/mcp/mcp-proxy.d.ts +4 -0
  339. package/dist/surface/mcp/mcp-proxy.js +29 -8
  340. package/dist/surface/mcp/mcp.d.ts +23 -0
  341. package/dist/surface/mcp/mcp.js +34 -4
  342. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  343. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  344. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  345. package/dist/surface/mcp/server-instructions.js +22 -14
  346. package/dist/surface/mcp/shared-params.js +1 -1
  347. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  348. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  349. package/dist/surface/tools/account-tool.d.ts +22 -0
  350. package/dist/surface/tools/account-tool.js +157 -0
  351. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  352. package/dist/surface/tools/act/act-danger.js +38 -1
  353. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  354. package/dist/surface/tools/act/act-observation.js +57 -0
  355. package/dist/surface/tools/act/act-preflight.js +25 -2
  356. package/dist/surface/tools/act/act-target.js +8 -3
  357. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  358. package/dist/surface/tools/act/resolve-target.js +18 -3
  359. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  360. package/dist/surface/tools/act/screen-request.js +113 -0
  361. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  362. package/dist/surface/tools/act/sequence-grade.js +13 -2
  363. package/dist/surface/tools/act-sequence-tool.js +136 -27
  364. package/dist/surface/tools/act-tools.d.ts +0 -9
  365. package/dist/surface/tools/act-tools.js +48 -34
  366. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  367. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  368. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  369. package/dist/surface/tools/agent/app-notes.js +48 -0
  370. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  371. package/dist/surface/tools/agent/build-staleness.js +62 -0
  372. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  373. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  374. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  375. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  376. package/dist/surface/tools/agent/notices.d.ts +50 -0
  377. package/dist/surface/tools/agent/notices.js +152 -0
  378. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  379. package/dist/surface/tools/agent/reteach.js +50 -0
  380. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  381. package/dist/surface/tools/args/alias-args.js +10 -0
  382. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  383. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  384. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  385. package/dist/surface/tools/assert/assert-source.js +40 -0
  386. package/dist/surface/tools/assert/assert-verdict.js +25 -15
  387. package/dist/surface/tools/browser-tools.js +43 -1
  388. package/dist/surface/tools/chat-drives.d.ts +75 -0
  389. package/dist/surface/tools/chat-drives.js +265 -21
  390. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  391. package/dist/surface/tools/coverage-tools.js +2 -53
  392. package/dist/surface/tools/dynamic-tools.js +29 -1
  393. package/dist/surface/tools/empty-session-list.d.ts +10 -0
  394. package/dist/surface/tools/empty-session-list.js +45 -5
  395. package/dist/surface/tools/error-recovery.d.ts +8 -0
  396. package/dist/surface/tools/error-recovery.js +69 -5
  397. package/dist/surface/tools/explore-tools.d.ts +23 -2
  398. package/dist/surface/tools/explore-tools.js +377 -74
  399. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  400. package/dist/surface/tools/feedback-tools.js +4 -3
  401. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  402. package/dist/surface/tools/gap-novelty.js +8 -1
  403. package/dist/surface/tools/harness-explore.d.ts +52 -73
  404. package/dist/surface/tools/harness-explore.js +177 -146
  405. package/dist/surface/tools/harness-gate.d.ts +88 -0
  406. package/dist/surface/tools/harness-gate.js +235 -0
  407. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  408. package/dist/surface/tools/harness-hunt.js +215 -0
  409. package/dist/surface/tools/harness-plan.d.ts +5 -0
  410. package/dist/surface/tools/harness-plan.js +7 -0
  411. package/dist/surface/tools/harness-script.d.ts +22 -0
  412. package/dist/surface/tools/harness-script.js +256 -38
  413. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  414. package/dist/surface/tools/harness-tab-guard.js +27 -0
  415. package/dist/surface/tools/harness-toolset.d.ts +8 -0
  416. package/dist/surface/tools/harness-toolset.js +27 -4
  417. package/dist/surface/tools/human-notes.d.ts +16 -0
  418. package/dist/surface/tools/human-notes.js +27 -0
  419. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  420. package/dist/surface/tools/invoke-tool.js +220 -93
  421. package/dist/surface/tools/lease-hint.js +26 -5
  422. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  423. package/dist/surface/tools/lease-permissions.js +73 -0
  424. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  425. package/dist/surface/tools/lease-readiness.js +57 -0
  426. package/dist/surface/tools/lease-seed.d.ts +20 -0
  427. package/dist/surface/tools/lease-seed.js +45 -1
  428. package/dist/surface/tools/lease-tools.d.ts +10 -1
  429. package/dist/surface/tools/lease-tools.js +119 -69
  430. package/dist/surface/tools/live-call-text.js +2 -2
  431. package/dist/surface/tools/merge-tools.js +42 -2
  432. package/dist/surface/tools/merged-name-redirect.js +4 -0
  433. package/dist/surface/tools/next-step.d.ts +11 -1
  434. package/dist/surface/tools/next-step.js +73 -18
  435. package/dist/surface/tools/observe-tools.js +43 -5
  436. package/dist/surface/tools/platform-moment.d.ts +60 -0
  437. package/dist/surface/tools/platform-moment.js +132 -4
  438. package/dist/surface/tools/read-tools.js +65 -14
  439. package/dist/surface/tools/reticle-result.d.ts +120 -0
  440. package/dist/surface/tools/reticle-result.js +364 -0
  441. package/dist/surface/tools/tool-kit.d.ts +68 -2
  442. package/dist/surface/tools/tool-kit.js +73 -1
  443. package/dist/surface/tools/tools.js +25 -13
  444. package/dist/telemetry/account-envelope.d.ts +7 -0
  445. package/dist/telemetry/account-envelope.js +61 -0
  446. package/dist/telemetry/agent-client.d.ts +15 -0
  447. package/dist/telemetry/agent-client.js +57 -0
  448. package/dist/telemetry/app-instrumented.js +9 -2
  449. package/dist/telemetry/argument-shape.d.ts +7 -0
  450. package/dist/telemetry/argument-shape.js +86 -1
  451. package/dist/telemetry/automation-hint.d.ts +2 -3
  452. package/dist/telemetry/automation-hint.js +33 -8
  453. package/dist/telemetry/cli-telemetry.js +7 -2
  454. package/dist/telemetry/daemon-telemetry.js +3 -0
  455. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  456. package/dist/telemetry/error-fingerprint.js +61 -5
  457. package/dist/telemetry/feedback-cli.d.ts +0 -13
  458. package/dist/telemetry/feedback-cli.js +0 -77
  459. package/dist/telemetry/feedback.d.ts +13 -0
  460. package/dist/telemetry/feedback.js +183 -17
  461. package/dist/telemetry/harness-run.d.ts +18 -0
  462. package/dist/telemetry/harness-run.js +80 -0
  463. package/dist/telemetry/hud-events.d.ts +16 -0
  464. package/dist/telemetry/hud-events.js +27 -0
  465. package/dist/telemetry/hud-metrics.d.ts +27 -6
  466. package/dist/telemetry/hud-metrics.js +99 -25
  467. package/dist/telemetry/init-telemetry.js +2 -2
  468. package/dist/telemetry/install-source.d.ts +13 -25
  469. package/dist/telemetry/install-source.js +44 -3
  470. package/dist/telemetry/mcp-connection.d.ts +0 -14
  471. package/dist/telemetry/mcp-connection.js +5 -1
  472. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  473. package/dist/telemetry/onboarding-firsts.js +81 -6
  474. package/dist/telemetry/platform-linked.d.ts +5 -0
  475. package/dist/telemetry/platform-linked.js +32 -0
  476. package/dist/telemetry/project-profile.js +5 -3
  477. package/dist/telemetry/proxy-telemetry.js +4 -1
  478. package/dist/telemetry/session-metrics.d.ts +15 -4
  479. package/dist/telemetry/session-metrics.js +88 -52
  480. package/dist/telemetry/telemetry.d.ts +26 -2
  481. package/dist/telemetry/telemetry.js +102 -21
  482. package/dist/telemetry/verification-of.d.ts +3 -1
  483. package/dist/telemetry/verification-of.js +12 -4
  484. package/dist/wire-journal.d.ts +2 -2
  485. package/dist/wire-journal.js +16 -5
  486. package/docs/README.md +2 -2
  487. package/docs/actions.mdx +6 -3
  488. package/docs/adapters.md +1 -1
  489. package/docs/agent-cheatsheet.md +24 -27
  490. package/docs/architecture.md +5 -5
  491. package/docs/autodrive.md +13 -12
  492. package/docs/benchmarks.md +5 -5
  493. package/docs/best-practices.mdx +27 -9
  494. package/docs/capabilities.mdx +14 -16
  495. package/docs/cli/affected.mdx +1 -1
  496. package/docs/cli/cloud.mdx +54 -75
  497. package/docs/cli/doctor.mdx +8 -3
  498. package/docs/cli/drive.mdx +12 -12
  499. package/docs/cli/feedback.mdx +3 -3
  500. package/docs/cli/gate.mdx +7 -2
  501. package/docs/cli/help.mdx +50 -55
  502. package/docs/cli/init.mdx +32 -15
  503. package/docs/cli/license.mdx +12 -8
  504. package/docs/cli/mcp.mdx +4 -4
  505. package/docs/cli/open.mdx +3 -3
  506. package/docs/cli/report.mdx +4 -2
  507. package/docs/cli/restart.mdx +2 -2
  508. package/docs/cli/rollback.mdx +14 -8
  509. package/docs/cli/serve.mdx +4 -4
  510. package/docs/cli/setup.mdx +23 -0
  511. package/docs/cli/status.mdx +13 -4
  512. package/docs/cli/stop.mdx +67 -8
  513. package/docs/cli/try.mdx +62 -0
  514. package/docs/cli/update.mdx +4 -3
  515. package/docs/cli/verify.mdx +17 -6
  516. package/docs/cli/version.mdx +3 -2
  517. package/docs/cli.mdx +110 -41
  518. package/docs/debugging.md +3 -3
  519. package/docs/deploy-checks.md +1 -1
  520. package/docs/desktop.mdx +5 -3
  521. package/docs/enterprise.md +11 -10
  522. package/docs/environment.mdx +5 -2
  523. package/docs/faq.mdx +3 -3
  524. package/docs/first-drive.md +5 -4
  525. package/docs/flows.md +35 -27
  526. package/docs/for-agents.md +4 -5
  527. package/docs/frameworks.mdx +32 -21
  528. package/docs/getting-started.md +66 -64
  529. package/docs/human-control.md +15 -14
  530. package/docs/index.mdx +15 -43
  531. package/docs/install-agentic.mdx +22 -37
  532. package/docs/install-manual.mdx +22 -12
  533. package/docs/instrumentation.mdx +5 -3
  534. package/docs/integration-patterns.md +7 -7
  535. package/docs/license-activation.mdx +1 -1
  536. package/docs/multi-agent-testing.md +24 -6
  537. package/docs/packages/babel-plugin.mdx +4 -2
  538. package/docs/packages/browser.mdx +16 -10
  539. package/docs/packages/core.mdx +12 -5
  540. package/docs/packages/electron.mdx +3 -2
  541. package/docs/packages/engine.mdx +1 -1
  542. package/docs/packages/eslint-plugin.mdx +18 -12
  543. package/docs/packages/next.mdx +8 -7
  544. package/docs/packages/open-verification.mdx +1 -1
  545. package/docs/packages/server.mdx +5 -5
  546. package/docs/packages/tauri.mdx +8 -8
  547. package/docs/packages/test.mdx +4 -10
  548. package/docs/packages/vite-plugin.mdx +11 -4
  549. package/docs/packages.mdx +11 -15
  550. package/docs/platform-integration.md +6 -5
  551. package/docs/predicates.mdx +40 -24
  552. package/docs/quickstart.mdx +58 -29
  553. package/docs/required-checks.md +8 -7
  554. package/docs/reticle-manual.md +15 -5
  555. package/docs/skill-file.mdx +17 -79
  556. package/docs/skill-setup.md +9 -9
  557. package/docs/skill.md +200 -0
  558. package/docs/system-map.md +7 -7
  559. package/docs/telemetry.md +22 -24
  560. package/docs/testing.md +4 -4
  561. package/docs/token-efficiency.md +12 -12
  562. package/docs/tools/act-and-wait.mdx +9 -2
  563. package/docs/tools/act-sequence.mdx +6 -7
  564. package/docs/tools/act.mdx +2 -2
  565. package/docs/tools/assert.mdx +18 -17
  566. package/docs/tools/console.mdx +9 -9
  567. package/docs/tools/inspect.mdx +16 -7
  568. package/docs/tools/look.mdx +24 -0
  569. package/docs/tools/navigate.mdx +5 -3
  570. package/docs/tools/network.mdx +2 -2
  571. package/docs/tools/observe.mdx +6 -6
  572. package/docs/tools/overview.mdx +34 -33
  573. package/docs/tools/query.mdx +5 -5
  574. package/docs/tools/session-and-feedback.mdx +13 -4
  575. package/docs/tools/sessions.mdx +8 -8
  576. package/docs/tools/snapshot.mdx +6 -5
  577. package/docs/tools/state.mdx +9 -9
  578. package/docs/tools/tools-and-run.mdx +26 -24
  579. package/docs/tools/verify.mdx +28 -0
  580. package/docs/tools/wait-for.mdx +8 -4
  581. package/docs/troubleshooting.mdx +21 -6
  582. package/docs/usage.md +51 -45
  583. package/docs/use-cases.mdx +3 -3
  584. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  585. package/docs/vs-playwright-mcp.mdx +3 -1
  586. package/docs/what-is-recorded.md +7 -5
  587. package/docs/what-is-reticle.mdx +2 -2
  588. package/docs/why-reticle.mdx +1 -1
  589. package/package.json +6 -5
  590. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  591. package/dist/command/cli/demo/demo-page.js +0 -249
  592. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  593. package/dist/command/cli/demo/demo-run.js +0 -138
  594. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  595. package/dist/judgement/hunt/hunt-report.js +0 -84
  596. package/dist/language/flows/buddy-status.d.ts +0 -25
  597. package/dist/language/flows/buddy-status.js +0 -32
  598. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  599. package/dist/language/flows/change/watch-batcher.js +0 -19
  600. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  601. package/dist/memory/cloud/harness-offer.js +0 -145
  602. package/dist/surface/tools/feature-capture.d.ts +0 -151
  603. package/dist/surface/tools/feature-capture.js +0 -235
  604. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  605. package/dist/surface/tools/tool-hit-rate.js +0 -90
  606. package/dist/telemetry/harness-drive.d.ts +0 -4
  607. package/dist/telemetry/harness-drive.js +0 -35
  608. package/dist/telemetry/identify.d.ts +0 -22
  609. package/dist/telemetry/identify.js +0 -73
  610. package/docs/cli/capsules.mdx +0 -70
  611. package/docs/cli/hunt.mdx +0 -73
  612. package/docs/cli/identify.mdx +0 -76
  613. package/docs/cli/kill.mdx +0 -91
  614. package/docs/cli/watch.mdx +0 -62
@@ -1,11 +1,21 @@
1
+ import { takeCallSecrets, withCallSecrets } from './tool-kit.js';
1
2
  import { healthEnvelope } from '../../portal/session/session-health.js';
2
3
  import { logToolCall, toolLogPath } from '../../hooks/tool-log.js';
3
4
  import { nextStep } from './next-step.js';
4
5
  import { currentDrivenBy } from '../../hooks/driven-by.js';
5
- import { sessionRoot } from '../../memory/project/session-root.js';
6
- import { takePlatformMoment } from './platform-moment.js';
6
+ import { runAsAgent } from '../../hooks/coding-agents.js';
7
+ import { takeHumanNotes } from './human-notes.js';
8
+ import { takeDriveNotes } from '../../features/harness/drive-runs.js';
9
+ import { harnessDriving, msgHarnessHasTheTab } from './harness-tab-guard.js';
10
+ import { sessionRoot, sessionTarget } from '../../memory/project/session-root.js';
11
+ import { ArtifactRootReason } from '../../memory/project/artifact-root.js';
12
+ import { agentNudge, takePlatformMoment } from './platform-moment.js';
13
+ import { RESULT_FIELD, trackVerdict } from './reticle-result.js';
14
+ import { forTheAgent } from './agent/for-the-agent.js';
15
+ import { feedbackAlreadyAsked, noteFeedbackAsked } from './agent/notices.js';
16
+ import { SKEW_SHORT_WARNING, SKEW_VERDICT_WARNING } from '../../portal/session/session-health.js';
7
17
  import { verifyNextBaton, SUPPRESS_VERIFY_NEXT_ENV } from './verify-next-baton.js';
8
- import { TelemetryActor, TelemetryEventKind, TRANSPORT_LIMITS, fingerprintFinding, } from '@reticlehq/core';
18
+ import { TelemetryActor, TelemetryEventKind, THROTTLED_WARNING, TRANSPORT_LIMITS, fingerprintFinding, } from '@reticlehq/core';
9
19
  import { getSessionMetrics } from '../../telemetry/session-metrics.js';
10
20
  import { getTelemetry } from '../../telemetry/telemetry.js';
11
21
  import { takeUpdateNudge } from '../../command/update/update-nudge.js';
@@ -18,21 +28,19 @@ import { buildErrorPayload, refusalReasonFor } from './error-recovery.js';
18
28
  import { resultIsError } from '../mcp/faults/mcp-is-error.js';
19
29
  import { verificationOf } from '../../telemetry/verification-of.js';
20
30
  import { emitBugFoundHook, emitVerdictHook } from '../../hooks/hook-emit.js';
21
- import { reportOnboardingStep } from '../../telemetry/onboarding-funnel.js';
22
- import { noteActed, noteFirstVerdict, noteOnboardingFirst } from '../../telemetry/onboarding-firsts.js';
23
- import { withHarnessDrive } from '../../telemetry/harness-drive.js';
24
- import { OnboardingPhase, OnboardingStepStatus } from '@reticlehq/core/telemetry';
25
- import { DiscoveryInvite, asString } from '@reticlehq/core';
31
+ import { noteActed, noteFirstVerdict, noteOnboardingFirst, noteVerdictProduced, } from '../../telemetry/onboarding-firsts.js';
32
+ import { DiscoveryInvite } from '@reticlehq/core';
26
33
  import { SESSION_ID_ARG, sessionIdFromArgs, spentRefFromArgs } from './tools-helpers.js';
27
- import { EnvelopeKey } from './tool-kit.js';
34
+ import { EnvelopeKey, HOST_STUB_NOTE, STEP_SHOT_TOOLS } from './tool-kit.js';
28
35
  import { ReticleTool } from '@reticlehq/core';
29
36
  import { takeFeedbackPrompt } from './feedback-tools.js';
30
37
  import { takeFeedbackUndelivered } from '../../telemetry/feedback-delivery.js';
31
38
  import { noteRefsMinted, wrongTabRefusal } from '../../portal/session/facts/ref-provenance.js';
32
- import { CAPTURED_TOOLS, noteCapturedCall, noteToolDispatched, } from './feature-capture.js';
33
39
  import { span } from '../../trace.js';
40
+ import { takeStepShot } from '../../features/visual/step-shots.js';
34
41
  import { defectForToolResult, deltaForToolResult, impactSnapshot, initImpact, recordImpact, } from '../../memory/impact/impact-recorder.js';
35
- import { frictionOf, inviteFor } from './feedback-invite.js';
42
+ import { FrictionKind, frictionOf, inviteFor } from './feedback-invite.js';
43
+ import { VACUOUS_BECAUSE } from '@reticlehq/engine/evidence/verified.js';
36
44
  /**
37
45
  * The live-session tools whose result MUST carry the
38
46
  * session-health envelope. Owned in ONE place — not retrofitted per handler — so a throttled tab
@@ -158,17 +166,6 @@ export const SESSION_EXEMPT_TOOLS = new Set([
158
166
  // when NO session exists — "nothing ever connected" is feedback we especially want.
159
167
  ReticleTool.FEEDBACK,
160
168
  ]);
161
- /**
162
- * The merged action that hands the drive to a model inside the daemon.
163
- *
164
- * Derived from the member tool's own name rather than spelled again: the merge dispatches on
165
- * `action`, and `reticle_verify` plus `explore` IS `reticle_verify_explore`. A literal here would be
166
- * a third spelling of one name, and the one that silently stops matching when the action is renamed.
167
- */
168
- const HARNESS_DRIVE_ACTION = ReticleTool.VERIFY_EXPLORE.slice(`${ReticleTool.VERIFY}_`.length);
169
- function isHarnessDrive(toolName, args) {
170
- return ReticleTool.VERIFY === toolName && HARNESS_DRIVE_ACTION === args['action'];
171
- }
172
169
  function isPlainObject(value) {
173
170
  return 'object' === typeof value && value !== null && !Array.isArray(value);
174
171
  }
@@ -183,7 +180,7 @@ function isPlainObject(value) {
183
180
  * The RULE itself lives in verification-of.ts, because getting it wrong fails silently.
184
181
  */
185
182
  function recordVerification(toolName, result, durationMs, brand, sessionId) {
186
- const verification = verificationOf(toolName, result, durationMs, brand);
183
+ const verification = verificationOf(toolName, result, durationMs, brand, currentDrivenBy() !== undefined);
187
184
  if (verification === undefined)
188
185
  return;
189
186
  getSessionMetrics().recordVerification();
@@ -202,12 +199,8 @@ function recordVerification(toolName, result, durationMs, brand, sessionId) {
202
199
  emitVerdictHook(toolName, result, verification.verified, sessionId);
203
200
  // The ONBOARD half of the same moment: the first verdict of this run, once.
204
201
  noteFirstVerdict();
205
- void reportOnboardingStep({
206
- phase: OnboardingPhase.FIRST_RUN,
207
- step: 'verdict_produced',
208
- status: OnboardingStepStatus.COMPLETED,
209
- elapsedMs: Math.max(0, Math.round(durationMs)),
210
- });
202
+ // The FIRST_RUN rung: once per machine + project, not once per verdict.
203
+ noteVerdictProduced(durationMs);
211
204
  }
212
205
  /**
213
206
  * Emit one `bug_found` per defect in a tool result, and count it into the session.
@@ -231,9 +224,15 @@ function reportBugsFound(toolName, result, sessionId) {
231
224
  ? { kind: bug.kind, source: bug.source, route }
232
225
  : { kind: bug.kind, source: bug.source };
233
226
  const fingerprint = fingerprintFinding(identity);
227
+ const occurrence = metrics.recordBugOccurrence(fingerprint);
234
228
  void getTelemetry().emit(TelemetryEventKind.BUG_FOUND, {
235
229
  actor: TelemetryActor.AGENT,
236
- bug: { ...bug, repeat: !first, fingerprint },
230
+ bug: {
231
+ ...bug,
232
+ repeat: !first,
233
+ fingerprint,
234
+ ...(occurrence === undefined ? {} : { occurrence }),
235
+ },
237
236
  });
238
237
  // The same defect, said out loud to whoever is building on Reticle. Inside the loop rather than
239
238
  // after it because the event is PER DEFECT — one event carrying a list would make a consumer
@@ -278,7 +277,9 @@ function frictionInviteFor(toolName, raw) {
278
277
  return undefined;
279
278
  const friction = frictionOf({
280
279
  unknownTool: false,
281
- verifiedUnknown: 'unknown' === raw['verified'],
280
+ // A vacuous unknown is the caller's: it asserted nothing real (a bare `settled` wait, which the
281
+ // instructions recommend). Inviting a bug report there told agents Reticle had failed them.
282
+ verifiedUnknown: 'unknown' === raw['verified'] && VACUOUS_BECAUSE !== raw['because'],
282
283
  repeatRun: getSessionMetrics().currentRun,
283
284
  errored: resultIsError(raw),
284
285
  // A verdict is progress. Without this, three successful act_and_wait calls in a row — the exact
@@ -344,13 +345,52 @@ function pinnedArgs(args, explicitSessionId, session) {
344
345
  return args;
345
346
  return { ...args, [SESSION_ID_ARG]: session.id };
346
347
  }
347
- export async function runTool(tool, deps, args) {
348
+ export async function runTool(tool, deps, given, call) {
349
+ // A replay's secrets leave the arguments here, before the tool log, the journal or telemetry can
350
+ // see them, and are supplied to this call alone.
351
+ const { secrets, rest: args } = takeCallSecrets(given);
352
+ // A verdict still being decided is waited for by a session end (`trackVerdict`); the result is
353
+ // compacted for the agent last, after telemetry and the tool log have read the full result.
354
+ return trackVerdict(tool.name, withCallSecrets(secrets, async () => {
355
+ const result = await loggedTool(tool, deps, args, call);
356
+ const attach = currentDrivenBy() === undefined ? deps.attachId : undefined;
357
+ const root = attach === undefined
358
+ ? undefined
359
+ : safeRoot(() => sessionRoot(deps, sessionIdFromArgs(args)));
360
+ return forTheAgent({ name: tool.name, args, result, attach, root, fold: NOTICE_FOLD });
361
+ }));
362
+ }
363
+ /** Advisories that become once-per-session notice lines. See agent/notices.ts. */
364
+ export const NOTICE_FOLD = {
365
+ advisories: [
366
+ EnvelopeKey.FEEDBACK_PROMPT,
367
+ EnvelopeKey.FEEDBACK_INVITE,
368
+ EnvelopeKey.TALK_TO_US,
369
+ EnvelopeKey.UPDATE_AVAILABLE,
370
+ // NOT `version_skew`: it is decisive — it explains every result after it and names the command to
371
+ // run — so it rides out as its own key, untouched (one-shot at its source already).
372
+ EnvelopeKey.PLATFORM,
373
+ EnvelopeKey.SESSION_LEASE,
374
+ EnvelopeKey.SESSION_AGE_WARNING,
375
+ EnvelopeKey.FEEDBACK_UNDELIVERED,
376
+ EnvelopeKey.ZERO_INSTALL,
377
+ ],
378
+ notices: EnvelopeKey.NOTICES,
379
+ next: EnvelopeKey.NEXT,
380
+ warning: EnvelopeKey.WARNING,
381
+ onceWarnings: new Map([
382
+ // `session.throttled` still rides on every result: only the paragraph explaining it goes.
383
+ [THROTTLED_WARNING, undefined],
384
+ [SKEW_VERDICT_WARNING, SKEW_SHORT_WARNING],
385
+ ]),
386
+ };
387
+ async function loggedTool(tool, deps, args, call) {
348
388
  const logPath = toolLogPath();
349
389
  if (logPath === undefined)
350
- return dispatchTool(tool, deps, args);
390
+ return dispatchTool(tool, deps, args, call);
351
391
  const at = deps.now();
352
392
  try {
353
- const result = await dispatchTool(tool, deps, args);
393
+ const result = await dispatchTool(tool, deps, args, call);
354
394
  logToolCall(logPath, { tool: tool.name, args, at, ms: deps.now() - at, result });
355
395
  return result;
356
396
  }
@@ -360,7 +400,7 @@ export async function runTool(tool, deps, args) {
360
400
  throw error;
361
401
  }
362
402
  }
363
- async function dispatchTool(tool, deps, args) {
403
+ async function dispatchTool(tool, deps, args, call) {
364
404
  // Both dispatch paths (MCP + programmatic) pass through here — the one place "which tool is mostly
365
405
  // used" can be counted. This used to EMIT an event per call; it now increments an in-process counter
366
406
  // that leaves once, with the session summary. A verification loop is 50–200 calls, and PostHog bills
@@ -399,6 +439,14 @@ async function dispatchTool(tool, deps, args) {
399
439
  reportRefusal(tool.name, error);
400
440
  return { error };
401
441
  }
442
+ // One driver per tab. The Harness clicking through a page while the agent clicks too is two hands
443
+ // on one mouse: neither result means anything. The agent's own action waits; its reads still run.
444
+ const busy = ACTION_TOOLS.has(tool.name) ? harnessDriving(deps, args) : undefined;
445
+ if (busy !== undefined) {
446
+ const error = msgHarnessHasTheTab(busy);
447
+ reportRefusal(tool.name, error);
448
+ return { error };
449
+ }
402
450
  // An ACTION is what gets abandoned. Counted here, against verifications, so "the agent drove the
403
451
  // page and then wandered off" becomes a number instead of an impression.
404
452
  if (ACTION_TOOLS.has(tool.name)) {
@@ -423,6 +471,24 @@ async function dispatchTool(tool, deps, args) {
423
471
  session = undefined;
424
472
  }
425
473
  }
474
+ // Nothing connected, and the app was never wired: a call that needs a page opens it zero-install
475
+ // rather than answering with a diagnosis the agent stops at. See zero-install-first-call.ts.
476
+ const openUnwired = deps.openUnwiredApp;
477
+ const opened = openUnwired !== undefined &&
478
+ session === undefined &&
479
+ bound &&
480
+ rawSessionId === undefined &&
481
+ 0 === deps.sessions.list().length
482
+ ? await openUnwired()
483
+ : undefined;
484
+ if (opened !== undefined) {
485
+ try {
486
+ session = deps.sessions.resolve(rawSessionId);
487
+ }
488
+ catch {
489
+ session = undefined;
490
+ }
491
+ }
426
492
  // CDP tools against a skewed session: refuse with the sentence reticle_sessions already knows,
427
493
  // before Playwright invents a closed page. ready:true leases still hit this path.
428
494
  if (session?.versionSkew !== undefined && CDP_TOOLS.has(tool.name)) {
@@ -430,43 +496,6 @@ async function dispatchTool(tool, deps, args) {
430
496
  reportRefusal(tool.name, message);
431
497
  throw new Error(message);
432
498
  }
433
- // The read-only calls the journal never keeps, recorded HERE because this is the one dispatch
434
- // point every call routes through — a second recording site is a second thing to forget, and this
435
- // instrument exists precisely because nothing was recorded before. Recorded before the handler
436
- // runs: a read dispatches no action, so the counter reads the same either side.
437
- //
438
- // `reticle_context` is session-EXEMPT, so `session` above is undefined for it and it needs its own
439
- // lenient resolve. Failing that resolve is silent by design: a call made with nothing connected
440
- // has no per-session ledger to land in, and an instrument must never be why a tool call fails.
441
- //
442
- // EVERY tool is counted here, not just the read set: which of the 70-odd names in the table an
443
- // agent actually reaches for is the question a decision about cutting or consolidating the surface
444
- // turns on, and it had no answer. `reticle_run` is the one exclusion, for the same reason
445
- // `reportRefusal` and `bugsInResult` exclude it — its handler calls `runTool` on the real tool, so
446
- // the inner call is already counted under the name that RAN, and counting the wrapper too would
447
- // both double the total and hide the run-only tier behind a single wrapper name. That tier is
448
- // precisely the one the decision hinges on. See surface/tools/tool-hit-rate.ts.
449
- if (ReticleTool.RUN !== tool.name) {
450
- let target = session;
451
- if (target === undefined) {
452
- try {
453
- target = deps.sessions.resolve(rawSessionId);
454
- }
455
- catch {
456
- target = undefined;
457
- }
458
- }
459
- if (target !== undefined) {
460
- noteToolDispatched(target, tool.name);
461
- if (CAPTURED_TOOLS.has(tool.name)) {
462
- const subject = asString(args['ref']) ?? asString(args['target']);
463
- noteCapturedCall(target, {
464
- tool: tool.name,
465
- ...(subject === undefined ? {} : { subject }),
466
- });
467
- }
468
- }
469
- }
470
499
  // A ref that was handed out by a DIFFERENT tab, on a call that named no session. Refused here, at
471
500
  // the one point that knows both the ref and the tab resolution picked — the handler only learns
472
501
  // that the ref missed, and answers that with "the DOM re-rendered", which is a confident diagnosis
@@ -500,16 +529,11 @@ async function dispatchTool(tool, deps, args) {
500
529
  // `dispatchArgs`, not `args`: an inferred session is pinned into the arguments before the
501
530
  // handler sees them, so a tool that resolves the session a second time cannot land on a
502
531
  // different one than the dispatcher chose.
503
- const call = () => span('tool.handler', { tool: tool.name, session: session?.id }, () => tool.handler(deps, dispatchArgs));
504
- // A drive we run on the user's behalf, marked for its whole span so the verdicts it produces
505
- // underneath are distinguishable from the ones the user's own agent earned.
506
- //
507
- // The outer call emits no verdict of its own, and that is the honest answer rather than a gap:
508
- // it drives and records, it adjudicates nothing, and its result carries no verified/pass field
509
- // to read. Deriving one from how far the drive got would be inventing a verdict nobody reached.
510
- // What was missing was never an event here — it was that a session driven BY US read exactly
511
- // like one the agent earned, which is what the span fixes.
512
- raw = await (isHarnessDrive(tool.name, args) ? withHarnessDrive(call) : call());
532
+ const invokeHandler = () => span('tool.handler', { tool: tool.name, session: session?.id }, () => tool.handler(deps, dispatchArgs, call));
533
+ // The Harness's own inner calls carry their drive in an async context (`runDrivenBy`), which is
534
+ // what attributes their verdicts; the outer explore call adjudicates nothing of its own.
535
+ // As the agent on this connection, so a note it reads is marked seen by that agent.
536
+ raw = await runAsAgent(deps.attachId, invokeHandler);
513
537
  }
514
538
  catch (error) {
515
539
  // The commonest refusal shape by far, and the one nothing could see: the message is built, handed
@@ -547,6 +571,7 @@ async function dispatchTool(tool, deps, args) {
547
571
  // concurrency slot and peakConcurrentTools would climb forever on an unhealthy session.
548
572
  settleTiming(Date.now() - startedAt);
549
573
  }
574
+ raw = await withStepShot(tool.name, deps, args, raw, session?.id ?? rawSessionId);
550
575
  // Milestones describe work that ran. Refusals and paused calls must not consume the firsts.
551
576
  // Record action before verdict: act_and_wait can complete both in this same call.
552
577
  if (isPlainObject(raw) && !resultIsError(raw) && raw['paused'] !== true && raw['ok'] !== false) {
@@ -600,7 +625,10 @@ async function dispatchTool(tool, deps, args) {
600
625
  if (session !== undefined && REF_MINTING_TOOLS.has(tool.name))
601
626
  noteRefsMinted(session.id);
602
627
  }
603
- const prompt = isPlainObject(raw) ? takeFeedbackPrompt(tool.name) : undefined;
628
+ // The feedback family is asked at most once per agent session (agent/notices.ts): gated here, at
629
+ // the take, so a suppressed ask is never counted as one that was made.
630
+ const asked = feedbackAlreadyAsked(currentDrivenBy() === undefined ? deps.attachId : undefined);
631
+ const prompt = isPlainObject(raw) && !asked ? takeFeedbackPrompt(tool.name) : undefined;
604
632
  // Same one-shot channel as the feedback ask: the agent is mid-task, so anything it would have to go
605
633
  // and ASK for is something it will never ask for. Spliced on ANY tool result, not just a
606
634
  // verification, because an out-of-date install is worth mentioning whatever the agent is doing.
@@ -625,9 +653,12 @@ async function dispatchTool(tool, deps, args) {
625
653
  // `refused` friction the line is written for. `errored` could only ever see the handlers that
626
654
  // RETURN an error. So the denominator was counting a small, unrepresentative slice of the
627
655
  // invitations and reading near-empty, which looks identical to a nudge that never fires.
628
- const friction = frictionInviteFor(tool.name, raw);
629
- // Once per project, on a proved verdict, when the runs live only on this machine.
630
- const platform = isPlainObject(raw)
656
+ const friction = asked || prompt !== undefined ? undefined : frictionInviteFor(tool.name, raw);
657
+ if (prompt !== undefined || friction !== undefined)
658
+ noteFeedbackAsked(currentDrivenBy() === undefined ? deps.attachId : undefined);
659
+ // Once per project, on a proved verdict, when the runs live only on this machine. Not on a result
660
+ // whose `reticleResult` already ends with the platform line: once per result, never twice.
661
+ const platform = isPlainObject(raw) && !(RESULT_FIELD in raw)
631
662
  ? await takePlatformMoment(deps, raw, () => sessionRoot(deps, rawSessionId))
632
663
  : undefined;
633
664
  // What the agent should do next, on every client that reads results. Not for the Harness, whose
@@ -636,18 +667,48 @@ async function dispatchTool(tool, deps, args) {
636
667
  const next = isPlainObject(raw) && ReticleTool.RUN !== tool.name && currentDrivenBy() === undefined
637
668
  ? nextStep({
638
669
  tool: tool.name,
670
+ unmatched: unmatchedRootOf(deps, rawSessionId),
639
671
  verdict: 'verified' in raw,
640
672
  root: safeRoot(() => sessionRoot(deps, rawSessionId)),
641
673
  // A partial deps (tests, the demo) may carry no clock; the line is advice, never a reason to fail.
642
674
  now: 'function' === typeof deps.now ? deps.now() : Date.now(),
643
675
  })
644
676
  : undefined;
645
- const result = prompt === undefined &&
677
+ // Only an agent's own call (an MCP connection, not the Harness, not the HUD's or the chat's calls
678
+ // into the same tools) takes what is waiting for the agent: those calls answer nobody who reads.
679
+ const answer = isPlainObject(raw) ? raw : undefined;
680
+ const agentCall = answer !== undefined && deps.attachId !== undefined && currentDrivenBy() === undefined;
681
+ // A Harness drive started or finished, from the HUD, the platform's chat or this agent: one line,
682
+ // once. Not about the run this very result already reports.
683
+ // One-time advisories toward the platform and the Harness (`platform-moment.ts`), only on the agent's
684
+ // own calls, riding the same platform line as the moments above.
685
+ const nudge = agentCall && answer !== undefined
686
+ ? await agentNudge({
687
+ deps,
688
+ tool: tool.name,
689
+ raw: answer,
690
+ isError: resultIsError(answer),
691
+ tab: session,
692
+ root: safeRoot(() => sessionRoot(deps, rawSessionId)),
693
+ harnessOn: () => impactSnapshot(artifactRoot)?.harnessConfig?.harnessEnabled,
694
+ })
695
+ : undefined;
696
+ const platformLine = platform === undefined ? nudge : nudge === undefined ? platform : `${platform}\n${nudge}`;
697
+ const drives = agentCall
698
+ ? takeDriveNotes('string' === typeof answer?.['runId'] ? answer['runId'] : undefined)
699
+ : [];
700
+ // The person's notes from the HUD, on ANY tool. Act tools splice their own `control` first.
701
+ const notes = agentCall && answer !== undefined && !(EnvelopeKey.CONTROL in answer)
702
+ ? await runAsAgent(deps.attachId, () => Promise.resolve(takeHumanNotes(deps.sessions, rawSessionId, session)))
703
+ : undefined;
704
+ const result = 0 === drives.length &&
705
+ notes === undefined &&
706
+ prompt === undefined &&
646
707
  update === undefined &&
647
708
  skew === undefined &&
648
709
  undelivered === undefined &&
649
710
  friction === undefined &&
650
- platform === undefined &&
711
+ platformLine === undefined &&
651
712
  next === undefined
652
713
  ? raw
653
714
  : {
@@ -657,14 +718,20 @@ async function dispatchTool(tool, deps, args) {
657
718
  ...(friction !== undefined
658
719
  ? {
659
720
  [EnvelopeKey.FEEDBACK_INVITE]: inviteFor(friction),
660
- // The moment Reticle got in somebody's way is the moment to offer them the founder.
661
- [EnvelopeKey.TALK_TO_US]: DiscoveryInvite.AGENT,
721
+ // The founder's calendar only for an agent genuinely STUCK (the same call, again,
722
+ // with no progress). An ordinary refusal carried it too, and read as a sales pitch
723
+ // stapled to an error message.
724
+ ...(FrictionKind.REPEATING === friction
725
+ ? { [EnvelopeKey.TALK_TO_US]: DiscoveryInvite.AGENT }
726
+ : {}),
662
727
  }
663
728
  : {}),
664
729
  ...(prompt !== undefined ? { [EnvelopeKey.FEEDBACK_PROMPT]: prompt } : {}),
665
730
  ...(update !== undefined ? { [EnvelopeKey.UPDATE_AVAILABLE]: update } : {}),
666
731
  ...(skew !== undefined ? { [EnvelopeKey.VERSION_SKEW]: skew } : {}),
667
- ...(platform !== undefined ? { [EnvelopeKey.PLATFORM]: platform } : {}),
732
+ ...(platformLine !== undefined ? { [EnvelopeKey.PLATFORM]: platformLine } : {}),
733
+ ...(0 === drives.length ? {} : { [EnvelopeKey.HARNESS]: drives.join('\n') }),
734
+ ...(notes === undefined ? {} : { [EnvelopeKey.CONTROL]: notes }),
668
735
  ...(undelivered !== undefined
669
736
  ? {
670
737
  [EnvelopeKey.FEEDBACK_UNDELIVERED]: `your earlier report did NOT send: ${undelivered}. Tell the human what you found so it is not lost.`,
@@ -675,7 +742,15 @@ async function dispatchTool(tool, deps, args) {
675
742
  return result;
676
743
  // Reuse the session resolved above so the health envelope describes the SAME session the handler
677
744
  // drove; only re-resolve if the up-front attempt failed but the handler somehow succeeded.
678
- const driven = session ?? deps.sessions.resolve(rawSessionId);
745
+ // A handler that answered with no tab to resolve (a Harness drive polled by runId after a daemon
746
+ // restart reads its record from disk) keeps its answer: there is no session health to describe.
747
+ let driven = session;
748
+ try {
749
+ driven ??= deps.sessions.resolve(rawSessionId);
750
+ }
751
+ catch {
752
+ return result;
753
+ }
679
754
  // ...unless the call replaced that document. A full navigation or reload registers a NEW Session
680
755
  // under the same id (or under the id the result reports it arrived at), and the object resolved
681
756
  // before the call is the page that unloaded: it reported itself hidden on the way out, so every
@@ -684,6 +759,14 @@ async function dispatchTool(tool, deps, args) {
684
759
  const arrivedId = 'string' === typeof result['sessionId'] ? result['sessionId'] : driven.id;
685
760
  const resolved = deps.sessions.get?.(arrivedId) ?? driven;
686
761
  const envelope = {};
762
+ // A leased tab opened with `initScript` runs a STUB of the bindings a desktop shell injects. Said
763
+ // on every session-bound result, not only on verdicts, for the same reason health is: a green from
764
+ // that tab proves the app's view logic, and nothing else in the result would say so.
765
+ // Optional-called: a partial pool in a test double has no lookup, and absence must read as "no
766
+ // stub", never as a crash on the whole tool surface.
767
+ if (true === deps.pool?.stubInstalled?.(resolved.id)) {
768
+ envelope[EnvelopeKey.HOST_STUB] = HOST_STUB_NOTE;
769
+ }
687
770
  // The health block is idempotent: add it only when the handler didn't already include a `session`.
688
771
  if (!('session' in result))
689
772
  Object.assign(envelope, healthEnvelope(resolved));
@@ -692,8 +775,13 @@ async function dispatchTool(tool, deps, args) {
692
775
  // does) — so a long-running backgrounded session, the case most likely to leak, never got the
693
776
  // one-time pool-lease reminder or the age cleanup nudge. Splice them regardless.
694
777
  const lease = resolved.takeSessionLease();
695
- if (lease !== undefined)
778
+ // In CI there is no panel and no human to hand it back to: the reminder was noise in every
779
+ // pipeline log. Still taken, so the once-per-session cadence is unchanged.
780
+ if (lease !== undefined && process.env['CI'] === undefined) {
696
781
  envelope[EnvelopeKey.SESSION_LEASE] = lease;
782
+ }
783
+ if (opened !== undefined)
784
+ envelope[EnvelopeKey.ZERO_INSTALL] = opened.notice;
697
785
  const warning = resolved.ageWarning();
698
786
  if (warning !== undefined)
699
787
  envelope[EnvelopeKey.SESSION_AGE_WARNING] = warning;
@@ -725,6 +813,23 @@ async function dispatchTool(tool, deps, args) {
725
813
  envelope[EnvelopeKey.VERIFY_NEXT] = verifyNextBaton(unverified, resolved.lastAct?.effect() ?? {});
726
814
  return Object.keys(envelope).length > 0 ? { ...result, ...envelope } : result;
727
815
  }
816
+ /**
817
+ * A picture of the page the moment this call's outcome was decided, named on the result. Only on
818
+ * an answer that touched the page: a refusal or a paused call drove nothing worth a picture. A
819
+ * navigation can land the page under a new id, so the id the result reports wins.
820
+ */
821
+ async function withStepShot(name, deps, args, raw, sessionId) {
822
+ if (!STEP_SHOT_TOOLS.has(name) || Array.isArray(args['steps']))
823
+ return raw;
824
+ if (!isPlainObject(raw) || resultIsError(raw) || true === raw['paused'])
825
+ return raw;
826
+ const tab = 'string' === typeof raw['sessionId'] ? raw['sessionId'] : sessionId;
827
+ if (tab === undefined)
828
+ return raw;
829
+ // Paired with its check when the run is written: the n-th verdict picture is the n-th check.
830
+ const verdict = 'verified' in raw && (ReticleTool.ACT_AND_WAIT === name || ReticleTool.ASSERT === name);
831
+ return { ...raw, [EnvelopeKey.SCREENSHOT]: await takeStepShot(deps, tab, name, { verdict }) };
832
+ }
728
833
  /** A root, or undefined when none can be resolved: a missing root is never a reason to throw. */
729
834
  function safeRoot(get) {
730
835
  try {
@@ -734,3 +839,25 @@ function safeRoot(get) {
734
839
  return undefined;
735
840
  }
736
841
  }
842
+ /**
843
+ * Where this session's evidence goes when no project claims it (`~/.reticle/unmatched/<id>`), with
844
+ * the folders that compete for its id; undefined when it lands in a project. Never throws.
845
+ */
846
+ function unmatchedRootOf(deps, sessionId) {
847
+ try {
848
+ const target = sessionTarget(deps, sessionId);
849
+ const resolved = deps.artifactRootFor?.(target.projectId, target.origin);
850
+ if (resolved === undefined || ArtifactRootReason.MATCHED_PROJECT === resolved.reason)
851
+ return undefined;
852
+ if (resolved.root === deps.reticleRoot)
853
+ return undefined;
854
+ return {
855
+ root: resolved.root,
856
+ contenders: resolved.candidates ?? [],
857
+ ...(resolved.serving === undefined ? {} : { serving: resolved.serving }),
858
+ };
859
+ }
860
+ catch {
861
+ return undefined;
862
+ }
863
+ }
@@ -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 { isLoopbackHostname } from '@reticlehq/core';
20
21
  const NUXT = 'nuxt';
21
22
  const PORT_DIFFERENTIAL = "The usual cause is a PORT MISMATCH: the app's SDK connects to the port it was BUILT with, so a " +
22
23
  "daemon on a different port never hears from it — check the app's reticle port (`.reticle.json`, " +
@@ -36,6 +37,17 @@ const NUXT_FIRST = 'This project is Nuxt: the most likely cause by a distance is
36
37
  'Reticle plugin, because Nuxt does NOT register a newly added plugin on HMR. Restart `nuxt dev` ' +
37
38
  'and re-acquire before investigating anything else.';
38
39
  const RELEASE = 'The tab stays leased either way — release it with reticle_lease{action:"release"}.';
40
+ const PRODUCTION_STUB = ' If this is a production build (`vite build`, `next build`, `next start`, or a deployed site), it strips ' +
41
+ 'Reticle or replaces it with an inert stub by design; point the lease at the dev server instead.';
42
+ function isRemoteUrl(url) {
43
+ try {
44
+ const hostname = new URL(url).hostname.toLowerCase();
45
+ return !isLoopbackHostname(hostname);
46
+ }
47
+ catch {
48
+ return false;
49
+ }
50
+ }
39
51
  function markerClause(sdkMarker) {
40
52
  if (sdkMarker === undefined)
41
53
  return '';
@@ -82,8 +94,8 @@ export function leaseNotConnectedHint(url, port, evidence = {}) {
82
94
  `this daemon is on ${String(port)}, so the dial never reached it. Nothing about the app's ` +
83
95
  `wiring is in question. Either start the daemon on ${String(dialled)}, or point the app at ` +
84
96
  `${String(port)} — the app's port comes from its build config (\`.reticle.json\`, ` +
85
- `RETICLE_PORT, or the build plugin's \`port\`), and \`VITE_RETICLE_WS_URL\` overrides it ` +
86
- `outright.${marker} ${RELEASE}`);
97
+ `RETICLE_PORT, or the build plugin's \`port\`), and \`reticle.connect({ url })\` ` +
98
+ `overrides it outright.${marker} ${RELEASE}`);
87
99
  }
88
100
  // 0b. The page's own policy forbids the connection. Read off the document it served, so it is
89
101
  // proof about the page in hand, and it holds whether or not the app ships an SDK: neither
@@ -118,18 +130,27 @@ export function leaseNotConnectedHint(url, port, evidence = {}) {
118
130
  : ' That may have been a DIFFERENT app, though: this one may carry no Reticle SDK at all, ' +
119
131
  'in which case run `reticle init` in ITS directory first — every cause below assumes the ' +
120
132
  'SDK is already installed.';
133
+ // Never beside a marker that WAS found: "it ships the SDK" and "the build stripped it" cannot
134
+ // both be the story.
135
+ const production = true !== evidence.sdkMarker && (false === evidence.sdkMarker || isRemoteUrl(url))
136
+ ? PRODUCTION_STUB
137
+ : '';
121
138
  return (`${opening} An app for this project HAS connected on this port before, so the port is ` +
122
- `proven.${notThisApp}${nuxt}${marker} ${REAL_CAUSES} ${RELEASE}`);
139
+ `proven.${notThisApp}${nuxt}${marker}${production} ${REAL_CAUSES} ${RELEASE}`);
123
140
  }
124
141
  // 4. Wired, but never seen connect. Rank the real causes; keep the port differential last, where
125
142
  // the evidence for it actually sits.
126
143
  if (true === evidence.initialized) {
127
- return `${opening}${nuxt}${marker} ${REAL_CAUSES} If none of those, it may be dialling a different daemon than this one: check the app's reticle port matches ${String(port)}. ${RELEASE}`;
144
+ const production = false === evidence.sdkMarker ? PRODUCTION_STUB : '';
145
+ return `${opening}${nuxt}${marker}${production} ${REAL_CAUSES} If none of those, it may be dialling a different daemon than this one: check the app's reticle port matches ${String(port)}. ${RELEASE}`;
128
146
  }
129
147
  // 5. Nothing known. The differential, plus the possibility this app carries no SDK at all —
130
148
  // except when the marker check already ruled that out, which is the whole reason for the bit.
149
+ // Nothing says the project was ever wired, so `reticle init` stays the advice whenever the SDK
150
+ // was not seen; a production build is the other way to serve a page without it.
131
151
  const noSdk = true === evidence.sdkMarker
132
152
  ? ''
133
- : ' If the app carries no Reticle SDK at all, run `reticle init` in it first.';
153
+ : ' If the app carries no Reticle SDK at all, run `reticle init` in it first.' +
154
+ (false === evidence.sdkMarker || isRemoteUrl(url) ? PRODUCTION_STUB : '');
134
155
  return `${opening}${nuxt}${marker} ${PORT_DIFFERENTIAL}${noSdk} ${REAL_CAUSES} ${RELEASE}`;
135
156
  }
@@ -0,0 +1,33 @@
1
+ /**
2
+ * The `permissions` argument of `reticle_lease { action: "acquire" }` (#1370).
3
+ *
4
+ * Granted before the first navigation of a fresh lease. On an origin that already has a live lease,
5
+ * acquire hands back THAT lease rather than opening a second tab, and it may be another agent's tab
6
+ * mid-flow — nothing at this layer knows whose it is. So its grants never change there: the same list
7
+ * is a plain reuse, a different one is refused with the way out (release, then acquire again).
8
+ */
9
+ import { z } from 'zod';
10
+ import type { BrowserPool } from '../../portal/pool/browser-pool.js';
11
+ export declare const LEASE_PERMISSIONS_ARG: z.ZodOptional<z.ZodArray<z.ZodString, "many">>;
12
+ type PermissionPool = Pick<BrowserPool, 'notificationPermission'>;
13
+ /** The validated list, undefined when the caller passed none, or a refusal naming the right shape. */
14
+ export declare function parseLeasePermissions(raw: unknown): readonly string[] | undefined;
15
+ /** A permission failure, reworded for the agent; undefined for every other error. */
16
+ export declare function permissionRefusal(err: unknown): Error | undefined;
17
+ /**
18
+ * What to tell the agent when the page cannot see a notifications grant, else undefined.
19
+ *
20
+ * Undefined too when the page could not be asked: the grant was made, and a reading nobody took is
21
+ * not evidence that it failed.
22
+ */
23
+ export declare function notificationReadBack(pool: PermissionPool, sessionId: string, permissions: readonly string[] | undefined): Promise<string | undefined>;
24
+ /**
25
+ * Refuse to reuse a held lease under a different set of grants. Nothing to refuse when the caller
26
+ * named no list, or the same one in any order.
27
+ */
28
+ export declare function refuseRegrant(pool: Pick<BrowserPool, 'permissionsOf'>, sessionId: string, permissions: readonly string[] | undefined): void;
29
+ /** `{ hint }` joining whichever parts are present, or nothing at all. */
30
+ export declare function hintOf(...parts: (string | undefined)[]): {
31
+ hint?: string;
32
+ };
33
+ export {};