@reticlehq/server 3.2.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.
- package/LICENSE-ENTERPRISE +1 -1
- package/README.md +3 -3
- package/SKILL.md +23 -22
- package/dist/chromium-launch-options.d.ts +4 -3
- package/dist/chromium-launch-options.js +6 -2
- package/dist/command/cli/adhoc-suite.d.ts +41 -0
- package/dist/command/cli/adhoc-suite.js +159 -0
- package/dist/command/cli/adhoc-verdict.d.ts +58 -2
- package/dist/command/cli/adhoc-verdict.js +108 -13
- package/dist/command/cli/answers/gate-hook-message.d.ts +6 -0
- package/dist/command/cli/answers/gate-hook-message.js +6 -0
- package/dist/command/cli/auth/cloud-keystore.d.ts +0 -2
- package/dist/command/cli/auth/cloud-keystore.js +0 -3
- package/dist/command/cli/auth/cloud-session.d.ts +4 -0
- package/dist/command/cli/auth/cloud-session.js +2 -0
- package/dist/command/cli/cli-doctor.js +30 -8
- package/dist/command/cli/cli-flow-commands.d.ts +3 -6
- package/dist/command/cli/cli-flow-commands.js +67 -4
- package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
- package/dist/command/cli/cli-parse-grammar.js +7 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -5
- package/dist/command/cli/cli-parse-verify.js +86 -13
- package/dist/command/cli/cli-parse.d.ts +14 -1
- package/dist/command/cli/cli-parse.js +54 -8
- package/dist/command/cli/cli-update-commands.js +8 -1
- package/dist/command/cli/cli-verify.d.ts +80 -0
- package/dist/command/cli/cli-verify.js +181 -26
- package/dist/command/cli/cloud-cli.js +5 -2
- package/dist/command/cli/cloud-kit.d.ts +0 -2
- package/dist/command/cli/cloud-kit.js +3 -5
- package/dist/command/cli/cloud-login.js +21 -3
- package/dist/command/cli/demo/demo-page.js +6 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +5 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +5 -0
- package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
- package/dist/command/cli/launch/cli-launch.d.ts +9 -29
- package/dist/command/cli/launch/cli-launch.js +27 -49
- package/dist/command/cli/launch/sdk-version-match.d.ts +84 -0
- package/dist/command/cli/launch/sdk-version-match.js +206 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +2 -16
- package/dist/command/cli/ports/resolve/cli-port.d.ts +38 -0
- package/dist/command/cli/ports/resolve/cli-port.js +169 -15
- package/dist/command/cli/report-command.d.ts +16 -0
- package/dist/command/cli/report-command.js +97 -0
- package/dist/command/cli/setup-mcp-cli.js +13 -13
- package/dist/command/cli/tutorial.d.ts +2 -2
- package/dist/command/cli/tutorial.js +21 -7
- package/dist/command/cli.js +67 -10
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +44 -2
- package/dist/command/daemon/binding/daemon-status-probe.js +79 -6
- package/dist/command/daemon/binding/port-presence.d.ts +1 -1
- package/dist/command/daemon/daemon-resolve.d.ts +9 -0
- package/dist/command/daemon/daemon-resolve.js +1 -1
- package/dist/command/daemon/idle-shutdown.d.ts +2 -1
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +7 -1
- package/dist/command/daemon/lifetime/daemon-usefulness.js +30 -7
- package/dist/command/dev/stale-issue-guard.d.ts +3 -4
- package/dist/command/dev/stale-issue-guard.js +8 -8
- package/dist/command/setup/bringup/connect-lease.d.ts +17 -0
- package/dist/command/setup/bringup/connect-lease.js +38 -0
- package/dist/command/setup/bringup/dev-server-files.d.ts +68 -0
- package/dist/command/setup/bringup/dev-server-files.js +131 -0
- package/dist/command/setup/bringup/dev-server-log-cap.d.ts +35 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +121 -0
- package/dist/command/setup/bringup/ensure-daemon.d.ts +65 -4
- package/dist/command/setup/bringup/ensure-daemon.js +135 -16
- package/dist/command/setup/bringup/static-page-server.d.ts +35 -0
- package/dist/command/setup/bringup/static-page-server.js +151 -0
- package/dist/command/setup/desktop-shape.d.ts +4 -0
- package/dist/command/setup/desktop-shape.js +18 -2
- package/dist/command/setup/init/init-host.js +8 -0
- package/dist/command/setup/init/init-port.d.ts +15 -0
- package/dist/command/setup/init/init-port.js +44 -0
- package/dist/command/setup/init/init-runtime.d.ts +1 -1
- package/dist/command/setup/init/init-runtime.js +39 -2
- package/dist/command/setup/node-effects.d.ts +27 -14
- package/dist/command/setup/node-effects.js +80 -44
- package/dist/command/setup/probe/loopback-probe-urls.d.ts +7 -0
- package/dist/command/setup/probe/loopback-probe-urls.js +40 -0
- package/dist/command/setup/probe/page-probe.d.ts +13 -2
- package/dist/command/setup/probe/page-probe.js +18 -3
- package/dist/command/setup/run-setup.d.ts +26 -1
- package/dist/command/setup/run-setup.js +96 -13
- package/dist/command/setup/session-pick.d.ts +13 -0
- package/dist/command/setup/session-pick.js +20 -0
- package/dist/command/setup/setup-command.d.ts +2 -14
- package/dist/command/setup/setup-command.js +105 -31
- package/dist/command/setup/setup-mcp.js +3 -3
- package/dist/command/setup/terminal/wait-progress.d.ts +8 -0
- package/dist/command/setup/terminal/wait-progress.js +17 -0
- package/dist/features/crawl/crawl-empty.js +1 -1
- package/dist/features/crawl/crawl-tools.d.ts +6 -0
- package/dist/features/crawl/crawl-tools.js +57 -0
- package/dist/features/crawl/crawl.d.ts +2 -0
- package/dist/features/crawl/crawl.js +171 -156
- package/dist/features/exhaust/app-coverage.d.ts +33 -0
- package/dist/features/exhaust/app-coverage.js +31 -0
- package/dist/features/exhaust/code-coverage.d.ts +47 -0
- package/dist/features/exhaust/code-coverage.js +77 -0
- package/dist/features/exhaust/exhaust-run.d.ts +33 -0
- package/dist/features/exhaust/exhaust-run.js +82 -0
- package/dist/features/exhaust/explorer.d.ts +103 -0
- package/dist/features/exhaust/explorer.js +195 -0
- package/dist/features/exhaust/failure-branches.d.ts +33 -0
- package/dist/features/exhaust/failure-branches.js +92 -0
- package/dist/features/exhaust/ledger.d.ts +202 -0
- package/dist/features/exhaust/ledger.js +252 -0
- package/dist/features/exhaust/session-fold.d.ts +31 -0
- package/dist/features/exhaust/session-fold.js +79 -0
- package/dist/features/exhaust/session-port.d.ts +36 -0
- package/dist/features/exhaust/session-port.js +102 -0
- package/dist/features/harness/drive-report.d.ts +0 -9
- package/dist/features/harness/drive-report.js +18 -0
- package/dist/features/harness/driver.js +4 -7
- package/dist/features/harness/fill-values.d.ts +6 -0
- package/dist/features/harness/fill-values.js +3 -0
- package/dist/features/harness/jev-driver.js +36 -22
- package/dist/features/harness/openai-driver.js +4 -7
- package/dist/features/harness/platform-config.d.ts +10 -0
- package/dist/features/harness/platform-config.js +13 -6
- package/dist/index.d.ts +10 -1
- package/dist/index.js +78 -104
- package/dist/judgement/capsule/capsule-store.d.ts +31 -2
- package/dist/judgement/capsule/capsule-store.js +58 -6
- package/dist/judgement/capsule/capsule.js +5 -0
- package/dist/judgement/capsule/causal-summary.d.ts +13 -1
- package/dist/judgement/capsule/causal-summary.js +7 -0
- package/dist/judgement/domain/domain-model.js +40 -9
- package/dist/judgement/oracles/self-instrument.js +4 -2
- package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
- package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
- package/dist/judgement/runs/artifact/gap-report.js +46 -0
- package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
- package/dist/judgement/runs/artifact/gap-summary.js +85 -0
- package/dist/judgement/runs/artifact/render-report.js +4 -1
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +2 -2
- package/dist/judgement/runs/artifact/replay-mapping.js +44 -9
- package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
- package/dist/judgement/runs/artifact/to-artifact.js +1 -1
- package/dist/judgement/runs/context-tools.js +21 -3
- package/dist/judgement/runs/drive-run.js +7 -2
- package/dist/judgement/runs/verification-sync.d.ts +3 -1
- package/dist/judgement/runs/verification-sync.js +1 -1
- package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
- package/dist/language/flows/annotate-notes/annotate.js +66 -18
- package/dist/language/flows/change/affected.d.ts +9 -0
- package/dist/language/flows/change/affected.js +35 -0
- package/dist/language/flows/change/gate.d.ts +20 -0
- package/dist/language/flows/change/gate.js +12 -1
- package/dist/language/flows/flow-anchor.d.ts +12 -0
- package/dist/language/flows/flow-anchor.js +20 -0
- package/dist/language/flows/flow-author.d.ts +7 -0
- package/dist/language/flows/flow-author.js +19 -0
- package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
- package/dist/language/flows/flow-expect-grammar.js +92 -11
- package/dist/language/flows/flow-intent.js +1 -1
- package/dist/language/flows/flow-journey.d.ts +54 -0
- package/dist/language/flows/flow-journey.js +119 -0
- package/dist/language/flows/flow-learning.d.ts +3 -0
- package/dist/language/flows/flow-learning.js +39 -8
- package/dist/language/flows/flow-replay-run.d.ts +33 -12
- package/dist/language/flows/flow-replay-run.js +131 -52
- package/dist/language/flows/flow-replay-types.d.ts +9 -0
- package/dist/language/flows/flow-replay.d.ts +27 -12
- package/dist/language/flows/flow-replay.js +127 -111
- package/dist/language/flows/flow-result.d.ts +2 -0
- package/dist/language/flows/flow-result.js +25 -0
- package/dist/language/flows/flow-step-runners.d.ts +26 -10
- package/dist/language/flows/flow-step-runners.js +20 -4
- package/dist/language/flows/flow-success.d.ts +21 -6
- package/dist/language/flows/flow-success.js +50 -138
- package/dist/language/flows/flow-tools.js +17 -5
- package/dist/language/flows/flows.d.ts +18 -5
- package/dist/language/flows/flows.js +101 -16
- package/dist/language/flows/heal.d.ts +9 -1
- package/dist/language/flows/heal.js +24 -2
- package/dist/language/flows/learned-sources.d.ts +21 -0
- package/dist/language/flows/learned-sources.js +84 -0
- package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
- package/dist/language/flows/recording/recording-backtrack.js +1 -1
- package/dist/language/flows/recording/replay-halt.d.ts +2 -1
- package/dist/language/flows/recording/replay-halt.js +3 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +31 -2
- package/dist/language/flows/recording/tape/recordings.js +55 -1
- package/dist/language/flows/replay.d.ts +19 -0
- package/dist/language/flows/replay.js +53 -13
- package/dist/language/flows/stores/annotation-store.d.ts +5 -5
- package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
- package/dist/language/flows/stores/flake-store.js +2 -3
- package/dist/language/flows/suite/coverage.d.ts +1 -1
- package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
- package/dist/language/flows/verify-change-tools.js +19 -2
- package/dist/launch-chromium.d.ts +80 -0
- package/dist/launch-chromium.js +218 -0
- package/dist/memory/cloud/cloud-config.d.ts +11 -2
- package/dist/memory/cloud/cloud-config.js +47 -7
- package/dist/memory/cloud/cloud-sync.d.ts +4 -3
- package/dist/memory/cloud/cloud-sync.js +7 -10
- package/dist/memory/cloud/harness-config.d.ts +2 -0
- package/dist/memory/cloud/harness-offer.js +5 -6
- package/dist/memory/cloud/harness-switch.js +5 -6
- package/dist/memory/cloud/sync-cycle.d.ts +78 -1
- package/dist/memory/cloud/sync-cycle.js +321 -53
- package/dist/memory/cloud/sync-daemon.d.ts +13 -0
- package/dist/memory/cloud/sync-daemon.js +45 -20
- package/dist/memory/cloud/sync-disk.js +27 -8
- package/dist/memory/impact/impact-store.js +6 -0
- package/dist/memory/intent/inline-intent.js +8 -3
- package/dist/memory/intent/intent-shard-store.d.ts +33 -47
- package/dist/memory/intent/intent-shard-store.js +252 -140
- package/dist/memory/intent/intent-shard.d.ts +0 -23
- package/dist/memory/intent/intent-shard.js +1 -11
- package/dist/memory/intent/intent-store.d.ts +13 -8
- package/dist/memory/intent/intent-store.js +46 -90
- package/dist/memory/intent/intent-tools.js +34 -23
- package/dist/memory/journal/ambient-store.js +2 -3
- package/dist/memory/journal/deviation-report.js +4 -1
- package/dist/memory/journal/deviation-service.js +10 -2
- package/dist/memory/journal/drive-flow.d.ts +19 -14
- package/dist/memory/journal/drive-flow.js +65 -48
- package/dist/memory/journal/envelope-store.js +2 -3
- package/dist/memory/journal/journal-recorder.d.ts +21 -0
- package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
- package/dist/memory/journal/on-disk/retain-policy.js +44 -0
- package/dist/memory/journal/on-disk/retention.d.ts +14 -10
- package/dist/memory/journal/on-disk/retention.js +13 -12
- package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
- package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -11
- package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -45
- package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
- package/dist/memory/journal/on-disk/workspace-tiers.js +90 -0
- package/dist/memory/journal/route-template.d.ts +22 -0
- package/dist/memory/journal/route-template.js +44 -0
- package/dist/memory/journal/session-end.d.ts +13 -2
- package/dist/memory/journal/session-end.js +88 -18
- package/dist/memory/journal/session-journal.d.ts +8 -1
- package/dist/memory/journal/session-journal.js +10 -0
- package/dist/memory/project/baselines.d.ts +1 -1
- package/dist/memory/project/dir/reticle-dir.d.ts +3 -1
- package/dist/memory/project/dir/reticle-dir.js +1 -0
- package/dist/memory/project/fs/fs-port.js +44 -5
- package/dist/memory/project/fs/write-atomic.d.ts +26 -0
- package/dist/memory/project/fs/write-atomic.js +48 -0
- package/dist/memory/project/project-tools.js +3 -1
- package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
- package/dist/memory/recall/prior/connection-memory.js +8 -0
- package/dist/memory/recall/registered-projects.d.ts +2 -1
- package/dist/portal/bridge/auth-failure-reason.d.ts +1 -1
- package/dist/portal/bridge/auth-failure-reason.js +9 -4
- package/dist/portal/bridge/bridge.d.ts +8 -0
- package/dist/portal/bridge/bridge.js +43 -2
- package/dist/portal/input/js-coverage.d.ts +25 -0
- package/dist/portal/input/js-coverage.js +30 -0
- package/dist/portal/input/real-input.d.ts +11 -0
- package/dist/portal/input/real-input.js +31 -5
- package/dist/portal/pool/browser-pool.d.ts +10 -0
- package/dist/portal/pool/browser-pool.js +10 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +21 -13
- package/dist/portal/pool/pool-contract.d.ts +2 -0
- package/dist/portal/pool/storage-seed.d.ts +2 -1
- package/dist/portal/pool/zero-install.d.ts +27 -0
- package/dist/portal/pool/zero-install.js +54 -0
- package/dist/portal/realm/web-realm.js +6 -0
- package/dist/portal/session/dev-server/dev-command.d.ts +2 -2
- package/dist/portal/session/dev-server/dev-command.js +30 -12
- package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
- package/dist/portal/session/dev-server/dev-server-probe.js +17 -1
- package/dist/portal/session/dev-server/route-status-probe.d.ts +24 -0
- package/dist/portal/session/dev-server/route-status-probe.js +57 -0
- package/dist/portal/session/dev-server/served-document.d.ts +21 -0
- package/dist/portal/session/dev-server/served-document.js +57 -0
- package/dist/portal/session/facts/background-traffic.d.ts +9 -0
- package/dist/portal/session/facts/background-traffic.js +25 -0
- package/dist/portal/session/facts/observed-state.d.ts +11 -0
- package/dist/portal/session/facts/observed-state.js +34 -0
- package/dist/portal/session/live-control-tools.js +48 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +29 -0
- package/dist/portal/session/no-session-diagnosis.js +62 -5
- package/dist/portal/session/no-session-next-action.d.ts +13 -0
- package/dist/portal/session/no-session-next-action.js +48 -9
- package/dist/portal/session/no-session-watch.d.ts +18 -0
- package/dist/portal/session/no-session-watch.js +88 -2
- package/dist/portal/session/presence/attachment-history.d.ts +13 -2
- package/dist/portal/session/session-health.d.ts +61 -0
- package/dist/portal/session/session-health.js +43 -3
- package/dist/portal/session/session-info.d.ts +6 -0
- package/dist/portal/session/session-manager.d.ts +29 -6
- package/dist/portal/session/session-manager.js +42 -5
- package/dist/portal/session/session-reaper.d.ts +28 -0
- package/dist/portal/session/session-reaper.js +49 -1
- package/dist/portal/session/session-successor.d.ts +11 -0
- package/dist/portal/session/session-successor.js +14 -1
- package/dist/portal/session/session-verdict-facts.d.ts +28 -0
- package/dist/portal/session/session-verdict-facts.js +15 -0
- package/dist/portal/session/session.d.ts +10 -0
- package/dist/portal/session/session.js +34 -26
- package/dist/surface/http-server.d.ts +2 -1
- package/dist/surface/http-server.js +4 -2
- package/dist/surface/mcp/mcp-proxy.d.ts +2 -2
- package/dist/surface/mcp/mcp-proxy.js +5 -5
- package/dist/surface/mcp/mcp.js +4 -2
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +13 -1
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +27 -2
- package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
- package/dist/surface/mcp/server-instructions.js +21 -8
- package/dist/surface/tools/act/after-match.d.ts +17 -0
- package/dist/surface/tools/act/after-match.js +30 -0
- package/dist/surface/tools/act/already-true.d.ts +40 -0
- package/dist/surface/tools/act/already-true.js +36 -0
- package/dist/surface/tools/act/durable.d.ts +69 -0
- package/dist/surface/tools/act/durable.js +139 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +19 -6
- package/dist/surface/tools/act/navigation/navigate-arrival.js +60 -10
- package/dist/surface/tools/act/navigation/navigate-result.d.ts +1 -12
- package/dist/surface/tools/act/navigation/navigate-result.js +21 -3
- package/dist/surface/tools/act/proved-controls.d.ts +9 -0
- package/dist/surface/tools/act/proved-controls.js +11 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +5 -0
- package/dist/surface/tools/act/sequence-grade.js +32 -1
- package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
- package/dist/surface/tools/act/settle-in-flight.js +29 -6
- package/dist/surface/tools/act-capsule.d.ts +7 -0
- package/dist/surface/tools/act-capsule.js +68 -8
- package/dist/surface/tools/act-sequence-tool.js +25 -8
- package/dist/surface/tools/act-tools.js +51 -74
- package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
- package/dist/surface/tools/args/numeric-bounds.js +30 -3
- package/dist/surface/tools/assert/assert-grade.js +26 -3
- package/dist/surface/tools/assert/assert-verdict.js +32 -6
- package/dist/surface/tools/browser-tools.js +17 -4
- package/dist/surface/tools/coverage-tools.js +27 -1
- package/dist/surface/tools/dynamic-tools.js +6 -0
- package/dist/surface/tools/error-recovery.js +4 -4
- package/dist/surface/tools/feedback-invite.js +6 -4
- package/dist/surface/tools/feedback-tools.d.ts +2 -1
- package/dist/surface/tools/feedback-tools.js +1 -1
- package/dist/surface/tools/harness-explore.d.ts +3 -2
- package/dist/surface/tools/harness-explore.js +7 -6
- package/dist/surface/tools/invoke-tool.js +17 -4
- package/dist/surface/tools/lease-hint.d.ts +8 -0
- package/dist/surface/tools/lease-hint.js +10 -0
- package/dist/surface/tools/lease-tools.d.ts +16 -28
- package/dist/surface/tools/lease-tools.js +68 -11
- package/dist/surface/tools/lineage-tools.js +1 -1
- package/dist/surface/tools/live-call-text.js +4 -1
- package/dist/surface/tools/observe-tools.js +23 -7
- package/dist/surface/tools/real-input-attempt.d.ts +0 -5
- package/dist/surface/tools/real-input-attempt.js +1 -1
- package/dist/surface/tools/tool-kit.d.ts +5 -0
- package/dist/surface/tools/tool-kit.js +6 -1
- package/dist/surface/tools/tool-surface.js +17 -5
- package/dist/surface/tools/tools.js +68 -29
- package/dist/telemetry/argument-shape.d.ts +0 -2
- package/dist/telemetry/argument-shape.js +0 -4
- package/dist/telemetry/error-class.d.ts +2 -3
- package/dist/telemetry/error-class.js +2 -3
- package/dist/telemetry/feedback-local.d.ts +1 -0
- package/dist/telemetry/feedback-local.js +1 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/harness-drive.d.ts +0 -2
- package/dist/telemetry/harness-drive.js +0 -4
- package/dist/telemetry/hud-metrics.d.ts +32 -0
- package/dist/telemetry/hud-metrics.js +95 -0
- package/dist/telemetry/session-metrics.d.ts +5 -0
- package/dist/telemetry/session-metrics.js +15 -1
- package/dist/wire-journal.d.ts +34 -0
- package/dist/wire-journal.js +104 -0
- package/dist/workspace-packages.d.ts +0 -2
- package/dist/workspace-packages.js +1 -9
- package/docs/README.md +5 -2
- package/docs/actions.mdx +3 -3
- package/docs/agent-cheatsheet.md +4 -4
- package/docs/architecture.md +6 -6
- package/docs/best-practices.mdx +1 -1
- package/docs/capabilities.mdx +32 -1
- package/docs/cli/cloud.mdx +21 -9
- package/docs/cli/doctor.mdx +4 -0
- package/docs/cli/feedback.mdx +2 -2
- package/docs/cli/gate.mdx +9 -4
- package/docs/cli/init.mdx +1 -0
- package/docs/cli/report.mdx +44 -0
- package/docs/cli/update.mdx +10 -0
- package/docs/cli.mdx +9 -0
- package/docs/desktop.mdx +14 -10
- package/docs/environment.mdx +87 -0
- package/docs/faq.mdx +18 -16
- package/docs/first-drive.md +5 -13
- package/docs/flows.md +32 -2
- package/docs/frameworks.mdx +140 -9
- package/docs/getting-started.md +3 -3
- package/docs/http-transport.md +6 -3
- package/docs/human-control.md +2 -2
- package/docs/index.mdx +16 -6
- package/docs/install-agentic.mdx +37 -1
- package/docs/install-manual.mdx +1 -1
- package/docs/integration-patterns.md +3 -3
- package/docs/multi-agent-testing.md +1 -1
- package/docs/packages/babel-plugin.mdx +1 -1
- package/docs/packages/browser.mdx +2 -2
- package/docs/packages/react.mdx +2 -2
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages/vite-plugin.mdx +2 -2
- package/docs/packages.mdx +9 -9
- package/docs/predicates.mdx +176 -7
- package/docs/quickstart.mdx +2 -2
- package/docs/recipes.mdx +2 -2
- package/docs/state-management.mdx +2 -2
- package/docs/system-map.md +1 -1
- package/docs/telemetry.md +1 -1
- package/docs/token-efficiency.md +3 -3
- package/docs/tools/act-and-wait.mdx +1 -0
- package/docs/tools/act-sequence.mdx +1 -1
- package/docs/tools/console.mdx +1 -1
- package/docs/tools/inspect.mdx +1 -1
- package/docs/tools/network.mdx +1 -1
- package/docs/tools/query.mdx +11 -11
- package/docs/tools/sessions.mdx +1 -1
- package/docs/tools/snapshot.mdx +1 -1
- package/docs/tools/state.mdx +1 -1
- package/docs/tools/wait-for.mdx +1 -1
- package/docs/usage.md +8 -7
- package/docs/use-cases.mdx +157 -0
- package/docs/vs-screenshots.mdx +3 -3
- package/docs/what-is-recorded.md +62 -0
- package/docs/what-is-reticle.mdx +17 -20
- package/docs/why-reticle.mdx +14 -21
- package/package.json +11 -10
- package/dist/judgement/capsule/minimize.d.ts +0 -12
- package/dist/judgement/capsule/minimize.js +0 -22
- package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
- package/dist/judgement/outcome/predicate-to-expect.js +0 -148
- package/dist/judgement/phenomena/phenomena.d.ts +0 -26
- package/dist/judgement/phenomena/phenomena.js +0 -101
- package/dist/language/flows/flow-report.d.ts +0 -22
- package/dist/language/flows/flow-report.js +0 -106
|
@@ -1,148 +0,0 @@
|
|
|
1
|
-
import { PredicateKind } from '@reticlehq/core';
|
|
2
|
-
/** Merge two partial expectations; later keys win only where the earlier one said nothing. */
|
|
3
|
-
function merge(into, from) {
|
|
4
|
-
return { ...from, ...into };
|
|
5
|
-
}
|
|
6
|
-
export function predicateToExpect(predicate) {
|
|
7
|
-
switch (predicate.kind) {
|
|
8
|
-
case PredicateKind.SIGNAL: {
|
|
9
|
-
if (predicate.name === undefined)
|
|
10
|
-
return undefined;
|
|
11
|
-
const signal = { signal: predicate.name };
|
|
12
|
-
if (predicate.dataMatches !== undefined)
|
|
13
|
-
signal.signalData = predicate.dataMatches;
|
|
14
|
-
if (predicate.count !== undefined)
|
|
15
|
-
signal.signalCount = predicate.count;
|
|
16
|
-
return signal;
|
|
17
|
-
}
|
|
18
|
-
case PredicateKind.ROUTE: {
|
|
19
|
-
// Carried, not invented: the agent said "until the route is X" in so many words. The kinds
|
|
20
|
-
// below this comment's twin in the header — animation, anyOf, not — stay refused because
|
|
21
|
-
// there the file would gain a claim nobody made.
|
|
22
|
-
const route = {};
|
|
23
|
-
if (predicate.pathname !== undefined)
|
|
24
|
-
route.pathname = predicate.pathname;
|
|
25
|
-
if (predicate.contains !== undefined)
|
|
26
|
-
route.contains = predicate.contains;
|
|
27
|
-
return 0 === Object.keys(route).length ? undefined : { route };
|
|
28
|
-
}
|
|
29
|
-
case PredicateKind.NET: {
|
|
30
|
-
const net = {};
|
|
31
|
-
if (predicate.method !== undefined)
|
|
32
|
-
net.method = predicate.method;
|
|
33
|
-
if (predicate.urlContains !== undefined)
|
|
34
|
-
net.urlContains = predicate.urlContains;
|
|
35
|
-
if (predicate.status !== undefined)
|
|
36
|
-
net.status = predicate.status;
|
|
37
|
-
if (predicate.count !== undefined)
|
|
38
|
-
net.count = predicate.count;
|
|
39
|
-
return 0 === Object.keys(net).length ? undefined : { net };
|
|
40
|
-
}
|
|
41
|
-
case PredicateKind.CONSOLE: {
|
|
42
|
-
// `contains` has no representation in FlowExpect.console (core keeps `level` and `absent`
|
|
43
|
-
// and nothing else). Copying the rest through anyway would record an assertion the agent
|
|
44
|
-
// never made: {console, level:'warn', contains:'no-op', absent:true} would save "no warn
|
|
45
|
-
// entries at all", a false red on any unrelated warning, and in the presence direction it
|
|
46
|
-
// saves a strictly weaker claim than the one chosen. This file's own rule applies: record
|
|
47
|
-
// nothing rather than something different, so the flow stays assertion-free there instead.
|
|
48
|
-
if (predicate.contains !== undefined)
|
|
49
|
-
return undefined;
|
|
50
|
-
const console_ = {};
|
|
51
|
-
if (predicate.level !== undefined)
|
|
52
|
-
console_.level = predicate.level;
|
|
53
|
-
if (predicate.absent !== undefined)
|
|
54
|
-
console_.absent = predicate.absent;
|
|
55
|
-
return 0 === Object.keys(console_).length ? undefined : { console: console_ };
|
|
56
|
-
}
|
|
57
|
-
case PredicateKind.ELEMENT: {
|
|
58
|
-
const element = {};
|
|
59
|
-
if (predicate.query.testid !== undefined)
|
|
60
|
-
element.testid = predicate.query.testid;
|
|
61
|
-
if (predicate.query.role !== undefined)
|
|
62
|
-
element.role = predicate.query.role;
|
|
63
|
-
if (predicate.query.name !== undefined)
|
|
64
|
-
element.name = predicate.query.name;
|
|
65
|
-
return 0 === Object.keys(element).length ? undefined : { element };
|
|
66
|
-
}
|
|
67
|
-
case PredicateKind.STATE: {
|
|
68
|
-
const state = { path: predicate.path };
|
|
69
|
-
if (predicate.store !== undefined)
|
|
70
|
-
state.store = predicate.store;
|
|
71
|
-
if (predicate.equals !== undefined)
|
|
72
|
-
state.equals = predicate.equals;
|
|
73
|
-
return { state };
|
|
74
|
-
}
|
|
75
|
-
case PredicateKind.ALL_OF: {
|
|
76
|
-
// `settled` members drop out on their own by returning undefined.
|
|
77
|
-
let combined;
|
|
78
|
-
for (const part of predicate.predicates) {
|
|
79
|
-
const expect = predicateToExpect(part);
|
|
80
|
-
if (expect === undefined)
|
|
81
|
-
continue;
|
|
82
|
-
combined = combined === undefined ? expect : merge(combined, expect);
|
|
83
|
-
}
|
|
84
|
-
return combined;
|
|
85
|
-
}
|
|
86
|
-
default:
|
|
87
|
-
// settled | route | animation | anyOf | not — nothing FlowExpect can say honestly.
|
|
88
|
-
return undefined;
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* The subset a REPLAY actually enforces.
|
|
93
|
-
*
|
|
94
|
-
* The rule has never changed: never write an assertion into a flow file that nothing evaluates. A
|
|
95
|
-
* flow reporting `grade: "asserted"` while its assertion is read by no one is a false green, in the
|
|
96
|
-
* feature whose entire purpose is preventing them.
|
|
97
|
-
*
|
|
98
|
-
* What changed is the SET. This kept only `element.testid` and `state`, because for a long time
|
|
99
|
-
* those were the only kinds replay checked — and the note here said lifting it "requires replay to
|
|
100
|
-
* evaluate them per step". Replay now does exactly that: `assertStepExpect` compiles every
|
|
101
|
-
* remaining kind through `successToPredicate` and waits on it. The condition was met and the filter
|
|
102
|
-
* was not updated, so the two drifted.
|
|
103
|
-
*
|
|
104
|
-
* That drift had a cost, and it fell on the agent. `reticle_act_and_wait { until }` IS the agent
|
|
105
|
-
* saying what success means, and `net` is overwhelmingly what it says. Every one of those was
|
|
106
|
-
* discarded at capture, so an agent-recorded flow reached disk assertion-free BY CONSTRUCTION and
|
|
107
|
-
* `reticle_verify` then correctly called it `unverifiable` — the record → save → verify path
|
|
108
|
-
* completing all the way to a run that could never be a pass. Found by driving it.
|
|
109
|
-
*
|
|
110
|
-
* The list below is exactly what `successToPredicate` reads, including an element located by
|
|
111
|
-
* role or name. A testid is also asserted directly against the DOM by the step runner. Anything
|
|
112
|
-
* it cannot compile is still dropped.
|
|
113
|
-
*/
|
|
114
|
-
export function enforcedOnReplay(expect) {
|
|
115
|
-
if (expect === undefined)
|
|
116
|
-
return undefined;
|
|
117
|
-
const kept = {};
|
|
118
|
-
// The step runner asserts a testid against the live DOM before the predicate engine. Role and
|
|
119
|
-
// name are not that path: successToPredicate compiles them, and dropping them here made a
|
|
120
|
-
// recorded `until` by button name vanish so the saved flow could not go red.
|
|
121
|
-
const element = expect.element;
|
|
122
|
-
if (undefined !== element &&
|
|
123
|
-
(undefined !== element.testid || undefined !== element.role || undefined !== element.name)) {
|
|
124
|
-
kept.element = element;
|
|
125
|
-
}
|
|
126
|
-
// Everything `successToPredicate` can compile. Replay evaluates EVERY kind of expect through it
|
|
127
|
-
// (see assertStepExpect); this list is what that function actually reads.
|
|
128
|
-
if (expect.state !== undefined)
|
|
129
|
-
kept.state = expect.state;
|
|
130
|
-
if (expect.signal !== undefined)
|
|
131
|
-
kept.signal = expect.signal;
|
|
132
|
-
if (expect.signalData !== undefined)
|
|
133
|
-
kept.signalData = expect.signalData;
|
|
134
|
-
if (expect.signalCount !== undefined)
|
|
135
|
-
kept.signalCount = expect.signalCount;
|
|
136
|
-
if (expect.net !== undefined)
|
|
137
|
-
kept.net = expect.net;
|
|
138
|
-
if (expect.console !== undefined)
|
|
139
|
-
kept.console = expect.console;
|
|
140
|
-
// `route` joined the list the day FlowExpect gained the field. This filter and
|
|
141
|
-
// `successToPredicate` are two allowlists for one question — "can replay check this?" — and the
|
|
142
|
-
// note above records them drifting once already. They drifted again here, in the same direction,
|
|
143
|
-
// within an hour: the field was added, the mapping was added, and a route assertion still reached
|
|
144
|
-
// disk as nothing because THIS list had not heard of it. Found by driving, not by a test.
|
|
145
|
-
if (expect.route !== undefined)
|
|
146
|
-
kept.route = expect.route;
|
|
147
|
-
return 0 === Object.keys(kept).length ? undefined : kept;
|
|
148
|
-
}
|
|
@@ -1,26 +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
|
-
export 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[];
|
|
@@ -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
|
-
}
|