@reticlehq/server 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (778) hide show
  1. package/README.md +1 -1
  2. package/dist/bridge-security.d.ts +0 -1
  3. package/dist/bridge-security.js +0 -1
  4. package/dist/bridge.d.ts +0 -1
  5. package/dist/bridge.js +60 -10
  6. package/dist/bridge.test-harness.d.ts +0 -1
  7. package/dist/bridge.test-harness.js +0 -1
  8. package/dist/capsule/capsule-store.d.ts +2 -3
  9. package/dist/capsule/capsule-store.js +0 -1
  10. package/dist/capsule/capsule.d.ts +0 -1
  11. package/dist/capsule/capsule.js +0 -1
  12. package/dist/capsule/causal-summary.d.ts +21 -1
  13. package/dist/capsule/causal-summary.js +20 -2
  14. package/dist/capsule/divergence.d.ts +0 -1
  15. package/dist/capsule/divergence.js +0 -1
  16. package/dist/capsule/minimize.d.ts +0 -1
  17. package/dist/capsule/minimize.js +0 -1
  18. package/dist/capsule/predicate-to-links.d.ts +0 -1
  19. package/dist/capsule/predicate-to-links.js +0 -1
  20. package/dist/cli-doctor.d.ts +6 -0
  21. package/dist/cli-doctor.js +60 -0
  22. package/dist/cli-flow-commands.d.ts +0 -1
  23. package/dist/cli-flow-commands.js +0 -1
  24. package/dist/cli-launch.d.ts +0 -1
  25. package/dist/cli-launch.js +7 -3
  26. package/dist/cli-parse.d.ts +34 -2
  27. package/dist/cli-parse.js +107 -1
  28. package/dist/cli-port.d.ts +0 -1
  29. package/dist/cli-port.js +0 -1
  30. package/dist/cli-verify.d.ts +0 -1
  31. package/dist/cli-verify.js +1 -2
  32. package/dist/cli.d.ts +0 -1
  33. package/dist/cli.js +79 -67
  34. package/dist/cloud/cloud-config.d.ts +0 -1
  35. package/dist/cloud/cloud-config.js +0 -1
  36. package/dist/cloud/cloud-sync.d.ts +4 -5
  37. package/dist/cloud/cloud-sync.js +0 -1
  38. package/dist/cloud-cli.d.ts +0 -1
  39. package/dist/cloud-cli.js +9 -2
  40. package/dist/crawl/crawl-tools.d.ts +0 -1
  41. package/dist/crawl/crawl-tools.js +1 -2
  42. package/dist/crawl/crawl.d.ts +17 -3
  43. package/dist/crawl/crawl.js +43 -4
  44. package/dist/daemon-resilience.d.ts +6 -1
  45. package/dist/daemon-resilience.js +63 -1
  46. package/dist/daemon.d.ts +23 -3
  47. package/dist/daemon.js +36 -24
  48. package/dist/domain/domain-model.d.ts +0 -1
  49. package/dist/domain/domain-model.js +1 -2
  50. package/dist/domain/domain-tools.d.ts +0 -7
  51. package/dist/domain/domain-tools.js +21 -4
  52. package/dist/domain/flow-risk.d.ts +0 -1
  53. package/dist/domain/flow-risk.js +0 -1
  54. package/dist/ee/audit-log.d.ts +0 -1
  55. package/dist/ee/audit-log.js +0 -1
  56. package/dist/events/body-failures.d.ts +4 -0
  57. package/dist/events/body-failures.js +113 -0
  58. package/dist/events/contradictions.d.ts +53 -0
  59. package/dist/events/contradictions.js +282 -0
  60. package/dist/events/echo-mismatch.d.ts +4 -0
  61. package/dist/events/echo-mismatch.js +138 -0
  62. package/dist/events/event-filters.d.ts +17 -3
  63. package/dist/events/event-filters.js +13 -3
  64. package/dist/events/json-salvage.d.ts +32 -0
  65. package/dist/events/json-salvage.js +96 -0
  66. package/dist/events/predicate-eval.d.ts +2 -1
  67. package/dist/events/predicate-eval.js +56 -9
  68. package/dist/events/predicate.d.ts +0 -1
  69. package/dist/events/predicate.js +56 -2
  70. package/dist/events/reaction.d.ts +0 -1
  71. package/dist/events/reaction.js +0 -1
  72. package/dist/events/reconcile.d.ts +39 -0
  73. package/dist/events/reconcile.js +211 -0
  74. package/dist/events/ring-buffer.d.ts +0 -1
  75. package/dist/events/ring-buffer.js +0 -1
  76. package/dist/events/stale-response.d.ts +4 -0
  77. package/dist/events/stale-response.js +139 -0
  78. package/dist/events/unit-mismatch.d.ts +16 -0
  79. package/dist/events/unit-mismatch.js +167 -0
  80. package/dist/flows/affected-tools.d.ts +18 -0
  81. package/dist/flows/affected-tools.js +52 -0
  82. package/dist/flows/affected.d.ts +0 -1
  83. package/dist/flows/affected.js +0 -1
  84. package/dist/flows/annotate-tools.d.ts +0 -1
  85. package/dist/flows/annotate-tools.js +21 -3
  86. package/dist/flows/annotate.d.ts +0 -1
  87. package/dist/flows/annotate.js +0 -1
  88. package/dist/flows/annotation-store.d.ts +0 -1
  89. package/dist/flows/annotation-store.js +0 -1
  90. package/dist/flows/assertion-integrity.d.ts +0 -1
  91. package/dist/flows/assertion-integrity.js +0 -1
  92. package/dist/flows/assertion-tiers-store.d.ts +0 -1
  93. package/dist/flows/assertion-tiers-store.js +0 -1
  94. package/dist/flows/buddy-status.d.ts +0 -1
  95. package/dist/flows/buddy-status.js +0 -1
  96. package/dist/flows/coverage.d.ts +0 -1
  97. package/dist/flows/coverage.js +0 -1
  98. package/dist/flows/decision.d.ts +0 -1
  99. package/dist/flows/decision.js +0 -1
  100. package/dist/flows/flake-store.d.ts +0 -1
  101. package/dist/flows/flake-store.js +0 -1
  102. package/dist/flows/flake.d.ts +0 -1
  103. package/dist/flows/flake.js +0 -1
  104. package/dist/flows/flow-classify.d.ts +0 -1
  105. package/dist/flows/flow-classify.js +0 -1
  106. package/dist/flows/flow-replay-run.d.ts +0 -1
  107. package/dist/flows/flow-replay-run.js +2 -3
  108. package/dist/flows/flow-replay.d.ts +20 -4
  109. package/dist/flows/flow-replay.js +9 -43
  110. package/dist/flows/flow-report.d.ts +0 -1
  111. package/dist/flows/flow-report.js +0 -1
  112. package/dist/flows/flow-scope.d.ts +0 -1
  113. package/dist/flows/flow-scope.js +0 -1
  114. package/dist/flows/flow-sources.d.ts +0 -1
  115. package/dist/flows/flow-sources.js +0 -1
  116. package/dist/flows/flow-step-runners.d.ts +23 -0
  117. package/dist/flows/flow-step-runners.js +102 -0
  118. package/dist/flows/flow-success.d.ts +0 -1
  119. package/dist/flows/flow-success.js +0 -1
  120. package/dist/flows/flow-tools.d.ts +0 -1
  121. package/dist/flows/flow-tools.js +30 -8
  122. package/dist/flows/flows.d.ts +6 -2
  123. package/dist/flows/flows.js +15 -2
  124. package/dist/flows/gate.d.ts +0 -1
  125. package/dist/flows/gate.js +0 -1
  126. package/dist/flows/git-changed.d.ts +0 -1
  127. package/dist/flows/git-changed.js +0 -1
  128. package/dist/flows/heal-run.d.ts +0 -1
  129. package/dist/flows/heal-run.js +0 -1
  130. package/dist/flows/heal.d.ts +0 -1
  131. package/dist/flows/heal.js +0 -1
  132. package/dist/flows/parallel-suite.d.ts +0 -1
  133. package/dist/flows/parallel-suite.js +0 -1
  134. package/dist/flows/recordings.d.ts +0 -1
  135. package/dist/flows/recordings.js +0 -1
  136. package/dist/flows/replay.d.ts +0 -1
  137. package/dist/flows/replay.js +71 -4
  138. package/dist/flows/server-verify.d.ts +0 -1
  139. package/dist/flows/server-verify.js +0 -1
  140. package/dist/flows/verify-change-tools.d.ts +2 -0
  141. package/dist/flows/verify-change-tools.js +187 -0
  142. package/dist/flows/watch-batcher.d.ts +0 -1
  143. package/dist/flows/watch-batcher.js +0 -1
  144. package/dist/honesty/accepted-write.d.ts +14 -0
  145. package/dist/honesty/accepted-write.js +17 -0
  146. package/dist/honesty/blind-spots.d.ts +18 -1
  147. package/dist/honesty/blind-spots.js +47 -5
  148. package/dist/honesty/honesty.d.ts +0 -1
  149. package/dist/honesty/honesty.js +0 -1
  150. package/dist/honesty/uncaptured-bodies.d.ts +19 -0
  151. package/dist/honesty/uncaptured-bodies.js +30 -0
  152. package/dist/honesty/unread-outcome.d.ts +2 -0
  153. package/dist/honesty/unread-outcome.js +50 -0
  154. package/dist/honesty/verified.d.ts +40 -0
  155. package/dist/honesty/verified.js +86 -0
  156. package/dist/http-server.d.ts +0 -1
  157. package/dist/http-server.js +5 -1
  158. package/dist/hunt/hunt-report.d.ts +50 -0
  159. package/dist/hunt/hunt-report.js +84 -0
  160. package/dist/idle-shutdown.d.ts +0 -1
  161. package/dist/idle-shutdown.js +0 -1
  162. package/dist/index.d.ts +0 -1
  163. package/dist/index.js +0 -1
  164. package/dist/init/agent-rules.d.ts +0 -1
  165. package/dist/init/agent-rules.js +4 -2
  166. package/dist/init/cursor.d.ts +0 -1
  167. package/dist/init/cursor.js +0 -1
  168. package/dist/init/desktop-doctor.d.ts +40 -0
  169. package/dist/init/desktop-doctor.js +198 -0
  170. package/dist/init/detect.d.ts +0 -1
  171. package/dist/init/detect.js +0 -1
  172. package/dist/init/mcp.d.ts +0 -1
  173. package/dist/init/mcp.js +0 -1
  174. package/dist/init/node-io.d.ts +0 -1
  175. package/dist/init/node-io.js +0 -1
  176. package/dist/init/plan.d.ts +4 -1
  177. package/dist/init/plan.js +23 -5
  178. package/dist/init/project-id.d.ts +0 -1
  179. package/dist/init/project-id.js +0 -1
  180. package/dist/init/run.d.ts +0 -1
  181. package/dist/init/run.js +31 -3
  182. package/dist/init/snippets.d.ts +5 -1
  183. package/dist/init/snippets.js +5 -1
  184. package/dist/init/vite-config.d.ts +0 -1
  185. package/dist/init/vite-config.js +0 -1
  186. package/dist/input/network-detail.d.ts +0 -1
  187. package/dist/input/network-detail.js +0 -1
  188. package/dist/input/network-mock-tools.d.ts +0 -1
  189. package/dist/input/network-mock-tools.js +3 -4
  190. package/dist/input/network-mock.d.ts +0 -1
  191. package/dist/input/network-mock.js +0 -1
  192. package/dist/input/real-input.d.ts +14 -1
  193. package/dist/input/real-input.js +45 -3
  194. package/dist/input/scroll-find.d.ts +0 -1
  195. package/dist/input/scroll-find.js +0 -1
  196. package/dist/input/scroll-tools.d.ts +0 -1
  197. package/dist/input/scroll-tools.js +0 -1
  198. package/dist/input/viewport-tools.d.ts +0 -1
  199. package/dist/input/viewport-tools.js +3 -4
  200. package/dist/journal/ambient-store.d.ts +0 -1
  201. package/dist/journal/ambient-store.js +0 -1
  202. package/dist/journal/ambient.d.ts +0 -1
  203. package/dist/journal/ambient.js +0 -1
  204. package/dist/journal/attach-journal.d.ts +0 -1
  205. package/dist/journal/attach-journal.js +0 -1
  206. package/dist/journal/deviation-report.d.ts +0 -1
  207. package/dist/journal/deviation-report.js +0 -1
  208. package/dist/journal/deviation-service.d.ts +0 -1
  209. package/dist/journal/deviation-service.js +0 -1
  210. package/dist/journal/envelope-store.d.ts +0 -1
  211. package/dist/journal/envelope-store.js +0 -1
  212. package/dist/journal/envelope.d.ts +8 -9
  213. package/dist/journal/envelope.js +0 -1
  214. package/dist/journal/journal-query.d.ts +0 -1
  215. package/dist/journal/journal-query.js +0 -1
  216. package/dist/journal/journal-recorder.d.ts +0 -1
  217. package/dist/journal/journal-recorder.js +0 -1
  218. package/dist/journal/retention.d.ts +0 -1
  219. package/dist/journal/retention.js +0 -1
  220. package/dist/journal/rollups.d.ts +0 -1
  221. package/dist/journal/rollups.js +0 -1
  222. package/dist/journal/session-end.d.ts +0 -1
  223. package/dist/journal/session-end.js +0 -1
  224. package/dist/journal/session-journal.d.ts +0 -1
  225. package/dist/journal/session-journal.js +0 -1
  226. package/dist/license/license.d.ts +0 -1
  227. package/dist/license/license.js +0 -1
  228. package/dist/log.d.ts +0 -1
  229. package/dist/log.js +0 -1
  230. package/dist/mcp-proxy.d.ts +0 -1
  231. package/dist/mcp-proxy.js +0 -1
  232. package/dist/mcp.d.ts +15 -1
  233. package/dist/mcp.js +145 -17
  234. package/dist/oracles/flow-instrument-gaps.d.ts +0 -1
  235. package/dist/oracles/flow-instrument-gaps.js +0 -1
  236. package/dist/oracles/propose-consequences.d.ts +0 -1
  237. package/dist/oracles/propose-consequences.js +0 -1
  238. package/dist/oracles/self-instrument.d.ts +0 -1
  239. package/dist/oracles/self-instrument.js +0 -1
  240. package/dist/pairing-token.d.ts +0 -1
  241. package/dist/pairing-token.js +0 -1
  242. package/dist/phenomena/phenomena.d.ts +0 -1
  243. package/dist/phenomena/phenomena.js +0 -1
  244. package/dist/pool/browser-pool.d.ts +0 -1
  245. package/dist/pool/browser-pool.js +0 -1
  246. package/dist/pool/lease-reaper.d.ts +0 -1
  247. package/dist/pool/lease-reaper.js +0 -1
  248. package/dist/pool/playwright-launcher.d.ts +0 -1
  249. package/dist/pool/playwright-launcher.js +10 -2
  250. package/dist/project/baselines.d.ts +0 -1
  251. package/dist/project/baselines.js +0 -1
  252. package/dist/project/file-lock.d.ts +2 -1
  253. package/dist/project/file-lock.js +12 -2
  254. package/dist/project/fs-port.d.ts +0 -1
  255. package/dist/project/fs-port.js +0 -1
  256. package/dist/project/project-store.d.ts +0 -1
  257. package/dist/project/project-store.js +0 -1
  258. package/dist/project/project-tools.d.ts +0 -1
  259. package/dist/project/project-tools.js +29 -4
  260. package/dist/project/reticle-dir.d.ts +0 -1
  261. package/dist/project/reticle-dir.js +0 -1
  262. package/dist/runs/build-verification-run.d.ts +0 -1
  263. package/dist/runs/build-verification-run.js +0 -1
  264. package/dist/runs/profile-redact.d.ts +0 -1
  265. package/dist/runs/profile-redact.js +0 -1
  266. package/dist/runs/render-report.d.ts +0 -1
  267. package/dist/runs/render-report.js +0 -1
  268. package/dist/runs/repair-prompt.d.ts +0 -1
  269. package/dist/runs/repair-prompt.js +0 -1
  270. package/dist/runs/replay-mapping.d.ts +0 -1
  271. package/dist/runs/replay-mapping.js +0 -1
  272. package/dist/runs/reticle-runner.d.ts +0 -1
  273. package/dist/runs/reticle-runner.js +4 -2
  274. package/dist/runs/risk-classify.d.ts +0 -1
  275. package/dist/runs/risk-classify.js +0 -1
  276. package/dist/runs/run-diff.d.ts +0 -1
  277. package/dist/runs/run-diff.js +0 -1
  278. package/dist/runs/run-store.d.ts +0 -1
  279. package/dist/runs/run-store.js +0 -1
  280. package/dist/runs/run-tools.d.ts +0 -1
  281. package/dist/runs/run-tools.js +0 -1
  282. package/dist/runs/runner-port.d.ts +0 -1
  283. package/dist/runs/runner-port.js +0 -1
  284. package/dist/runs/verification-sync.d.ts +0 -1
  285. package/dist/runs/verification-sync.js +0 -1
  286. package/dist/runs/verify-http.d.ts +0 -1
  287. package/dist/runs/verify-http.js +0 -1
  288. package/dist/runs/verify-server.d.ts +0 -1
  289. package/dist/runs/verify-server.js +0 -1
  290. package/dist/server-version.d.ts +0 -1
  291. package/dist/server-version.js +0 -1
  292. package/dist/session/command-timeout.d.ts +35 -0
  293. package/dist/session/command-timeout.js +41 -0
  294. package/dist/session/control-envelope.d.ts +2 -3
  295. package/dist/session/control-envelope.js +2 -3
  296. package/dist/session/last-act.d.ts +31 -0
  297. package/dist/session/last-act.js +24 -0
  298. package/dist/session/live-control-tools.d.ts +0 -1
  299. package/dist/session/live-control-tools.js +3 -4
  300. package/dist/session/live-control.d.ts +0 -1
  301. package/dist/session/live-control.js +0 -1
  302. package/dist/session/observed-state.d.ts +12 -2
  303. package/dist/session/observed-state.js +29 -2
  304. package/dist/session/output-budget.d.ts +0 -1
  305. package/dist/session/output-budget.js +0 -1
  306. package/dist/session/pending-commands.d.ts +12 -0
  307. package/dist/session/pending-commands.js +36 -0
  308. package/dist/session/presenter-args.d.ts +0 -1
  309. package/dist/session/presenter-args.js +0 -1
  310. package/dist/session/review-store.d.ts +0 -1
  311. package/dist/session/review-store.js +0 -1
  312. package/dist/session/session-health.d.ts +26 -2
  313. package/dist/session/session-health.js +13 -1
  314. package/dist/session/session-info.d.ts +29 -0
  315. package/dist/session/session-info.js +1 -0
  316. package/dist/session/session-lease.d.ts +25 -0
  317. package/dist/session/session-lease.js +14 -0
  318. package/dist/session/session-manager.d.ts +7 -19
  319. package/dist/session/session-manager.js +29 -2
  320. package/dist/session/session-readiness.d.ts +0 -1
  321. package/dist/session/session-readiness.js +3 -4
  322. package/dist/session/session-reaper.d.ts +0 -1
  323. package/dist/session/session-reaper.js +0 -1
  324. package/dist/session/session-recommendation.d.ts +0 -1
  325. package/dist/session/session-recommendation.js +0 -1
  326. package/dist/session/session-tools.d.ts +0 -1
  327. package/dist/session/session-tools.js +2 -3
  328. package/dist/session/session.d.ts +27 -53
  329. package/dist/session/session.js +95 -66
  330. package/dist/session/state-select.d.ts +0 -1
  331. package/dist/session/state-select.js +0 -1
  332. package/dist/telemetry/argument-shape.d.ts +41 -0
  333. package/dist/telemetry/argument-shape.js +87 -0
  334. package/dist/telemetry/bug-found.d.ts +33 -0
  335. package/dist/telemetry/bug-found.js +95 -0
  336. package/dist/telemetry/cli-telemetry.d.ts +13 -0
  337. package/dist/telemetry/cli-telemetry.js +43 -0
  338. package/dist/telemetry/connect-failure.d.ts +16 -0
  339. package/dist/telemetry/connect-failure.js +44 -0
  340. package/dist/telemetry/daemon-telemetry.d.ts +19 -0
  341. package/dist/telemetry/daemon-telemetry.js +76 -0
  342. package/dist/telemetry/dev-repo.d.ts +10 -0
  343. package/dist/telemetry/dev-repo.js +80 -0
  344. package/dist/telemetry/error-fingerprint.d.ts +24 -0
  345. package/dist/telemetry/error-fingerprint.js +88 -0
  346. package/dist/telemetry/feedback-cli.d.ts +31 -0
  347. package/dist/telemetry/feedback-cli.js +102 -0
  348. package/dist/telemetry/feedback-context.d.ts +32 -0
  349. package/dist/telemetry/feedback-context.js +143 -0
  350. package/dist/telemetry/feedback.d.ts +66 -0
  351. package/dist/telemetry/feedback.js +175 -0
  352. package/dist/telemetry/git-facts.d.ts +21 -0
  353. package/dist/telemetry/git-facts.js +109 -0
  354. package/dist/telemetry/identify.d.ts +22 -0
  355. package/dist/telemetry/identify.js +73 -0
  356. package/dist/telemetry/init-telemetry.d.ts +26 -0
  357. package/dist/telemetry/init-telemetry.js +33 -0
  358. package/dist/telemetry/machine-snapshot.d.ts +6 -0
  359. package/dist/telemetry/machine-snapshot.js +39 -0
  360. package/dist/telemetry/mcp-connection.d.ts +5 -0
  361. package/dist/telemetry/mcp-connection.js +44 -0
  362. package/dist/telemetry/project-profile.d.ts +44 -0
  363. package/dist/telemetry/project-profile.js +205 -0
  364. package/dist/telemetry/run-telemetry.d.ts +21 -0
  365. package/dist/telemetry/run-telemetry.js +62 -0
  366. package/dist/telemetry/session-metrics.d.ts +103 -0
  367. package/dist/telemetry/session-metrics.js +329 -0
  368. package/dist/telemetry/telemetry.d.ts +35 -8
  369. package/dist/telemetry/telemetry.js +105 -12
  370. package/dist/token-auth.d.ts +0 -1
  371. package/dist/token-auth.js +0 -1
  372. package/dist/tools/act-capsule.d.ts +23 -0
  373. package/dist/tools/act-capsule.js +47 -0
  374. package/dist/tools/act-danger.d.ts +7 -0
  375. package/dist/tools/act-danger.js +44 -0
  376. package/dist/tools/act-helpers.d.ts +17 -0
  377. package/dist/tools/act-helpers.js +40 -0
  378. package/dist/tools/act-tools.d.ts +8 -1
  379. package/dist/tools/act-tools.js +96 -98
  380. package/dist/tools/act-view.d.ts +7 -1
  381. package/dist/tools/act-view.js +13 -1
  382. package/dist/tools/assert-grade.d.ts +22 -1
  383. package/dist/tools/assert-grade.js +46 -1
  384. package/dist/tools/assert-verdict.d.ts +21 -0
  385. package/dist/tools/assert-verdict.js +62 -0
  386. package/dist/tools/browser-tools.d.ts +0 -1
  387. package/dist/tools/browser-tools.js +2 -2
  388. package/dist/tools/contract-tools.d.ts +0 -1
  389. package/dist/tools/contract-tools.js +0 -1
  390. package/dist/tools/coverage-tools.d.ts +9 -0
  391. package/dist/tools/coverage-tools.js +92 -0
  392. package/dist/tools/dynamic-tools.d.ts +0 -1
  393. package/dist/tools/dynamic-tools.js +21 -2
  394. package/dist/tools/error-recovery.d.ts +18 -2
  395. package/dist/tools/error-recovery.js +42 -7
  396. package/dist/tools/feedback-tools.d.ts +24 -0
  397. package/dist/tools/feedback-tools.js +180 -0
  398. package/dist/tools/invoke-tool.d.ts +0 -1
  399. package/dist/tools/invoke-tool.js +115 -5
  400. package/dist/tools/lease-tools.d.ts +0 -1
  401. package/dist/tools/lease-tools.js +6 -5
  402. package/dist/tools/merge-tools.d.ts +0 -1
  403. package/dist/tools/merge-tools.js +0 -1
  404. package/dist/tools/observe-tools.d.ts +0 -1
  405. package/dist/tools/observe-tools.js +91 -39
  406. package/dist/tools/profiles.d.ts +1 -2
  407. package/dist/tools/profiles.js +43 -16
  408. package/dist/tools/query-paginate.d.ts +0 -1
  409. package/dist/tools/query-paginate.js +0 -1
  410. package/dist/tools/read-tools.d.ts +0 -1
  411. package/dist/tools/read-tools.js +10 -8
  412. package/dist/tools/reconcile-tools.d.ts +2 -0
  413. package/dist/tools/reconcile-tools.js +111 -0
  414. package/dist/tools/snapshot-delta.d.ts +0 -1
  415. package/dist/tools/snapshot-delta.js +0 -0
  416. package/dist/tools/tool-invoker.d.ts +0 -1
  417. package/dist/tools/tool-invoker.js +0 -1
  418. package/dist/tools/tool-kit.d.ts +16 -1
  419. package/dist/tools/tool-kit.js +8 -2
  420. package/dist/tools/tool-names.d.ts +6 -1
  421. package/dist/tools/tool-names.js +6 -1
  422. package/dist/tools/tools-helpers.d.ts +0 -1
  423. package/dist/tools/tools-helpers.js +0 -1
  424. package/dist/tools/tools.d.ts +0 -1
  425. package/dist/tools/tools.js +24 -4
  426. package/dist/update/update-checker.d.ts +0 -1
  427. package/dist/update/update-checker.js +0 -1
  428. package/dist/update/update-nudge.d.ts +20 -0
  429. package/dist/update/update-nudge.js +72 -0
  430. package/dist/update/updater.d.ts +14 -1
  431. package/dist/update/updater.js +33 -2
  432. package/dist/visual/visual-diff.d.ts +0 -1
  433. package/dist/visual/visual-diff.js +0 -1
  434. package/dist/visual/visual-store.d.ts +0 -1
  435. package/dist/visual/visual-store.js +0 -1
  436. package/dist/visual/visual-tools.d.ts +0 -1
  437. package/dist/visual/visual-tools.js +103 -16
  438. package/package.json +2 -2
  439. package/dist/bridge-security.d.ts.map +0 -1
  440. package/dist/bridge-security.js.map +0 -1
  441. package/dist/bridge.d.ts.map +0 -1
  442. package/dist/bridge.js.map +0 -1
  443. package/dist/bridge.test-harness.d.ts.map +0 -1
  444. package/dist/bridge.test-harness.js.map +0 -1
  445. package/dist/capsule/capsule-store.d.ts.map +0 -1
  446. package/dist/capsule/capsule-store.js.map +0 -1
  447. package/dist/capsule/capsule.d.ts.map +0 -1
  448. package/dist/capsule/capsule.js.map +0 -1
  449. package/dist/capsule/causal-summary.d.ts.map +0 -1
  450. package/dist/capsule/causal-summary.js.map +0 -1
  451. package/dist/capsule/divergence.d.ts.map +0 -1
  452. package/dist/capsule/divergence.js.map +0 -1
  453. package/dist/capsule/minimize.d.ts.map +0 -1
  454. package/dist/capsule/minimize.js.map +0 -1
  455. package/dist/capsule/predicate-to-links.d.ts.map +0 -1
  456. package/dist/capsule/predicate-to-links.js.map +0 -1
  457. package/dist/cli-flow-commands.d.ts.map +0 -1
  458. package/dist/cli-flow-commands.js.map +0 -1
  459. package/dist/cli-launch.d.ts.map +0 -1
  460. package/dist/cli-launch.js.map +0 -1
  461. package/dist/cli-parse.d.ts.map +0 -1
  462. package/dist/cli-parse.js.map +0 -1
  463. package/dist/cli-port.d.ts.map +0 -1
  464. package/dist/cli-port.js.map +0 -1
  465. package/dist/cli-verify.d.ts.map +0 -1
  466. package/dist/cli-verify.js.map +0 -1
  467. package/dist/cli.d.ts.map +0 -1
  468. package/dist/cli.js.map +0 -1
  469. package/dist/cloud/cloud-config.d.ts.map +0 -1
  470. package/dist/cloud/cloud-config.js.map +0 -1
  471. package/dist/cloud/cloud-sync.d.ts.map +0 -1
  472. package/dist/cloud/cloud-sync.js.map +0 -1
  473. package/dist/cloud-cli.d.ts.map +0 -1
  474. package/dist/cloud-cli.js.map +0 -1
  475. package/dist/crawl/crawl-tools.d.ts.map +0 -1
  476. package/dist/crawl/crawl-tools.js.map +0 -1
  477. package/dist/crawl/crawl.d.ts.map +0 -1
  478. package/dist/crawl/crawl.js.map +0 -1
  479. package/dist/daemon-resilience.d.ts.map +0 -1
  480. package/dist/daemon-resilience.js.map +0 -1
  481. package/dist/daemon.d.ts.map +0 -1
  482. package/dist/daemon.js.map +0 -1
  483. package/dist/domain/domain-model.d.ts.map +0 -1
  484. package/dist/domain/domain-model.js.map +0 -1
  485. package/dist/domain/domain-tools.d.ts.map +0 -1
  486. package/dist/domain/domain-tools.js.map +0 -1
  487. package/dist/domain/flow-risk.d.ts.map +0 -1
  488. package/dist/domain/flow-risk.js.map +0 -1
  489. package/dist/ee/audit-log.d.ts.map +0 -1
  490. package/dist/ee/audit-log.js.map +0 -1
  491. package/dist/events/event-filters.d.ts.map +0 -1
  492. package/dist/events/event-filters.js.map +0 -1
  493. package/dist/events/predicate-eval.d.ts.map +0 -1
  494. package/dist/events/predicate-eval.js.map +0 -1
  495. package/dist/events/predicate.d.ts.map +0 -1
  496. package/dist/events/predicate.js.map +0 -1
  497. package/dist/events/reaction.d.ts.map +0 -1
  498. package/dist/events/reaction.js.map +0 -1
  499. package/dist/events/ring-buffer.d.ts.map +0 -1
  500. package/dist/events/ring-buffer.js.map +0 -1
  501. package/dist/flows/affected.d.ts.map +0 -1
  502. package/dist/flows/affected.js.map +0 -1
  503. package/dist/flows/annotate-tools.d.ts.map +0 -1
  504. package/dist/flows/annotate-tools.js.map +0 -1
  505. package/dist/flows/annotate.d.ts.map +0 -1
  506. package/dist/flows/annotate.js.map +0 -1
  507. package/dist/flows/annotation-store.d.ts.map +0 -1
  508. package/dist/flows/annotation-store.js.map +0 -1
  509. package/dist/flows/assertion-integrity.d.ts.map +0 -1
  510. package/dist/flows/assertion-integrity.js.map +0 -1
  511. package/dist/flows/assertion-tiers-store.d.ts.map +0 -1
  512. package/dist/flows/assertion-tiers-store.js.map +0 -1
  513. package/dist/flows/buddy-status.d.ts.map +0 -1
  514. package/dist/flows/buddy-status.js.map +0 -1
  515. package/dist/flows/coverage.d.ts.map +0 -1
  516. package/dist/flows/coverage.js.map +0 -1
  517. package/dist/flows/decision.d.ts.map +0 -1
  518. package/dist/flows/decision.js.map +0 -1
  519. package/dist/flows/flake-store.d.ts.map +0 -1
  520. package/dist/flows/flake-store.js.map +0 -1
  521. package/dist/flows/flake.d.ts.map +0 -1
  522. package/dist/flows/flake.js.map +0 -1
  523. package/dist/flows/flow-classify.d.ts.map +0 -1
  524. package/dist/flows/flow-classify.js.map +0 -1
  525. package/dist/flows/flow-replay-run.d.ts.map +0 -1
  526. package/dist/flows/flow-replay-run.js.map +0 -1
  527. package/dist/flows/flow-replay.d.ts.map +0 -1
  528. package/dist/flows/flow-replay.js.map +0 -1
  529. package/dist/flows/flow-report.d.ts.map +0 -1
  530. package/dist/flows/flow-report.js.map +0 -1
  531. package/dist/flows/flow-scope.d.ts.map +0 -1
  532. package/dist/flows/flow-scope.js.map +0 -1
  533. package/dist/flows/flow-sources.d.ts.map +0 -1
  534. package/dist/flows/flow-sources.js.map +0 -1
  535. package/dist/flows/flow-success.d.ts.map +0 -1
  536. package/dist/flows/flow-success.js.map +0 -1
  537. package/dist/flows/flow-tools.d.ts.map +0 -1
  538. package/dist/flows/flow-tools.js.map +0 -1
  539. package/dist/flows/flows.d.ts.map +0 -1
  540. package/dist/flows/flows.js.map +0 -1
  541. package/dist/flows/gate.d.ts.map +0 -1
  542. package/dist/flows/gate.js.map +0 -1
  543. package/dist/flows/git-changed.d.ts.map +0 -1
  544. package/dist/flows/git-changed.js.map +0 -1
  545. package/dist/flows/heal-run.d.ts.map +0 -1
  546. package/dist/flows/heal-run.js.map +0 -1
  547. package/dist/flows/heal.d.ts.map +0 -1
  548. package/dist/flows/heal.js.map +0 -1
  549. package/dist/flows/parallel-suite.d.ts.map +0 -1
  550. package/dist/flows/parallel-suite.js.map +0 -1
  551. package/dist/flows/recordings.d.ts.map +0 -1
  552. package/dist/flows/recordings.js.map +0 -1
  553. package/dist/flows/replay.d.ts.map +0 -1
  554. package/dist/flows/replay.js.map +0 -1
  555. package/dist/flows/server-verify.d.ts.map +0 -1
  556. package/dist/flows/server-verify.js.map +0 -1
  557. package/dist/flows/watch-batcher.d.ts.map +0 -1
  558. package/dist/flows/watch-batcher.js.map +0 -1
  559. package/dist/honesty/blind-spots.d.ts.map +0 -1
  560. package/dist/honesty/blind-spots.js.map +0 -1
  561. package/dist/honesty/honesty.d.ts.map +0 -1
  562. package/dist/honesty/honesty.js.map +0 -1
  563. package/dist/http-server.d.ts.map +0 -1
  564. package/dist/http-server.js.map +0 -1
  565. package/dist/idle-shutdown.d.ts.map +0 -1
  566. package/dist/idle-shutdown.js.map +0 -1
  567. package/dist/index.d.ts.map +0 -1
  568. package/dist/index.js.map +0 -1
  569. package/dist/init/agent-rules.d.ts.map +0 -1
  570. package/dist/init/agent-rules.js.map +0 -1
  571. package/dist/init/cursor.d.ts.map +0 -1
  572. package/dist/init/cursor.js.map +0 -1
  573. package/dist/init/detect.d.ts.map +0 -1
  574. package/dist/init/detect.js.map +0 -1
  575. package/dist/init/mcp.d.ts.map +0 -1
  576. package/dist/init/mcp.js.map +0 -1
  577. package/dist/init/node-io.d.ts.map +0 -1
  578. package/dist/init/node-io.js.map +0 -1
  579. package/dist/init/plan.d.ts.map +0 -1
  580. package/dist/init/plan.js.map +0 -1
  581. package/dist/init/project-id.d.ts.map +0 -1
  582. package/dist/init/project-id.js.map +0 -1
  583. package/dist/init/run.d.ts.map +0 -1
  584. package/dist/init/run.js.map +0 -1
  585. package/dist/init/snippets.d.ts.map +0 -1
  586. package/dist/init/snippets.js.map +0 -1
  587. package/dist/init/vite-config.d.ts.map +0 -1
  588. package/dist/init/vite-config.js.map +0 -1
  589. package/dist/input/network-detail.d.ts.map +0 -1
  590. package/dist/input/network-detail.js.map +0 -1
  591. package/dist/input/network-mock-tools.d.ts.map +0 -1
  592. package/dist/input/network-mock-tools.js.map +0 -1
  593. package/dist/input/network-mock.d.ts.map +0 -1
  594. package/dist/input/network-mock.js.map +0 -1
  595. package/dist/input/real-input.d.ts.map +0 -1
  596. package/dist/input/real-input.js.map +0 -1
  597. package/dist/input/scroll-find.d.ts.map +0 -1
  598. package/dist/input/scroll-find.js.map +0 -1
  599. package/dist/input/scroll-tools.d.ts.map +0 -1
  600. package/dist/input/scroll-tools.js.map +0 -1
  601. package/dist/input/viewport-tools.d.ts.map +0 -1
  602. package/dist/input/viewport-tools.js.map +0 -1
  603. package/dist/journal/ambient-store.d.ts.map +0 -1
  604. package/dist/journal/ambient-store.js.map +0 -1
  605. package/dist/journal/ambient.d.ts.map +0 -1
  606. package/dist/journal/ambient.js.map +0 -1
  607. package/dist/journal/attach-journal.d.ts.map +0 -1
  608. package/dist/journal/attach-journal.js.map +0 -1
  609. package/dist/journal/deviation-report.d.ts.map +0 -1
  610. package/dist/journal/deviation-report.js.map +0 -1
  611. package/dist/journal/deviation-service.d.ts.map +0 -1
  612. package/dist/journal/deviation-service.js.map +0 -1
  613. package/dist/journal/envelope-store.d.ts.map +0 -1
  614. package/dist/journal/envelope-store.js.map +0 -1
  615. package/dist/journal/envelope.d.ts.map +0 -1
  616. package/dist/journal/envelope.js.map +0 -1
  617. package/dist/journal/journal-query.d.ts.map +0 -1
  618. package/dist/journal/journal-query.js.map +0 -1
  619. package/dist/journal/journal-recorder.d.ts.map +0 -1
  620. package/dist/journal/journal-recorder.js.map +0 -1
  621. package/dist/journal/retention.d.ts.map +0 -1
  622. package/dist/journal/retention.js.map +0 -1
  623. package/dist/journal/rollups.d.ts.map +0 -1
  624. package/dist/journal/rollups.js.map +0 -1
  625. package/dist/journal/session-end.d.ts.map +0 -1
  626. package/dist/journal/session-end.js.map +0 -1
  627. package/dist/journal/session-journal.d.ts.map +0 -1
  628. package/dist/journal/session-journal.js.map +0 -1
  629. package/dist/license/license.d.ts.map +0 -1
  630. package/dist/license/license.js.map +0 -1
  631. package/dist/log.d.ts.map +0 -1
  632. package/dist/log.js.map +0 -1
  633. package/dist/mcp-proxy.d.ts.map +0 -1
  634. package/dist/mcp-proxy.js.map +0 -1
  635. package/dist/mcp.d.ts.map +0 -1
  636. package/dist/mcp.js.map +0 -1
  637. package/dist/oracles/flow-instrument-gaps.d.ts.map +0 -1
  638. package/dist/oracles/flow-instrument-gaps.js.map +0 -1
  639. package/dist/oracles/propose-consequences.d.ts.map +0 -1
  640. package/dist/oracles/propose-consequences.js.map +0 -1
  641. package/dist/oracles/self-instrument.d.ts.map +0 -1
  642. package/dist/oracles/self-instrument.js.map +0 -1
  643. package/dist/pairing-token.d.ts.map +0 -1
  644. package/dist/pairing-token.js.map +0 -1
  645. package/dist/phenomena/phenomena.d.ts.map +0 -1
  646. package/dist/phenomena/phenomena.js.map +0 -1
  647. package/dist/pool/browser-pool.d.ts.map +0 -1
  648. package/dist/pool/browser-pool.js.map +0 -1
  649. package/dist/pool/lease-reaper.d.ts.map +0 -1
  650. package/dist/pool/lease-reaper.js.map +0 -1
  651. package/dist/pool/playwright-launcher.d.ts.map +0 -1
  652. package/dist/pool/playwright-launcher.js.map +0 -1
  653. package/dist/project/baselines.d.ts.map +0 -1
  654. package/dist/project/baselines.js.map +0 -1
  655. package/dist/project/file-lock.d.ts.map +0 -1
  656. package/dist/project/file-lock.js.map +0 -1
  657. package/dist/project/fs-port.d.ts.map +0 -1
  658. package/dist/project/fs-port.js.map +0 -1
  659. package/dist/project/project-store.d.ts.map +0 -1
  660. package/dist/project/project-store.js.map +0 -1
  661. package/dist/project/project-tools.d.ts.map +0 -1
  662. package/dist/project/project-tools.js.map +0 -1
  663. package/dist/project/reticle-dir.d.ts.map +0 -1
  664. package/dist/project/reticle-dir.js.map +0 -1
  665. package/dist/runs/build-verification-run.d.ts.map +0 -1
  666. package/dist/runs/build-verification-run.js.map +0 -1
  667. package/dist/runs/profile-redact.d.ts.map +0 -1
  668. package/dist/runs/profile-redact.js.map +0 -1
  669. package/dist/runs/render-report.d.ts.map +0 -1
  670. package/dist/runs/render-report.js.map +0 -1
  671. package/dist/runs/repair-prompt.d.ts.map +0 -1
  672. package/dist/runs/repair-prompt.js.map +0 -1
  673. package/dist/runs/replay-mapping.d.ts.map +0 -1
  674. package/dist/runs/replay-mapping.js.map +0 -1
  675. package/dist/runs/reticle-runner.d.ts.map +0 -1
  676. package/dist/runs/reticle-runner.js.map +0 -1
  677. package/dist/runs/risk-classify.d.ts.map +0 -1
  678. package/dist/runs/risk-classify.js.map +0 -1
  679. package/dist/runs/run-diff.d.ts.map +0 -1
  680. package/dist/runs/run-diff.js.map +0 -1
  681. package/dist/runs/run-store.d.ts.map +0 -1
  682. package/dist/runs/run-store.js.map +0 -1
  683. package/dist/runs/run-tools.d.ts.map +0 -1
  684. package/dist/runs/run-tools.js.map +0 -1
  685. package/dist/runs/runner-port.d.ts.map +0 -1
  686. package/dist/runs/runner-port.js.map +0 -1
  687. package/dist/runs/verification-sync.d.ts.map +0 -1
  688. package/dist/runs/verification-sync.js.map +0 -1
  689. package/dist/runs/verify-http.d.ts.map +0 -1
  690. package/dist/runs/verify-http.js.map +0 -1
  691. package/dist/runs/verify-server.d.ts.map +0 -1
  692. package/dist/runs/verify-server.js.map +0 -1
  693. package/dist/server-version.d.ts.map +0 -1
  694. package/dist/server-version.js.map +0 -1
  695. package/dist/session/control-envelope.d.ts.map +0 -1
  696. package/dist/session/control-envelope.js.map +0 -1
  697. package/dist/session/live-control-tools.d.ts.map +0 -1
  698. package/dist/session/live-control-tools.js.map +0 -1
  699. package/dist/session/live-control.d.ts.map +0 -1
  700. package/dist/session/live-control.js.map +0 -1
  701. package/dist/session/observed-state.d.ts.map +0 -1
  702. package/dist/session/observed-state.js.map +0 -1
  703. package/dist/session/output-budget.d.ts.map +0 -1
  704. package/dist/session/output-budget.js.map +0 -1
  705. package/dist/session/presenter-args.d.ts.map +0 -1
  706. package/dist/session/presenter-args.js.map +0 -1
  707. package/dist/session/review-store.d.ts.map +0 -1
  708. package/dist/session/review-store.js.map +0 -1
  709. package/dist/session/session-health.d.ts.map +0 -1
  710. package/dist/session/session-health.js.map +0 -1
  711. package/dist/session/session-manager.d.ts.map +0 -1
  712. package/dist/session/session-manager.js.map +0 -1
  713. package/dist/session/session-readiness.d.ts.map +0 -1
  714. package/dist/session/session-readiness.js.map +0 -1
  715. package/dist/session/session-reaper.d.ts.map +0 -1
  716. package/dist/session/session-reaper.js.map +0 -1
  717. package/dist/session/session-recommendation.d.ts.map +0 -1
  718. package/dist/session/session-recommendation.js.map +0 -1
  719. package/dist/session/session-tools.d.ts.map +0 -1
  720. package/dist/session/session-tools.js.map +0 -1
  721. package/dist/session/session.d.ts.map +0 -1
  722. package/dist/session/session.js.map +0 -1
  723. package/dist/session/state-select.d.ts.map +0 -1
  724. package/dist/session/state-select.js.map +0 -1
  725. package/dist/telemetry/telemetry.d.ts.map +0 -1
  726. package/dist/telemetry/telemetry.js.map +0 -1
  727. package/dist/token-auth.d.ts.map +0 -1
  728. package/dist/token-auth.js.map +0 -1
  729. package/dist/tools/act-tools.d.ts.map +0 -1
  730. package/dist/tools/act-tools.js.map +0 -1
  731. package/dist/tools/act-view.d.ts.map +0 -1
  732. package/dist/tools/act-view.js.map +0 -1
  733. package/dist/tools/assert-grade.d.ts.map +0 -1
  734. package/dist/tools/assert-grade.js.map +0 -1
  735. package/dist/tools/browser-tools.d.ts.map +0 -1
  736. package/dist/tools/browser-tools.js.map +0 -1
  737. package/dist/tools/contract-tools.d.ts.map +0 -1
  738. package/dist/tools/contract-tools.js.map +0 -1
  739. package/dist/tools/dynamic-tools.d.ts.map +0 -1
  740. package/dist/tools/dynamic-tools.js.map +0 -1
  741. package/dist/tools/error-recovery.d.ts.map +0 -1
  742. package/dist/tools/error-recovery.js.map +0 -1
  743. package/dist/tools/invoke-tool.d.ts.map +0 -1
  744. package/dist/tools/invoke-tool.js.map +0 -1
  745. package/dist/tools/lease-tools.d.ts.map +0 -1
  746. package/dist/tools/lease-tools.js.map +0 -1
  747. package/dist/tools/merge-tools.d.ts.map +0 -1
  748. package/dist/tools/merge-tools.js.map +0 -1
  749. package/dist/tools/observe-tools.d.ts.map +0 -1
  750. package/dist/tools/observe-tools.js.map +0 -1
  751. package/dist/tools/profiles.d.ts.map +0 -1
  752. package/dist/tools/profiles.js.map +0 -1
  753. package/dist/tools/query-paginate.d.ts.map +0 -1
  754. package/dist/tools/query-paginate.js.map +0 -1
  755. package/dist/tools/read-tools.d.ts.map +0 -1
  756. package/dist/tools/read-tools.js.map +0 -1
  757. package/dist/tools/snapshot-delta.d.ts.map +0 -1
  758. package/dist/tools/snapshot-delta.js.map +0 -1
  759. package/dist/tools/tool-invoker.d.ts.map +0 -1
  760. package/dist/tools/tool-invoker.js.map +0 -1
  761. package/dist/tools/tool-kit.d.ts.map +0 -1
  762. package/dist/tools/tool-kit.js.map +0 -1
  763. package/dist/tools/tool-names.d.ts.map +0 -1
  764. package/dist/tools/tool-names.js.map +0 -1
  765. package/dist/tools/tools-helpers.d.ts.map +0 -1
  766. package/dist/tools/tools-helpers.js.map +0 -1
  767. package/dist/tools/tools.d.ts.map +0 -1
  768. package/dist/tools/tools.js.map +0 -1
  769. package/dist/update/update-checker.d.ts.map +0 -1
  770. package/dist/update/update-checker.js.map +0 -1
  771. package/dist/update/updater.d.ts.map +0 -1
  772. package/dist/update/updater.js.map +0 -1
  773. package/dist/visual/visual-diff.d.ts.map +0 -1
  774. package/dist/visual/visual-diff.js.map +0 -1
  775. package/dist/visual/visual-store.d.ts.map +0 -1
  776. package/dist/visual/visual-store.js.map +0 -1
  777. package/dist/visual/visual-tools.d.ts.map +0 -1
  778. package/dist/visual/visual-tools.js.map +0 -1
