@reticlehq/server 2.3.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 (424) 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} +105 -15
  8. package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +6 -11
  9. package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +21 -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/cli-parse.d.ts +143 -0
  25. package/dist/{cli-parse.js → cli/cli-parse.js} +146 -65
  26. package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +15 -0
  27. package/dist/{cli-port.js → cli/cli-port.js} +29 -8
  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 +182 -93
  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.d.ts +0 -6
  88. package/dist/flows/decision.js +64 -8
  89. package/dist/flows/empty-flow.d.ts +6 -0
  90. package/dist/flows/empty-flow.js +24 -0
  91. package/dist/flows/flake-store.d.ts +0 -1
  92. package/dist/flows/flake-store.js +1 -1
  93. package/dist/flows/flake.d.ts +2 -1
  94. package/dist/flows/flake.js +2 -2
  95. package/dist/flows/flow-classify.js +12 -0
  96. package/dist/flows/flow-replay-run.js +4 -4
  97. package/dist/flows/flow-replay.d.ts +5 -7
  98. package/dist/flows/flow-replay.js +114 -47
  99. package/dist/flows/flow-report.js +1 -1
  100. package/dist/flows/flow-scope.d.ts +1 -6
  101. package/dist/flows/flow-step-runners.d.ts +26 -6
  102. package/dist/flows/flow-step-runners.js +157 -6
  103. package/dist/flows/flow-success.js +20 -15
  104. package/dist/flows/flow-tools.js +67 -13
  105. package/dist/flows/flows.js +15 -11
  106. package/dist/flows/gate.d.ts +4 -3
  107. package/dist/flows/gate.js +1 -1
  108. package/dist/flows/heal-run.d.ts +0 -8
  109. package/dist/flows/heal-run.js +5 -5
  110. package/dist/flows/heal.js +3 -3
  111. package/dist/flows/predicate-to-expect.d.ts +38 -0
  112. package/dist/flows/predicate-to-expect.js +95 -0
  113. package/dist/flows/replay.d.ts +16 -1
  114. package/dist/flows/replay.js +58 -22
  115. package/dist/flows/role-anchor-nearest.d.ts +6 -0
  116. package/dist/flows/role-anchor-nearest.js +45 -0
  117. package/dist/flows/server-verify.d.ts +1 -1
  118. package/dist/flows/server-verify.js +5 -5
  119. package/dist/flows/verify-change-tools.js +32 -10
  120. package/dist/flows/verify-change-verdict.d.ts +15 -0
  121. package/dist/flows/verify-change-verdict.js +25 -0
  122. package/dist/flows/watch-batcher.d.ts +3 -2
  123. package/dist/honesty/already-true.d.ts +2 -0
  124. package/dist/honesty/already-true.js +31 -0
  125. package/dist/honesty/blind-spots.d.ts +16 -3
  126. package/dist/honesty/blind-spots.js +24 -12
  127. package/dist/honesty/honesty.d.ts +3 -2
  128. package/dist/honesty/honesty.js +4 -4
  129. package/dist/honesty/uncaptured-bodies.js +1 -1
  130. package/dist/honesty/unread-outcome.js +2 -2
  131. package/dist/honesty/verified.d.ts +22 -3
  132. package/dist/honesty/verified.js +48 -8
  133. package/dist/http-server.js +14 -7
  134. package/dist/hunt/hunt-report.d.ts +2 -1
  135. package/dist/hunt/hunt-report.js +2 -2
  136. package/dist/index.d.ts +8 -6
  137. package/dist/index.js +32 -25
  138. package/dist/init/agent-rules.d.ts +2 -1
  139. package/dist/init/agent-rules.js +45 -7
  140. package/dist/init/app-choice.d.ts +20 -0
  141. package/dist/init/app-choice.js +25 -0
  142. package/dist/init/astro-host.d.ts +21 -0
  143. package/dist/init/astro-host.js +27 -0
  144. package/dist/init/astro-patch.d.ts +16 -0
  145. package/dist/init/astro-patch.js +240 -0
  146. package/dist/init/capabilities.d.ts +17 -0
  147. package/dist/init/capabilities.js +54 -0
  148. package/dist/init/cra.d.ts +37 -0
  149. package/dist/init/cra.js +90 -0
  150. package/dist/init/cursor.js +39 -4
  151. package/dist/init/desktop-doctor.d.ts +3 -2
  152. package/dist/init/desktop-doctor.js +4 -4
  153. package/dist/init/detect.d.ts +26 -0
  154. package/dist/init/detect.js +78 -5
  155. package/dist/init/mcp-registered.d.ts +12 -0
  156. package/dist/init/mcp-registered.js +14 -0
  157. package/dist/init/mcp.d.ts +27 -2
  158. package/dist/init/mcp.js +40 -4
  159. package/dist/init/next-patch.d.ts +39 -0
  160. package/dist/init/next-patch.js +196 -0
  161. package/dist/init/node-io.js +48 -6
  162. package/dist/init/patch-kind.d.ts +20 -0
  163. package/dist/init/patch-kind.js +10 -0
  164. package/dist/init/plan-framework.d.ts +50 -0
  165. package/dist/init/plan-framework.js +341 -0
  166. package/dist/init/plan.d.ts +119 -6
  167. package/dist/init/plan.js +230 -131
  168. package/dist/init/project-id.d.ts +5 -9
  169. package/dist/init/project-id.js +10 -22
  170. package/dist/init/run.d.ts +22 -0
  171. package/dist/init/run.js +393 -28
  172. package/dist/init/slash-command.d.ts +27 -0
  173. package/dist/init/slash-command.js +61 -0
  174. package/dist/init/snippets.d.ts +41 -3
  175. package/dist/init/snippets.js +185 -10
  176. package/dist/init/vite-config.d.ts +4 -10
  177. package/dist/init/vite-config.js +15 -7
  178. package/dist/init/workspace-apps.d.ts +23 -0
  179. package/dist/init/workspace-apps.js +68 -0
  180. package/dist/input/driven-redaction.d.ts +15 -0
  181. package/dist/input/driven-redaction.js +76 -0
  182. package/dist/input/network-detail.d.ts +9 -3
  183. package/dist/input/network-detail.js +43 -23
  184. package/dist/input/network-mock-tools.js +2 -2
  185. package/dist/input/network-mock.js +4 -4
  186. package/dist/input/real-input.js +8 -3
  187. package/dist/input/scroll-find.js +2 -2
  188. package/dist/input/scroll-tools.d.ts +0 -5
  189. package/dist/input/scroll-tools.js +11 -4
  190. package/dist/input/viewport-tools.js +2 -2
  191. package/dist/journal/ambient-store.d.ts +0 -2
  192. package/dist/journal/ambient-store.js +1 -1
  193. package/dist/journal/ambient.js +1 -1
  194. package/dist/journal/attach-journal.d.ts +2 -1
  195. package/dist/journal/deviation-report.js +6 -6
  196. package/dist/journal/deviation-service.js +1 -1
  197. package/dist/journal/envelope-store.d.ts +0 -2
  198. package/dist/journal/envelope-store.js +1 -1
  199. package/dist/journal/envelope.d.ts +2 -3
  200. package/dist/journal/envelope.js +3 -3
  201. package/dist/journal/journal-query.js +1 -1
  202. package/dist/journal/journal-recorder.d.ts +2 -1
  203. package/dist/journal/journal-recorder.js +2 -2
  204. package/dist/journal/rollups.js +9 -9
  205. package/dist/journal/session-end.d.ts +2 -1
  206. package/dist/journal/session-journal.js +4 -4
  207. package/dist/license/license.d.ts +0 -14
  208. package/dist/license/license.js +8 -8
  209. package/dist/log.d.ts +10 -0
  210. package/dist/log.js +11 -1
  211. package/dist/mcp/mcp-is-error.d.ts +13 -0
  212. package/dist/mcp/mcp-is-error.js +18 -0
  213. package/dist/mcp/mcp-outage.d.ts +31 -0
  214. package/dist/mcp/mcp-outage.js +48 -0
  215. package/dist/mcp/mcp-proxy.d.ts +124 -0
  216. package/dist/mcp/mcp-proxy.js +697 -0
  217. package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
  218. package/dist/{mcp.js → mcp/mcp.js} +110 -35
  219. package/dist/mcp/proxy-handshake.d.ts +3 -0
  220. package/dist/mcp/proxy-handshake.js +54 -0
  221. package/dist/mcp/proxy-lifecycle.d.ts +64 -0
  222. package/dist/mcp/proxy-lifecycle.js +70 -0
  223. package/dist/mcp/tool-catalog-cache.d.ts +29 -0
  224. package/dist/mcp/tool-catalog-cache.js +55 -0
  225. package/dist/oracles/propose-consequences.d.ts +2 -1
  226. package/dist/oracles/propose-consequences.js +16 -11
  227. package/dist/oracles/self-instrument.d.ts +2 -1
  228. package/dist/oracles/self-instrument.js +1 -1
  229. package/dist/phenomena/phenomena.js +3 -3
  230. package/dist/platform.d.ts +16 -0
  231. package/dist/platform.js +16 -0
  232. package/dist/pool/playwright-launcher.d.ts +15 -2
  233. package/dist/pool/playwright-launcher.js +21 -2
  234. package/dist/project/fs-port.js +1 -1
  235. package/dist/project/project-tools.js +2 -2
  236. package/dist/runs/build-verification-run.js +1 -1
  237. package/dist/runs/repair-prompt.d.ts +0 -6
  238. package/dist/runs/repair-prompt.js +3 -3
  239. package/dist/runs/risk-classify.js +1 -1
  240. package/dist/runs/run-diff.d.ts +0 -2
  241. package/dist/runs/run-diff.js +3 -3
  242. package/dist/runs/run-tools.js +2 -2
  243. package/dist/runs/verification-sync.js +2 -2
  244. package/dist/runs/verify-http.js +1 -1
  245. package/dist/runs/verify-server.js +1 -1
  246. package/dist/session/command-timeout.d.ts +11 -3
  247. package/dist/session/command-timeout.js +2 -2
  248. package/dist/session/control-envelope.d.ts +6 -0
  249. package/dist/session/control-envelope.js +7 -1
  250. package/dist/session/dev-server-probe.d.ts +13 -0
  251. package/dist/session/dev-server-probe.js +52 -0
  252. package/dist/session/last-act.d.ts +17 -3
  253. package/dist/session/last-act.js +16 -4
  254. package/dist/session/live-control-tools.js +7 -2
  255. package/dist/session/live-control.js +1 -1
  256. package/dist/session/looks-like-dev-server.d.ts +14 -0
  257. package/dist/session/looks-like-dev-server.js +25 -0
  258. package/dist/session/no-session-diagnosis.d.ts +38 -0
  259. package/dist/session/no-session-diagnosis.js +70 -0
  260. package/dist/session/no-session-watch.d.ts +19 -0
  261. package/dist/session/no-session-watch.js +61 -0
  262. package/dist/session/observed-state.d.ts +4 -0
  263. package/dist/session/observed-state.js +19 -1
  264. package/dist/session/output-budget.js +1 -1
  265. package/dist/session/session-health.d.ts +8 -1
  266. package/dist/session/session-health.js +8 -7
  267. package/dist/session/session-info.d.ts +26 -7
  268. package/dist/session/session-info.js +42 -1
  269. package/dist/session/session-lease.d.ts +0 -11
  270. package/dist/session/session-lease.js +1 -1
  271. package/dist/session/session-manager.d.ts +3 -0
  272. package/dist/session/session-manager.js +58 -9
  273. package/dist/session/session-readiness.d.ts +1 -1
  274. package/dist/session/session-readiness.js +6 -1
  275. package/dist/session/session-reaper.js +1 -1
  276. package/dist/session/session-reconnect.d.ts +32 -0
  277. package/dist/session/session-reconnect.js +42 -0
  278. package/dist/session/session.d.ts +20 -2
  279. package/dist/session/session.js +76 -26
  280. package/dist/session/state-select.d.ts +1 -1
  281. package/dist/session/state-select.js +1 -1
  282. package/dist/status-payload.d.ts +19 -0
  283. package/dist/status-payload.js +11 -0
  284. package/dist/telemetry/argument-shape.js +10 -1
  285. package/dist/telemetry/browser-mode.d.ts +27 -0
  286. package/dist/telemetry/browser-mode.js +33 -0
  287. package/dist/telemetry/bug-found.d.ts +17 -21
  288. package/dist/telemetry/bug-found.js +120 -8
  289. package/dist/telemetry/cli-telemetry.d.ts +2 -12
  290. package/dist/telemetry/cli-telemetry.js +27 -4
  291. package/dist/telemetry/daemon-telemetry.d.ts +19 -0
  292. package/dist/telemetry/daemon-telemetry.js +12 -2
  293. package/dist/telemetry/dev-repo.js +4 -4
  294. package/dist/telemetry/error-fingerprint.js +21 -2
  295. package/dist/telemetry/feedback-cli.d.ts +1 -1
  296. package/dist/telemetry/feedback-cli.js +4 -4
  297. package/dist/telemetry/feedback-context.d.ts +22 -0
  298. package/dist/telemetry/feedback-context.js +41 -1
  299. package/dist/telemetry/feedback-delivery.d.ts +20 -0
  300. package/dist/telemetry/feedback-delivery.js +30 -0
  301. package/dist/telemetry/feedback-outbox.d.ts +22 -0
  302. package/dist/telemetry/feedback-outbox.js +87 -0
  303. package/dist/telemetry/feedback.d.ts +22 -1
  304. package/dist/telemetry/feedback.js +67 -8
  305. package/dist/telemetry/git-facts.js +1 -1
  306. package/dist/telemetry/session-metrics.d.ts +2 -0
  307. package/dist/telemetry/session-metrics.js +68 -6
  308. package/dist/telemetry/telemetry.d.ts +27 -2
  309. package/dist/telemetry/telemetry.js +119 -29
  310. package/dist/telemetry/verification-of.d.ts +22 -0
  311. package/dist/telemetry/verification-of.js +84 -0
  312. package/dist/tools/act-capsule.js +2 -2
  313. package/dist/tools/act-danger.d.ts +12 -0
  314. package/dist/tools/act-danger.js +20 -3
  315. package/dist/tools/act-helpers.js +4 -4
  316. package/dist/tools/act-tools.d.ts +0 -8
  317. package/dist/tools/act-tools.js +84 -115
  318. package/dist/tools/act-view.js +7 -7
  319. package/dist/tools/alias-args.d.ts +17 -0
  320. package/dist/tools/alias-args.js +25 -0
  321. package/dist/tools/assert-grade.js +9 -9
  322. package/dist/tools/assert-verdict.d.ts +3 -1
  323. package/dist/tools/assert-verdict.js +8 -5
  324. package/dist/tools/browser-tools.js +30 -11
  325. package/dist/tools/contract-tools.js +1 -1
  326. package/dist/tools/coverage-identity.d.ts +34 -0
  327. package/dist/tools/coverage-identity.js +46 -0
  328. package/dist/tools/coverage-tools.js +10 -14
  329. package/dist/tools/dynamic-tools.d.ts +2 -1
  330. package/dist/tools/dynamic-tools.js +90 -18
  331. package/dist/tools/error-recovery.d.ts +20 -2
  332. package/dist/tools/error-recovery.js +179 -4
  333. package/dist/tools/feedback-tools.d.ts +12 -1
  334. package/dist/tools/feedback-tools.js +28 -5
  335. package/dist/tools/invoke-tool.d.ts +0 -6
  336. package/dist/tools/invoke-tool.js +57 -32
  337. package/dist/tools/lease-hint.d.ts +17 -0
  338. package/dist/tools/lease-hint.js +24 -0
  339. package/dist/tools/lease-tools.js +6 -5
  340. package/dist/tools/merge-tools.d.ts +10 -1
  341. package/dist/tools/merge-tools.js +9 -3
  342. package/dist/tools/merged-name-redirect.d.ts +13 -0
  343. package/dist/tools/merged-name-redirect.js +55 -0
  344. package/dist/tools/navigate-result.d.ts +17 -0
  345. package/dist/tools/navigate-result.js +31 -0
  346. package/dist/tools/observe-tools.js +54 -20
  347. package/dist/tools/observed-nothing.d.ts +25 -0
  348. package/dist/tools/observed-nothing.js +33 -0
  349. package/dist/tools/query-paginate.js +2 -2
  350. package/dist/tools/query-shape.d.ts +18 -0
  351. package/dist/tools/query-shape.js +39 -0
  352. package/dist/tools/read-tools.js +85 -20
  353. package/dist/tools/real-input-attempt.d.ts +28 -0
  354. package/dist/tools/real-input-attempt.js +88 -0
  355. package/dist/tools/reconcile-tools.js +7 -7
  356. package/dist/tools/reload-result.d.ts +14 -0
  357. package/dist/tools/reload-result.js +29 -0
  358. package/dist/tools/snapshot-delta.d.ts +4 -5
  359. package/dist/tools/snapshot-delta.js +0 -0
  360. package/dist/tools/tool-kit.d.ts +8 -0
  361. package/dist/tools/tool-surface.d.ts +83 -0
  362. package/dist/tools/tool-surface.js +204 -0
  363. package/dist/tools/tools-helpers.js +6 -6
  364. package/dist/tools/tools.d.ts +15 -0
  365. package/dist/tools/tools.js +53 -17
  366. package/dist/tools/unadvertised-help.d.ts +5 -0
  367. package/dist/tools/unadvertised-help.js +39 -0
  368. package/dist/trace.d.ts +69 -0
  369. package/dist/trace.js +150 -0
  370. package/dist/update/nudge-credit.d.ts +4 -0
  371. package/dist/update/nudge-credit.js +53 -0
  372. package/dist/update/sdk-sync.d.ts +21 -0
  373. package/dist/update/sdk-sync.js +42 -0
  374. package/dist/update/update-checker.js +3 -3
  375. package/dist/update/update-nudge.d.ts +63 -6
  376. package/dist/update/update-nudge.js +128 -15
  377. package/dist/update/updater.d.ts +1 -9
  378. package/dist/update/updater.js +13 -8
  379. package/dist/version/peer-announce.d.ts +4 -0
  380. package/dist/version/peer-announce.js +30 -0
  381. package/dist/{server-version.js → version/server-version.js} +5 -1
  382. package/dist/version/version-nudge.d.ts +28 -0
  383. package/dist/version/version-nudge.js +40 -0
  384. package/dist/version/version-skew.d.ts +66 -0
  385. package/dist/version/version-skew.js +71 -0
  386. package/dist/visual/visual-diff.js +2 -2
  387. package/dist/visual/visual-tools.js +4 -4
  388. package/docs/agent-cheatsheet.md +85 -0
  389. package/docs/architecture.md +113 -0
  390. package/docs/benchmarks.md +255 -0
  391. package/docs/debugging.md +102 -0
  392. package/docs/deploy-checks.md +69 -0
  393. package/docs/desktop-apps.md +256 -0
  394. package/docs/enterprise.md +62 -0
  395. package/docs/fixtures.md +28 -0
  396. package/docs/flows.md +166 -0
  397. package/docs/getting-started.md +469 -0
  398. package/docs/human-control.md +63 -0
  399. package/docs/integration-patterns.md +171 -0
  400. package/docs/local-registry.md +126 -0
  401. package/docs/mint.json +61 -0
  402. package/docs/multi-agent-testing.md +55 -0
  403. package/docs/platform-integration.md +122 -0
  404. package/docs/telemetry-contract.md +214 -0
  405. package/docs/telemetry.md +184 -0
  406. package/docs/testing.md +82 -0
  407. package/docs/token-efficiency.md +80 -0
  408. package/docs/usage.md +1046 -0
  409. package/package.json +8 -5
  410. package/dist/cli-launch.js +0 -112
  411. package/dist/cli-parse.d.ts +0 -140
  412. package/dist/daemon-resilience.d.ts +0 -22
  413. package/dist/daemon-resilience.js +0 -85
  414. package/dist/mcp-proxy.d.ts +0 -35
  415. package/dist/mcp-proxy.js +0 -190
  416. package/dist/tools/profiles.d.ts +0 -37
  417. package/dist/tools/profiles.js +0 -139
  418. /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
  419. /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
  420. /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
  421. /package/dist/{cli-doctor.d.ts → cli/cli-doctor.d.ts} +0 -0
  422. /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
  423. /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
  424. /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
