@reticlehq/server 3.1.0 → 3.3.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 (384) hide show
  1. package/SKILL.md +30 -28
  2. package/dist/command/cli/adhoc-suite.d.ts +19 -0
  3. package/dist/command/cli/adhoc-suite.js +88 -0
  4. package/dist/command/cli/adhoc-verdict.d.ts +23 -2
  5. package/dist/command/cli/adhoc-verdict.js +18 -10
  6. package/dist/command/cli/auth/device-flow.d.ts +2 -2
  7. package/dist/command/cli/cli-doctor.js +37 -5
  8. package/dist/command/cli/cli-flow-commands.d.ts +2 -1
  9. package/dist/command/cli/cli-kill.js +1 -1
  10. package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
  11. package/dist/command/cli/cli-parse-grammar.js +7 -0
  12. package/dist/command/cli/cli-parse-verify.d.ts +2 -5
  13. package/dist/command/cli/cli-parse-verify.js +86 -13
  14. package/dist/command/cli/cli-parse.d.ts +8 -1
  15. package/dist/command/cli/cli-parse.js +38 -7
  16. package/dist/command/cli/cli-verify.d.ts +59 -0
  17. package/dist/command/cli/cli-verify.js +131 -19
  18. package/dist/command/cli/cloud-cli.js +7 -6
  19. package/dist/command/cli/cloud-kit.d.ts +0 -2
  20. package/dist/command/cli/cloud-kit.js +3 -7
  21. package/dist/command/cli/config/config-discovery.d.ts +12 -0
  22. package/dist/command/cli/config/config-discovery.js +19 -0
  23. package/dist/command/cli/doctor/doctor-rows.d.ts +12 -0
  24. package/dist/command/cli/doctor/doctor-rows.js +12 -0
  25. package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
  26. package/dist/command/cli/drive/drive-command.js +1 -1
  27. package/dist/command/cli/launch/cli-launch.d.ts +3 -23
  28. package/dist/command/cli/launch/cli-launch.js +29 -70
  29. package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +33 -0
  30. package/dist/command/cli/lifecycle/daemon-lifecycle.js +198 -0
  31. package/dist/command/cli/mcp-command.js +5 -3
  32. package/dist/command/cli/ports/resolve/cli-port.d.ts +15 -1
  33. package/dist/command/cli/ports/resolve/cli-port.js +50 -2
  34. package/dist/command/cli/report-command.d.ts +16 -0
  35. package/dist/command/cli/report-command.js +97 -0
  36. package/dist/command/cli/status/status-lines.d.ts +28 -0
  37. package/dist/command/cli/status/status-lines.js +117 -0
  38. package/dist/command/cli.d.ts +1 -1
  39. package/dist/command/cli.js +29 -177
  40. package/dist/command/daemon/binding/daemon-status-probe.d.ts +32 -0
  41. package/dist/command/daemon/binding/daemon-status-probe.js +93 -0
  42. package/dist/command/daemon/binding/loopback-reach.d.ts +42 -0
  43. package/dist/command/daemon/binding/loopback-reach.js +63 -0
  44. package/dist/command/daemon/binding/port-presence.d.ts +1 -1
  45. package/dist/command/daemon/daemon-resilience.d.ts +13 -1
  46. package/dist/command/daemon/daemon-resilience.js +12 -1
  47. package/dist/command/daemon/daemon.d.ts +2 -11
  48. package/dist/command/daemon/daemon.js +8 -11
  49. package/dist/command/daemon/idle-shutdown.d.ts +2 -1
  50. package/dist/command/daemon/lifetime/heartbeat.d.ts +8 -0
  51. package/dist/command/daemon/lifetime/heartbeat.js +10 -0
  52. package/dist/command/daemon/lifetime/log-cap.d.ts +68 -0
  53. package/dist/command/daemon/lifetime/log-cap.js +115 -0
  54. package/dist/command/setup/agent-notice-memory.d.ts +16 -0
  55. package/dist/command/setup/agent-notice-memory.js +65 -0
  56. package/dist/command/setup/bringup/dev-server-wait.d.ts +1 -0
  57. package/dist/command/setup/bringup/dev-server-wait.js +16 -0
  58. package/dist/command/setup/bringup/ensure-daemon.js +1 -1
  59. package/dist/command/setup/init/init-host.js +8 -0
  60. package/dist/command/setup/init/init-runtime.js +13 -1
  61. package/dist/command/setup/node-effects.js +1 -1
  62. package/dist/command/setup/probe/page-probe.js +9 -2
  63. package/dist/command/setup/run-setup.d.ts +25 -7
  64. package/dist/command/setup/run-setup.js +51 -9
  65. package/dist/command/setup/setup-command.js +31 -3
  66. package/dist/command/setup/terminal/confirm.js +2 -1
  67. package/dist/command/update/updater.d.ts +27 -0
  68. package/dist/command/update/updater.js +35 -2
  69. package/dist/features/crawl/crawl-tools.js +3 -1
  70. package/dist/features/crawl/crawl.d.ts +2 -0
  71. package/dist/features/crawl/crawl.js +3 -1
  72. package/dist/features/harness/drive-report.d.ts +73 -0
  73. package/dist/features/harness/drive-report.js +196 -0
  74. package/dist/features/harness/driver.js +29 -8
  75. package/dist/features/harness/drivers.d.ts +19 -0
  76. package/dist/features/harness/drivers.js +19 -0
  77. package/dist/features/harness/fill-values.d.ts +67 -0
  78. package/dist/features/harness/fill-values.js +153 -0
  79. package/dist/features/harness/jev-driver.d.ts +188 -0
  80. package/dist/features/harness/jev-driver.js +661 -0
  81. package/dist/features/harness/openai-driver.d.ts +46 -0
  82. package/dist/features/harness/openai-driver.js +197 -0
  83. package/dist/features/harness/platform-config.d.ts +62 -0
  84. package/dist/features/harness/platform-config.js +97 -0
  85. package/dist/features/visual/visual-tools.js +26 -2
  86. package/dist/index.d.ts +1 -1
  87. package/dist/index.js +80 -130
  88. package/dist/judgement/capsule/capsule-store.d.ts +31 -2
  89. package/dist/judgement/capsule/capsule-store.js +58 -6
  90. package/dist/judgement/capsule/capsule.js +5 -0
  91. package/dist/judgement/capsule/causal-summary.d.ts +13 -1
  92. package/dist/judgement/capsule/causal-summary.js +7 -0
  93. package/dist/judgement/domain/domain-model.js +38 -9
  94. package/dist/judgement/domain/domain-tools.js +4 -2
  95. package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
  96. package/dist/judgement/phenomena/phenomena.d.ts +2 -1
  97. package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
  98. package/dist/judgement/runs/artifact/gap-report.js +46 -0
  99. package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
  100. package/dist/judgement/runs/artifact/gap-summary.js +85 -0
  101. package/dist/judgement/runs/artifact/render-report.js +4 -1
  102. package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
  103. package/dist/judgement/runs/artifact/to-artifact.js +1 -1
  104. package/dist/judgement/runs/context-tools.js +21 -3
  105. package/dist/judgement/runs/drive-run.js +7 -2
  106. package/dist/judgement/runs/verification-sync.d.ts +2 -2
  107. package/dist/judgement/runs/verification-sync.js +9 -2
  108. package/dist/language/flows/affected-tools.js +6 -3
  109. package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
  110. package/dist/language/flows/annotate-notes/annotate.js +66 -18
  111. package/dist/language/flows/flow-anchor.d.ts +12 -0
  112. package/dist/language/flows/flow-anchor.js +20 -0
  113. package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
  114. package/dist/language/flows/flow-expect-grammar.js +92 -11
  115. package/dist/language/flows/flow-intent.js +1 -1
  116. package/dist/language/flows/flow-learning.d.ts +3 -0
  117. package/dist/language/flows/flow-learning.js +39 -8
  118. package/dist/language/flows/flow-replay-run.d.ts +55 -10
  119. package/dist/language/flows/flow-replay-run.js +217 -58
  120. package/dist/language/flows/flow-replay-types.d.ts +9 -0
  121. package/dist/language/flows/flow-replay.d.ts +29 -11
  122. package/dist/language/flows/flow-replay.js +221 -203
  123. package/dist/language/flows/flow-result.d.ts +18 -1
  124. package/dist/language/flows/flow-result.js +18 -2
  125. package/dist/language/flows/flow-step-runners.d.ts +26 -10
  126. package/dist/language/flows/flow-step-runners.js +20 -4
  127. package/dist/language/flows/flow-store-for-session.d.ts +2 -1
  128. package/dist/language/flows/flow-success.d.ts +21 -6
  129. package/dist/language/flows/flow-success.js +50 -138
  130. package/dist/language/flows/flow-tools.js +8 -4
  131. package/dist/language/flows/flows.d.ts +15 -10
  132. package/dist/language/flows/flows.js +17 -4
  133. package/dist/language/flows/heal.d.ts +9 -1
  134. package/dist/language/flows/heal.js +24 -2
  135. package/dist/language/flows/learned-sources.d.ts +21 -0
  136. package/dist/language/flows/learned-sources.js +84 -0
  137. package/dist/language/flows/narrow-write.d.ts +4 -4
  138. package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
  139. package/dist/language/flows/recording/recording-backtrack.js +1 -1
  140. package/dist/language/flows/recording/replay-halt.d.ts +2 -1
  141. package/dist/language/flows/recording/tape/recordings.d.ts +2 -2
  142. package/dist/language/flows/replay.js +13 -9
  143. package/dist/language/flows/stores/annotation-store.d.ts +5 -5
  144. package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
  145. package/dist/language/flows/stores/flake-store.js +2 -3
  146. package/dist/language/flows/suite/coverage.d.ts +1 -1
  147. package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
  148. package/dist/language/flows/suite-selection.d.ts +15 -1
  149. package/dist/language/flows/suite-selection.js +1 -1
  150. package/dist/language/flows/verify-change-tools.js +21 -4
  151. package/dist/memory/cloud/account-state.d.ts +1 -1
  152. package/dist/memory/cloud/account-state.js +5 -4
  153. package/dist/memory/cloud/cloud-config.d.ts +9 -0
  154. package/dist/memory/cloud/cloud-config.js +9 -0
  155. package/dist/memory/cloud/cloud-sync.d.ts +7 -4
  156. package/dist/memory/cloud/cloud-sync.js +11 -6
  157. package/dist/memory/cloud/harness-config.d.ts +12 -0
  158. package/dist/memory/cloud/harness-config.js +58 -0
  159. package/dist/memory/cloud/harness-offer.d.ts +44 -0
  160. package/dist/memory/cloud/harness-offer.js +146 -0
  161. package/dist/memory/cloud/harness-switch.d.ts +11 -0
  162. package/dist/memory/cloud/harness-switch.js +53 -0
  163. package/dist/memory/cloud/sync-cycle.d.ts +12 -0
  164. package/dist/memory/cloud/sync-cycle.js +29 -4
  165. package/dist/memory/cloud/sync-daemon.d.ts +35 -2
  166. package/dist/memory/cloud/sync-daemon.js +45 -0
  167. package/dist/memory/cloud/sync-disk.js +11 -6
  168. package/dist/memory/impact/impact-recorder.d.ts +8 -0
  169. package/dist/memory/impact/impact-recorder.js +2 -1
  170. package/dist/memory/impact/impact-store.d.ts +5 -0
  171. package/dist/memory/impact/impact-store.js +25 -0
  172. package/dist/memory/intent/inline-intent.js +8 -3
  173. package/dist/memory/intent/intent-shard-store.d.ts +33 -47
  174. package/dist/memory/intent/intent-shard-store.js +253 -141
  175. package/dist/memory/intent/intent-shard.d.ts +22 -23
  176. package/dist/memory/intent/intent-shard.js +1 -1
  177. package/dist/memory/intent/intent-store.d.ts +13 -8
  178. package/dist/memory/intent/intent-store.js +46 -90
  179. package/dist/memory/intent/intent-tools.js +34 -23
  180. package/dist/memory/journal/ambient-store.js +2 -3
  181. package/dist/memory/journal/attach-journal.d.ts +11 -0
  182. package/dist/memory/journal/attach-journal.js +1 -1
  183. package/dist/memory/journal/deviation-report.js +4 -1
  184. package/dist/memory/journal/deviation-service.js +10 -2
  185. package/dist/memory/journal/drive-flow.d.ts +2 -2
  186. package/dist/memory/journal/drive-flow.js +21 -12
  187. package/dist/memory/journal/envelope-store.js +2 -3
  188. package/dist/memory/journal/journal-query.d.ts +35 -1
  189. package/dist/memory/journal/journal-query.js +46 -0
  190. package/dist/memory/journal/journal-recorder.d.ts +71 -2
  191. package/dist/memory/journal/journal-recorder.js +45 -7
  192. package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
  193. package/dist/memory/journal/on-disk/retain-policy.js +44 -0
  194. package/dist/memory/journal/on-disk/retention.d.ts +91 -2
  195. package/dist/memory/journal/on-disk/retention.js +181 -11
  196. package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
  197. package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
  198. package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -2
  199. package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -38
  200. package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
  201. package/dist/memory/journal/on-disk/workspace-tiers.js +88 -0
  202. package/dist/memory/journal/route-template.d.ts +22 -0
  203. package/dist/memory/journal/route-template.js +44 -0
  204. package/dist/memory/journal/self-observation.d.ts +3 -0
  205. package/dist/memory/journal/self-observation.js +67 -0
  206. package/dist/memory/journal/session-end.d.ts +17 -4
  207. package/dist/memory/journal/session-end.js +85 -7
  208. package/dist/memory/journal/session-journal.d.ts +122 -5
  209. package/dist/memory/journal/session-journal.js +489 -32
  210. package/dist/memory/project/artifact-root-resolver.d.ts +3 -0
  211. package/dist/memory/project/artifact-root-resolver.js +89 -0
  212. package/dist/memory/project/artifact-root.d.ts +39 -2
  213. package/dist/memory/project/artifact-root.js +58 -1
  214. package/dist/memory/project/baselines.d.ts +1 -1
  215. package/dist/memory/project/dir/fill-value-store.d.ts +32 -0
  216. package/dist/memory/project/dir/fill-value-store.js +88 -0
  217. package/dist/memory/project/dir/reticle-dir.d.ts +15 -5
  218. package/dist/memory/project/dir/reticle-dir.js +11 -0
  219. package/dist/memory/project/fs/fs-port.d.ts +22 -1
  220. package/dist/memory/project/fs/fs-port.js +72 -5
  221. package/dist/memory/project/fs/write-atomic.d.ts +26 -0
  222. package/dist/memory/project/fs/write-atomic.js +48 -0
  223. package/dist/memory/project/learned-routes.d.ts +16 -2
  224. package/dist/memory/project/learned-routes.js +26 -10
  225. package/dist/memory/project/project-for-root.d.ts +30 -0
  226. package/dist/memory/project/project-for-root.js +43 -0
  227. package/dist/memory/project/project-tools.js +10 -5
  228. package/dist/memory/project/session-root.d.ts +35 -6
  229. package/dist/memory/project/session-root.js +70 -8
  230. package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
  231. package/dist/memory/recall/prior/connection-memory.js +8 -0
  232. package/dist/memory/recall/registered-projects.d.ts +2 -1
  233. package/dist/portal/bridge/auth-failure-reason.d.ts +9 -0
  234. package/dist/portal/bridge/auth-failure-reason.js +20 -3
  235. package/dist/portal/bridge/bridge.d.ts +6 -1
  236. package/dist/portal/bridge/bridge.js +36 -2
  237. package/dist/portal/input/real-input.js +2 -1
  238. package/dist/portal/pool/browser-pool.d.ts +10 -0
  239. package/dist/portal/pool/browser-pool.js +10 -0
  240. package/dist/portal/pool/playwright-launcher.js +1 -0
  241. package/dist/portal/pool/pool-contract.d.ts +2 -0
  242. package/dist/portal/pool/storage-seed.d.ts +2 -1
  243. package/dist/portal/pool/zero-install.d.ts +27 -0
  244. package/dist/portal/pool/zero-install.js +54 -0
  245. package/dist/portal/realm/web-realm.js +6 -0
  246. package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
  247. package/dist/portal/session/dev-server/served-document.d.ts +21 -0
  248. package/dist/portal/session/dev-server/served-document.js +57 -0
  249. package/dist/portal/session/facts/background-traffic.d.ts +9 -0
  250. package/dist/portal/session/facts/background-traffic.js +25 -0
  251. package/dist/portal/session/facts/session-replaced.d.ts +19 -0
  252. package/dist/portal/session/facts/session-replaced.js +22 -0
  253. package/dist/portal/session/live-control-tools.js +48 -3
  254. package/dist/portal/session/no-session-diagnosis.d.ts +1 -0
  255. package/dist/portal/session/no-session-diagnosis.js +67 -60
  256. package/dist/portal/session/no-session-next-action.js +3 -2
  257. package/dist/portal/session/no-session-watch.js +14 -10
  258. package/dist/portal/session/presence/attachment-history.d.ts +13 -2
  259. package/dist/portal/session/rebind.d.ts +18 -0
  260. package/dist/portal/session/rebind.js +38 -0
  261. package/dist/portal/session/session-health.d.ts +61 -0
  262. package/dist/portal/session/session-health.js +40 -1
  263. package/dist/portal/session/session-info.d.ts +6 -0
  264. package/dist/portal/session/session-manager.d.ts +13 -0
  265. package/dist/portal/session/session-manager.js +42 -3
  266. package/dist/portal/session/session-successor.d.ts +11 -0
  267. package/dist/portal/session/session-successor.js +14 -1
  268. package/dist/portal/session/session-verdict-facts.d.ts +28 -0
  269. package/dist/portal/session/session-verdict-facts.js +15 -0
  270. package/dist/portal/session/session.d.ts +26 -10
  271. package/dist/portal/session/session.js +48 -49
  272. package/dist/status-payload.d.ts +12 -1
  273. package/dist/status-payload.js +4 -1
  274. package/dist/surface/http-server.js +3 -5
  275. package/dist/surface/mcp/faults/mcp-outage.d.ts +2 -1
  276. package/dist/surface/mcp/faults/mcp-outage.js +20 -4
  277. package/dist/surface/mcp/mcp-proxy.d.ts +10 -1
  278. package/dist/surface/mcp/mcp-proxy.js +23 -12
  279. package/dist/surface/mcp/mcp.d.ts +10 -1
  280. package/dist/surface/mcp/mcp.js +59 -29
  281. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +15 -2
  282. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +22 -5
  283. package/dist/surface/mcp/proxy/proxy-log.d.ts +5 -11
  284. package/dist/surface/mcp/proxy/proxy-log.js +7 -22
  285. package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
  286. package/dist/surface/mcp/server-instructions.js +12 -1
  287. package/dist/surface/tools/act/act-preflight.js +6 -1
  288. package/dist/surface/tools/act/already-true.d.ts +40 -0
  289. package/dist/surface/tools/act/already-true.js +36 -0
  290. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +6 -0
  291. package/dist/surface/tools/act/navigation/navigate-arrival.js +13 -0
  292. package/dist/surface/tools/act/sequence-grade.js +13 -0
  293. package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
  294. package/dist/surface/tools/act/settle-in-flight.js +29 -6
  295. package/dist/surface/tools/act-capsule.js +49 -8
  296. package/dist/surface/tools/act-tools.js +25 -24
  297. package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
  298. package/dist/surface/tools/args/numeric-bounds.js +30 -3
  299. package/dist/surface/tools/assert/assert-grade.js +14 -2
  300. package/dist/surface/tools/assert/assert-verdict.js +74 -21
  301. package/dist/surface/tools/browser-tools.js +4 -3
  302. package/dist/surface/tools/coverage-tools.js +5 -2
  303. package/dist/surface/tools/dynamic-tools.js +43 -46
  304. package/dist/surface/tools/error-recovery.d.ts +6 -0
  305. package/dist/surface/tools/error-recovery.js +15 -0
  306. package/dist/surface/tools/explore-tools.js +80 -7
  307. package/dist/surface/tools/feedback-tools.d.ts +2 -1
  308. package/dist/surface/tools/feedback-tools.js +50 -3
  309. package/dist/surface/tools/first-sentence.d.ts +24 -0
  310. package/dist/surface/tools/first-sentence.js +0 -0
  311. package/dist/surface/tools/harness-explore.d.ts +125 -1
  312. package/dist/surface/tools/harness-explore.js +401 -15
  313. package/dist/surface/tools/harness-plan.d.ts +76 -0
  314. package/dist/surface/tools/harness-plan.js +156 -0
  315. package/dist/surface/tools/harness-toolset.js +12 -1
  316. package/dist/surface/tools/invoke-tool.js +82 -9
  317. package/dist/surface/tools/lease-hint.d.ts +8 -0
  318. package/dist/surface/tools/lease-hint.js +10 -0
  319. package/dist/surface/tools/lease-tools.d.ts +16 -28
  320. package/dist/surface/tools/lease-tools.js +53 -5
  321. package/dist/surface/tools/lineage-tools.js +1 -1
  322. package/dist/surface/tools/live-call-text.d.ts +6 -0
  323. package/dist/surface/tools/live-call-text.js +36 -2
  324. package/dist/surface/tools/observe-tools.js +69 -15
  325. package/dist/surface/tools/read/query-windowed.d.ts +1 -1
  326. package/dist/surface/tools/read/query-windowed.js +1 -1
  327. package/dist/surface/tools/read-tools.js +1 -2
  328. package/dist/surface/tools/real-input-attempt.d.ts +0 -5
  329. package/dist/surface/tools/real-input-attempt.js +1 -1
  330. package/dist/surface/tools/tool-kit.d.ts +23 -3
  331. package/dist/surface/tools/tool-kit.js +6 -1
  332. package/dist/surface/tools/tool-surface.js +17 -5
  333. package/dist/surface/tools/tools-helpers.d.ts +8 -7
  334. package/dist/surface/tools/tools-helpers.js +11 -13
  335. package/dist/surface/tools/tools.js +70 -30
  336. package/dist/telemetry/bug-found.js +32 -2
  337. package/dist/telemetry/feedback-context.js +3 -3
  338. package/dist/telemetry/feedback-local.d.ts +1 -0
  339. package/dist/telemetry/feedback-local.js +1 -3
  340. package/dist/telemetry/feedback.d.ts +1 -1
  341. package/dist/telemetry/harness-drive.d.ts +6 -0
  342. package/dist/telemetry/harness-drive.js +39 -0
  343. package/dist/telemetry/hud-metrics.d.ts +32 -0
  344. package/dist/telemetry/hud-metrics.js +95 -0
  345. package/dist/telemetry/mcp-connection.d.ts +14 -1
  346. package/dist/telemetry/mcp-connection.js +17 -2
  347. package/dist/telemetry/onboarding-firsts.d.ts +30 -1
  348. package/dist/telemetry/onboarding-firsts.js +54 -12
  349. package/dist/telemetry/session-metrics.d.ts +5 -0
  350. package/dist/telemetry/session-metrics.js +15 -1
  351. package/dist/telemetry/verification-of.js +31 -3
  352. package/dist/wire-journal.d.ts +31 -0
  353. package/dist/wire-journal.js +100 -0
  354. package/docs/README.md +1 -0
  355. package/docs/agent-cheatsheet.md +7 -3
  356. package/docs/autodrive.md +42 -2
  357. package/docs/benchmarks.md +1 -1
  358. package/docs/capabilities.mdx +1 -1
  359. package/docs/cli/cloud.mdx +11 -9
  360. package/docs/cli/doctor.mdx +1 -0
  361. package/docs/cli/init.mdx +1 -0
  362. package/docs/cli/report.mdx +44 -0
  363. package/docs/cli/status.mdx +35 -20
  364. package/docs/cli.mdx +8 -18
  365. package/docs/desktop.mdx +1 -1
  366. package/docs/faq.mdx +1 -1
  367. package/docs/flows.md +11 -0
  368. package/docs/frameworks.mdx +113 -1
  369. package/docs/install-agentic.mdx +36 -0
  370. package/docs/install-manual.mdx +1 -1
  371. package/docs/packages/tauri.mdx +1 -1
  372. package/docs/packages.mdx +1 -1
  373. package/docs/predicates.mdx +144 -4
  374. package/docs/system-map.md +6 -4
  375. package/docs/telemetry.md +2 -1
  376. package/docs/token-efficiency.md +2 -2
  377. package/docs/tools/overview.mdx +1 -1
  378. package/docs/tools/query.mdx +10 -10
  379. package/docs/troubleshooting.mdx +8 -2
  380. package/docs/usage.md +2 -2
  381. package/docs/what-is-recorded.md +62 -0
  382. package/package.json +5 -5
  383. package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
  384. package/dist/judgement/outcome/predicate-to-expect.js +0 -148
