@reticlehq/server 3.7.0 → 3.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (578) hide show
  1. package/SKILL.md +59 -68
  2. package/bin/reticle.js +9 -2
  3. package/dist/command/cli/adhoc-suite.js +1 -1
  4. package/dist/command/cli/adhoc-verdict.d.ts +12 -0
  5. package/dist/command/cli/adhoc-verdict.js +62 -4
  6. package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
  7. package/dist/command/cli/answers/gate-hook-message.js +5 -1
  8. package/dist/command/cli/auth/cloud-session.d.ts +11 -19
  9. package/dist/command/cli/auth/cloud-session.js +23 -0
  10. package/dist/command/cli/auth/device-flow.d.ts +3 -37
  11. package/dist/command/cli/cli-doctor.js +66 -21
  12. package/dist/command/cli/cli-flow-commands.js +53 -11
  13. package/dist/command/cli/cli-kill.d.ts +8 -0
  14. package/dist/command/cli/cli-kill.js +43 -3
  15. package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
  16. package/dist/command/cli/cli-parse-feedback.js +13 -1
  17. package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
  18. package/dist/command/cli/cli-parse-grammar.js +1 -6
  19. package/dist/command/cli/cli-parse-serve.d.ts +24 -0
  20. package/dist/command/cli/cli-parse-serve.js +124 -0
  21. package/dist/command/cli/cli-parse.d.ts +12 -11
  22. package/dist/command/cli/cli-parse.js +100 -123
  23. package/dist/command/cli/cli-usage.d.ts +0 -11
  24. package/dist/command/cli/cli-usage.js +43 -16
  25. package/dist/command/cli/cli-verify.d.ts +1 -1
  26. package/dist/command/cli/cli-verify.js +29 -14
  27. package/dist/command/cli/cloud-cli.js +27 -9
  28. package/dist/command/cli/cloud-kit.js +3 -3
  29. package/dist/command/cli/cloud-link.d.ts +1 -20
  30. package/dist/command/cli/cloud-link.js +2 -0
  31. package/dist/command/cli/cloud-login.d.ts +6 -2
  32. package/dist/command/cli/cloud-login.js +13 -41
  33. package/dist/command/cli/config/checkout.d.ts +10 -0
  34. package/dist/command/cli/config/checkout.js +78 -0
  35. package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
  36. package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
  37. package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
  38. package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
  39. package/dist/command/cli/doctor/doctor-rows.js +4 -0
  40. package/dist/command/cli/drive/drive-attach.d.ts +5 -0
  41. package/dist/command/cli/drive/drive-attach.js +21 -1
  42. package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
  43. package/dist/command/cli/hook/codex-transcript.js +224 -0
  44. package/dist/command/cli/hook/episode-structure.d.ts +24 -0
  45. package/dist/command/cli/hook/episode-structure.js +138 -0
  46. package/dist/command/cli/hook/hook-command.d.ts +9 -0
  47. package/dist/command/cli/hook/hook-command.js +211 -0
  48. package/dist/command/cli/hook/hook-fast.d.ts +31 -0
  49. package/dist/command/cli/hook/hook-fast.js +136 -0
  50. package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
  51. package/dist/command/cli/hook/prompt-hook.js +199 -0
  52. package/dist/command/cli/hook/tool-hook.d.ts +21 -0
  53. package/dist/command/cli/hook/tool-hook.js +259 -0
  54. package/dist/command/cli/launch/cli-launch.d.ts +2 -0
  55. package/dist/command/cli/launch/cli-launch.js +22 -2
  56. package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
  57. package/dist/command/cli/mcp-command.d.ts +9 -0
  58. package/dist/command/cli/mcp-command.js +127 -41
  59. package/dist/command/cli/open-navigate.d.ts +43 -0
  60. package/dist/command/cli/open-navigate.js +85 -0
  61. package/dist/command/cli/ports/port-holder.d.ts +16 -4
  62. package/dist/command/cli/ports/port-holder.js +58 -12
  63. package/dist/command/cli/ports/resolve/cli-port.js +18 -2
  64. package/dist/command/cli/project-name.d.ts +1 -7
  65. package/dist/command/cli/project-name.js +1 -0
  66. package/dist/command/cli/report-command.d.ts +8 -2
  67. package/dist/command/cli/report-command.js +95 -18
  68. package/dist/command/cli/status-fields.d.ts +9 -2
  69. package/dist/command/cli/status-fields.js +148 -4
  70. package/dist/command/cli/try-command.d.ts +3 -4
  71. package/dist/command/cli/try-command.js +6 -11
  72. package/dist/command/cli/verify-results.d.ts +4 -1
  73. package/dist/command/cli/verify-results.js +3 -1
  74. package/dist/command/cli.d.ts +1 -7
  75. package/dist/command/cli.js +79 -160
  76. package/dist/command/daemon/daemon-resilience.d.ts +6 -1
  77. package/dist/command/daemon/daemon-resilience.js +31 -18
  78. package/dist/command/daemon/daemon.d.ts +11 -0
  79. package/dist/command/daemon/daemon.js +70 -2
  80. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
  81. package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
  82. package/dist/command/daemon/wake-decision.js +4 -2
  83. package/dist/command/daemon/win32-escape.d.ts +32 -0
  84. package/dist/command/daemon/win32-escape.js +119 -0
  85. package/dist/command/setup/agent-configs.d.ts +9 -0
  86. package/dist/command/setup/agent-configs.js +9 -0
  87. package/dist/command/setup/auto-approve.d.ts +10 -3
  88. package/dist/command/setup/auto-approve.js +51 -3
  89. package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
  90. package/dist/command/setup/bringup/dev-server-wait.js +5 -1
  91. package/dist/command/setup/bringup/ensure-daemon.js +4 -7
  92. package/dist/command/setup/init/init-host.js +6 -0
  93. package/dist/command/setup/init/init-port.js +5 -4
  94. package/dist/command/setup/init/init-runtime.js +7 -1
  95. package/dist/command/setup/node-effects.d.ts +8 -0
  96. package/dist/command/setup/node-effects.js +36 -4
  97. package/dist/command/setup/probe/dev-port.d.ts +26 -0
  98. package/dist/command/setup/probe/dev-port.js +117 -0
  99. package/dist/command/setup/probe/page-probe.d.ts +1 -1
  100. package/dist/command/setup/probe/page-probe.js +11 -3
  101. package/dist/command/setup/remaining-steps.d.ts +0 -7
  102. package/dist/command/setup/remaining-steps.js +3 -2
  103. package/dist/command/setup/run-setup.d.ts +11 -0
  104. package/dist/command/setup/run-setup.js +33 -5
  105. package/dist/command/setup/setup-command.d.ts +2 -0
  106. package/dist/command/setup/setup-command.js +22 -4
  107. package/dist/command/update/updater.d.ts +1 -6
  108. package/dist/command/update/updater.js +4 -5
  109. package/dist/command/update/version-seen.d.ts +24 -0
  110. package/dist/command/update/version-seen.js +65 -0
  111. package/dist/command/version/peer-announce.d.ts +9 -1
  112. package/dist/command/version/peer-announce.js +25 -2
  113. package/dist/command/version/sdk-fix.d.ts +5 -6
  114. package/dist/command/version/sdk-fix.js +17 -32
  115. package/dist/command/version/version-skew.d.ts +16 -1
  116. package/dist/command/version/version-skew.js +84 -10
  117. package/dist/features/crawl/crawl-tools.js +2 -2
  118. package/dist/features/crawl/crawl.js +2 -0
  119. package/dist/features/exhaust/ledger.d.ts +15 -96
  120. package/dist/features/exhaust/ledger.js +3 -3
  121. package/dist/features/harness/drive-runs.d.ts +28 -4
  122. package/dist/features/harness/drive-runs.js +99 -7
  123. package/dist/features/harness/drivers.d.ts +1 -1
  124. package/dist/features/harness/drivers.js +1 -1
  125. package/dist/features/harness/harness.d.ts +5 -0
  126. package/dist/features/harness/harness.js +24 -12
  127. package/dist/features/harness/platform/platform-drives.d.ts +7 -1
  128. package/dist/features/harness/platform/platform-drives.js +12 -7
  129. package/dist/features/harness/platform/refusal.d.ts +1 -1
  130. package/dist/features/harness/platform/refusal.js +4 -4
  131. package/dist/features/harness/platform/remote-drive.js +70 -28
  132. package/dist/features/harness/platform/server-driver.js +22 -1
  133. package/dist/features/harness/platform-config.d.ts +1 -10
  134. package/dist/features/harness/platform-config.js +0 -20
  135. package/dist/features/license/license.d.ts +2 -14
  136. package/dist/features/visual/step-shots.d.ts +33 -1
  137. package/dist/features/visual/step-shots.js +155 -1
  138. package/dist/features/visual/visual-tools.js +12 -4
  139. package/dist/hooks/coding-agents.d.ts +6 -0
  140. package/dist/hooks/coding-agents.js +24 -3
  141. package/dist/hooks/episode-stamp.d.ts +32 -0
  142. package/dist/hooks/episode-stamp.js +61 -0
  143. package/dist/hooks/hook-commands.js +19 -9
  144. package/dist/index.d.ts +5 -1
  145. package/dist/index.js +66 -24
  146. package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
  147. package/dist/judgement/app-graph/journal-steps.js +92 -0
  148. package/dist/judgement/capsule/capsule-store.d.ts +2 -39
  149. package/dist/judgement/domain/domain-model.js +1 -10
  150. package/dist/judgement/domain/domain-tools.js +4 -2
  151. package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
  152. package/dist/judgement/runs/artifact/run-store.js +153 -28
  153. package/dist/judgement/runs/default-run-id.d.ts +3 -1
  154. package/dist/judgement/runs/default-run-id.js +15 -3
  155. package/dist/judgement/runs/drive-run.d.ts +3 -3
  156. package/dist/judgement/runs/drive-run.js +11 -7
  157. package/dist/judgement/runs/run-ledger.d.ts +21 -0
  158. package/dist/judgement/runs/run-ledger.js +143 -0
  159. package/dist/judgement/runs/runner-port.d.ts +1 -1
  160. package/dist/judgement/runs/runner-port.js +8 -2
  161. package/dist/judgement/runs/verification-sync.d.ts +4 -3
  162. package/dist/judgement/runs/verification-sync.js +27 -5
  163. package/dist/language/flows/affected-tools.js +2 -1
  164. package/dist/language/flows/annotate-notes/annotate.js +8 -3
  165. package/dist/language/flows/annotate-tools.js +1 -1
  166. package/dist/language/flows/change/affected.d.ts +8 -0
  167. package/dist/language/flows/change/affected.js +20 -7
  168. package/dist/language/flows/decision.js +19 -4
  169. package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
  170. package/dist/language/flows/fields/flow-secret-field.js +67 -5
  171. package/dist/language/flows/flow-anchor.d.ts +5 -0
  172. package/dist/language/flows/flow-anchor.js +4 -0
  173. package/dist/language/flows/flow-cross-step.d.ts +7 -1
  174. package/dist/language/flows/flow-cross-step.js +9 -0
  175. package/dist/language/flows/flow-expect-grammar.js +15 -10
  176. package/dist/language/flows/flow-intent.js +6 -1
  177. package/dist/language/flows/flow-journey.d.ts +8 -0
  178. package/dist/language/flows/flow-journey.js +13 -0
  179. package/dist/language/flows/flow-lease.d.ts +27 -0
  180. package/dist/language/flows/flow-lease.js +59 -0
  181. package/dist/language/flows/flow-replay-run.d.ts +1 -87
  182. package/dist/language/flows/flow-replay-run.js +111 -310
  183. package/dist/language/flows/flow-replay.js +21 -19
  184. package/dist/language/flows/flow-replayable.d.ts +38 -0
  185. package/dist/language/flows/flow-replayable.js +179 -0
  186. package/dist/language/flows/flow-start-path.d.ts +108 -0
  187. package/dist/language/flows/flow-start-path.js +313 -0
  188. package/dist/language/flows/flow-step-runners.d.ts +23 -2
  189. package/dist/language/flows/flow-step-runners.js +191 -32
  190. package/dist/language/flows/flow-store-for-session.d.ts +8 -1
  191. package/dist/language/flows/flow-store-for-session.js +6 -0
  192. package/dist/language/flows/flow-tools.d.ts +2 -23
  193. package/dist/language/flows/flow-tools.js +63 -113
  194. package/dist/language/flows/flows.d.ts +4 -6
  195. package/dist/language/flows/flows.js +90 -15
  196. package/dist/language/flows/heal-run.d.ts +10 -4
  197. package/dist/language/flows/heal-run.js +26 -9
  198. package/dist/language/flows/recording/flake.d.ts +3 -27
  199. package/dist/language/flows/recording/flake.js +1 -1
  200. package/dist/language/flows/recording/recording-backtrack.js +1 -4
  201. package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
  202. package/dist/language/flows/recording/tape/recordings.js +9 -3
  203. package/dist/language/flows/replay.d.ts +25 -5
  204. package/dist/language/flows/replay.js +83 -16
  205. package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
  206. package/dist/language/flows/suite/coverage.d.ts +9 -0
  207. package/dist/language/flows/suite/coverage.js +12 -1
  208. package/dist/language/flows/suite-selection.d.ts +25 -0
  209. package/dist/language/flows/suite-selection.js +41 -9
  210. package/dist/machine/git-tracks.d.ts +6 -0
  211. package/dist/machine/git-tracks.js +36 -0
  212. package/dist/memory/cloud/background-sync.d.ts +25 -0
  213. package/dist/memory/cloud/background-sync.js +79 -0
  214. package/dist/memory/cloud/cloud-config.d.ts +12 -1
  215. package/dist/memory/cloud/cloud-config.js +39 -13
  216. package/dist/memory/cloud/cloud-sync.d.ts +3 -24
  217. package/dist/memory/cloud/cloud-sync.js +5 -2
  218. package/dist/memory/cloud/harness-config.d.ts +0 -7
  219. package/dist/memory/cloud/memory-scope.d.ts +19 -0
  220. package/dist/memory/cloud/memory-scope.js +48 -0
  221. package/dist/memory/cloud/sync-answer.d.ts +43 -0
  222. package/dist/memory/cloud/sync-answer.js +42 -0
  223. package/dist/memory/cloud/sync-cycle.d.ts +40 -10
  224. package/dist/memory/cloud/sync-cycle.js +97 -144
  225. package/dist/memory/cloud/sync-daemon.d.ts +50 -3
  226. package/dist/memory/cloud/sync-daemon.js +473 -83
  227. package/dist/memory/cloud/sync-describe.d.ts +28 -0
  228. package/dist/memory/cloud/sync-describe.js +92 -0
  229. package/dist/memory/cloud/sync-disk.d.ts +9 -1
  230. package/dist/memory/cloud/sync-disk.js +137 -33
  231. package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
  232. package/dist/memory/cloud/sync-flow-versions.js +42 -0
  233. package/dist/memory/impact/impact-store.js +32 -15
  234. package/dist/memory/intent/intent-shard.d.ts +41 -266
  235. package/dist/memory/intent/intent-tools.js +20 -61
  236. package/dist/memory/intent/record-request.d.ts +27 -0
  237. package/dist/memory/intent/record-request.js +88 -0
  238. package/dist/memory/intent/settled-words.js +9 -1
  239. package/dist/memory/journal/drive-flow.d.ts +3 -0
  240. package/dist/memory/journal/drive-flow.js +11 -41
  241. package/dist/memory/journal/envelope-store.js +1 -1
  242. package/dist/memory/journal/envelope.d.ts +6 -154
  243. package/dist/memory/journal/episode-log.d.ts +107 -0
  244. package/dist/memory/journal/episode-log.js +302 -0
  245. package/dist/memory/journal/journal-recorder.d.ts +7 -0
  246. package/dist/memory/journal/journal-recorder.js +22 -9
  247. package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
  248. package/dist/memory/journal/on-disk/ambient-file.js +1 -1
  249. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
  250. package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
  251. package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
  252. package/dist/memory/journal/self-observation.js +3 -1
  253. package/dist/memory/journal/session-end.js +23 -9
  254. package/dist/memory/journal/session-journal.js +39 -20
  255. package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
  256. package/dist/memory/project/artifact-root-resolver.js +68 -23
  257. package/dist/memory/project/artifact-root.d.ts +17 -3
  258. package/dist/memory/project/artifact-root.js +47 -9
  259. package/dist/memory/project/fs/fs-port.d.ts +5 -0
  260. package/dist/memory/project/fs/fs-port.js +13 -0
  261. package/dist/memory/project/learned-routes.d.ts +3 -4
  262. package/dist/memory/project/learned-routes.js +3 -11
  263. package/dist/memory/project/link-directory.js +5 -2
  264. package/dist/memory/project/root-claims.d.ts +3 -1
  265. package/dist/memory/project/root-claims.js +41 -7
  266. package/dist/memory/project/session-root.d.ts +1 -1
  267. package/dist/memory/project/session-root.js +1 -15
  268. package/dist/memory/project/sync-status.js +5 -6
  269. package/dist/memory/recall/memory-tools.js +2 -2
  270. package/dist/memory/recall/platform-memory.d.ts +3 -1
  271. package/dist/memory/recall/platform-memory.js +9 -1
  272. package/dist/memory/recall/project-memory.js +15 -19
  273. package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
  274. package/dist/portal/bridge/auth-failure-reason.js +19 -0
  275. package/dist/portal/bridge/bridge.d.ts +19 -4
  276. package/dist/portal/bridge/bridge.js +150 -177
  277. package/dist/portal/bridge/harness-request.d.ts +15 -0
  278. package/dist/portal/bridge/harness-request.js +19 -0
  279. package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
  280. package/dist/portal/bridge/origin/origin-follow.js +110 -0
  281. package/dist/portal/bridge/pairing-token.d.ts +6 -0
  282. package/dist/portal/bridge/pairing-token.js +47 -16
  283. package/dist/portal/bridge/protocol-skew.d.ts +27 -2
  284. package/dist/portal/bridge/protocol-skew.js +66 -2
  285. package/dist/portal/bridge/session-nonces.d.ts +46 -0
  286. package/dist/portal/bridge/session-nonces.js +72 -0
  287. package/dist/portal/input/viewport-tools.d.ts +31 -0
  288. package/dist/portal/input/viewport-tools.js +106 -15
  289. package/dist/portal/pool/bounded-close.d.ts +23 -0
  290. package/dist/portal/pool/bounded-close.js +38 -0
  291. package/dist/portal/pool/browser-pool.d.ts +44 -39
  292. package/dist/portal/pool/browser-pool.js +247 -95
  293. package/dist/portal/pool/context-permissions.d.ts +9 -1
  294. package/dist/portal/pool/context-permissions.js +26 -0
  295. package/dist/portal/pool/lease-emulation.d.ts +37 -0
  296. package/dist/portal/pool/lease-emulation.js +29 -0
  297. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  298. package/dist/portal/pool/playwright-launcher.js +74 -7
  299. package/dist/portal/pool/pool-contract.d.ts +23 -1
  300. package/dist/portal/pool/pool-lease.d.ts +128 -0
  301. package/dist/portal/pool/pool-lease.js +49 -0
  302. package/dist/portal/pool/zero-install.d.ts +8 -1
  303. package/dist/portal/pool/zero-install.js +24 -2
  304. package/dist/portal/production/production-activation.d.ts +136 -0
  305. package/dist/portal/production/production-activation.js +173 -0
  306. package/dist/portal/production/production-drive.d.ts +52 -0
  307. package/dist/portal/production/production-drive.js +301 -0
  308. package/dist/portal/production/production-hello.d.ts +23 -0
  309. package/dist/portal/production/production-hello.js +23 -0
  310. package/dist/portal/realm/web-realm.js +42 -15
  311. package/dist/portal/session/control-envelope.d.ts +1 -1
  312. package/dist/portal/session/dev-server/served-document.d.ts +0 -5
  313. package/dist/portal/session/dev-server/served-document.js +6 -8
  314. package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
  315. package/dist/portal/session/first-run-wiring.d.ts +3 -36
  316. package/dist/portal/session/first-run-wiring.js +10 -103
  317. package/dist/portal/session/live-control-tools.js +61 -19
  318. package/dist/portal/session/no-session-next-action.d.ts +11 -0
  319. package/dist/portal/session/no-session-next-action.js +40 -15
  320. package/dist/portal/session/no-session-watch.d.ts +7 -0
  321. package/dist/portal/session/no-session-watch.js +67 -23
  322. package/dist/portal/session/output-budget.d.ts +10 -0
  323. package/dist/portal/session/output-budget.js +16 -0
  324. package/dist/portal/session/presence/session-lease.d.ts +2 -0
  325. package/dist/portal/session/presence/session-lease.js +8 -0
  326. package/dist/portal/session/recorded-gaps.d.ts +15 -11
  327. package/dist/portal/session/recorded-gaps.js +39 -18
  328. package/dist/portal/session/serving-directory.d.ts +24 -2
  329. package/dist/portal/session/serving-directory.js +93 -5
  330. package/dist/portal/session/session-info.d.ts +26 -0
  331. package/dist/portal/session/session-info.js +20 -0
  332. package/dist/portal/session/session-manager.d.ts +35 -3
  333. package/dist/portal/session/session-manager.js +69 -14
  334. package/dist/portal/session/session-successor.js +1 -9
  335. package/dist/portal/session/session-tools.js +22 -4
  336. package/dist/portal/session/session.d.ts +10 -10
  337. package/dist/portal/session/session.js +37 -29
  338. package/dist/portal/session/zero-install-first-call.d.ts +7 -2
  339. package/dist/portal/session/zero-install-first-call.js +43 -20
  340. package/dist/start-wiring.d.ts +2 -2
  341. package/dist/start-wiring.js +17 -3
  342. package/dist/status-payload.d.ts +11 -1
  343. package/dist/status-payload.js +7 -1
  344. package/dist/surface/agent-presence-grace.d.ts +11 -0
  345. package/dist/surface/agent-presence-grace.js +34 -0
  346. package/dist/surface/http-server.d.ts +12 -1
  347. package/dist/surface/http-server.js +64 -15
  348. package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
  349. package/dist/surface/mcp/faults/mcp-outage.js +19 -1
  350. package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
  351. package/dist/surface/mcp/mcp-proxy.js +194 -267
  352. package/dist/surface/mcp/mcp.d.ts +20 -3
  353. package/dist/surface/mcp/mcp.js +88 -25
  354. package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
  355. package/dist/surface/mcp/proxy/drive-calls.js +114 -5
  356. package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
  357. package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
  358. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
  359. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
  360. package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
  361. package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
  362. package/dist/surface/mcp/server-instructions.js +35 -16
  363. package/dist/surface/mcp/shared-params.d.ts +8 -0
  364. package/dist/surface/mcp/shared-params.js +15 -1
  365. package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
  366. package/dist/surface/mcp/sse-frame-parser.js +18 -0
  367. package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
  368. package/dist/surface/mcp/surface-vocabulary.js +13 -0
  369. package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
  370. package/dist/surface/mcp/tool-catalog-cache.js +14 -4
  371. package/dist/surface/tools/account-tool.d.ts +4 -3
  372. package/dist/surface/tools/account-tool.js +20 -31
  373. package/dist/surface/tools/act/act-danger.d.ts +2 -0
  374. package/dist/surface/tools/act/act-danger.js +41 -14
  375. package/dist/surface/tools/act/act-observation.d.ts +11 -0
  376. package/dist/surface/tools/act/act-observation.js +33 -0
  377. package/dist/surface/tools/act/act-preflight.js +10 -3
  378. package/dist/surface/tools/act/act-sequence-retry.js +2 -1
  379. package/dist/surface/tools/act/act-target.js +19 -5
  380. package/dist/surface/tools/act/durable.js +1 -1
  381. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
  382. package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
  383. package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
  384. package/dist/surface/tools/act/unsettled-find.js +71 -0
  385. package/dist/surface/tools/act-sequence-tool.js +53 -24
  386. package/dist/surface/tools/act-tools.d.ts +2 -3
  387. package/dist/surface/tools/act-tools.js +49 -47
  388. package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
  389. package/dist/surface/tools/agent/for-the-agent.js +41 -3
  390. package/dist/surface/tools/assert/assert-grade.js +8 -3
  391. package/dist/surface/tools/assert/assert-verdict.js +4 -2
  392. package/dist/surface/tools/browser-tools.js +7 -4
  393. package/dist/surface/tools/chat-drives.js +50 -25
  394. package/dist/surface/tools/coverage-tools.js +1 -1
  395. package/dist/surface/tools/dynamic-tools.d.ts +8 -0
  396. package/dist/surface/tools/dynamic-tools.js +89 -34
  397. package/dist/surface/tools/empty-session-list.d.ts +18 -25
  398. package/dist/surface/tools/empty-session-list.js +67 -38
  399. package/dist/surface/tools/error-recovery.d.ts +17 -7
  400. package/dist/surface/tools/error-recovery.js +53 -20
  401. package/dist/surface/tools/explore-tools.d.ts +10 -0
  402. package/dist/surface/tools/explore-tools.js +72 -19
  403. package/dist/surface/tools/feedback-tools.js +23 -2
  404. package/dist/surface/tools/gap-novelty.d.ts +6 -0
  405. package/dist/surface/tools/gap-novelty.js +9 -0
  406. package/dist/surface/tools/gaps/capability-absences.js +4 -3
  407. package/dist/surface/tools/harness-explore.d.ts +1 -1
  408. package/dist/surface/tools/harness-explore.js +6 -4
  409. package/dist/surface/tools/harness-gate.d.ts +43 -21
  410. package/dist/surface/tools/harness-gate.js +55 -81
  411. package/dist/surface/tools/harness-script.d.ts +2 -0
  412. package/dist/surface/tools/harness-script.js +11 -6
  413. package/dist/surface/tools/harness-toolset.js +3 -4
  414. package/dist/surface/tools/invoke-tool.d.ts +0 -8
  415. package/dist/surface/tools/invoke-tool.js +164 -178
  416. package/dist/surface/tools/lease-hint.d.ts +9 -0
  417. package/dist/surface/tools/lease-hint.js +22 -3
  418. package/dist/surface/tools/lease-permissions.d.ts +1 -1
  419. package/dist/surface/tools/lease-readiness.d.ts +55 -0
  420. package/dist/surface/tools/lease-readiness.js +150 -2
  421. package/dist/surface/tools/lease-tools.d.ts +3 -75
  422. package/dist/surface/tools/lease-tools.js +124 -188
  423. package/dist/surface/tools/map-tools.d.ts +20 -0
  424. package/dist/surface/tools/map-tools.js +145 -0
  425. package/dist/surface/tools/merge-tools.js +11 -7
  426. package/dist/surface/tools/next-step.js +6 -3
  427. package/dist/surface/tools/observe-tools.js +46 -35
  428. package/dist/surface/tools/platform-moment.d.ts +3 -12
  429. package/dist/surface/tools/platform-moment.js +12 -24
  430. package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
  431. package/dist/surface/tools/read/complete-snapshot.js +13 -2
  432. package/dist/surface/tools/read/query-paginate.js +6 -0
  433. package/dist/surface/tools/read/query-shape.d.ts +9 -0
  434. package/dist/surface/tools/read/query-shape.js +15 -0
  435. package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
  436. package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
  437. package/dist/surface/tools/read-tools.js +5 -5
  438. package/dist/surface/tools/real-input-attempt.d.ts +11 -0
  439. package/dist/surface/tools/real-input-attempt.js +206 -38
  440. package/dist/surface/tools/reconcile-tools.js +21 -8
  441. package/dist/surface/tools/reticle-result.d.ts +3 -0
  442. package/dist/surface/tools/reticle-result.js +8 -1
  443. package/dist/surface/tools/run-report.d.ts +22 -0
  444. package/dist/surface/tools/run-report.js +141 -0
  445. package/dist/surface/tools/session-ports.d.ts +57 -0
  446. package/dist/surface/tools/session-ports.js +102 -0
  447. package/dist/surface/tools/tool-kit.d.ts +58 -4
  448. package/dist/surface/tools/tool-kit.js +140 -6
  449. package/dist/surface/tools/tool-surface.d.ts +2 -0
  450. package/dist/surface/tools/tool-surface.js +45 -0
  451. package/dist/surface/tools/tools.js +49 -87
  452. package/dist/telemetry/automation-hint.d.ts +5 -0
  453. package/dist/telemetry/automation-hint.js +7 -0
  454. package/dist/telemetry/cli-telemetry.d.ts +22 -0
  455. package/dist/telemetry/cli-telemetry.js +80 -11
  456. package/dist/telemetry/daemon-telemetry.d.ts +3 -1
  457. package/dist/telemetry/daemon-telemetry.js +9 -2
  458. package/dist/telemetry/feedback-cli.d.ts +1 -1
  459. package/dist/telemetry/feedback-cli.js +8 -3
  460. package/dist/telemetry/feedback.d.ts +1 -1
  461. package/dist/telemetry/feedback.js +51 -4
  462. package/dist/telemetry/harness-run.d.ts +3 -3
  463. package/dist/telemetry/harness-run.js +18 -7
  464. package/dist/telemetry/hud-events.d.ts +1 -1
  465. package/dist/telemetry/hud-metrics.d.ts +6 -3
  466. package/dist/telemetry/hud-metrics.js +20 -8
  467. package/dist/telemetry/install-source.js +1 -1
  468. package/dist/telemetry/mcp-connection.d.ts +1 -1
  469. package/dist/telemetry/mcp-connection.js +21 -2
  470. package/dist/telemetry/onboarding-firsts.d.ts +6 -1
  471. package/dist/telemetry/onboarding-firsts.js +41 -1
  472. package/dist/telemetry/proxy-telemetry.d.ts +42 -0
  473. package/dist/telemetry/proxy-telemetry.js +70 -1
  474. package/dist/telemetry/session-metrics.d.ts +1 -3
  475. package/dist/telemetry/session-metrics.js +16 -12
  476. package/dist/telemetry/telemetry.d.ts +9 -1
  477. package/dist/telemetry/telemetry.js +16 -1
  478. package/dist/telemetry/verification-of.d.ts +3 -1
  479. package/dist/telemetry/verification-of.js +7 -1
  480. package/dist/wire-journal.js +12 -2
  481. package/docs/README.md +4 -2
  482. package/docs/actions.mdx +7 -6
  483. package/docs/adapters.md +2 -1
  484. package/docs/agent-cheatsheet.md +19 -5
  485. package/docs/architecture.md +13 -10
  486. package/docs/autodrive.md +6 -5
  487. package/docs/benchmarks.md +2 -2
  488. package/docs/capabilities.mdx +1 -1
  489. package/docs/cli/affected.mdx +1 -1
  490. package/docs/cli/cloud.mdx +6 -6
  491. package/docs/cli/doctor.mdx +3 -1
  492. package/docs/cli/feedback.mdx +11 -7
  493. package/docs/cli/gate.mdx +1 -1
  494. package/docs/cli/help.mdx +1 -1
  495. package/docs/cli/init.mdx +20 -16
  496. package/docs/cli/mcp.mdx +5 -2
  497. package/docs/cli/open.mdx +5 -2
  498. package/docs/cli/report.mdx +1 -1
  499. package/docs/cli/restart.mdx +1 -1
  500. package/docs/cli/rollback.mdx +4 -4
  501. package/docs/cli/serve.mdx +7 -5
  502. package/docs/cli/setup.mdx +1 -1
  503. package/docs/cli/status.mdx +6 -2
  504. package/docs/cli/stop.mdx +3 -3
  505. package/docs/cli/telemetry.mdx +5 -1
  506. package/docs/cli/try.mdx +8 -8
  507. package/docs/cli/update.mdx +8 -5
  508. package/docs/cli/verify.mdx +12 -5
  509. package/docs/cli/version.mdx +1 -1
  510. package/docs/cli.mdx +10 -6
  511. package/docs/debugging.md +1 -1
  512. package/docs/deploy-checks.md +8 -6
  513. package/docs/desktop.mdx +14 -18
  514. package/docs/enterprise.md +6 -6
  515. package/docs/environment.mdx +5 -3
  516. package/docs/faq.mdx +9 -6
  517. package/docs/first-drive.md +19 -9
  518. package/docs/flows.md +3 -4
  519. package/docs/for-agents.md +1 -1
  520. package/docs/frameworks.mdx +34 -11
  521. package/docs/getting-started.md +46 -29
  522. package/docs/http-transport.md +2 -2
  523. package/docs/human-control.md +8 -8
  524. package/docs/index.mdx +2 -2
  525. package/docs/install-agentic.mdx +18 -19
  526. package/docs/install-manual.mdx +8 -4
  527. package/docs/integration-patterns.md +5 -5
  528. package/docs/multi-agent-testing.md +7 -5
  529. package/docs/packages/browser.mdx +34 -2
  530. package/docs/packages/core.mdx +2 -1
  531. package/docs/packages/electron.mdx +15 -3
  532. package/docs/packages/eslint-plugin.mdx +1 -1
  533. package/docs/packages/next.mdx +17 -5
  534. package/docs/packages/react.mdx +8 -1
  535. package/docs/packages/server.mdx +3 -3
  536. package/docs/packages/tauri.mdx +3 -3
  537. package/docs/packages/vite-plugin.mdx +1 -1
  538. package/docs/packages.mdx +19 -6
  539. package/docs/platform-integration.md +12 -4
  540. package/docs/predicates.mdx +18 -7
  541. package/docs/production-mode.md +108 -0
  542. package/docs/prompt-capture.md +99 -0
  543. package/docs/quickstart.mdx +14 -12
  544. package/docs/recipes.mdx +9 -8
  545. package/docs/required-checks.md +3 -2
  546. package/docs/skill-file.mdx +4 -3
  547. package/docs/skill-setup.md +2 -2
  548. package/docs/skill.md +62 -70
  549. package/docs/state-files.md +1 -0
  550. package/docs/state-management.mdx +11 -9
  551. package/docs/system-map.md +14 -13
  552. package/docs/telemetry.md +32 -24
  553. package/docs/testing.md +9 -5
  554. package/docs/tools/act-and-wait.mdx +17 -13
  555. package/docs/tools/act-sequence.mdx +40 -66
  556. package/docs/tools/act.mdx +7 -5
  557. package/docs/tools/assert.mdx +1 -1
  558. package/docs/tools/look.mdx +1 -1
  559. package/docs/tools/navigate.mdx +1 -1
  560. package/docs/tools/network.mdx +13 -11
  561. package/docs/tools/overview.mdx +3 -3
  562. package/docs/tools/query.mdx +3 -3
  563. package/docs/tools/session-and-feedback.mdx +9 -6
  564. package/docs/tools/sessions.mdx +7 -0
  565. package/docs/tools/snapshot.mdx +9 -7
  566. package/docs/tools/tools-and-run.mdx +11 -10
  567. package/docs/tools/verify.mdx +1 -1
  568. package/docs/troubleshooting.mdx +21 -9
  569. package/docs/usage.md +58 -43
  570. package/docs/use-cases.mdx +2 -2
  571. package/docs/vs-chrome-devtools-mcp.mdx +5 -5
  572. package/docs/vs-playwright-mcp.mdx +5 -4
  573. package/docs/what-is-recorded.md +12 -7
  574. package/docs/what-is-reticle.mdx +2 -2
  575. package/docs/why-reticle.mdx +1 -1
  576. package/package.json +9 -12
  577. package/dist/command/dev/stale-issue-guard.d.ts +0 -34
  578. package/dist/command/dev/stale-issue-guard.js +0 -69
