@reticlehq/server 3.4.0 → 3.6.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 (350) hide show
  1. package/README.md +1 -1
  2. package/SKILL.md +16 -8
  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-verdict.d.ts +1 -0
  6. package/dist/command/cli/adhoc-verdict.js +6 -3
  7. package/dist/command/cli/answers/open-note.d.ts +2 -0
  8. package/dist/command/cli/answers/open-note.js +22 -0
  9. package/dist/command/cli/auth/cloud-session.d.ts +4 -4
  10. package/dist/command/cli/auth/device-flow.d.ts +2 -2
  11. package/dist/command/cli/cli-flow-commands.js +4 -8
  12. package/dist/command/cli/cli-parse.d.ts +1 -1
  13. package/dist/command/cli/cli-parse.js +13 -11
  14. package/dist/command/cli/cli-verify.d.ts +1 -1
  15. package/dist/command/cli/cli-verify.js +35 -25
  16. package/dist/command/cli/cloud-cli.js +110 -12
  17. package/dist/command/cli/cloud-login.d.ts +9 -1
  18. package/dist/command/cli/cloud-login.js +43 -8
  19. package/dist/command/cli/demo/demo-page.js +11 -3
  20. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
  21. package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
  22. package/dist/command/cli/drive/drive-attach.d.ts +27 -2
  23. package/dist/command/cli/drive/drive-attach.js +71 -4
  24. package/dist/command/cli/drive/drive-command.d.ts +2 -1
  25. package/dist/command/cli/drive/drive-command.js +13 -7
  26. package/dist/command/cli/lifecycle/daemon-lifecycle.js +4 -1
  27. package/dist/command/cli/ports/port-holder.d.ts +10 -0
  28. package/dist/command/cli/ports/port-holder.js +24 -0
  29. package/dist/command/cli/setup-mcp-cli.js +15 -5
  30. package/dist/command/cli/tutorial.d.ts +2 -2
  31. package/dist/command/cli/tutorial.js +6 -9
  32. package/dist/command/cli.d.ts +6 -0
  33. package/dist/command/cli.js +45 -23
  34. package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
  35. package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
  36. package/dist/command/daemon/daemon-resolve.d.ts +14 -0
  37. package/dist/command/daemon/daemon-resolve.js +33 -2
  38. package/dist/command/setup/agent-writer.d.ts +1 -1
  39. package/dist/command/setup/agent-writer.js +3 -2
  40. package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
  41. package/dist/command/setup/bringup/connect-lease.js +1 -0
  42. package/dist/command/setup/bringup/dev-server-wait.d.ts +10 -0
  43. package/dist/command/setup/bringup/dev-server-wait.js +20 -1
  44. package/dist/command/setup/init/init-port.d.ts +4 -0
  45. package/dist/command/setup/init/init-port.js +10 -0
  46. package/dist/command/setup/init/init-runtime.d.ts +10 -0
  47. package/dist/command/setup/init/init-runtime.js +71 -9
  48. package/dist/command/setup/node-effects.js +8 -2
  49. package/dist/command/setup/remaining-steps.js +2 -1
  50. package/dist/command/setup/run-setup.d.ts +7 -0
  51. package/dist/command/setup/run-setup.js +38 -25
  52. package/dist/command/setup/setup-command.d.ts +2 -1
  53. package/dist/command/setup/setup-command.js +2 -0
  54. package/dist/command/setup/setup-mcp.d.ts +2 -0
  55. package/dist/command/setup/setup-mcp.js +14 -5
  56. package/dist/command/version/peer-announce.d.ts +6 -2
  57. package/dist/command/version/peer-announce.js +8 -6
  58. package/dist/command/version/version-nudge.d.ts +17 -3
  59. package/dist/command/version/version-nudge.js +25 -4
  60. package/dist/command/version/version-skew.js +11 -2
  61. package/dist/features/crawl/crawl-tools.js +4 -0
  62. package/dist/features/crawl/crawl.d.ts +6 -0
  63. package/dist/features/crawl/crawl.js +9 -1
  64. package/dist/features/exhaust/ledger.d.ts +7 -0
  65. package/dist/features/exhaust/ledger.js +35 -9
  66. package/dist/features/harness/app-findings.d.ts +2 -0
  67. package/dist/features/harness/app-findings.js +52 -0
  68. package/dist/features/harness/drive-report.d.ts +27 -1
  69. package/dist/features/harness/drive-report.js +162 -11
  70. package/dist/features/harness/drivers.d.ts +10 -14
  71. package/dist/features/harness/drivers.js +10 -14
  72. package/dist/features/harness/fill-values.d.ts +3 -69
  73. package/dist/features/harness/fill-values.js +3 -133
  74. package/dist/features/harness/goals.d.ts +21 -0
  75. package/dist/features/harness/goals.js +77 -0
  76. package/dist/features/harness/harness.d.ts +21 -0
  77. package/dist/features/harness/harness.js +69 -2
  78. package/dist/features/harness/platform/drive-target.d.ts +30 -0
  79. package/dist/features/harness/platform/drive-target.js +81 -0
  80. package/dist/features/harness/platform/local-apps.d.ts +94 -0
  81. package/dist/features/harness/platform/local-apps.js +204 -0
  82. package/dist/features/harness/platform/remote-drive.d.ts +180 -0
  83. package/dist/features/harness/platform/remote-drive.js +365 -0
  84. package/dist/features/harness/platform/script.d.ts +48 -0
  85. package/dist/features/harness/platform/script.js +128 -0
  86. package/dist/features/harness/platform/server-driver.d.ts +41 -0
  87. package/dist/features/harness/platform/server-driver.js +179 -0
  88. package/dist/features/harness/platform-config.d.ts +7 -0
  89. package/dist/features/harness/platform-config.js +14 -2
  90. package/dist/features/harness/script/app-controls.d.ts +5 -0
  91. package/dist/features/harness/script/app-controls.js +40 -0
  92. package/dist/features/harness/script/lane-ids.d.ts +14 -0
  93. package/dist/features/harness/script/lane-ids.js +16 -0
  94. package/dist/features/harness/script/script-run.d.ts +41 -0
  95. package/dist/features/harness/script/script-run.js +299 -0
  96. package/dist/features/license/license.d.ts +2 -2
  97. package/dist/features/visual/visual-tools.d.ts +10 -1
  98. package/dist/features/visual/visual-tools.js +40 -3
  99. package/dist/hooks/driven-by.d.ts +4 -0
  100. package/dist/hooks/driven-by.js +16 -0
  101. package/dist/hooks/hook-commands.js +15 -4
  102. package/dist/hooks/tool-log.d.ts +9 -0
  103. package/dist/hooks/tool-log.js +29 -0
  104. package/dist/index.d.ts +1 -0
  105. package/dist/index.js +91 -89
  106. package/dist/judgement/capsule/capsule-store.d.ts +4 -4
  107. package/dist/judgement/runs/artifact/build-verification-run.js +6 -0
  108. package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
  109. package/dist/judgement/runs/artifact/replay-mapping.js +16 -6
  110. package/dist/judgement/runs/artifact/run-store.d.ts +1 -1
  111. package/dist/judgement/runs/artifact/run-store.js +26 -1
  112. package/dist/judgement/runs/drive-run.d.ts +22 -0
  113. package/dist/judgement/runs/drive-run.js +99 -1
  114. package/dist/judgement/runs/repair-prompt.js +1 -1
  115. package/dist/judgement/runs/reticle-runner.js +8 -1
  116. package/dist/judgement/runs/verification-sync.d.ts +3 -2
  117. package/dist/judgement/runs/verification-sync.js +4 -3
  118. package/dist/language/flows/change/gate.d.ts +10 -0
  119. package/dist/language/flows/change/gate.js +22 -0
  120. package/dist/language/flows/decision.js +34 -0
  121. package/dist/language/flows/flow-anchor.d.ts +54 -8
  122. package/dist/language/flows/flow-anchor.js +88 -3
  123. package/dist/language/flows/flow-cross-step.d.ts +15 -0
  124. package/dist/language/flows/flow-cross-step.js +21 -0
  125. package/dist/language/flows/flow-learning.js +8 -11
  126. package/dist/language/flows/flow-mutate-tools.js +5 -3
  127. package/dist/language/flows/flow-replay-run.d.ts +23 -9
  128. package/dist/language/flows/flow-replay-run.js +101 -94
  129. package/dist/language/flows/flow-replay.d.ts +23 -1
  130. package/dist/language/flows/flow-replay.js +92 -19
  131. package/dist/language/flows/flow-scope.js +5 -1
  132. package/dist/language/flows/flow-step-runners.d.ts +20 -2
  133. package/dist/language/flows/flow-step-runners.js +236 -42
  134. package/dist/language/flows/flow-store-for-session.d.ts +2 -2
  135. package/dist/language/flows/flow-store-for-session.js +2 -2
  136. package/dist/language/flows/flow-tools.js +58 -34
  137. package/dist/language/flows/flows.js +5 -2
  138. package/dist/language/flows/heal-run.js +6 -4
  139. package/dist/language/flows/recording/flake.d.ts +2 -2
  140. package/dist/language/flows/recording/tape/recordings.d.ts +30 -4
  141. package/dist/language/flows/recording/tape/recordings.js +40 -8
  142. package/dist/language/flows/replay-from-hud.d.ts +20 -0
  143. package/dist/language/flows/replay-from-hud.js +51 -0
  144. package/dist/language/flows/replay.d.ts +9 -5
  145. package/dist/language/flows/replay.js +27 -9
  146. package/dist/language/flows/suite/suite-flakes.js +2 -0
  147. package/dist/language/flows/suite-selection.d.ts +2 -15
  148. package/dist/language/flows/suite-selection.js +4 -3
  149. package/dist/language/flows/verify-change-tools.js +8 -4
  150. package/dist/launch-chromium.d.ts +27 -5
  151. package/dist/launch-chromium.js +38 -8
  152. package/dist/memory/cloud/cloud-config.d.ts +12 -0
  153. package/dist/memory/cloud/cloud-config.js +15 -0
  154. package/dist/memory/cloud/cloud-sync.d.ts +17 -14
  155. package/dist/memory/cloud/cloud-sync.js +12 -1
  156. package/dist/memory/cloud/harness-config.d.ts +26 -1
  157. package/dist/memory/cloud/harness-config.js +99 -4
  158. package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
  159. package/dist/memory/cloud/hud-notices-source.js +128 -0
  160. package/dist/memory/cloud/memory-scope.d.ts +144 -0
  161. package/dist/memory/cloud/memory-scope.js +205 -0
  162. package/dist/memory/cloud/sync-cycle.d.ts +21 -3
  163. package/dist/memory/cloud/sync-cycle.js +45 -5
  164. package/dist/memory/cloud/sync-daemon.js +7 -5
  165. package/dist/memory/cloud/sync-disk.d.ts +1 -1
  166. package/dist/memory/cloud/sync-disk.js +5 -8
  167. package/dist/memory/impact/account-watch.d.ts +19 -0
  168. package/dist/memory/impact/account-watch.js +34 -0
  169. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  170. package/dist/memory/impact/impact-recorder.js +12 -2
  171. package/dist/memory/impact/impact-store.d.ts +16 -0
  172. package/dist/memory/impact/impact-store.js +142 -26
  173. package/dist/memory/intent/intent-shard.d.ts +2 -2
  174. package/dist/memory/intent/intent-tools.js +88 -5
  175. package/dist/memory/journal/envelope.d.ts +16 -16
  176. package/dist/memory/journal/journal-query.d.ts +14 -0
  177. package/dist/memory/journal/journal-query.js +15 -0
  178. package/dist/memory/journal/journal-recorder.js +7 -1
  179. package/dist/memory/journal/on-disk/retention.d.ts +3 -0
  180. package/dist/memory/journal/on-disk/retention.js +5 -0
  181. package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
  182. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -4
  183. package/dist/memory/journal/session-end.js +6 -4
  184. package/dist/memory/project/artifact-root-resolver.d.ts +36 -1
  185. package/dist/memory/project/artifact-root-resolver.js +134 -26
  186. package/dist/memory/project/artifact-root.d.ts +42 -5
  187. package/dist/memory/project/artifact-root.js +87 -8
  188. package/dist/memory/project/dir/reticle-dir.d.ts +4 -2
  189. package/dist/memory/project/dir/reticle-dir.js +3 -1
  190. package/dist/memory/project/project-tools.js +22 -3
  191. package/dist/memory/project/session-root.d.ts +24 -1
  192. package/dist/memory/project/session-root.js +41 -5
  193. package/dist/memory/project/sync-status.d.ts +39 -0
  194. package/dist/memory/project/sync-status.js +90 -0
  195. package/dist/memory/recall/memory-tools.js +2 -0
  196. package/dist/memory/recall/project-memory.d.ts +19 -0
  197. package/dist/memory/recall/project-memory.js +45 -6
  198. package/dist/portal/bridge/bridge.d.ts +7 -4
  199. package/dist/portal/bridge/bridge.js +25 -3
  200. package/dist/portal/bridge/pairing-token.d.ts +9 -0
  201. package/dist/portal/bridge/pairing-token.js +17 -0
  202. package/dist/portal/input/real-input.d.ts +81 -10
  203. package/dist/portal/input/real-input.js +207 -22
  204. package/dist/portal/input/viewport-tools.js +19 -9
  205. package/dist/portal/pool/browser-pool.d.ts +22 -9
  206. package/dist/portal/pool/browser-pool.js +70 -35
  207. package/dist/portal/pool/playwright-launcher.d.ts +13 -0
  208. package/dist/portal/pool/playwright-launcher.js +17 -1
  209. package/dist/portal/pool/pool-contract.d.ts +7 -4
  210. package/dist/portal/session/command-payload.d.ts +8 -0
  211. package/dist/portal/session/command-payload.js +19 -0
  212. package/dist/portal/session/dev-server/dev-command.d.ts +12 -0
  213. package/dist/portal/session/dev-server/dev-command.js +61 -12
  214. package/dist/portal/session/facts/departure-note.d.ts +22 -0
  215. package/dist/portal/session/facts/departure-note.js +47 -0
  216. package/dist/portal/session/facts/session-replaced.d.ts +5 -0
  217. package/dist/portal/session/facts/session-replaced.js +5 -0
  218. package/dist/portal/session/first-run-wiring.d.ts +42 -0
  219. package/dist/portal/session/first-run-wiring.js +132 -0
  220. package/dist/portal/session/human/notes-ledger.d.ts +20 -0
  221. package/dist/portal/session/human/notes-ledger.js +55 -0
  222. package/dist/portal/session/human/review-store.d.ts +12 -0
  223. package/dist/portal/session/human/review-store.js +18 -10
  224. package/dist/portal/session/live-control-tools.d.ts +0 -13
  225. package/dist/portal/session/live-control-tools.js +28 -3
  226. package/dist/portal/session/no-session-diagnosis.d.ts +7 -0
  227. package/dist/portal/session/no-session-diagnosis.js +15 -0
  228. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  229. package/dist/portal/session/no-session-next-action.js +31 -5
  230. package/dist/portal/session/no-session-watch.d.ts +14 -1
  231. package/dist/portal/session/no-session-watch.js +63 -10
  232. package/dist/portal/session/presence/session-mirror.js +3 -0
  233. package/dist/portal/session/serving-directory.d.ts +27 -0
  234. package/dist/portal/session/serving-directory.js +45 -0
  235. package/dist/portal/session/session-health.d.ts +7 -0
  236. package/dist/portal/session/session-health.js +6 -0
  237. package/dist/portal/session/session-info.d.ts +8 -1
  238. package/dist/portal/session/session-info.js +6 -0
  239. package/dist/portal/session/session-manager.d.ts +21 -0
  240. package/dist/portal/session/session-manager.js +44 -8
  241. package/dist/portal/session/session-reaper.js +4 -1
  242. package/dist/portal/session/session-successor.d.ts +5 -0
  243. package/dist/portal/session/session-tools.js +26 -3
  244. package/dist/portal/session/session.d.ts +12 -10
  245. package/dist/portal/session/session.js +30 -31
  246. package/dist/start-options.d.ts +6 -0
  247. package/dist/status-payload.d.ts +10 -0
  248. package/dist/status-payload.js +23 -0
  249. package/dist/surface/http-server.d.ts +1 -1
  250. package/dist/surface/http-server.js +15 -4
  251. package/dist/surface/mcp/mcp-proxy.d.ts +5 -0
  252. package/dist/surface/mcp/mcp-proxy.js +36 -5
  253. package/dist/surface/mcp/mcp.d.ts +11 -6
  254. package/dist/surface/mcp/mcp.js +28 -14
  255. package/dist/surface/mcp/proxy/proxy-log.js +3 -5
  256. package/dist/surface/mcp/server-instructions.d.ts +4 -2
  257. package/dist/surface/mcp/server-instructions.js +14 -4
  258. package/dist/surface/mcp/shared-params.js +2 -2
  259. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
  260. package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
  261. package/dist/surface/tools/act/settle-in-flight.js +25 -3
  262. package/dist/surface/tools/act-sequence-tool.js +2 -2
  263. package/dist/surface/tools/act-tools.js +25 -9
  264. package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
  265. package/dist/surface/tools/assert/assert-verdict.js +17 -2
  266. package/dist/surface/tools/browser-tools.js +8 -1
  267. package/dist/surface/tools/chat-drives.d.ts +26 -0
  268. package/dist/surface/tools/chat-drives.js +165 -0
  269. package/dist/surface/tools/dynamic-tools.js +29 -2
  270. package/dist/surface/tools/empty-session-list.d.ts +41 -0
  271. package/dist/surface/tools/empty-session-list.js +80 -0
  272. package/dist/surface/tools/error-recovery.d.ts +6 -0
  273. package/dist/surface/tools/error-recovery.js +38 -6
  274. package/dist/surface/tools/explore-tools.d.ts +10 -1
  275. package/dist/surface/tools/explore-tools.js +82 -13
  276. package/dist/surface/tools/feedback-tools.js +14 -0
  277. package/dist/surface/tools/harness-explore.d.ts +96 -14
  278. package/dist/surface/tools/harness-explore.js +227 -202
  279. package/dist/surface/tools/harness-plan.d.ts +12 -0
  280. package/dist/surface/tools/harness-plan.js +31 -0
  281. package/dist/surface/tools/harness-script.d.ts +8 -0
  282. package/dist/surface/tools/harness-script.js +342 -0
  283. package/dist/surface/tools/harness-toolset.d.ts +14 -1
  284. package/dist/surface/tools/harness-toolset.js +77 -6
  285. package/dist/surface/tools/invoke-tool.js +64 -9
  286. package/dist/surface/tools/lease-seed.d.ts +29 -0
  287. package/dist/surface/tools/lease-seed.js +123 -0
  288. package/dist/surface/tools/lease-tools.d.ts +3 -23
  289. package/dist/surface/tools/lease-tools.js +30 -131
  290. package/dist/surface/tools/live-call-text.js +2 -2
  291. package/dist/surface/tools/next-step.d.ts +19 -0
  292. package/dist/surface/tools/next-step.js +159 -0
  293. package/dist/surface/tools/observe-tools.js +2 -4
  294. package/dist/surface/tools/platform-moment.d.ts +12 -0
  295. package/dist/surface/tools/platform-moment.js +168 -0
  296. package/dist/surface/tools/query-hint-schema.d.ts +7 -0
  297. package/dist/surface/tools/query-hint-schema.js +10 -0
  298. package/dist/surface/tools/read-tools.js +8 -2
  299. package/dist/surface/tools/real-input-attempt.js +96 -13
  300. package/dist/surface/tools/tool-kit.d.ts +25 -1
  301. package/dist/surface/tools/tool-kit.js +4 -6
  302. package/dist/surface/tools/tools.js +20 -48
  303. package/dist/telemetry/argument-shape.js +1 -1
  304. package/dist/telemetry/hud-metrics.d.ts +2 -0
  305. package/dist/telemetry/hud-metrics.js +17 -0
  306. package/dist/telemetry/onboarding-firsts.d.ts +2 -2
  307. package/dist/telemetry/onboarding-firsts.js +2 -2
  308. package/dist/telemetry/telemetry.d.ts +12 -0
  309. package/dist/telemetry/telemetry.js +43 -14
  310. package/dist/telemetry/verification-of.js +1 -0
  311. package/dist/wire-journal.js +4 -1
  312. package/docs/README.md +1 -1
  313. package/docs/actions.mdx +1 -2
  314. package/docs/agent-cheatsheet.md +1 -1
  315. package/docs/autodrive.md +29 -25
  316. package/docs/cli/cloud.mdx +6 -4
  317. package/docs/cli/doctor.mdx +6 -0
  318. package/docs/cli/drive.mdx +8 -2
  319. package/docs/cli/init.mdx +11 -13
  320. package/docs/cli/status.mdx +5 -1
  321. package/docs/cli/version.mdx +3 -3
  322. package/docs/cli.mdx +14 -8
  323. package/docs/desktop.mdx +5 -1
  324. package/docs/environment.mdx +3 -7
  325. package/docs/getting-started.md +14 -2
  326. package/docs/human-control.md +1 -2
  327. package/docs/index.mdx +4 -3
  328. package/docs/install-agentic.mdx +1 -1
  329. package/docs/install-manual.mdx +2 -2
  330. package/docs/packages/next.mdx +3 -0
  331. package/docs/packages/tauri.mdx +2 -2
  332. package/docs/packages/vite-plugin.mdx +24 -1
  333. package/docs/packages.mdx +1 -1
  334. package/docs/quickstart.mdx +23 -11
  335. package/docs/telemetry.md +1 -1
  336. package/docs/tools/act.mdx +1 -1
  337. package/docs/tools/session-and-feedback.mdx +9 -9
  338. package/docs/usage.md +5 -3
  339. package/docs/what-is-recorded.md +13 -3
  340. package/docs/what-is-reticle.mdx +3 -1
  341. package/package.json +8 -12
  342. package/dist/features/harness/driver.d.ts +0 -50
  343. package/dist/features/harness/driver.js +0 -236
  344. package/dist/features/harness/jev-driver.d.ts +0 -188
  345. package/dist/features/harness/jev-driver.js +0 -678
  346. package/dist/features/harness/openai-driver.d.ts +0 -46
  347. package/dist/features/harness/openai-driver.js +0 -194
  348. package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
  349. package/dist/memory/project/dir/fill-value-store.js +0 -88
  350. package/docs/local-registry.md +0 -143
