@reticlehq/server 3.3.0 → 3.4.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 (299) hide show
  1. package/LICENSE-ENTERPRISE +1 -1
  2. package/README.md +3 -3
  3. package/SKILL.md +12 -14
  4. package/dist/chromium-launch-options.d.ts +4 -3
  5. package/dist/chromium-launch-options.js +6 -2
  6. package/dist/command/cli/adhoc-suite.d.ts +22 -0
  7. package/dist/command/cli/adhoc-suite.js +90 -19
  8. package/dist/command/cli/adhoc-verdict.d.ts +35 -0
  9. package/dist/command/cli/adhoc-verdict.js +90 -3
  10. package/dist/command/cli/answers/gate-hook-message.d.ts +6 -0
  11. package/dist/command/cli/answers/gate-hook-message.js +6 -0
  12. package/dist/command/cli/auth/cloud-keystore.d.ts +0 -2
  13. package/dist/command/cli/auth/cloud-keystore.js +0 -3
  14. package/dist/command/cli/auth/cloud-session.d.ts +4 -0
  15. package/dist/command/cli/auth/cloud-session.js +2 -0
  16. package/dist/command/cli/cli-doctor.js +7 -5
  17. package/dist/command/cli/cli-flow-commands.d.ts +3 -6
  18. package/dist/command/cli/cli-flow-commands.js +67 -4
  19. package/dist/command/cli/cli-parse.d.ts +8 -1
  20. package/dist/command/cli/cli-parse.js +21 -3
  21. package/dist/command/cli/cli-update-commands.js +8 -1
  22. package/dist/command/cli/cli-verify.d.ts +24 -3
  23. package/dist/command/cli/cli-verify.js +54 -11
  24. package/dist/command/cli/cloud-cli.js +5 -2
  25. package/dist/command/cli/cloud-kit.js +3 -5
  26. package/dist/command/cli/cloud-login.js +21 -3
  27. package/dist/command/cli/demo/demo-page.js +6 -3
  28. package/dist/command/cli/doctor/browser/chromium-hint.d.ts +5 -0
  29. package/dist/command/cli/doctor/browser/chromium-hint.js +5 -0
  30. package/dist/command/cli/launch/cli-launch.d.ts +8 -0
  31. package/dist/command/cli/launch/cli-launch.js +21 -9
  32. package/dist/command/cli/launch/sdk-version-match.d.ts +84 -0
  33. package/dist/command/cli/launch/sdk-version-match.js +206 -0
  34. package/dist/command/cli/lifecycle/daemon-lifecycle.js +2 -16
  35. package/dist/command/cli/ports/resolve/cli-port.d.ts +25 -0
  36. package/dist/command/cli/ports/resolve/cli-port.js +125 -15
  37. package/dist/command/cli/setup-mcp-cli.js +13 -13
  38. package/dist/command/cli/tutorial.d.ts +2 -2
  39. package/dist/command/cli/tutorial.js +21 -7
  40. package/dist/command/cli.js +62 -10
  41. package/dist/command/daemon/binding/daemon-status-probe.d.ts +14 -2
  42. package/dist/command/daemon/binding/daemon-status-probe.js +34 -6
  43. package/dist/command/daemon/daemon-resolve.d.ts +9 -0
  44. package/dist/command/daemon/daemon-resolve.js +1 -1
  45. package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +7 -1
  46. package/dist/command/daemon/lifetime/daemon-usefulness.js +30 -7
  47. package/dist/command/dev/stale-issue-guard.d.ts +3 -4
  48. package/dist/command/dev/stale-issue-guard.js +8 -8
  49. package/dist/command/setup/bringup/connect-lease.d.ts +17 -0
  50. package/dist/command/setup/bringup/connect-lease.js +38 -0
  51. package/dist/command/setup/bringup/dev-server-files.d.ts +68 -0
  52. package/dist/command/setup/bringup/dev-server-files.js +131 -0
  53. package/dist/command/setup/bringup/dev-server-log-cap.d.ts +35 -0
  54. package/dist/command/setup/bringup/dev-server-log-cap.js +121 -0
  55. package/dist/command/setup/bringup/ensure-daemon.d.ts +65 -4
  56. package/dist/command/setup/bringup/ensure-daemon.js +135 -16
  57. package/dist/command/setup/bringup/static-page-server.d.ts +35 -0
  58. package/dist/command/setup/bringup/static-page-server.js +151 -0
  59. package/dist/command/setup/desktop-shape.d.ts +4 -0
  60. package/dist/command/setup/desktop-shape.js +18 -2
  61. package/dist/command/setup/init/init-port.d.ts +15 -0
  62. package/dist/command/setup/init/init-port.js +44 -0
  63. package/dist/command/setup/init/init-runtime.d.ts +1 -1
  64. package/dist/command/setup/init/init-runtime.js +39 -2
  65. package/dist/command/setup/node-effects.d.ts +27 -14
  66. package/dist/command/setup/node-effects.js +80 -44
  67. package/dist/command/setup/probe/loopback-probe-urls.d.ts +7 -0
  68. package/dist/command/setup/probe/loopback-probe-urls.js +40 -0
  69. package/dist/command/setup/probe/page-probe.d.ts +13 -2
  70. package/dist/command/setup/probe/page-probe.js +18 -3
  71. package/dist/command/setup/run-setup.d.ts +26 -1
  72. package/dist/command/setup/run-setup.js +96 -13
  73. package/dist/command/setup/session-pick.d.ts +13 -0
  74. package/dist/command/setup/session-pick.js +20 -0
  75. package/dist/command/setup/setup-command.d.ts +2 -14
  76. package/dist/command/setup/setup-command.js +105 -31
  77. package/dist/command/setup/setup-mcp.js +3 -3
  78. package/dist/command/setup/terminal/wait-progress.d.ts +8 -0
  79. package/dist/command/setup/terminal/wait-progress.js +17 -0
  80. package/dist/features/crawl/crawl-empty.js +1 -1
  81. package/dist/features/crawl/crawl-tools.d.ts +6 -0
  82. package/dist/features/crawl/crawl-tools.js +57 -0
  83. package/dist/features/crawl/crawl.js +171 -157
  84. package/dist/features/exhaust/app-coverage.d.ts +33 -0
  85. package/dist/features/exhaust/app-coverage.js +31 -0
  86. package/dist/features/exhaust/code-coverage.d.ts +47 -0
  87. package/dist/features/exhaust/code-coverage.js +77 -0
  88. package/dist/features/exhaust/exhaust-run.d.ts +33 -0
  89. package/dist/features/exhaust/exhaust-run.js +82 -0
  90. package/dist/features/exhaust/explorer.d.ts +103 -0
  91. package/dist/features/exhaust/explorer.js +195 -0
  92. package/dist/features/exhaust/failure-branches.d.ts +33 -0
  93. package/dist/features/exhaust/failure-branches.js +92 -0
  94. package/dist/features/exhaust/ledger.d.ts +202 -0
  95. package/dist/features/exhaust/ledger.js +252 -0
  96. package/dist/features/exhaust/session-fold.d.ts +31 -0
  97. package/dist/features/exhaust/session-fold.js +79 -0
  98. package/dist/features/exhaust/session-port.d.ts +36 -0
  99. package/dist/features/exhaust/session-port.js +102 -0
  100. package/dist/features/harness/drive-report.d.ts +0 -9
  101. package/dist/features/harness/drive-report.js +18 -0
  102. package/dist/features/harness/driver.js +4 -7
  103. package/dist/features/harness/fill-values.d.ts +6 -0
  104. package/dist/features/harness/fill-values.js +3 -0
  105. package/dist/features/harness/jev-driver.js +30 -13
  106. package/dist/features/harness/openai-driver.js +4 -7
  107. package/dist/features/harness/platform-config.js +5 -6
  108. package/dist/index.d.ts +9 -0
  109. package/dist/index.js +40 -11
  110. package/dist/judgement/domain/domain-model.js +3 -1
  111. package/dist/judgement/oracles/self-instrument.js +4 -2
  112. package/dist/judgement/runs/artifact/replay-mapping.d.ts +2 -2
  113. package/dist/judgement/runs/artifact/replay-mapping.js +44 -9
  114. package/dist/judgement/runs/verification-sync.d.ts +3 -1
  115. package/dist/judgement/runs/verification-sync.js +1 -1
  116. package/dist/language/flows/change/affected.d.ts +9 -0
  117. package/dist/language/flows/change/affected.js +35 -0
  118. package/dist/language/flows/change/gate.d.ts +20 -0
  119. package/dist/language/flows/change/gate.js +12 -1
  120. package/dist/language/flows/flow-author.d.ts +7 -0
  121. package/dist/language/flows/flow-author.js +19 -0
  122. package/dist/language/flows/flow-expect-grammar.js +1 -1
  123. package/dist/language/flows/flow-journey.d.ts +54 -0
  124. package/dist/language/flows/flow-journey.js +119 -0
  125. package/dist/language/flows/flow-replay-run.d.ts +2 -3
  126. package/dist/language/flows/flow-replay-run.js +13 -47
  127. package/dist/language/flows/flow-replay.d.ts +22 -8
  128. package/dist/language/flows/flow-replay.js +55 -9
  129. package/dist/language/flows/flow-result.d.ts +2 -0
  130. package/dist/language/flows/flow-result.js +25 -0
  131. package/dist/language/flows/flow-tools.js +17 -5
  132. package/dist/language/flows/flows.d.ts +10 -1
  133. package/dist/language/flows/flows.js +90 -14
  134. package/dist/language/flows/recording/replay-halt.js +3 -1
  135. package/dist/language/flows/recording/tape/recordings.d.ts +30 -1
  136. package/dist/language/flows/recording/tape/recordings.js +55 -1
  137. package/dist/language/flows/replay.d.ts +19 -0
  138. package/dist/language/flows/replay.js +42 -6
  139. package/dist/language/flows/verify-change-tools.js +5 -2
  140. package/dist/launch-chromium.d.ts +80 -0
  141. package/dist/launch-chromium.js +218 -0
  142. package/dist/memory/cloud/cloud-config.d.ts +11 -2
  143. package/dist/memory/cloud/cloud-config.js +47 -7
  144. package/dist/memory/cloud/cloud-sync.d.ts +4 -1
  145. package/dist/memory/cloud/cloud-sync.js +6 -9
  146. package/dist/memory/cloud/harness-offer.js +5 -6
  147. package/dist/memory/cloud/harness-switch.js +5 -6
  148. package/dist/memory/cloud/sync-cycle.d.ts +68 -3
  149. package/dist/memory/cloud/sync-cycle.js +298 -55
  150. package/dist/memory/cloud/sync-daemon.js +24 -20
  151. package/dist/memory/cloud/sync-disk.js +16 -2
  152. package/dist/memory/intent/intent-shard.d.ts +10 -32
  153. package/dist/memory/intent/intent-shard.js +0 -10
  154. package/dist/memory/journal/drive-flow.d.ts +18 -13
  155. package/dist/memory/journal/drive-flow.js +45 -37
  156. package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
  157. package/dist/memory/journal/session-end.d.ts +9 -1
  158. package/dist/memory/journal/session-end.js +24 -12
  159. package/dist/memory/project/dir/reticle-dir.d.ts +2 -0
  160. package/dist/memory/project/dir/reticle-dir.js +1 -0
  161. package/dist/memory/project/project-tools.js +3 -1
  162. package/dist/portal/bridge/auth-failure-reason.d.ts +1 -1
  163. package/dist/portal/bridge/auth-failure-reason.js +4 -2
  164. package/dist/portal/bridge/bridge.d.ts +8 -0
  165. package/dist/portal/bridge/bridge.js +43 -2
  166. package/dist/portal/input/js-coverage.d.ts +25 -0
  167. package/dist/portal/input/js-coverage.js +30 -0
  168. package/dist/portal/input/real-input.d.ts +11 -0
  169. package/dist/portal/input/real-input.js +29 -4
  170. package/dist/portal/pool/playwright-launcher.d.ts +6 -0
  171. package/dist/portal/pool/playwright-launcher.js +20 -13
  172. package/dist/portal/session/dev-server/dev-command.d.ts +2 -2
  173. package/dist/portal/session/dev-server/dev-command.js +30 -12
  174. package/dist/portal/session/dev-server/dev-server-probe.js +17 -1
  175. package/dist/portal/session/dev-server/route-status-probe.d.ts +24 -0
  176. package/dist/portal/session/dev-server/route-status-probe.js +57 -0
  177. package/dist/portal/session/facts/observed-state.d.ts +11 -0
  178. package/dist/portal/session/facts/observed-state.js +34 -0
  179. package/dist/portal/session/no-session-diagnosis.d.ts +29 -0
  180. package/dist/portal/session/no-session-diagnosis.js +62 -5
  181. package/dist/portal/session/no-session-next-action.d.ts +13 -0
  182. package/dist/portal/session/no-session-next-action.js +48 -9
  183. package/dist/portal/session/no-session-watch.d.ts +18 -0
  184. package/dist/portal/session/no-session-watch.js +88 -2
  185. package/dist/portal/session/session-health.js +3 -2
  186. package/dist/portal/session/session-manager.d.ts +20 -6
  187. package/dist/portal/session/session-manager.js +19 -3
  188. package/dist/portal/session/session-reaper.d.ts +28 -0
  189. package/dist/portal/session/session-reaper.js +49 -1
  190. package/dist/portal/session/session.d.ts +5 -0
  191. package/dist/portal/session/session.js +15 -19
  192. package/dist/surface/http-server.d.ts +2 -1
  193. package/dist/surface/http-server.js +4 -2
  194. package/dist/surface/mcp/mcp-proxy.d.ts +2 -2
  195. package/dist/surface/mcp/mcp-proxy.js +2 -2
  196. package/dist/surface/mcp/mcp.js +4 -2
  197. package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +13 -1
  198. package/dist/surface/mcp/proxy/proxy-daemon-probe.js +27 -2
  199. package/dist/surface/mcp/server-instructions.js +9 -7
  200. package/dist/surface/tools/act/after-match.d.ts +17 -0
  201. package/dist/surface/tools/act/after-match.js +30 -0
  202. package/dist/surface/tools/act/durable.d.ts +69 -0
  203. package/dist/surface/tools/act/durable.js +139 -0
  204. package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +13 -6
  205. package/dist/surface/tools/act/navigation/navigate-arrival.js +47 -10
  206. package/dist/surface/tools/act/navigation/navigate-result.d.ts +1 -12
  207. package/dist/surface/tools/act/navigation/navigate-result.js +21 -3
  208. package/dist/surface/tools/act/proved-controls.d.ts +9 -0
  209. package/dist/surface/tools/act/proved-controls.js +11 -0
  210. package/dist/surface/tools/act/sequence-grade.d.ts +5 -0
  211. package/dist/surface/tools/act/sequence-grade.js +32 -1
  212. package/dist/surface/tools/act-capsule.d.ts +7 -0
  213. package/dist/surface/tools/act-capsule.js +46 -1
  214. package/dist/surface/tools/act-sequence-tool.js +25 -8
  215. package/dist/surface/tools/act-tools.js +26 -50
  216. package/dist/surface/tools/assert/assert-grade.js +12 -1
  217. package/dist/surface/tools/assert/assert-verdict.js +2 -2
  218. package/dist/surface/tools/browser-tools.js +14 -2
  219. package/dist/surface/tools/coverage-tools.js +27 -1
  220. package/dist/surface/tools/error-recovery.js +4 -4
  221. package/dist/surface/tools/feedback-invite.js +6 -4
  222. package/dist/surface/tools/harness-explore.d.ts +3 -2
  223. package/dist/surface/tools/harness-explore.js +7 -6
  224. package/dist/surface/tools/lease-tools.js +15 -6
  225. package/dist/surface/tools/live-call-text.js +4 -1
  226. package/dist/surface/tools/observe-tools.js +9 -1
  227. package/dist/surface/tools/tools.js +4 -0
  228. package/dist/telemetry/argument-shape.d.ts +0 -2
  229. package/dist/telemetry/argument-shape.js +0 -4
  230. package/dist/telemetry/error-class.d.ts +2 -3
  231. package/dist/telemetry/error-class.js +2 -3
  232. package/dist/telemetry/harness-drive.d.ts +0 -2
  233. package/dist/telemetry/harness-drive.js +0 -4
  234. package/dist/wire-journal.d.ts +3 -0
  235. package/dist/wire-journal.js +4 -0
  236. package/dist/workspace-packages.d.ts +0 -2
  237. package/dist/workspace-packages.js +1 -9
  238. package/docs/README.md +4 -2
  239. package/docs/actions.mdx +3 -3
  240. package/docs/agent-cheatsheet.md +4 -4
  241. package/docs/architecture.md +6 -6
  242. package/docs/best-practices.mdx +1 -1
  243. package/docs/capabilities.mdx +32 -1
  244. package/docs/cli/cloud.mdx +14 -4
  245. package/docs/cli/doctor.mdx +4 -0
  246. package/docs/cli/feedback.mdx +2 -2
  247. package/docs/cli/gate.mdx +9 -4
  248. package/docs/cli/update.mdx +10 -0
  249. package/docs/cli.mdx +9 -0
  250. package/docs/desktop.mdx +14 -10
  251. package/docs/environment.mdx +87 -0
  252. package/docs/faq.mdx +18 -16
  253. package/docs/first-drive.md +5 -13
  254. package/docs/flows.md +21 -2
  255. package/docs/frameworks.mdx +29 -10
  256. package/docs/getting-started.md +3 -3
  257. package/docs/http-transport.md +6 -3
  258. package/docs/human-control.md +2 -2
  259. package/docs/index.mdx +16 -6
  260. package/docs/install-agentic.mdx +1 -1
  261. package/docs/install-manual.mdx +1 -1
  262. package/docs/integration-patterns.md +3 -3
  263. package/docs/multi-agent-testing.md +1 -1
  264. package/docs/packages/babel-plugin.mdx +1 -1
  265. package/docs/packages/browser.mdx +2 -2
  266. package/docs/packages/react.mdx +2 -2
  267. package/docs/packages/tauri.mdx +1 -1
  268. package/docs/packages/vite-plugin.mdx +2 -2
  269. package/docs/packages.mdx +9 -9
  270. package/docs/predicates.mdx +50 -5
  271. package/docs/quickstart.mdx +2 -2
  272. package/docs/recipes.mdx +2 -2
  273. package/docs/state-management.mdx +2 -2
  274. package/docs/system-map.md +1 -1
  275. package/docs/telemetry.md +1 -1
  276. package/docs/token-efficiency.md +3 -3
  277. package/docs/tools/act-and-wait.mdx +1 -0
  278. package/docs/tools/act-sequence.mdx +1 -1
  279. package/docs/tools/console.mdx +1 -1
  280. package/docs/tools/inspect.mdx +1 -1
  281. package/docs/tools/network.mdx +1 -1
  282. package/docs/tools/query.mdx +1 -1
  283. package/docs/tools/sessions.mdx +1 -1
  284. package/docs/tools/snapshot.mdx +1 -1
  285. package/docs/tools/state.mdx +1 -1
  286. package/docs/tools/wait-for.mdx +1 -1
  287. package/docs/usage.md +7 -6
  288. package/docs/use-cases.mdx +157 -0
  289. package/docs/vs-screenshots.mdx +3 -3
  290. package/docs/what-is-recorded.md +2 -2
  291. package/docs/what-is-reticle.mdx +17 -20
  292. package/docs/why-reticle.mdx +14 -21
  293. package/package.json +10 -9
  294. package/dist/judgement/capsule/minimize.d.ts +0 -12
  295. package/dist/judgement/capsule/minimize.js +0 -22
  296. package/dist/judgement/phenomena/phenomena.d.ts +0 -27
  297. package/dist/judgement/phenomena/phenomena.js +0 -101
  298. package/dist/language/flows/flow-report.d.ts +0 -22
  299. package/dist/language/flows/flow-report.js +0 -106