@@ -1,4 +1,11 @@
1
1
  import { type JournalAction, type JournalWriteLoss, type ReticleEvent } from '@reticlehq/core';
2
+ /**
3
+ * The arguments as the journal keeps them: every typed value replaced, at any depth (a sequence's
4
+ * steps too). A fill's arguments kept a typed password in clear in `actions.jsonl`; the page cannot
5
+ * tell the daemon which field was secret before the call is written, and nothing reads a typed value
6
+ * back from the journal — the run fold reads the ref, the target and the action — so none is kept.
7
+ */
8
+ export declare function withoutTypedInput(args: unknown): unknown;
2
9
  /** Where a recorder persists. `SessionJournal` satisfies this structurally. */
3
10
  export interface JournalSink {
4
11
  appendEvents(events: readonly ReticleEvent[]): Promise<void>;
@@ -3,6 +3,7 @@ import { isSelfObservation } from './self-observation.js';
3
3
  import { currentDrivenBy } from '../../hooks/driven-by.js';
4
4
  import { callerClientName } from '../../hooks/coding-agents.js';
5
5
  import { log } from '../../log.js';
6
+ import { runLedger } from '../../judgement/runs/run-ledger.js';
6
7
  /**
7
8
  * Logged the FIRST time a journal write is lost, and never again for that recorder.
8
9
  *
@@ -23,11 +24,13 @@ const TYPED_KEYS = ['value', 'text'];
23
24
  * tell the daemon which field was secret before the call is written, and nothing reads a typed value
24
25
  * back from the journal — the run fold reads the ref, the target and the action — so none is kept.
25
26
  */
26
- function withoutTypedInput(args) {
27
- if (Array.isArray(args))
27
+ export function withoutTypedInput(args) {
28
+ if (Array.isArray(args)) {
28
29
  return args.map(withoutTypedInput);
29
- if ('object' !== typeof args || null === args)
30
+ }
31
+ if ('object' !== typeof args || null === args) {
30
32
  return args;
33
+ }
31
34
  const record = args;
32
35
  const typing = TYPING_ACTIONS.has(String(record['action']));
33
36
  const out = {};
@@ -37,9 +40,11 @@ function withoutTypedInput(args) {
37
40
  }
38
41
  if (typing && 'object' === typeof record['args'] && null !== record['args']) {
39
42
  const inner = { ...record['args'] };
40
- for (const key of TYPED_KEYS)
41
- if ('string' === typeof inner[key])
43
+ for (const key of TYPED_KEYS) {
44
+ if ('string' === typeof inner[key]) {
42
45
  inner[key] = REDACTED_VALUE;
46
+ }
47
+ }
43
48
  out['args'] = inner;
44
49
  }
45
50
  return out;
@@ -90,8 +95,9 @@ export class JournalRecorder {
90
95
  // session keeps seeing this event. What is declined is the DURABLE copy: see isSelfObservation.
91
96
  if (!isSelfObservation(out)) {
92
97
  this.#pending.push(out);
93
- if (this.#pending.length >= this.#flushAt)
98
+ if (this.#pending.length >= this.#flushAt) {
94
99
  this.#enqueueFlush();
100
+ }
95
101
  }
96
102
  return out;
97
103
  }
@@ -109,8 +115,9 @@ export class JournalRecorder {
109
115
  /** Close the active window: persist its buffered events, then the action record. No-op if none active. */
110
116
  finishAction(effect, settled, settledInMs) {
111
117
  const active = this.#active;
112
- if (active === undefined)
118
+ if (active === undefined) {
113
119
  return;
120
+ }
114
121
  this.#active = undefined;
115
122
  const action = {
116
123
  v: JOURNAL_FILE_VERSION,
@@ -128,6 +135,8 @@ export class JournalRecorder {
128
135
  ...(active.drivenBy === undefined ? {} : { drivenBy: active.drivenBy }),
129
136
  ...(active.agent === undefined ? {} : { agent: active.agent }),
130
137
  };
138
+ // The agent's own verdicts make its run's report; the ledger ignores the Harness's.
139
+ runLedger.verdict(action);
131
140
  this.#enqueueFlush();
132
141
  this.#chain = this.#chain
133
142
  .then(() => this.#sink.appendAction(action))
@@ -173,6 +182,8 @@ export class JournalRecorder {
173
182
  return agent === undefined ? {} : { agent };
174
183
  })(),
175
184
  };
185
+ // The agent's own verdicts make its run's report; the ledger ignores the Harness's.
186
+ runLedger.verdict(action);
176
187
  this.#enqueueFlush();
177
188
  this.#chain = this.#chain
178
189
  .then(() => this.#sink.appendAction(action))
@@ -184,8 +195,9 @@ export class JournalRecorder {
184
195
  await this.#chain;
185
196
  }
186
197
  #enqueueFlush() {
187
- if (0 === this.#pending.length)
198
+ if (0 === this.#pending.length) {
188
199
  return;
200
+ }
189
201
  const batch = this.#pending;
190
202
  this.#pending = [];
191
203
  this.#chain = this.#chain
@@ -194,8 +206,9 @@ export class JournalRecorder {
194
206
  }
195
207
  /** Swallow a lost write, but say so once. See JOURNAL_WRITE_LOST. */
196
208
  #reportLoss(error) {
197
- if (this.#lossReported)
209
+ if (this.#lossReported) {
198
210
  return;
211
+ }
199
212
  this.#lossReported = true;
200
213
  log(JOURNAL_WRITE_LOST, { error: error instanceof Error ? error.message : String(error) });
201
214
  }
@@ -12,10 +12,4 @@ import { z } from 'zod';
12
12
  export declare const AmbientFileSchema: z.ZodObject<{
13
13
  version: z.ZodLiteral<1>;
14
14
  regions: z.ZodRecord<z.ZodString, z.ZodNumber>;
15
- }, "strip", z.ZodTypeAny, {
16
- version: 1;
17
- regions: Record<string, number>;
18
- }, {
19
- version: 1;
20
- regions: Record<string, number>;
21
- }>;
15
+ }, z.core.$strip>;
@@ -11,5 +11,5 @@ import { z } from 'zod';
11
11
  */
12
12
  export const AmbientFileSchema = z.object({
13
13
  version: z.literal(1),
14
- regions: z.record(z.number()),
14
+ regions: z.record(z.string(), z.number()),
15
15
  });
@@ -1,10 +1,31 @@
1
1
  import type { FileSystemPort } from '../../project/fs/fs-port.js';
2
2
  /**
3
- * Write `.reticle/.gitignore` if it is not already there.
3
+ * The `.reticle/` entries that are LOCAL state, and must never be committed by accident.
4
4
  *
5
- * Never overwrites — once the file exists it belongs to whoever edited it last, and silently
5
+ * Read from the tier table rather than restated here: which half a name belongs to is one decision,
6
+ * and a second copy of it is the list that silently disagrees. This file asks the table exactly one
7
+ * of its two questions — `sharing` — and has no opinion at all about what retention may delete.
8
+ *
9
+ * The reason this matters beyond tidiness: a session journal carries URLs, request and response
10
+ * bodies, and DOM text from the app under test. `.reticle/` is created by the daemon rather than by
11
+ * the user, so it arrives untracked and unexplained, and one `git add -A` puts an app's traffic into
12
+ * a shared repository. Reticle created the directory; the ignore for it is Reticle's to write.
13
+ */
14
+ /** The ignore file inside `.reticle/`. */
15
+ export declare const WORKSPACE_GITIGNORE = ".gitignore";
16
+ /**
17
+ * The ignore file `.reticle/` should hold, given the one it holds now (`undefined`: none). Returns
18
+ * `undefined` when nothing needs to change. A new file gets every local entry. An existing file
19
+ * keeps every line it has, and gets only the prompt files it lacks, appended at the end.
20
+ */
21
+ export declare function workspaceGitignore(existing: string | undefined): string | undefined;
22
+ /**
23
+ * Write `.reticle/.gitignore`, or add the prompt files to the one that is there.
24
+ *
25
+ * Never overwrites. Once the file exists it belongs to whoever edited it last, and silently
6
26
  * reverting somebody's change to a file we placed in their repository is worse than not having
7
- * written it. Best-effort throughout: this runs on the daemon's start path, and a workspace that
27
+ * written it. The one exception is additive: the prompt files are appended when missing, because
28
+ * a file written before prompt capture existed would otherwise let them be committed. Best-effort throughout: this runs on the daemon's start path, and a workspace that
8
29
  * cannot be written must not stop a daemon coming up. Nothing about verification depends on it.
9
30
  */
10
31
  export declare function ensureWorkspaceGitignore(fs: FileSystemPort, root: string): Promise<void>;
@@ -13,6 +13,8 @@ import { LOCAL_DIRS, LOCAL_FILES } from './workspace-tiers.js';
13
13
  * the user, so it arrives untracked and unexplained, and one `git add -A` puts an app's traffic into
14
14
  * a shared repository. Reticle created the directory; the ignore for it is Reticle's to write.
15
15
  */
16
+ /** The ignore file inside `.reticle/`. */
17
+ export const WORKSPACE_GITIGNORE = '.gitignore';
16
18
  const TRANSIENT = [
17
19
  ...LOCAL_DIRS.map((dir) => `${dir}/`),
18
20
  ...LOCAL_FILES,
@@ -30,23 +32,52 @@ const HEADER = [
30
32
  `# ${ReticleDir.CAPSULES_SUBDIR}/. Those are meant to be committed — a saved flow only earns its keep`,
31
33
  '# when a teammate or CI can replay it.',
32
34
  '#',
33
- '# Edit freely: Reticle writes this once and never rewrites it.',
35
+ '# Edit freely. Reticle only adds the prompt files below when they are missing: they hold every',
36
+ '# prompt you typed, and a `git add -A` must never publish them.',
34
37
  ];
35
38
  /**
36
- * Write `.reticle/.gitignore` if it is not already there.
39
+ * The entries Reticle adds to an ignore file that already exists. They are the user's prompts, and
40
+ * a `.gitignore` written before prompt capture existed has none of them.
41
+ */
42
+ const PROMPT_FILES = [
43
+ ReticleDir.REQUEST_FILE,
44
+ ReticleDir.REQUESTS_LOG_FILE,
45
+ ReticleDir.REQUESTS_LOG_ROTATED_FILE,
46
+ ];
47
+ const MERGED_NOTE = '# Added by Reticle: the prompts you typed, kept on this machine.';
48
+ /**
49
+ * The ignore file `.reticle/` should hold, given the one it holds now (`undefined`: none). Returns
50
+ * `undefined` when nothing needs to change. A new file gets every local entry. An existing file
51
+ * keeps every line it has, and gets only the prompt files it lacks, appended at the end.
52
+ */
53
+ export function workspaceGitignore(existing) {
54
+ if (existing === undefined)
55
+ return `${[...HEADER, '', ...TRANSIENT].join('\n')}\n`;
56
+ const lines = new Set(existing.split(/\r?\n/).map((line) => line.trim()));
57
+ const missing = PROMPT_FILES.filter((name) => !lines.has(name) && !lines.has(`/${name}`));
58
+ if (0 === missing.length)
59
+ return undefined;
60
+ const base = existing.endsWith('\n') || '' === existing ? existing : `${existing}\n`;
61
+ return `${base}${[MERGED_NOTE, ...missing].join('\n')}\n`;
62
+ }
63
+ /**
64
+ * Write `.reticle/.gitignore`, or add the prompt files to the one that is there.
37
65
  *
38
- * Never overwrites — once the file exists it belongs to whoever edited it last, and silently
66
+ * Never overwrites. Once the file exists it belongs to whoever edited it last, and silently
39
67
  * reverting somebody's change to a file we placed in their repository is worse than not having
40
- * written it. Best-effort throughout: this runs on the daemon's start path, and a workspace that
68
+ * written it. The one exception is additive: the prompt files are appended when missing, because
69
+ * a file written before prompt capture existed would otherwise let them be committed. Best-effort throughout: this runs on the daemon's start path, and a workspace that
41
70
  * cannot be written must not stop a daemon coming up. Nothing about verification depends on it.
42
71
  */
43
72
  export async function ensureWorkspaceGitignore(fs, root) {
44
- const path = join(root, '.gitignore');
73
+ const path = join(root, WORKSPACE_GITIGNORE);
45
74
  try {
46
- if (await fs.exists(path))
75
+ const existing = (await fs.exists(path)) ? await fs.readFile(path) : undefined;
76
+ const next = workspaceGitignore(existing);
77
+ if (next === undefined)
47
78
  return;
48
79
  await fs.mkdir(root);
49
- await fs.writeFile(path, `${[...HEADER, '', ...TRANSIENT].join('\n')}\n`);
80
+ await fs.writeFile(path, next);
50
81
  }
51
82
  catch {
52
83
  /* a workspace we cannot write is not a reason to fail a session */
@@ -41,7 +41,11 @@ const sharedFile = { durability: Durability.MEMORY, sharing: Sharing.COMMIT, isD
41
41
  */
42
42
  export const WORKSPACE_TIERS = {
43
43
  [ReticleDir.SESSIONS_SUBDIR]: localDir,
44
+ // Every tool call and its whole result: app data, so local, and evidence, so swept by age.
45
+ [ReticleDir.EPISODES_SUBDIR]: localDir,
44
46
  [ReticleDir.RUNS_SUBDIR]: localDir,
47
+ // A dev server's output, written here only when the state home cannot be written.
48
+ [ReticleDir.LOGS_SUBDIR]: localDir,
45
49
  [ReticleDir.VISUAL_SUBDIR]: localDir,
46
50
  // Write-only: a local copy of what was already sent. The outbox is the record.
47
51
  [ReticleDir.FEEDBACK_SUBDIR]: localDir,
@@ -56,6 +60,9 @@ export const WORKSPACE_TIERS = {
56
60
  [ReticleDir.TIERS_FILE]: localFile,
57
61
  // The user's request in their own words: it leaves only with `shareRequests`, never by git push.
58
62
  [ReticleDir.REQUEST_FILE]: localFile,
63
+ // Every prompt the agent hook captured: the same words, so the same rule.
64
+ [ReticleDir.REQUESTS_LOG_FILE]: localFile,
65
+ [ReticleDir.REQUESTS_LOG_ROTATED_FILE]: localFile,
59
66
  // How to target this app, learned from corrected failures: a teammate's agent needs it too.
60
67
  [ReticleDir.APP_NOTES_FILE]: sharedFile,
61
68
  [ReticleDir.PLATFORM_MOMENTS_FILE]: localFile,
@@ -46,6 +46,7 @@ const NET_TYPES = new Set([
46
46
  EventType.NET_REQUEST,
47
47
  EventType.NET_PENDING,
48
48
  EventType.NET_DETAIL,
49
+ EventType.NET_RESPONSE_BODY,
49
50
  EventType.NET_STREAM,
50
51
  ]);
51
52
  /** A base for parsing relative URLs. Never dereferenced — only the path is read. */
@@ -60,8 +61,9 @@ function pathOf(url) {
60
61
  }
61
62
  /** True when this event is the page fetching Reticle's own code rather than doing anything. */
62
63
  export function isSelfObservation(event) {
63
- if (!NET_TYPES.has(event.type))
64
+ if (!NET_TYPES.has(event.type)) {
64
65
  return false;
66
+ }
65
67
  const path = pathOf(urlForMatch(event.data));
66
68
  return path.includes(SCOPE_PATH) || path.includes(SCOPE_FLATTENED);
67
69
  }
@@ -22,6 +22,8 @@ import { RunStore } from '../../judgement/runs/artifact/run-store.js';
22
22
  * starts already knowing which regions churn.
23
23
  */
24
24
  export function makeSessionEnd(deps) {
25
+ // The `flow_recorded` outcomes this daemon already reported. See saveDrivenFlow.
26
+ const flowStepsSent = new Set();
25
27
  return async (session) => {
26
28
  /*
27
29
  * Retention is maintenance of a directory, not a part of journalling, so it runs either way.
@@ -94,7 +96,7 @@ export function makeSessionEnd(deps) {
94
96
  // Saved only when the tape declared a consequence — see drive-flow.ts for why the alternative is
95
97
  // a false-green factory running once per session.
96
98
  try {
97
- await saveDrivenFlow(deps, session);
99
+ await saveDrivenFlow(deps, session, flowStepsSent);
98
100
  }
99
101
  catch (error) {
100
102
  // A flow is a by-product of the session; failing to write one never fails the teardown. It is
@@ -171,8 +173,9 @@ export function makeSessionEnd(deps) {
171
173
  export async function recordDriveRun(deps, session) {
172
174
  // Called through the object, not lifted into a local: a lifted method loses its `this`, and the
173
175
  // real Session's reader closes over the journal it was constructed with.
174
- if (session.readJournalActions === undefined)
176
+ if (session.readJournalActions === undefined) {
175
177
  return;
178
+ }
176
179
  const actions = await session.readJournalActions();
177
180
  const root = session.artifactRoot ?? deps.reticleRoot;
178
181
  const inputs = driveRunsFrom(actions, {
@@ -188,8 +191,9 @@ export async function recordDriveRun(deps, session) {
188
191
  ...(session.projectId === undefined ? {} : { projectId: session.projectId }),
189
192
  projectName: basename(dirname(root)),
190
193
  });
191
- if (0 === inputs.length)
194
+ if (0 === inputs.length) {
192
195
  return;
196
+ }
193
197
  // The protocol reaching the artifact a person actually reads. Only when the session could say
194
198
  // where it was: a subject with no locator is not a weaker subject, it is a guess, and the
195
199
  // schema makes the field optional so that absence can be told from invention.
@@ -213,15 +217,16 @@ export async function recordDriveRun(deps, session) {
213
217
  // restamping on every rewrite showed the tab's close as the drive's time.
214
218
  const held = await store.read(asRunId(input.runId));
215
219
  const firstAt = held.ok ? held.run.createdAt : undefined;
216
- await store.write(buildVerificationRun({ ...input, ...(subject === undefined ? {} : { subject }) }, firstAt === undefined ? clock : () => firstAt));
220
+ await store.write(buildVerificationRun({ ...input, ...(subject === undefined ? {} : { subject }) }, firstAt === undefined ? clock : () => firstAt), { sessionId: session.id });
217
221
  }
218
222
  }
219
223
  /** Persist what this session drove as a replayable flow, when it declared anything provable. */
220
- async function saveDrivenFlow(deps, session) {
224
+ async function saveDrivenFlow(deps, session, stepsSent) {
221
225
  const takeTape = deps.takeAmbientTape;
222
226
  const flows = deps.flowsAt?.(session.artifactRoot ?? deps.reticleRoot) ?? deps.flows;
223
- if (takeTape === undefined || flows === undefined)
227
+ if (takeTape === undefined || flows === undefined) {
224
228
  return;
229
+ }
225
230
  // One flow per journey the session contained, not one flow per session — see drive-flow.ts.
226
231
  const { programs, outcome } = driveFlowsFrom(takeTape(session.id));
227
232
  const author = deps.author?.();
@@ -235,7 +240,7 @@ async function saveDrivenFlow(deps, session) {
235
240
  // which is a real outcome and not our bug. Counting it as a failure would blame the product for a
236
241
  // choice the agent made, and counting it as success would claim a regression test that cannot go
237
242
  // red. `unprovenSteps` is what separates "drove and proved nothing" from "drove nothing at all".
238
- await deps.reportStep?.({
243
+ const step = {
239
244
  phase: OnboardingPhase.FIRST_RUN,
240
245
  step: 'flow_recorded',
241
246
  status: 0 === programs.length ? OnboardingStepStatus.SKIPPED : OnboardingStepStatus.COMPLETED,
@@ -246,7 +251,15 @@ async function saveDrivenFlow(deps, session) {
246
251
  ...(0 < programs.length || outcome.mockedSteps === undefined
247
252
  ? {}
248
253
  : { reason: DriveFlowSkipReason.DRIVEN_UNDER_NETWORK_MOCKS }),
249
- });
254
+ };
255
+ // Once per daemon for each status and reason. A browser session ends at every page reload, and
256
+ // a page that reloads in a loop sent this step without end. A repeat tells the funnel nothing.
257
+ const key = `${step.status}/${step.reason ?? ''}`;
258
+ if (stepsSent.has(key)) {
259
+ return;
260
+ }
261
+ stepsSent.add(key);
262
+ await deps.reportStep?.(step);
250
263
  }
251
264
  /**
252
265
  * Remove this session's journal when it served no tool call.
@@ -258,8 +271,9 @@ async function saveDrivenFlow(deps, session) {
258
271
  async function dropUndrivenJournal(fs, root, sessionId) {
259
272
  try {
260
273
  const actions = await fs.readFile(journalActionsPath(root, sessionId)).catch(() => '');
261
- if (actions.trim().length > 0)
274
+ if (actions.trim().length > 0) {
262
275
  return;
276
+ }
263
277
  await fs.rm(sessionDirPath(root, sessionId));
264
278
  }
265
279
  catch {
@@ -49,8 +49,9 @@ const CACHE_COMPACT_AT = 1024;
49
49
  * bound is used in and silently disable it, which is the one failure mode a bound must not have.
50
50
  */
51
51
  function boundedOption(value, fallback, name) {
52
- if (value === undefined)
52
+ if (value === undefined) {
53
53
  return fallback;
54
+ }
54
55
  if (!Number.isSafeInteger(value) || value <= 0) {
55
56
  throw new Error(`refusing a journal ${name} that is not a positive whole number: ${String(value)}`);
56
57
  }
@@ -184,11 +185,13 @@ export class SessionJournal {
184
185
  * already on disk is deleted, and the loss is at the end where it can be declared.
185
186
  */
186
187
  async appendEvents(events) {
187
- if (0 === events.length)
188
+ if (0 === events.length) {
188
189
  return;
190
+ }
189
191
  // Durable, not a field: see #writeLoss. A closed ledger is closed for a one-event batch too.
190
- if ((await this.#closureReport()) !== undefined)
192
+ if ((await this.#closureReport()) !== undefined) {
191
193
  return;
194
+ }
192
195
  await this.#ensureDir();
193
196
  const path = journalEventsPath(this.#root, this.#sessionId);
194
197
  const written = await this.#eventBytesOnDisk(path);
@@ -221,8 +224,9 @@ export class SessionJournal {
221
224
  */
222
225
  async #eventBytesOnDisk(path) {
223
226
  const known = this.#eventBytes;
224
- if (known !== undefined)
227
+ if (known !== undefined) {
225
228
  return known;
229
+ }
226
230
  let size;
227
231
  try {
228
232
  size = (await this.#fs.stat(path)).size;
@@ -235,8 +239,9 @@ export class SessionJournal {
235
239
  // by exactly the conditions most likely to accompany a failing disk. Thrown before anything is
236
240
  // appended; `JournalRecorder` swallows sink errors, so a live session is never taken down by
237
241
  // one.
238
- if (!this.#fs.isNotFound(error))
242
+ if (!this.#fs.isNotFound(error)) {
239
243
  throw error;
244
+ }
240
245
  size = 0;
241
246
  }
242
247
  this.#eventBytes = size;
@@ -252,16 +257,18 @@ export class SessionJournal {
252
257
  * necessarily the ceiling that closed the file.
253
258
  */
254
259
  async #closureReport() {
255
- if (this.#lossLoaded)
260
+ if (this.#lossLoaded) {
256
261
  return this.#writeLoss;
262
+ }
257
263
  let text;
258
264
  try {
259
265
  text = await this.#fs.readFile(journalClosedPath(this.#root, this.#sessionId));
260
266
  }
261
267
  catch (error) {
262
268
  // Same rule as the size read above, and for the same reason: only ENOENT is "never closed".
263
- if (!this.#fs.isNotFound(error))
269
+ if (!this.#fs.isNotFound(error)) {
264
270
  throw error;
271
+ }
265
272
  this.#lossLoaded = true;
266
273
  return undefined;
267
274
  }
@@ -371,8 +378,9 @@ export class SessionJournal {
371
378
  await this.#fs.appendFile(path, text);
372
379
  }
373
380
  catch (error) {
374
- if (!this.#fs.isNotFound(error))
381
+ if (!this.#fs.isNotFound(error)) {
375
382
  throw error;
383
+ }
376
384
  this.#dirEnsured = false;
377
385
  await this.#ensureDir();
378
386
  await this.#fs.appendFile(path, text);
@@ -390,8 +398,9 @@ export class SessionJournal {
390
398
  chunk = await readFrom(path, this.#eventBytesConsumed, this.#maxReadBytes);
391
399
  }
392
400
  catch (error) {
393
- if (this.#fs.isNotFound(error))
401
+ if (this.#fs.isNotFound(error)) {
394
402
  return this.#liveEvents();
403
+ }
395
404
  throw error;
396
405
  }
397
406
  // Shrink guard: if the file is smaller than what we consumed, the offset is meaningless — reset
@@ -408,8 +417,9 @@ export class SessionJournal {
408
417
  const from = chunk.from ?? this.#eventBytesConsumed;
409
418
  const skipped = Math.max(0, from - this.#eventBytesConsumed);
410
419
  this.#ingestTail(chunk.text);
411
- if (skipped > 0)
420
+ if (skipped > 0) {
412
421
  this.#noteCut(skipped);
422
+ }
413
423
  // Resume at the end of the last COMPLETE line, counted forward over the bytes that actually
414
424
  // ARRIVED. Not from `chunk.size`: that is the file's end as `fstat` reported it, and a read
415
425
  // truncated or cut short returns less — a cursor there would skip every unread byte, silently
@@ -424,8 +434,9 @@ export class SessionJournal {
424
434
  text = await this.#fs.readFile(path);
425
435
  }
426
436
  catch (error) {
427
- if (this.#fs.isNotFound(error))
437
+ if (this.#fs.isNotFound(error)) {
428
438
  return this.#liveEvents();
439
+ }
429
440
  throw error;
430
441
  }
431
442
  // Fallback (whole-file) path: #eventCharsConsumed is a UTF-16 offset into the whole text. Shrink
@@ -467,11 +478,13 @@ export class SessionJournal {
467
478
  */
468
479
  #ingestTail(tail) {
469
480
  const end = tail.lastIndexOf('\n') + 1;
470
- if (0 === end)
471
- return; // no complete line yet
481
+ if (0 === end) {
482
+ return;
483
+ } // no complete line yet
472
484
  for (const line of tail.slice(0, end).split('\n')) {
473
- if (0 === line.length)
485
+ if (0 === line.length) {
474
486
  continue;
487
+ }
475
488
  let parsed;
476
489
  try {
477
490
  parsed = JSON.parse(line);
@@ -515,8 +528,9 @@ export class SessionJournal {
515
528
  this.#droppedBytes += cost;
516
529
  this.#droppedEvents += 1;
517
530
  // Exact, unlike a byte cut: this record was parsed, so the millisecond it was lost at is known.
518
- if (victim !== undefined)
531
+ if (victim !== undefined) {
519
532
  this.#lostThroughT = Math.max(this.#lostThroughT, victim.t);
533
+ }
520
534
  // Release the payload now. Waiting for slot compaction keeps evicted snapshots strongly
521
535
  // reachable, so a short returned list alone would not bound retained evidence in memory.
522
536
  this.#eventCache[this.#cacheHead] = undefined;
@@ -545,8 +559,9 @@ export class SessionJournal {
545
559
  * is what carries this to a verdict.
546
560
  */
547
561
  readLoss() {
548
- if (0 === this.#droppedBytes && 0 === this.#droppedEvents)
562
+ if (0 === this.#droppedBytes && 0 === this.#droppedEvents) {
549
563
  return undefined;
564
+ }
550
565
  const bounded = Number.isFinite(this.#lostThroughT);
551
566
  return {
552
567
  droppedBytes: this.#droppedBytes,
@@ -568,8 +583,9 @@ export class SessionJournal {
568
583
  return this.#readLines(journalActionsPath(this.#root, this.#sessionId), JournalActionSchema);
569
584
  }
570
585
  async #ensureDir() {
571
- if (this.#dirEnsured)
586
+ if (this.#dirEnsured) {
572
587
  return;
588
+ }
573
589
  await this.#fs.mkdir(sessionDirPath(this.#root, this.#sessionId));
574
590
  this.#dirEnsured = true;
575
591
  }
@@ -579,14 +595,16 @@ export class SessionJournal {
579
595
  text = await this.#fs.readFile(path);
580
596
  }
581
597
  catch (error) {
582
- if (this.#fs.isNotFound(error))
598
+ if (this.#fs.isNotFound(error)) {
583
599
  return [];
600
+ }
584
601
  throw error;
585
602
  }
586
603
  const out = [];
587
604
  for (const line of text.split('\n')) {
588
- if (0 === line.length)
605
+ if (0 === line.length) {
589
606
  continue;
607
+ }
590
608
  let parsed;
591
609
  try {
592
610
  parsed = JSON.parse(line);
@@ -596,8 +614,9 @@ export class SessionJournal {
596
614
  }
597
615
  const result = schema.safeParse(parsed);
598
616
  // Validated at this boundary; ZodTypeAny widens `.data` to any, so re-narrow to the schema output.
599
- if (result.success)
617
+ if (result.success) {
600
618
  out.push(result.data);
619
+ }
601
620
  }
602
621
  return out;
603
622
  }
@@ -1,6 +1,15 @@
1
1
  import { type ProjectCandidate } from '@reticlehq/core/artifacts';
2
- import { type ProjectId } from '@reticlehq/core';
2
+ import { type Checkout, type ProjectId } from '@reticlehq/core';
3
3
  import { type ArtifactRoot } from './artifact-root.js';
4
+ /**
5
+ * May the daemon write into this `.reticle` root? This is the one answer for every writer.
6
+ *
7
+ * The resolver asks it ONCE for the daemon's own root: a directory does not become a project
8
+ * between two tabs connecting, and this is the IO half `unmatchedRoot` deliberately does not do.
9
+ * A writer that holds a root for the daemon's life (the impact ledger) asks it on each write, so
10
+ * that it starts to write into the project when `init` wires it.
11
+ */
12
+ export declare function mayWriteIntoRoot(reticleRoot: string): boolean;
4
13
  /**
5
14
  * Every project this machine knows the directory of: discovered `.reticle.json` files first, then
6
15
  * the user-level registry, then the dev servers the build plugin announced. Read on each call, since
@@ -34,5 +43,9 @@ export interface ArtifactRootResolverDeps {
34
43
  * would silently keep sending every worktree's artifacts to the primary checkout.
35
44
  */
36
45
  servingDirectory: (origin: string) => string | undefined;
46
+ /** The git checkout a directory is in. Defaults to reading `.git` on disk. */
47
+ checkout?: (dir: string) => Checkout | undefined;
48
+ /** Whether a repository has linked worktrees. Defaults to one directory read. */
49
+ hasWorktrees?: (commonDir: string) => boolean;
37
50
  }
38
51
  export declare function artifactRootResolver(daemonRoot: string, deps: ArtifactRootResolverDeps): (projectId: ProjectId | undefined, origin?: string) => ArtifactRoot;