@reticlehq/server 2.1.0 → 2.2.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 +37 -0
- package/README.md +5 -1
- package/dist/bridge-security.d.ts +1 -1
- package/dist/bridge-security.js +1 -1
- package/dist/bridge.d.ts +7 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +22 -3
- package/dist/bridge.js.map +1 -1
- package/dist/bridge.test-harness.d.ts +5 -0
- package/dist/bridge.test-harness.d.ts.map +1 -1
- package/dist/bridge.test-harness.js +4 -0
- package/dist/bridge.test-harness.js.map +1 -1
- package/dist/capsule/capsule-store.d.ts +66 -0
- package/dist/capsule/capsule-store.d.ts.map +1 -0
- package/dist/capsule/capsule-store.js +110 -0
- package/dist/capsule/capsule-store.js.map +1 -0
- package/dist/capsule/capsule.d.ts +19 -0
- package/dist/capsule/capsule.d.ts.map +1 -0
- package/dist/capsule/capsule.js +36 -0
- package/dist/capsule/capsule.js.map +1 -0
- package/dist/capsule/causal-summary.d.ts +36 -0
- package/dist/capsule/causal-summary.d.ts.map +1 -0
- package/dist/capsule/causal-summary.js +111 -0
- package/dist/capsule/causal-summary.js.map +1 -0
- package/dist/capsule/divergence.d.ts +31 -0
- package/dist/capsule/divergence.d.ts.map +1 -0
- package/dist/capsule/divergence.js +41 -0
- package/dist/capsule/divergence.js.map +1 -0
- package/dist/capsule/minimize.d.ts +13 -0
- package/dist/capsule/minimize.d.ts.map +1 -0
- package/dist/capsule/minimize.js +23 -0
- package/dist/capsule/minimize.js.map +1 -0
- package/dist/capsule/predicate-to-links.d.ts +9 -0
- package/dist/capsule/predicate-to-links.d.ts.map +1 -0
- package/dist/capsule/predicate-to-links.js +31 -0
- package/dist/capsule/predicate-to-links.js.map +1 -0
- package/dist/cli-flow-commands.d.ts +31 -0
- package/dist/cli-flow-commands.d.ts.map +1 -0
- package/dist/cli-flow-commands.js +207 -0
- package/dist/cli-flow-commands.js.map +1 -0
- package/dist/cli-parse.d.ts +18 -2
- package/dist/cli-parse.d.ts.map +1 -1
- package/dist/cli-parse.js +57 -0
- package/dist/cli-parse.js.map +1 -1
- package/dist/cli-port.d.ts +10 -4
- package/dist/cli-port.d.ts.map +1 -1
- package/dist/cli-port.js +32 -6
- package/dist/cli-port.js.map +1 -1
- package/dist/cli-verify.d.ts.map +1 -1
- package/dist/cli-verify.js +29 -10
- package/dist/cli-verify.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +81 -2
- package/dist/cli.js.map +1 -1
- package/dist/crawl/crawl-tools.d.ts.map +1 -1
- package/dist/crawl/crawl-tools.js +12 -0
- package/dist/crawl/crawl-tools.js.map +1 -1
- package/dist/crawl/crawl.d.ts +23 -1
- package/dist/crawl/crawl.d.ts.map +1 -1
- package/dist/crawl/crawl.js +36 -9
- package/dist/crawl/crawl.js.map +1 -1
- package/dist/daemon-resilience.d.ts +5 -5
- package/dist/daemon-resilience.js +5 -5
- package/dist/daemon.d.ts +1 -1
- package/dist/daemon.js +1 -1
- package/dist/domain/domain-tools.d.ts.map +1 -1
- package/dist/domain/domain-tools.js +11 -1
- package/dist/domain/domain-tools.js.map +1 -1
- package/dist/domain/flow-risk.d.ts +4 -4
- package/dist/domain/flow-risk.js +4 -4
- package/dist/ee/audit-log.d.ts +2 -2
- package/dist/ee/audit-log.js +2 -2
- package/dist/events/event-filters.d.ts +29 -1
- package/dist/events/event-filters.d.ts.map +1 -1
- package/dist/events/event-filters.js +75 -1
- package/dist/events/event-filters.js.map +1 -1
- package/dist/events/predicate-eval.d.ts +15 -0
- package/dist/events/predicate-eval.d.ts.map +1 -1
- package/dist/events/predicate-eval.js +97 -18
- package/dist/events/predicate-eval.js.map +1 -1
- package/dist/events/predicate.d.ts +22 -1
- package/dist/events/predicate.d.ts.map +1 -1
- package/dist/events/predicate.js +154 -20
- package/dist/events/predicate.js.map +1 -1
- package/dist/events/ring-buffer.d.ts +3 -3
- package/dist/events/ring-buffer.d.ts.map +1 -1
- package/dist/events/ring-buffer.js +54 -8
- package/dist/events/ring-buffer.js.map +1 -1
- package/dist/flows/affected.d.ts +25 -0
- package/dist/flows/affected.d.ts.map +1 -0
- package/dist/flows/affected.js +36 -0
- package/dist/flows/affected.js.map +1 -0
- package/dist/flows/annotate.d.ts +4 -4
- package/dist/flows/annotate.js +4 -4
- package/dist/flows/assertion-integrity.d.ts +24 -0
- package/dist/flows/assertion-integrity.d.ts.map +1 -0
- package/dist/flows/assertion-integrity.js +27 -0
- package/dist/flows/assertion-integrity.js.map +1 -0
- package/dist/flows/assertion-tiers-store.d.ts +80 -0
- package/dist/flows/assertion-tiers-store.d.ts.map +1 -0
- package/dist/flows/assertion-tiers-store.js +99 -0
- package/dist/flows/assertion-tiers-store.js.map +1 -0
- package/dist/flows/buddy-status.d.ts +25 -0
- package/dist/flows/buddy-status.d.ts.map +1 -0
- package/dist/flows/buddy-status.js +33 -0
- package/dist/flows/buddy-status.js.map +1 -0
- package/dist/flows/coverage.d.ts +28 -0
- package/dist/flows/coverage.d.ts.map +1 -0
- package/dist/flows/coverage.js +22 -0
- package/dist/flows/coverage.js.map +1 -0
- package/dist/flows/decision.d.ts.map +1 -1
- package/dist/flows/decision.js +16 -8
- package/dist/flows/decision.js.map +1 -1
- package/dist/flows/flake-store.d.ts +20 -0
- package/dist/flows/flake-store.d.ts.map +1 -0
- package/dist/flows/flake-store.js +59 -0
- package/dist/flows/flake-store.js.map +1 -0
- package/dist/flows/flake.d.ts +58 -0
- package/dist/flows/flake.d.ts.map +1 -0
- package/dist/flows/flake.js +36 -0
- package/dist/flows/flake.js.map +1 -0
- package/dist/flows/flow-classify.d.ts +8 -8
- package/dist/flows/flow-classify.js +8 -8
- package/dist/flows/flow-replay-run.d.ts.map +1 -1
- package/dist/flows/flow-replay-run.js +36 -0
- package/dist/flows/flow-replay-run.js.map +1 -1
- package/dist/flows/flow-replay.d.ts +9 -0
- package/dist/flows/flow-replay.d.ts.map +1 -1
- package/dist/flows/flow-replay.js +48 -13
- package/dist/flows/flow-replay.js.map +1 -1
- package/dist/flows/flow-report.d.ts +4 -4
- package/dist/flows/flow-sources.d.ts +20 -0
- package/dist/flows/flow-sources.d.ts.map +1 -0
- package/dist/flows/flow-sources.js +33 -0
- package/dist/flows/flow-sources.js.map +1 -0
- package/dist/flows/flow-tools.d.ts +13 -1
- package/dist/flows/flow-tools.d.ts.map +1 -1
- package/dist/flows/flow-tools.js +92 -5
- package/dist/flows/flow-tools.js.map +1 -1
- package/dist/flows/flows.d.ts +9 -4
- package/dist/flows/flows.d.ts.map +1 -1
- package/dist/flows/flows.js +38 -21
- package/dist/flows/flows.js.map +1 -1
- package/dist/flows/gate.d.ts +39 -0
- package/dist/flows/gate.d.ts.map +1 -0
- package/dist/flows/gate.js +34 -0
- package/dist/flows/gate.js.map +1 -0
- package/dist/flows/git-changed.d.ts +9 -0
- package/dist/flows/git-changed.d.ts.map +1 -0
- package/dist/flows/git-changed.js +25 -0
- package/dist/flows/git-changed.js.map +1 -0
- package/dist/flows/heal-run.d.ts +1 -1
- package/dist/flows/heal-run.js +1 -1
- package/dist/flows/parallel-suite.d.ts +27 -0
- package/dist/flows/parallel-suite.d.ts.map +1 -0
- package/dist/flows/parallel-suite.js +51 -0
- package/dist/flows/parallel-suite.js.map +1 -0
- package/dist/flows/replay.d.ts.map +1 -1
- package/dist/flows/replay.js +33 -11
- package/dist/flows/replay.js.map +1 -1
- package/dist/flows/watch-batcher.d.ts +18 -0
- package/dist/flows/watch-batcher.d.ts.map +1 -0
- package/dist/flows/watch-batcher.js +20 -0
- package/dist/flows/watch-batcher.js.map +1 -0
- package/dist/honesty/blind-spots.d.ts +37 -0
- package/dist/honesty/blind-spots.d.ts.map +1 -0
- package/dist/honesty/blind-spots.js +57 -0
- package/dist/honesty/blind-spots.js.map +1 -0
- package/dist/honesty/honesty.d.ts +57 -0
- package/dist/honesty/honesty.d.ts.map +1 -0
- package/dist/honesty/honesty.js +63 -0
- package/dist/honesty/honesty.js.map +1 -0
- package/dist/http-server.d.ts +5 -5
- package/dist/http-server.js +4 -4
- package/dist/idle-shutdown.d.ts +2 -2
- package/dist/idle-shutdown.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -13
- package/dist/index.js.map +1 -1
- package/dist/init/agent-rules.d.ts +38 -0
- package/dist/init/agent-rules.d.ts.map +1 -0
- package/dist/init/agent-rules.js +65 -0
- package/dist/init/agent-rules.js.map +1 -0
- package/dist/init/plan.d.ts +6 -0
- package/dist/init/plan.d.ts.map +1 -1
- package/dist/init/plan.js +79 -3
- package/dist/init/plan.js.map +1 -1
- package/dist/init/run.d.ts.map +1 -1
- package/dist/init/run.js +4 -0
- package/dist/init/run.js.map +1 -1
- package/dist/init/snippets.js +1 -1
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +2 -2
- package/dist/init/vite-config.js.map +1 -1
- package/dist/input/network-detail.d.ts +74 -0
- package/dist/input/network-detail.d.ts.map +1 -0
- package/dist/input/network-detail.js +160 -0
- package/dist/input/network-detail.js.map +1 -0
- package/dist/input/network-mock.d.ts +4 -4
- package/dist/input/real-input.d.ts +44 -11
- package/dist/input/real-input.d.ts.map +1 -1
- package/dist/input/real-input.js +57 -9
- package/dist/input/real-input.js.map +1 -1
- package/dist/journal/ambient-store.d.ts +16 -0
- package/dist/journal/ambient-store.d.ts.map +1 -0
- package/dist/journal/ambient-store.js +46 -0
- package/dist/journal/ambient-store.js.map +1 -0
- package/dist/journal/ambient.d.ts +48 -0
- package/dist/journal/ambient.d.ts.map +1 -0
- package/dist/journal/ambient.js +48 -0
- package/dist/journal/ambient.js.map +1 -0
- package/dist/journal/attach-journal.d.ts +22 -0
- package/dist/journal/attach-journal.d.ts.map +1 -0
- package/dist/journal/attach-journal.js +20 -0
- package/dist/journal/attach-journal.js.map +1 -0
- package/dist/journal/deviation-report.d.ts +28 -0
- package/dist/journal/deviation-report.d.ts.map +1 -0
- package/dist/journal/deviation-report.js +54 -0
- package/dist/journal/deviation-report.js.map +1 -0
- package/dist/journal/deviation-service.d.ts +12 -0
- package/dist/journal/deviation-service.d.ts.map +1 -0
- package/dist/journal/deviation-service.js +32 -0
- package/dist/journal/deviation-service.js.map +1 -0
- package/dist/journal/envelope-store.d.ts +19 -0
- package/dist/journal/envelope-store.d.ts.map +1 -0
- package/dist/journal/envelope-store.js +62 -0
- package/dist/journal/envelope-store.js.map +1 -0
- package/dist/journal/envelope.d.ts +232 -0
- package/dist/journal/envelope.d.ts.map +1 -0
- package/dist/journal/envelope.js +94 -0
- package/dist/journal/envelope.js.map +1 -0
- package/dist/journal/journal-query.d.ts +20 -0
- package/dist/journal/journal-query.d.ts.map +1 -0
- package/dist/journal/journal-query.js +28 -0
- package/dist/journal/journal-query.js.map +1 -0
- package/dist/journal/journal-recorder.d.ts +38 -0
- package/dist/journal/journal-recorder.d.ts.map +1 -0
- package/dist/journal/journal-recorder.js +81 -0
- package/dist/journal/journal-recorder.js.map +1 -0
- package/dist/journal/retention.d.ts +21 -0
- package/dist/journal/retention.d.ts.map +1 -0
- package/dist/journal/retention.js +50 -0
- package/dist/journal/retention.js.map +1 -0
- package/dist/journal/rollups.d.ts +49 -0
- package/dist/journal/rollups.d.ts.map +1 -0
- package/dist/journal/rollups.js +83 -0
- package/dist/journal/rollups.js.map +1 -0
- package/dist/journal/session-end.d.ts +32 -0
- package/dist/journal/session-end.d.ts.map +1 -0
- package/dist/journal/session-end.js +52 -0
- package/dist/journal/session-end.js.map +1 -0
- package/dist/journal/session-journal.d.ts +25 -0
- package/dist/journal/session-journal.d.ts.map +1 -0
- package/dist/journal/session-journal.js +168 -0
- package/dist/journal/session-journal.js.map +1 -0
- package/dist/license/license.d.ts +8 -3
- package/dist/license/license.d.ts.map +1 -1
- package/dist/license/license.js +34 -11
- package/dist/license/license.js.map +1 -1
- package/dist/mcp-proxy.d.ts +20 -0
- package/dist/mcp-proxy.d.ts.map +1 -1
- package/dist/mcp-proxy.js +45 -27
- package/dist/mcp-proxy.js.map +1 -1
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +79 -9
- package/dist/mcp.js.map +1 -1
- package/dist/oracles/flow-instrument-gaps.d.ts +19 -0
- package/dist/oracles/flow-instrument-gaps.d.ts.map +1 -0
- package/dist/oracles/flow-instrument-gaps.js +45 -0
- package/dist/oracles/flow-instrument-gaps.js.map +1 -0
- package/dist/oracles/propose-consequences.d.ts +22 -0
- package/dist/oracles/propose-consequences.d.ts.map +1 -0
- package/dist/oracles/propose-consequences.js +93 -0
- package/dist/oracles/propose-consequences.js.map +1 -0
- package/dist/oracles/self-instrument.d.ts +32 -0
- package/dist/oracles/self-instrument.d.ts.map +1 -0
- package/dist/oracles/self-instrument.js +44 -0
- package/dist/oracles/self-instrument.js.map +1 -0
- package/dist/pairing-token.d.ts +1 -1
- package/dist/phenomena/phenomena.d.ts +27 -0
- package/dist/phenomena/phenomena.d.ts.map +1 -0
- package/dist/phenomena/phenomena.js +102 -0
- package/dist/phenomena/phenomena.js.map +1 -0
- package/dist/pool/browser-pool.d.ts +5 -3
- package/dist/pool/browser-pool.d.ts.map +1 -1
- package/dist/pool/browser-pool.js +21 -3
- package/dist/pool/browser-pool.js.map +1 -1
- package/dist/pool/playwright-launcher.d.ts.map +1 -1
- package/dist/pool/playwright-launcher.js +9 -2
- package/dist/pool/playwright-launcher.js.map +1 -1
- package/dist/project/file-lock.d.ts +2 -0
- package/dist/project/file-lock.d.ts.map +1 -0
- package/dist/project/file-lock.js +24 -0
- package/dist/project/file-lock.js.map +1 -0
- package/dist/project/fs-port.d.ts +18 -0
- package/dist/project/fs-port.d.ts.map +1 -1
- package/dist/project/fs-port.js +24 -2
- package/dist/project/fs-port.js.map +1 -1
- package/dist/project/project-store.d.ts.map +1 -1
- package/dist/project/project-store.js +13 -7
- package/dist/project/project-store.js.map +1 -1
- package/dist/project/project-tools.d.ts +0 -6
- package/dist/project/project-tools.d.ts.map +1 -1
- package/dist/project/project-tools.js +24 -1
- package/dist/project/project-tools.js.map +1 -1
- package/dist/project/reticle-dir.d.ts +39 -14
- package/dist/project/reticle-dir.d.ts.map +1 -1
- package/dist/project/reticle-dir.js +30 -4
- package/dist/project/reticle-dir.js.map +1 -1
- package/dist/runs/build-verification-run.d.ts +1 -1
- package/dist/runs/build-verification-run.js +1 -1
- package/dist/runs/repair-prompt.d.ts +2 -0
- package/dist/runs/repair-prompt.d.ts.map +1 -1
- package/dist/runs/repair-prompt.js +14 -1
- package/dist/runs/repair-prompt.js.map +1 -1
- package/dist/runs/reticle-runner.d.ts +1 -1
- package/dist/runs/reticle-runner.d.ts.map +1 -1
- package/dist/runs/run-diff.d.ts +34 -0
- package/dist/runs/run-diff.d.ts.map +1 -0
- package/dist/runs/run-diff.js +71 -0
- package/dist/runs/run-diff.js.map +1 -0
- package/dist/runs/run-store.d.ts +6 -1
- package/dist/runs/run-store.d.ts.map +1 -1
- package/dist/runs/run-store.js +22 -2
- package/dist/runs/run-store.js.map +1 -1
- package/dist/runs/run-tools.d.ts.map +1 -1
- package/dist/runs/run-tools.js +16 -3
- package/dist/runs/run-tools.js.map +1 -1
- package/dist/runs/verify-server.js +1 -1
- package/dist/runs/verify-server.js.map +1 -1
- package/dist/session/control-envelope.d.ts +9 -1
- package/dist/session/control-envelope.d.ts.map +1 -1
- package/dist/session/control-envelope.js +13 -1
- package/dist/session/control-envelope.js.map +1 -1
- package/dist/session/live-control-tools.d.ts +1 -1
- package/dist/session/live-control-tools.js +1 -1
- package/dist/session/live-control.d.ts +38 -0
- package/dist/session/live-control.d.ts.map +1 -0
- package/dist/session/live-control.js +64 -0
- package/dist/session/live-control.js.map +1 -0
- package/dist/session/observed-state.d.ts +46 -0
- package/dist/session/observed-state.d.ts.map +1 -0
- package/dist/session/observed-state.js +76 -0
- package/dist/session/observed-state.js.map +1 -0
- package/dist/session/output-budget.d.ts +9 -0
- package/dist/session/output-budget.d.ts.map +1 -1
- package/dist/session/output-budget.js +9 -0
- package/dist/session/output-budget.js.map +1 -1
- package/dist/session/review-store.d.ts +1 -1
- package/dist/session/review-store.d.ts.map +1 -1
- package/dist/session/review-store.js +2 -2
- package/dist/session/review-store.js.map +1 -1
- package/dist/session/session-manager.d.ts +9 -7
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +8 -8
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/session-readiness.js +1 -1
- package/dist/session/session-readiness.js.map +1 -1
- package/dist/session/session-reaper.d.ts +1 -1
- package/dist/session/session-reaper.js +1 -1
- package/dist/session/session-recommendation.d.ts +1 -1
- package/dist/session/session-recommendation.js +1 -1
- package/dist/session/session-tools.js +1 -1
- package/dist/session/session-tools.js.map +1 -1
- package/dist/session/session.d.ts +43 -11
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +115 -46
- package/dist/session/session.js.map +1 -1
- package/dist/tools/act-tools.d.ts.map +1 -1
- package/dist/tools/act-tools.js +252 -70
- package/dist/tools/act-tools.js.map +1 -1
- package/dist/tools/act-view.d.ts +4 -4
- package/dist/tools/act-view.js +4 -4
- package/dist/tools/browser-tools.d.ts.map +1 -1
- package/dist/tools/browser-tools.js +32 -8
- package/dist/tools/browser-tools.js.map +1 -1
- package/dist/tools/contract-tools.d.ts.map +1 -1
- package/dist/tools/contract-tools.js +5 -0
- package/dist/tools/contract-tools.js.map +1 -1
- package/dist/tools/dynamic-tools.d.ts.map +1 -1
- package/dist/tools/dynamic-tools.js +7 -6
- package/dist/tools/dynamic-tools.js.map +1 -1
- package/dist/tools/invoke-tool.d.ts.map +1 -1
- package/dist/tools/invoke-tool.js +32 -29
- package/dist/tools/invoke-tool.js.map +1 -1
- package/dist/tools/lease-tools.d.ts +16 -0
- package/dist/tools/lease-tools.d.ts.map +1 -1
- package/dist/tools/lease-tools.js +11 -0
- package/dist/tools/lease-tools.js.map +1 -1
- package/dist/tools/merge-tools.d.ts +43 -0
- package/dist/tools/merge-tools.d.ts.map +1 -0
- package/dist/tools/merge-tools.js +66 -0
- package/dist/tools/merge-tools.js.map +1 -0
- package/dist/tools/observe-tools.d.ts.map +1 -1
- package/dist/tools/observe-tools.js +172 -29
- package/dist/tools/observe-tools.js.map +1 -1
- package/dist/tools/profiles.d.ts +18 -13
- package/dist/tools/profiles.d.ts.map +1 -1
- package/dist/tools/profiles.js +39 -33
- package/dist/tools/profiles.js.map +1 -1
- package/dist/tools/query-paginate.d.ts +9 -2
- package/dist/tools/query-paginate.d.ts.map +1 -1
- package/dist/tools/query-paginate.js +21 -4
- package/dist/tools/query-paginate.js.map +1 -1
- package/dist/tools/read-tools.d.ts.map +1 -1
- package/dist/tools/read-tools.js +30 -1
- package/dist/tools/read-tools.js.map +1 -1
- package/dist/tools/snapshot-delta.d.ts +2 -0
- package/dist/tools/snapshot-delta.d.ts.map +1 -1
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/snapshot-delta.js.map +1 -1
- package/dist/tools/tool-kit.d.ts +3 -2
- package/dist/tools/tool-kit.d.ts.map +1 -1
- package/dist/tools/tool-kit.js +11 -1
- package/dist/tools/tool-kit.js.map +1 -1
- package/dist/tools/tool-names.d.ts +18 -10
- package/dist/tools/tool-names.d.ts.map +1 -1
- package/dist/tools/tool-names.js +22 -13
- package/dist/tools/tool-names.js.map +1 -1
- package/dist/tools/tools-helpers.d.ts +12 -0
- package/dist/tools/tools-helpers.d.ts.map +1 -1
- package/dist/tools/tools-helpers.js +20 -0
- package/dist/tools/tools-helpers.js.map +1 -1
- package/dist/tools/tools.d.ts.map +1 -1
- package/dist/tools/tools.js +162 -12
- package/dist/tools/tools.js.map +1 -1
- package/dist/update/updater.d.ts +1 -1
- package/dist/update/updater.js +2 -2
- package/dist/update/updater.js.map +1 -1
- package/package.json +8 -3
- package/dist/update/update-tools.d.ts +0 -3
- package/dist/update/update-tools.d.ts.map +0 -1
- package/dist/update/update-tools.js +0 -94
- package/dist/update/update-tools.js.map +0 -1
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified-surface coverage — the buddy channel's honest answer to "is EVERYTHING working?". A green on
|
|
3
|
+
* three flows says nothing about the twelve testids never exercised. This measures the declared surface
|
|
4
|
+
* (contract testids/signals/flows) actually touched by passing verification, so "everything" is honest
|
|
5
|
+
* about what everything means. Pure set math; the deviation report + gate carry the number.
|
|
6
|
+
*/
|
|
7
|
+
export interface DeclaredSurface {
|
|
8
|
+
testids: readonly string[];
|
|
9
|
+
signals: readonly string[];
|
|
10
|
+
flows: readonly string[];
|
|
11
|
+
}
|
|
12
|
+
export interface CoverageDimension {
|
|
13
|
+
total: number;
|
|
14
|
+
covered: number;
|
|
15
|
+
/** Percent covered, rounded; 100 when nothing is declared (vacuously complete). */
|
|
16
|
+
pct: number;
|
|
17
|
+
/** Declared-but-never-exercised members — what "everything" is silently missing. */
|
|
18
|
+
uncovered: string[];
|
|
19
|
+
}
|
|
20
|
+
export interface Coverage {
|
|
21
|
+
testids: CoverageDimension;
|
|
22
|
+
signals: CoverageDimension;
|
|
23
|
+
flows: CoverageDimension;
|
|
24
|
+
/** Overall percent across all three dimensions combined. */
|
|
25
|
+
overallPct: number;
|
|
26
|
+
}
|
|
27
|
+
export declare function computeCoverage(declared: DeclaredSurface, exercised: DeclaredSurface): Coverage;
|
|
28
|
+
//# sourceMappingURL=coverage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.d.ts","sourceRoot":"","sources":["../../src/flows/coverage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,OAAO,EAAE,SAAS,MAAM,EAAE,CAAC;IAC3B,KAAK,EAAE,SAAS,MAAM,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC;IAChB,mFAAmF;IACnF,GAAG,EAAE,MAAM,CAAC;IACZ,oFAAoF;IACpF,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED,MAAM,WAAW,QAAQ;IACvB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,OAAO,EAAE,iBAAiB,CAAC;IAC3B,KAAK,EAAE,iBAAiB,CAAC;IACzB,4DAA4D;IAC5D,UAAU,EAAE,MAAM,CAAC;CACpB;AASD,wBAAgB,eAAe,CAAC,QAAQ,EAAE,eAAe,EAAE,SAAS,EAAE,eAAe,GAAG,QAAQ,CAQ/F"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Verified-surface coverage — the buddy channel's honest answer to "is EVERYTHING working?". A green on
|
|
3
|
+
* three flows says nothing about the twelve testids never exercised. This measures the declared surface
|
|
4
|
+
* (contract testids/signals/flows) actually touched by passing verification, so "everything" is honest
|
|
5
|
+
* about what everything means. Pure set math; the deviation report + gate carry the number.
|
|
6
|
+
*/
|
|
7
|
+
function dimension(declared, exercised) {
|
|
8
|
+
const uncovered = declared.filter((d) => !exercised.has(d));
|
|
9
|
+
const covered = declared.length - uncovered.length;
|
|
10
|
+
const pct = declared.length === 0 ? 100 : Math.round((covered / declared.length) * 100);
|
|
11
|
+
return { total: declared.length, covered, pct, uncovered };
|
|
12
|
+
}
|
|
13
|
+
export function computeCoverage(declared, exercised) {
|
|
14
|
+
const testids = dimension(declared.testids, new Set(exercised.testids));
|
|
15
|
+
const signals = dimension(declared.signals, new Set(exercised.signals));
|
|
16
|
+
const flows = dimension(declared.flows, new Set(exercised.flows));
|
|
17
|
+
const total = testids.total + signals.total + flows.total;
|
|
18
|
+
const covered = testids.covered + signals.covered + flows.covered;
|
|
19
|
+
const overallPct = total === 0 ? 100 : Math.round((covered / total) * 100);
|
|
20
|
+
return { testids, signals, flows, overallPct };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"coverage.js","sourceRoot":"","sources":["../../src/flows/coverage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAyBH,SAAS,SAAS,CAAC,QAA2B,EAAE,SAA8B;IAC5E,MAAM,SAAS,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IAC5D,MAAM,OAAO,GAAG,QAAQ,CAAC,MAAM,GAAG,SAAS,CAAC,MAAM,CAAC;IACnD,MAAM,GAAG,GAAG,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,QAAQ,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC,CAAC;IACxF,OAAO,EAAE,KAAK,EAAE,QAAQ,CAAC,MAAM,EAAE,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAC7D,CAAC;AAED,MAAM,UAAU,eAAe,CAAC,QAAyB,EAAE,SAA0B;IACnF,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,MAAM,OAAO,GAAG,SAAS,CAAC,QAAQ,CAAC,OAAO,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC;IACxE,MAAM,KAAK,GAAG,SAAS,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,GAAG,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;IAClE,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,GAAG,OAAO,CAAC,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC;IAC1D,MAAM,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC,OAAO,CAAC;IAClE,MAAM,UAAU,GAAG,KAAK,KAAK,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,OAAO,GAAG,KAAK,CAAC,GAAG,GAAG,CAAC,CAAC;IAC3E,OAAO,EAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAE,CAAC;AACjD,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../src/flows/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAErB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"decision.d.ts","sourceRoot":"","sources":["../../src/flows/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAErB,KAAK,cAAc,EAEnB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAoCzB,wBAAgB,aAAa,CAAC,MAAM,EAAE,gBAAgB,EAAE,IAAI,CAAC,EAAE,QAAQ,GAAG,cAAc,CAyDvF;AAQD;;;;;GAKG;AACH,wBAAgB,iBAAiB,CAC/B,IAAI,EAAE,aAAa,CAAC;IAAE,MAAM,EAAE,gBAAgB,CAAC;IAAC,IAAI,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC,GACjE,YAAY,CAuBd"}
|
package/dist/flows/decision.js
CHANGED
|
@@ -5,21 +5,29 @@ import { SUCCESS_STEP_TOOL } from './flow-success.js';
|
|
|
5
5
|
* Turn a replay result into the autonomy DECISION envelope — the judgement a human reviewer used to
|
|
6
6
|
* make, expressed so a coding agent can act on it without one. Pure: no IO, no clock.
|
|
7
7
|
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
8
|
+
* pass → intent held; next action is none (or "add a consequence oracle" if the flow asserts nothing).
|
|
9
|
+
* drift → a locator/anchor missed; point at WHERE (file:line from the source anchor) + a rebind hint.
|
|
10
|
+
* fail → an action ran but its consequence/success oracle didn't fire (green-but-wrong) — check the handler.
|
|
11
11
|
*/
|
|
12
12
|
/** The first step that drifted or failed (drift takes precedence as the legible cause). */
|
|
13
13
|
function failingStep(steps) {
|
|
14
14
|
return steps.find((s) => s.drift !== undefined) ?? steps.find((s) => !s.ok);
|
|
15
15
|
}
|
|
16
|
-
/**
|
|
16
|
+
/**
|
|
17
|
+
* `file:line` for a step, from whichever anchor recorded provenance — or nothing.
|
|
18
|
+
*
|
|
19
|
+
* It used to fall back to `step.page`, which meant a field named "whereInSource" could return
|
|
20
|
+
* "/checkout". The report writer renders it as **Where:** `<value>`, so a route arrived looking
|
|
21
|
+
* exactly like a file path. A locator that is sometimes a route cannot be trusted when it genuinely
|
|
22
|
+
* is a path, which costs more than the fallback ever added — the page is already reported separately
|
|
23
|
+
* on the step.
|
|
24
|
+
*/
|
|
17
25
|
function whereInSource(step, flow) {
|
|
18
26
|
const anchor = flow?.steps[step.step]?.anchor;
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
return
|
|
27
|
+
const source = anchor?.kind === AnchorKind.COMPONENT || anchor?.kind === AnchorKind.TESTID
|
|
28
|
+
? anchor.source
|
|
29
|
+
: undefined;
|
|
30
|
+
return source === undefined ? undefined : `${source.file}:${String(source.line)}`;
|
|
23
31
|
}
|
|
24
32
|
export function buildDecision(result, flow) {
|
|
25
33
|
const { name, status, steps } = result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/flows/decision.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,YAAY,GAOb,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,sBAAsB,EAAE,MAAM,oBAAoB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD;;;;;;;GAOG;AAEH,2FAA2F;AAC3F,SAAS,WAAW,CAAC,KAAuB;IAC1C,OAAO,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAC9E,CAAC;AAED
|
|
1
|
+
{"version":3,"file":"decision.js","sourceRoot":"","sources":["../../src/flows/decision.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { FileSystemPort } from '../project/fs-port.js';
|
|
2
|
+
import { type FlakeLedger } from './flake.js';
|
|
3
|
+
export declare const FLAKE_FILE_VERSION = 1;
|
|
4
|
+
/**
|
|
5
|
+
* Persists the per-flow flake ledger at `.reticle/flake.json`. Local single-project memory (stays OSS —
|
|
6
|
+
* OSS-VS-SERVER). Loads never throw: missing/malformed/wrong-version degrades to an empty ledger, so
|
|
7
|
+
* a bad file never blocks a gate — it just re-learns flakiness. `record` accrues one unchanged-code
|
|
8
|
+
* replay outcome; `flakyFlows` is what the gate quarantines.
|
|
9
|
+
*/
|
|
10
|
+
export declare class FlakeStore {
|
|
11
|
+
#private;
|
|
12
|
+
constructor(fs: FileSystemPort, root: string);
|
|
13
|
+
load(): Promise<FlakeLedger>;
|
|
14
|
+
save(ledger: FlakeLedger): Promise<void>;
|
|
15
|
+
/** Accrue one unchanged-code replay outcome for a flow and persist. */
|
|
16
|
+
record(flow: string, passed: boolean): Promise<void>;
|
|
17
|
+
/** The flows currently quarantined as flaky — what the gate excludes from blocking. */
|
|
18
|
+
flakyFlows(): Promise<string[]>;
|
|
19
|
+
}
|
|
20
|
+
//# sourceMappingURL=flake-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flake-store.d.ts","sourceRoot":"","sources":["../../src/flows/flake-store.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAwD,KAAK,WAAW,EAAE,MAAM,YAAY,CAAC;AAEpG,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC;;;;;GAKG;AACH,qBAAa,UAAU;;gBAIT,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM;IAKtC,IAAI,IAAI,OAAO,CAAC,WAAW,CAAC;IAkB5B,IAAI,CAAC,MAAM,EAAE,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAQ9C,uEAAuE;IACjE,MAAM,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAM1D,uFAAuF;IACjF,UAAU,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;CAMtC"}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { dirname } from 'node:path';
|
|
2
|
+
import { reticleDirPaths } from '../project/reticle-dir.js';
|
|
3
|
+
import { FlakeFileSchema, emptyRecord, isFlaky, recordOutcome } from './flake.js';
|
|
4
|
+
export const FLAKE_FILE_VERSION = 1;
|
|
5
|
+
/**
|
|
6
|
+
* Persists the per-flow flake ledger at `.reticle/flake.json`. Local single-project memory (stays OSS —
|
|
7
|
+
* OSS-VS-SERVER). Loads never throw: missing/malformed/wrong-version degrades to an empty ledger, so
|
|
8
|
+
* a bad file never blocks a gate — it just re-learns flakiness. `record` accrues one unchanged-code
|
|
9
|
+
* replay outcome; `flakyFlows` is what the gate quarantines.
|
|
10
|
+
*/
|
|
11
|
+
export class FlakeStore {
|
|
12
|
+
#fs;
|
|
13
|
+
#path;
|
|
14
|
+
constructor(fs, root) {
|
|
15
|
+
this.#fs = fs;
|
|
16
|
+
this.#path = reticleDirPaths(root).flake;
|
|
17
|
+
}
|
|
18
|
+
async load() {
|
|
19
|
+
let text;
|
|
20
|
+
try {
|
|
21
|
+
text = await this.#fs.readFile(this.#path);
|
|
22
|
+
}
|
|
23
|
+
catch (error) {
|
|
24
|
+
if (this.#fs.isNotFound(error))
|
|
25
|
+
return {};
|
|
26
|
+
throw error;
|
|
27
|
+
}
|
|
28
|
+
let parsed;
|
|
29
|
+
try {
|
|
30
|
+
parsed = JSON.parse(text);
|
|
31
|
+
}
|
|
32
|
+
catch {
|
|
33
|
+
return {};
|
|
34
|
+
}
|
|
35
|
+
const result = FlakeFileSchema.safeParse(parsed);
|
|
36
|
+
return result.success ? result.data.flows : {};
|
|
37
|
+
}
|
|
38
|
+
async save(ledger) {
|
|
39
|
+
await this.#fs.mkdir(dirname(this.#path));
|
|
40
|
+
const body = `${JSON.stringify({ version: FLAKE_FILE_VERSION, flows: ledger }, null, 2)}\n`;
|
|
41
|
+
const tmp = `${this.#path}.tmp`;
|
|
42
|
+
await this.#fs.writeFile(tmp, body);
|
|
43
|
+
await this.#fs.rename(tmp, this.#path);
|
|
44
|
+
}
|
|
45
|
+
/** Accrue one unchanged-code replay outcome for a flow and persist. */
|
|
46
|
+
async record(flow, passed) {
|
|
47
|
+
const ledger = await this.load();
|
|
48
|
+
ledger[flow] = recordOutcome(ledger[flow] ?? emptyRecord(), passed);
|
|
49
|
+
await this.save(ledger);
|
|
50
|
+
}
|
|
51
|
+
/** The flows currently quarantined as flaky — what the gate excludes from blocking. */
|
|
52
|
+
async flakyFlows() {
|
|
53
|
+
const ledger = await this.load();
|
|
54
|
+
return Object.entries(ledger)
|
|
55
|
+
.filter(([, record]) => isFlaky(record))
|
|
56
|
+
.map(([flow]) => flow);
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
//# sourceMappingURL=flake-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flake-store.js","sourceRoot":"","sources":["../../src/flows/flake-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,EAAE,aAAa,EAAoB,MAAM,YAAY,CAAC;AAEpG,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,CAAC;AAEpC;;;;;GAKG;AACH,MAAM,OAAO,UAAU;IACZ,GAAG,CAAiB;IACpB,KAAK,CAAS;IAEvB,YAAY,EAAkB,EAAE,IAAY;QAC1C,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC;IAC3C,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,EAAE,CAAC;YAC1C,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,EAAE,CAAC;QACZ,CAAC;QACD,MAAM,MAAM,GAAG,eAAe,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACjD,OAAO,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;IACjD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,MAAmB;QAC5B,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,kBAAkB,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;QAC5F,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC;QAChC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,uEAAuE;IACvE,KAAK,CAAC,MAAM,CAAC,IAAY,EAAE,MAAe;QACxC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,MAAM,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,WAAW,EAAE,EAAE,MAAM,CAAC,CAAC;QACpE,MAAM,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1B,CAAC;IAED,uFAAuF;IACvF,KAAK,CAAC,UAAU;QACd,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QACjC,OAAO,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC;aAC1B,MAAM,CAAC,CAAC,CAAC,EAAE,MAAM,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;aACvC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,CAAC;IAC3B,CAAC;CACF"}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Flake ledger. Trust in the red is the product; one unexplained flake a week kills it. A flow that
|
|
4
|
+
* fails intermittently at UNCHANGED code is flaky, not a real regression — it must be quarantined
|
|
5
|
+
* (excluded from gate-blocking) and surfaced for repair, never silently blocking. The caller accrues an
|
|
6
|
+
* outcome ONLY for unchanged-code replays (a fail after a code change is a legitimate red, not flake).
|
|
7
|
+
*/
|
|
8
|
+
export declare const FlakeRecordSchema: z.ZodObject<{
|
|
9
|
+
runs: z.ZodNumber;
|
|
10
|
+
fails: z.ZodNumber;
|
|
11
|
+
}, "strip", z.ZodTypeAny, {
|
|
12
|
+
fails: number;
|
|
13
|
+
runs: number;
|
|
14
|
+
}, {
|
|
15
|
+
fails: number;
|
|
16
|
+
runs: number;
|
|
17
|
+
}>;
|
|
18
|
+
export type FlakeRecord = z.infer<typeof FlakeRecordSchema>;
|
|
19
|
+
/** Per-flow map (flow name → record). */
|
|
20
|
+
export type FlakeLedger = Record<string, FlakeRecord>;
|
|
21
|
+
export declare const FlakeFileSchema: z.ZodObject<{
|
|
22
|
+
version: z.ZodLiteral<1>;
|
|
23
|
+
flows: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
24
|
+
runs: z.ZodNumber;
|
|
25
|
+
fails: z.ZodNumber;
|
|
26
|
+
}, "strip", z.ZodTypeAny, {
|
|
27
|
+
fails: number;
|
|
28
|
+
runs: number;
|
|
29
|
+
}, {
|
|
30
|
+
fails: number;
|
|
31
|
+
runs: number;
|
|
32
|
+
}>>;
|
|
33
|
+
}, "strip", z.ZodTypeAny, {
|
|
34
|
+
version: 1;
|
|
35
|
+
flows: Record<string, {
|
|
36
|
+
fails: number;
|
|
37
|
+
runs: number;
|
|
38
|
+
}>;
|
|
39
|
+
}, {
|
|
40
|
+
version: 1;
|
|
41
|
+
flows: Record<string, {
|
|
42
|
+
fails: number;
|
|
43
|
+
runs: number;
|
|
44
|
+
}>;
|
|
45
|
+
}>;
|
|
46
|
+
/** Minimum unchanged-code replays before flakiness can be judged (too few = noise). */
|
|
47
|
+
export declare const DEFAULT_MIN_FLAKE_RUNS = 5;
|
|
48
|
+
export declare function emptyRecord(): FlakeRecord;
|
|
49
|
+
/** Accrue one unchanged-code replay outcome. */
|
|
50
|
+
export declare function recordOutcome(record: FlakeRecord, passed: boolean): FlakeRecord;
|
|
51
|
+
/**
|
|
52
|
+
* Flaky = enough unchanged-code runs, and it has BOTH passed and failed (intermittent). A flow that
|
|
53
|
+
* always fails is a real red; one that always passes is healthy; only the mix is flake.
|
|
54
|
+
*/
|
|
55
|
+
export declare function isFlaky(record: FlakeRecord, minRuns?: number): boolean;
|
|
56
|
+
/** Observed intermittent-failure rate (0 when too few runs to judge). */
|
|
57
|
+
export declare function flakeRate(record: FlakeRecord): number;
|
|
58
|
+
//# sourceMappingURL=flake.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flake.d.ts","sourceRoot":"","sources":["../../src/flows/flake.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AAEH,eAAO,MAAM,iBAAiB;;;;;;;;;EAG5B,CAAC;AACH,MAAM,MAAM,WAAW,GAAG,CAAC,CAAC,KAAK,CAAC,OAAO,iBAAiB,CAAC,CAAC;AAE5D,yCAAyC;AACzC,MAAM,MAAM,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;AAEtD,eAAO,MAAM,eAAe;;;;;;;;;;;;;;;;;;;;;;;;EAG1B,CAAC;AAEH,uFAAuF;AACvF,eAAO,MAAM,sBAAsB,IAAI,CAAC;AAExC,wBAAgB,WAAW,IAAI,WAAW,CAEzC;AAED,gDAAgD;AAChD,wBAAgB,aAAa,CAAC,MAAM,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,GAAG,WAAW,CAE/E;AAED;;;GAGG;AACH,wBAAgB,OAAO,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,GAAE,MAA+B,GAAG,OAAO,CAE9F;AAED,yEAAyE;AACzE,wBAAgB,SAAS,CAAC,MAAM,EAAE,WAAW,GAAG,MAAM,CAErD"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
/**
|
|
3
|
+
* Flake ledger. Trust in the red is the product; one unexplained flake a week kills it. A flow that
|
|
4
|
+
* fails intermittently at UNCHANGED code is flaky, not a real regression — it must be quarantined
|
|
5
|
+
* (excluded from gate-blocking) and surfaced for repair, never silently blocking. The caller accrues an
|
|
6
|
+
* outcome ONLY for unchanged-code replays (a fail after a code change is a legitimate red, not flake).
|
|
7
|
+
*/
|
|
8
|
+
export const FlakeRecordSchema = z.object({
|
|
9
|
+
runs: z.number().int().min(0),
|
|
10
|
+
fails: z.number().int().min(0),
|
|
11
|
+
});
|
|
12
|
+
export const FlakeFileSchema = z.object({
|
|
13
|
+
version: z.literal(1),
|
|
14
|
+
flows: z.record(FlakeRecordSchema),
|
|
15
|
+
});
|
|
16
|
+
/** Minimum unchanged-code replays before flakiness can be judged (too few = noise). */
|
|
17
|
+
export const DEFAULT_MIN_FLAKE_RUNS = 5;
|
|
18
|
+
export function emptyRecord() {
|
|
19
|
+
return { runs: 0, fails: 0 };
|
|
20
|
+
}
|
|
21
|
+
/** Accrue one unchanged-code replay outcome. */
|
|
22
|
+
export function recordOutcome(record, passed) {
|
|
23
|
+
return { runs: record.runs + 1, fails: record.fails + (passed ? 0 : 1) };
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Flaky = enough unchanged-code runs, and it has BOTH passed and failed (intermittent). A flow that
|
|
27
|
+
* always fails is a real red; one that always passes is healthy; only the mix is flake.
|
|
28
|
+
*/
|
|
29
|
+
export function isFlaky(record, minRuns = DEFAULT_MIN_FLAKE_RUNS) {
|
|
30
|
+
return record.runs >= minRuns && record.fails > 0 && record.fails < record.runs;
|
|
31
|
+
}
|
|
32
|
+
/** Observed intermittent-failure rate (0 when too few runs to judge). */
|
|
33
|
+
export function flakeRate(record) {
|
|
34
|
+
return record.runs === 0 ? 0 : record.fails / record.runs;
|
|
35
|
+
}
|
|
36
|
+
//# sourceMappingURL=flake.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"flake.js","sourceRoot":"","sources":["../../src/flows/flake.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AAExB;;;;;GAKG;AAEH,MAAM,CAAC,MAAM,iBAAiB,GAAG,CAAC,CAAC,MAAM,CAAC;IACxC,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;IAC7B,KAAK,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;CAC/B,CAAC,CAAC;AAMH,MAAM,CAAC,MAAM,eAAe,GAAG,CAAC,CAAC,MAAM,CAAC;IACtC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;IACrB,KAAK,EAAE,CAAC,CAAC,MAAM,CAAC,iBAAiB,CAAC;CACnC,CAAC,CAAC;AAEH,uFAAuF;AACvF,MAAM,CAAC,MAAM,sBAAsB,GAAG,CAAC,CAAC;AAExC,MAAM,UAAU,WAAW;IACzB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,KAAK,EAAE,CAAC,EAAE,CAAC;AAC/B,CAAC;AAED,gDAAgD;AAChD,MAAM,UAAU,aAAa,CAAC,MAAmB,EAAE,MAAe;IAChE,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,GAAG,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,KAAK,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;AAC3E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,OAAO,CAAC,MAAmB,EAAE,UAAkB,sBAAsB;IACnF,OAAO,MAAM,CAAC,IAAI,IAAI,OAAO,IAAI,MAAM,CAAC,KAAK,GAAG,CAAC,IAAI,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;AAClF,CAAC;AAED,yEAAyE;AACzE,MAAM,UAAU,SAAS,CAAC,MAAmB;IAC3C,OAAO,MAAM,CAAC,IAAI,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC;AAC5D,CAAC"}
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Classify whether a flow asserts an observable CONSEQUENCE or is "assertion-free" / presence-only.
|
|
3
3
|
*
|
|
4
4
|
* Why this exists (grounded in real testing behavior):
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* - Martin Fowler, *Assertion-Free Testing*: teams hit 100% coverage with tests that "weren't any
|
|
6
|
+
* assertions" — green, but verifying nothing.
|
|
7
|
+
* - Kent C. Dodds, *Make Your Test Fail*: a test that doesn't fail when you break the code gives
|
|
8
|
+
* false security.
|
|
9
|
+
* - Self-healing vendors (mabl, qate.ai) admit a locator healed to the WRONG element makes a test
|
|
10
|
+
* pass green while a real regression ships — but only if the test merely checks presence.
|
|
11
|
+
* - AI agents agree with human pass/fail only ~68% of the time (arXiv 2510.02418), so the flow
|
|
12
|
+
* itself must carry a real oracle, not rely on the agent eyeballing success.
|
|
13
13
|
*
|
|
14
14
|
* For a flow, an FlowExpect can assert a `signal` (app emitted an event), a `net` call, or just an
|
|
15
15
|
* `element` presence. signal/net are OBSERVABLE CONSEQUENCES — they can't be satisfied by a wrong
|
|
@@ -2,14 +2,14 @@
|
|
|
2
2
|
* Classify whether a flow asserts an observable CONSEQUENCE or is "assertion-free" / presence-only.
|
|
3
3
|
*
|
|
4
4
|
* Why this exists (grounded in real testing behavior):
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
*
|
|
8
|
-
*
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
5
|
+
* - Martin Fowler, *Assertion-Free Testing*: teams hit 100% coverage with tests that "weren't any
|
|
6
|
+
* assertions" — green, but verifying nothing.
|
|
7
|
+
* - Kent C. Dodds, *Make Your Test Fail*: a test that doesn't fail when you break the code gives
|
|
8
|
+
* false security.
|
|
9
|
+
* - Self-healing vendors (mabl, qate.ai) admit a locator healed to the WRONG element makes a test
|
|
10
|
+
* pass green while a real regression ships — but only if the test merely checks presence.
|
|
11
|
+
* - AI agents agree with human pass/fail only ~68% of the time (arXiv 2510.02418), so the flow
|
|
12
|
+
* itself must carry a real oracle, not rely on the agent eyeballing success.
|
|
13
13
|
*
|
|
14
14
|
* For a flow, an FlowExpect can assert a `signal` (app emitted an event), a `net` call, or just an
|
|
15
15
|
* `element` presence. signal/net are OBSERVABLE CONSEQUENCES — they can't be satisfied by a wrong
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-replay-run.d.ts","sourceRoot":"","sources":["../../src/flows/flow-replay-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,EAKb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAErB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"flow-replay-run.d.ts","sourceRoot":"","sources":["../../src/flows/flow-replay-run.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,aAAa,EAKb,KAAK,QAAQ,EACb,KAAK,gBAAgB,EAErB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAYzB,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,mBAAmB,CAAC;AAElD,wBAAgB,kBAAkB,CAChC,MAAM,EAAE,YAAY,EAAE,GACrB;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,iBAAiB,EAAE,QAAQ,CAAA;CAAE,GAAG,SAAS,CAQxE;AAED,kFAAkF;AAClF,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,aAAa,GAAG,MAAM,CAW5D;AA+BD;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,IAAI,EAAE,QAAQ,EACd,OAAO,EAAE;IAAE,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAAA;CAAE,GACvD,MAAM,GAAG,SAAS,CASpB;AAED;;;;GAIG;AACH,wBAAsB,eAAe,CACnC,IAAI,EAAE,QAAQ,EACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAC5B,OAAO,CAAC,gBAAgB,CAAC,CA+F3B;AA2BD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,IAAI,EAAE,QAAQ,EACd,SAAS,EAAE,MAAM,GAAG,SAAS,GAC5B,MAAM,GAAG,SAAS,CAMpB"}
|
|
@@ -4,6 +4,11 @@ import { replayFlow } from './flow-replay.js';
|
|
|
4
4
|
import { assertSuccess, dynamicTestids, successLabel, SUCCESS_STEP_TOOL } from './flow-success.js';
|
|
5
5
|
import { buildDecision } from './decision.js';
|
|
6
6
|
import { waitForPredicate } from '../events/predicate.js';
|
|
7
|
+
import { computeSegments } from '../journal/rollups.js';
|
|
8
|
+
import { AssertionTiersStore } from './assertion-tiers-store.js';
|
|
9
|
+
import { toFlowSources } from './flow-sources.js';
|
|
10
|
+
import { reportAndAccumulate } from '../journal/deviation-service.js';
|
|
11
|
+
import { EnvelopeStore } from '../journal/envelope-store.js';
|
|
7
12
|
export function latestRecordedFlow(events) {
|
|
8
13
|
for (let i = events.length - 1; i >= 0; i--) {
|
|
9
14
|
const event = events[i];
|
|
@@ -125,6 +130,18 @@ export async function replayNamedFlow(deps, args) {
|
|
|
125
130
|
const allOk = steps.every((s) => s.ok);
|
|
126
131
|
const status = driftSteps > 0 ? ReplayStatus.DRIFT : allOk ? ReplayStatus.OK : ReplayStatus.ERROR;
|
|
127
132
|
await recordReplayRun(deps, name, status, driftSteps, deps.now() - startedAt);
|
|
133
|
+
// Anti-reward-hacking baseline: record what this flow asserted ONLY when it passed clean. A
|
|
134
|
+
// failing run must never become the baseline a later weakening is measured against.
|
|
135
|
+
if (status === ReplayStatus.OK) {
|
|
136
|
+
await new AssertionTiersStore(deps.fs, deps.reticleRoot).recordPassing(name, loaded.value.steps.map((s, i) => ({
|
|
137
|
+
step: i,
|
|
138
|
+
...(s.expect === undefined ? {} : { expect: s.expect }),
|
|
139
|
+
})),
|
|
140
|
+
// Record what this flow COVERS so a later deletion can be scoped to the files that changed.
|
|
141
|
+
toFlowSources([{ name, steps: loaded.value.steps }])[0]?.sources ?? []);
|
|
142
|
+
}
|
|
143
|
+
// Push-default: the deviation report over this drive's segments, learned across runs. Best-effort.
|
|
144
|
+
const deviation = await computeReplayDeviation(deps, session, replayFloor);
|
|
128
145
|
const failed = steps.find((step) => !step.ok && step.drift === undefined);
|
|
129
146
|
if (failed !== undefined) {
|
|
130
147
|
const errored = {
|
|
@@ -135,14 +152,33 @@ export async function replayNamedFlow(deps, args) {
|
|
|
135
152
|
};
|
|
136
153
|
errored.decision = buildDecision(errored, loaded.value);
|
|
137
154
|
applyStartPathHint(errored, startPathHint);
|
|
155
|
+
if (deviation !== undefined)
|
|
156
|
+
errored.deviation = deviation;
|
|
138
157
|
return errored;
|
|
139
158
|
}
|
|
140
159
|
const result = { name, status, steps };
|
|
141
160
|
if (status !== ReplayStatus.OK)
|
|
142
161
|
result.decision = buildDecision(result, loaded.value);
|
|
143
162
|
applyStartPathHint(result, startPathHint);
|
|
163
|
+
if (deviation !== undefined)
|
|
164
|
+
result.deviation = deviation;
|
|
144
165
|
return result;
|
|
145
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* The deviation report over a replay's route segments — compared against the learned envelope, which is
|
|
169
|
+
* then updated. Best-effort: any failure (disk, empty window) yields undefined, never breaking the replay.
|
|
170
|
+
*/
|
|
171
|
+
async function computeReplayDeviation(deps, session, floor) {
|
|
172
|
+
try {
|
|
173
|
+
const segments = computeSegments(session.eventsSince(floor));
|
|
174
|
+
if (segments.length === 0)
|
|
175
|
+
return undefined;
|
|
176
|
+
return await reportAndAccumulate(new EnvelopeStore(deps.fs, deps.reticleRoot), segments);
|
|
177
|
+
}
|
|
178
|
+
catch {
|
|
179
|
+
return undefined;
|
|
180
|
+
}
|
|
181
|
+
}
|
|
146
182
|
/** Fold a start-page-mismatch hint onto a non-passing replay's decision (the actionable next move). */
|
|
147
183
|
function applyStartPathHint(result, hint) {
|
|
148
184
|
if (hint === undefined || result.decision === undefined)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-replay-run.js","sourceRoot":"","sources":["../../src/flows/flow-replay-run.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,SAAS,EACT,sBAAsB,EACtB,aAAa,EACb,kBAAkB,EAClB,YAAY,EACZ,OAAO,EACP,SAAS,GAKV,MAAM,iBAAiB,CAAC;AACzB,OAAO,EAAE,QAAQ,EAAE,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,cAAc,EAAE,YAAY,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AACnG,OAAO,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AAC9C,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"flow-replay-run.js","sourceRoot":"","sources":["../../src/flows/flow-replay-run.ts"],"names":[],"mappings":"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"}
|
|
@@ -7,6 +7,15 @@ import type { EvalResult, Predicate } from '../events/predicate.js';
|
|
|
7
7
|
*/
|
|
8
8
|
export interface FlowReplaySession {
|
|
9
9
|
command(name: string, args?: Record<string, unknown>): Promise<CommandResult>;
|
|
10
|
+
/**
|
|
11
|
+
* Attribution window around each replayed step. Optional so a minimal test double still satisfies the
|
|
12
|
+
* interface, but a real session MUST supply it: without a window the step's own effects carry no
|
|
13
|
+
* actionId, and Session.pushEvent classifies an unattributed ref-bearing event as ambient background
|
|
14
|
+
* churn. A 15-step flow can therefore teach the settle oracle to ignore every region the app reacts
|
|
15
|
+
* in — and this is the CI path, so the result is a green suite over an app that is still working.
|
|
16
|
+
*/
|
|
17
|
+
beginAction?(tool: string, args: Record<string, unknown>): void;
|
|
18
|
+
finishAction?(error?: string, settled?: boolean, settleMs?: number): void;
|
|
10
19
|
eventsSince(cursor: number): ReticleEvent[];
|
|
11
20
|
onEvent(listener: (event: ReticleEvent) => void): () => void;
|
|
12
21
|
/** Buffer clock (ms since connect) — required by the predicate engine's `settled` check. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"flow-replay.d.ts","sourceRoot":"","sources":["../../src/flows/flow-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,aAAa,EAIlB,KAAK,QAAQ,EAEb,KAAK,cAAc,EACnB,KAAK,YAAY,EAElB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"flow-replay.d.ts","sourceRoot":"","sources":["../../src/flows/flow-replay.ts"],"names":[],"mappings":"AAAA,OAAO,EAML,KAAK,aAAa,EAIlB,KAAK,QAAQ,EAEb,KAAK,cAAc,EACnB,KAAK,YAAY,EAElB,MAAM,iBAAiB,CAAC;AACzB,OAAO,KAAK,EAAE,UAAU,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAKpE;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,OAAO,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;IAC9E;;;;;;OAMG;IACH,WAAW,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,CAAC;IAChE,YAAY,CAAC,CAAC,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1E,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,YAAY,EAAE,CAAC;IAC5C,OAAO,CAAC,QAAQ,EAAE,CAAC,KAAK,EAAE,YAAY,KAAK,IAAI,GAAG,MAAM,IAAI,CAAC;IAC7D,4FAA4F;IAC5F,OAAO,IAAI,MAAM,CAAC;CACnB;AAED;;;;GAIG;AACH,MAAM,MAAM,aAAa,GAAG,CAC1B,OAAO,EAAE,iBAAiB,EAC1B,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,MAAM,EACjB,KAAK,CAAC,EAAE,MAAM,KACX,OAAO,CAAC,UAAU,CAAC,CAAC;AAEzB;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAiBzD;AAED;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,MAAM,GAAG,IAAI,CAkB/E;AAYD,mGAAmG;AACnG,KAAK,KAAK,GAAG,CAAC,EAAE,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;AA2B3C;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,GAAG,OAAO,CAc9E;AAuSD;;;;;GAKG;AACH,wBAAsB,UAAU,CAC9B,OAAO,EAAE,iBAAiB,EAC1B,IAAI,EAAE,QAAQ,EACd,aAAa,EAAE,aAAa,EAC5B,eAAe,EAAE,MAAM,EACvB,gBAAgB,UAAQ,EACxB,KAAK,GAAE,KAAiB,GACvB,OAAO,CAAC,cAAc,EAAE,CAAC,CA+D3B"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { AnchorKind, DriftReason, EventType, ReticleCommand, QueryBy, } from '@reticlehq/core';
|
|
2
2
|
import { asRecord, asString } from '../tools/tools-helpers.js';
|
|
3
3
|
import { replayActionArgs, ambiguousTestidNote, queryRefs } from './replay.js';
|
|
4
|
+
import { ReticleTool } from '../tools/tool-names.js';
|
|
4
5
|
/**
|
|
5
6
|
* A single ASCII-ish edit distance (case-insensitive). Small inputs (testids), so O(n*m) is fine.
|
|
6
7
|
* Exported so the heal proposal layer derives its confidence from the SAME distance used to
|
|
@@ -241,11 +242,21 @@ async function runComponentStep(session, step, index, anchor, confirmDangerous,
|
|
|
241
242
|
};
|
|
242
243
|
}
|
|
243
244
|
const ref = refs[0] ?? '';
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
245
|
+
// Attribute the step's effects to the step. Without this window they arrive with no actionId and are
|
|
246
|
+
// learned as ambient churn on the very regions the flow exercises.
|
|
247
|
+
session.beginAction?.(ReticleTool.FLOW_REPLAY, { ref, action: step.action ?? '' });
|
|
248
|
+
let act;
|
|
249
|
+
try {
|
|
250
|
+
act = await session.command(ReticleCommand.ACT, {
|
|
251
|
+
ref,
|
|
252
|
+
action: step.action ?? '',
|
|
253
|
+
args: replayActionArgs(step.args, confirmDangerous),
|
|
254
|
+
});
|
|
255
|
+
}
|
|
256
|
+
finally {
|
|
257
|
+
// Close on every exit so a throwing step cannot leak the window onto the next step's events.
|
|
258
|
+
session.finishAction?.();
|
|
259
|
+
}
|
|
249
260
|
const result = { step: index, tool: step.tool, anchor: label, ok: act.ok };
|
|
250
261
|
if (!act.ok)
|
|
251
262
|
result.error = act.error ?? 'command failed';
|
|
@@ -265,11 +276,18 @@ async function runTestidStep(session, step, index, value, dynamic, confirmDanger
|
|
|
265
276
|
}
|
|
266
277
|
const ref = refs[0] ?? '';
|
|
267
278
|
const note = refs.length > 1 ? ambiguousTestidNote(value) : undefined;
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
279
|
+
session.beginAction?.(ReticleTool.FLOW_REPLAY, { ref, action: step.action ?? '' });
|
|
280
|
+
let act;
|
|
281
|
+
try {
|
|
282
|
+
act = await session.command(ReticleCommand.ACT, {
|
|
283
|
+
ref,
|
|
284
|
+
action: step.action ?? '',
|
|
285
|
+
args: replayActionArgs(step.args, confirmDangerous),
|
|
286
|
+
});
|
|
287
|
+
}
|
|
288
|
+
finally {
|
|
289
|
+
session.finishAction?.();
|
|
290
|
+
}
|
|
273
291
|
const result = { step: index, tool: step.tool, anchor: value, ok: act.ok };
|
|
274
292
|
if (!act.ok) {
|
|
275
293
|
result.error = act.error ?? 'command failed';
|
|
@@ -320,8 +338,17 @@ async function assertStepState(session, state, waitForSignal, timeoutMs, since)
|
|
|
320
338
|
};
|
|
321
339
|
}
|
|
322
340
|
/** Run one signal-anchored step: wait for the signal predicate, else drift (no nearest for signals). */
|
|
323
|
-
async function runSignalStep(session, step, index, name, waitForSignal, signalTimeoutMs) {
|
|
324
|
-
|
|
341
|
+
async function runSignalStep(session, step, index, name, waitForSignal, signalTimeoutMs, since) {
|
|
342
|
+
// Scope to THIS replay's floor, not the whole buffer.
|
|
343
|
+
//
|
|
344
|
+
// A signal step is a pure wait — the signal is fired by the PRECEDING act step — so a per-step floor
|
|
345
|
+
// would miss it (false negative). But the default whole-buffer read (since=0) was too loose in the
|
|
346
|
+
// one place it matters most: reticle_flow_verify replays every saved flow back-to-back in ONE
|
|
347
|
+
// session, so a signal an EARLIER flow emitted (`auth:granted`, `nav:changed`) sat in the buffer and
|
|
348
|
+
// satisfied a LATER flow's signal step even when that flow's own action never fired it — a
|
|
349
|
+
// cross-flow false green on the exact suite-verify path the regression-cost claim rests on. The
|
|
350
|
+
// replay-start floor excludes prior flows/runs while still seeing this run's adjacent-step signal.
|
|
351
|
+
const verdict = await waitForSignal(session, { kind: 'signal', name }, signalTimeoutMs, since);
|
|
325
352
|
if (verdict.pass)
|
|
326
353
|
return { step: index, tool: step.tool, anchor: name, ok: true };
|
|
327
354
|
return {
|
|
@@ -349,6 +376,9 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
349
376
|
const dynamic = new Set((flow.dynamic ?? [])
|
|
350
377
|
.filter((a) => a.kind === AnchorKind.TESTID)
|
|
351
378
|
.map((a) => (a.kind === AnchorKind.TESTID ? a.value : '')));
|
|
379
|
+
// Floor for signal steps: signals that fire during THIS replay, never a prior flow/run in the same
|
|
380
|
+
// session. Captured once, before any step, so a back-to-back suite verify cannot cross-satisfy.
|
|
381
|
+
const replayFloor = session.elapsed();
|
|
352
382
|
let index = 0;
|
|
353
383
|
for (const step of flow.steps) {
|
|
354
384
|
const label = anchorLabel(step.anchor);
|
|
@@ -358,7 +388,7 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
358
388
|
const cursorBefore = session.elapsed();
|
|
359
389
|
let result;
|
|
360
390
|
if (step.anchor.kind === AnchorKind.SIGNAL) {
|
|
361
|
-
result = await runSignalStep(session, step, index, label, waitForSignal, signalTimeoutMs);
|
|
391
|
+
result = await runSignalStep(session, step, index, label, waitForSignal, signalTimeoutMs, replayFloor);
|
|
362
392
|
}
|
|
363
393
|
else if (step.anchor.kind === AnchorKind.COMPONENT) {
|
|
364
394
|
result = await runComponentStep(session, step, index, step.anchor, confirmDangerous, sleep);
|
|
@@ -380,6 +410,11 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
380
410
|
const consequence = summarizeConsequence(session.eventsSince(cursorBefore).filter((e) => e.t >= cursorBefore));
|
|
381
411
|
if (consequence !== undefined)
|
|
382
412
|
result.consequence = consequence;
|
|
413
|
+
// Per-step wall time from the session's injected clock (dispatch → here, post-settle). Only set when
|
|
414
|
+
// the clock actually advanced, so a fixed-clock fake reads durationMs-free (additive, non-breaking).
|
|
415
|
+
const durationMs = session.elapsed() - cursorBefore;
|
|
416
|
+
if (durationMs > 0)
|
|
417
|
+
result.durationMs = durationMs;
|
|
383
418
|
results.push(result);
|
|
384
419
|
if (result.drift !== undefined || !result.ok)
|
|
385
420
|
break;
|