@reticlehq/server 3.5.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 (721) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +123 -116
  3. package/dist/chromium-launch-options.d.ts +3 -1
  4. package/dist/chromium-launch-options.js +2 -1
  5. package/dist/command/cli/adhoc-suite.d.ts +14 -0
  6. package/dist/command/cli/adhoc-suite.js +42 -7
  7. package/dist/command/cli/adhoc-verdict.d.ts +19 -2
  8. package/dist/command/cli/adhoc-verdict.js +76 -9
  9. package/dist/command/cli/answers/gate-exit.d.ts +23 -0
  10. package/dist/command/cli/answers/gate-exit.js +45 -0
  11. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  12. package/dist/command/cli/answers/gate-hook-message.js +3 -1
  13. package/dist/command/cli/answers/open-note.d.ts +2 -0
  14. package/dist/command/cli/answers/open-note.js +22 -0
  15. package/dist/command/cli/auth/device-flow.d.ts +13 -2
  16. package/dist/command/cli/auth/device-flow.js +17 -0
  17. package/dist/command/cli/cli-doctor.js +14 -0
  18. package/dist/command/cli/cli-flow-commands.d.ts +0 -11
  19. package/dist/command/cli/cli-flow-commands.js +31 -112
  20. package/dist/command/cli/cli-kill.js +3 -2
  21. package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
  22. package/dist/command/cli/cli-parse-grammar.js +75 -0
  23. package/dist/command/cli/cli-parse-verify.d.ts +2 -0
  24. package/dist/command/cli/cli-parse-verify.js +18 -0
  25. package/dist/command/cli/cli-parse.d.ts +19 -28
  26. package/dist/command/cli/cli-parse.js +82 -182
  27. package/dist/command/cli/cli-update-commands.d.ts +1 -1
  28. package/dist/command/cli/cli-update-commands.js +61 -9
  29. package/dist/command/cli/cli-usage.d.ts +33 -0
  30. package/dist/command/cli/cli-usage.js +287 -0
  31. package/dist/command/cli/cli-verify.d.ts +35 -5
  32. package/dist/command/cli/cli-verify.js +114 -35
  33. package/dist/command/cli/cloud-cli.d.ts +13 -0
  34. package/dist/command/cli/cloud-cli.js +192 -341
  35. package/dist/command/cli/cloud-kit.d.ts +12 -0
  36. package/dist/command/cli/cloud-kit.js +41 -2
  37. package/dist/command/cli/cloud-link.d.ts +57 -0
  38. package/dist/command/cli/cloud-link.js +308 -0
  39. package/dist/command/cli/cloud-login.d.ts +22 -0
  40. package/dist/command/cli/cloud-login.js +96 -8
  41. package/dist/command/cli/context-command.d.ts +1 -0
  42. package/dist/command/cli/context-command.js +33 -0
  43. package/dist/command/cli/daemon-start-options.d.ts +3 -0
  44. package/dist/command/cli/daemon-start-options.js +24 -3
  45. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
  46. package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
  47. package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
  48. package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
  49. package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
  50. package/dist/command/cli/doctor/doctor-project-line.js +5 -4
  51. package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
  52. package/dist/command/cli/doctor/doctor-rows.js +6 -0
  53. package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
  54. package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
  55. package/dist/command/cli/drive/drive-attach.d.ts +27 -2
  56. package/dist/command/cli/drive/drive-attach.js +71 -4
  57. package/dist/command/cli/drive/drive-command.d.ts +2 -1
  58. package/dist/command/cli/drive/drive-command.js +13 -7
  59. package/dist/command/cli/known-regression.d.ts +13 -0
  60. package/dist/command/cli/known-regression.js +34 -0
  61. package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
  62. package/dist/command/cli/launch/sdk-version-match.js +25 -0
  63. package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
  64. package/dist/command/cli/mcp-command.d.ts +6 -0
  65. package/dist/command/cli/mcp-command.js +13 -5
  66. package/dist/command/cli/ports/port-holder.d.ts +10 -0
  67. package/dist/command/cli/ports/port-holder.js +25 -1
  68. package/dist/command/cli/project-name.d.ts +29 -1
  69. package/dist/command/cli/project-name.js +107 -2
  70. package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
  71. package/dist/command/cli/setup-mcp-cli.js +35 -12
  72. package/dist/command/cli/status/status-lines.d.ts +1 -0
  73. package/dist/command/cli/status/status-lines.js +47 -2
  74. package/dist/command/cli/status/workspace-links.d.ts +10 -0
  75. package/dist/command/cli/status/workspace-links.js +29 -0
  76. package/dist/command/cli/try-command.d.ts +96 -0
  77. package/dist/command/cli/try-command.js +362 -0
  78. package/dist/command/cli/tutorial.d.ts +0 -100
  79. package/dist/command/cli/tutorial.js +0 -181
  80. package/dist/command/cli/verify-results.d.ts +19 -0
  81. package/dist/command/cli/verify-results.js +29 -0
  82. package/dist/command/cli-onboarding.d.ts +0 -11
  83. package/dist/command/cli-onboarding.js +0 -15
  84. package/dist/command/cli.d.ts +20 -0
  85. package/dist/command/cli.js +130 -104
  86. package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
  87. package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
  88. package/dist/command/daemon/daemon-resilience.js +4 -4
  89. package/dist/command/daemon/daemon-resolve.d.ts +23 -1
  90. package/dist/command/daemon/daemon-resolve.js +79 -9
  91. package/dist/command/setup/agent-writer.d.ts +1 -1
  92. package/dist/command/setup/agent-writer.js +3 -2
  93. package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
  94. package/dist/command/setup/bringup/bridge-port.js +13 -3
  95. package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
  96. package/dist/command/setup/bringup/connect-lease.js +1 -0
  97. package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
  98. package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
  99. package/dist/command/setup/bringup/dev-server-wait.js +19 -0
  100. package/dist/command/setup/bringup/ensure-daemon.js +9 -2
  101. package/dist/command/setup/init/agent-restart.d.ts +23 -0
  102. package/dist/command/setup/init/agent-restart.js +28 -0
  103. package/dist/command/setup/init/init-port.d.ts +14 -1
  104. package/dist/command/setup/init/init-port.js +32 -2
  105. package/dist/command/setup/init/init-runtime.d.ts +22 -2
  106. package/dist/command/setup/init/init-runtime.js +114 -38
  107. package/dist/command/setup/node-effects.d.ts +2 -0
  108. package/dist/command/setup/node-effects.js +38 -9
  109. package/dist/command/setup/probe/existing-app.d.ts +12 -0
  110. package/dist/command/setup/probe/existing-app.js +14 -0
  111. package/dist/command/setup/remaining-steps.js +2 -1
  112. package/dist/command/setup/run-setup.d.ts +34 -9
  113. package/dist/command/setup/run-setup.js +65 -51
  114. package/dist/command/setup/setup-command.d.ts +25 -1
  115. package/dist/command/setup/setup-command.js +59 -4
  116. package/dist/command/setup/setup-mcp.js +25 -2
  117. package/dist/command/setup/tauri-signing.d.ts +19 -0
  118. package/dist/command/setup/tauri-signing.js +79 -0
  119. package/dist/command/setup/terminal/listeners.d.ts +10 -1
  120. package/dist/command/setup/terminal/listeners.js +37 -6
  121. package/dist/command/update/update-nudge.d.ts +9 -0
  122. package/dist/command/update/update-nudge.js +1 -1
  123. package/dist/command/update/updater.js +11 -15
  124. package/dist/command/version/version-nudge.js +3 -0
  125. package/dist/command/version/version-skew.d.ts +20 -1
  126. package/dist/command/version/version-skew.js +49 -4
  127. package/dist/features/crawl/crawl-tools.js +4 -0
  128. package/dist/features/crawl/crawl.d.ts +6 -0
  129. package/dist/features/crawl/crawl.js +23 -2
  130. package/dist/features/exhaust/ledger.d.ts +21 -14
  131. package/dist/features/exhaust/ledger.js +35 -9
  132. package/dist/features/harness/app-findings.d.ts +2 -0
  133. package/dist/features/harness/app-findings.js +52 -0
  134. package/dist/features/harness/drive-report.d.ts +61 -1
  135. package/dist/features/harness/drive-report.js +394 -26
  136. package/dist/features/harness/drive-runs.d.ts +120 -0
  137. package/dist/features/harness/drive-runs.js +289 -0
  138. package/dist/features/harness/drivers.d.ts +10 -14
  139. package/dist/features/harness/drivers.js +10 -14
  140. package/dist/features/harness/explore/console-pages.d.ts +15 -0
  141. package/dist/features/harness/explore/console-pages.js +146 -0
  142. package/dist/features/harness/explore/disparity.d.ts +19 -0
  143. package/dist/features/harness/explore/disparity.js +71 -0
  144. package/dist/features/harness/explore/fake-app.d.ts +16 -0
  145. package/dist/features/harness/explore/fake-app.js +49 -0
  146. package/dist/features/harness/explore/goal-search.d.ts +26 -0
  147. package/dist/features/harness/explore/goal-search.js +144 -0
  148. package/dist/features/harness/explore/page-tree.d.ts +49 -0
  149. package/dist/features/harness/explore/page-tree.js +148 -0
  150. package/dist/features/harness/explore/site-map.d.ts +34 -0
  151. package/dist/features/harness/explore/site-map.js +150 -0
  152. package/dist/features/harness/fill-values.d.ts +3 -73
  153. package/dist/features/harness/fill-values.js +3 -169
  154. package/dist/features/harness/goals.d.ts +82 -0
  155. package/dist/features/harness/goals.js +330 -0
  156. package/dist/features/harness/harness.d.ts +51 -1
  157. package/dist/features/harness/harness.js +207 -6
  158. package/dist/features/harness/platform/drive-target.d.ts +30 -0
  159. package/dist/features/harness/platform/drive-target.js +81 -0
  160. package/dist/features/harness/platform/local-apps.d.ts +127 -0
  161. package/dist/features/harness/platform/local-apps.js +280 -0
  162. package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
  163. package/dist/features/harness/platform/persona-credentials.js +69 -0
  164. package/dist/features/harness/platform/platform-drives.d.ts +61 -0
  165. package/dist/features/harness/platform/platform-drives.js +114 -0
  166. package/dist/features/harness/platform/refusal.d.ts +52 -0
  167. package/dist/features/harness/platform/refusal.js +71 -0
  168. package/dist/features/harness/platform/remote-drive.d.ts +186 -0
  169. package/dist/features/harness/platform/remote-drive.js +378 -0
  170. package/dist/features/harness/platform/script.d.ts +94 -0
  171. package/dist/features/harness/platform/script.js +260 -0
  172. package/dist/features/harness/platform/server-driver.d.ts +54 -0
  173. package/dist/features/harness/platform/server-driver.js +182 -0
  174. package/dist/features/harness/platform-config.d.ts +41 -1
  175. package/dist/features/harness/platform-config.js +106 -9
  176. package/dist/features/harness/route-guess.d.ts +13 -0
  177. package/dist/features/harness/route-guess.js +49 -0
  178. package/dist/features/harness/script/app-controls.d.ts +5 -0
  179. package/dist/features/harness/script/app-controls.js +40 -0
  180. package/dist/features/harness/script/lane-ids.d.ts +14 -0
  181. package/dist/features/harness/script/lane-ids.js +16 -0
  182. package/dist/features/harness/script/script-run.d.ts +70 -0
  183. package/dist/features/harness/script/script-run.js +606 -0
  184. package/dist/features/license/license.d.ts +2 -2
  185. package/dist/features/visual/step-shots.d.ts +31 -0
  186. package/dist/features/visual/step-shots.js +231 -0
  187. package/dist/features/visual/visual-tools.d.ts +10 -1
  188. package/dist/features/visual/visual-tools.js +62 -17
  189. package/dist/hooks/client-directory.d.ts +18 -0
  190. package/dist/hooks/client-directory.js +57 -0
  191. package/dist/hooks/coding-agents.d.ts +34 -0
  192. package/dist/hooks/coding-agents.js +117 -0
  193. package/dist/hooks/driven-by.d.ts +23 -0
  194. package/dist/hooks/driven-by.js +56 -0
  195. package/dist/hooks/hook-bus.d.ts +4 -0
  196. package/dist/hooks/hook-bus.js +18 -0
  197. package/dist/hooks/hook-commands.js +15 -4
  198. package/dist/hooks/tool-log.d.ts +9 -0
  199. package/dist/hooks/tool-log.js +29 -0
  200. package/dist/index.d.ts +2 -0
  201. package/dist/index.js +80 -243
  202. package/dist/judgement/capsule/capsule-store.d.ts +2 -2
  203. package/dist/judgement/capsule/causal-summary.d.ts +15 -1
  204. package/dist/judgement/capsule/causal-summary.js +33 -0
  205. package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
  206. package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
  207. package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
  208. package/dist/judgement/runs/artifact/gap-summary.js +12 -3
  209. package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
  210. package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
  211. package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
  212. package/dist/judgement/runs/artifact/run-store.js +195 -3
  213. package/dist/judgement/runs/context-tools.js +59 -1
  214. package/dist/judgement/runs/default-run-id.d.ts +3 -0
  215. package/dist/judgement/runs/default-run-id.js +16 -0
  216. package/dist/judgement/runs/drive-run.d.ts +71 -1
  217. package/dist/judgement/runs/drive-run.js +317 -5
  218. package/dist/judgement/runs/repair-prompt.js +1 -1
  219. package/dist/judgement/runs/resume.d.ts +44 -0
  220. package/dist/judgement/runs/resume.js +137 -0
  221. package/dist/judgement/runs/reticle-runner.js +13 -3
  222. package/dist/judgement/runs/runner-port.d.ts +5 -1
  223. package/dist/judgement/runs/runner-port.js +8 -2
  224. package/dist/judgement/runs/verification-sync.d.ts +5 -2
  225. package/dist/judgement/runs/verification-sync.js +40 -18
  226. package/dist/language/flows/change/gate.d.ts +10 -0
  227. package/dist/language/flows/change/gate.js +22 -0
  228. package/dist/language/flows/decision.js +36 -1
  229. package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
  230. package/dist/language/flows/fields/flow-secret-field.js +25 -2
  231. package/dist/language/flows/flow-anchor.d.ts +61 -10
  232. package/dist/language/flows/flow-anchor.js +98 -6
  233. package/dist/language/flows/flow-cross-step.d.ts +15 -0
  234. package/dist/language/flows/flow-cross-step.js +21 -0
  235. package/dist/language/flows/flow-intent.d.ts +1 -0
  236. package/dist/language/flows/flow-journey.d.ts +6 -0
  237. package/dist/language/flows/flow-journey.js +20 -0
  238. package/dist/language/flows/flow-learning.d.ts +4 -0
  239. package/dist/language/flows/flow-learning.js +45 -14
  240. package/dist/language/flows/flow-mutate-tools.js +5 -3
  241. package/dist/language/flows/flow-replay-run.d.ts +23 -9
  242. package/dist/language/flows/flow-replay-run.js +115 -110
  243. package/dist/language/flows/flow-replay-types.d.ts +1 -1
  244. package/dist/language/flows/flow-replay.d.ts +40 -1
  245. package/dist/language/flows/flow-replay.js +110 -22
  246. package/dist/language/flows/flow-result.d.ts +22 -1
  247. package/dist/language/flows/flow-result.js +47 -2
  248. package/dist/language/flows/flow-scope.js +5 -1
  249. package/dist/language/flows/flow-step-runners.d.ts +22 -2
  250. package/dist/language/flows/flow-step-runners.js +247 -47
  251. package/dist/language/flows/flow-store-for-session.d.ts +2 -2
  252. package/dist/language/flows/flow-store-for-session.js +7 -3
  253. package/dist/language/flows/flow-tools.d.ts +10 -0
  254. package/dist/language/flows/flow-tools.js +112 -89
  255. package/dist/language/flows/flows.d.ts +16 -1
  256. package/dist/language/flows/flows.js +74 -12
  257. package/dist/language/flows/heal-run.js +6 -4
  258. package/dist/language/flows/narrow-write.d.ts +7 -0
  259. package/dist/language/flows/narrow-write.js +36 -1
  260. package/dist/language/flows/recording/flake.d.ts +2 -2
  261. package/dist/language/flows/recording/recording-backtrack.js +14 -1
  262. package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
  263. package/dist/language/flows/recording/tape/recordings.js +95 -13
  264. package/dist/language/flows/replay-from-hud.d.ts +20 -0
  265. package/dist/language/flows/replay-from-hud.js +51 -0
  266. package/dist/language/flows/replay.d.ts +9 -5
  267. package/dist/language/flows/replay.js +56 -15
  268. package/dist/language/flows/single-replay.d.ts +7 -0
  269. package/dist/language/flows/single-replay.js +26 -0
  270. package/dist/language/flows/suite/suite-flakes.js +2 -0
  271. package/dist/language/flows/suite-selection.d.ts +2 -15
  272. package/dist/language/flows/suite-selection.js +4 -3
  273. package/dist/language/flows/verify-change-tools.d.ts +1 -0
  274. package/dist/language/flows/verify-change-tools.js +202 -191
  275. package/dist/launch-chromium.d.ts +27 -5
  276. package/dist/launch-chromium.js +38 -8
  277. package/dist/memory/cloud/cloud-config.d.ts +22 -1
  278. package/dist/memory/cloud/cloud-config.js +34 -5
  279. package/dist/memory/cloud/cloud-sync.d.ts +17 -14
  280. package/dist/memory/cloud/cloud-sync.js +15 -4
  281. package/dist/memory/cloud/harness-config.d.ts +75 -1
  282. package/dist/memory/cloud/harness-config.js +115 -24
  283. package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
  284. package/dist/memory/cloud/hud-notices-source.js +128 -0
  285. package/dist/memory/cloud/memory-scope.d.ts +161 -0
  286. package/dist/memory/cloud/memory-scope.js +227 -0
  287. package/dist/memory/cloud/sync-cycle.d.ts +44 -7
  288. package/dist/memory/cloud/sync-cycle.js +129 -15
  289. package/dist/memory/cloud/sync-daemon.d.ts +11 -0
  290. package/dist/memory/cloud/sync-daemon.js +121 -9
  291. package/dist/memory/cloud/sync-disk.d.ts +1 -1
  292. package/dist/memory/cloud/sync-disk.js +31 -10
  293. package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
  294. package/dist/memory/cloud/sync-screenshots.js +105 -0
  295. package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
  296. package/dist/memory/cloud/unsynced-roots.js +166 -0
  297. package/dist/memory/impact/account-watch.d.ts +34 -0
  298. package/dist/memory/impact/account-watch.js +59 -0
  299. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  300. package/dist/memory/impact/impact-recorder.js +12 -2
  301. package/dist/memory/impact/impact-store.d.ts +17 -4
  302. package/dist/memory/impact/impact-store.js +169 -63
  303. package/dist/memory/intent/inline-intent.d.ts +1 -0
  304. package/dist/memory/intent/intent-shard-store.js +16 -4
  305. package/dist/memory/intent/intent-shard.d.ts +14 -2
  306. package/dist/memory/intent/intent-store.d.ts +1 -0
  307. package/dist/memory/intent/intent-tools.js +122 -4
  308. package/dist/memory/intent/open-intents.d.ts +6 -0
  309. package/dist/memory/intent/open-intents.js +10 -1
  310. package/dist/memory/intent/settled-words.d.ts +24 -0
  311. package/dist/memory/intent/settled-words.js +130 -0
  312. package/dist/memory/journal/drive-flow.d.ts +16 -0
  313. package/dist/memory/journal/drive-flow.js +34 -2
  314. package/dist/memory/journal/drive-run-flush.d.ts +2 -0
  315. package/dist/memory/journal/drive-run-flush.js +20 -5
  316. package/dist/memory/journal/envelope.d.ts +8 -8
  317. package/dist/memory/journal/journal-recorder.js +52 -3
  318. package/dist/memory/journal/on-disk/retention.d.ts +8 -0
  319. package/dist/memory/journal/on-disk/retention.js +32 -2
  320. package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
  321. package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
  322. package/dist/memory/journal/session-end.d.ts +15 -1
  323. package/dist/memory/journal/session-end.js +42 -9
  324. package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
  325. package/dist/memory/project/artifact-root-resolver.js +125 -16
  326. package/dist/memory/project/artifact-root.d.ts +46 -8
  327. package/dist/memory/project/artifact-root.js +89 -10
  328. package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
  329. package/dist/memory/project/dir/reticle-dir.js +26 -3
  330. package/dist/memory/project/link-directory.d.ts +15 -0
  331. package/dist/memory/project/link-directory.js +44 -0
  332. package/dist/memory/project/project-tools.js +22 -3
  333. package/dist/memory/project/root-claims.d.ts +6 -0
  334. package/dist/memory/project/root-claims.js +39 -0
  335. package/dist/memory/project/session-root.d.ts +26 -1
  336. package/dist/memory/project/session-root.js +49 -5
  337. package/dist/memory/project/sync-status.d.ts +85 -0
  338. package/dist/memory/project/sync-status.js +224 -0
  339. package/dist/memory/recall/memory-tools.js +47 -2
  340. package/dist/memory/recall/platform-memory.d.ts +34 -0
  341. package/dist/memory/recall/platform-memory.js +139 -0
  342. package/dist/memory/recall/project-memory.d.ts +19 -0
  343. package/dist/memory/recall/project-memory.js +80 -13
  344. package/dist/portal/bridge/bridge.d.ts +9 -3
  345. package/dist/portal/bridge/bridge.js +82 -22
  346. package/dist/portal/bridge/harness-request.d.ts +23 -0
  347. package/dist/portal/bridge/harness-request.js +27 -0
  348. package/dist/portal/bridge/pairing-token.d.ts +9 -0
  349. package/dist/portal/bridge/pairing-token.js +17 -0
  350. package/dist/portal/bridge/wrong-path.d.ts +17 -0
  351. package/dist/portal/bridge/wrong-path.js +35 -0
  352. package/dist/portal/input/network-mock-tools.js +11 -2
  353. package/dist/portal/input/real-input.d.ts +83 -10
  354. package/dist/portal/input/real-input.js +218 -30
  355. package/dist/portal/input/viewport-tools.js +3 -3
  356. package/dist/portal/pool/browser-pool.d.ts +70 -9
  357. package/dist/portal/pool/browser-pool.js +190 -37
  358. package/dist/portal/pool/context-permissions.d.ts +33 -0
  359. package/dist/portal/pool/context-permissions.js +33 -0
  360. package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
  361. package/dist/portal/pool/lease-marker-stamp.js +49 -0
  362. package/dist/portal/pool/playwright-launcher.d.ts +35 -0
  363. package/dist/portal/pool/playwright-launcher.js +64 -3
  364. package/dist/portal/pool/pool-contract.d.ts +28 -5
  365. package/dist/portal/session/agent-link.d.ts +8 -0
  366. package/dist/portal/session/agent-link.js +17 -0
  367. package/dist/portal/session/command-payload.d.ts +8 -0
  368. package/dist/portal/session/command-payload.js +24 -0
  369. package/dist/portal/session/daemon-answers.d.ts +3 -3
  370. package/dist/portal/session/daemon-answers.js +4 -2
  371. package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
  372. package/dist/portal/session/dev-server/dev-command.js +87 -12
  373. package/dist/portal/session/facts/departure-note.d.ts +22 -0
  374. package/dist/portal/session/facts/departure-note.js +47 -0
  375. package/dist/portal/session/facts/observed-state.d.ts +16 -18
  376. package/dist/portal/session/facts/observed-state.js +46 -3
  377. package/dist/portal/session/facts/session-replaced.d.ts +5 -0
  378. package/dist/portal/session/facts/session-replaced.js +5 -0
  379. package/dist/portal/session/first-run-wiring.d.ts +42 -0
  380. package/dist/portal/session/first-run-wiring.js +132 -0
  381. package/dist/portal/session/human/live-control.d.ts +9 -2
  382. package/dist/portal/session/human/live-control.js +12 -3
  383. package/dist/portal/session/human/notes-ledger.d.ts +20 -0
  384. package/dist/portal/session/human/notes-ledger.js +55 -0
  385. package/dist/portal/session/human/review-store.d.ts +12 -0
  386. package/dist/portal/session/human/review-store.js +18 -10
  387. package/dist/portal/session/live-control-tools.d.ts +0 -13
  388. package/dist/portal/session/live-control-tools.js +107 -13
  389. package/dist/portal/session/narration-args.d.ts +5 -0
  390. package/dist/portal/session/narration-args.js +17 -0
  391. package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
  392. package/dist/portal/session/no-session-diagnosis.js +46 -9
  393. package/dist/portal/session/no-session-next-action.d.ts +31 -0
  394. package/dist/portal/session/no-session-next-action.js +159 -60
  395. package/dist/portal/session/no-session-watch.d.ts +14 -1
  396. package/dist/portal/session/no-session-watch.js +227 -17
  397. package/dist/portal/session/presence/session-lease.js +1 -1
  398. package/dist/portal/session/presence/session-mirror.js +3 -0
  399. package/dist/portal/session/recorded-gaps.d.ts +97 -0
  400. package/dist/portal/session/recorded-gaps.js +251 -0
  401. package/dist/portal/session/serving-directory.d.ts +27 -0
  402. package/dist/portal/session/serving-directory.js +45 -0
  403. package/dist/portal/session/session-health.d.ts +18 -0
  404. package/dist/portal/session/session-health.js +9 -1
  405. package/dist/portal/session/session-info.d.ts +8 -1
  406. package/dist/portal/session/session-info.js +8 -1
  407. package/dist/portal/session/session-manager.d.ts +39 -0
  408. package/dist/portal/session/session-manager.js +98 -11
  409. package/dist/portal/session/session-reaper.js +4 -1
  410. package/dist/portal/session/session-successor.d.ts +13 -0
  411. package/dist/portal/session/session-successor.js +1 -1
  412. package/dist/portal/session/session-tools.js +26 -3
  413. package/dist/portal/session/session.d.ts +22 -30
  414. package/dist/portal/session/session.js +81 -79
  415. package/dist/portal/session/timing/command-timeout.js +25 -1
  416. package/dist/portal/session/timing/wall-clock.d.ts +1 -1
  417. package/dist/portal/session/timing/wall-clock.js +1 -1
  418. package/dist/portal/session/zero-install-first-call.d.ts +31 -0
  419. package/dist/portal/session/zero-install-first-call.js +88 -0
  420. package/dist/start-options.d.ts +12 -0
  421. package/dist/start-wiring.d.ts +63 -0
  422. package/dist/start-wiring.js +169 -0
  423. package/dist/status-payload.d.ts +23 -1
  424. package/dist/status-payload.js +36 -1
  425. package/dist/surface/http-server.js +18 -2
  426. package/dist/surface/mcp/attach-memory.d.ts +1 -0
  427. package/dist/surface/mcp/attach-memory.js +12 -1
  428. package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
  429. package/dist/surface/mcp/mcp-proxy.js +65 -13
  430. package/dist/surface/mcp/mcp.d.ts +34 -6
  431. package/dist/surface/mcp/mcp.js +61 -17
  432. package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
  433. package/dist/surface/mcp/proxy/drive-calls.js +27 -0
  434. package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
  435. package/dist/surface/mcp/server-instructions.d.ts +4 -2
  436. package/dist/surface/mcp/server-instructions.js +32 -14
  437. package/dist/surface/mcp/shared-params.js +2 -2
  438. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  439. package/dist/surface/mcp/surface-vocabulary.js +1 -0
  440. package/dist/surface/tools/account-tool.d.ts +22 -0
  441. package/dist/surface/tools/account-tool.js +157 -0
  442. package/dist/surface/tools/act/act-danger.d.ts +11 -0
  443. package/dist/surface/tools/act/act-danger.js +38 -1
  444. package/dist/surface/tools/act/act-observation.d.ts +33 -0
  445. package/dist/surface/tools/act/act-observation.js +57 -0
  446. package/dist/surface/tools/act/act-preflight.js +25 -2
  447. package/dist/surface/tools/act/act-target.js +8 -3
  448. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
  449. package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
  450. package/dist/surface/tools/act/resolve-target.d.ts +1 -1
  451. package/dist/surface/tools/act/resolve-target.js +18 -3
  452. package/dist/surface/tools/act/screen-request.d.ts +34 -0
  453. package/dist/surface/tools/act/screen-request.js +113 -0
  454. package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
  455. package/dist/surface/tools/act/sequence-grade.js +13 -2
  456. package/dist/surface/tools/act/settle-in-flight.js +25 -3
  457. package/dist/surface/tools/act-sequence-tool.js +138 -29
  458. package/dist/surface/tools/act-tools.d.ts +0 -9
  459. package/dist/surface/tools/act-tools.js +71 -41
  460. package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
  461. package/dist/surface/tools/agent/app-notes-learning.js +80 -0
  462. package/dist/surface/tools/agent/app-notes.d.ts +4 -0
  463. package/dist/surface/tools/agent/app-notes.js +48 -0
  464. package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
  465. package/dist/surface/tools/agent/build-staleness.js +62 -0
  466. package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
  467. package/dist/surface/tools/agent/compact-envelope.js +374 -0
  468. package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
  469. package/dist/surface/tools/agent/for-the-agent.js +44 -0
  470. package/dist/surface/tools/agent/notices.d.ts +50 -0
  471. package/dist/surface/tools/agent/notices.js +152 -0
  472. package/dist/surface/tools/agent/reteach.d.ts +11 -0
  473. package/dist/surface/tools/agent/reteach.js +50 -0
  474. package/dist/surface/tools/args/alias-args.d.ts +5 -0
  475. package/dist/surface/tools/args/alias-args.js +10 -0
  476. package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
  477. package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
  478. package/dist/surface/tools/assert/assert-source.d.ts +15 -0
  479. package/dist/surface/tools/assert/assert-source.js +40 -0
  480. package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
  481. package/dist/surface/tools/assert/assert-verdict.js +42 -17
  482. package/dist/surface/tools/browser-tools.js +51 -2
  483. package/dist/surface/tools/chat-drives.d.ts +101 -0
  484. package/dist/surface/tools/chat-drives.js +409 -0
  485. package/dist/surface/tools/coverage-tools.d.ts +2 -10
  486. package/dist/surface/tools/coverage-tools.js +2 -53
  487. package/dist/surface/tools/dynamic-tools.js +29 -1
  488. package/dist/surface/tools/empty-session-list.d.ts +51 -0
  489. package/dist/surface/tools/empty-session-list.js +120 -0
  490. package/dist/surface/tools/error-recovery.d.ts +14 -0
  491. package/dist/surface/tools/error-recovery.js +105 -8
  492. package/dist/surface/tools/explore-tools.d.ts +31 -1
  493. package/dist/surface/tools/explore-tools.js +438 -66
  494. package/dist/surface/tools/feedback-tools.d.ts +2 -3
  495. package/dist/surface/tools/feedback-tools.js +18 -3
  496. package/dist/surface/tools/gap-novelty.d.ts +3 -1
  497. package/dist/surface/tools/gap-novelty.js +8 -1
  498. package/dist/surface/tools/harness-explore.d.ts +118 -57
  499. package/dist/surface/tools/harness-explore.js +344 -292
  500. package/dist/surface/tools/harness-gate.d.ts +88 -0
  501. package/dist/surface/tools/harness-gate.js +235 -0
  502. package/dist/surface/tools/harness-hunt.d.ts +43 -0
  503. package/dist/surface/tools/harness-hunt.js +215 -0
  504. package/dist/surface/tools/harness-plan.d.ts +17 -0
  505. package/dist/surface/tools/harness-plan.js +38 -0
  506. package/dist/surface/tools/harness-script.d.ts +30 -0
  507. package/dist/surface/tools/harness-script.js +560 -0
  508. package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
  509. package/dist/surface/tools/harness-tab-guard.js +27 -0
  510. package/dist/surface/tools/harness-toolset.d.ts +22 -1
  511. package/dist/surface/tools/harness-toolset.js +101 -7
  512. package/dist/surface/tools/human-notes.d.ts +16 -0
  513. package/dist/surface/tools/human-notes.js +27 -0
  514. package/dist/surface/tools/invoke-tool.d.ts +5 -2
  515. package/dist/surface/tools/invoke-tool.js +263 -85
  516. package/dist/surface/tools/lease-hint.js +26 -5
  517. package/dist/surface/tools/lease-permissions.d.ts +33 -0
  518. package/dist/surface/tools/lease-permissions.js +73 -0
  519. package/dist/surface/tools/lease-readiness.d.ts +38 -0
  520. package/dist/surface/tools/lease-readiness.js +57 -0
  521. package/dist/surface/tools/lease-seed.d.ts +49 -0
  522. package/dist/surface/tools/lease-seed.js +167 -0
  523. package/dist/surface/tools/lease-tools.d.ts +13 -24
  524. package/dist/surface/tools/lease-tools.js +146 -197
  525. package/dist/surface/tools/live-call-text.js +4 -4
  526. package/dist/surface/tools/merge-tools.js +42 -2
  527. package/dist/surface/tools/merged-name-redirect.js +4 -0
  528. package/dist/surface/tools/next-step.d.ts +29 -0
  529. package/dist/surface/tools/next-step.js +214 -0
  530. package/dist/surface/tools/observe-tools.js +45 -9
  531. package/dist/surface/tools/platform-moment.d.ts +72 -0
  532. package/dist/surface/tools/platform-moment.js +296 -0
  533. package/dist/surface/tools/query-hint-schema.d.ts +7 -0
  534. package/dist/surface/tools/query-hint-schema.js +10 -0
  535. package/dist/surface/tools/read-tools.js +71 -14
  536. package/dist/surface/tools/real-input-attempt.js +96 -13
  537. package/dist/surface/tools/reticle-result.d.ts +120 -0
  538. package/dist/surface/tools/reticle-result.js +364 -0
  539. package/dist/surface/tools/tool-kit.d.ts +83 -3
  540. package/dist/surface/tools/tool-kit.js +77 -7
  541. package/dist/surface/tools/tools.js +43 -59
  542. package/dist/telemetry/account-envelope.d.ts +7 -0
  543. package/dist/telemetry/account-envelope.js +61 -0
  544. package/dist/telemetry/agent-client.d.ts +15 -0
  545. package/dist/telemetry/agent-client.js +57 -0
  546. package/dist/telemetry/app-instrumented.js +9 -2
  547. package/dist/telemetry/argument-shape.d.ts +7 -0
  548. package/dist/telemetry/argument-shape.js +86 -1
  549. package/dist/telemetry/automation-hint.d.ts +2 -3
  550. package/dist/telemetry/automation-hint.js +33 -8
  551. package/dist/telemetry/cli-telemetry.js +7 -2
  552. package/dist/telemetry/daemon-telemetry.js +3 -0
  553. package/dist/telemetry/error-fingerprint.d.ts +10 -1
  554. package/dist/telemetry/error-fingerprint.js +61 -5
  555. package/dist/telemetry/feedback-cli.d.ts +0 -13
  556. package/dist/telemetry/feedback-cli.js +0 -77
  557. package/dist/telemetry/feedback.d.ts +13 -0
  558. package/dist/telemetry/feedback.js +183 -17
  559. package/dist/telemetry/harness-run.d.ts +18 -0
  560. package/dist/telemetry/harness-run.js +80 -0
  561. package/dist/telemetry/hud-events.d.ts +16 -0
  562. package/dist/telemetry/hud-events.js +27 -0
  563. package/dist/telemetry/hud-metrics.d.ts +29 -6
  564. package/dist/telemetry/hud-metrics.js +116 -25
  565. package/dist/telemetry/init-telemetry.js +2 -2
  566. package/dist/telemetry/install-source.d.ts +13 -25
  567. package/dist/telemetry/install-source.js +44 -3
  568. package/dist/telemetry/mcp-connection.d.ts +0 -14
  569. package/dist/telemetry/mcp-connection.js +5 -1
  570. package/dist/telemetry/onboarding-firsts.d.ts +32 -0
  571. package/dist/telemetry/onboarding-firsts.js +81 -6
  572. package/dist/telemetry/platform-linked.d.ts +5 -0
  573. package/dist/telemetry/platform-linked.js +32 -0
  574. package/dist/telemetry/project-profile.js +5 -3
  575. package/dist/telemetry/proxy-telemetry.js +4 -1
  576. package/dist/telemetry/session-metrics.d.ts +15 -4
  577. package/dist/telemetry/session-metrics.js +88 -52
  578. package/dist/telemetry/telemetry.d.ts +38 -2
  579. package/dist/telemetry/telemetry.js +144 -34
  580. package/dist/telemetry/verification-of.d.ts +3 -1
  581. package/dist/telemetry/verification-of.js +13 -4
  582. package/dist/wire-journal.d.ts +2 -2
  583. package/dist/wire-journal.js +20 -6
  584. package/docs/README.md +3 -3
  585. package/docs/actions.mdx +6 -3
  586. package/docs/adapters.md +1 -1
  587. package/docs/agent-cheatsheet.md +25 -28
  588. package/docs/architecture.md +5 -5
  589. package/docs/autodrive.md +33 -28
  590. package/docs/benchmarks.md +5 -5
  591. package/docs/best-practices.mdx +27 -9
  592. package/docs/capabilities.mdx +14 -16
  593. package/docs/cli/affected.mdx +1 -1
  594. package/docs/cli/cloud.mdx +54 -75
  595. package/docs/cli/doctor.mdx +14 -3
  596. package/docs/cli/drive.mdx +20 -14
  597. package/docs/cli/feedback.mdx +3 -3
  598. package/docs/cli/gate.mdx +7 -2
  599. package/docs/cli/help.mdx +50 -55
  600. package/docs/cli/init.mdx +43 -28
  601. package/docs/cli/license.mdx +12 -8
  602. package/docs/cli/mcp.mdx +4 -4
  603. package/docs/cli/open.mdx +3 -3
  604. package/docs/cli/report.mdx +4 -2
  605. package/docs/cli/restart.mdx +2 -2
  606. package/docs/cli/rollback.mdx +14 -8
  607. package/docs/cli/serve.mdx +4 -4
  608. package/docs/cli/setup.mdx +23 -0
  609. package/docs/cli/status.mdx +18 -5
  610. package/docs/cli/stop.mdx +67 -8
  611. package/docs/cli/try.mdx +62 -0
  612. package/docs/cli/update.mdx +4 -3
  613. package/docs/cli/verify.mdx +17 -6
  614. package/docs/cli/version.mdx +5 -4
  615. package/docs/cli.mdx +111 -42
  616. package/docs/debugging.md +3 -3
  617. package/docs/deploy-checks.md +1 -1
  618. package/docs/desktop.mdx +9 -3
  619. package/docs/enterprise.md +11 -10
  620. package/docs/environment.mdx +7 -8
  621. package/docs/faq.mdx +3 -3
  622. package/docs/first-drive.md +5 -4
  623. package/docs/flows.md +35 -27
  624. package/docs/for-agents.md +4 -5
  625. package/docs/frameworks.mdx +32 -21
  626. package/docs/getting-started.md +65 -61
  627. package/docs/human-control.md +16 -16
  628. package/docs/index.mdx +15 -42
  629. package/docs/install-agentic.mdx +22 -37
  630. package/docs/install-manual.mdx +23 -13
  631. package/docs/instrumentation.mdx +5 -3
  632. package/docs/integration-patterns.md +7 -7
  633. package/docs/license-activation.mdx +1 -1
  634. package/docs/multi-agent-testing.md +24 -6
  635. package/docs/packages/babel-plugin.mdx +4 -2
  636. package/docs/packages/browser.mdx +16 -10
  637. package/docs/packages/core.mdx +12 -5
  638. package/docs/packages/electron.mdx +3 -2
  639. package/docs/packages/engine.mdx +1 -1
  640. package/docs/packages/eslint-plugin.mdx +18 -12
  641. package/docs/packages/next.mdx +8 -7
  642. package/docs/packages/open-verification.mdx +1 -1
  643. package/docs/packages/server.mdx +5 -5
  644. package/docs/packages/tauri.mdx +9 -9
  645. package/docs/packages/test.mdx +4 -10
  646. package/docs/packages/vite-plugin.mdx +32 -4
  647. package/docs/packages.mdx +11 -15
  648. package/docs/platform-integration.md +6 -5
  649. package/docs/predicates.mdx +40 -24
  650. package/docs/quickstart.mdx +69 -30
  651. package/docs/required-checks.md +8 -7
  652. package/docs/reticle-manual.md +15 -5
  653. package/docs/skill-file.mdx +17 -79
  654. package/docs/skill-setup.md +9 -9
  655. package/docs/skill.md +200 -0
  656. package/docs/system-map.md +7 -7
  657. package/docs/telemetry.md +23 -25
  658. package/docs/testing.md +4 -4
  659. package/docs/token-efficiency.md +12 -12
  660. package/docs/tools/act-and-wait.mdx +9 -2
  661. package/docs/tools/act-sequence.mdx +6 -7
  662. package/docs/tools/act.mdx +2 -2
  663. package/docs/tools/assert.mdx +18 -17
  664. package/docs/tools/console.mdx +9 -9
  665. package/docs/tools/inspect.mdx +16 -7
  666. package/docs/tools/look.mdx +24 -0
  667. package/docs/tools/navigate.mdx +5 -3
  668. package/docs/tools/network.mdx +2 -2
  669. package/docs/tools/observe.mdx +6 -6
  670. package/docs/tools/overview.mdx +34 -33
  671. package/docs/tools/query.mdx +5 -5
  672. package/docs/tools/session-and-feedback.mdx +22 -13
  673. package/docs/tools/sessions.mdx +8 -8
  674. package/docs/tools/snapshot.mdx +6 -5
  675. package/docs/tools/state.mdx +9 -9
  676. package/docs/tools/tools-and-run.mdx +26 -24
  677. package/docs/tools/verify.mdx +28 -0
  678. package/docs/tools/wait-for.mdx +8 -4
  679. package/docs/troubleshooting.mdx +21 -6
  680. package/docs/usage.md +55 -46
  681. package/docs/use-cases.mdx +3 -3
  682. package/docs/vs-chrome-devtools-mcp.mdx +9 -6
  683. package/docs/vs-playwright-mcp.mdx +3 -1
  684. package/docs/what-is-recorded.md +17 -5
  685. package/docs/what-is-reticle.mdx +5 -3
  686. package/docs/why-reticle.mdx +1 -1
  687. package/package.json +9 -12
  688. package/dist/command/cli/demo/demo-page.d.ts +0 -78
  689. package/dist/command/cli/demo/demo-page.js +0 -241
  690. package/dist/command/cli/demo/demo-run.d.ts +0 -38
  691. package/dist/command/cli/demo/demo-run.js +0 -138
  692. package/dist/features/harness/driver.d.ts +0 -50
  693. package/dist/features/harness/driver.js +0 -236
  694. package/dist/features/harness/jev-driver.d.ts +0 -188
  695. package/dist/features/harness/jev-driver.js +0 -678
  696. package/dist/features/harness/openai-driver.d.ts +0 -58
  697. package/dist/features/harness/openai-driver.js +0 -206
  698. package/dist/judgement/hunt/hunt-report.d.ts +0 -49
  699. package/dist/judgement/hunt/hunt-report.js +0 -84
  700. package/dist/language/flows/buddy-status.d.ts +0 -25
  701. package/dist/language/flows/buddy-status.js +0 -32
  702. package/dist/language/flows/change/watch-batcher.d.ts +0 -18
  703. package/dist/language/flows/change/watch-batcher.js +0 -19
  704. package/dist/memory/cloud/harness-offer.d.ts +0 -44
  705. package/dist/memory/cloud/harness-offer.js +0 -145
  706. package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
  707. package/dist/memory/project/dir/fill-value-store.js +0 -88
  708. package/dist/surface/tools/feature-capture.d.ts +0 -151
  709. package/dist/surface/tools/feature-capture.js +0 -235
  710. package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
  711. package/dist/surface/tools/tool-hit-rate.js +0 -90
  712. package/dist/telemetry/harness-drive.d.ts +0 -4
  713. package/dist/telemetry/harness-drive.js +0 -35
  714. package/dist/telemetry/identify.d.ts +0 -22
  715. package/dist/telemetry/identify.js +0 -73
  716. package/docs/cli/capsules.mdx +0 -70
  717. package/docs/cli/hunt.mdx +0 -73
  718. package/docs/cli/identify.mdx +0 -76
  719. package/docs/cli/kill.mdx +0 -91
  720. package/docs/cli/watch.mdx +0 -62
  721. package/docs/local-registry.md +0 -143