@@ -12,7 +12,7 @@
12
12
  *
13
13
  * Pure: no IO, no clock. The tool layer loads flows + contract and calls this.
14
14
  */
15
- import { AnchorKind, } from '@reticlehq/core';
15
+ import { AnchorKind, PredicateKind, } from '@reticlehq/core';
16
16
  import { classifyFlowAssertions, FlowAssertionGrade } from '../../language/flows/flow-classify.js';
17
17
  import { successLabel } from '../../language/flows/flow-success.js';
18
18
  import { flowRisk, latestRun, rankByRisk, RiskLevel } from './flow-risk.js';
@@ -25,16 +25,45 @@ function flatten(steps) {
25
25
  }
26
26
  return out;
27
27
  }
28
+ /*
29
+ * The vocabulary a flow uses, read out of a predicate TREE.
30
+ *
31
+ * These were property reads when `expect` was a struct with one slot per kind. A predicate nests, and
32
+ * the domain model is about what a flow TALKS ABOUT, so the walk goes all the way down: a signal
33
+ * named inside an `allOf` two levels deep is still a signal this flow depends on, and missing it
34
+ * would quietly shrink the model that decides which flows a change affects.
35
+ */
36
+ function walkClauses(predicate) {
37
+ if (predicate === undefined)
38
+ return [];
39
+ if (PredicateKind.ALL_OF === predicate.kind || PredicateKind.ANY_OF === predicate.kind) {
40
+ return predicate.predicates.flatMap(walkClauses);
41
+ }
42
+ if (PredicateKind.NOT === predicate.kind)
43
+ return walkClauses(predicate.predicate);
44
+ return [predicate];
45
+ }
46
+ function signalNamesIn(predicate) {
47
+ return walkClauses(predicate)
48
+ .filter((c) => PredicateKind.SIGNAL === c.kind)
49
+ .map((c) => (PredicateKind.SIGNAL === c.kind ? c.name : undefined))
50
+ .filter((name) => name !== undefined);
51
+ }
52
+ function elementTestidsIn(predicate) {
53
+ return walkClauses(predicate)
54
+ .map((c) => (PredicateKind.ELEMENT === c.kind ? c.query.testid : undefined))
55
+ .filter((testid) => testid !== undefined);
56
+ }
28
57
  function flowSignals(flow) {
29
58
  const set = new Set();
30
59
  for (const step of flatten(flow.steps)) {
31
60
  if (step.anchor.kind === AnchorKind.SIGNAL)
32
61
  set.add(step.anchor.name);
33
- if (step.expect?.signal !== undefined)
34
- set.add(step.expect.signal);
62
+ for (const name of signalNamesIn(step.expect))
63
+ set.add(name);
35
64
  }
36
- if (flow.success?.signal !== undefined)
37
- set.add(flow.success.signal);
65
+ for (const name of signalNamesIn(flow.success))
66
+ set.add(name);
38
67
  return [...set];
39
68
  }