@@ -0,0 +1,282 @@
1
+ import { ContradictionKind, EventType, MUTATING_METHODS } from '@reticlehq/core';
2
+ import { findStaleResponses } from './stale-response.js';
3
+ import { findBodyFailures } from './body-failures.js';
4
+ import { findEchoMismatches } from './echo-mismatch.js';
5
+ import { findUnitMismatches } from './unit-mismatch.js';
6
+ import { asNumber, asString } from '../tools/tools-helpers.js';
7
+ function netCall(e) {
8
+ const status = asNumber(e.data['status']);
9
+ return {
10
+ method: (asString(e.data['method']) ?? '').toUpperCase(),
11
+ url: asString(e.data['url']) ?? '',
12
+ status,
13
+ // `ok` is authoritative when present (IPC sets it explicitly); status is the HTTP fallback.
14
+ // Neither present = no verdict was ever reported, which stays undefined all the way through.
15
+ ok: e.data['ok'] === undefined && status === undefined
16
+ ? undefined
17
+ : e.data['ok'] === true || (e.data['ok'] === undefined && (status ?? 0) < 400),
18
+ };
19
+ }
20
+ /**
21
+ * Did the user-visible application state move forward? DOM, store and route only — deliberately NOT
22
+ * network, animation or signal. The question every rule below asks is "did the app act as if it
23
+ * succeeded", and a request firing is not the app acting as if anything.
24
+ */
25
+ function uiAdvanced(events) {
26
+ return events.some((e) => e.type === EventType.DOM_ADDED ||
27
+ e.type === EventType.DOM_REMOVED ||
28
+ e.type === EventType.DOM_ATTR ||
29
+ e.type === EventType.DOM_TEXT ||
30
+ e.type === EventType.STATE_CHANGE ||
31
+ e.type === EventType.ROUTE_CHANGE);
32
+ }
33
+ function isMutating(call) {
34
+ return MUTATING_METHODS.includes(call.method);
35
+ }
36
+ /**
37
+ * State paths/values that read as the app recording a failure rather than hiding one.
38
+ *
39
+ * English-only, and knowingly so — this is the softest edge in the file. It is a fallback for when
40
+ * the structural check below cannot decide, not the primary signal.
41
+ */
42
+ const ACKNOWLEDGED = /error|fail|invalid|reject|denied|unable|could not|couldn't/i;
43
+ /**
44
+ * Below this length an error string is too generic to be evidence — "no", "err", a bare code — and
45
+ * could coincide with unrelated state text.
46
+ */
47
+ const MIN_ECHOED_ERROR_LENGTH = 8;
48
+ /**
49
+ * Wording that blames the USER — bad credentials, no permission, wrong input. Distinct from
50
+ * ACKNOWLEDGED, which merely means "a failure was recorded": an app can honestly report a failure
51
+ * ("server error, try again") without misattributing it.
52
+ */
53
+ const BLAMES_USER = /denied|invalid|unauthor|forbidden|incorrect|wrong |not allowed|not permitted/i;
54
+ /** A server-fault status: the user cannot fix it and should never be asked to. */
55
+ const SERVER_FAULT_MIN = 500;
56
+ /**
57
+ * Did the app record the failure in its OWN state — the layer the UI renders from?
58
+ *
59
+ * Without this, "the UI moved while a request failed" fires on correct code: a handler that catches
60
+ * the rejection and renders "could not add" also moves the UI. Both look identical at the level of
61
+ * "DOM changed + request failed"; what separates them is whether the app acknowledged the failure
62
+ * anywhere, or silently proceeded as if it had succeeded.
63
+ *
64
+ * Deliberately NOT satisfied by a console error. `console.error` is invisible to the user, so an app
65
+ * that logs and then shows success is still lying to whoever is looking at it — precisely the case
66
+ * worth reporting.
67
+ *
68
+ * A heuristic, and the one soft edge in this file: an app that surfaces failure through a value this
69
+ * pattern does not recognize will produce a finding a human must dismiss. That direction is the safe
70
+ * one — a false alarm costs a glance, a missed false green ships.
71
+ */
72
+ function failureAcknowledged(events) {
73
+ // STRUCTURAL first, and language-independent: if the app put the failed call's OWN error text into
74
+ // its state, it plainly knows the call failed — whatever language it says so in. The lexical
75
+ // patterns below are English-only, so without this a German or Japanese app that surfaces its
76
+ // failure perfectly well would be reported as hiding it.
77
+ const errors = events
78
+ .filter((e) => e.type === EventType.NET_REQUEST && e.data['ok'] !== true)
79
+ .map((e) => asString(e.data['error']))
80
+ .filter((text) => text !== undefined && text.length >= MIN_ECHOED_ERROR_LENGTH);
81
+ const echoesAnError = events.some((e) => {
82
+ if (e.type !== EventType.STATE_CHANGE)
83
+ return false;
84
+ const value = asString(e.data['value']);
85
+ return value !== undefined && errors.some((text) => value.includes(text));
86
+ });
87
+ if (echoesAnError)
88
+ return true;
89
+ return events.some((e) => {
90
+ // A failure-shaped SIGNAL is an acknowledgement too. An app that fires `auth:denied` has plainly
91
+ // not proceeded as if it succeeded, whatever its state paths happen to be named.
92
+ if (e.type === EventType.SIGNAL)
93
+ return ACKNOWLEDGED.test(asString(e.data['name']) ?? '');
94
+ if (e.type !== EventType.STATE_CHANGE)
95
+ return false;
96
+ const path = asString(e.data['path']) ?? '';
97
+ const value = e.data['value'];
98
+ return ACKNOWLEDGED.test(path) || (typeof value === 'string' && ACKNOWLEDGED.test(value));
99
+ });
100
+ }
101
+ function describe(call) {
102
+ return `${call.method} ${call.url}${call.status === undefined ? '' : ` → ${String(call.status)}`}`;
103
+ }
104
+ /**
105
+ * Actions that are SUPPOSED to make something happen, so producing nothing is a finding.
106
+ *
107
+ * Deliberately narrow. `hover`, `focus` and `scrollIntoView` can legitimately move nothing, and
108
+ * `fill`/`type` change an input's value without necessarily mutating the DOM tree — flagging those
109
+ * would manufacture noise, which is the failure mode opposite to a false green and just as bad.
110
+ */
111
+ const MUST_DO_SOMETHING = new Set(['click', 'dblclick', 'submit']);
112
+ /**
113
+ * Whether NOTHING in this window is attributable to the action.
114
+ *
115
+ * Ambient churn is deliberately not counted as evidence the action worked — a background event
116
+ * stream, a polling store, a perf sample and a scroll position all move on their own. What counts:
117
+ *
118
+ * - a mutation inside the target's own subtree (what the target itself did),
119
+ * - a request (the action asked the server for something),
120
+ * - a navigation, or a dialog/live region appearing — the two ways a real reaction legitimately
121
+ * lands OUTSIDE the target, e.g. a modal portalled to the body.
122
+ *
123
+ * The last clause is what keeps this from manufacturing noise: a button that opens a modal mutates
124
+ * nothing within itself, and must not be called dead.
125
+ */
126
+ function didNothing(events, requests, mutatedWithin) {
127
+ if (mutatedWithin === undefined)
128
+ return events.length === 0;
129
+ if (mutatedWithin > 0 || requests.length > 0)
130
+ return false;
131
+ return !events.some((e) => e.type === EventType.ROUTE_CHANGE || e.type === EventType.VISIBLE_SHOWN);
132
+ }
133
+ export function findContradictions(events, options = {}) {
134
+ const found = [];
135
+ const settled = events.filter((e) => e.type === EventType.NET_REQUEST).map(netCall);
136
+ // ── Overlapping reads that settled out of order ─────────────────────────────────────────────
137
+ // Independent of any action, so it runs on every window: the race is a property of the timeline.
138
+ found.push(...findStaleResponses(events));
139
+ // ── A 2xx whose BODY says it failed ─────────────────────────────────────────────────────────
140
+ // Needs body capture; silent without it, which is why the assert path also declares when bodies
141
+ // were never recorded rather than letting an unread payload read as an empty one.
142
+ found.push(...findBodyFailures(events));
143
+ found.push(...findEchoMismatches(events));
144
+ // ── A money value written back at the wrong SCALE ───────────────────────────────────────────
145
+ found.push(...findUnitMismatches(events, options.prior ?? []));
146
+ // ── The action landed on something that does not react ──────────────────────────────────────
147
+ // Checked first and returned alone: nothing is attributable to the action, so every rule below is
148
+ // reasoning about someone else's events.
149
+ const action = (options.action ?? '').toLowerCase();
150
+ if (MUST_DO_SOMETHING.has(action) && didNothing(events, settled, options.mutatedWithin)) {
151
+ const measured = options.mutatedWithin !== undefined;
152
+ return [
153
+ {
154
+ kind: ContradictionKind.ACTION_HAD_NO_EFFECT,
155
+ claim: `the ${action} was dispatched and the page settled`,
156
+ counter: measured
157
+ ? 'nothing changed inside the target, and no request, navigation or dialog followed — whatever else moved on the page was not this'
158
+ : 'no channel observed anything at all — DOM, store, route, network, signal, console',
159
+ detail: 'the target does not react to this action (a non-interactive wrapper resolved instead of the control, a disabled handler, or a no-op) — settling proves only that the page was quiet, which a page that did nothing always is',
160
+ },
161
+ ];
162
+ }
163
+ const failed = settled.filter((c) => c.ok === false);
164
+ const advanced = uiAdvanced(events);
165
+ const signals = events
166
+ .filter((e) => e.type === EventType.SIGNAL)
167
+ .map((e) => asString(e.data['name']) ?? 'signal');
168
+ // ── The route moved and nothing was rendered for it ─────────────────────────────────────────
169
+ // A navigation that neither fetches nor renders arrived nowhere. Distinct from a dead control:
170
+ // the control worked, the DESTINATION is empty — which is why every "did the click do something"
171
+ // heuristic passes it, a route change being unambiguously something.
172
+ const routed = events.some((e) => e.type === EventType.ROUTE_CHANGE);
173
+ const rendered = events.some((e) => e.type === EventType.DOM_ADDED || e.type === EventType.DOM_REMOVED);
174
+ const fetched = events.some((e) => e.type === EventType.NET_REQUEST || e.type === EventType.NET_PENDING);
175
+ if (routed && !rendered && !fetched) {
176
+ found.push({
177
+ kind: ContradictionKind.ROUTE_RENDERED_NOTHING,
178
+ claim: 'the app navigated to a new route',
179
+ counter: 'nothing was rendered for it — no content added or removed, and no request made',
180
+ detail: 'the URL moved but the destination produced no content: a route with no view, a view that returned null, or data the page never asked for. A control that navigates always looks alive, so this is invisible to a dead-control check. Confirm by reading the page — a view revealed from DOM that already existed emits this same window',
181
+ });
182
+ }
183
+ // ── The app claimed success while its own request failed ────────────────────────────────────
184
+ // A signal is the sharper claim: the app did not merely LOOK right, it explicitly asserted
185
+ // success. When both hold it is one fact, so only the sharper one is reported.
186
+ // ── The server faulted and the app blamed the user ──────────────────────────────────────────
187
+ // Checked BEFORE the success-claim rules, because it is the sharper reading of the same events:
188
+ // the app did not claim success, it claimed the wrong failure. Telling someone their password is
189
+ // wrong while the backend is down sends them to fix something they cannot fix.
190
+ const serverFaults = settled.filter((c) => c.ok === false && c.status !== undefined && c.status >= SERVER_FAULT_MIN);
191
+ const userBlame = [
192
+ ...signals.filter((name) => BLAMES_USER.test(name)),
193
+ ...events
194
+ .filter((e) => e.type === EventType.STATE_CHANGE)
195
+ .map((e) => asString(e.data['value']) ?? '')
196
+ .filter((value) => BLAMES_USER.test(value)),
197
+ ];
198
+ const misattributed = serverFaults.length > 0 && userBlame.length > 0;
199
+ if (misattributed) {
200
+ found.push({
201
+ kind: ContradictionKind.FAILURE_MISATTRIBUTED,
202
+ claim: `the app told the user they were at fault (${userBlame.map((b) => `"${b}"`).join(', ')})`,
203
+ counter: 'the server returned a 5xx — the user cannot fix this and the real fault is unreported',
204
+ detail: serverFaults.map(describe).join('; '),
205
+ });
206
+ }
207
+ // A failure-shaped signal is not a success claim, so it must not be read as one: saying "the app
208
+ // claimed success" about an app that plainly reported a failure is true in outline and wrong in
209
+ // its reasoning, which is how a checker stops being believed.
210
+ const successSignals = signals.filter((name) => !ACKNOWLEDGED.test(name));
211
+ if (failed.length > 0 && successSignals.length > 0) {
212
+ found.push({
213
+ kind: ContradictionKind.SIGNAL_CONTRADICTED,
214
+ claim: `the app fired ${successSignals.map((s) => `"${s}"`).join(', ')}`,
215
+ counter: `${String(failed.length)} request(s) in the same window failed`,
216
+ detail: failed.map(describe).join('; '),
217
+ });
218
+ }
219
+ else if (failed.length > 0 && advanced && !misattributed && !failureAcknowledged(events)) {
220
+ found.push({
221
+ kind: ContradictionKind.UI_ADVANCED_REQUEST_FAILED,
222
+ claim: 'the UI moved forward (DOM/store/route changed)',
223
+ counter: `${String(failed.length)} request(s) in the same window failed`,
224
+ detail: failed.map(describe).join('; '),
225
+ });
226
+ }
227
+ // ── A write succeeded and nothing on the client moved ───────────────────────────────────────
228
+ // Writes only: a GET that changes nothing is a prefetch; a POST that changes nothing is a lost
229
+ // write, a response parsed into the void, or a render that never happened.
230
+ if (!advanced) {
231
+ const ignoredWrites = settled.filter((c) => c.ok === true && isMutating(c));
232
+ if (ignoredWrites.length > 0) {
233
+ found.push({
234
+ kind: ContradictionKind.RESPONSE_IGNORED,
235
+ claim: `${String(ignoredWrites.length)} write(s) succeeded on the server`,
236
+ counter: 'nothing on the client changed — no DOM, store or route movement',
237
+ detail: ignoredWrites.map(describe).join('; '),
238
+ });
239
+ }
240
+ }
241
+ // ── The same write fired more than once ─────────────────────────────────────────────────────
242
+ const writeCounts = new Map();
243
+ for (const call of settled) {
244
+ if (!isMutating(call))
245
+ continue;
246
+ const key = `${call.method} ${call.url}`;
247
+ writeCounts.set(key, (writeCounts.get(key) ?? 0) + 1);
248
+ }
249
+ for (const [key, count] of writeCounts) {
250
+ if (count < 2)
251
+ continue;
252
+ found.push({
253
+ kind: ContradictionKind.DUPLICATE_REQUEST,
254
+ claim: 'one user action was performed',
255
+ counter: `the same write fired ${String(count)} times`,
256
+ detail: `${key} ×${String(count)}`,
257
+ });
258
+ }
259
+ // ── The UI advanced over a request that never came back ─────────────────────────────────────
260
+ // Gated on the UI having moved: an in-flight request while the app is still visibly waiting is
261
+ // just a slow request, not a contradiction. It becomes one when the app proceeded regardless —
262
+ // which is also what makes a later `{ kind: "settled" }` assertion a false green.
263
+ if (advanced) {
264
+ const settledIds = new Set(events
265
+ .filter((e) => e.type === EventType.NET_REQUEST)
266
+ .map((e) => asString(e.data['id']))
267
+ .filter((id) => id !== undefined));
268
+ const inFlight = events
269
+ .filter((e) => e.type === EventType.NET_PENDING)
270
+ .map((e) => ({ id: asString(e.data['id']), call: netCall(e) }))
271
+ .filter((p) => p.id === undefined || !settledIds.has(p.id));
272
+ if (inFlight.length > 0) {
273
+ found.push({
274
+ kind: ContradictionKind.REQUEST_NEVER_SETTLED,
275
+ claim: 'the UI moved forward and the action reported done',
276
+ counter: `${String(inFlight.length)} request(s) were still in flight`,
277
+ detail: inFlight.map((p) => describe(p.call)).join('; '),
278
+ });
279
+ }
280
+ }
281
+ return found;
282
+ }
@@ -0,0 +1,4 @@
1
+ import { type ReticleEvent } from '@reticlehq/core';
2
+ import type { Contradiction } from './contradictions.js';
3
+ /** Contradictions for writes whose response echoes a different value than the request asked for. */
4
+ export declare function findEchoMismatches(events: readonly ReticleEvent[]): Contradiction[];
@@ -0,0 +1,138 @@
1
+ import { ContradictionKind, EventType } from '@reticlehq/core';
2
+ /**
3
+ * A write that returned OK and quietly did not apply part of what it was asked to.
4
+ *
5
+ * Measured on a desktop preferences write: the request asked for `{density:'compact', locale:'fr'}`,
6
+ * the response echoed `{"ok":true,"saved":{"density":"compact","locale":"en"}}`, the UI said
7
+ * "Preferences saved", and every channel agreed. `locale` was silently discarded. Nothing above the
8
+ * payload can see this — the status is 200, the body reports no failure, the UI advanced, the page
9
+ * settled. It is a false green with the evidence already in hand.
10
+ *
11
+ * The shape is ordinary in real backends: a field not in the UPDATE statement, a schema that strips
12
+ * unknown keys, a PATCH that honours a subset, an enum that falls back to a default.
13
+ *
14
+ * ## Why this is narrow on purpose
15
+ *
16
+ * Servers legitimately transform what they echo — trimming, lower-casing, rounding, canonicalising,
17
+ * filling defaults, assigning ids and timestamps. A rule that flagged every echoed field that differs
18
+ * would fire on healthy APIs constantly, and a contradiction kind that cries wolf gets filtered out
19
+ * by the agents reading it, taking the true positives with it. So:
20
+ *
21
+ * - only keys the request actually SENT are considered;
22
+ * - only scalars, since deep structural diffing is where the false positives live;
23
+ * - values are compared NORMALISED (trimmed, case-folded, numbers as numbers), so `FR` vs `fr` and
24
+ * `1` vs `1.0` stay silent while `fr` vs `en` speaks;
25
+ * - if the key appears anywhere in the response carrying the requested value, it is treated as
26
+ * applied — an envelope that echoes both the old and the new value is not a dropped write.
27
+ *
28
+ * The residue after those filters is a field the caller set, the server echoed back, and the echoed
29
+ * value is a genuinely different value. That is worth one line of an agent's attention.
30
+ */
31
+ /** Bodies larger than this are skipped — a diff over a huge payload is neither cheap nor legible. */
32
+ const MAX_ECHO_KEYS = 200;
33
+ function isRecord(value) {
34
+ return typeof value === 'object' && value !== null && !Array.isArray(value);
35
+ }
36
+ /**
37
+ * Any JSON value, not just an object. An HTTP write sends an object; an IPC call sends its ARGUMENT
38
+ * LIST, so `savePrefs({locale})` arrives as `[{"locale":"fr"}]`. Requiring a top-level object here
39
+ * silently excluded every desktop write from this check — the exact platform the finding came from.
40
+ */
41
+ function parse(raw) {
42
+ if (typeof raw !== 'string' || raw.length === 0)
43
+ return undefined;
44
+ try {
45
+ return JSON.parse(raw);
46
+ }
47
+ catch {
48
+ return undefined;
49
+ }
50
+ }
51
+ /** Comparable form of a scalar. Non-scalars return undefined and are never compared. */
52
+ function normalize(value) {
53
+ if (typeof value === 'string')
54
+ return value.trim().toLowerCase();
55
+ if (typeof value === 'number')
56
+ return Number.isFinite(value) ? String(value) : undefined;
57
+ if (typeof value === 'boolean')
58
+ return String(value);
59
+ return undefined;
60
+ }
61
+ /**
62
+ * Every scalar value the response carries for each key, at any depth.
63
+ *
64
+ * Depth matters because the echo is usually nested — `{ok:true, saved:{...}}`, `{data:{...}}`,
65
+ * `{result:{...}}` — and demanding the same path as the request would miss nearly every real API.
66
+ * Collecting ALL values for a key is what makes the "echoes both old and new" case safe.
67
+ */
68
+ function scalarsByKey(body, into = new Map(), depth = 0) {
69
+ if (depth > 6 || into.size > MAX_ECHO_KEYS)
70
+ return into;
71
+ if (Array.isArray(body)) {
72
+ for (const item of body)
73
+ scalarsByKey(item, into, depth + 1);
74
+ return into;
75
+ }
76
+ if (!isRecord(body))
77
+ return into;
78
+ for (const [key, value] of Object.entries(body)) {
79
+ const scalar = normalize(value);
80
+ if (scalar === undefined) {
81
+ scalarsByKey(value, into, depth + 1);
82
+ continue;
83
+ }
84
+ const seen = into.get(key) ?? new Set();
85
+ seen.add(scalar);
86
+ into.set(key, seen);
87
+ }
88
+ return into;
89
+ }
90
+ const OK_MIN = 200;
91
+ const OK_MAX = 300;
92
+ /** Contradictions for writes whose response echoes a different value than the request asked for. */
93
+ export function findEchoMismatches(events) {
94
+ const found = [];
95
+ for (const event of events) {
96
+ if (event.type !== EventType.NET_REQUEST)
97
+ continue;
98
+ // IPC reports `ok` rather than a status; HTTP reports a status. Either must say success — a write
99
+ // that already failed is a different (and louder) finding than one that half-applied.
100
+ const status = event.data['status'];
101
+ const httpOk = typeof status === 'number' && status >= OK_MIN && status < OK_MAX;
102
+ if (!httpOk && event.data['ok'] !== true)
103
+ continue;
104
+ const request = parse(event.data['requestBody']);
105
+ const response = parse(event.data['responseBody']);
106
+ if (request === undefined || response === undefined)
107
+ continue;
108
+ const echoed = scalarsByKey(response);
109
+ const asked = scalarsByKey(request);
110
+ const dropped = [];
111
+ for (const [key, wanted] of asked) {
112
+ // More than one requested value for a key (a before/after pair, a list of items) makes "what
113
+ // was asked for" ambiguous, and a guess here is exactly how this kind would earn a reputation
114
+ // for crying wolf.
115
+ if (wanted.size !== 1)
116
+ continue;
117
+ const values = echoed.get(key);
118
+ // Not echoed at all = no evidence either way. Only a key the server chose to report back can
119
+ // contradict the request, and silence is not a contradiction.
120
+ if (values === undefined || values.size === 0)
121
+ continue;
122
+ const [want] = [...wanted];
123
+ if (want !== undefined && !values.has(want))
124
+ dropped.push(`${key}: asked ${want}, got ${[...values].join('/')}`);
125
+ }
126
+ if (dropped.length === 0)
127
+ continue;
128
+ const url = typeof event.data['url'] === 'string' ? event.data['url'] : '';
129
+ const method = typeof event.data['method'] === 'string' ? event.data['method'] : '';
130
+ found.push({
131
+ kind: ContradictionKind.WRITE_FIELD_IGNORED,
132
+ claim: 'the write returned success and the page treated it as saved',
133
+ counter: `its own echo shows ${String(dropped.length)} field(s) NOT applied — ${dropped.join('; ')}`,
134
+ detail: `${method} ${url} — the server answered OK and returned a different value than it was asked to set, so the write half-applied; the UI has no way to know and will show the value the user typed`,
135
+ });
136
+ }
137
+ return found;
138
+ }
@@ -16,8 +16,15 @@ export declare const OBSERVE_FILTER_BUCKETS: Record<string, readonly string[]>;
16
16
  * nothing rather than throwing — a typo narrows the result, it never crashes the observe.