@@ -0,0 +1,88 @@
1
+ import type { ToolDeps } from './tool-kit.js';
2
+ import { type ConfigFetch } from '../../features/harness/platform-config.js';
3
+ /** What the platform half of the gate reads off a drive's options; `ExploreOptions` satisfies it. */
4
+ export interface HarnessAsk {
5
+ skipPlatformConfig?: boolean;
6
+ configFetch?: ConfigFetch;
7
+ planId?: string;
8
+ }
9
+ /**
10
+ * Why the harness is unavailable, phrased as the way to make it available.
11
+ *
12
+ * A missing key is a configuration fact, not a fault, and the sentence a user reads has to tell them
13
+ * the one thing to do about it. Named here because both the CLI and the honest no-flows refusal
14
+ * print it, and two copies of this sentence would drift.
15
+ */
16
+ export declare const MSG_NO_HARNESS_KEY: string;
17
+ /**
18
+ * The environment, plus the credential this machine already has.
19
+ *
20
+ * `reticle link` mints a project-scoped key and files it in `~/.reticle/credentials.json`; the CLI
21
+ * has read it from there for as long as it has existed. The harness did not, and read only
22
+ * `process.env` — so somebody who had signed in, linked their project and been told they were
23
+ * connected still got "no model configured to drive the app", and the only way out was to find the
24
+ * key in the console and export it by hand. Five manual steps to reach a feature they had already
25
+ * finished setting up.
26
+ *
27
+ * Resolved into the env rather than threaded through four call sites: the drivers and the
28
+ * preference lookup all read an env record, and giving them a completed one leaves each of them
29
+ * exactly as simple as it was. The key precedence is the resolver's, the same as sync's and the
30
+ * CLI's: the stored key for the link's host, else the exported one (which is how CI, with no
31
+ * keystore, gets here). An explicitly exported HOST still wins, so a proxy is not overridden.
32
+ *
33
+ * The credential arrives through `deps.linkedCloud`, a port, because resolving it here would make
34
+ * the tool surface reach into `memory/cloud` — a reach the directory guard refused, correctly.
35
+ */
36
+ export declare function withLinkedCredential(deps: ToolDeps, env: Record<string, string | undefined>,
37
+ /**
38
+ * The tab a drive is for: its own project's link, not the daemon's. A plan saved with the
39
+ * daemon's key while its runs synced under the tab's project left every run link of the plan
40
+ * "Run unavailable". Absent: the daemon's own link.
41
+ */
42
+ tab?: {
43
+ sessionId: string | undefined;
44
+ }): Promise<Record<string, string | undefined>>;
45
+ /** Introduces the prompt under a coverage refusal, so the agent knows it is for itself. */
46
+ export declare const MSG_GATE_PROMPT_LEAD = "To unlock it, do this (or hand it to your coding agent):";
47
+ /**
48
+ * Why the Harness must not drive this tab's app yet, or undefined when it may: below the coverage
49
+ * gate (core's `instrumentation-coverage.ts`), one reason sentence and the prompt that closes it. Every Harness
50
+ * start passes here (an agent's explore, Run Harness, `reticle try`, the platform's chat), so the
51
+ * gate holds wherever a drive starts; every other tool works at any coverage. A tab that cannot be
52
+ * resolved is not refused here: the drive itself answers for a missing tab. Counted once per refusal.
53
+ */
54
+ export declare function coverageRefusal(deps: ToolDeps, sessionId: string | undefined): string | undefined;
55
+ /**
56
+ * The gate a Harness start obeys. When the project is linked, the platform's verdict is the one
57
+ * source of truth: it locks a run mid-drive on the same report, so a daemon that refused what the
58
+ * platform unlocked showed two scores for one project. The daemon's own reading only refuses when
59
+ * the platform said nothing (not linked, unreachable, an older API) or said locked too, in which
60
+ * case the daemon's sentence names what this tab can fix.
61
+ */
62
+ export declare function harnessLockRefusal(deps: ToolDeps, sessionId: string | undefined, env: Record<string, string | undefined>, fetchConfig?: ConfigFetch): Promise<string | undefined>;
63
+ /**
64
+ * Can this machine reach the Harness? Only through the platform: a linked project or a platform
65
+ * key. Whether the workspace is entitled is the platform's answer, asked when the drive starts.
66
+ */
67
+ export declare function harnessAvailable(env: Record<string, string | undefined>): boolean;
68
+ /**
69
+ * The reason this drive must not start, or `undefined` to go ahead.
70
+ *
71
+ * A drive on somebody's OWN model key never waits on the platform beyond the off switch: their key,
72
+ * their spend. A drive through the platform proxy bills Reticle, and that one needs a confirmed yes
73
+ * — enabled, entitled, and a model ready. It used to fail open: `fetchPlatformConfig` answers
74
+ * `undefined` on a network error, a non-2xx, a body that does not parse, or a two-second timeout,
75
+ * and all four read as "carry on", so a slow second on a settings endpoint let an unentitled
76
+ * workspace drive on Reticle's budget. Now the same silence refuses with a message that says to
77
+ * retry or bring a key. Fields an older platform omits still default to yes inside
78
+ * `fetchPlatformConfig`; only an answer that never arrived is a no.
79
+ */
80
+ export declare function refusedByPlatform(env: Record<string, string | undefined>, options: HarnessAsk): Promise<string | undefined>;
81
+ /**
82
+ * `refusedByPlatform`, for a run that may be a saved plan. A plan that only replays saved flows
83
+ * spends no model turn, so a model drive's gates do not stop it; a refused plan is still reported to
84
+ * the plan, every journey blocked with the reason, so its history records the attempt.
85
+ */
86
+ export declare function refusedForPlan(env: Record<string, string | undefined>, options: HarnessAsk): Promise<string | undefined>;
87
+ /** The sentence a refusal leads with, without the prompt that follows it. */
88
+ export declare const firstLine: (text: string) => string;
@@ -0,0 +1,235 @@
1
+ /**
2
+ * Whether the Harness may drive at all, and with which credential — answered before a drive starts.
3
+ *
4
+ * Split from `harness-explore.ts`, which runs the drive. This is the gate every Harness start passes
5
+ * through (an agent's explore, Run Harness, `reticle try`, the platform's chat): the linked
6
+ * credential, the instrumentation-coverage lock, and the platform's own yes or no.
7
+ */
8
+ import { reportAppsNow } from '../../features/harness/platform/local-apps.js';
9
+ import { serverOptionsFromEnv } from '../../features/harness/platform/server-driver.js';
10
+ import { ReticleEnv, cloudUrlFrom } from '@reticlehq/core';
11
+ import { creditsSpent, creditsUsedLine } from '@reticlehq/core/hud';
12
+ import { planUrl } from '../../features/harness/platform/platform-drives.js';
13
+ import { isUnmatchedRoot } from '../../memory/project/dir/reticle-dir.js';
14
+ import { sessionRoot } from '../../memory/project/session-root.js';
15
+ import { fetchPlatformConfig } from '../../features/harness/platform-config.js';
16
+ import { reportPlanBlocked, savedPlanDrivesNothing } from '../../features/harness/platform/script.js';
17
+ import { instrumentationOf, probeMarkers } from '../../portal/session/recorded-gaps.js';
18
+ import { getSessionMetrics } from '../../telemetry/session-metrics.js';
19
+ import { MSG_HARNESS_DISABLED, MSG_HARNESS_UNCLAIMED, MSG_HARNESS_UNCONFIRMED, } from '../../features/harness/platform/refusal.js';
20
+ /**
21
+ * Why the harness is unavailable, phrased as the way to make it available.
22
+ *
23
+ * A missing key is a configuration fact, not a fault, and the sentence a user reads has to tell them
24
+ * the one thing to do about it. Named here because both the CLI and the honest no-flows refusal
25
+ * print it, and two copies of this sentence would drift.
26
+ */
27
+ export const MSG_NO_HARNESS_KEY = `The Reticle Harness runs on the Reticle platform, and a new account gets 10 free credits ` +
28
+ `to try it: run \`reticle connect\` to link this project and sign in. ` +
29
+ `Without it, drive the journey yourself with reticle_act_and_wait and an \`until\` on its last step: ` +
30
+ `what you drive is saved as a flow just the same.`;
31
+ /**
32
+ * The environment, plus the credential this machine already has.
33
+ *
34
+ * `reticle link` mints a project-scoped key and files it in `~/.reticle/credentials.json`; the CLI
35
+ * has read it from there for as long as it has existed. The harness did not, and read only
36
+ * `process.env` — so somebody who had signed in, linked their project and been told they were
37
+ * connected still got "no model configured to drive the app", and the only way out was to find the
38
+ * key in the console and export it by hand. Five manual steps to reach a feature they had already
39
+ * finished setting up.
40
+ *
41
+ * Resolved into the env rather than threaded through four call sites: the drivers and the
42
+ * preference lookup all read an env record, and giving them a completed one leaves each of them
43
+ * exactly as simple as it was. The key precedence is the resolver's, the same as sync's and the
44
+ * CLI's: the stored key for the link's host, else the exported one (which is how CI, with no
45
+ * keystore, gets here). An explicitly exported HOST still wins, so a proxy is not overridden.
46
+ *
47
+ * The credential arrives through `deps.linkedCloud`, a port, because resolving it here would make
48
+ * the tool surface reach into `memory/cloud` — a reach the directory guard refused, correctly.
49
+ */
50
+ export async function withLinkedCredential(deps, env,
51
+ /**
52
+ * The tab a drive is for: its own project's link, not the daemon's. A plan saved with the
53
+ * daemon's key while its runs synced under the tab's project left every run link of the plan
54
+ * "Run unavailable". Absent: the daemon's own link.
55
+ */
56
+ tab) {
57
+ try {
58
+ const root = tab === undefined ? undefined : tabRoot(deps, tab);
59
+ // A tab whose page reported no project (its root is `unmatched/`) is nobody else's: it drives on
60
+ // the daemon's own link, never "run reticle connect" to a project that is linked.
61
+ const own = root !== undefined && isUnmatchedRoot(root) ? undefined : root;
62
+ const linked = await deps.linkedCloud?.(own);
63
+ if (linked === undefined || null === linked)
64
+ return env;
65
+ return {
66
+ ...env,
67
+ [ReticleEnv.API_KEY]: linked.apiKey,
68
+ [ReticleEnv.CLOUD_URL]: cloudUrlFrom(env) ?? linked.url,
69
+ };
70
+ }
71
+ catch {
72
+ // A credential store that cannot be read is "not linked", not an error. The harness is optional
73
+ // and its absence is a routine answer; a drive must never fail because a JSON file was odd.
74
+ return env;
75
+ }
76
+ }
77
+ /** A tab's `.reticle`, or undefined (the daemon's) when the tab cannot be resolved to one. */
78
+ function tabRoot(deps, tab) {
79
+ try {
80
+ return sessionRoot(deps, tab.sessionId);
81
+ }
82
+ catch {
83
+ return undefined;
84
+ }
85
+ }
86
+ /** Introduces the prompt under a coverage refusal, so the agent knows it is for itself. */
87
+ export const MSG_GATE_PROMPT_LEAD = 'To unlock it, do this (or hand it to your coding agent):';
88
+ /**
89
+ * Why the Harness must not drive this tab's app yet, or undefined when it may: below the coverage
90
+ * gate (core's `instrumentation-coverage.ts`), one reason sentence and the prompt that closes it. Every Harness
91
+ * start passes here (an agent's explore, Run Harness, `reticle try`, the platform's chat), so the
92
+ * gate holds wherever a drive starts; every other tool works at any coverage. A tab that cannot be
93
+ * resolved is not refused here: the drive itself answers for a missing tab. Counted once per refusal.
94
+ */
95
+ export function coverageRefusal(deps, sessionId) {
96
+ const refused = localGateRefusal(deps, sessionId);
97
+ if (refused !== undefined)
98
+ getSessionMetrics().recordHarnessRefused(refused.percent);
99
+ return refused?.text;
100
+ }
101
+ /** This tab and every other live tab of its app, or undefined when the tab cannot be resolved. */
102
+ function appTabsOf(deps, sessionId) {
103
+ let tab;
104
+ try {
105
+ tab = deps.sessions.resolve(sessionId);
106
+ }
107
+ catch {
108
+ return undefined;
109
+ }
110
+ // Every tab of the app, the way the platform's merged report reads it, so the two name the same
111
+ // missing items.
112
+ const siblings = (deps.sessions.list?.() ?? [])
113
+ .filter((info) => info.sessionId !== tab.id && sameApp(info.projectId, tab.projectId))
114
+ .flatMap((info) => {
115
+ const live = deps.sessions.get?.(info.sessionId);
116
+ return live === undefined ? [] : [live];
117
+ });
118
+ return { tab, siblings };
119
+ }
120
+ /** The daemon's own reading of the gate for this tab's app, uncounted. */
121
+ function localGateRefusal(deps, sessionId) {
122
+ const app = appTabsOf(deps, sessionId);
123
+ if (app === undefined)
124
+ return undefined;
125
+ const { tab } = app;
126
+ const siblings = app.siblings.map((live) => ({
127
+ id: live.id,
128
+ url: live.url,
129
+ projectId: live.projectId,
130
+ channels: live.channels,
131
+ sourceMapping: live.sourceMapping,
132
+ }));
133
+ const coverage = instrumentationOf(tab, siblings);
134
+ const gate = coverage.harnessGate;
135
+ if (gate.unlocked || gate.reason === undefined)
136
+ return undefined;
137
+ const text = coverage.prompt === undefined
138
+ ? gate.reason
139
+ : `${gate.reason}\n\n${MSG_GATE_PROMPT_LEAD}\n${coverage.prompt}`;
140
+ return { text, percent: gate.percent };
141
+ }
142
+ /**
143
+ * The gate a Harness start obeys. When the project is linked, the platform's verdict is the one
144
+ * source of truth: it locks a run mid-drive on the same report, so a daemon that refused what the
145
+ * platform unlocked showed two scores for one project. The daemon's own reading only refuses when
146
+ * the platform said nothing (not linked, unreachable, an older API) or said locked too, in which
147
+ * case the daemon's sentence names what this tab can fix.
148
+ */
149
+ export async function harnessLockRefusal(deps, sessionId, env, fetchConfig) {
150
+ // What the app's pages carry decides, not what an act happened to reach: ask them first.
151
+ const app = appTabsOf(deps, sessionId);
152
+ // Learned something: the platform hears it before it is asked, or it refuses on its old score.
153
+ if (app !== undefined && (await probeMarkers([app.tab, ...app.siblings])))
154
+ await reportAppsNow().catch(() => undefined);
155
+ if (undefined === localGateRefusal(deps, sessionId))
156
+ return undefined;
157
+ const platform = await fetchPlatformConfig(env, fetchConfig);
158
+ if (true === platform?.gate?.unlocked)
159
+ return undefined;
160
+ return coverageRefusal(deps, sessionId);
161
+ }
162
+ /** Two tabs are one app when both name the same project. A tab that names none stands alone. */
163
+ const sameApp = (a, b) => a !== undefined && a === b;
164
+ /**
165
+ * Can this machine reach the Harness? Only through the platform: a linked project or a platform
166
+ * key. Whether the workspace is entitled is the platform's answer, asked when the drive starts.
167
+ */
168
+ export function harnessAvailable(env) {
169
+ return serverOptionsFromEnv(env) !== undefined;
170
+ }
171
+ /** One read, however many questions are asked of the answer. */
172
+ function platformConfig(env, options) {
173
+ return options.configFetch === undefined
174
+ ? fetchPlatformConfig(env)
175
+ : fetchPlatformConfig(env, options.configFetch);
176
+ }
177
+ /**
178
+ * The reason this drive must not start, or `undefined` to go ahead.
179
+ *
180
+ * A drive on somebody's OWN model key never waits on the platform beyond the off switch: their key,
181
+ * their spend. A drive through the platform proxy bills Reticle, and that one needs a confirmed yes
182
+ * — enabled, entitled, and a model ready. It used to fail open: `fetchPlatformConfig` answers
183
+ * `undefined` on a network error, a non-2xx, a body that does not parse, or a two-second timeout,
184
+ * and all four read as "carry on", so a slow second on a settings endpoint let an unentitled
185
+ * workspace drive on Reticle's budget. Now the same silence refuses with a message that says to
186
+ * retry or bring a key. Fields an older platform omits still default to yes inside
187
+ * `fetchPlatformConfig`; only an answer that never arrived is a no.
188
+ */
189
+ export async function refusedByPlatform(env, options) {
190
+ if (true === options.skipPlatformConfig)
191
+ return undefined;
192
+ // No platform, no Harness: it runs there, on the workspace's credits.
193
+ if (serverOptionsFromEnv(env) === undefined)
194
+ return MSG_NO_HARNESS_KEY;
195
+ const config = await platformConfig(env, options);
196
+ // It needs a confirmed yes, not the absence of a no. The platform also checks on every turn.
197
+ if (config === undefined)
198
+ return MSG_HARNESS_UNCONFIRMED;
199
+ // The project-wide lock before the switch: a fresh tab passes the per-tab gate with no gaps
200
+ // recorded, and "off" hid the one refusal that names its fix.
201
+ const gate = config.gate;
202
+ if (false === gate?.unlocked && gate.reason !== undefined)
203
+ return gate.prompt === undefined
204
+ ? gate.reason
205
+ : `${gate.reason}\n\n${MSG_GATE_PROMPT_LEAD}\n${gate.prompt}`;
206
+ if (!config.harnessEnabled)
207
+ return MSG_HARNESS_DISABLED;
208
+ // Before entitlement: no credits left is why most workspaces are not entitled, said as the HUD says it.
209
+ if (config.credits !== undefined && creditsSpent(config.credits))
210
+ return creditsUsedLine(config.credits,
211
+ // The platform's own page; built from the API origin only for a platform that names none.
212
+ config.planUrl ?? planUrl(config.platformUrl ?? cloudUrlFrom(env) ?? ''));
213
+ if (!config.harnessEntitled)
214
+ return MSG_HARNESS_UNCLAIMED;
215
+ return undefined;
216
+ }
217
+ /**
218
+ * `refusedByPlatform`, for a run that may be a saved plan. A plan that only replays saved flows
219
+ * spends no model turn, so a model drive's gates do not stop it; a refused plan is still reported to
220
+ * the plan, every journey blocked with the reason, so its history records the attempt.
221
+ */
222
+ export async function refusedForPlan(env, options) {
223
+ const planId = options.planId;
224
+ const platform = serverOptionsFromEnv(env);
225
+ if (planId === undefined || platform === undefined)
226
+ return refusedByPlatform(env, options);
227
+ if (await savedPlanDrivesNothing(platform, planId))
228
+ return undefined;
229
+ const refusal = await refusedByPlatform(env, options);
230
+ if (refusal !== undefined)
231
+ await reportPlanBlocked(platform, planId, firstLine(refusal));
232
+ return refusal;
233
+ }
234
+ /** The sentence a refusal leads with, without the prompt that follows it. */
235
+ export const firstLine = (text) => text.split('\n')[0] ?? text;
@@ -0,0 +1,43 @@
1
+ import type { RunDisparity } from '@reticlehq/core';
2
+ import type { HarnessMap } from '@reticlehq/core/artifacts';
3
+ import { type Goal, type GoalCheck } from '../../features/harness/goals.js';
4
+ import type { ToolOutcome } from '../../features/harness/harness.js';
5
+ import type { Invoke } from '../../features/harness/explore/page-tree.js';
6
+ import type { ToolDeps } from './tool-kit.js';
7
+ /** The pages a map knows, by route: what a drive is pointed at before it guesses. */
8
+ export declare const knownRoutes: (map: HarnessMap | undefined) => string[];
9
+ /** The app's map: the kept one while it is fresh, else a new survey merged over it. */
10
+ export declare function siteMapFor(deps: ToolDeps, sessionId: string | undefined, invoke: Invoke): Promise<HarnessMap | undefined>;
11
+ /** What a drive read, folded into the kept map, so the map grows from use. */
12
+ export declare function refreshMap(deps: ToolDeps, sessionId: string | undefined, map: HarnessMap | undefined, calls: readonly ToolOutcome[]): Promise<void>;
13
+ /** A drive's goals as graded, and how each compared with the agent's verdict. */
14
+ export interface Graded {
15
+ goals: GoalCheck[];
16
+ disparity: RunDisparity[];
17
+ /** The navigations and clicks the hunt made: the Harness driving the app, said as such. */
18
+ moved: ToolOutcome[];
19
+ }
20
+ /**
21
+ * One grade from each lane's: per goal, the lane that proved it, else one that disproved it on its
22
+ * own page, else the first. A plan's lane that reached the end text proved it, whatever the others
23
+ * (a known-defects lane, a lane on another page) saw.
24
+ */
25
+ export declare function bestOfLanes(lanes: readonly Graded[]): Graded;
26
+ /**
27
+ * The goals graded after a hunt for the journey's end. The end is the last goal the page did not
28
+ * already show; when the hunt does not find it the check is undecided and says where it looked.
29
+ */
30
+ export declare function huntAndGrade(deps: ToolDeps, driving: Invoke, ask: {
31
+ sessionId?: string | undefined;
32
+ goals: readonly (string | Goal)[];
33
+ expect?: Record<string, unknown> | undefined;
34
+ opening?: string | undefined;
35
+ journey?: string | undefined;
36
+ map?: HarnessMap | undefined;
37
+ /** Text the Harness wrote besides the journey: its plan's journeys, its flows' names. */
38
+ own?: readonly string[] | undefined;
39
+ /** The pages the drive reached (`pagesReached`), searched when the end is not where it stopped. */
40
+ reached?: readonly string[] | undefined;
41
+ /** The values the drive typed (`typedValues`): inputs, graded only when one is the end. */
42
+ typed?: readonly string[] | undefined;
43
+ }): Promise<Graded>;
@@ -0,0 +1,215 @@
1
+ /**
2
+ * The exploratory Harness around a drive: map the app first, hunt for the goal before grading it,
3
+ * and compare the verdict with the coding agent's. The drive itself is the platform's; these are the
4
+ * daemon's deterministic halves, shared by the planned and the unplanned path.
5
+ */
6
+ import { dirname, join } from 'node:path';
7
+ import { checkExpect, checkGoals, endGoalsOf, } from '../../features/harness/goals.js';
8
+ import { ReticleTool } from '@reticlehq/core';
9
+ import { searchForGoal } from '../../features/harness/explore/goal-search.js';
10
+ import { MAP_FRESH_MS, mergePages, pagesReadIn, parseMap, surveyApp, } from '../../features/harness/explore/site-map.js';
11
+ import { agentVerdictsIn, disparityFor } from '../../features/harness/explore/disparity.js';
12
+ import { reticleDirPaths } from '../../memory/project/dir/reticle-dir.js';
13
+ import { sessionRoot } from '../../memory/project/session-root.js';
14
+ import { JournalActionSchema, ReticleDir, Verified, VerifiedReason, } from '@reticlehq/core';
15
+ import { isValidSessionId } from '../../memory/project/dir/reticle-dir.js';
16
+ /**
17
+ * Kept beside the plans: what this machine's drives learned about the app, local like them.
18
+ * ponytail: a file in `plans/`, not a new `.reticle/` name, which would need the workspace tiers
19
+ * and the ignore file to learn it; give it its own name if it ever needs to be shared.
20
+ */
21
+ const HARNESS_MAP_FILE = 'harness-map.json';
22
+ /** Fewer pages than this and the kept map is not a map of the app. */
23
+ const MIN_MAPPED_PAGES = 2;
24
+ /** Sessions read from disk for the agent's verdicts: the recent past of one project, not its history. */
25
+ const MAX_JOURNALS_READ = 40;
26
+ function mapPath(deps, sessionId) {
27
+ try {
28
+ return join(reticleDirPaths(sessionRoot(deps, sessionId)).plans, HARNESS_MAP_FILE);
29
+ }
30
+ catch {
31
+ return undefined;
32
+ }
33
+ }
34
+ async function readMap(deps, path) {
35
+ try {
36
+ return parseMap(await deps.fs.readFile(path));
37
+ }
38
+ catch {
39
+ return undefined;
40
+ }
41
+ }
42
+ async function writeMap(deps, path, map) {
43
+ try {
44
+ await deps.fs.mkdir(dirname(path));
45
+ await deps.fs.writeFile(path, `${JSON.stringify(map, null, 2)}\n`);
46
+ }
47
+ catch {
48
+ /* a map that cannot be kept is surveyed again next time */
49
+ }
50
+ }
51
+ /** The pages a map knows, by route: what a drive is pointed at before it guesses. */
52
+ export const knownRoutes = (map) => map === undefined ? [] : [...new Set(map.pages.map((page) => page.route))];
53
+ /** The app's map: the kept one while it is fresh, else a new survey merged over it. */
54
+ export async function siteMapFor(deps, sessionId, invoke) {
55
+ const path = mapPath(deps, sessionId);
56
+ const kept = path === undefined ? undefined : await readMap(deps, path);
57
+ // A map of one page is a survey that saw nothing (a menu was open): it is surveyed again.
58
+ if (kept !== undefined &&
59
+ MIN_MAPPED_PAGES <= kept.pages.length &&
60
+ deps.now() - kept.surveyedAt < MAP_FRESH_MS)
61
+ return kept;
62
+ const surveyed = await surveyApp(invoke, deps.now);
63
+ if (surveyed === undefined)
64
+ return kept;
65
+ const map = kept === undefined ? surveyed : mergePages(kept, surveyed.pages, surveyed.surveyedAt);
66
+ if (path !== undefined)
67
+ await writeMap(deps, path, map);
68
+ return map;
69
+ }
70
+ /** What a drive read, folded into the kept map, so the map grows from use. */
71
+ export async function refreshMap(deps, sessionId, map, calls) {
72
+ const path = mapPath(deps, sessionId);
73
+ if (path === undefined || map === undefined)
74
+ return;
75
+ const read = pagesReadIn(calls, deps.now());
76
+ if (0 < read.length)
77
+ await writeMap(deps, path, mergePages(map, read));
78
+ }
79
+ /**
80
+ * The decided verdicts the connected agent made on this app: in its live tabs, and in the journals
81
+ * on disk of tabs that have closed. Persona 21's agent proved both goals on a tab that had closed by
82
+ * the time the Harness graded, and the comparison was never made.
83
+ */
84
+ async function agentVerdicts(deps, sessionId) {
85
+ let projectId;
86
+ let own;
87
+ try {
88
+ const tab = deps.sessions.resolve(sessionId);
89
+ projectId = tab.projectId;
90
+ own = tab.id;
91
+ }
92
+ catch {
93
+ return [];
94
+ }
95
+ const tabs = deps.sessions
96
+ .all()
97
+ .filter((s) => s.id === own || (projectId !== undefined && s.projectId === projectId));
98
+ const live = await Promise.all(tabs.map((s) => s.readJournalActions().catch(() => [])));
99
+ const onDisk = await journalsOnDisk(deps, sessionId, new Set(tabs.map((s) => s.id)));
100
+ return agentVerdictsIn([...live.flat(), ...onDisk]);
101
+ }
102
+ /** A journal's lines as actions; a line that does not parse is left out, as the journal reader does. */
103
+ function actionsIn(text) {
104
+ return text.split('\n').flatMap((line) => {
105
+ if (0 === line.trim().length)
106
+ return [];
107
+ try {
108
+ const parsed = JournalActionSchema.safeParse(JSON.parse(line));
109
+ return parsed.success ? [parsed.data] : [];
110
+ }
111
+ catch {
112
+ return [];
113
+ }
114
+ });
115
+ }
116
+ /** The actions of this project's sessions that are no longer live, from their journals. */
117
+ async function journalsOnDisk(deps, sessionId, live) {
118
+ try {
119
+ const root = sessionRoot(deps, sessionId);
120
+ const ids = (await deps.fs.readdir(reticleDirPaths(root).sessions))
121
+ .filter((id) => !live.has(id) && isValidSessionId(id))
122
+ .slice(-MAX_JOURNALS_READ);
123
+ const read = await Promise.all(ids.map((id) => deps.fs
124
+ .readFile(join(reticleDirPaths(root).sessions, id, ReticleDir.JOURNAL_ACTIONS_FILE))
125
+ .then(actionsIn)
126
+ .catch(() => [])));
127
+ return read.flat();
128
+ }
129
+ catch {
130
+ return [];
131
+ }
132
+ }
133
+ /** What the hunt does to the app. Its asserts are not kept here: they would count as checks. */
134
+ const HUNT_MOVES = new Set([ReticleTool.NAVIGATE, ReticleTool.ACT]);
135
+ /** The invoke, keeping each move it makes. */
136
+ function keepingMoves(invoke, moved) {
137
+ return async (name, args) => {
138
+ const result = await invoke(name, args);
139
+ if (HUNT_MOVES.has(name))
140
+ moved.push({ id: `hunt-${String(moved.length + 1)}`, name, args, result, isError: false });
141
+ return result;
142
+ };
143
+ }
144
+ const RANK = { [Verified.YES]: 0, [Verified.NO]: 1 };
145
+ /**
146
+ * One grade from each lane's: per goal, the lane that proved it, else one that disproved it on its
147
+ * own page, else the first. A plan's lane that reached the end text proved it, whatever the others
148
+ * (a known-defects lane, a lane on another page) saw.
149
+ */
150
+ export function bestOfLanes(lanes) {
151
+ const first = lanes[0] ?? { goals: [], disparity: [], moved: [] };
152
+ const goals = first.goals
153
+ .map((_, i) => {
154
+ const all = lanes.flatMap((l) => (l.goals[i] === undefined ? [] : [l.goals[i]]));
155
+ return ([...all].sort((a, b) => (RANK[a.verified] ?? 2) - (RANK[b.verified] ?? 2))[0] ??
156
+ first.goals[i]);
157
+ })
158
+ .filter((g) => g !== undefined);
159
+ const disparity = goals.flatMap((g) => {
160
+ const lane = lanes.find((l) => l.goals.includes(g));
161
+ return lane?.disparity.filter((d) => d.goal === g.text) ?? [];
162
+ });
163
+ return { goals, disparity, moved: lanes.flatMap((l) => l.moved) };
164
+ }
165
+ /**
166
+ * The goals graded after a hunt for the journey's end. The end is the last goal the page did not
167
+ * already show; when the hunt does not find it the check is undecided and says where it looked.
168
+ */
169
+ export async function huntAndGrade(deps, driving, ask) {
170
+ const moved = [];
171
+ const invoke = keepingMoves(driving, moved);
172
+ // The journey names the plan and the flows this run saves: shown back on a page, it proves nothing.
173
+ const own = [...(ask.own ?? []), ...(ask.journey === undefined ? [] : [ask.journey])];
174
+ const goals = endGoalsOf(ask.goals.map((g) => ('string' === typeof g ? { text: g } : g)), ask.typed ?? []);
175
+ const end = goals
176
+ .filter((g) => true !== g.absent && true !== ask.opening?.includes(g.text))
177
+ .at(-1);
178
+ const hunt = (goal) => searchForGoal(invoke, {
179
+ goal,
180
+ ...(ask.journey === undefined ? {} : { journey: ask.journey }),
181
+ ...(ask.map === undefined ? {} : { map: ask.map }),
182
+ ...(ask.reached === undefined ? {} : { reached: ask.reached }),
183
+ own,
184
+ });
185
+ const search = end === undefined ? undefined : await hunt(end.text);
186
+ // The end not found anywhere: the tab is left where an earlier goal is, so that one is graded
187
+ // where it shows rather than where the hunt gave up.
188
+ if (search !== undefined && !search.found)
189
+ for (const earlier of goals.filter((g) => g !== end && true !== g.absent).reverse())
190
+ if ((await hunt(earlier.text)).found)
191
+ break;
192
+ const checks = (await checkGoals(invoke, goals, ask.opening, own)).map((c) => end !== undefined &&
193
+ c.text === end.text &&
194
+ Verified.YES !== c.verified &&
195
+ search !== undefined &&
196
+ !search.found
197
+ ? {
198
+ ...c,
199
+ reason: `${VerifiedReason.INCONCLUSIVE}: not found after searching ${search.searched.join(' → ')}`,
200
+ }
201
+ : c);
202
+ const agent = await agentVerdicts(deps, ask.sessionId);
203
+ const disparity = checks.flatMap((c) => {
204
+ const d = disparityFor(c, agent, c.text === end?.text ? search : undefined);
205
+ return d === undefined ? [] : [d];
206
+ });
207
+ return {
208
+ goals: [
209
+ ...checks,
210
+ ...(ask.expect === undefined ? [] : [await checkExpect(invoke, ask.expect)]),
211
+ ],
212
+ disparity,
213
+ moved,
214
+ };
215
+ }
@@ -74,3 +74,20 @@ export declare function buildHarnessPlan(domain: DomainModel): HarnessPlan;
74
74
  * so it can prefer finishing the cheap deterministic half before spending itself on the rest.
