@reticlehq/server 2.4.0 → 2.5.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 (416) hide show
  1. package/SKILL.md +702 -0
  2. package/dist/bridge/auth-failure-reason.d.ts +19 -0
  3. package/dist/bridge/auth-failure-reason.js +29 -0
  4. package/dist/{bridge-security.d.ts → bridge/bridge-security.d.ts} +1 -1
  5. package/dist/{bridge-security.js → bridge/bridge-security.js} +1 -1
  6. package/dist/{bridge.d.ts → bridge/bridge.d.ts} +1 -1
  7. package/dist/{bridge.js → bridge/bridge.js} +63 -13
  8. package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +1 -11
  9. package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +9 -9
  10. package/dist/{pairing-token.js → bridge/pairing-token.js} +1 -1
  11. package/dist/capsule/capsule-store.d.ts +8 -3
  12. package/dist/capsule/capsule-store.js +7 -2
  13. package/dist/capsule/capsule.js +3 -3
  14. package/dist/capsule/causal-summary.d.ts +8 -0
  15. package/dist/capsule/causal-summary.js +22 -12
  16. package/dist/capsule/divergence.d.ts +9 -4
  17. package/dist/capsule/divergence.js +8 -8
  18. package/dist/capsule/predicate-to-links.js +11 -8
  19. package/dist/{cli-doctor.js → cli/cli-doctor.js} +9 -2
  20. package/dist/{cli-flow-commands.d.ts → cli/cli-flow-commands.d.ts} +2 -2
  21. package/dist/{cli-flow-commands.js → cli/cli-flow-commands.js} +15 -15
  22. package/dist/{cli-launch.d.ts → cli/cli-launch.d.ts} +32 -3
  23. package/dist/cli/cli-launch.js +171 -0
  24. package/dist/{cli-parse.d.ts → cli/cli-parse.d.ts} +2 -11
  25. package/dist/{cli-parse.js → cli/cli-parse.js} +113 -60
  26. package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +12 -0
  27. package/dist/{cli-port.js → cli/cli-port.js} +9 -9
  28. package/dist/cli/cli-update-commands.d.ts +4 -0
  29. package/dist/cli/cli-update-commands.js +93 -0
  30. package/dist/{cli-verify.js → cli/cli-verify.js} +14 -14
  31. package/dist/{cloud-cli.js → cli/cloud-cli.js} +29 -24
  32. package/dist/cli.d.ts +2 -2
  33. package/dist/cli.js +174 -92
  34. package/dist/cloud/cloud-config.d.ts +0 -1
  35. package/dist/cloud/cloud-config.js +9 -9
  36. package/dist/cloud/cloud-sync.d.ts +1 -7
  37. package/dist/cloud/cloud-sync.js +12 -12
  38. package/dist/crawl/crawl-empty.d.ts +16 -0
  39. package/dist/crawl/crawl-empty.js +24 -0
  40. package/dist/crawl/crawl-tools.js +4 -1
  41. package/dist/crawl/crawl.js +26 -7
  42. package/dist/daemon/daemon-resilience.d.ts +49 -0
  43. package/dist/daemon/daemon-resilience.js +191 -0
  44. package/dist/daemon/daemon-usefulness.d.ts +61 -0
  45. package/dist/daemon/daemon-usefulness.js +62 -0
  46. package/dist/{daemon.d.ts → daemon/daemon.d.ts} +33 -8
  47. package/dist/{daemon.js → daemon/daemon.js} +80 -48
  48. package/dist/daemon/idle-grace.d.ts +32 -0
  49. package/dist/daemon/idle-grace.js +41 -0
  50. package/dist/{idle-shutdown.d.ts → daemon/idle-shutdown.d.ts} +13 -0
  51. package/dist/{idle-shutdown.js → daemon/idle-shutdown.js} +27 -4
  52. package/dist/domain/domain-model.js +2 -2
  53. package/dist/events/body-failures.js +8 -8
  54. package/dist/events/contradictions.d.ts +1 -1
  55. package/dist/events/contradictions.js +60 -10
  56. package/dist/events/echo-mismatch.js +10 -10
  57. package/dist/events/event-filters.js +6 -6
  58. package/dist/events/json-salvage.d.ts +2 -1
  59. package/dist/events/json-salvage.js +6 -6
  60. package/dist/events/observed-in-window.d.ts +12 -0
  61. package/dist/events/observed-in-window.js +21 -0
  62. package/dist/events/predicate-eval.d.ts +43 -20
  63. package/dist/events/predicate-eval.js +159 -55
  64. package/dist/events/predicate.d.ts +2 -2
  65. package/dist/events/predicate.js +112 -35
  66. package/dist/events/reconcile.js +5 -5
  67. package/dist/events/ring-buffer.js +1 -1
  68. package/dist/events/stale-response.js +6 -6
  69. package/dist/events/testid-near-miss.d.ts +22 -0
  70. package/dist/events/testid-near-miss.js +33 -0
  71. package/dist/events/unit-mismatch.js +8 -8
  72. package/dist/flows/affected-tools.js +19 -4
  73. package/dist/flows/affected.js +1 -1
  74. package/dist/flows/annotate-target.d.ts +1 -0
  75. package/dist/flows/annotate-target.js +20 -0
  76. package/dist/flows/annotate-tools.js +25 -3
  77. package/dist/flows/annotate.js +17 -4
  78. package/dist/flows/assertion-integrity.d.ts +2 -1
  79. package/dist/flows/assertion-tiers-store.d.ts +3 -66
  80. package/dist/flows/assertion-tiers-store.js +2 -2
  81. package/dist/flows/attributed-failure.d.ts +17 -0
  82. package/dist/flows/attributed-failure.js +20 -0
  83. package/dist/flows/buddy-status.d.ts +2 -1
  84. package/dist/flows/buddy-status.js +2 -2
  85. package/dist/flows/coverage.d.ts +3 -2
  86. package/dist/flows/coverage.js +2 -2
  87. package/dist/flows/decision.js +24 -9
  88. package/dist/flows/empty-flow.d.ts +6 -0
  89. package/dist/flows/empty-flow.js +24 -0
  90. package/dist/flows/flake-store.d.ts +0 -1
  91. package/dist/flows/flake-store.js +1 -1
  92. package/dist/flows/flake.d.ts +2 -1
  93. package/dist/flows/flake.js +2 -2
  94. package/dist/flows/flow-classify.js +12 -0
  95. package/dist/flows/flow-replay-run.js +4 -4
  96. package/dist/flows/flow-replay.d.ts +5 -7
  97. package/dist/flows/flow-replay.js +114 -47
  98. package/dist/flows/flow-report.js +1 -1
  99. package/dist/flows/flow-scope.d.ts +1 -6
  100. package/dist/flows/flow-step-runners.d.ts +26 -6
  101. package/dist/flows/flow-step-runners.js +157 -6
  102. package/dist/flows/flow-success.js +20 -15
  103. package/dist/flows/flow-tools.js +53 -7
  104. package/dist/flows/flows.js +15 -11
  105. package/dist/flows/gate.d.ts +4 -3
  106. package/dist/flows/gate.js +1 -1
  107. package/dist/flows/heal-run.d.ts +0 -8
  108. package/dist/flows/heal-run.js +5 -5
  109. package/dist/flows/heal.js +3 -3
  110. package/dist/flows/predicate-to-expect.d.ts +38 -0
  111. package/dist/flows/predicate-to-expect.js +95 -0
  112. package/dist/flows/replay.d.ts +16 -1
  113. package/dist/flows/replay.js +58 -22
  114. package/dist/flows/role-anchor-nearest.d.ts +6 -0
  115. package/dist/flows/role-anchor-nearest.js +45 -0
  116. package/dist/flows/server-verify.d.ts +1 -1
  117. package/dist/flows/server-verify.js +5 -5
  118. package/dist/flows/verify-change-tools.js +32 -10
  119. package/dist/flows/verify-change-verdict.d.ts +15 -0
  120. package/dist/flows/verify-change-verdict.js +25 -0
  121. package/dist/flows/watch-batcher.d.ts +3 -2
  122. package/dist/honesty/already-true.d.ts +2 -0
  123. package/dist/honesty/already-true.js +31 -0
  124. package/dist/honesty/blind-spots.d.ts +16 -3
  125. package/dist/honesty/blind-spots.js +24 -12
  126. package/dist/honesty/honesty.d.ts +3 -2
  127. package/dist/honesty/honesty.js +4 -4
  128. package/dist/honesty/uncaptured-bodies.js +1 -1
  129. package/dist/honesty/unread-outcome.js +2 -2
  130. package/dist/honesty/verified.d.ts +22 -3
  131. package/dist/honesty/verified.js +48 -8
  132. package/dist/http-server.js +14 -7
  133. package/dist/hunt/hunt-report.d.ts +2 -1
  134. package/dist/hunt/hunt-report.js +2 -2
  135. package/dist/index.d.ts +8 -6
  136. package/dist/index.js +32 -25
  137. package/dist/init/agent-rules.d.ts +2 -1
  138. package/dist/init/agent-rules.js +45 -7
  139. package/dist/init/app-choice.d.ts +20 -0
  140. package/dist/init/app-choice.js +25 -0
  141. package/dist/init/astro-host.d.ts +21 -0
  142. package/dist/init/astro-host.js +27 -0
  143. package/dist/init/astro-patch.d.ts +16 -0
  144. package/dist/init/astro-patch.js +240 -0
  145. package/dist/init/capabilities.js +4 -1
  146. package/dist/init/cra.d.ts +37 -0
  147. package/dist/init/cra.js +90 -0
  148. package/dist/init/cursor.js +39 -4
  149. package/dist/init/desktop-doctor.d.ts +3 -2
  150. package/dist/init/desktop-doctor.js +4 -4
  151. package/dist/init/detect.d.ts +3 -2
  152. package/dist/init/detect.js +16 -5
  153. package/dist/init/mcp-registered.d.ts +12 -0
  154. package/dist/init/mcp-registered.js +14 -0
  155. package/dist/init/mcp.d.ts +27 -2
  156. package/dist/init/mcp.js +40 -4
  157. package/dist/init/next-patch.d.ts +2 -4
  158. package/dist/init/next-patch.js +109 -19
  159. package/dist/init/node-io.js +23 -6
  160. package/dist/init/plan-framework.d.ts +16 -1
  161. package/dist/init/plan-framework.js +132 -8
  162. package/dist/init/plan.d.ts +73 -8
  163. package/dist/init/plan.js +133 -34
  164. package/dist/init/project-id.d.ts +5 -9
  165. package/dist/init/project-id.js +10 -22
  166. package/dist/init/run.d.ts +5 -0
  167. package/dist/init/run.js +210 -36
  168. package/dist/init/slash-command.d.ts +9 -0
  169. package/dist/init/slash-command.js +10 -1
  170. package/dist/init/snippets.d.ts +7 -10
  171. package/dist/init/snippets.js +44 -15
  172. package/dist/init/vite-config.js +1 -1
  173. package/dist/init/workspace-apps.d.ts +23 -0
  174. package/dist/init/workspace-apps.js +68 -0
  175. package/dist/input/driven-redaction.js +1 -1
  176. package/dist/input/network-detail.js +8 -8
  177. package/dist/input/network-mock-tools.js +2 -2
  178. package/dist/input/network-mock.js +4 -4
  179. package/dist/input/real-input.js +8 -3
  180. package/dist/input/scroll-find.js +2 -2
  181. package/dist/input/scroll-tools.d.ts +0 -5
  182. package/dist/input/scroll-tools.js +11 -4
  183. package/dist/input/viewport-tools.js +2 -2
  184. package/dist/journal/ambient-store.d.ts +0 -2
  185. package/dist/journal/ambient-store.js +1 -1
  186. package/dist/journal/ambient.js +1 -1
  187. package/dist/journal/attach-journal.d.ts +2 -1
  188. package/dist/journal/deviation-report.js +6 -6
  189. package/dist/journal/deviation-service.js +1 -1
  190. package/dist/journal/envelope-store.d.ts +0 -2
  191. package/dist/journal/envelope-store.js +1 -1
  192. package/dist/journal/envelope.d.ts +2 -3
  193. package/dist/journal/envelope.js +3 -3
  194. package/dist/journal/journal-query.js +1 -1
  195. package/dist/journal/journal-recorder.d.ts +2 -1
  196. package/dist/journal/journal-recorder.js +2 -2
  197. package/dist/journal/rollups.js +9 -9
  198. package/dist/journal/session-end.d.ts +2 -1
  199. package/dist/journal/session-journal.js +4 -4
  200. package/dist/license/license.d.ts +0 -14
  201. package/dist/license/license.js +8 -8
  202. package/dist/log.d.ts +10 -0
  203. package/dist/log.js +11 -1
  204. package/dist/mcp/mcp-is-error.d.ts +13 -0
  205. package/dist/mcp/mcp-is-error.js +18 -0
  206. package/dist/mcp/mcp-outage.d.ts +31 -0
  207. package/dist/mcp/mcp-outage.js +48 -0
  208. package/dist/mcp/mcp-proxy.d.ts +124 -0
  209. package/dist/mcp/mcp-proxy.js +697 -0
  210. package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
  211. package/dist/{mcp.js → mcp/mcp.js} +110 -35
  212. package/dist/mcp/proxy-handshake.d.ts +3 -0
  213. package/dist/mcp/proxy-handshake.js +54 -0
  214. package/dist/mcp/proxy-lifecycle.d.ts +64 -0
  215. package/dist/mcp/proxy-lifecycle.js +70 -0
  216. package/dist/mcp/tool-catalog-cache.d.ts +29 -0
  217. package/dist/mcp/tool-catalog-cache.js +55 -0
  218. package/dist/oracles/propose-consequences.d.ts +2 -1
  219. package/dist/oracles/propose-consequences.js +16 -11
  220. package/dist/oracles/self-instrument.d.ts +2 -1
  221. package/dist/oracles/self-instrument.js +1 -1
  222. package/dist/phenomena/phenomena.js +3 -3
  223. package/dist/platform.d.ts +16 -0
  224. package/dist/platform.js +16 -0
  225. package/dist/pool/playwright-launcher.d.ts +15 -2
  226. package/dist/pool/playwright-launcher.js +21 -2
  227. package/dist/project/fs-port.js +1 -1
  228. package/dist/project/project-tools.js +2 -2
  229. package/dist/runs/build-verification-run.js +1 -1
  230. package/dist/runs/repair-prompt.d.ts +0 -6
  231. package/dist/runs/repair-prompt.js +3 -3
  232. package/dist/runs/risk-classify.js +1 -1
  233. package/dist/runs/run-diff.d.ts +0 -2
  234. package/dist/runs/run-diff.js +3 -3
  235. package/dist/runs/run-tools.js +2 -2
  236. package/dist/runs/verification-sync.js +2 -2
  237. package/dist/runs/verify-http.js +1 -1
  238. package/dist/runs/verify-server.js +1 -1
  239. package/dist/session/command-timeout.d.ts +11 -3
  240. package/dist/session/command-timeout.js +2 -2
  241. package/dist/session/control-envelope.d.ts +6 -0
  242. package/dist/session/control-envelope.js +7 -1
  243. package/dist/session/dev-server-probe.d.ts +13 -0
  244. package/dist/session/dev-server-probe.js +52 -0
  245. package/dist/session/last-act.d.ts +17 -3
  246. package/dist/session/last-act.js +16 -4
  247. package/dist/session/live-control-tools.js +7 -2
  248. package/dist/session/live-control.js +1 -1
  249. package/dist/session/looks-like-dev-server.d.ts +14 -0
  250. package/dist/session/looks-like-dev-server.js +25 -0
  251. package/dist/session/no-session-diagnosis.d.ts +38 -0
  252. package/dist/session/no-session-diagnosis.js +70 -0
  253. package/dist/session/no-session-watch.d.ts +19 -0
  254. package/dist/session/no-session-watch.js +61 -0
  255. package/dist/session/observed-state.d.ts +4 -0
  256. package/dist/session/observed-state.js +19 -1
  257. package/dist/session/output-budget.js +1 -1
  258. package/dist/session/session-health.d.ts +8 -1
  259. package/dist/session/session-health.js +8 -7
  260. package/dist/session/session-info.d.ts +26 -7
  261. package/dist/session/session-info.js +42 -1
  262. package/dist/session/session-lease.d.ts +0 -11
  263. package/dist/session/session-lease.js +1 -1
  264. package/dist/session/session-manager.d.ts +3 -0
  265. package/dist/session/session-manager.js +52 -9
  266. package/dist/session/session-readiness.d.ts +1 -1
  267. package/dist/session/session-readiness.js +6 -1
  268. package/dist/session/session-reaper.js +1 -1
  269. package/dist/session/session-reconnect.d.ts +32 -0
  270. package/dist/session/session-reconnect.js +42 -0
  271. package/dist/session/session.d.ts +14 -2
  272. package/dist/session/session.js +69 -26
  273. package/dist/session/state-select.d.ts +1 -1
  274. package/dist/session/state-select.js +1 -1
  275. package/dist/status-payload.d.ts +19 -0
  276. package/dist/status-payload.js +11 -0
  277. package/dist/telemetry/argument-shape.js +10 -1
  278. package/dist/telemetry/browser-mode.d.ts +27 -0
  279. package/dist/telemetry/browser-mode.js +33 -0
  280. package/dist/telemetry/bug-found.d.ts +17 -21
  281. package/dist/telemetry/bug-found.js +120 -8
  282. package/dist/telemetry/cli-telemetry.d.ts +2 -12
  283. package/dist/telemetry/cli-telemetry.js +27 -4
  284. package/dist/telemetry/daemon-telemetry.d.ts +19 -0
  285. package/dist/telemetry/daemon-telemetry.js +12 -2
  286. package/dist/telemetry/dev-repo.js +4 -4
  287. package/dist/telemetry/error-fingerprint.js +21 -2
  288. package/dist/telemetry/feedback-cli.d.ts +1 -1
  289. package/dist/telemetry/feedback-cli.js +4 -4
  290. package/dist/telemetry/feedback-context.d.ts +22 -0
  291. package/dist/telemetry/feedback-context.js +41 -1
  292. package/dist/telemetry/feedback-delivery.d.ts +20 -0
  293. package/dist/telemetry/feedback-delivery.js +30 -0
  294. package/dist/telemetry/feedback-outbox.d.ts +22 -0
  295. package/dist/telemetry/feedback-outbox.js +87 -0
  296. package/dist/telemetry/feedback.d.ts +22 -1
  297. package/dist/telemetry/feedback.js +67 -8
  298. package/dist/telemetry/git-facts.js +1 -1
  299. package/dist/telemetry/session-metrics.d.ts +2 -0
  300. package/dist/telemetry/session-metrics.js +68 -6
  301. package/dist/telemetry/telemetry.d.ts +27 -2
  302. package/dist/telemetry/telemetry.js +119 -29
  303. package/dist/telemetry/verification-of.d.ts +22 -0
  304. package/dist/telemetry/verification-of.js +84 -0
  305. package/dist/tools/act-capsule.js +2 -2
  306. package/dist/tools/act-danger.d.ts +12 -0
  307. package/dist/tools/act-danger.js +20 -3
  308. package/dist/tools/act-helpers.js +4 -4
  309. package/dist/tools/act-tools.d.ts +0 -8
  310. package/dist/tools/act-tools.js +84 -115
  311. package/dist/tools/act-view.js +7 -7
  312. package/dist/tools/alias-args.d.ts +17 -0
  313. package/dist/tools/alias-args.js +25 -0
  314. package/dist/tools/assert-grade.js +9 -9
  315. package/dist/tools/assert-verdict.d.ts +3 -1
  316. package/dist/tools/assert-verdict.js +8 -5
  317. package/dist/tools/browser-tools.js +30 -11
  318. package/dist/tools/contract-tools.js +1 -1
  319. package/dist/tools/coverage-identity.d.ts +34 -0
  320. package/dist/tools/coverage-identity.js +46 -0
  321. package/dist/tools/coverage-tools.js +10 -14
  322. package/dist/tools/dynamic-tools.d.ts +2 -1
  323. package/dist/tools/dynamic-tools.js +90 -18
  324. package/dist/tools/error-recovery.d.ts +20 -2
  325. package/dist/tools/error-recovery.js +179 -4
  326. package/dist/tools/feedback-tools.d.ts +12 -1
  327. package/dist/tools/feedback-tools.js +28 -5
  328. package/dist/tools/invoke-tool.d.ts +0 -6
  329. package/dist/tools/invoke-tool.js +57 -32
  330. package/dist/tools/lease-hint.d.ts +17 -0
  331. package/dist/tools/lease-hint.js +24 -0
  332. package/dist/tools/lease-tools.js +6 -5
  333. package/dist/tools/merge-tools.d.ts +10 -1
  334. package/dist/tools/merge-tools.js +9 -3
  335. package/dist/tools/merged-name-redirect.d.ts +13 -0
  336. package/dist/tools/merged-name-redirect.js +55 -0
  337. package/dist/tools/navigate-result.d.ts +17 -0
  338. package/dist/tools/navigate-result.js +31 -0
  339. package/dist/tools/observe-tools.js +54 -20
  340. package/dist/tools/observed-nothing.d.ts +25 -0
  341. package/dist/tools/observed-nothing.js +33 -0
  342. package/dist/tools/query-paginate.js +2 -2
  343. package/dist/tools/query-shape.d.ts +18 -0
  344. package/dist/tools/query-shape.js +39 -0
  345. package/dist/tools/read-tools.js +81 -20
  346. package/dist/tools/real-input-attempt.d.ts +28 -0
  347. package/dist/tools/real-input-attempt.js +88 -0
  348. package/dist/tools/reconcile-tools.js +7 -7
  349. package/dist/tools/reload-result.d.ts +14 -0
  350. package/dist/tools/reload-result.js +29 -0
  351. package/dist/tools/snapshot-delta.d.ts +4 -5
  352. package/dist/tools/snapshot-delta.js +0 -0
  353. package/dist/tools/tool-kit.d.ts +8 -0
  354. package/dist/tools/tool-surface.d.ts +83 -0
  355. package/dist/tools/tool-surface.js +204 -0
  356. package/dist/tools/tools-helpers.js +6 -6
  357. package/dist/tools/tools.d.ts +15 -0
  358. package/dist/tools/tools.js +53 -17
  359. package/dist/tools/unadvertised-help.d.ts +5 -0
  360. package/dist/tools/unadvertised-help.js +39 -0
  361. package/dist/trace.d.ts +69 -0
  362. package/dist/trace.js +150 -0
  363. package/dist/update/nudge-credit.d.ts +4 -0
  364. package/dist/update/nudge-credit.js +53 -0
  365. package/dist/update/sdk-sync.d.ts +21 -0
  366. package/dist/update/sdk-sync.js +42 -0
  367. package/dist/update/update-checker.js +3 -3
  368. package/dist/update/update-nudge.d.ts +63 -6
  369. package/dist/update/update-nudge.js +128 -15
  370. package/dist/update/updater.d.ts +1 -9
  371. package/dist/update/updater.js +13 -8
  372. package/dist/version/peer-announce.d.ts +4 -0
  373. package/dist/version/peer-announce.js +30 -0
  374. package/dist/{server-version.js → version/server-version.js} +5 -1
  375. package/dist/version/version-nudge.d.ts +28 -0
  376. package/dist/version/version-nudge.js +40 -0
  377. package/dist/version/version-skew.d.ts +66 -0
  378. package/dist/version/version-skew.js +71 -0
  379. package/dist/visual/visual-diff.js +2 -2
  380. package/dist/visual/visual-tools.js +4 -4
  381. package/docs/agent-cheatsheet.md +85 -0
  382. package/docs/architecture.md +113 -0
  383. package/docs/benchmarks.md +255 -0
  384. package/docs/debugging.md +102 -0
  385. package/docs/deploy-checks.md +69 -0
  386. package/docs/desktop-apps.md +256 -0
  387. package/docs/enterprise.md +62 -0
  388. package/docs/fixtures.md +28 -0
  389. package/docs/flows.md +166 -0
  390. package/docs/getting-started.md +469 -0
  391. package/docs/human-control.md +63 -0
  392. package/docs/integration-patterns.md +171 -0
  393. package/docs/local-registry.md +126 -0
  394. package/docs/mint.json +61 -0
  395. package/docs/multi-agent-testing.md +55 -0
  396. package/docs/platform-integration.md +122 -0
  397. package/docs/telemetry-contract.md +214 -0
  398. package/docs/telemetry.md +184 -0
  399. package/docs/testing.md +82 -0
  400. package/docs/token-efficiency.md +80 -0
  401. package/docs/usage.md +1046 -0
  402. package/package.json +8 -5
  403. package/dist/cli-launch.js +0 -112
  404. package/dist/daemon-resilience.d.ts +0 -22
  405. package/dist/daemon-resilience.js +0 -85
  406. package/dist/mcp-proxy.d.ts +0 -67
  407. package/dist/mcp-proxy.js +0 -337
  408. package/dist/tools/profiles.d.ts +0 -37
  409. package/dist/tools/profiles.js +0 -139
  410. /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
  411. /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
  412. /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
  413. /package/dist/{cli-doctor.d.ts → cli/cli-doctor.d.ts} +0 -0
  414. /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
  415. /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
  416. /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