17
17
  */
18
18
  export declare function eventMatchesFilters(e: ReticleEvent, filters: readonly string[]): boolean;
19
- /** Match a net.request event against optional method/url/status filters (reticle_network). */
20
- export declare function matchNet(e: ReticleEvent, method: string | undefined, urlContains: string | undefined, status: number | undefined): boolean;
19
+ /**
20
+ * Match a net.request event against optional method/url/status/ok filters (reticle_network).
21
+ *
22
+ * `ok` is the filter the tool's own description points at for desktop IPC, whose 200/500 is derived
23
+ * rather than sent by any server. A still-PENDING call never matches an `ok` filter in either
24
+ * direction: unresolved is not the same as failed, and answering "yes, it failed" about a request
25
+ * still in flight is the false green this whole surface exists to prevent.
26
+ */
27
+ export declare function matchNet(e: ReticleEvent, method: string | undefined, urlContains: string | undefined, status: number | undefined, ok?: boolean): boolean;
21
28
  /**
22
29
  * Reconcile network events into completed calls + still-in-flight calls. A NET_PENDING whose
23
30
  * `id` never gets a matching NET_REQUEST is an unresolved/hung request — the case
@@ -41,6 +48,14 @@ interface NetCallView {
41
48
  ms?: number;
42
49
  /** Authoritative response headers merged from the driven (CDP) path — present only when driven. */