75
75
  */
76
76
  export declare function planAsText(plan: HarnessPlan): string;
77
+ /**
78
+ * The plan a model drives from: the gaps only. Saved flows are replayed by the plan's own lanes, or
79
+ * not at all when a person named the journey; a model handed them replayed every one, unrelated to
80
+ * the journey it was asked for, and spent most of its drive there.
81
+ */
82
+ export declare function withoutReplays(plan: HarnessPlan): HarnessPlan;
83
+ /**
84
+ * The plan a drive is handed: the gaps, or nothing beside a journey a person named. A named run was
85
+ * handed every other session's open intents too, and named its flow after one of them.
86
+ */
87
+ export declare function drivingPlan(plan: HarnessPlan, focus: string | undefined): HarnessPlan;
88
+ /**
89
+ * What the planner is told about the product: the plan from `.reticle`, then the app's own controls
90
+ * as they are on screen now. With only the plan, an empty project read "PLAN: none" and the planner
91
+ * proposed generic people (an admin, a sign-in journey) for an app that has neither.
92
+ */
93
+ export declare function aboutTheApp(planText: string, invoke: (name: string, args: Record<string, unknown>) => Promise<unknown>, seenBefore?: readonly string[]): Promise<string>;
@@ -21,6 +21,7 @@
21
21
  * Nothing here calls a model. The plan is the deterministic half, and the model's only job is to