@@ -0,0 +1,23 @@
1
+ /**
2
+ * Which directories to look in for the app, when `reticle init` runs at a monorepo root.
3
+ *
4
+ * This used to be the literal list `['apps', 'packages']`. Measured on a real repo with three Next
5
+ * apps at `web/`, `admin/` and `space/`, it found none — so the redirect never fired, init ran
6
+ * against the root, and it reported ✓ for writing `app/reticle-dev.tsx` into a directory Next never
7
+ * compiles. A ⚠ tells a human to act; a ✓ tells them it is handled.
8
+ *
9
+ * A workspace DECLARES its packages, so that declaration is used first and directory names are not
10
+ * guessed at all. Where nothing is declared, every top-level directory is a better candidate than two
11
+ * hardcoded ones — filtered by the usual non-source suspects, and still subject to the `looksLikeApp`
12
+ * check that follows, so a wrong guess here costs a `package.json` read.
13
+ */
14
+ interface WorkspaceSources {
15
+ /** Raw contents of pnpm-workspace.yaml, when present. */
16
+ pnpmWorkspace?: string;
17
+ /** The `workspaces` field of package.json — array form or the yarn/npm object form. */
18
+ pkgWorkspaces?: unknown;
19
+ /** Directory names at the repo root, used when nothing is declared. */
20
+ topLevelDirs?: readonly string[];
21
+ }
22
+ export declare function workspaceParents(sources: WorkspaceSources): string[];
23
+ export {};
@@ -0,0 +1,68 @@
1
+ /**
2
+ * Which directories to look in for the app, when `reticle init` runs at a monorepo root.
3
+ *
4
+ * This used to be the literal list `['apps', 'packages']`. Measured on a real repo with three Next
5
+ * apps at `web/`, `admin/` and `space/`, it found none — so the redirect never fired, init ran
6
+ * against the root, and it reported ✓ for writing `app/reticle-dev.tsx` into a directory Next never
7
+ * compiles. A ⚠ tells a human to act; a ✓ tells them it is handled.
8
+ *
9
+ * A workspace DECLARES its packages, so that declaration is used first and directory names are not
10
+ * guessed at all. Where nothing is declared, every top-level directory is a better candidate than two
11
+ * hardcoded ones — filtered by the usual non-source suspects, and still subject to the `looksLikeApp`
12
+ * check that follows, so a wrong guess here costs a `package.json` read.
13
+ */
14
+ /** Directories that are never a workspace package, whatever the layout. */
15
+ const NEVER_A_PACKAGE = new Set(['node_modules', 'dist', 'build', 'out', 'coverage', 'target']);
16
+ /** `packages/*` -> `packages`; `web` -> `web`. The base directory a glob searches. */
17
+ function globBase(pattern) {
18
+ const base = pattern
19
+ .split('/')[0]
20
+ ?.trim()
21
+ .replace(/^['"]|['"]$/g, '');
22
+ return base === undefined || '' === base || '.' === base || base.includes('*') ? undefined : base;
23
+ }
24
+ function fromPnpm(yaml) {
25
+ // A deliberately small reader rather than a YAML dependency: this file is a list of globs, and the
26
+ // only shape that matters is `- 'pattern'` under `packages:`. A malformed file yields nothing,
27
+ // which falls through to the top-level scan rather than failing the install.
28
+ const out = [];
29
+ let inPackages = false;
30
+ for (const line of yaml.split('\n')) {
31
+ if (/^packages\s*:/.test(line)) {
32
+ inPackages = true;
33
+ continue;
34
+ }
35
+ if (inPackages && /^\S/.test(line))
36
+ break;
37
+ const item = /^\s*-\s*(.+)$/.exec(line);
38
+ if (inPackages && item?.[1] !== undefined) {
39
+ const base = globBase(item[1]);
40
+ if (base !== undefined)
41
+ out.push(base);
42
+ }
43
+ }
44
+ return out;
45
+ }
46
+ function fromPkg(workspaces) {
47
+ const list = Array.isArray(workspaces)
48
+ ? workspaces
49
+ : 'object' === typeof workspaces && workspaces !== null
50
+ ? workspaces.packages
51
+ : undefined;
52
+ if (!Array.isArray(list))
53
+ return [];
54
+ return list
55
+ .filter((p) => 'string' === typeof p)
56
+ .map(globBase)
57
+ .filter((p) => p !== undefined);
58
+ }
59
+ export function workspaceParents(sources) {
60
+ const declared = [
61
+ ...(sources.pnpmWorkspace === undefined ? [] : fromPnpm(sources.pnpmWorkspace)),
62
+ ...fromPkg(sources.pkgWorkspaces),
63
+ ];
64
+ const candidates = declared.length > 0
65
+ ? declared
66
+ : (sources.topLevelDirs ?? []).filter((d) => !d.startsWith('.') && !NEVER_A_PACKAGE.has(d));
67
+ return [...new Set(candidates)];
68
+ }
@@ -35,7 +35,7 @@ function invalidate() {
35
35
  }
36
36
  /** Record what a session declared sensitive. Called when its hello lands. */
37
37
  export function declareDrivenRedactionKeys(sessionId, keys) {
38
- if (keys.length === 0) {
38
+ if (0 === keys.length) {
39
39
  if (declaredBySession.delete(sessionId))
40
40
  invalidate();
41
41
  return;
@@ -21,7 +21,7 @@ const DEFAULT_POLICY = { isSensitiveKey: defaultIsSensitiveKey };
21
21
  function redactByKey(value, policy) {
22
22
  if (Array.isArray(value))
23
23
  return value.map((v) => redactByKey(v, policy));
24
- if (value !== null && typeof value === 'object') {
24
+ if (value !== null && 'object' === typeof value) {
25
25
  const out = {};
26
26
  for (const [k, v] of Object.entries(value)) {
27
27
  out[k] = policy.isSensitiveKey(k) ? REDACTED_VALUE : redactByKey(v, policy);
@@ -82,15 +82,15 @@ export function buildNetworkDetail(raw, policy = DEFAULT_POLICY) {
82
82
  status: raw.status,
83
83
  headers: projectHeaders(raw.headers, policy),
84
84
  ...(raw.resourceType === undefined ? {} : { resourceType: raw.resourceType }),
85
- ...(raw.requestBody === undefined || raw.requestBody.length === 0
85
+ ...(raw.requestBody === undefined || 0 === raw.requestBody.length
86
86
  ? {}
87
87
  : { requestBody: projectWireBody(raw.requestBody, policy) }),
88
- ...(raw.pageUrl === undefined || raw.pageUrl.length === 0 ? {} : { pageUrl: raw.pageUrl }),
88
+ ...(raw.pageUrl === undefined || 0 === raw.pageUrl.length ? {} : { pageUrl: raw.pageUrl }),
89
89
  };
90
90
  }
91
91
  function keyOf(url, method) {
92
- const m = typeof method === 'string' ? method.toUpperCase() : '';
93
- const u = typeof url === 'string' ? url : '';
92
+ const m = 'string' === typeof method ? method.toUpperCase() : '';
93
+ const u = 'string' === typeof url ? url : '';
94
94
  return `${m} ${u}`;
95
95
  }
96
96
  /**
@@ -127,9 +127,9 @@ export function mergeNetworkDetail(events) {
127
127
  // finding — that is the whole reason for capturing it — so the authoritative one wins and the
128
128
  // divergence is flagged rather than silently resolved.
129
129
  const wireBody = e.data['requestBody'];
130
- if (typeof wireBody === 'string') {
130
+ if ('string' === typeof wireBody) {
131
131
  const pageBody = data['requestBody'];
132
- if (typeof pageBody === 'string' && pageBody !== wireBody) {
132
+ if ('string' === typeof pageBody && pageBody !== wireBody) {
133
133
  data['requestBodyDivergedFromPage'] = true;
134
134
  }
135
135
  data['requestBody'] = wireBody;
@@ -162,7 +162,7 @@ export function attachNetworkDetail(page, emit) {
162
162
  status: response.status(),
163
163
  headers,
164
164
  ...(resourceType === undefined ? {} : { resourceType }),
165
- ...(postData === null ? {} : { requestBody: postData }),
165
+ ...(null === postData ? {} : { requestBody: postData }),
166
166
  pageUrl: page.url(),
167
167
  },
168
168
  // Resolved per response, not per attachment: a session declaring extra keys can connect
@@ -5,7 +5,7 @@ import { sessionIdShape } from '../tools/tool-kit.js';
5
5
  import { asString } from '../tools/tools-helpers.js';
6
6
  function mockProvider(deps) {
7
7
  const p = deps.realInput;
8
- return p !== undefined && typeof p.setMocks === 'function' ? p : undefined;
8
+ return p !== undefined && 'function' === typeof p.setMocks ? p : undefined;
9
9
  }
10
10
  const ruleShape = z.object({
11
11
  urlContains: z
@@ -80,7 +80,7 @@ export const NETWORK_MOCK_TOOLS = [
80
80
  };
81
81
  }
82
82
  const session = deps.sessions.resolve(asString(args['sessionId']));
83
- const rules = args['clear'] === true ? [] : toRules(args['mocks']);
83
+ const rules = true === args['clear'] ? [] : toRules(args['mocks']);
84
84
  const applied = await provider.setMocks(session.url, rules);
85
85
  return { applied, count: applied ? rules.length : 0 };
86
86
  },
@@ -10,7 +10,7 @@ export function matchMock(rules, req) {
10
10
  continue;
11
11
  if (rule.method !== undefined && rule.method.toUpperCase() !== req.method.toUpperCase())
12
12
  continue;
13
- if (rule.abort === true)
13
+ if (true === rule.abort)
14
14
  return { kind: 'abort' };
15
15
  const outcome = {
16
16
  kind: 'fulfill',
@@ -27,11 +27,11 @@ export function matchMock(rules, req) {
27
27
  }
28
28
  /** Apply a matched outcome to a Playwright Route. Exported so the route handler is testable in isolation. */
29
29
  export async function applyOutcome(route, outcome, sleep) {
30
- if (outcome.kind === 'continue') {
30
+ if ('continue' === outcome.kind) {
31
31
  await route.continue();
32
32
  return;
33
33
  }
34
- if (outcome.kind === 'abort') {
34
+ if ('abort' === outcome.kind) {
35
35
  await route.abort('failed');
36
36
  return;
37
37
  }
@@ -51,7 +51,7 @@ const realSleep = (ms) => new Promise((res) => setTimeout(res, ms));
51
51
  */
52
52
  export async function installNetworkMocks(page, rules, sleep = realSleep) {
53
53
  await page.unroute('**/*').catch(() => undefined);
54
- if (rules.length === 0)
54
+ if (0 === rules.length)
55
55
  return;
56
56
  await page.route('**/*', (route) => {
57
57
  const req = route.request();
@@ -1,3 +1,4 @@
1
+ import { gotoOptions } from '../pool/playwright-launcher.js';
1
2
  import { BrowserLaunchKind } from '@reticlehq/core';
2
3
  import { getSessionMetrics } from '../telemetry/session-metrics.js';
3
4
  import { classifyConnectFailure } from '../telemetry/connect-failure.js';
@@ -93,7 +94,7 @@ const SCREENSHOT_DETERMINISM = { style: HIDE_RETICLE_CHROME_CSS, animations: 'di
93
94
  export async function capturePage(page, opts) {
94
95
  const buf = await page.screenshot(opts.clip !== undefined
95
96
  ? { ...SCREENSHOT_DETERMINISM, clip: opts.clip }
96
- : opts.fullPage === true
97
+ : true === opts.fullPage
97
98
  ? { ...SCREENSHOT_DETERMINISM, fullPage: true }
98
99
  : { ...SCREENSHOT_DETERMINISM });
99
100
  return new Uint8Array(buf.buffer, buf.byteOffset, buf.byteLength);
@@ -269,7 +270,11 @@ export class LaunchedRealInputProvider {
269
270
  if (this.#onNetworkDetail !== undefined)
270
271
  attachNetworkDetail(page, this.#onNetworkDetail);
271
272
  try {
272
- await page.goto(this.#driveUrl);
273
+ // Same navigation rule as the pool, and for the same measured reason: Playwright's default
274
+ // waits for `load`, which an app with one never-finishing subresource never fires — 30s of
275
+ // nothing and then a failure that blames the app. The SDK connect is a module script, so it
276
+ // has already run by DOMContentLoaded. See gotoOptions.
277
+ await page.goto(this.#driveUrl, gotoOptions(undefined));
273
278
  }
274
279
  catch (e) {
275
280
  throw new DriveError(DriveErrorCode.NAVIGATE_FAILED, e instanceof Error ? e.message : String(e));
@@ -369,7 +374,7 @@ export function selectPage(pages, sessionUrl) {
369
374
  return exact;
370
375
  const target = stripVolatile(sessionUrl);
371
376
  const loose = pages.filter((p) => stripVolatile(p.url()) === target);
372
- return loose.length === 1 ? loose[0] : undefined;
377
+ return 1 === loose.length ? loose[0] : undefined;
373
378
  }
374
379
  function stripVolatile(url) {
375
380
  const hash = url.indexOf('#');
@@ -38,7 +38,7 @@ export async function scrollToFind(session, q, opts = {}) {
38
38
  return { found: true, element: hit, scrolls, exhausted: false };
39
39
  // Fall through to linear refinement from current position (already near the target).
40
40
  const data = asRecord(sr.result);
41
- if (data['atEnd'] === true || data['scrolled'] === false) {
41
+ if (true === data['atEnd'] || false === data['scrolled']) {
42
42
  return { found: false, scrolls, exhausted: true };
43
43
  }
44
44
  }
@@ -50,7 +50,7 @@ export async function scrollToFind(session, q, opts = {}) {
50
50
  if (hit !== undefined)
51
51
  return { found: true, element: hit, scrolls, exhausted: false };
52
52
  // Reached the bottom or the container would not move — no more rows to reveal.
53
- if (data['atEnd'] === true || data['scrolled'] === false) {
53
+ if (true === data['atEnd'] || false === data['scrolled']) {
54
54
  return { found: false, scrolls, exhausted: true };
55
55
  }
56
56
  }
@@ -1,7 +1,2 @@
1
1
  import type { ToolDef } from '../tools/tools.js';
2
- /**
3
- * reticle_scroll_to — the windowed/virtualized-list escape hatch. A plain reticle_query
4
- * only sees rendered nodes, so an off-screen row in a react-window/react-virtualized list returns
5
- * nothing. This scrolls the container until the row mounts, then returns its ref.
6
- */
7
2
  export declare const SCROLL_TOOLS: ToolDef[];
@@ -1,4 +1,5 @@
1
1
  import { z } from 'zod';
2
+ import { QueryBy } from '@reticlehq/core';
2
3
  import { ReticleTool } from '../tools/tool-names.js';
3
4
  import { asNumber, asString } from '../tools/tools-helpers.js';
4
5
  import { scrollToFind } from './scroll-find.js';
@@ -7,14 +8,20 @@ import { scrollToFind } from './scroll-find.js';
7
8
  * only sees rendered nodes, so an off-screen row in a react-window/react-virtualized list returns
8
9
  * nothing. This scrolls the container until the row mounts, then returns its ref.
9
10
  */
11
+ /**
12
+ * The query strategies, derived from QueryBy — the same vocabulary reticle_query uses, and for the
13
+ * same reason. A free string here produced the identical false negative: `by:'css'` scrolled the
14
+ * whole list and reported `{ found: false, exhausted: true }`, which reads as "the row is not in
15
+ * this list" rather than "that strategy does not exist".
16
+ */
17
+ const QUERY_BY_LIST = Object.values(QueryBy).join(' | ');
18
+ const queryByEnum = z.enum(Object.values(QueryBy));
10
19
  export const SCROLL_TOOLS = [
11
20
  {
12
21
  name: ReticleTool.SCROLL_TO,
13
- description: 'Find an element in a VIRTUALIZED list that has not rendered yet. Pass `by` (role|text|testid|label|placeholder|alt) and `value` (query string) to identify the target row. Scrolls the container until the row mounts, the list ends, or maxScrolls (default 20) is spent. Pass targetIndex + totalCount for bisection — jumps directly to the estimated offset in one scroll (e.g. targetIndex:800 totalCount:1000 jumps to 80% of scrollHeight). Returns { found, element?, scrolls, exhausted }.',
22
+ description: 'Find an element in a VIRTUALIZED list that has not rendered yet. Pass `by` (see the parameter for the exact strategies) and `value` (query string) to identify the target row. Scrolls the container until the row mounts, the list ends, or maxScrolls (default 20) is spent. Pass targetIndex + totalCount for bisection — jumps directly to the estimated offset in one scroll (e.g. targetIndex:800 totalCount:1000 jumps to 80% of scrollHeight). Returns { found, element?, scrolls, exhausted }.',
14
23
  inputSchema: {
15
- by: z
16
- .string()
17
- .describe('Query strategy for finding the target: role | text | testid | label | placeholder | alt'),
24
+ by: queryByEnum.describe(`Query strategy for finding the target: ${QUERY_BY_LIST}`),
18
25
  value: z
19
26
  .string()
20
27
  .describe('Query value for the selected strategy (the element to scroll into view).'),
@@ -8,7 +8,7 @@ const MIN_DIM = 64;
8
8
  const MAX_DIM = 10000;
9
9
  function viewportProvider(deps) {
10
10
  const p = deps.realInput;
11
- return p !== undefined && typeof p.setViewport === 'function'
11
+ return p !== undefined && 'function' === typeof p.setViewport
12
12
  ? p
13
13
  : undefined;
14
14
  }
@@ -54,6 +54,6 @@ export const VIEWPORT_TOOLS = [
54
54
  ];
55
55
  /** Clamp a requested dimension into [MIN_DIM, MAX_DIM]; a missing/NaN value falls back to MIN_DIM. */
56
56
  function clampDim(value) {
57
- const n = typeof value === 'number' && Number.isFinite(value) ? Math.round(value) : MIN_DIM;
57
+ const n = 'number' === typeof value && Number.isFinite(value) ? Math.round(value) : MIN_DIM;
58
58
  return Math.max(MIN_DIM, Math.min(n, MAX_DIM));
59
59
  }
@@ -1,7 +1,5 @@
1
1
  import type { FileSystemPort } from '../project/fs-port.js';
2
2
  import { type AmbientCounts } from './ambient.js';
3
- /** Bumped on any breaking change to the persisted ambient-map shape. */
4
- export declare const AMBIENT_FILE_VERSION = 1;
5
3
  /**
6
4
  * Persists the learned ambient-churn region map at `.reticle/ambient.json`. Local, single-project
7
5
  * memory (stays OSS — OSS-VS-SERVER). Loads never throw: missing/malformed/wrong-version degrades to
@@ -2,7 +2,7 @@ import { dirname } from 'node:path';
2
2
  import { reticleDirPaths } from '../project/reticle-dir.js';
3
3
  import { AmbientFileSchema } from './ambient.js';
4
4
  /** Bumped on any breaking change to the persisted ambient-map shape. */
5
- export const AMBIENT_FILE_VERSION = 1;
5
+ const AMBIENT_FILE_VERSION = 1;
6
6
  /**
7
7
  * Persists the learned ambient-churn region map at `.reticle/ambient.json`. Local, single-project
8
8
  * memory (stays OSS — OSS-VS-SERVER). Loads never throw: missing/malformed/wrong-version degrades to
@@ -8,7 +8,7 @@ import { z } from 'zod';
8
8
  */
9
9
  export function ambientKeyOf(event) {
10
10
  const region = event.data?.['region'];
11
- if (typeof region === 'string' && region.length > 0)
11
+ if ('string' === typeof region && region.length > 0)
12
12
  return region;
13
13
  return event.ref;
14
14
  }
@@ -7,7 +7,7 @@ export interface JournalTarget {
7
7
  elapsed(): number;
8
8
  setJournal(recorder: JournalRecorder, reader?: JournalReader): void;
9
9
  }
10
- export interface JournalAttachDeps {
10
+ interface JournalAttachDeps {
11
11
  fs: FileSystemPort;
12
12
  reticleRoot: string;
13
13
  /** Journaling is on by default; the opt-out (`.reticle.json` journal:false / env) sets this false. */
@@ -19,3 +19,4 @@ export interface JournalAttachDeps {
19
19
  * journaling concern). The recorder's clock is the session's own elapsed time.
20
20
  */
21
21
  export declare function makeJournalAttach(deps: JournalAttachDeps): (session: JournalTarget) => void;
22
+ export {};
@@ -6,13 +6,13 @@ function headlineFor(report) {
6
6
  if (report.insufficientSamples) {
7
7
  return `envelope too new (need ${String(MIN_ENVELOPE_SAMPLES)} runs) — see causal summary${truncNote}`;
8
8
  }
9
- if (report.deviations.length === 0) {
10
- const s = report.nominalSegments === 1 ? '' : 's';
9
+ if (0 === report.deviations.length) {
10
+ const s = 1 === report.nominalSegments ? '' : 's';
11
11
  return `${String(report.nominalSegments)} segment${s} nominal${truncNote}`;
12
12
  }
13
13
  const routes = [...new Set(report.deviations.map((d) => d.route))].join(', ');
14
14
  const n = report.deviations.length;
15
- return `${String(n)} deviation${n === 1 ? '' : 's'}: ${routes}${truncNote}`;
15
+ return `${String(n)} deviation${1 === n ? '' : 's'}: ${routes}${truncNote}`;
16
16
  }
17
17
  /**
18
18
  * Judge observed segments against their per-route envelopes. Segments without a route, or whose
@@ -27,7 +27,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
27
27
  if (segment.route === undefined)
28
28
  continue;
29
29
  // A truncated segment's counts understate reality — judging it could read a false "nominal".
30
- if (segment.truncated === true) {
30
+ if (true === segment.truncated) {
31
31
  truncated += 1;
32
32
  continue;
33
33
  }
@@ -36,7 +36,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
36
36
  continue;
37
37
  judged += 1;
38
38
  const segDeviations = compareSegment(envelope, segment, zThreshold);
39
- if (segDeviations.length === 0)
39
+ if (0 === segDeviations.length)
40
40
  nominal += 1;
41
41
  else
42
42
  deviations.push(...segDeviations);
@@ -47,7 +47,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
47
47
  nominalSegments: nominal,
48
48
  judgedSegments: judged,
49
49
  truncatedSegments: truncated,
50
- insufficientSamples: judged === 0,
50
+ insufficientSamples: 0 === judged,
51
51
  };
52
52
  return { ...base, headline: headlineFor(base) };
53
53
  }
@@ -20,7 +20,7 @@ export async function reportAndAccumulate(store, segments, zThreshold) {
20
20
  if (segment.route === undefined)
21
21
  continue;
22
22
  // Never learn from a truncated sample — its understated counts would poison the baseline.
23
- if (segment.truncated === true)
23
+ if (true === segment.truncated)
24
24
  continue;
25
25
  const current = envelopes.get(segment.route) ?? emptyEnvelope(segment.route);
26
26
  envelopes.set(segment.route, addSegmentToEnvelope(current, segment));
@@ -1,7 +1,5 @@
1
1
  import type { FileSystemPort } from '../project/fs-port.js';
2
2
  import { type RouteEnvelope } from './envelope.js';
3
- /** Bumped on any breaking change to the persisted envelope shape (matches the runs/contract convention). */
4
- export declare const ENVELOPE_FILE_VERSION = 1;
5
3
  /**
6
4
  * Persists the learned per-route envelopes at `.reticle/envelopes.json`. Local, single-project statistics
7
5
  * (single-player memory stays OSS — OSS-VS-SERVER). Loads never throw: a missing, malformed, or
@@ -3,7 +3,7 @@ import { dirname } from 'node:path';
3
3
  import { reticleDirPaths } from '../project/reticle-dir.js';
4
4
  import { RouteEnvelopeSchema } from './envelope.js';
5
5
  /** Bumped on any breaking change to the persisted envelope shape (matches the runs/contract convention). */
6
- export const ENVELOPE_FILE_VERSION = 1;
6
+ const ENVELOPE_FILE_VERSION = 1;
7
7
  const EnvelopeFileSchema = z.object({
8
8
  version: z.literal(ENVELOPE_FILE_VERSION),
9
9
  routes: z.record(RouteEnvelopeSchema),
@@ -21,7 +21,7 @@ export declare function stddev(stats: MetricStats): number;
21
21
  /** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
22
22
  export declare function zScore(stats: MetricStats, x: number): number;
23
23
  /** The metrics an envelope tracks per route. */
24
- export declare const ENVELOPE_METRICS: readonly ["durationMs", "net", "netErrors", "consoleErrors"];
24
+ declare const ENVELOPE_METRICS: readonly ["durationMs", "net", "netErrors", "consoleErrors"];
25
25
  export type EnvelopeMetric = (typeof ENVELOPE_METRICS)[number];
26
26
  export interface RouteEnvelope {
27
27
  route: string;
@@ -31,8 +31,6 @@ export interface RouteEnvelope {
31
31
  }
32
32
  /** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
33
33
  export declare const MIN_ENVELOPE_SAMPLES = 3;
34
- /** Default flag threshold in stddevs. The number is a placeholder for fleet-calibrated priors. */
35
- export declare const DEFAULT_Z_THRESHOLD = 3;
36
34
  /** Persisted shape of a route envelope. Validated on load; a bad file degrades to no envelope. */
37
35
  export declare const RouteEnvelopeSchema: z.ZodObject<{
38
36
  route: z.ZodString;
@@ -229,3 +227,4 @@ export interface Deviation {
229
227
  * falls back to the causal summary in that case.
230
228
  */
231
229
  export declare function compareSegment(envelope: RouteEnvelope, segment: SegmentRollup, zThreshold?: number): Deviation[];
230
+ export {};
@@ -15,14 +15,14 @@ export function stddev(stats) {
15
15
  /** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
16
16
  export function zScore(stats, x) {
17
17
  const sd = stddev(stats);
18
- return sd === 0 ? 0 : (x - stats.mean) / sd;
18
+ return 0 === sd ? 0 : (x - stats.mean) / sd;
19
19
  }
20
20
  /** The metrics an envelope tracks per route. */
21
- export const ENVELOPE_METRICS = ['durationMs', 'net', 'netErrors', 'consoleErrors'];
21
+ const ENVELOPE_METRICS = ['durationMs', 'net', 'netErrors', 'consoleErrors'];
22
22
  /** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
23
23
  export const MIN_ENVELOPE_SAMPLES = 3;
24
24
  /** Default flag threshold in stddevs. The number is a placeholder for fleet-calibrated priors. */
25
- export const DEFAULT_Z_THRESHOLD = 3;
25
+ const DEFAULT_Z_THRESHOLD = 3;
26
26
  const MetricStatsSchema = z.object({
27
27
  count: z.number(),
28
28
  mean: z.number(),
@@ -8,7 +8,7 @@ export function mergeEventsBySeq(journal, buffer) {
8
8
  const bySeq = new Map();
9
9
  const noSeq = [];
10
10
  for (const event of [...journal, ...buffer]) {
11
- if (typeof event.seq === 'number')
11
+ if ('number' === typeof event.seq)
12
12
  bySeq.set(event.seq, event);
13
13
  else
14
14
  noSeq.push(event);
@@ -8,7 +8,7 @@ export interface JournalSink {
8
8
  export interface JournalReader {
9
9
  readEvents(): Promise<ReticleEvent[]>;
10
10
  }
11
- export interface JournalRecorderOptions {
11
+ interface JournalRecorderOptions {
12
12
  /** Injected elapsed-ms clock (never read from Date here — the clock-injection rule). */
13
13
  now: () => number;
14
14
  /** Flush the pending-event batch once this many accumulate. */
@@ -35,3 +35,4 @@ export declare class JournalRecorder {
35
35
  /** Persist any buffered events now (call on session end). Awaits the write chain to settle. */
36
36
  flush(): Promise<void>;
37
37
  }
38
+ export {};
@@ -27,7 +27,7 @@ export class JournalRecorder {
27
27
  const active = this.#active;
28
28
  if (active !== undefined) {
29
29
  out = { ...event, actionId: active.actionId, attribution: EventAttribution.WINDOW };
30
- if (typeof event.seq === 'number') {
30
+ if ('number' === typeof event.seq) {
31
31
  active.seqFrom =
32
32
  active.seqFrom === undefined ? event.seq : Math.min(active.seqFrom, event.seq);
33
33
  active.seqTo = active.seqTo === undefined ? event.seq : Math.max(active.seqTo, event.seq);
@@ -71,7 +71,7 @@ export class JournalRecorder {
71
71
  await this.#chain;
72
72
  }
73
73
  #enqueueFlush() {
74
- if (this.#pending.length === 0)
74
+ if (0 === this.#pending.length)
75
75
  return;
76
76
  const batch = this.#pending;
77
77
  this.#pending = [];
@@ -1,4 +1,4 @@
1
- import { EventType } from '@reticlehq/core';
1
+ import { EventType, StreamDirection } from '@reticlehq/core';
2
2
  function finalize(acc) {
3
3
  return {
4
4
  ...(acc.route === undefined ? {} : { route: acc.route }),
@@ -9,13 +9,13 @@ function finalize(acc) {
9
9
  net: { total: acc.netTotal, errors: acc.netErrors },
10
10
  consoleErrors: acc.consoleErrors,
11
11
  statePathsChanged: acc.statePaths,
12
- ...(acc.streams.frames === 0 ? {} : { streams: acc.streams }),
12
+ ...(0 === acc.streams.frames ? {} : { streams: acc.streams }),
13
13
  ...(acc.truncated ? { truncated: true } : {}),
14
14
  };
15
15
  }
16
16
  function isNetError(event) {
17
17
  const status = event.data['status'];
18
- return event.data['ok'] === false || (typeof status === 'number' && status >= 400);
18
+ return false === event.data['ok'] || ('number' === typeof status && status >= 400);
19
19
  }
20
20
  /**
21
21
  * Fold an ordered event list into route segments split at each ROUTE_CHANGE. Pure: no clock, no IO —
@@ -41,13 +41,13 @@ export function computeSegments(events) {
41
41
  if (acc !== undefined)
42
42
  segments.push(finalize(acc));
43
43
  const pathname = event.data['pathname'];
44
- acc = open(typeof pathname === 'string' ? pathname : undefined, event.t);
44
+ acc = open('string' === typeof pathname ? pathname : undefined, event.t);
45
45
  continue;
46
46
  }
47
47
  if (acc === undefined)
48
48
  acc = open(undefined, event.t);
49
49
  acc.to = event.t;
50
- if (typeof event.actionId === 'string')
50
+ if ('string' === typeof event.actionId)
51
51
  acc.actionIds.add(event.actionId);
52
52
  if (event.type === EventType.NET_REQUEST) {
53
53
  acc.netTotal += 1;
@@ -59,17 +59,17 @@ export function computeSegments(events) {
59
59
  }
60
60
  if (event.type === EventType.STATE_CHANGE) {
61
61
  const name = event.data['name'];
62
- if (typeof name === 'string' && !acc.statePaths.includes(name))
62
+ if ('string' === typeof name && !acc.statePaths.includes(name))
63
63
  acc.statePaths.push(name);
64
64
  }
65
65
  if (event.type === EventType.NET_STREAM) {
66
66
  acc.streams.frames += 1;
67
67
  const direction = event.data['direction'];
68
- if (direction === 'open')
68
+ if (StreamDirection.OPEN === direction)
69
69
  acc.streams.opened += 1;
70
- else if (direction === 'in')
70
+ else if (StreamDirection.IN === direction)
71
71
  acc.streams.in += 1;
72
- else if (direction === 'out')
72
+ else if (StreamDirection.OUT === direction)
73
73
  acc.streams.out += 1;
74
74
  }
75
75
  if (event.type === EventType.TRUNCATED || event.type === EventType.TRANSPORT_OVERFLOW) {
@@ -17,7 +17,7 @@ export interface SessionEndTarget {
17
17
  ambientCounts(): AmbientCounts;
18
18
  ownAmbientCounts(): AmbientCounts;
19
19
  }
20
- export interface SessionEndDeps {
20
+ interface SessionEndDeps {
21
21
  fs: FileSystemPort;
22
22
  reticleRoot: string;
23
23
  /** Journaling/persistence off (opt-out) → teardown is a no-op. */
@@ -29,3 +29,4 @@ export interface SessionEndDeps {
29
29
  * starts already knowing which regions churn.
30
30
  */
31
31
  export declare function makeSessionEnd(deps: SessionEndDeps): (session: SessionEndTarget) => Promise<void>;
32
+ export {};
@@ -37,7 +37,7 @@ export class SessionJournal {
37
37
  this.#sessionId = sessionId;
38
38
  }
39
39
  async appendEvents(events) {
40
- if (events.length === 0)
40
+ if (0 === events.length)
41
41
  return;
42
42
  await this.#ensureDir();
43
43
  const text = `${events.map((e) => JSON.stringify(e)).join('\n')}\n`;
@@ -108,11 +108,11 @@ export class SessionJournal {
108
108
  #ingestTail(tail) {
109
109
  const cache = this.#eventCache ?? (this.#eventCache = []);
110
110
  const end = tail.lastIndexOf('\n') + 1;
111
- if (end === 0)
111
+ if (0 === end)
112
112
  return 0; // no complete line yet
113
113
  const complete = tail.slice(0, end);
114
114
  for (const line of complete.split('\n')) {
115
- if (line.length === 0)
115
+ if (0 === line.length)
116
116
  continue;
117
117
  let parsed;
118
118
  try {
@@ -148,7 +148,7 @@ export class SessionJournal {
148
148
  }
149
149
  const out = [];
150
150
  for (const line of text.split('\n')) {
151
- if (line.length === 0)
151
+ if (0 === line.length)
152
152
  continue;
153
153
  let parsed;
154
154
  try {