@@ -1,6 +1,16 @@
1
- import { EventType, REDACTED_VALUE, isSensitiveKey, scrubKnownSecrets, } from '@reticlehq/core';
1
+ import { EventType, REDACTED_VALUE, defaultIsSensitiveKey, scrubKnownSecrets, } from '@reticlehq/core';
2
+ import { drivenRedactionPolicy } from './driven-redaction.js';
2
3
  /** Bound on a captured wire body — matches the in-page capture so the two are comparable. */
3
4
  const MAX_WIRE_BODY_CHARS = 8192;
5
+ /**
6
+ * The rule this module redacts by.
7
+ *
8
+ * `defaultIsSensitiveKey`, never the ambient `isSensitiveKey`: a daemon serves many sessions in one
9
+ * process, so an ambient policy here would let one app's config decide another app's redaction.
10
+ * Callers that have a session's declarations pass a policy explicitly; everything else gets the
11
+ * built-in floor, which is exactly what this module did before the rule became configurable.
12
+ */
13
+ const DEFAULT_POLICY = { isSensitiveKey: defaultIsSensitiveKey };
4
14
  /**
5
15
  * Redact a sensitive key's value whatever its TYPE — string, number, array, or a nested object.
6
16
  *
@@ -8,19 +18,19 @@ const MAX_WIRE_BODY_CHARS = 8192;
8
18
  * SDK's sanitizer (Playwright hands it over raw), so its redaction has to be as strong as the SDK's,
9
19
  * which is key-based over a parsed object — not string-shaped.
10
20
  */