43
50
  headers?: Record<string, string>;
51
+ /**
52
+ * A fire-and-forget desktop IPC send (`ipcRenderer.send`): dispatched, outcome unknowable.
53
+ *
54
+ * Carried into the projection on purpose. Such a record has no `status` and no `ok`, and without
55
+ * this flag a reader has no way to tell "the outcome is unknown" from "the fields were dropped" —
56
+ * which is the reading that turns an unverifiable call into an assumed success.
57
+ */
58
+ oneWay?: boolean;
44
59
  }
45
60
  export declare function projectNetCall(e: ReticleEvent): NetCallView;
46
61
  /**
@@ -96,4 +111,3 @@ interface ConsoleEmptyHint {
96
111
  }
97
112
  export declare function consoleEmptyHint(allConsole: ReticleEvent[]): ConsoleEmptyHint;
98
113
  export {};
99
- //# sourceMappingURL=event-filters.d.ts.map
@@ -42,8 +42,15 @@ export function eventMatchesFilters(e, filters) {
42
42
  }
43
43
  return false;
44
44
  }
45
- /** Match a net.request event against optional method/url/status filters (reticle_network). */
46
- export function matchNet(e, method, urlContains, status) {
45
+ /**
46
+ * Match a net.request event against optional method/url/status/ok filters (reticle_network).
47
+ *
48
+ * `ok` is the filter the tool's own description points at for desktop IPC, whose 200/500 is derived
49
+ * rather than sent by any server. A still-PENDING call never matches an `ok` filter in either
50
+ * direction: unresolved is not the same as failed, and answering "yes, it failed" about a request
51
+ * still in flight is the false green this whole surface exists to prevent.
52
+ */
53
+ export function matchNet(e, method, urlContains, status, ok) {
47
54
  const d = e.data;
48
55
  if (method !== undefined && asString(d['method'])?.toUpperCase() !== method.toUpperCase()) {
49
56
  return false;
@@ -53,6 +60,8 @@ export function matchNet(e, method, urlContains, status) {
53
60
  }
54
61
  if (status !== undefined && asNumber(d['status']) !== status)
55
62
  return false;
63
+ if (ok !== undefined && d['ok'] !== ok)
64
+ return false;
56
65
  return true;
57
66
  }
58
67
  /**
@@ -106,6 +115,8 @@ export function projectNetCall(e) {
106
115
  }
107
116
  if (ms !== undefined)
108
117
  view.ms = ms;
118
+ if (e.data['oneWay'] === true)
119
+ view.oneWay = true;
109
120
  const headers = e.data['headers'];
110
121
  if (headers !== null && typeof headers === 'object') {
111
122
  view.headers = headers;
@@ -182,4 +193,3 @@ export function consoleEmptyHint(allConsole) {
182
193
  }
183
194
  return { totalInWindow: allConsole.length, byLevel };
184
195
  }
185
- //# sourceMappingURL=event-filters.js.map
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Read what CAN be read out of a truncated JSON payload.
3
+ *
4
+ * Response bodies are capped (8192 bytes) so one enormous payload cannot blow the transport budget.
5
+ * The cap is right; treating what it produces as "no body" is not. Measured on a 10,000-row console:
6
+ * the list response is 19,932 bytes, arrives truncated mid-object, `JSON.parse` throws, and every
7
+ * body-based check — currency reconciliation, per-item failures, unit mismatches — silently reported
8
+ * nothing on the one page with the most data to be wrong about.
9
+ *
10
+ * Worse, the tool then advised turning on body capture, which was already on. Advice that cannot
11
+ * work is more expensive than silence: it sends the reader to change a setting that is already
12
+ * correct, and teaches them the tool does not know what it is looking at.
13
+ *
14
+ * A truncated array of records is still mostly complete records. This recovers the ones that closed
15
+ * before the cut and reports how many it had to drop, so a partial answer is delivered AS partial
16
+ * rather than as a clean one.
17
+ */
18
+ export interface Salvaged {
19
+ /** Parsed values — one whole body, or the records recovered from a truncated one. */
20
+ values: unknown[];
21
+ /** True when the payload was incomplete and only part of it could be read. */
22
+ partial: boolean;
23
+ }
24
+ /**
25
+ * Parse a body, falling back to whole records when it was cut short.
26
+ *
27
+ * The nesting caveat is real and stated rather than hidden: an object cut mid-nesting contributes its
28
+ * completed CHILDREN instead of itself, so a salvaged set can hold records the envelope would have
29
+ * grouped differently. For field-level comparison — is this id's currency rendered correctly — that
30
+ * costs nothing, because each record still carries its own id and its own fields.
31
+ */
32
+ export declare function salvageJson(raw: string): Salvaged;
@@ -0,0 +1,96 @@
1
+ /**
2
+ * Read what CAN be read out of a truncated JSON payload.
3
+ *
4
+ * Response bodies are capped (8192 bytes) so one enormous payload cannot blow the transport budget.
5
+ * The cap is right; treating what it produces as "no body" is not. Measured on a 10,000-row console:
6
+ * the list response is 19,932 bytes, arrives truncated mid-object, `JSON.parse` throws, and every
7
+ * body-based check — currency reconciliation, per-item failures, unit mismatches — silently reported
8
+ * nothing on the one page with the most data to be wrong about.
9
+ *
10
+ * Worse, the tool then advised turning on body capture, which was already on. Advice that cannot
11
+ * work is more expensive than silence: it sends the reader to change a setting that is already
12
+ * correct, and teaches them the tool does not know what it is looking at.
13
+ *
14
+ * A truncated array of records is still mostly complete records. This recovers the ones that closed
15
+ * before the cut and reports how many it had to drop, so a partial answer is delivered AS partial
16
+ * rather than as a clean one.
17
+ */
18
+ /**
19
+ * Complete `{...}` objects inside a truncated payload, in order.
20
+ *
21
+ * NOT top-level ones: a cut body is typically `{"rows":[{…},{…},{…` where the OUTER brace never
22
+ * closes, so nothing at depth 0 completes and a depth-0 scan recovers exactly nothing. The records
23
+ * are one level in.
24
+ *
25
+ * Objects are kept only at the SHALLOWEST depth at which anything closes — that is the record level.
26
+ * Keeping every depth would also return each record's nested children (a shipment's legs, an order's
27
+ * line items), and those carry their own `id` and `status`, which would pollute the comparison with
28
+ * values that were never meant to be rendered as rows.
29
+ */
30
+ function completeObjects(text) {
31
+ const found = [];
32
+ let depth = 0;
33
+ const starts = [];
34
+ let inString = false;
35
+ let escaped = false;
36
+ for (let i = 0; i < text.length; i += 1) {
37
+ const ch = text[i];
38
+ if (inString) {
39
+ if (escaped)
40
+ escaped = false;
41
+ else if (ch === '\\')
42
+ escaped = true;
43
+ else if (ch === '"')
44
+ inString = false;
45
+ continue;
46
+ }
47
+ if (ch === '"') {
48
+ inString = true;
49
+ continue;
50
+ }
51
+ if (ch === '{') {
52
+ starts.push(i);
53
+ depth += 1;
54
+ continue;
55
+ }
56
+ if (ch === '}') {
57
+ depth -= 1;
58
+ // A negative depth means the cut removed an opening brace; nothing further is trustworthy.
59
+ if (depth < 0)
60
+ break;
61
+ const start = starts.pop();
62
+ if (start !== undefined)
63
+ found.push({ depth: depth + 1, text: text.slice(start, i + 1) });
64
+ }
65
+ }
66
+ if (found.length === 0)
67
+ return [];
68
+ const shallowest = Math.min(...found.map((f) => f.depth));
69
+ return found.filter((f) => f.depth === shallowest).map((f) => f.text);
70
+ }
71
+ /**
72
+ * Parse a body, falling back to whole records when it was cut short.
73
+ *
74
+ * The nesting caveat is real and stated rather than hidden: an object cut mid-nesting contributes its
75
+ * completed CHILDREN instead of itself, so a salvaged set can hold records the envelope would have
76
+ * grouped differently. For field-level comparison — is this id's currency rendered correctly — that
77
+ * costs nothing, because each record still carries its own id and its own fields.
78
+ */
79
+ export function salvageJson(raw) {
80
+ try {
81
+ return { values: [JSON.parse(raw)], partial: false };
82
+ }
83
+ catch {
84
+ // fall through to record-level recovery
85
+ }
86
+ const values = [];
87
+ for (const chunk of completeObjects(raw)) {
88
+ try {
89
+ values.push(JSON.parse(chunk));
90
+ }
91
+ catch {
92
+ // a chunk that still will not parse is simply not recovered
93
+ }
94
+ }
95
+ return { values, partial: true };
96
+ }
@@ -15,6 +15,8 @@ export type Predicate = {
15
15
  method?: string;
16
16
  urlContains?: string;
17
17
  status?: number;
18
+ /** Did the call succeed? The honest field for IPC, which has no status code. */
19
+ ok?: boolean;
18
20
  since?: number;
19
21
  count?: number;
20
22
  } | {
@@ -103,4 +105,3 @@ export declare function evalSignal(events: ReticleEvent[], p: Extract<Predicate,
103
105
  export declare function evalSettled(events: ReticleEvent[], p: Extract<Predicate, {
104
106
  kind: 'settled';
105
107
  }>, now: number): EvalResult;
106
- //# sourceMappingURL=predicate-eval.d.ts.map