22
22
  * choose among steps somebody already decided were worth taking.
23
23
  */
24
+ import { ReticleTool } from '@reticlehq/core';
24
25
  export const PlanStepKind = {
25
26
  /** Already recorded: replay it deterministically instead of paying a model to rediscover it. */
26
27
  REPLAY: 'replay',
@@ -154,3 +155,40 @@ export function planAsText(plan) {
154
155
  const lines = plan.steps.map((step, index) => ` ${String(index + 1)}. [${step.kind}] ${step.target} — ${step.why}`);
155
156
  return `PLAN (from .reticle, not from the source):\n${lines.join('\n')}`;
156
157
  }
158
+ /**
159
+ * The plan a model drives from: the gaps only. Saved flows are replayed by the plan's own lanes, or
160
+ * not at all when a person named the journey; a model handed them replayed every one, unrelated to
161
+ * the journey it was asked for, and spent most of its drive there.
162
+ */
163
+ export function withoutReplays(plan) {
164
+ return { ...plan, steps: plan.steps.filter((step) => PlanStepKind.DRIVE === step.kind) };
165
+ }
166
+ /**
167
+ * The plan a drive is handed: the gaps, or nothing beside a journey a person named. A named run was
168
+ * handed every other session's open intents too, and named its flow after one of them.
169
+ */
170
+ export function drivingPlan(plan, focus) {
171
+ return focus === undefined ? withoutReplays(plan) : { ...plan, steps: [] };
172
+ }
173
+ /** How much of the live page the planner reads. Enough for a dashboard's nav and main controls. */
174
+ const MAX_ABOUT_SNAPSHOT = 6_000;
175
+ /**
176
+ * What the planner is told about the product: the plan from `.reticle`, then the app's own controls
177
+ * as they are on screen now. With only the plan, an empty project read "PLAN: none" and the planner
178
+ * proposed generic people (an admin, a sign-in journey) for an app that has neither.
179
+ */
180
+ export async function aboutTheApp(planText, invoke, seenBefore = []) {
181
+ const seen = 0 === seenBefore.length
182
+ ? ''
183
+ : `\n\nCONTROLS SEEN ACROSS THE WHOLE APP LAST TIME, BY PAGE (not only this page):\n${seenBefore.join('\n')}`;
184
+ try {
185
+ const snap = await invoke(ReticleTool.SNAPSHOT, { mode: 'interactive' });
186
+ const tree = 'object' === typeof snap && null !== snap ? snap.tree : undefined;
187
+ if ('string' !== typeof tree || 0 === tree.length)
188
+ return `${planText}${seen}`;
189
+ return `${planText}\n\nTHE APP AS IT IS ON SCREEN NOW (its own controls, in its own words):\n${tree.slice(0, MAX_ABOUT_SNAPSHOT)}${seen}`;
190
+ }
191
+ catch {
192
+ return `${planText}${seen}`;
193
+ }
194
+ }