11
- function redactByKey(value) {
21
+ function redactByKey(value, policy) {
12
22
  if (Array.isArray(value))
13
- return value.map(redactByKey);
14
- if (value !== null && typeof value === 'object') {
23
+ return value.map((v) => redactByKey(v, policy));
24
+ if (value !== null && 'object' === typeof value) {
15
25
  const out = {};
16
26
  for (const [k, v] of Object.entries(value)) {
17
- out[k] = isSensitiveKey(k) ? REDACTED_VALUE : redactByKey(v);
27
+ out[k] = policy.isSensitiveKey(k) ? REDACTED_VALUE : redactByKey(v, policy);
18
28
  }
19
29
  return out;
20
30
  }
21
31
  return value;
22
32
  }
23
- function projectWireBody(raw) {
33
+ function projectWireBody(raw, policy) {
24
34
  const bounded = raw.length > MAX_WIRE_BODY_CHARS ? raw.slice(0, MAX_WIRE_BODY_CHARS) : raw;
25
35
  const byShape = scrubKnownSecrets(bounded);
26
36
  // Prefer a STRUCTURAL pass. A sensitive key must be redacted regardless of its value type — a
@@ -29,7 +39,7 @@ function projectWireBody(raw) {
29
39
  // straight to the agent's context and the on-disk journal. Parsing and walking redacts them by key
30
40
  // whatever the shape.
31
41
  try {
32
- return JSON.stringify(redactByKey(JSON.parse(byShape)));
42
+ return JSON.stringify(redactByKey(JSON.parse(byShape), policy));
33
43
  }
34
44
  catch {
35
45
  // Not JSON (a truncated capture, or a form-encoded body — the shape a login form actually POSTs).
@@ -37,8 +47,8 @@ function projectWireBody(raw) {
37
47
  // truncated body still contains, and the `key=value` pair of `application/x-www-form-urlencoded`,
38
48
  // which neither the JSON path nor the old regex ever touched — so `password=hunter2` leaked.
39
49
  return byShape
40
- .replace(/"([^"]+)"\s*:\s*"([^"]*)"/g, (whole, key) => isSensitiveKey(key) ? `"${key}":"${REDACTED_VALUE}"` : whole)
41
- .replace(/([^&?=\s]+)=([^&\s]*)/g, (whole, key) => isSensitiveKey(key) ? `${key}=${REDACTED_VALUE}` : whole);
50
+ .replace(/"([^"]+)"\s*:\s*"([^"]*)"/g, (whole, key) => policy.isSensitiveKey(key) ? `"${key}":"${REDACTED_VALUE}"` : whole)
51
+ .replace(/([^&?=\s]+)=([^&\s]*)/g, (whole, key) => policy.isSensitiveKey(key) ? `${key}=${REDACTED_VALUE}` : whole);
42
52
  }
43
53
  }
44
54
  /**
@@ -50,31 +60,37 @@ function projectWireBody(raw) {
50
60
  * credential HEADER is redacted whole by key; any other header value is still swept for known secret
51
61
  * SHAPES (a JWT echoed in a custom header), matching how request bodies are handled.
52
62
  */
53
- function projectHeaders(headers) {
63
+ function projectHeaders(headers, policy) {
54
64
  const out = {};
55
65
  for (const [k, v] of Object.entries(headers)) {
56
66
  const key = k.toLowerCase();
57
- out[key] = isSensitiveKey(key) ? REDACTED_VALUE : scrubKnownSecrets(v);
67
+ out[key] = policy.isSensitiveKey(key) ? REDACTED_VALUE : scrubKnownSecrets(v);
58
68
  }
59
69
  return out;
60
70
  }
61
- /** Shape a raw authoritative response into a NET_DETAIL payload (lower-cased headers). */
62
- export function buildNetworkDetail(raw) {
71
+ /**
72
+ * Shape a raw authoritative response into a NET_DETAIL payload (lower-cased headers).
73
+ *
74
+ * `policy` defaults to the built-in rule so this stays a PURE builder — the driven-path union is
75
+ * resolved by `attachNetworkDetail`, at the glue layer, where reading process state is not a lie
76
+ * about the function's inputs.
77
+ */
78
+ export function buildNetworkDetail(raw, policy = DEFAULT_POLICY) {
63
79
  return {
64
80
  url: raw.url,
65
81
  ...(raw.method === undefined ? {} : { method: raw.method }),
66
82
  status: raw.status,
67
- headers: projectHeaders(raw.headers),
83
+ headers: projectHeaders(raw.headers, policy),
68
84
  ...(raw.resourceType === undefined ? {} : { resourceType: raw.resourceType }),
69
- ...(raw.requestBody === undefined || raw.requestBody.length === 0
85
+ ...(raw.requestBody === undefined || 0 === raw.requestBody.length
70
86
  ? {}
71
- : { requestBody: projectWireBody(raw.requestBody) }),
72
- ...(raw.pageUrl === undefined || raw.pageUrl.length === 0 ? {} : { pageUrl: raw.pageUrl }),
87
+ : { requestBody: projectWireBody(raw.requestBody, policy) }),
88
+ ...(raw.pageUrl === undefined || 0 === raw.pageUrl.length ? {} : { pageUrl: raw.pageUrl }),
73
89
  };
74
90
  }
75
91
  function keyOf(url, method) {
76
- const m = typeof method === 'string' ? method.toUpperCase() : '';
77
- const u = typeof url === 'string' ? url : '';
92
+ const m = 'string' === typeof method ? method.toUpperCase() : '';
93
+ const u = 'string' === typeof url ? url : '';
78
94
  return `${m} ${u}`;
79
95
  }
80
96
  /**
@@ -111,9 +127,9 @@ export function mergeNetworkDetail(events) {
111
127
  // finding — that is the whole reason for capturing it — so the authoritative one wins and the
112
128
  // divergence is flagged rather than silently resolved.
113
129
  const wireBody = e.data['requestBody'];
114
- if (typeof wireBody === 'string') {
130
+ if ('string' === typeof wireBody) {
115
131
  const pageBody = data['requestBody'];
116
- if (typeof pageBody === 'string' && pageBody !== wireBody) {
132
+ if ('string' === typeof pageBody && pageBody !== wireBody) {
117
133
  data['requestBodyDivergedFromPage'] = true;
118
134
  }
119
135
  data['requestBody'] = wireBody;
@@ -146,9 +162,13 @@ export function attachNetworkDetail(page, emit) {
146
162
  status: response.status(),
147
163
  headers,
148
164
  ...(resourceType === undefined ? {} : { resourceType }),
149
- ...(postData === null ? {} : { requestBody: postData }),
165
+ ...(null === postData ? {} : { requestBody: postData }),
150
166
  pageUrl: page.url(),
151
- }));
167
+ },
168
+ // Resolved per response, not per attachment: a session declaring extra keys can connect
169
+ // after the listener is attached, and capturing the policy once would leave every
170
+ // already-driven page redacting by the rule that was in force before the app said so.
171
+ drivenRedactionPolicy()));
152
172
  });
153
173
  // `response.headers()` REJECTS when the page/CDP session is closing — precisely when responses race
154
174
  // teardown (navigation, tab close). Without this catch the rejection floats; on the daemon path a
@@ -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 {
@@ -70,20 +70,6 @@ export declare function assertEnterprise(feature: string, ctx: GateContext): voi
70
70
  /** Env names that carry the activation: the operator's key, and the issuer public key baked at release. */
71
71
  export declare const LICENSE_KEY_ENV = "RETICLE_LICENSE_KEY";
72
72
  export declare const LICENSE_PUBLIC_KEY_ENV = "RETICLE_LICENSE_PUBLIC_KEY";
73
- /**
74
- * Issuer public key COMPILED INTO the build. Empty in the source tree; the release pipeline replaces
75
- * this literal with the real spki PEM. Baking it (rather than only reading env) is what makes the
76
- * enterprise gate fail closed: a self-hosted operator can no longer disable enforcement by simply
77
- * never setting RETICLE_LICENSE_PUBLIC_KEY, because the baked key takes precedence. The public key is
78
- * safe to ship openly — it can only verify licenses, never mint them (that needs the private key).
79
- */
80
- export declare const BAKED_ISSUER_PUBLIC_KEY_PEM = "";
81
- /**
82
- * Resolve the issuer public-key PEM enforcement uses: the baked-in release key wins, so it can't be
83
- * turned off from the environment. Only when nothing is baked (dev/repo) does the env var apply — that
84
- * env path is the test/self-eval escape hatch, not the production switch.
85
- */
86
- export declare function resolveIssuerPublicKeyPem(env: NodeJS.ProcessEnv, baked?: string): string | undefined;
87
73
  /** The human-facing state of enterprise activation on this machine (what `reticle license status` shows). */
88
74
  interface LicenseReport {
89
75
  status: 'active' | 'missing' | 'invalid' | 'expired' | 'eval';