40
69
  function flowTestids(flow) {
@@ -42,11 +71,11 @@ function flowTestids(flow) {
42
71
  for (const step of flatten(flow.steps)) {
43
72
  if (step.anchor.kind === AnchorKind.TESTID)
44
73
  set.add(step.anchor.value);
45
- if (step.expect?.element?.testid !== undefined)
46
- set.add(step.expect.element.testid);
74
+ for (const testid of elementTestidsIn(step.expect))
75
+ set.add(testid);
47
76
  }
48
- if (flow.success?.element?.testid !== undefined)
49
- set.add(flow.success.element.testid);
77
+ for (const testid of elementTestidsIn(flow.success))
78
+ set.add(testid);
50
79
  return [...set];
51
80
  }
52
81
  const EMPTY_CONTRACT = { testids: [], signals: [], stores: [], flows: [] };
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { projectForRoot } from '../../memory/project/project-for-root.js';
2
3
  import { sessionRoot } from '../../memory/project/session-root.js';
3
4
  import { asNumber, asString } from '@reticlehq/core';
4
5
  import { ReticleTool } from '@reticlehq/core';
@@ -75,8 +76,9 @@ export const DOMAIN_TOOLS = [
75
76
  if (loaded.ok)
76
77
  flows.push(loaded.value);
77
78
  }
78
- const contract = await readContract(deps.fs, sessionRoot(deps, asString(args['sessionId'])));
79
- const project = await deps.project.read();
79
+ const root = sessionRoot(deps, asString(args['sessionId']));
80
+ const contract = await readContract(deps.fs, root);
81
+ const project = await projectForRoot(deps, root).read();
80
82
  const runs = project.ok ? project.file.runs : [];
81
83
  const model = buildDomainModel(flows, contract.ok ? contract.capabilities : null, runs);
82
84
  // Self-instrumentation: turn located gaps (unasserted flows with a source stamp) into apply-ready diffs.
@@ -1,4 +1,4 @@
1
- import { type FlowExpect } from '@reticlehq/core';
1
+ import { type Predicate } from '@reticlehq/core';
2
2
  /**
3
3
  * Anti-reward-hacking (research-mandated). Test-gated agents pass gates by WEAKENING assertions — the
4
4
  * canonical documented failure. Flows are git-checked and agent-editable, so a mustHold that dropped
@@ -7,10 +7,10 @@ import { type FlowExpect } from '@reticlehq/core';
7
7
  * and flow_verify surface it.
8
8
  */
9
9
  /** True when `after` weakened `before` — a real consequence became a fakeable presence-only check. */
10
- export declare function isAssertionDowngrade(before: FlowExpect | undefined, after: FlowExpect | undefined): boolean;
10
+ export declare function isAssertionDowngrade(before: Predicate | undefined, after: Predicate | undefined): boolean;
11
11
  export interface StepExpect {
12
12
  step: number;
13
- expect?: FlowExpect;
13
+ expect?: Predicate;
14
14
  }
15
15
  interface DowngradeFinding {
16
16
  step: number;
@@ -4,7 +4,7 @@ import { PhenomenonType, type JournalAction, type ReticleEvent } from '@reticleh
4
4
  * scanning by the agent: the layer names the fault, the agent acts on the name. `pre-hydration-click`
5
5
  * lands once the hydration signal (a later item) exists; the three here need only journal data.
6
6
  */
7
- export interface Finding {
7
+ interface Finding {
8
8
  phenomenon: PhenomenonType;
9
9
  evidence: Record<string, unknown>;
10
10
  }
@@ -24,3 +24,4 @@ export declare function detectPreHydrationClicks(events: readonly ReticleEvent[]
24
24
  export declare function detectSwallowedErrors(events: readonly ReticleEvent[]): Finding[];
25
25
  /** Run every journal-only matcher over a session's events + actions. */
26
26
  export declare function detectPhenomena(events: readonly ReticleEvent[], actions: readonly JournalAction[]): Finding[];
27
+ export {};
@@ -0,0 +1,17 @@
1
+ /**
2
+ * The session gap, as a person reads it — and as a Stop hook prints it.
3
+ *
4
+ * `gapSummary` folds the journal into what was claimed and what held. This is its only renderer, so
5
+ * `reticle report` and the hook cannot describe the same session two different ways.
6
+ */
7
+ import type { GapSummary } from './gap-summary.js';
8
+ /**
9
+ * One line when the agent finishes without a single `yes`, and nothing otherwise.
10
+ *
11
+ * Silent after a `yes` on purpose: a hook that speaks on every stop is a hook people turn off, and the
12
+ * question it exists to raise is "did anything get proved at all". Every answer that is not a yes is
13
+ * counted by name — an `unknown` is never folded into anything, because that fold is the false green.
14
+ */
15
+ export declare function gapHookLine(gap: GapSummary): string | undefined;
16
+ /** The whole gap: held of claimed first, then each kind of not-held with who can act on it. */
17
+ export declare function gapReportLines(gap: GapSummary): string[];
@@ -0,0 +1,46 @@
1
+ const HOOK_PREFIX = 'Reticle: not verified.';
2
+ const NO_CLAIM_HOOK = `${HOOK_PREFIX} No claim was checked this session`;
3
+ const NO_CLAIM_REPORT = 'no claims this session, so nothing was verified';
4
+ const plural = (n, word) => `${String(n)} ${word}${1 === n ? '' : 's'}`;
5
+ /**
6
+ * One line when the agent finishes without a single `yes`, and nothing otherwise.
7
+ *
8
+ * Silent after a `yes` on purpose: a hook that speaks on every stop is a hook people turn off, and the
9
+ * question it exists to raise is "did anything get proved at all". Every answer that is not a yes is
10
+ * counted by name — an `unknown` is never folded into anything, because that fold is the false green.
11
+ */
12
+ export function gapHookLine(gap) {
13
+ if (0 < gap.held)
14
+ return undefined;
15
+ if (0 === gap.claims)
16
+ return NO_CLAIM_HOOK;
17
+ const parts = [
18
+ 0 < gap.failed ? `${String(gap.failed)} failed` : undefined,
19
+ 0 < gap.undecided ? `${String(gap.undecided)} unknown` : undefined,
20
+ 0 < gap.nothingToProve ? `${String(gap.nothingToProve)} proved nothing` : undefined,
21
+ ].filter((part) => part !== undefined);
22
+ return `${HOOK_PREFIX} ${plural(gap.claims, 'claim')}: ${parts.join(', ')}`;
23
+ }
24
+ /** The whole gap: held of claimed first, then each kind of not-held with who can act on it. */
25
+ export function gapReportLines(gap) {
26
+ if (0 === gap.claims)
27
+ return [NO_CLAIM_REPORT];
28
+ const lines = [`${String(gap.held)} of ${plural(gap.claims, 'claim')} held`];
29
+ if (0 < gap.failed) {
30
+ const caught = 0 < gap.falseGreensCaught
31
+ ? `, ${String(gap.falseGreensCaught)} of them a green a channel contradicted`
32
+ : '';
33
+ lines.push(`${String(gap.failed)} failed${caught}`);
34
+ }
35
+ if (0 < gap.undecided) {
36
+ const owners = Object.entries(gap.undecidedBy)
37
+ .map(([owner, n]) => `${owner}: ${String(n)}`)
38
+ .join(', ');
39
+ lines.push(`${String(gap.undecided)} unknown${'' === owners ? '' : ` (${owners})`}`);
40
+ }
41
+ if (0 < gap.nothingToProve)
42
+ lines.push(`${String(gap.nothingToProve)} proved nothing`);
43
+ for (const failure of gap.failures)
44
+ lines.push(` ✗ ${failure.claim}`);
45
+ return lines;
46
+ }
@@ -0,0 +1,58 @@
1
+ /**
2
+ * The gap, as a number the person who ran the session can see.
3
+ *
4
+ * Reticle's whole claim is that it measures the distance between what an agent believed happened
5
+ * and what did. It measures that on every verdict, writes the answer into the journal, and shows it
6
+ * to nobody: the counts exist, the reasons exist, the contradictions exist, and no surface anywhere
7
+ * says "you made 14 claims, 9 held, 2 were false, 3 could not be decided, and here is who owns each
8
+ * of those three". The value of the product is the one thing it never reports.
9
+ *
10
+ * A FOLD over the journal, never a second store — the rule `run-context.ts` next door states, for
11
+ * the same reason: two ways to compute one number is worse than one way, because the day they
12
+ * disagree the disagreement lands inside a verdict and a user finds it before we do.
13
+ *
14
+ * Nothing here sends anything anywhere, and that is deliberate rather than incidental. This is the
15
+ * LOCAL half. Whether a fleet-wide version of the same number is worth collecting is a separate
16
+ * decision with a separate owner, and building the local one first is what makes that decision
17
+ * answerable from something other than a guess.
18
+ */
19
+ import { VerifiedReason, VerdictAttribution, type JournalAction } from '@reticlehq/core';
20
+ /** One claim that did not hold, in the words it was made and the engine's reason for refusing it. */
21
+ export interface GapFailure {
22
+ claim: string;
23
+ reason?: VerifiedReason;
24
+ }
25
+ export interface GapSummary {
26
+ /** Actions that asserted something. An action that only drove the app is not a claim. */
27
+ claims: number;
28
+ held: number;
29
+ failed: number;
30
+ /** `unknown`: Reticle could not tell. Never folded into held or failed — that is the false green. */
31
+ undecided: number;
32
+ /**
33
+ * `no-fault`: nothing was declared, so nothing was checked.
34
+ *
35
+ * The fourth answer, kept apart from the other three. Folding it anywhere is how a session that
36
+ * proved nothing reads as a session that proved something.
37
+ */
38
+ nothingToProve: number;
39
+ /**
40
+ * WHO can act on each undecided verdict, counted per owner.
41
+ *
42
+ * The only part of an `unknown` a reader can do anything with: the four owners imply four
43
+ * different next moves — wait, fix the app, fix the harness, look again. Empty when nothing was
44
+ * undecided, and a verdict that recorded no reason contributes to no owner rather than to a
45
+ * guessed one.
46
+ */
47
+ undecidedBy: Partial<Record<VerdictAttribution, number>>;
48
+ /**
49
+ * Failures where a CHANNEL disagreed with what the app showed.
50
+ *
51
+ * Counted apart from an ordinary failure because they mean different things to the reader: an
52
+ * assertion that failed is a check doing its job, and a contradiction is a green that would have
53
+ * been believed. This number is the product's own headline, measured on the reader's own session.
54
+ */
55
+ falseGreensCaught: number;
56
+ failures: GapFailure[];
57
+ }
58
+ export declare function gapSummary(actions: readonly JournalAction[]): GapSummary;
@@ -0,0 +1,85 @@
1
+ /**
2
+ * The gap, as a number the person who ran the session can see.
3
+ *
4
+ * Reticle's whole claim is that it measures the distance between what an agent believed happened
5
+ * and what did. It measures that on every verdict, writes the answer into the journal, and shows it
6
+ * to nobody: the counts exist, the reasons exist, the contradictions exist, and no surface anywhere
7
+ * says "you made 14 claims, 9 held, 2 were false, 3 could not be decided, and here is who owns each
8
+ * of those three". The value of the product is the one thing it never reports.
9
+ *
10
+ * A FOLD over the journal, never a second store — the rule `run-context.ts` next door states, for
11
+ * the same reason: two ways to compute one number is worse than one way, because the day they
12
+ * disagree the disagreement lands inside a verdict and a user finds it before we do.
13
+ *
14
+ * Nothing here sends anything anywhere, and that is deliberate rather than incidental. This is the
15
+ * LOCAL half. Whether a fleet-wide version of the same number is worth collecting is a separate
16
+ * decision with a separate owner, and building the local one first is what makes that decision
17
+ * answerable from something other than a guess.
18
+ */
19
+ import { JournalVerdictEffectSchema, Verified, VerifiedReason, VerdictAttribution, verdictAttributionOf, } from '@reticlehq/core';
20
+ /**
21
+ * The reason, as the engine's own enum, or undefined.
22
+ *
23
+ * The journal stores `reason` as a free string rather than the enum — deliberately, because the
24
+ * ledger has to keep reading records written by an older engine whose vocabulary it cannot know.
25
+ * So a reason this build does not recognise is treated exactly like an absent one: no owner. The
26
+ * alternative is attributing an unknown word to one of four buckets, which is inventing an
27
+ * attribution nobody recorded.
28
+ */
29
+ function knownReason(reason) {
30
+ if (reason === undefined)
31
+ return undefined;
32
+ const known = Object.values(VerifiedReason);
33
+ return known.includes(reason) ? reason : undefined;
34
+ }
35
+ /** The verdict a verification tool recorded on this action, if it recorded one. */
36
+ function verdictOf(action) {
37
+ const parsed = JournalVerdictEffectSchema.safeParse(action.effect);
38
+ return parsed.success ? parsed.data : undefined;
39
+ }
40
+ export function gapSummary(actions) {
41
+ const summary = {
42
+ claims: 0,
43
+ held: 0,
44
+ failed: 0,
45
+ undecided: 0,
46
+ nothingToProve: 0,
47
+ undecidedBy: {},
48
+ falseGreensCaught: 0,
49
+ failures: [],
50
+ };
51
+ for (const action of actions) {
52
+ const verdict = verdictOf(action);
53
+ if (verdict === undefined)
54
+ continue;
55
+ summary.claims += 1;
56
+ switch (verdict.verified) {
57
+ case Verified.YES:
58
+ summary.held += 1;
59
+ break;
60
+ case Verified.NO: {
61
+ summary.failed += 1;
62
+ if (VerifiedReason.CONTRADICTED === verdict.reason)
63
+ summary.falseGreensCaught += 1;
64
+ const reason = knownReason(verdict.reason);
65
+ summary.failures.push(reason === undefined ? { claim: verdict.claim } : { claim: verdict.claim, reason });
66
+ break;
67
+ }
68
+ case Verified.UNKNOWN: {
69
+ summary.undecided += 1;
70
+ // A record written before `reason` existed has none, and must not be read as though it did:
71
+ // counting it under an owner would invent an attribution nobody recorded.
72
+ const reason = knownReason(verdict.reason);
73
+ const owner = reason === undefined ? undefined : verdictAttributionOf(reason);
74
+ if (owner !== undefined && VerdictAttribution.NONE !== owner) {
75
+ summary.undecidedBy[owner] = (summary.undecidedBy[owner] ?? 0) + 1;
76
+ }
77
+ break;
78
+ }
79
+ case Verified.NO_FAULT:
80
+ summary.nothingToProve += 1;
81
+ break;
82
+ }
83
+ }
84
+ return summary;
85
+ }
@@ -35,7 +35,10 @@ const CHECK_GLYPH = {
35
35
  [Verified.NO_FAULT]: '–',
36
36
  };
37
37
  function checkLine(c) {
38
- return ` ${CHECK_GLYPH[c.status]} ${c.kind}: ${c.predicate}`;
38
+ // No kind, no prefix. A check folded from a journal that never recorded one has nothing to name
39
+ // here, and printing a placeholder would read as a kind.
40
+ const read = c.kind === undefined ? '' : `${c.kind}: `;
41
+ return ` ${CHECK_GLYPH[c.status]} ${read}${c.predicate}`;
39
42
  }
40
43
  function riskLine(r) {
41
44
  return ` ⚠ ${r.surface} (${r.severity})${r.gated ? ' [GATED]' : ''} — ${r.detail}`;
@@ -22,8 +22,13 @@ export declare const OVP_ARTIFACT_VERSION = 1;
22
22
  export interface ExportedCheck {
23
23
  /** What was claimed, as the person or agent wrote it. */
24
24
  readonly claim: string;
25
- /** Which source of truth answering it required. */
26
- readonly reads: PredicateKind;
25
+ /**
26
+ * Which source of truth answering it required.
27
+ *
28
+ * Absent when the run did not record one -- which is the same rule the rest of this file follows:
29
+ * a kind nobody wrote down is left out, never filled in with a plausible one.
30
+ */
31
+ readonly reads?: PredicateKind;
27
32
  /**
28
33
  * Was the claim written down before the action, or after it?
29
34
  *
@@ -31,7 +31,7 @@ function exportedChecks(run) {
31
31
  for (const check of run.checks) {
32
32
  decided.push({
33
33
  claim: check.predicate,
34
- reads: check.kind,
34
+ ...(check.kind === undefined ? {} : { reads: check.kind }),
35
35
  verdict: check.status,
36
36
  // Spread, so a value the run did not record leaves the key out rather than writing a
37
37
  // comfortable default. `declaredBeforeActing: false` says the claim came afterwards; absent
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import {} from '@reticlehq/core';
3
3
  import { runContextFor } from './artifact/run-context.js';
4
+ import { gapSummary } from './artifact/gap-summary.js';
4
5
  import { openSessionIntents } from '../../memory/intent/open-intents.js';
5
6
  import { ReticleTool } from '@reticlehq/core';
6
7
  import { sessionIdShape } from '../../surface/tools/tool-kit.js';
@@ -27,9 +28,13 @@ const CONTEXT_OUTPUT_SCHEMA = {
27
28
  proven: z
28
29
  .array(z.unknown())
29
30
  .describe('Claims a verdict already settled, each `{ claim, verified, source?, doc?, epoch? }`. Read this before re-driving something: re-proving it is slow, and assuming it is a false green.'),
31
+ gap: z
32
+ .object({})
33
+ .passthrough()
34
+ .describe('The distance between what was claimed and what held, over THIS session: `{ claims, held, failed, undecided, nothingToProve, undecidedBy, falseGreensCaught, failures }`. `undecidedBy` says WHO can act on each unknown — environment (wait), code (fix the app), harness (fix Reticle or the call), could-not-see (look again). Folded from the same journal as everything else here, so it cannot disagree with it.'),
30
35
  remaining: z
31
36
  .array(z.string())
32
- .describe('The intents from .reticle/intent.json that no verdict has discharged. Derived from the ledger, never a guess at what you meant to do next.'),
37
+ .describe('The intents from .reticle/intent/ that no verdict has discharged. Derived from the ledger, never a guess at what you meant to do next.'),
33
38
  };
34
39
  /** The ledger and the live page state this run is folded out of. `[]`/undefined when nothing is connected. */
35
40
  async function evidenceFor(deps, sessionId) {
@@ -57,14 +62,27 @@ async function evidenceFor(deps, sessionId) {
57
62
  export const CONTEXT_TOOLS = [
58
63
  {
59
64
  name: ReticleTool.CONTEXT,
60
- description: 'What THIS run has already established, so you do not rediscover it. Call it when your own copy is gone: right after a compaction, at the top of a fresh sub-agent, or at the start of a turn you did not begin. Returns `established` (what Reticle OBSERVED, with the source file:line where one was reported), `proven` (claims a verdict already settled, so you neither re-prove them nor assume them) and `remaining` (the intents from .reticle/intent.json that nothing has discharged). It is a FOLD over the journal, never a second store, so it cannot disagree with the ledger. Bounded and superseding rather than accumulating, and anything observed under a replaced document or before your last source edit is already dropped rather than presented as current. Only what Reticle observed goes in: it never reports what you intended or believed.',
65
+ description: 'What THIS run has already established, so you do not rediscover it. Call it when your own copy is gone: right after a compaction, at the top of a fresh sub-agent, or at the start of a turn you did not begin. Returns `established` (what Reticle OBSERVED, with the source file:line where one was reported), `proven` (claims a verdict already settled, so you neither re-prove them nor assume them) and `remaining` (the intents from .reticle/intent/ that nothing has discharged). It is a FOLD over the journal, never a second store, so it cannot disagree with the ledger. Bounded and superseding rather than accumulating, and anything observed under a replaced document or before your last source edit is already dropped rather than presented as current. Only what Reticle observed goes in: it never reports what you intended or believed.',
61
66
  example: {},
62
67
  inputSchema: { ...sessionIdShape },
63
68
  outputSchema: CONTEXT_OUTPUT_SCHEMA,
64
69
  handler: async (deps, args) => {
65
70
  const sessionId = asString(args['sessionId']);
66
71
  const evidence = await evidenceFor(deps, sessionId);
67
- return runContextFor({ ...evidence, intents: await openSessionIntents(deps, sessionId) });
72
+ const context = runContextFor({
73
+ ...evidence,
74
+ intents: await openSessionIntents(deps, sessionId),
75
+ });
76
+ /*
77
+ * The gap rides on `reticle_context` rather than on a tool of its own.
78
+ *
79
+ * This is the one call an agent makes when it needs to know what the run has already settled,
80
+ * which is exactly the moment "and what did NOT settle, and whose problem each of those is"
81
+ * is worth reading. It is folded from the same journal the rest of this response is folded
82
+ * from, so it costs one more pass over an array already in hand and cannot disagree with the
83
+ * `proven` list beside it.
84
+ */
85
+ return { ...context, gap: gapSummary(evidence.actions) };
68
86
  },
69
87
  },
70
88
  ];
@@ -24,7 +24,7 @@
24
24
  */
25
25
  import { isValidRunId } from '../../memory/project/dir/reticle-dir.js';
26
26
  import { defaultRunId } from './runner-port.js';
27
- import { JournalVerdictEffectSchema, RunAgentKind, PredicateKind, RunFramework, RunProfile, RunTrigger, } from '@reticlehq/core';
27
+ import { JournalVerdictEffectSchema, RunAgentKind, RunFramework, RunProfile, RunTrigger, } from '@reticlehq/core';
28
28
  import { withCorrections } from './late-answer.js';
29
29
  /** The author of record when no MCP peer introduced itself. Mirrors verification-sync's default. */
30
30
  const UNNAMED_AGENT = 'reticle-mcp';
@@ -77,13 +77,18 @@ export function driveRunFrom(actions, deps) {
77
77
  const checks = [];
78
78
  for (const verdict of found) {
79
79
  checks.push({
80
- kind: PredicateKind.ELEMENT,
81
80
  predicate: verdict.claim,
82
81
  status: verdict.verified,
83
82
  ...(verdict.source === undefined ? {} : { evidence: { source: verdict.source } }),
84
83
  // Carried through rather than recomputed. These were established at the moment the verdict
85
84
  // was made and written down then; a run built later cannot know any of them, and inferring
86
85
  // them here would be inventing evidence about evidence.
86
+ //
87
+ // `kind` was the one field that rule was not applied to: it was stamped `element` on every
88
+ // check ever folded, including the ones whose `grade` in the same object said `net`. A
89
+ // journal old enough to have no kind now produces a check with no kind, which is the honest
90
+ // answer -- a missing field, rather than a wrong one nothing downstream can question.
91
+ ...(verdict.kind === undefined ? {} : { kind: verdict.kind }),
87
92
  ...(verdict.declaredBeforeActing === undefined
88
93
  ? {}
89
94
  : { declaredBeforeActing: verdict.declaredBeforeActing }),
@@ -1,4 +1,4 @@
1
- import { type FlowReplayResult } from '@reticlehq/core';
1
+ import { type ProjectId, type FlowReplayResult } from '@reticlehq/core';
2
2
  import type { ToolDeps } from '../../surface/tools/tool-kit.js';
3
3
  /** A replay plus the wall-clock time it took — the shape the verify handler already collects. */
4
4
  export interface TimedReplay {
@@ -10,4 +10,4 @@ export interface TimedReplay {
10
10
  * tool — a disk or network failure is logged and swallowed so the verdict the agent asked for is
11
11
  * unaffected. Returns the runId (for logging/tests); undefined if nothing was produced (empty suite).
12
12
  */
13
- export declare function persistAndSyncVerificationRun(deps: ToolDeps, timed: TimedReplay[], projectId: string | undefined): Promise<string | undefined>;
13
+ export declare function persistAndSyncVerificationRun(deps: ToolDeps, timed: TimedReplay[], projectId: ProjectId | undefined): Promise<string | undefined>;
@@ -18,6 +18,7 @@ import { RunStore } from './artifact/run-store.js';
18
18
  import { cloudFetch, syncRunToCloud, SyncOutcome } from '../../memory/cloud/cloud-sync.js';
19
19
  import { resolveProjectCloud } from '../../memory/cloud/cloud-config.js';
20
20
  import { log } from '../../log.js';
21
+ import { rootForProjectId } from '../../memory/project/session-root.js';
21
22
  /** The author of record when no MCP peer introduced itself — a CLI run, or a client that skipped the handshake. */
22
23
  const RETICLE_MCP_AGENT_ID = 'reticle-mcp';
23
24
  /** Assemble the ReticleVerificationRun artifact for a verify suite (pure — no IO). */
@@ -60,9 +61,15 @@ export async function persistAndSyncVerificationRun(deps, timed, projectId) {
60
61
  if (0 === timed.length)
61
62
  return undefined;
62
63
  let run;
64
+ // The project the suite ran for, not the directory the daemon was started in. Both halves below
65
+ // take it: the artifact `reticle_run` reads back through `sessionRoot`, and the cloud link that
66
+ // decides WHICH DASHBOARD this run is pushed to. The daemon's own directory has no link file, so
67
+ // a misrouted read silently meant "not attached" — and where it DID have one, the run was pushed
68
+ // to a dashboard belonging to whoever that checkout was linked to.
69
+ const root = rootForProjectId(deps, projectId);
63
70
  try {
64
71
  run = assembleRun(deps, timed, projectId);
65
- await new RunStore(deps.fs, deps.reticleRoot).write(run);
72
+ await new RunStore(deps.fs, root).write(run);
66
73
  }
67
74
  catch (error) {
68
75
  log('verification-run-persist-failed', {
@@ -71,7 +78,7 @@ export async function persistAndSyncVerificationRun(deps, timed, projectId) {
71
78
  return undefined;
72
79
  }
73
80
  // Per-project cloud: only push when THIS project has cloud attached AND its policy allows runs.
74
- const cloud = await resolveProjectCloud(deps.fs, deps.reticleRoot, homedir(), process.env);
81
+ const cloud = await resolveProjectCloud(deps.fs, root, homedir(), process.env);
75
82
  if (null === cloud.config || !cloud.policy.runs)
76
83
  return run.runId; // not attached / runs disabled → local only
77
84
  const result = await syncRunToCloud(run, cloud.config, cloudFetch);
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { ReticleTool } from '@reticlehq/core';
3
3
  import { loadNamedFlows, resolveChangedFiles } from '../../command/cli/cli-flow-commands.js';
4
+ import { projectDirFor } from '../../memory/project/session-root.js';
4
5
  import { sessionRoot, sessionProjectId } from '../../memory/project/session-root.js';
5
6
  import { affectedSavedFlows } from './change/flow-sources.js';
6
7
  /**
@@ -44,9 +45,11 @@ export const AFFECTED_TOOLS = [
44
45
  ? args['files'].filter((f) => 'string' === typeof f)
45
46
  : [];
46
47
  const since = 'string' === typeof args['since'] ? args['since'] : undefined;
47
- // Same address as verify_change, resolved the same way: `deps.reticleRoot` is the configured
48
- // project directory (the daemon's cwd is not), and the session names which project's flows.
49
- const changed = await resolveChangedFiles(files, since, deps.reticleRoot);
48
+ // Same address as verify_change, resolved the same way. `deps.reticleRoot` is NOT the project
49
+ // directory this line used to claim it was — it is the daemon's `.reticle` subdirectory, in
50
+ // whichever tree the MCP host was started in. `undefined` here resolves the single connected
51
+ // session, which is the same rule the flow lookup below already follows.
52
+ const changed = await resolveChangedFiles(files, since, projectDirFor(deps, undefined));
50
53
  const changedFiles = changed.files;
51
54
  // No `sessionId` on this tool's surface, and it does not need one: passing `undefined`
52
55
  // resolves the single connected session, and falls back exactly as before when it cannot.
@@ -1,19 +1,4 @@
1
1
  import { type Annotation, type AnnotateOutcome } from '@reticlehq/core';
2
- /**
3
- * The PURE compiler at the heart of the annotation facet. A structured annotation +
4
- * the current captured-step count → an AnnotateOutcome (a result envelope + the patch to apply to
5
- * the AnnotationStore). No IO, no clock, unit-testable in isolation.
6
- *
7
- * assert-signal → step.expect.signal (+ signalData) on the LAST step (needs ≥1 step)
8
- * assert-visible → step.expect.element.testid on the LAST step (needs ≥1 step)
9
- * mark-dynamic → flow.dynamic[] += testid flow-level, allowed with 0 steps
10
- * success-state → flow.success = { signal | state | net | console | element | text } flow-level,
11
- * resolved in that precedence order (a consequence beats a presence check)
12
- *
13
- * FIRST CUT: only the four structured kinds above. Free natural-language annotation → predicate
14
- * compilation is explicitly FUTURE — an NL string never reaches here (AnnotationSchema
15
- * rejects it upstream; the tool maps that to UNKNOWN_KIND). No NL parser exists or is faked.
16
- */
17
2
  export declare function compileAnnotation(a: Annotation, stepCount: number): AnnotateOutcome;
18
3
  /**
19
4
  * Human-readable confirmation text for the recorder strip / tool result,