@@ -252,7 +252,6 @@ export declare const IntentShardSchema: z.ZodObject<{
252
252
  }>>;
253
253
  }, "strip", z.ZodTypeAny, {
254
254
  version: 1;
255
- subject: string;
256
255
  intents: Record<string, {
257
256
  status: "proved" | "proposed" | "agreed" | "stale";
258
257
  state: "proved" | "declared" | "bound";
@@ -279,9 +278,9 @@ export declare const IntentShardSchema: z.ZodObject<{
279
278
  statement: string;
280
279
  }[] | undefined;
281
280
  }>;
281
+ subject: string;
282
282
  }, {
283
283
  version: 1;
284
- subject: string;
285
284
  intents: Record<string, {
286
285
  status: "proved" | "proposed" | "agreed" | "stale";
287
286
  state: "proved" | "declared" | "bound";
@@ -308,6 +307,7 @@ export declare const IntentShardSchema: z.ZodObject<{
308
307
  statement: string;
309
308
  }[] | undefined;
310
309
  }>;
310
+ subject: string;
311
311
  }>;
312
312
  export type IntentShard = z.infer<typeof IntentShardSchema>;
313
313
  export declare const IntentIndexSchema: z.ZodObject<{
@@ -1,8 +1,13 @@
1
+ import { existsSync, readFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
1
3
  import { z } from 'zod';
4
+ import { StatementSource, classifyStatement, splitStatements, } from '@reticlehq/core/artifacts';
5
+ import { redactFeedbackText } from '../../telemetry/feedback.js';
6
+ import { reticleDirPaths } from '../project/dir/reticle-dir.js';
2
7
  import { IntentStore } from './intent-store.js';
3
8
  import { IntentShardStore } from './intent-shard-store.js';
4
9
  import { IntentStatus } from './intent-shard.js';
5
- import { ReticleTool } from '@reticlehq/core';
10
+ import { ReticleDir, ReticleTool, apiKeyFrom } from '@reticlehq/core';
6
11
  import { sessionIdShape } from '../../surface/tools/tool-kit.js';
7
12
  import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate.js';
8
13
  import { sessionRoot } from '../project/session-root.js';
@@ -32,7 +37,7 @@ const MIGRATE = 'migrate';
32
37
  export const INTENT_TOOLS = [
33
38
  {
34
39
  name: ReticleTool.INTENT,
35
- description: 'Record what a change is SUPPOSED to make true, as a durable statement ABOUT THE PRODUCT that a teammate who was not here will understand in six months — name the behaviour, not this run or its step number, and never "renders cleanly", which nothing can check. It is SHARED memory: pooled per project and read back by later agents. Capture it while you still know — then verification does not have to re-derive it from the DOM later. { action:"declare", intents:[{ id, statement, surface? }] } takes prose and needs NO predicate: at declare time there is often no route, no ref and no code yet, and a predicate demanded there is just a mechanism. Declare EARLY (as you build) and batch them — one call per feature is the whole budget. { action:"bind", id, binding } attaches the predicate that would prove it once you know how; an intent with no binding is not a failure, it is the most interesting row in the ledger — something meant that nothing can currently prove. { action:"list" } returns what is still open. Stored in .reticle/intent/<subject>/intent.json (a flow name is its subject), git-checked so a human sees in review if an intent was later narrowed to match what was easy to prove.',
40
+ description: 'Record what a change is SUPPOSED to make true, as a durable statement ABOUT THE PRODUCT that a teammate who was not here will understand in six months — name the behaviour, not this run or its step number, and never "renders cleanly", which nothing can check. It is SHARED memory: pooled per project and read back by later agents. Capture it while you still know — then verification does not have to re-derive it from the DOM later. { action:"declare", intents:[{ id, statement, surface? }] } takes prose and needs NO predicate: at declare time there is often no route, no ref and no code yet, and a predicate demanded there is just a mechanism. Declare EARLY (as you build) and batch them — one call per feature is the whole budget. { action:"bind", id, binding } attaches the predicate that would prove it once you know how; an intent with no binding is not a failure, it is the most interesting row in the ledger — something meant that nothing can currently prove. { action:"list" } returns what is still open. Pass `request` (what the user asked, verbatim) once per task. Stored in .reticle/intent/, git-checked.',
36
41
  example: {
37
42
  action: DECLARE,
38
43
  intents: [
@@ -70,8 +75,11 @@ export const INTENT_TOOLS = [
70
75
  })
71
76
  .optional(),
72
77
  }))
78
+ // Non-empty in the schema too, so the advertised contract says what `declare` enforces.
79
+ .min(1)
73
80
  .optional()
74
81
  .describe('declare only. Batchable — declare every intent for a feature in one call.'),
82
+ request: z.string().optional().describe("declare: the user's words, verbatim."),
75
83
  id: z.string().optional().describe('bind only: which intent the predicate proves.'),
76
84
  /*
77
85
  * The predicate schema, not `unknown`.
@@ -153,9 +161,18 @@ export const INTENT_TOOLS = [
153
161
  return { intents: await store.open() };
154
162
  }
155
163
  const raw = args['intents'];
156
- const entries = Array.isArray(raw)
157
- ? raw
158
- : [];
164
+ const request = asString(args['request']);
165
+ if (request !== undefined && 0 < request.trim().length) {
166
+ await recordRequest(deps, root, request, Array.isArray(raw) ? raw : []);
167
+ if (!Array.isArray(raw) || 0 === raw.length)
168
+ return { request: 'recorded', path: root };
169
+ }
170
+ // Refused, not read as an empty list: `declare` with nothing to declare stored nothing and
171
+ // answered `{ intents: [] }`, which an agent reads as a declaration that worked (#1118).
172
+ if (!Array.isArray(raw) || 0 === raw.length) {
173
+ throw new Error(`${ReticleTool.INTENT} declare: \`intents\` must be a non-empty array of { id, statement }, got ${raw === undefined ? 'nothing' : JSON.stringify(raw)} — nothing was stored`);
174
+ }
175
+ const entries = raw;
159
176
  const declared = await store.declare(entries);
160
177
  // Said, not swallowed: an agent that declared something and finds nothing stored would
161
178
  // otherwise conclude the ledger lost it.
@@ -166,3 +183,69 @@ export const INTENT_TOOLS = [
166
183
  },
167
184
  },
168
185
  ];
186
+ const MAX_REQUEST = 20_000;
187
+ const MAX_STATEMENT = 500;
188
+ const MAX_STATEMENTS = 100;
189
+ const PROJECT_CONFIG = '.reticle.json';
190
+ /** Credentials and personal data out, length capped: the same rules feedback reports follow. */
191
+ function redactSecrets(text, max) {
192
+ return redactFeedbackText(text, max).text;
193
+ }
194
+ /**
195
+ * Whether the request goes to the platform with the runs that verify it.
196
+ *
197
+ * A LINKED project shares it unless `.reticle.json` says `"shareRequests": false`: the platform
198
+ * reads what each run was for, which is half of what a run means. An unlinked project has nowhere
199
+ * to send it, and `"shareRequests": true` still shares from one that links later.
200
+ */
201
+ function sharesRequests(projectDir, reticleRoot) {
202
+ let setting;
203
+ try {
204
+ const config = JSON.parse(readFileSync(join(projectDir, PROJECT_CONFIG), 'utf8'));
205
+ setting = config?.shareRequests;
206
+ }
207
+ catch {
208
+ setting = undefined;
209
+ }
210
+ if (false === setting)
211
+ return false;
212
+ if (true === setting)
213
+ return true;
214
+ // Linked by `reticle connect` (cloud.json), or by a key in the environment, the way CI syncs.
215
+ return (existsSync(join(reticleRoot, ReticleDir.CLOUD_LINK_FILE)) ||
216
+ apiKeyFrom(process.env) !== undefined);
217
+ }
218
+ /**
219
+ * Keep the user's request, and every statement in it and in the declared intents, classified and
220
+ * attributed, for the runs that verify it. Secrets are redacted before anything is written.
221
+ *
222
+ * Shared with the platform from a linked project unless `.reticle.json` says `"shareRequests": false`.
223
+ */
224
+ async function recordRequest(deps, root, request, declared) {
225
+ const text = redactSecrets(request, MAX_REQUEST);
226
+ const agentStatements = declared.flatMap((d) => {
227
+ const statement = d?.statement;
228
+ return 'string' === typeof statement ? [statement] : [];
229
+ });
230
+ const context = {
231
+ request: text,
232
+ statements: [
233
+ ...splitStatements(text).map((t) => ({ text: t, source: StatementSource.USER })),
234
+ ...agentStatements.map((t) => ({
235
+ text: redactSecrets(t, MAX_STATEMENT),
236
+ source: StatementSource.AGENT,
237
+ })),
238
+ ]
239
+ .slice(0, MAX_STATEMENTS)
240
+ .map((s) => ({
241
+ ...s,
242
+ text: s.text.slice(0, MAX_STATEMENT),
243
+ kind: classifyStatement(s.text),
244
+ })),
245
+ at: deps.now(),
246
+ shared: sharesRequests(dirname(root), root),
247
+ };
248
+ const path = reticleDirPaths(root).request;
249
+ await deps.fs.mkdir(dirname(path));
250
+ await deps.fs.writeFile(path, `${JSON.stringify(context, null, 2)}\n`);
251
+ }
@@ -101,50 +101,50 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
101
101
  max: number;
102
102
  }>;
103
103
  }, "strip", z.ZodTypeAny, {
104
- durationMs: {
104
+ net: {
105
105
  count: number;
106
106
  mean: number;
107
107
  m2: number;
108
108
  max: number;
109
109
  };
110
- net: {
110
+ durationMs: {
111
111
  count: number;
112
112
  mean: number;
113
113
  m2: number;
114
114
  max: number;
115
115
  };
116
- netErrors: {
116
+ consoleErrors: {
117
117
  count: number;
118
118
  mean: number;
119
119
  m2: number;
120
120
  max: number;
121
121
  };
122
- consoleErrors: {
122
+ netErrors: {
123
123
  count: number;
124
124
  mean: number;
125
125
  m2: number;
126
126
  max: number;
127
127
  };
128
128
  }, {
129
- durationMs: {
129
+ net: {
130
130
  count: number;
131
131
  mean: number;
132
132
  m2: number;
133
133
  max: number;
134
134
  };
135
- net: {
135
+ durationMs: {
136
136
  count: number;
137
137
  mean: number;
138
138
  m2: number;
139
139
  max: number;
140
140
  };
141
- netErrors: {
141
+ consoleErrors: {
142
142
  count: number;
143
143
  mean: number;
144
144
  m2: number;
145
145
  max: number;
146
146
  };
147
- consoleErrors: {
147
+ netErrors: {
148
148
  count: number;
149
149
  mean: number;
150
150
  m2: number;
@@ -155,25 +155,25 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
155
155
  route: string;
156
156
  samples: number;
157
157
  stats: {
158
- durationMs: {
158
+ net: {
159
159
  count: number;
160
160
  mean: number;
161
161
  m2: number;
162
162
  max: number;
163
163
  };
164
- net: {
164
+ durationMs: {
165
165
  count: number;
166
166
  mean: number;
167
167
  m2: number;
168
168
  max: number;
169
169
  };
170
- netErrors: {
170
+ consoleErrors: {
171
171
  count: number;
172
172
  mean: number;
173
173
  m2: number;
174
174
  max: number;
175
175
  };
176
- consoleErrors: {
176
+ netErrors: {
177
177
  count: number;
178
178
  mean: number;
179
179
  m2: number;
@@ -184,25 +184,25 @@ export declare const RouteEnvelopeSchema: z.ZodObject<{
184
184
  route: string;
185
185
  samples: number;
186
186
  stats: {
187
- durationMs: {
187
+ net: {
188
188
  count: number;
189
189
  mean: number;
190
190
  m2: number;
191
191
  max: number;
192
192
  };
193
- net: {
193
+ durationMs: {
194
194
  count: number;
195
195
  mean: number;
196
196
  m2: number;
197
197
  max: number;
198
198
  };
199
- netErrors: {
199
+ consoleErrors: {
200
200
  count: number;
201
201
  mean: number;
202
202
  m2: number;
203
203
  max: number;
204
204
  };
205
- consoleErrors: {
205
+ netErrors: {
206
206
  count: number;
207
207
  mean: number;
208
208
  m2: number;
@@ -62,5 +62,19 @@ export declare function readQueryEvents(reader: JournalReader | undefined, buffe
62
62
  * "nothing was lost" — see `JournalReader.readWriteLoss`.
63
63
  */
64
64
  export declare function readJournalWriteLoss(reader: JournalReader | undefined, buffer: QueryBuffer): Promise<JournalWriteLoss | undefined>;
65
+ /** The slice of the ring buffer `windowLost` reads. `RingBuffer` satisfies it structurally. */
66
+ export interface LossBuffer {
67
+ lostSince(cursor: number): boolean;
68
+ }
69
+ /**
70
+ * Did the EVENT STORE lose scarce evidence from a window opened at `cursor`? The input to whether a
71
+ * verdict's capture was clean — see `RingBuffer.lostSince`, and never the raw drop counter, which
72
+ * moves for the age and churn evictions that every live page produces continuously. The journal is
73
+ * the other half of that store, so a durable read that could not reach back to `cursor` lost
74
+ * exactly what an eviction would have. Both boundaries are INCLUSIVE (`t` is a millisecond many
75
+ * records share) and an absent `lostThroughT` impeaches every window rather than none — the
76
+ * conservative direction, both times.
77
+ */
78
+ export declare function windowLost(reader: JournalReader | undefined, buffer: LossBuffer, cursor: number): boolean;
65
79
  /** Apply since/until/actionId bounds to an event list. */
66
80
  export declare function filterEvents(events: readonly ReticleEvent[], options: EventQueryOptions): ReticleEvent[];
@@ -90,6 +90,21 @@ export async function readJournalWriteLoss(reader, buffer) {
90
90
  return undefined;
91
91
  return (await reader?.readWriteLoss?.()) ?? undefined;
92
92
  }
93
+ /**
94
+ * Did the EVENT STORE lose scarce evidence from a window opened at `cursor`? The input to whether a
95
+ * verdict's capture was clean — see `RingBuffer.lostSince`, and never the raw drop counter, which
96
+ * moves for the age and churn evictions that every live page produces continuously. The journal is
97
+ * the other half of that store, so a durable read that could not reach back to `cursor` lost
98
+ * exactly what an eviction would have. Both boundaries are INCLUSIVE (`t` is a millisecond many
99
+ * records share) and an absent `lostThroughT` impeaches every window rather than none — the
100
+ * conservative direction, both times.
101
+ */
102
+ export function windowLost(reader, buffer, cursor) {
103
+ if (buffer.lostSince(cursor))
104
+ return true;
105
+ const lost = reader?.readLoss?.();
106
+ return lost !== undefined && (lost.lostThroughT === undefined || lost.lostThroughT >= cursor);
107
+ }
93
108
  /** Apply since/until/actionId bounds to an event list. */
94
109
  export function filterEvents(events, options) {
95
110
  return events.filter((event) => (options.since === undefined || event.t >= options.since) &&
@@ -1,5 +1,6 @@
1
1
  import { EventAttribution, JOURNAL_FILE_VERSION, } from '@reticlehq/core';
2
2
  import { isSelfObservation } from './self-observation.js';
3
+ import { currentDrivenBy } from '../../hooks/driven-by.js';
3
4
  import { log } from '../../log.js';
4
5
  /**
5
6
  * Logged the FIRST time a journal write is lost, and never again for that recorder.
@@ -65,7 +66,7 @@ export class JournalRecorder {
65
66
  }
66
67
  /** Open an attribution window. One action is active at a time (the agent drives sequentially). */
67
68
  beginAction(actionId, tool, args) {
68
- this.#active = { actionId, tool, args, tStart: this.#now() };
69
+ this.#active = { actionId, tool, args, tStart: this.#now(), drivenBy: currentDrivenBy() };
69
70
  }
70
71
  /** Close the active window: persist its buffered events, then the action record. No-op if none active. */
71
72
  finishAction(effect, settled, settledInMs) {
@@ -86,6 +87,7 @@ export class JournalRecorder {
86
87
  : { from: active.seqFrom, to: active.seqTo },
87
88
  tRange: { from: active.tStart, to: this.#now() },
88
89
  at: active.tStart,
90
+ ...(active.drivenBy === undefined ? {} : { drivenBy: active.drivenBy }),
89
91
  };
90
92
  this.#enqueueFlush();
91
93
  this.#chain = this.#chain
@@ -123,6 +125,10 @@ export class JournalRecorder {
123
125
  // of zero, which is exactly how much time this action attributed events over.
124
126
  tRange: { from: at, to: at },
125
127
  at,
128
+ ...(() => {
129
+ const by = currentDrivenBy();
130
+ return by === undefined ? {} : { drivenBy: by };
131
+ })(),
126
132
  };
127
133
  this.#enqueueFlush();
128
134
  this.#chain = this.#chain
@@ -11,6 +11,8 @@ export declare const DEFAULT_DIFF_RETENTION = 10;
11
11
  * for the one case where delivery was refused and somebody has to file the report by hand.
12
12
  */
13
13
  export declare const DEFAULT_FEEDBACK_RETENTION = 20;
14
+ /** Harness plans kept on disk: the platform keeps every one, this machine the recent ones. */
15
+ export declare const DEFAULT_PLAN_RETENTION = 50;
14
16
  /**
15
17
  * The TOTAL the evidence tier of one `.reticle/` may occupy, across sessions, runs, overlay diffs
16
18
  * and feedback copies together.
@@ -141,5 +143,6 @@ export declare function pruneEvidenceBudget(fs: FileSystemPort, root: string, bu
141
143
  * Capped from here rather than from the writer, which lives in an area this file does not own. A
142
144
  * retention rule is the same rule whether the directory holds journals, diffs or reports.
143
145
  */
146
+ export declare function prunePlans(fs: FileSystemPort, root: string, retention?: number): Promise<void>;
144
147
  export declare function pruneFeedback(fs: FileSystemPort, root: string, retention?: number): Promise<void>;
145
148
  export {};
@@ -14,6 +14,8 @@ export const DEFAULT_DIFF_RETENTION = 10;
14
14
  * for the one case where delivery was refused and somebody has to file the report by hand.
15
15
  */
16
16
  export const DEFAULT_FEEDBACK_RETENTION = 20;
17
+ /** Harness plans kept on disk: the platform keeps every one, this machine the recent ones. */
18
+ export const DEFAULT_PLAN_RETENTION = 50;
17
19
  const DIFF_SUFFIX = '.diff.png';
18
20
  const PNG_SUFFIX = '.png';
19
21
  /**
@@ -287,6 +289,9 @@ export async function pruneEvidenceBudget(fs, root, budgetBytes = DEFAULT_EVIDEN
287
289
  * Capped from here rather than from the writer, which lives in an area this file does not own. A
288
290
  * retention rule is the same rule whether the directory holds journals, diffs or reports.
289
291
  */
292
+ export async function prunePlans(fs, root, retention = DEFAULT_PLAN_RETENTION) {
293
+ await pruneByRecency(fs, join(root, ReticleDir.PLANS_SUBDIR), retention);
294
+ }
290
295
  export async function pruneFeedback(fs, root, retention = DEFAULT_FEEDBACK_RETENTION) {
291
296
  await pruneByRecency(fs, join(root, ReticleDir.FEEDBACK_SUBDIR), retention);
292
297
  }
@@ -1,4 +1,4 @@
1
- import { pruneEvidenceBudget, pruneFeedback, pruneSessions, pruneVisualDiffs, } from './retention.js';
1
+ import { pruneEvidenceBudget, pruneFeedback, prunePlans, pruneSessions, pruneVisualDiffs, } from './retention.js';
2
2
  import { DEFAULT_RETAIN } from './retain-policy.js';
3
3
  export async function pruneWorkspace(fs, root, live, options = {}) {
4
4
  const retain = { ...DEFAULT_RETAIN, ...options };
@@ -9,6 +9,8 @@ export async function pruneWorkspace(fs, root, live, options = {}) {
9
9
  await pruneVisualDiffs(fs, root, retain.visual);
10
10
  // Write-only local copies of reports the outbox already carries.
11
11
  await pruneFeedback(fs, root, retain.feedback);
12
+ // The recent plans are what somebody reads back; the platform holds every one.
13
+ await prunePlans(fs, root);
12
14
  // LAST, and the one that was missing: the only bound that limits SIZE rather than count.
13
15
  await pruneEvidenceBudget(fs, root, retain.budgetBytes, live);
14
16
  }
@@ -45,6 +45,8 @@ export const WORKSPACE_TIERS = {
45
45
  [ReticleDir.VISUAL_SUBDIR]: localDir,
46
46
  // Write-only: a local copy of what was already sent. The outbox is the record.
47
47
  [ReticleDir.FEEDBACK_SUBDIR]: localDir,
48
+ // What the Harness planned on this machine, and how it went. The platform keeps the team's copy.
49
+ [ReticleDir.PLANS_SUBDIR]: localDir,
48
50
  [ReticleDir.PROJECT_FILE]: localFile,
49
51
  [ReticleDir.AMBIENT_FILE]: localFile,
50
52
  [ReticleDir.ENVELOPES_FILE]: localFile,
@@ -52,6 +54,11 @@ export const WORKSPACE_TIERS = {
52
54
  // What THIS machine's drives covered, and the best each level reached — the gate's ratchet.
53
55
  [ReticleDir.COVERAGE_FILE]: localFile,
54
56
  [ReticleDir.TIERS_FILE]: localFile,
57
+ // The user's request in their own words: it leaves only with `shareRequests`, never by git push.
58
+ [ReticleDir.REQUEST_FILE]: localFile,
59
+ [ReticleDir.PLATFORM_MOMENTS_FILE]: localFile,
60
+ // Notes a human pinned in the HUD: free text about the page. The team reads them on the platform.
61
+ [ReticleDir.NOTES_FILE]: localFile,
55
62
  // The user's own record of what Reticle did for them, on THIS machine.
56
63
  [ReticleDir.IMPACT_FILE]: localFile,
57
64
  // This machine's conversation with the server. Its own doc comment says why committing it is
@@ -72,10 +79,6 @@ export const WORKSPACE_TIERS = {
72
79
  // credential, so it is safe to commit — the same reasoning that puts `cloud.json` here while its
73
80
  // API key stays in ~/.reticle.
74
81
  [ReticleDir.HOOKS_FILE]: sharedFile,
75
- // What a drive types into each labelled field. Committed for two reasons: a replay must send
76
- // exactly what the recording sent or it is not a replay, and a value a model wrote once should be
77
- // reviewable and editable by the team rather than regenerated differently on every machine.
78
- [ReticleDir.FILL_VALUES_FILE]: sharedFile,
79
82
  };
80
83
  function namesWhere(match) {
81
84
  return Object.entries(WORKSPACE_TIERS)
@@ -13,7 +13,7 @@ import { AmbientStore } from './ambient-store.js';
13
13
  import { subjectOf } from '@reticlehq/core';
14
14
  import { pruneWorkspace } from './on-disk/startup-maintenance.js';
15
15
  import { buildVerificationRun } from '../../judgement/runs/artifact/build-verification-run.js';
16
- import { driveRunFrom, driveRunId } from '../../judgement/runs/drive-run.js';
16
+ import { driveRunId, driveRunsFrom } from '../../judgement/runs/drive-run.js';
17
17
  import { RunStore } from '../../judgement/runs/artifact/run-store.js';
18
18
  /**
19
19
  * Build the teardown handler the bridge fires when a session is removed. Flushes the journal first (so no
@@ -173,7 +173,7 @@ export async function recordDriveRun(deps, session) {
173
173
  if (session.readJournalActions === undefined)
174
174
  return;
175
175
  const actions = await session.readJournalActions();
176
- const input = driveRunFrom(actions, {
176
+ const inputs = driveRunsFrom(actions, {
177
177
  // Derived from the session, NOT random. Teardown fires on every socket close, and a reconnecting
178
178
  // tab keeps its session id and appends to the same ledger — so a drive across two page reloads
179
179
  // would fold the whole ledger twice and publish two overlapping rows, the second a superset of
@@ -182,7 +182,7 @@ export async function recordDriveRun(deps, session) {
182
182
  runId: driveRunId(session.id),
183
183
  ...(session.projectId === undefined ? {} : { projectId: session.projectId }),
184
184
  });
185
- if (input === undefined)
185
+ if (0 === inputs.length)
186
186
  return;
187
187
  // The protocol reaching the artifact a person actually reads. Only when the session could say
188
188
  // where it was: a subject with no locator is not a weaker subject, it is a guess, and the
@@ -201,7 +201,9 @@ export async function recordDriveRun(deps, session) {
201
201
  // used to write this artifact with no callback at all, so the evidence from a whole session sat
202
202
  // on disk until a timer noticed — which, for the last session of the day, could be never.
203
203
  deps.onRunPersisted === undefined ? undefined : { onWrote: deps.onRunPersisted });
204
- await store.write(buildVerificationRun({ ...input, ...(subject === undefined ? {} : { subject }) }, deps.now ?? (() => Date.now())));
204
+ for (const input of inputs) {
205
+ await store.write(buildVerificationRun({ ...input, ...(subject === undefined ? {} : { subject }) }, deps.now ?? (() => Date.now())));
206
+ }
205
207
  }
206
208
  /** Persist what this session drove as a replayable flow, when it declared anything provable. */
207
209
  async function saveDrivenFlow(deps, session) {
@@ -1,3 +1,38 @@
1
+ import { type ProjectCandidate } from '@reticlehq/core/artifacts';
1
2
  import { type ProjectId } from '@reticlehq/core';
2
3
  import { type ArtifactRoot } from './artifact-root.js';
3
- export declare function artifactRootResolver(daemonRoot: string): (projectId: ProjectId | undefined, origin?: string) => ArtifactRoot;
4
+ /**
5
+ * Every project this machine knows the directory of: discovered `.reticle.json` files first, then
6
+ * the user-level registry, then the dev servers the build plugin announced. Read on each call, since
7
+ * `init` can run in another terminal while the daemon is up.
8
+ *
9
+ * Exported because sync must cover exactly the projects runs are written into. It kept its own list
10
+ * without the announced dev servers, so a project known only through its running dev server had its
11
+ * runs written to its `.reticle/runs/` and never sent, with nothing reporting a problem.
12
+ */
13
+ export declare function knownProjectCandidates(): ProjectCandidate[];
14
+ /**
15
+ * The directory of the project a page announced, or undefined when this machine does not know it.
16
+ *
17
+ * A daemon is shared: started from `$HOME`, a monorepo root, or another project's MCP client, its
18
+ * cwd is often not the app that sent the HELLO. The version-skew remedy read `package.json` from
19
+ * cwd anyway, so it fell back to the generic sensor package and told a Next.js project to install
20
+ * `@reticlehq/browser` (#1135). This is the same lookup the artifact root uses, keyed by the page's
21
+ * own project id.
22
+ */
23
+ export declare function projectDirectoryFor(projectId: string | undefined): string | undefined;
24
+ /** Where this resolver gets its IO answers. The defaults are the production ones. */
25
+ export interface ArtifactRootResolverDeps {
26
+ /** Every project this machine knows about. Defaults to discovery + the user registry. */
27
+ candidates?: () => ProjectCandidate[];
28
+ /** Whether the daemon's own directory is a Reticle project. Defaults to looking at disk. */
29
+ daemonIsProject?: (daemonRoot: string) => boolean;
30
+ /**
31
+ * The directory of the dev server that served a page origin, or undefined when unobservable.
32
+ * Required, not defaulted: the production answer reads daemon state and shells out, which is the
33
+ * wiring layer's business (`portal/session/serving-directory.ts`), and a resolver built without it
34
+ * would silently keep sending every worktree's artifacts to the primary checkout.
35
+ */
36
+ servingDirectory: (origin: string) => string | undefined;
37
+ }
38
+ export declare function artifactRootResolver(daemonRoot: string, deps: ArtifactRootResolverDeps): (projectId: ProjectId | undefined, origin?: string) => ArtifactRoot;