@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
@@ -93,6 +93,11 @@ const COMMON_TLDS = new Set([
93
93
  'in',
94
94
  'eu',
95
95
  ]);
96
+ /**
97
+ * One path separator in every spelling that a report can carry: `/` and `\`, and the JSON-escaped
98
+ * forms `\/`, `\\` and `\\/`. An agent that pastes a JSON string doubles each backslash.
99
+ */
100
+ const PATH_SEP = String.raw `(?:\\{0,2}\/|\\{1,2})`;
96
101
  /**
97
102
  * The shapes that leak. Ordered most-specific first — a URL carrying inline credentials must be
98
103
  * caught as a URL before the bare-token rule chews the middle out of it.
@@ -117,22 +122,48 @@ const REDACTIONS = [
117
122
  // Credential assignments: the KEY stays (it is the useful part), the VALUE goes. The auth SCHEME
118
123
  // (`Bearer`, `Basic`, `Token`) is consumed as part of the value, not left as the value — matching
119
124
  // only `\S+` after the separator ate the word "Bearer" and published the secret right behind it.
125
+ // A linking verb is skipped too: "my password is hunter2" lost the word "is" and kept hunter2.
126
+ {
127
+ pattern: /\b(authorization|api[-_]?key|secret|token|password|passwd|pwd)\b(?:\s*[:=]\s*|\s+(?:(?:is|was|=|:)\s+)?)(?:(?:bearer|basic|token|digest)\s+)?\S+/gi,
128
+ label: 'credential-assignment',
129
+ },
130
+ // An environment-style assignment: `STRIPE_SECRET_KEY=…`, `AWS_SECRET_ACCESS_KEY=…`, `DB_PASS: …`.
131
+ // `\b` does not end a word at `_`, so the rule above never saw these. The sensitive word must be
132
+ // one whole `_` segment of the name, so `PASSPORT_ID` or `TOKENIZER_MODE` stay.
120
133
  {
121
- pattern: /\b(authorization|api[-_]?key|secret|token|password|passwd|pwd)\b(?:\s*[:=]\s*|\s+)(?:(?:bearer|basic|token|digest)\s+)?\S+/gi,
134
+ pattern: /\b((?:[A-Za-z0-9]+_)*(?:SECRET|TOKEN|PASS|PASSWORD|PASSWD|PWD|PASSPHRASE|API_?KEY|PRIVATE_?KEY|ACCESS_?KEY|AUTH|CREDENTIALS?)(?:_[A-Za-z0-9]+)*)\s*[:=]\s*\S+/gi,
122
135
  label: 'credential-assignment',
123
136
  },
124
- // Vendor key formats that are self-identifying (sk-…, ghp_…, AKIA…, xoxb-…, eyJ… JWTs).
137
+ // Vendor key formats that are self-identifying (sk-…, sk_live_…, ghp_…, AKIA…, xoxb-…, eyJ… JWTs).
125
138
  { pattern: /\b(?:sk|pk|rk)-[A-Za-z0-9_-]{16,}\b/g, label: 'vendor-key' },
139
+ { pattern: /\b(?:sk|pk|rk)_(?:live|test)_[A-Za-z0-9]{10,}\b/g, label: 'vendor-key' },
126
140
  { pattern: /\bgh[pousr]_[A-Za-z0-9]{20,}\b/g, label: 'github-token' },
127
- { pattern: /\bAKIA[0-9A-Z]{16}\b/g, label: 'aws-key' },
141
+ { pattern: /\bgithub_pat_[A-Za-z0-9_]{20,}\b/g, label: 'github-token' },
142
+ { pattern: /\bglpat-[A-Za-z0-9_-]{20,}\b/g, label: 'gitlab-token' },
143
+ { pattern: /\bAIza[0-9A-Za-z_-]{35}\b/g, label: 'google-key' },
144
+ { pattern: /\b(?:AKIA|ASIA)[0-9A-Z]{16}\b/g, label: 'aws-key' },
128
145
  { pattern: /\bxox[baprs]-[A-Za-z0-9-]{10,}\b/g, label: 'slack-token' },
129
146
  { pattern: /\beyJ[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\.[A-Za-z0-9_-]{10,}\b/g, label: 'jwt' },
147
+ // A payment card: 13 to 19 digits, spaces or dashes allowed, that pass the Luhn check. An id or a
148
+ // millisecond timestamp rarely starts with 2 to 6 AND passes Luhn, so those stay.
149
+ {
150
+ pattern: /\b[2-6](?:[ -]?\d){12,18}\b/g,
151
+ label: 'card-number',
152
+ replace: (digits) => (luhnValid(digits.replace(/\D/g, '')) ? REDACTED : digits),
153
+ },
154
+ // A phone number: an international `+` number, or a ten-digit (123) 456-7890 shape.
155
+ {
156
+ pattern: /(?<![\w+])\+\d[\d ().-]{6,18}\d(?!\w)/g,
157
+ label: 'phone',
158
+ replace: (number) => (8 <= number.replace(/\D/g, '').length ? REDACTED : number),
159
+ },
160
+ { pattern: /(?<![\w(])\(?\d{3}\)?[ .-]\d{3}[ .-]\d{4}\b/g, label: 'phone' },
130
161
  // Home directories carry the account name, and a trace is full of them. The name runs to the next
131
162
  // separator, quote or line end, NOT the next space: `C:\Users\Jane Doe\…` stopped at the space and
132
163
  // sent the surname. Then the rest of the path goes with it. Over-redacting a sentence that follows
133
164
  // a bare home directory is the price, and it is the right way round.
134
165
  {
135
- pattern: /(?:\\\\\?\\)?(?:\/Users\/|\/home\/|[A-Za-z]:[\\/]Users[\\/])[^\\/\r\n"'`]+(?:[\\/][^\s\\/"'`]*)*/g,
166
+ pattern: new RegExp(String.raw `(?:\\\\\?\\)?(?:${PATH_SEP}(?:Users|home)${PATH_SEP}|[A-Za-z]:${PATH_SEP}Users${PATH_SEP})[^\\/\r\n"'${'`'}]+(?:[\\/][^\s\\/"'${'`'}]*)*`, 'gi'),
136
167
  label: 'home-path',
137
168
  },
138
169
  // Any other absolute path: a Windows one (segments may hold spaces when a separator follows)...
@@ -164,6 +195,20 @@ const REDACTIONS = [
164
195
  },
165
196
  },
166
197
  ];
198
+ /** The Luhn checksum every payment card number carries. */
199
+ function luhnValid(digits) {
200
+ let sum = 0;
201
+ for (let i = 0; i < digits.length; i++) {
202
+ let d = Number(digits[digits.length - 1 - i]);
203
+ if (1 === i % 2) {
204
+ d *= 2;
205
+ if (9 < d)
206
+ d -= 9;
207
+ }
208
+ sum += d;
209
+ }
210
+ return 0 === sum % 10;
211
+ }
167
212
  /** Strip credential/PII shapes and cap the length. Pure — the tests read like a spec of what leaks. */
168
213
  export function redactFeedbackText(input, max) {
169
214
  const removed = new Set();
@@ -284,6 +329,8 @@ export async function submitFeedback(input, opts = {}) {
284
329
  ...Object.fromEntries([...redactions].filter(([, r]) => r.text !== '').map(([key, r]) => [key, r.text])),
285
330
  text: body.text,
286
331
  ...(input.rating !== undefined ? { rating: input.rating } : {}),
332
+ // Not redacted: the person gave this address so the maintainers can answer. Sent only then.
333
+ ...(input.contact !== undefined ? { contact: input.contact } : {}),
287
334
  ...context,
288
335
  });
289
336
  if (!parsed.success) {
@@ -1,4 +1,4 @@
1
- import { HarnessRunSource, type HarnessRun } from '@reticlehq/core/telemetry';
1
+ import { HarnessRunReason, HarnessRunSource, type HarnessRun } from '@reticlehq/core/telemetry';
2
2
  import { DriveOrigin, DriveStatus } from '../features/harness/drive-runs.js';
3
3
  import { type Telemetry } from './telemetry.js';
4
4
  export interface HarnessRunStart {
@@ -8,11 +8,11 @@ export interface HarnessRunStart {
8
8
  /** Who started it. A saved plan is a plan whoever pressed Run. */
9
9
  export declare function harnessRunSource(origin: DriveOrigin, planId: string | undefined): HarnessRunSource;
10
10
  /** How a finished run ended, from what the registry recorded. */
11
- export declare function harnessRunEnd(status: DriveStatus, result: Record<string, unknown> | undefined): Pick<HarnessRun, 'outcome' | 'journeys' | 'replayed'>;
11
+ export declare function harnessRunEnd(status: DriveStatus, result: Record<string, unknown> | undefined, reason?: HarnessRunReason): Pick<HarnessRun, 'outcome' | 'journeys' | 'replayed' | 'reason'>;
12
12
  /** Report the run's start, run it, report its end, and hand back exactly what it did. */
13
13
  export declare function reportHarnessRun<T extends {
14
14
  status: DriveStatus;
15
15
  result: Record<string, unknown>;
16
16
  }>(start: HarnessRunStart, run: () => Promise<T>, refused: (error: unknown) => boolean, telemetry?: Pick<Telemetry, 'emit'>): Promise<T>;
17
17
  /** A run the gate refused before it could start: still somebody who asked for one. */
18
- export declare function reportHarnessBlocked(start: HarnessRunStart, telemetry?: Pick<Telemetry, 'emit'>): void;
18
+ export declare function reportHarnessBlocked(start: HarnessRunStart, reason: HarnessRunReason, telemetry?: Pick<Telemetry, 'emit'>): void;
@@ -10,8 +10,8 @@
10
10
  */
11
11
  import { asRecord } from '@reticlehq/core';
12
12
  import { JourneyBy } from '@reticlehq/core/artifacts';
13
- import { HarnessRunOutcome, HarnessRunPhase, HarnessRunSource, TelemetryEventKind, countBucket, } from '@reticlehq/core/telemetry';
14
- import { DriveOrigin, DriveStatus } from '../features/harness/drive-runs.js';
13
+ import { HarnessRunOutcome, HarnessRunPhase, HarnessRunReason, HarnessRunSource, TelemetryEventKind, countBucket, } from '@reticlehq/core/telemetry';
14
+ import { DriveOrigin, DriveRefusedError, DriveStatus } from '../features/harness/drive-runs.js';
15
15
  import { getTelemetry } from './telemetry.js';
16
16
  const SOURCE_OF = {
17
17
  [DriveOrigin.AGENT]: HarnessRunSource.AGENT,
@@ -24,7 +24,7 @@ export function harnessRunSource(origin, planId) {
24
24
  return planId === undefined ? SOURCE_OF[origin] : HarnessRunSource.PLAN;
25
25
  }
26
26
  /** How a finished run ended, from what the registry recorded. */
27
- export function harnessRunEnd(status, result) {
27
+ export function harnessRunEnd(status, result, reason) {
28
28
  const journeys = Array.isArray(result?.['journeys']) ? result['journeys'] : undefined;
29
29
  const replayed = (journeys ?? []).filter((j) => JourneyBy.REPLAY === asRecord(j)['by']).length;
30
30
  const outcome = DriveStatus.REFUSED === status
@@ -38,7 +38,18 @@ export function harnessRunEnd(status, result) {
38
38
  : HarnessRunOutcome.NOT_PROVED;
39
39
  // An unplanned drive is one journey; a refused one drove none.
40
40
  const count = journeys?.length ?? (HarnessRunOutcome.BLOCKED === outcome ? 0 : 1);
41
- return { outcome, journeys: countBucket(count), replayed: countBucket(replayed) };
41
+ // Why it did not drive: only a blocked or failed run has a reason, and a break names itself.
42
+ const why = HarnessRunOutcome.BLOCKED === outcome
43
+ ? (reason ?? HarnessRunReason.OTHER)
44
+ : HarnessRunOutcome.FAILED === outcome
45
+ ? (reason ?? HarnessRunReason.BROKEN)
46
+ : undefined;
47
+ return {
48
+ outcome,
49
+ journeys: countBucket(count),
50
+ replayed: countBucket(replayed),
51
+ ...(why === undefined ? {} : { reason: why }),
52
+ };
42
53
  }
43
54
  function emit(telemetry, harness) {
44
55
  try {
@@ -64,17 +75,17 @@ export async function reportHarnessRun(start, run, refused, telemetry = getTelem
64
75
  emit(telemetry, {
65
76
  phase: HarnessRunPhase.COMPLETED,
66
77
  ...start,
67
- ...harnessRunEnd(refused(error) ? DriveStatus.REFUSED : DriveStatus.BROKEN, undefined),
78
+ ...harnessRunEnd(refused(error) ? DriveStatus.REFUSED : DriveStatus.BROKEN, undefined, error instanceof DriveRefusedError ? error.reason : undefined),
68
79
  });
69
80
  throw error;
70
81
  }
71
82
  }
72
83
  /** A run the gate refused before it could start: still somebody who asked for one. */
73
- export function reportHarnessBlocked(start, telemetry = getTelemetry()) {
84
+ export function reportHarnessBlocked(start, reason, telemetry = getTelemetry()) {
74
85
  emit(telemetry, { phase: HarnessRunPhase.STARTED, ...start });
75
86
  emit(telemetry, {
76
87
  phase: HarnessRunPhase.COMPLETED,
77
88
  ...start,
78
- ...harnessRunEnd(DriveStatus.REFUSED, undefined),
89
+ ...harnessRunEnd(DriveStatus.REFUSED, undefined, reason),
79
90
  });
80
91
  }
@@ -4,7 +4,7 @@
4
4
  * order; these say how often and by whom, which a window summed across a session cannot.
5
5
  *
6
6
  * Sent by the daemon, like every HUD measure, so every opt-out applies, and only from the names the
7
- * wire schema already narrowed. The dedupe (per tab, per page or surface) lives in `HudMetrics`.
7
+ * wire schema already narrowed. The dedupe (per daemon, per page or surface) lives in `HudMetrics`.
8
8
  */
9
9
  import type { HudUseData } from '@reticlehq/core';
10
10
  import { type Telemetry } from './telemetry.js';
@@ -26,13 +26,16 @@ export interface HudSummary {
26
26
  /** Times each rail slide became the visible one. Slide ids are Reticle's own, never page text. */
27
27
  hudSlides?: Record<string, number>;
28
28
  }
29
- /** The same page opened again on the same tab within this long is one view, not two. */
29
+ /**
30
+ * The same page opened again within this long is one view, not two. Per daemon, not per tab: a page
31
+ * reload makes a new tab id, and a page that reloads in a loop is still one person on one page.
32
+ */
30
33
  export declare const HUD_VIEW_DEDUPE_MS = 30000;
31
34
  /** What one HUD use means for the per-event signals, beside what it adds to the summary. */
32
35
  export interface HudSignals {
33
- /** A page this tab had not opened within the dedupe window. */
36
+ /** A page not opened within the dedupe window. */
34
37
  viewed?: HudPanel;
35
- /** A sign-in prompt this tab had not shown before. */
38
+ /** A sign-in prompt this daemon had not shown before. */
36
39
  prompted?: HudPromptSurface;
37
40
  /** Tabs with a HUD right now. */
38
41
  tabs: number;
@@ -16,7 +16,10 @@ export const HUD_JOURNEY_MAX = 60;
16
16
  /** Distinct slide ids counted per window; past this a broken notices file is not a dashboard. */
17
17
  const MAX_SLIDE_IDS = 20;
18
18
  const SLIDE_ID = /^[a-z0-9-]{1,56}$/;
19
- /** The same page opened again on the same tab within this long is one view, not two. */
19
+ /**
20
+ * The same page opened again within this long is one view, not two. Per daemon, not per tab: a page
21
+ * reload makes a new tab id, and a page that reloads in a loop is still one person on one page.
22
+ */
20
23
  export const HUD_VIEW_DEDUPE_MS = 30_000;
21
24
  /** A tab whose page reported HUD use without saying which tab: an older caller, or a test. */
22
25
  const UNNAMED_TAB = '';
@@ -28,6 +31,10 @@ export class HudMetrics {
28
31
  #journey = [];
29
32
  #slides = new Map();
30
33
  #tabs = new Map();
34
+ /** When each page last counted as a view. Daemon-lifetime: a window reset keeps it. */
35
+ #viewedAt = new Map();
36
+ /** The prompts already reported. Daemon-lifetime, like the views. */
37
+ #prompted = new Set();
31
38
  #cut = false;
32
39
  /** Did anything happen this window. A HUD merely sitting open is not worth a flush of its own. */
33
40
  #changed = false;
@@ -37,8 +44,8 @@ export class HudMetrics {
37
44
  record(use, tabId = UNNAMED_TAB) {
38
45
  const tab = this.#tab(tabId);
39
46
  const signals = { tabs: this.#tabs.size };
40
- if (use.prompt !== undefined && !tab.prompted.has(use.prompt)) {
41
- tab.prompted.add(use.prompt);
47
+ if (use.prompt !== undefined && !this.#prompted.has(use.prompt)) {
48
+ this.#prompted.add(use.prompt);
42
49
  signals.prompted = use.prompt;
43
50
  }
44
51
  // A control the HUD never rendered is dropped here, the one place HUD use is counted, so free
@@ -53,6 +60,7 @@ export class HudMetrics {
53
60
  const key = use.toggle === undefined ? control : `${control}:${use.toggle}`;
54
61
  this.#controls.set(key, (this.#controls.get(key) ?? 0) + 1);
55
62
  this.#step(key);
63
+ tab.pressed = true;
56
64
  }
57
65
  const at = this.#now();
58
66
  const since = tab.hidden ? undefined : at;
@@ -62,13 +70,18 @@ export class HudMetrics {
62
70
  this.#step(`view:${use.view}`);
63
71
  }
64
72
  if (use.panel !== undefined && use.panel !== tab.panel?.value) {
73
+ // The HUD opens the Agent Log by itself when an agent acts, or on load when the person left it
74
+ // open. No press came first, so it is not a choice and not a view. Its time still counts in
75
+ // `hudPanelMs`.
76
+ const opensByItself = HudPanel.CHAT === use.panel && !tab.pressed;
77
+ tab.pressed = false;
65
78
  this.#close(tab.panel, this.#panelMs);
66
79
  tab.panel = { value: use.panel, since };
67
80
  if (use.panel !== HudPanel.NONE) {
68
81
  this.#step(`panel:${use.panel}`);
69
- const last = tab.viewedAt.get(use.panel);
70
- if (last === undefined || at - last >= HUD_VIEW_DEDUPE_MS) {
71
- tab.viewedAt.set(use.panel, at);
82
+ const last = this.#viewedAt.get(use.panel);
83
+ if (!opensByItself && (last === undefined || at - last >= HUD_VIEW_DEDUPE_MS)) {
84
+ this.#viewedAt.set(use.panel, at);
72
85
  signals.viewed = use.panel;
73
86
  }
74
87
  }
@@ -111,8 +124,7 @@ export class HudMetrics {
111
124
  view: undefined,
112
125
  panel: undefined,
113
126
  hidden: false,
114
- viewedAt: new Map(),
115
- prompted: new Set(),
127
+ pressed: false,
116
128
  };
117
129
  this.#tabs.set(tabId, tab);
118
130
  return tab;
@@ -11,7 +11,7 @@
11
11
  * WHICH CHANNELS ARE GENUINELY DETECTABLE TODAY, so nobody later reads a small `unknown` as success:
12
12
  * - `plugin` — real. The Claude Code plugin registers the MCP server itself and can set the marker
13
13
  * in that server's `env`, so it is carried by the process without anybody typing anything.
14
- * - `skill_file` / `npx_skill` / `docs_site` / `readme` — real ONLY where that channel's own copy
14
+ * - `skill_file` / `npx_skill` / `docs_site` / `readme` / `blog` — real ONLY where that channel's own copy
15
15
  * of the install command carries the marker. Each is a separately published artifact, so a copy
16
16
  * that has not been updated is indistinguishable from no channel at all.
17
17
  * - `cli_direct` — NOT detectable. Nobody types a marker to say they typed a command. It exists so
@@ -1,4 +1,4 @@
1
1
  export declare function markDaemonStart(now: number): void;
2
- export declare function reportMcpConnected(client?: string, now?: () => number): void;
2
+ export declare function reportMcpConnected(client?: string, attachId?: string, now?: () => number): void;
3
3
  /** Tests only. */
4
4
  export declare function resetMcpConnections(): void;
@@ -13,11 +13,14 @@ import { TelemetryEventKind } from '@reticlehq/core/telemetry';
13
13
  import { getTelemetry } from './telemetry.js';
14
14
  import { appEverConnected } from './app-instrumented.js';
15
15
  let connectsSeen = 0;
16
+ /** The proxies already reported. A proxy sends one id on every connect of its process. */
17
+ const proxiesSeen = new Set();
16
18
  /** Set when the daemon starts, so the FIRST connect can report how long Reticle sat unused. */
17
19
  let daemonStartedAt;
18
20
  export function markDaemonStart(now) {
19
21
  daemonStartedAt = now;
20
22
  connectsSeen = 0;
23
+ proxiesSeen.clear();
21
24
  }
22
25
  /**
23
26
  * Report one client attaching, BY NAME. Best-effort; a metric must never affect whether a client
@@ -32,12 +35,24 @@ export function markDaemonStart(now) {
32
35
  * An unnamed call reports NOTHING. A stream that opens and never completes a handshake is a probe,
33
36
  * not a client attaching, and counting it was what put an unattributable row exactly where the name
34
37
  * belonged.
38
+ *
39
+ * ONCE per proxy. `attachId` is the proxy's own id, and the proxy sends the same id each time it
40
+ * reconnects. A reconnect of a known proxy is the same agent coming back, and an event for each one
41
+ * made this the largest event kind with no new fact in it. The proxy counts its own drops on
42
+ * `mcp_proxy_exited`. An older proxy sends no id, so each of its connects still reports.
35
43
  */
36
44
  /** `connection.client`'s wire cap. */
37
45
  const MAX_CLIENT_NAME = 64;
38
- export function reportMcpConnected(client, now = () => Date.now()) {
39
- if (client === undefined)
46
+ export function reportMcpConnected(client, attachId, now = () => Date.now()) {
47
+ if (client === undefined) {
40
48
  return;
49
+ }
50
+ if (attachId !== undefined) {
51
+ if (proxiesSeen.has(attachId)) {
52
+ return;
53
+ }
54
+ proxiesSeen.add(attachId);
55
+ }
41
56
  try {
42
57
  const reconnect = connectsSeen > 0;
43
58
  connectsSeen += 1;
@@ -56,6 +71,9 @@ export function reportMcpConnected(client, now = () => Date.now()) {
56
71
  // `app_instrumented` sets, never a second counter, so the two halves of the funnel cannot
57
72
  // disagree about one daemon run.
58
73
  appConnected: appEverConnected(),
74
+ // The proxy that attached. Its `mcp_connection_lost` and `mcp_proxy_exited` rows carry the
75
+ // same id and no `sessionId`, so this row is how they join this daemon run.
76
+ ...(attachId === undefined ? {} : { proxyId: attachId }),
59
77
  },
60
78
  });
61
79
  }
@@ -66,5 +84,6 @@ export function reportMcpConnected(client, now = () => Date.now()) {
66
84
  /** Tests only. */
67
85
  export function resetMcpConnections() {
68
86
  connectsSeen = 0;
87
+ proxiesSeen.clear();
69
88
  daemonStartedAt = undefined;
70
89
  }
@@ -1,4 +1,4 @@
1
- import { type OnboardingStep } from '@reticlehq/core';
1
+ import { NextStepOffered, type OnboardingStep } from '@reticlehq/core';
2
2
  /** Report `step` once per process, and only if this machine + project has never reported it. */
3
3
  export declare function reportFirstStep(step: OnboardingStep): void;
4
4
  /** A successful page read. The dispatcher calls this after excluding refusals and pauses. */
@@ -44,6 +44,11 @@ export declare function noteDriven(): void;
44
44
  * took: it fired on every verdict, so a busy session put hundreds of first-run steps in the funnel.
45
45
  */
46
46
  export declare function noteVerdictProduced(elapsedMs: number): void;
47
+ export declare function noteNextStepOffered(offered: NextStepOffered, wired: () => boolean): void;
48
+ /** Called on every agent call, before its handler runs. Closes an open offer, once. */
49
+ export declare function noteNextCall(tool: string, args: Record<string, unknown>): void;
50
+ /** Tests only: forget an open offer. */
51
+ export declare function resetNextStepOffered(): void;
47
52
  /** Arm again for the next daemon run — the tests' seam, mirroring resetAppInstrumented. */
48
53
  export declare function resetOnboardingFirsts(): void;
49
54
  /**
@@ -1,4 +1,4 @@
1
- import { ActionType, OnboardingPhase, OnboardingStepStatus, ReticleTool, } from '@reticlehq/core';
1
+ import { ActionType, NextStepOffered, OnboardingPhase, OnboardingStepStatus, ReticleTool, } from '@reticlehq/core';
2
2
  import { mkdirSync, writeFileSync } from 'node:fs';
3
3
  import { homedir } from 'node:os';
4
4
  import { join } from 'node:path';
@@ -124,6 +124,46 @@ export function noteVerdictProduced(elapsedMs) {
124
124
  elapsedMs: Math.max(0, Math.round(elapsedMs)),
125
125
  });
126
126
  }
127
+ // ponytail: one pending offer per daemon, not per agent. Two agents in two unwired projects at the
128
+ // same moment can close each other's offer. Key it by attach id if the data shows that case.
129
+ let pending;
130
+ const STEP = 'next_step_offered';
131
+ const ACQUIRE = 'acquire';
132
+ export function noteNextStepOffered(offered, wired) {
133
+ pending = { offered, wired };
134
+ void reportOnboardingStep({
135
+ phase: OnboardingPhase.FIRST_RUN,
136
+ step: STEP,
137
+ status: OnboardingStepStatus.STARTED,
138
+ offered,
139
+ });
140
+ }
141
+ /** Called on every agent call, before its handler runs. Closes an open offer, once. */
142
+ export function noteNextCall(tool, args) {
143
+ const offer = pending;
144
+ if (offer === undefined) {
145
+ return;
146
+ }
147
+ pending = undefined;
148
+ void reportOnboardingStep({
149
+ phase: OnboardingPhase.FIRST_RUN,
150
+ step: STEP,
151
+ status: OnboardingStepStatus.COMPLETED,
152
+ offered: offer.offered,
153
+ nextFollowed: followed(offer, tool, args),
154
+ });
155
+ }
156
+ function followed(offer, tool, args) {
157
+ if (NextStepOffered.LEASE === offer.offered) {
158
+ return (ReticleTool.LEASE_ACQUIRE === tool ||
159
+ (ReticleTool.LEASE === tool && ACQUIRE === args['action']));
160
+ }
161
+ return offer.wired();
162
+ }
163
+ /** Tests only: forget an open offer. */
164
+ export function resetNextStepOffered() {
165
+ pending = undefined;
166
+ }
127
167
  /** Looking: the tools that read the page without changing it. */
128
168
  const LOOK_TOOLS = new Set([
129
169
  ReticleTool.SNAPSHOT,
@@ -1,3 +1,45 @@
1
+ /**
2
+ * The MCP proxy's session rollup.
3
+ *
4
+ * POST socket failures (`ENOBUFS`, `EMFILE`, `ECONNREFUSED` before any bytes were sent) happen in
5
+ * this process, not the daemon's. `tool_refused` never fires (the handler never ran) and
6
+ * `mcp_connection_lost` never fires (the SSE stream is fine). Counts live on SessionMetrics here
7
+ * and leave as one `session_progress` — an existing kind, omitted when nothing happened.
8
+ *
9
+ * The send is awaited. Fire-and-forget microseconds before `process.exit` is how `daemon_stopped`
10
+ * never arrived: the POST was killed every time and nothing threw.
11
+ */
12
+ import { type ProxyExitReason, type WakeRefusalPresence } from '@reticlehq/core/telemetry';
1
13
  import { type SessionMetrics } from './session-metrics.js';
2
14
  import { type Telemetry } from './telemetry.js';
3
15
  export declare function flushProxySessionMetrics(telemetry?: Telemetry, metrics?: SessionMetrics): Promise<void>;
16
+ /**
17
+ * This proxy process's id. The proxy sends it to the daemon on every connect, and the daemon puts
18
+ * it on `mcp_client_connected`. The proxy's own events carry it too, so an outage or an exit joins
19
+ * the daemon run it served. A random UUID for each process: it names nothing on the machine.
20
+ */
21
+ export declare const PROXY_ID: `${string}-${string}-${string}-${string}-${string}`;
22
+ /** The proxy lost its daemon stream. */
23
+ export declare function noteProxyDrop(): void;
24
+ /** The client sent a `tools/call` through the proxy. */
25
+ export declare function noteProxyToolCall(): void;
26
+ /** Reset between tests. A real process reports each of these at most once. */
27
+ export declare function resetProxyExitReporting(): void;
28
+ /**
29
+ * Send `mcp_proxy_exited`, once per process. Awaited by the caller before it exits, because a send
30
+ * that is not awaited before `process.exit` does not arrive. `emit` bounds the send with its own
31
+ * timeout, and it never throws.
32
+ *
33
+ * Sent even when every count is zero: a proxy that left with nothing else to say is the case that
34
+ * was invisible.
35
+ */
36
+ export declare function reportProxyExited(reason: ProxyExitReason, telemetry?: Telemetry, uptimeMs?: number): Promise<void>;
37
+ /** Everything the proxy sends on its way out. Awaited, then the caller exits. */
38
+ export declare function flushProxyExit(reason: ProxyExitReason): Promise<void>;
39
+ /** Send `daemon_died_unclean`. Fire-and-forget is fine for callers: the process lives on. */
40
+ export declare function reportDaemonDiedUnclean(ageMs: number, telemetry?: Telemetry): Promise<void>;
41
+ /**
42
+ * Send `wake_refused`, once per process. A dormant proxy refuses again on every client request, and
43
+ * one event per request would count the client's retries, not the refusal.
44
+ */
45
+ export declare function reportWakeRefused(presence: WakeRefusalPresence, telemetry?: Telemetry): Promise<void>;
@@ -9,7 +9,8 @@
9
9
  * The send is awaited. Fire-and-forget microseconds before `process.exit` is how `daemon_stopped`
10
10
  * never arrived: the POST was killed every time and nothing threw.
11
11
  */
12
- import { TelemetryEventKind } from '@reticlehq/core/telemetry';
12
+ import { TelemetryEventKind, } from '@reticlehq/core/telemetry';
13
+ import { randomUUID } from 'node:crypto';
13
14
  import { getSessionMetrics } from './session-metrics.js';
14
15
  import { getTelemetry } from './telemetry.js';
15
16
  export async function flushProxySessionMetrics(telemetry = getTelemetry(), metrics = getSessionMetrics()) {
@@ -22,3 +23,71 @@ export async function flushProxySessionMetrics(telemetry = getTelemetry(), metri
22
23
  session: metrics.summarize(false),
23
24
  });
24
25
  }
26
+ /**
27
+ * This proxy process's id. The proxy sends it to the daemon on every connect, and the daemon puts
28
+ * it on `mcp_client_connected`. The proxy's own events carry it too, so an outage or an exit joins
29
+ * the daemon run it served. A random UUID for each process: it names nothing on the machine.
30
+ */
31
+ export const PROXY_ID = randomUUID();
32
+ /** What this proxy process saw in its life, for `mcp_proxy_exited`. One proxy per process. */
33
+ let drops = 0;
34
+ let toolCalls = 0;
35
+ let exitReported = false;
36
+ let wakeRefusalReported = false;
37
+ /** The proxy lost its daemon stream. */
38
+ export function noteProxyDrop() {
39
+ drops += 1;
40
+ }
41
+ /** The client sent a `tools/call` through the proxy. */
42
+ export function noteProxyToolCall() {
43
+ toolCalls += 1;
44
+ }
45
+ /** Reset between tests. A real process reports each of these at most once. */
46
+ export function resetProxyExitReporting() {
47
+ drops = 0;
48
+ toolCalls = 0;
49
+ exitReported = false;
50
+ wakeRefusalReported = false;
51
+ }
52
+ /**
53
+ * Send `mcp_proxy_exited`, once per process. Awaited by the caller before it exits, because a send
54
+ * that is not awaited before `process.exit` does not arrive. `emit` bounds the send with its own
55
+ * timeout, and it never throws.
56
+ *
57
+ * Sent even when every count is zero: a proxy that left with nothing else to say is the case that
58
+ * was invisible.
59
+ */
60
+ export async function reportProxyExited(reason, telemetry = getTelemetry(),
61
+ // The process clock, read at this boundary: the proxy's uptime IS the process's.
62
+ uptimeMs = Math.round(process.uptime() * 1000)) {
63
+ if (exitReported) {
64
+ return;
65
+ }
66
+ exitReported = true;
67
+ await telemetry.emit(TelemetryEventKind.MCP_PROXY_EXITED, {
68
+ proxyExit: { reason, uptimeMs, drops, toolCalls, proxyId: PROXY_ID },
69
+ });
70
+ }
71
+ /** Everything the proxy sends on its way out. Awaited, then the caller exits. */
72
+ export async function flushProxyExit(reason) {
73
+ await Promise.allSettled([flushProxySessionMetrics(), reportProxyExited(reason)]);
74
+ }
75
+ /** Send `daemon_died_unclean`. Fire-and-forget is fine for callers: the process lives on. */
76
+ export async function reportDaemonDiedUnclean(ageMs, telemetry = getTelemetry()) {
77
+ await telemetry.emit(TelemetryEventKind.DAEMON_DIED_UNCLEAN, {
78
+ daemonDeath: { ageMs: Math.max(0, Math.round(ageMs)) },
79
+ });
80
+ }
81
+ /**
82
+ * Send `wake_refused`, once per process. A dormant proxy refuses again on every client request, and
83
+ * one event per request would count the client's retries, not the refusal.
84
+ */
85
+ export async function reportWakeRefused(presence, telemetry = getTelemetry()) {
86
+ if (wakeRefusalReported) {
87
+ return;
88
+ }
89
+ wakeRefusalReported = true;
90
+ await telemetry.emit(TelemetryEventKind.WAKE_REFUSED, {
91
+ wakeRefusal: { presence },
92
+ });
93
+ }
@@ -108,7 +108,7 @@ export declare class SessionMetrics {
108
108
  * Zero of these at shutdown means the daemon ran and no app ever connected — a broken install.
109
109
  * Non-zero with no tool calls is the opposite problem. See SessionSummary.appConnects.
110
110
  */
111
- recordAppConnected(): void;
111
+ recordAppConnected(sdkVersion?: string): void;
112
112
  /** One action driven at the page. Settled by the next verdict; see #unsettledActions. */
113
113
  recordAction(): void;
114
114
  recordVerification(): void;
@@ -146,8 +146,6 @@ export declare class SessionMetrics {
146
146
  recordFeedbackPrompt(): void;
147
147
  /** An agent was shown a platform or Harness advisory. */
148
148
  recordNudge(kind: AgentNudgeKind): void;
149
- /** A Harness drive was refused because the app's coverage is below the gate. */
150
- recordHarnessRefused(percent: number): void;
151
149
  /** Which tool surface was advertised to agents this session. */
152
150
  recordSurface(surface: string): void;
153
151
  /**