@@ -1,22 +0,0 @@
1
- /**
2
- * Bug-capsule minimization — first cut: prefix-trim. A recorded flow that fails is often mostly setup;
3
- * the capsule should be the SMALLEST flow that still reproduces the failure, so a regression flow stays
4
- * fast and legible. Prefix-trim drops leading steps while the failure persists — the cheap, deterministic
5
- * v1 (delta-debugging over arbitrary subsets is a later refinement). The `stillFails` predicate is
6
- * injected (a real replay), so this stays pure and unit-testable.
7
- */
8
- /**
9
- * Return the shortest trailing sub-flow that still fails, by removing leading steps one at a time while
10
- * `stillFails` holds. Never trims below one step. Deterministic given a deterministic predicate.
11
- */
12
- export async function prefixTrim(steps, stillFails) {
13
- let kept = [...steps];
14
- while (kept.length > 1) {
15
- const trimmed = kept.slice(1);
16
- if (await stillFails(trimmed))
17
- kept = trimmed;
18
- else
19
- break;
20
- }
21
- return kept;
22
- }
@@ -1,27 +0,0 @@
1
- import { PhenomenonType, type JournalAction, type ReticleEvent } from '@reticlehq/core';
2
- /**
3
- * A detected phenomenon — a named, evidence-backed anomaly over the journal. Deterministic matchers, no
4
- * scanning by the agent: the layer names the fault, the agent acts on the name. `pre-hydration-click`
5
- * lands once the hydration signal (a later item) exists; the three here need only journal data.
6
- */
7
- interface Finding {
8
- phenomenon: PhenomenonType;
9
- evidence: Record<string, unknown>;
10
- }
11
- /** A request that started (NET_PENDING) but never completed (no NET_REQUEST with the same id). */
12
- export declare function detectHungRequests(events: readonly ReticleEvent[]): Finding[];
13
- /** A 5xx response observed while the page was hidden — an error the user never sees. */
14
- export declare function detectHidden500(events: readonly ReticleEvent[]): Finding[];
15
- /** An act that dispatched but attributed no events — the app did nothing. */
16
- export declare function detectDeadClicks(actions: readonly JournalAction[]): Finding[];
17
- /**
18
- * A click that landed BEFORE React hydration attached handlers — a silent no-op. Detectable only in-app:
19
- * the hydration-complete signal's time vs the click action's dispatch. No signal ⇒ can't tell (not a
20
- * React app, or hydration never completed), so we don't guess.
21
- */
22
- export declare function detectPreHydrationClicks(events: readonly ReticleEvent[], actions: readonly JournalAction[]): Finding[];
23
- /** A React error boundary that caught and swallowed — surfaced on the signal channel by the adapter. */
24
- export declare function detectSwallowedErrors(events: readonly ReticleEvent[]): Finding[];
25
- /** Run every journal-only matcher over a session's events + actions. */
26
- export declare function detectPhenomena(events: readonly ReticleEvent[], actions: readonly JournalAction[]): Finding[];
27
- export {};
@@ -1,101 +0,0 @@
1
- import { EventType, FlowStepTool, PhenomenonType, RETICLE_ERROR_BOUNDARY_SIGNAL, RETICLE_HYDRATION_SIGNAL, } from '@reticlehq/core';
2
- /** ACT tools that represent a user-style interaction (a "click"), for dead-click detection. */
3
- const CLICK_TOOLS = new Set([FlowStepTool.ACT, FlowStepTool.ACT_AND_WAIT]);
4
- /** A request that started (NET_PENDING) but never completed (no NET_REQUEST with the same id). */
5
- export function detectHungRequests(events) {
6
- const completed = new Set();
7
- for (const event of events) {
8
- if (event.type === EventType.NET_REQUEST)
9
- completed.add(event.data['id']);
10
- }
11
- const findings = [];
12
- for (const event of events) {
13
- if (event.type !== EventType.NET_PENDING)
14
- continue;
15
- if (completed.has(event.data['id']))
16
- continue;
17
- findings.push({
18
- phenomenon: PhenomenonType.HUNG_REQUEST,
19
- evidence: { id: event.data['id'], method: event.data['method'], url: event.data['url'] },
20
- });
21
- }
22
- return findings;
23
- }
24
- /** A 5xx response observed while the page was hidden — an error the user never sees. */
25
- export function detectHidden500(events) {
26
- const findings = [];
27
- let hidden = false;
28
- for (const event of events) {
29
- if (event.type === EventType.PAGE_HEALTH) {
30
- const h = event.data['hidden'];
31
- if ('boolean' === typeof h)
32
- hidden = h;
33
- continue;
34
- }
35
- if (event.type !== EventType.NET_REQUEST)
36
- continue;
37
- const status = event.data['status'];
38
- if (hidden && 'number' === typeof status && status >= 500) {
39
- findings.push({
40
- phenomenon: PhenomenonType.HIDDEN_500,
41
- evidence: { url: event.data['url'], status, method: event.data['method'] },
42
- });
43
- }
44
- }
45
- return findings;
46
- }
47
- /** An act that dispatched but attributed no events — the app did nothing. */
48
- export function detectDeadClicks(actions) {
49
- const findings = [];
50
- for (const action of actions) {
51
- if (!CLICK_TOOLS.has(action.tool))
52
- continue;
53
- if (action.seqRange !== undefined)
54
- continue; // it caused something → not dead
55
- findings.push({
56
- phenomenon: PhenomenonType.DEAD_CLICK,
57
- evidence: { actionId: action.actionId, tool: action.tool, args: action.args },
58
- });
59
- }
60
- return findings;
61
- }
62
- /**
63
- * A click that landed BEFORE React hydration attached handlers — a silent no-op. Detectable only in-app:
64
- * the hydration-complete signal's time vs the click action's dispatch. No signal ⇒ can't tell (not a
65
- * React app, or hydration never completed), so we don't guess.
66
- */
67
- export function detectPreHydrationClicks(events, actions) {
68
- const hydration = events.find((e) => e.type === EventType.SIGNAL && e.data['name'] === RETICLE_HYDRATION_SIGNAL);
69
- if (hydration === undefined)
70
- return [];
71
- return actions
72
- .filter((a) => CLICK_TOOLS.has(a.tool) && a.tRange.from < hydration.t)
73
- .map((a) => ({
74
- phenomenon: PhenomenonType.PRE_HYDRATION_CLICK,
75
- evidence: { actionId: a.actionId, clickedAt: a.tRange.from, hydratedAt: hydration.t },
76
- }));
77
- }
78
- /** A React error boundary that caught and swallowed — surfaced on the signal channel by the adapter. */
79
- export function detectSwallowedErrors(events) {
80
- const findings = [];
81
- for (const event of events) {
82
- if (event.type === EventType.SIGNAL && event.data['name'] === RETICLE_ERROR_BOUNDARY_SIGNAL) {
83
- const detail = event.data['data'];
84
- findings.push({
85
- phenomenon: PhenomenonType.SWALLOWED_ERROR,
86
- evidence: 'object' === typeof detail && detail !== null ? detail : {},
87
- });
88
- }
89
- }
90
- return findings;
91
- }
92
- /** Run every journal-only matcher over a session's events + actions. */
93
- export function detectPhenomena(events, actions) {
94
- return [
95
- ...detectHungRequests(events),
96
- ...detectHidden500(events),
97
- ...detectDeadClicks(actions),
98
- ...detectPreHydrationClicks(events, actions),
99
- ...detectSwallowedErrors(events),
100
- ];
101
- }
@@ -1,22 +0,0 @@
1
- import { type FlowFile, type FlowReplayResult } from '@reticlehq/core';
2
- /**
3
- * Render a HUMAN-facing confidence report for a replayed flow — the artifact a developer reads to
4
- * trust the test without re-running it. It answers the three confidence questions in one page:
5
- * WHY — the declared business intent (+ whether it is actually asserted).
6
- * WHAT — the journey: a mermaid flow diagram + a per-step page → action → consequence table.
7
- * PROOF — the verdict (pass/drift/fail), the observed evidence (signals/network), and the
8
- * measured cost (deterministic replay tokens vs an LLM re-drive).
9
- *
10
- * Pure: no IO, no clock. Markdown out (mermaid is the one place mermaid earns its tokens — a human
11
- * renders it). Token figures are passed in (measured by the caller), never faked.
12
- */
13
- interface FlowReportInput {
14
- flow: FlowFile;
15
- replay: FlowReplayResult;
16
- /** Measured deterministic replay cost (o200k proxy), for the "PROOF / cost" line. Optional. */
17
- replayTokens?: number;
18
- /** Measured per-run LLM re-drive cost of a step-driving tool, for the ratio. Optional. */
19
- competitorTokens?: number;
20
- }
21
- export declare function buildFlowReport(input: FlowReportInput): string;
22
- export {};
@@ -1,106 +0,0 @@
1
- import { ReplayStatus, } from '@reticlehq/core';
2
- import { classifyFlowAssertions } from './flow-classify.js';
3
- import { SUCCESS_STEP_TOOL } from './flow-success.js';
4
- const VERDICT_GLYPH = {
5
- [ReplayStatus.OK]: '✅ pass',
6
- [ReplayStatus.DRIFT]: '⚠️ drift',
7
- [ReplayStatus.ERROR]: '❌ fail',
8
- };
9
- /** A mermaid-safe node id (mermaid ids must be alnum/underscore). */
10
- function nodeId(index) {
11
- return `s${index}`;
12
- }
13
- /** Escape a label for a mermaid `["..."]` node (quotes/newlines break the parser). */
14
- function mermaidLabel(text) {
15
- return text.replace(/"/g, "'").replace(/\n/g, ' ').slice(0, 80);
16
- }
17
- /** A short action verb for a step row ("act" is the tool; the anchor carries the target). */
18
- function stepAction(step) {
19
- return step.tool === SUCCESS_STEP_TOOL ? 'assert outcome' : step.anchor;
20
- }
21
- /** The mermaid flowchart of the journey: one node per step, page-labelled, consequence on the edge. */
22
- function mermaidDiagram(steps) {
23
- const lines = ['```mermaid', 'flowchart TD'];
24
- steps.forEach((step, i) => {
25
- const page = step.page !== undefined ? `${step.page} — ` : '';
26
- const glyph = step.ok ? '' : ' ✗';
27
- lines.push(` ${nodeId(i)}["${mermaidLabel(`${page}${stepAction(step)}${glyph}`)}"]`);
28
- if (i > 0) {
29
- const edge = steps[i - 1]?.consequence;
30
- const label = edge !== undefined ? `|"${mermaidLabel(edge)}"|` : '';
31
- lines.push(` ${nodeId(i - 1)} -->${label} ${nodeId(i)}`);
32
- }
33
- });
34
- lines.push('```');
35
- return lines.join('\n');
36
- }
37
- /** The per-step journey table (page → action → consequence → result). */
38
- function journeyTable(steps) {
39
- const rows = [
40
- '| # | page | action | consequence | result |',
41
- '|---|------|--------|-------------|--------|',
42
- ];
43
- for (const step of steps) {
44
- const page = step.page ?? '—';
45
- const consequence = step.consequence ?? '—';
46
- const result = step.ok
47
- ? 'ok'
48
- : step.drift !== undefined
49
- ? `drift (${step.drift.anchor})`
50
- : 'fail';
51
- rows.push(`| ${step.step} | ${page} | ${stepAction(step)} | ${consequence} | ${result} |`);
52
- }
53
- return rows.join('\n');
54
- }
55
- /** Distinct observed consequences across the journey — the evidence the verdict rests on. */
56
- function evidenceList(steps) {
57
- const seen = new Set();
58
- for (const step of steps) {
59
- if (step.consequence !== undefined) {
60
- for (const part of step.consequence.split(';'))
61
- seen.add(part.trim());
62
- }
63
- }
64
- if (0 === seen.size)
65
- return '_No observable consequence captured._';
66
- return [...seen].map((e) => `- ${e}`).join('\n');
67
- }
68
- export function buildFlowReport(input) {
69
- const { flow, replay, replayTokens, competitorTokens } = input;
70
- const grade = classifyFlowAssertions(flow);
71
- const verdict = VERDICT_GLYPH[replay.status] ?? replay.status;
72
- const intent = flow.intent ?? '_(no intent declared)_';
73
- const intentLine = flow.intent !== undefined
74
- ? grade.intentVerified
75
- ? `**Intent:** ${flow.intent} — **verified** (an observable outcome is asserted).`
76
- : `**Intent:** ${flow.intent} — ⚠️ declared but NOT asserted (add a consequence oracle).`
77
- : `**Intent:** ${intent}`;
78
- const out = [];
79
- out.push(`# Flow report — \`${flow.name}\``);
80
- out.push('');
81
- out.push(intentLine);
82
- out.push(`**Verdict:** ${verdict} · **steps:** ${replay.steps.length}`);
83
- if (replayTokens !== undefined) {
84
- const ratio = competitorTokens !== undefined && replayTokens > 0
85
- ? ` · **${Math.round(competitorTokens / replayTokens)}×** cheaper than an LLM re-drive`
86
- : '';
87
- out.push(`**Cost:** ${replayTokens} tokens (deterministic replay, no LLM)${ratio}`);
88
- }
89
- if (replay.decision !== undefined) {
90
- out.push('');
91
- out.push(`> **Next action:** ${replay.decision.nextAction}`);
92
- if (replay.decision.whereInSource !== undefined) {
93
- out.push(`> **Where:** \`${replay.decision.whereInSource}\``);
94
- }
95
- }
96
- out.push('');
97
- out.push('## Journey');
98
- out.push(mermaidDiagram(replay.steps));
99
- out.push('');
100
- out.push(journeyTable(replay.steps));
101
- out.push('');
102
- out.push('## Evidence');
103
- out.push(evidenceList(replay.steps));
104
- out.push('');
105
- return out.join('\n');
106
- }