@reticlehq/server 3.7.0 → 3.8.1
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/SKILL.md +59 -68
- package/bin/reticle.js +9 -2
- package/dist/command/cli/adhoc-suite.js +1 -1
- package/dist/command/cli/adhoc-verdict.d.ts +12 -0
- package/dist/command/cli/adhoc-verdict.js +62 -4
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +5 -1
- package/dist/command/cli/auth/cloud-session.d.ts +11 -19
- package/dist/command/cli/auth/cloud-session.js +23 -0
- package/dist/command/cli/auth/device-flow.d.ts +3 -37
- package/dist/command/cli/cli-doctor.js +66 -21
- package/dist/command/cli/cli-flow-commands.js +53 -11
- package/dist/command/cli/cli-kill.d.ts +8 -0
- package/dist/command/cli/cli-kill.js +43 -3
- package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
- package/dist/command/cli/cli-parse-feedback.js +13 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
- package/dist/command/cli/cli-parse-grammar.js +1 -6
- package/dist/command/cli/cli-parse-serve.d.ts +24 -0
- package/dist/command/cli/cli-parse-serve.js +124 -0
- package/dist/command/cli/cli-parse.d.ts +12 -11
- package/dist/command/cli/cli-parse.js +100 -123
- package/dist/command/cli/cli-usage.d.ts +0 -11
- package/dist/command/cli/cli-usage.js +43 -16
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +29 -14
- package/dist/command/cli/cloud-cli.js +27 -9
- package/dist/command/cli/cloud-kit.js +3 -3
- package/dist/command/cli/cloud-link.d.ts +1 -20
- package/dist/command/cli/cloud-link.js +2 -0
- package/dist/command/cli/cloud-login.d.ts +6 -2
- package/dist/command/cli/cloud-login.js +13 -41
- package/dist/command/cli/config/checkout.d.ts +10 -0
- package/dist/command/cli/config/checkout.js +78 -0
- package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/drive/drive-attach.d.ts +5 -0
- package/dist/command/cli/drive/drive-attach.js +21 -1
- package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
- package/dist/command/cli/hook/codex-transcript.js +224 -0
- package/dist/command/cli/hook/episode-structure.d.ts +24 -0
- package/dist/command/cli/hook/episode-structure.js +138 -0
- package/dist/command/cli/hook/hook-command.d.ts +9 -0
- package/dist/command/cli/hook/hook-command.js +211 -0
- package/dist/command/cli/hook/hook-fast.d.ts +31 -0
- package/dist/command/cli/hook/hook-fast.js +136 -0
- package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
- package/dist/command/cli/hook/prompt-hook.js +199 -0
- package/dist/command/cli/hook/tool-hook.d.ts +21 -0
- package/dist/command/cli/hook/tool-hook.js +259 -0
- package/dist/command/cli/launch/cli-launch.d.ts +2 -0
- package/dist/command/cli/launch/cli-launch.js +22 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
- package/dist/command/cli/mcp-command.d.ts +9 -0
- package/dist/command/cli/mcp-command.js +127 -41
- package/dist/command/cli/open-navigate.d.ts +43 -0
- package/dist/command/cli/open-navigate.js +85 -0
- package/dist/command/cli/ports/port-holder.d.ts +16 -4
- package/dist/command/cli/ports/port-holder.js +58 -12
- package/dist/command/cli/ports/resolve/cli-port.js +18 -2
- package/dist/command/cli/project-name.d.ts +1 -7
- package/dist/command/cli/project-name.js +1 -0
- package/dist/command/cli/report-command.d.ts +8 -2
- package/dist/command/cli/report-command.js +95 -18
- package/dist/command/cli/status-fields.d.ts +9 -2
- package/dist/command/cli/status-fields.js +148 -4
- package/dist/command/cli/try-command.d.ts +3 -4
- package/dist/command/cli/try-command.js +6 -11
- package/dist/command/cli/verify-results.d.ts +4 -1
- package/dist/command/cli/verify-results.js +3 -1
- package/dist/command/cli.d.ts +1 -7
- package/dist/command/cli.js +79 -160
- package/dist/command/daemon/daemon-resilience.d.ts +6 -1
- package/dist/command/daemon/daemon-resilience.js +31 -18
- package/dist/command/daemon/daemon.d.ts +11 -0
- package/dist/command/daemon/daemon.js +70 -2
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
- package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
- package/dist/command/daemon/wake-decision.js +4 -2
- package/dist/command/daemon/win32-escape.d.ts +32 -0
- package/dist/command/daemon/win32-escape.js +119 -0
- package/dist/command/setup/agent-configs.d.ts +9 -0
- package/dist/command/setup/agent-configs.js +9 -0
- package/dist/command/setup/auto-approve.d.ts +10 -3
- package/dist/command/setup/auto-approve.js +51 -3
- package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
- package/dist/command/setup/bringup/dev-server-wait.js +5 -1
- package/dist/command/setup/bringup/ensure-daemon.js +4 -7
- package/dist/command/setup/init/init-host.js +6 -0
- package/dist/command/setup/init/init-port.js +5 -4
- package/dist/command/setup/init/init-runtime.js +7 -1
- package/dist/command/setup/node-effects.d.ts +8 -0
- package/dist/command/setup/node-effects.js +36 -4
- package/dist/command/setup/probe/dev-port.d.ts +26 -0
- package/dist/command/setup/probe/dev-port.js +117 -0
- package/dist/command/setup/probe/page-probe.d.ts +1 -1
- package/dist/command/setup/probe/page-probe.js +11 -3
- package/dist/command/setup/remaining-steps.d.ts +0 -7
- package/dist/command/setup/remaining-steps.js +3 -2
- package/dist/command/setup/run-setup.d.ts +11 -0
- package/dist/command/setup/run-setup.js +33 -5
- package/dist/command/setup/setup-command.d.ts +2 -0
- package/dist/command/setup/setup-command.js +22 -4
- package/dist/command/update/updater.d.ts +1 -6
- package/dist/command/update/updater.js +4 -5
- package/dist/command/update/version-seen.d.ts +24 -0
- package/dist/command/update/version-seen.js +65 -0
- package/dist/command/version/peer-announce.d.ts +9 -1
- package/dist/command/version/peer-announce.js +25 -2
- package/dist/command/version/sdk-fix.d.ts +5 -6
- package/dist/command/version/sdk-fix.js +17 -32
- package/dist/command/version/version-skew.d.ts +16 -1
- package/dist/command/version/version-skew.js +84 -10
- package/dist/features/crawl/crawl-tools.js +2 -2
- package/dist/features/crawl/crawl.js +2 -0
- package/dist/features/exhaust/ledger.d.ts +15 -96
- package/dist/features/exhaust/ledger.js +3 -3
- package/dist/features/harness/drive-runs.d.ts +28 -4
- package/dist/features/harness/drive-runs.js +99 -7
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/harness.d.ts +5 -0
- package/dist/features/harness/harness.js +24 -12
- package/dist/features/harness/platform/platform-drives.d.ts +7 -1
- package/dist/features/harness/platform/platform-drives.js +12 -7
- package/dist/features/harness/platform/refusal.d.ts +1 -1
- package/dist/features/harness/platform/refusal.js +4 -4
- package/dist/features/harness/platform/remote-drive.js +70 -28
- package/dist/features/harness/platform/server-driver.js +22 -1
- package/dist/features/harness/platform-config.d.ts +1 -10
- package/dist/features/harness/platform-config.js +0 -20
- package/dist/features/license/license.d.ts +2 -14
- package/dist/features/visual/step-shots.d.ts +33 -1
- package/dist/features/visual/step-shots.js +155 -1
- package/dist/features/visual/visual-tools.js +12 -4
- package/dist/hooks/coding-agents.d.ts +6 -0
- package/dist/hooks/coding-agents.js +24 -3
- package/dist/hooks/episode-stamp.d.ts +32 -0
- package/dist/hooks/episode-stamp.js +61 -0
- package/dist/hooks/hook-commands.js +19 -9
- package/dist/index.d.ts +5 -1
- package/dist/index.js +66 -24
- package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
- package/dist/judgement/app-graph/journal-steps.js +92 -0
- package/dist/judgement/capsule/capsule-store.d.ts +2 -39
- package/dist/judgement/domain/domain-model.js +1 -10
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
- package/dist/judgement/runs/artifact/run-store.js +153 -28
- package/dist/judgement/runs/default-run-id.d.ts +3 -1
- package/dist/judgement/runs/default-run-id.js +15 -3
- package/dist/judgement/runs/drive-run.d.ts +3 -3
- package/dist/judgement/runs/drive-run.js +11 -7
- package/dist/judgement/runs/run-ledger.d.ts +21 -0
- package/dist/judgement/runs/run-ledger.js +143 -0
- package/dist/judgement/runs/runner-port.d.ts +1 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +4 -3
- package/dist/judgement/runs/verification-sync.js +27 -5
- package/dist/language/flows/affected-tools.js +2 -1
- package/dist/language/flows/annotate-notes/annotate.js +8 -3
- package/dist/language/flows/annotate-tools.js +1 -1
- package/dist/language/flows/change/affected.d.ts +8 -0
- package/dist/language/flows/change/affected.js +20 -7
- package/dist/language/flows/decision.js +19 -4
- package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
- package/dist/language/flows/fields/flow-secret-field.js +67 -5
- package/dist/language/flows/flow-anchor.d.ts +5 -0
- package/dist/language/flows/flow-anchor.js +4 -0
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +9 -0
- package/dist/language/flows/flow-expect-grammar.js +15 -10
- package/dist/language/flows/flow-intent.js +6 -1
- package/dist/language/flows/flow-journey.d.ts +8 -0
- package/dist/language/flows/flow-journey.js +13 -0
- package/dist/language/flows/flow-lease.d.ts +27 -0
- package/dist/language/flows/flow-lease.js +59 -0
- package/dist/language/flows/flow-replay-run.d.ts +1 -87
- package/dist/language/flows/flow-replay-run.js +111 -310
- package/dist/language/flows/flow-replay.js +21 -19
- package/dist/language/flows/flow-replayable.d.ts +38 -0
- package/dist/language/flows/flow-replayable.js +179 -0
- package/dist/language/flows/flow-start-path.d.ts +108 -0
- package/dist/language/flows/flow-start-path.js +313 -0
- package/dist/language/flows/flow-step-runners.d.ts +23 -2
- package/dist/language/flows/flow-step-runners.js +191 -32
- package/dist/language/flows/flow-store-for-session.d.ts +8 -1
- package/dist/language/flows/flow-store-for-session.js +6 -0
- package/dist/language/flows/flow-tools.d.ts +2 -23
- package/dist/language/flows/flow-tools.js +63 -113
- package/dist/language/flows/flows.d.ts +4 -6
- package/dist/language/flows/flows.js +90 -15
- package/dist/language/flows/heal-run.d.ts +10 -4
- package/dist/language/flows/heal-run.js +26 -9
- package/dist/language/flows/recording/flake.d.ts +3 -27
- package/dist/language/flows/recording/flake.js +1 -1
- package/dist/language/flows/recording/recording-backtrack.js +1 -4
- package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
- package/dist/language/flows/recording/tape/recordings.js +9 -3
- package/dist/language/flows/replay.d.ts +25 -5
- package/dist/language/flows/replay.js +83 -16
- package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
- package/dist/language/flows/suite/coverage.d.ts +9 -0
- package/dist/language/flows/suite/coverage.js +12 -1
- package/dist/language/flows/suite-selection.d.ts +25 -0
- package/dist/language/flows/suite-selection.js +41 -9
- package/dist/machine/git-tracks.d.ts +6 -0
- package/dist/machine/git-tracks.js +36 -0
- package/dist/memory/cloud/background-sync.d.ts +25 -0
- package/dist/memory/cloud/background-sync.js +79 -0
- package/dist/memory/cloud/cloud-config.d.ts +12 -1
- package/dist/memory/cloud/cloud-config.js +39 -13
- package/dist/memory/cloud/cloud-sync.d.ts +3 -24
- package/dist/memory/cloud/cloud-sync.js +5 -2
- package/dist/memory/cloud/harness-config.d.ts +0 -7
- package/dist/memory/cloud/memory-scope.d.ts +19 -0
- package/dist/memory/cloud/memory-scope.js +48 -0
- package/dist/memory/cloud/sync-answer.d.ts +43 -0
- package/dist/memory/cloud/sync-answer.js +42 -0
- package/dist/memory/cloud/sync-cycle.d.ts +40 -10
- package/dist/memory/cloud/sync-cycle.js +97 -144
- package/dist/memory/cloud/sync-daemon.d.ts +50 -3
- package/dist/memory/cloud/sync-daemon.js +473 -83
- package/dist/memory/cloud/sync-describe.d.ts +28 -0
- package/dist/memory/cloud/sync-describe.js +92 -0
- package/dist/memory/cloud/sync-disk.d.ts +9 -1
- package/dist/memory/cloud/sync-disk.js +137 -33
- package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
- package/dist/memory/cloud/sync-flow-versions.js +42 -0
- package/dist/memory/impact/impact-store.js +32 -15
- package/dist/memory/intent/intent-shard.d.ts +41 -266
- package/dist/memory/intent/intent-tools.js +20 -61
- package/dist/memory/intent/record-request.d.ts +27 -0
- package/dist/memory/intent/record-request.js +88 -0
- package/dist/memory/intent/settled-words.js +9 -1
- package/dist/memory/journal/drive-flow.d.ts +3 -0
- package/dist/memory/journal/drive-flow.js +11 -41
- package/dist/memory/journal/envelope-store.js +1 -1
- package/dist/memory/journal/envelope.d.ts +6 -154
- package/dist/memory/journal/episode-log.d.ts +107 -0
- package/dist/memory/journal/episode-log.js +302 -0
- package/dist/memory/journal/journal-recorder.d.ts +7 -0
- package/dist/memory/journal/journal-recorder.js +22 -9
- package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
- package/dist/memory/journal/on-disk/ambient-file.js +1 -1
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
- package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
- package/dist/memory/journal/self-observation.js +3 -1
- package/dist/memory/journal/session-end.js +23 -9
- package/dist/memory/journal/session-journal.js +39 -20
- package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
- package/dist/memory/project/artifact-root-resolver.js +68 -23
- package/dist/memory/project/artifact-root.d.ts +17 -3
- package/dist/memory/project/artifact-root.js +47 -9
- package/dist/memory/project/fs/fs-port.d.ts +5 -0
- package/dist/memory/project/fs/fs-port.js +13 -0
- package/dist/memory/project/learned-routes.d.ts +3 -4
- package/dist/memory/project/learned-routes.js +3 -11
- package/dist/memory/project/link-directory.js +5 -2
- package/dist/memory/project/root-claims.d.ts +3 -1
- package/dist/memory/project/root-claims.js +41 -7
- package/dist/memory/project/session-root.d.ts +1 -1
- package/dist/memory/project/session-root.js +1 -15
- package/dist/memory/project/sync-status.js +5 -6
- package/dist/memory/recall/memory-tools.js +2 -2
- package/dist/memory/recall/platform-memory.d.ts +3 -1
- package/dist/memory/recall/platform-memory.js +9 -1
- package/dist/memory/recall/project-memory.js +15 -19
- package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
- package/dist/portal/bridge/auth-failure-reason.js +19 -0
- package/dist/portal/bridge/bridge.d.ts +19 -4
- package/dist/portal/bridge/bridge.js +150 -177
- package/dist/portal/bridge/harness-request.d.ts +15 -0
- package/dist/portal/bridge/harness-request.js +19 -0
- package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
- package/dist/portal/bridge/origin/origin-follow.js +110 -0
- package/dist/portal/bridge/pairing-token.d.ts +6 -0
- package/dist/portal/bridge/pairing-token.js +47 -16
- package/dist/portal/bridge/protocol-skew.d.ts +27 -2
- package/dist/portal/bridge/protocol-skew.js +66 -2
- package/dist/portal/bridge/session-nonces.d.ts +46 -0
- package/dist/portal/bridge/session-nonces.js +72 -0
- package/dist/portal/input/viewport-tools.d.ts +31 -0
- package/dist/portal/input/viewport-tools.js +106 -15
- package/dist/portal/pool/bounded-close.d.ts +23 -0
- package/dist/portal/pool/bounded-close.js +38 -0
- package/dist/portal/pool/browser-pool.d.ts +44 -39
- package/dist/portal/pool/browser-pool.js +247 -95
- package/dist/portal/pool/context-permissions.d.ts +9 -1
- package/dist/portal/pool/context-permissions.js +26 -0
- package/dist/portal/pool/lease-emulation.d.ts +37 -0
- package/dist/portal/pool/lease-emulation.js +29 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +74 -7
- package/dist/portal/pool/pool-contract.d.ts +23 -1
- package/dist/portal/pool/pool-lease.d.ts +128 -0
- package/dist/portal/pool/pool-lease.js +49 -0
- package/dist/portal/pool/zero-install.d.ts +8 -1
- package/dist/portal/pool/zero-install.js +24 -2
- package/dist/portal/production/production-activation.d.ts +136 -0
- package/dist/portal/production/production-activation.js +173 -0
- package/dist/portal/production/production-drive.d.ts +52 -0
- package/dist/portal/production/production-drive.js +301 -0
- package/dist/portal/production/production-hello.d.ts +23 -0
- package/dist/portal/production/production-hello.js +23 -0
- package/dist/portal/realm/web-realm.js +42 -15
- package/dist/portal/session/control-envelope.d.ts +1 -1
- package/dist/portal/session/dev-server/served-document.d.ts +0 -5
- package/dist/portal/session/dev-server/served-document.js +6 -8
- package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
- package/dist/portal/session/first-run-wiring.d.ts +3 -36
- package/dist/portal/session/first-run-wiring.js +10 -103
- package/dist/portal/session/live-control-tools.js +61 -19
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +40 -15
- package/dist/portal/session/no-session-watch.d.ts +7 -0
- package/dist/portal/session/no-session-watch.js +67 -23
- package/dist/portal/session/output-budget.d.ts +10 -0
- package/dist/portal/session/output-budget.js +16 -0
- package/dist/portal/session/presence/session-lease.d.ts +2 -0
- package/dist/portal/session/presence/session-lease.js +8 -0
- package/dist/portal/session/recorded-gaps.d.ts +15 -11
- package/dist/portal/session/recorded-gaps.js +39 -18
- package/dist/portal/session/serving-directory.d.ts +24 -2
- package/dist/portal/session/serving-directory.js +93 -5
- package/dist/portal/session/session-info.d.ts +26 -0
- package/dist/portal/session/session-info.js +20 -0
- package/dist/portal/session/session-manager.d.ts +35 -3
- package/dist/portal/session/session-manager.js +69 -14
- package/dist/portal/session/session-successor.js +1 -9
- package/dist/portal/session/session-tools.js +22 -4
- package/dist/portal/session/session.d.ts +10 -10
- package/dist/portal/session/session.js +37 -29
- package/dist/portal/session/zero-install-first-call.d.ts +7 -2
- package/dist/portal/session/zero-install-first-call.js +43 -20
- package/dist/start-wiring.d.ts +2 -2
- package/dist/start-wiring.js +17 -3
- package/dist/status-payload.d.ts +11 -1
- package/dist/status-payload.js +7 -1
- package/dist/surface/agent-presence-grace.d.ts +11 -0
- package/dist/surface/agent-presence-grace.js +34 -0
- package/dist/surface/http-server.d.ts +12 -1
- package/dist/surface/http-server.js +64 -15
- package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
- package/dist/surface/mcp/faults/mcp-outage.js +19 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
- package/dist/surface/mcp/mcp-proxy.js +194 -267
- package/dist/surface/mcp/mcp.d.ts +20 -3
- package/dist/surface/mcp/mcp.js +88 -25
- package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
- package/dist/surface/mcp/proxy/drive-calls.js +114 -5
- package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
- package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
- package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
- package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
- package/dist/surface/mcp/server-instructions.js +35 -16
- package/dist/surface/mcp/shared-params.d.ts +8 -0
- package/dist/surface/mcp/shared-params.js +15 -1
- package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
- package/dist/surface/mcp/sse-frame-parser.js +18 -0
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +13 -0
- package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
- package/dist/surface/mcp/tool-catalog-cache.js +14 -4
- package/dist/surface/tools/account-tool.d.ts +4 -3
- package/dist/surface/tools/account-tool.js +20 -31
- package/dist/surface/tools/act/act-danger.d.ts +2 -0
- package/dist/surface/tools/act/act-danger.js +41 -14
- package/dist/surface/tools/act/act-observation.d.ts +11 -0
- package/dist/surface/tools/act/act-observation.js +33 -0
- package/dist/surface/tools/act/act-preflight.js +10 -3
- package/dist/surface/tools/act/act-sequence-retry.js +2 -1
- package/dist/surface/tools/act/act-target.js +19 -5
- package/dist/surface/tools/act/durable.js +1 -1
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
- package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
- package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
- package/dist/surface/tools/act/unsettled-find.js +71 -0
- package/dist/surface/tools/act-sequence-tool.js +53 -24
- package/dist/surface/tools/act-tools.d.ts +2 -3
- package/dist/surface/tools/act-tools.js +49 -47
- package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
- package/dist/surface/tools/agent/for-the-agent.js +41 -3
- package/dist/surface/tools/assert/assert-grade.js +8 -3
- package/dist/surface/tools/assert/assert-verdict.js +4 -2
- package/dist/surface/tools/browser-tools.js +7 -4
- package/dist/surface/tools/chat-drives.js +50 -25
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.d.ts +8 -0
- package/dist/surface/tools/dynamic-tools.js +89 -34
- package/dist/surface/tools/empty-session-list.d.ts +18 -25
- package/dist/surface/tools/empty-session-list.js +67 -38
- package/dist/surface/tools/error-recovery.d.ts +17 -7
- package/dist/surface/tools/error-recovery.js +53 -20
- package/dist/surface/tools/explore-tools.d.ts +10 -0
- package/dist/surface/tools/explore-tools.js +72 -19
- package/dist/surface/tools/feedback-tools.js +23 -2
- package/dist/surface/tools/gap-novelty.d.ts +6 -0
- package/dist/surface/tools/gap-novelty.js +9 -0
- package/dist/surface/tools/gaps/capability-absences.js +4 -3
- package/dist/surface/tools/harness-explore.d.ts +1 -1
- package/dist/surface/tools/harness-explore.js +6 -4
- package/dist/surface/tools/harness-gate.d.ts +43 -21
- package/dist/surface/tools/harness-gate.js +55 -81
- package/dist/surface/tools/harness-script.d.ts +2 -0
- package/dist/surface/tools/harness-script.js +11 -6
- package/dist/surface/tools/harness-toolset.js +3 -4
- package/dist/surface/tools/invoke-tool.d.ts +0 -8
- package/dist/surface/tools/invoke-tool.js +164 -178
- package/dist/surface/tools/lease-hint.d.ts +9 -0
- package/dist/surface/tools/lease-hint.js +22 -3
- package/dist/surface/tools/lease-permissions.d.ts +1 -1
- package/dist/surface/tools/lease-readiness.d.ts +55 -0
- package/dist/surface/tools/lease-readiness.js +150 -2
- package/dist/surface/tools/lease-tools.d.ts +3 -75
- package/dist/surface/tools/lease-tools.js +124 -188
- package/dist/surface/tools/map-tools.d.ts +20 -0
- package/dist/surface/tools/map-tools.js +145 -0
- package/dist/surface/tools/merge-tools.js +11 -7
- package/dist/surface/tools/next-step.js +6 -3
- package/dist/surface/tools/observe-tools.js +46 -35
- package/dist/surface/tools/platform-moment.d.ts +3 -12
- package/dist/surface/tools/platform-moment.js +12 -24
- package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
- package/dist/surface/tools/read/complete-snapshot.js +13 -2
- package/dist/surface/tools/read/query-paginate.js +6 -0
- package/dist/surface/tools/read/query-shape.d.ts +9 -0
- package/dist/surface/tools/read/query-shape.js +15 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
- package/dist/surface/tools/read-tools.js +5 -5
- package/dist/surface/tools/real-input-attempt.d.ts +11 -0
- package/dist/surface/tools/real-input-attempt.js +206 -38
- package/dist/surface/tools/reconcile-tools.js +21 -8
- package/dist/surface/tools/reticle-result.d.ts +3 -0
- package/dist/surface/tools/reticle-result.js +8 -1
- package/dist/surface/tools/run-report.d.ts +22 -0
- package/dist/surface/tools/run-report.js +141 -0
- package/dist/surface/tools/session-ports.d.ts +57 -0
- package/dist/surface/tools/session-ports.js +102 -0
- package/dist/surface/tools/tool-kit.d.ts +58 -4
- package/dist/surface/tools/tool-kit.js +140 -6
- package/dist/surface/tools/tool-surface.d.ts +2 -0
- package/dist/surface/tools/tool-surface.js +45 -0
- package/dist/surface/tools/tools.js +49 -87
- package/dist/telemetry/automation-hint.d.ts +5 -0
- package/dist/telemetry/automation-hint.js +7 -0
- package/dist/telemetry/cli-telemetry.d.ts +22 -0
- package/dist/telemetry/cli-telemetry.js +80 -11
- package/dist/telemetry/daemon-telemetry.d.ts +3 -1
- package/dist/telemetry/daemon-telemetry.js +9 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +8 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/feedback.js +51 -4
- package/dist/telemetry/harness-run.d.ts +3 -3
- package/dist/telemetry/harness-run.js +18 -7
- package/dist/telemetry/hud-events.d.ts +1 -1
- package/dist/telemetry/hud-metrics.d.ts +6 -3
- package/dist/telemetry/hud-metrics.js +20 -8
- package/dist/telemetry/install-source.js +1 -1
- package/dist/telemetry/mcp-connection.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +21 -2
- package/dist/telemetry/onboarding-firsts.d.ts +6 -1
- package/dist/telemetry/onboarding-firsts.js +41 -1
- package/dist/telemetry/proxy-telemetry.d.ts +42 -0
- package/dist/telemetry/proxy-telemetry.js +70 -1
- package/dist/telemetry/session-metrics.d.ts +1 -3
- package/dist/telemetry/session-metrics.js +16 -12
- package/dist/telemetry/telemetry.d.ts +9 -1
- package/dist/telemetry/telemetry.js +16 -1
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +7 -1
- package/dist/wire-journal.js +12 -2
- package/docs/README.md +4 -2
- package/docs/actions.mdx +7 -6
- package/docs/adapters.md +2 -1
- package/docs/agent-cheatsheet.md +19 -5
- package/docs/architecture.md +13 -10
- package/docs/autodrive.md +6 -5
- package/docs/benchmarks.md +2 -2
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +6 -6
- package/docs/cli/doctor.mdx +3 -1
- package/docs/cli/feedback.mdx +11 -7
- package/docs/cli/gate.mdx +1 -1
- package/docs/cli/help.mdx +1 -1
- package/docs/cli/init.mdx +20 -16
- package/docs/cli/mcp.mdx +5 -2
- package/docs/cli/open.mdx +5 -2
- package/docs/cli/report.mdx +1 -1
- package/docs/cli/restart.mdx +1 -1
- package/docs/cli/rollback.mdx +4 -4
- package/docs/cli/serve.mdx +7 -5
- package/docs/cli/setup.mdx +1 -1
- package/docs/cli/status.mdx +6 -2
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/telemetry.mdx +5 -1
- package/docs/cli/try.mdx +8 -8
- package/docs/cli/update.mdx +8 -5
- package/docs/cli/verify.mdx +12 -5
- package/docs/cli/version.mdx +1 -1
- package/docs/cli.mdx +10 -6
- package/docs/debugging.md +1 -1
- package/docs/deploy-checks.md +8 -6
- package/docs/desktop.mdx +14 -18
- package/docs/enterprise.md +6 -6
- package/docs/environment.mdx +5 -3
- package/docs/faq.mdx +9 -6
- package/docs/first-drive.md +19 -9
- package/docs/flows.md +3 -4
- package/docs/for-agents.md +1 -1
- package/docs/frameworks.mdx +34 -11
- package/docs/getting-started.md +46 -29
- package/docs/http-transport.md +2 -2
- package/docs/human-control.md +8 -8
- package/docs/index.mdx +2 -2
- package/docs/install-agentic.mdx +18 -19
- package/docs/install-manual.mdx +8 -4
- package/docs/integration-patterns.md +5 -5
- package/docs/multi-agent-testing.md +7 -5
- package/docs/packages/browser.mdx +34 -2
- package/docs/packages/core.mdx +2 -1
- package/docs/packages/electron.mdx +15 -3
- package/docs/packages/eslint-plugin.mdx +1 -1
- package/docs/packages/next.mdx +17 -5
- package/docs/packages/react.mdx +8 -1
- package/docs/packages/server.mdx +3 -3
- package/docs/packages/tauri.mdx +3 -3
- package/docs/packages/vite-plugin.mdx +1 -1
- package/docs/packages.mdx +19 -6
- package/docs/platform-integration.md +12 -4
- package/docs/predicates.mdx +18 -7
- package/docs/production-mode.md +108 -0
- package/docs/prompt-capture.md +99 -0
- package/docs/quickstart.mdx +14 -12
- package/docs/recipes.mdx +9 -8
- package/docs/required-checks.md +3 -2
- package/docs/skill-file.mdx +4 -3
- package/docs/skill-setup.md +2 -2
- package/docs/skill.md +62 -70
- package/docs/state-files.md +1 -0
- package/docs/state-management.mdx +11 -9
- package/docs/system-map.md +14 -13
- package/docs/telemetry.md +32 -24
- package/docs/testing.md +9 -5
- package/docs/tools/act-and-wait.mdx +17 -13
- package/docs/tools/act-sequence.mdx +40 -66
- package/docs/tools/act.mdx +7 -5
- package/docs/tools/assert.mdx +1 -1
- package/docs/tools/look.mdx +1 -1
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/network.mdx +13 -11
- package/docs/tools/overview.mdx +3 -3
- package/docs/tools/query.mdx +3 -3
- package/docs/tools/session-and-feedback.mdx +9 -6
- package/docs/tools/sessions.mdx +7 -0
- package/docs/tools/snapshot.mdx +9 -7
- package/docs/tools/tools-and-run.mdx +11 -10
- package/docs/tools/verify.mdx +1 -1
- package/docs/troubleshooting.mdx +21 -9
- package/docs/usage.md +58 -43
- package/docs/use-cases.mdx +2 -2
- package/docs/vs-chrome-devtools-mcp.mdx +5 -5
- package/docs/vs-playwright-mcp.mdx +5 -4
- package/docs/what-is-recorded.md +12 -7
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/dev/stale-issue-guard.d.ts +0 -34
- package/dist/command/dev/stale-issue-guard.js +0 -69
|
@@ -5,11 +5,11 @@ import { ambiguityDrift, anchorLabel, expectElementDrift, reresolved, resolveTes
|
|
|
5
5
|
export { nearestIsAmbiguous, nearestTestid, resolveQuery } from './flow-anchor.js';
|
|
6
6
|
import { routeOfEvent, routeOfUrl } from '@reticlehq/engine/question/predicate/predicate-route.js';
|
|
7
7
|
import { evalConsole } from '@reticlehq/engine/question/predicate/predicate-console.js';
|
|
8
|
-
import { stepEffect } from '@reticlehq/engine/evidence/step-effect.js';
|
|
8
|
+
import { appScope, stepEffect } from '@reticlehq/engine/evidence/step-effect.js';
|
|
9
9
|
import { AnchorKind, DriftReason, EventType, FlowStepTool, StepEffect, PredicateKind, ReplayStatus, } from '@reticlehq/core';
|
|
10
10
|
import { asString, invokedFlowMissing, isConsequenceDrift } from '@reticlehq/core';
|
|
11
11
|
import { anchorFieldName } from './fields/flow-secret-field.js';
|
|
12
|
-
import { degradedStepResult, isDegradedAnchor, runComponentStep, runRoleStep, runSequenceStep, } from './flow-step-runners.js';
|
|
12
|
+
import { degradedStepResult, isDocumentPressStep, isDegradedAnchor, runComponentStep, runRoleStep, runSequenceStep, } from './flow-step-runners.js';
|
|
13
13
|
import { inFlightRequestLabels } from '../../surface/tools/act/settle-in-flight.js';
|
|
14
14
|
import { namedNetIsInFlight } from '@reticlehq/engine/evidence/unsettled.js';
|
|
15
15
|
/** What a still-open named request means, in the drift's own words. */
|
|
@@ -464,6 +464,9 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
464
464
|
continue;
|
|
465
465
|
}
|
|
466
466
|
const label = anchorLabel(step.anchor);
|
|
467
|
+
/** One sub-step's expect, over the window that sub-step opened. See runSequenceStep. */
|
|
468
|
+
const judgeSubStep = async (expectation, since) => (await assertStepExpect(session, expectation, waitForSignal, waitFor(step), since)) ??
|
|
469
|
+
lateConsoleDrift(expectation, session.eventsSince(since).filter((e) => e.t >= since));
|
|
467
470
|
// The page this step runs on (the journey's "which page") — captured before the action.
|
|
468
471
|
const page = currentRoute(session);
|
|
469
472
|
// Event-time floor so the consequence reflects only THIS step's aftermath, not prior steps'.
|
|
@@ -477,8 +480,12 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
477
480
|
// Never QUERY the sentinel — it marks "no anchor was determined", not an element to find.
|
|
478
481
|
return degradedStepResult(step, index, label);
|
|
479
482
|
}
|
|
483
|
+
if (subSteps === undefined && isDocumentPressStep(step)) {
|
|
484
|
+
// A document-key press: dispatched with no ref, as it ran live (#1559).
|
|
485
|
+
return actOnResolvedRef(session, step, index, label, '', confirmDangerous);
|
|
486
|
+
}
|
|
480
487
|
if (subSteps !== undefined && subSteps.length > 0) {
|
|
481
|
-
return runSequenceStep(session, step, index, subSteps, confirmDangerous, sleep, dynamic);
|
|
488
|
+
return runSequenceStep(session, step, index, subSteps, confirmDangerous, sleep, dynamic, index < from ? undefined : judgeSubStep);
|
|
482
489
|
}
|
|
483
490
|
if (step.anchor.kind === AnchorKind.SIGNAL) {
|
|
484
491
|
return runSignalStep(session, step, index, label, waitForSignal, waitFor(step), replayFloor);
|
|
@@ -496,25 +503,18 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
496
503
|
// Once the anchor resolved and the action ran, the step's own expect is evaluated — signal, net,
|
|
497
504
|
// console and store truth alike — deterministically, in the same cheap replay loop, with no LLM.
|
|
498
505
|
/*
|
|
499
|
-
* The step's own expect
|
|
500
|
-
*
|
|
501
|
-
* `classifyFlowAssertions` already walks act_sequence sub-steps and counts an expect on either
|
|
502
|
-
* level, and states the invariant plainly: this and what replay enforces must move together, or
|
|
503
|
-
* "the difference is a false green or a lost verification". Enforcing only the top level was
|
|
504
|
-
* that difference -- a sequence whose sub-step declared a consequence was GRADED asserted and
|
|
505
|
-
* checked by nothing, so it could not go red while wearing the grade that says it could.
|
|
506
|
+
* The step's own expect. A sub-step's expect was judged by the sequence runner, in the window
|
|
507
|
+
* of that sub-step, as the live `act_sequence` path judges it.
|
|
506
508
|
*
|
|
507
|
-
*
|
|
508
|
-
*
|
|
509
|
-
*
|
|
510
|
-
*
|
|
511
|
-
* `act_sequence` path takes a cursor before each dispatch and does not have this. Narrowing it
|
|
512
|
-
* here means dispatching sub-steps individually on replay, which is a behaviour change to the
|
|
513
|
-
* replay path and belongs in its own commit.
|
|
509
|
+
* `classifyFlowAssertions` walks act_sequence sub-steps and counts an expect on either level,
|
|
510
|
+
* and this and what replay enforces must move together, or "the difference is a false green or
|
|
511
|
+
* a lost verification". Judged here, at the end, a route expect on a middle sub-step failed
|
|
512
|
+
* once a later one moved on, and a later claim could pass on an earlier sub-step's request.
|
|
514
513
|
*/
|
|
515
514
|
const declared = [step.expect, ...(step.steps ?? []).map((sub) => sub.expect)].filter((expectation) => expectation !== undefined);
|
|
515
|
+
const own = step.expect === undefined ? [] : [step.expect];
|
|
516
516
|
// A setup step's consequence is not checked: it is re-driven to get somewhere, not to prove it.
|
|
517
|
-
const checked = index < from ? [] :
|
|
517
|
+
const checked = index < from ? [] : own;
|
|
518
518
|
for (const expectation of checked) {
|
|
519
519
|
if (!result.ok || result.drift !== undefined)
|
|
520
520
|
break;
|
|
@@ -551,7 +551,9 @@ export async function replayFlow(session, flow, waitForSignal, signalTimeoutMs,
|
|
|
551
551
|
const cursorAfter = session.elapsed();
|
|
552
552
|
// ONE builder, shared with the live act path, so a driven step and a replayed one describe what
|
|
553
553
|
// happened in identical words rather than in two vocabularies that agree by coincidence.
|
|
554
|
-
Object.assign(result, stepEffect(windowEvents, { since: cursorBefore, until: cursorAfter }
|
|
554
|
+
Object.assign(result, stepEffect(windowEvents, { since: cursorBefore, until: cursorAfter },
|
|
555
|
+
// A failure the step declared is its expected result, as it is on the live path.
|
|
556
|
+
{ ...appScope(session), declared }));
|
|
555
557
|
/*
|
|
556
558
|
* A prefix step is setup and is not reported -- UNLESS it failed.
|
|
557
559
|
*
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a saved flow can replay at all, decided when it is saved, and what save changes so it can.
|
|
3
|
+
*
|
|
4
|
+
* Of 34 flows saved over one night, 5 replayed green. None of the misses was a defect in the app:
|
|
5
|
+
* a flow with no starting page, an anchor six buttons share, a live count ("Open 336") the next run
|
|
6
|
+
* cannot see again, or a step that WROTE real data each time it replayed. Each was found by a
|
|
7
|
+
* replay that drifted, never said when the flow was saved. This says it at save, and again with
|
|
8
|
+
* every suite verdict.
|
|
9
|
+
*
|
|
10
|
+
* Pure: a flow in, a flow or a report out. No IO, no clock.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { type FlowFile } from '@reticlehq/core';
|
|
14
|
+
export declare const Replayable: {
|
|
15
|
+
readonly YES: "replayable";
|
|
16
|
+
readonly NO: "not_replayable";
|
|
17
|
+
/** It replays, but an expect names data the next run will not see again. */
|
|
18
|
+
readonly DATA_BOUND: "data_bound";
|
|
19
|
+
};
|
|
20
|
+
export type Replayable = (typeof Replayable)[keyof typeof Replayable];
|
|
21
|
+
export interface Replayability {
|
|
22
|
+
status: Replayable;
|
|
23
|
+
/** One sentence for each reason, by step. Absent when there is nothing to say. */
|
|
24
|
+
why?: string[];
|
|
25
|
+
/** A step sends a write request, so a replay changes real data. */
|
|
26
|
+
writes?: true;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* The flow as it is saved: a live count in a text expect becomes word-level where the step allows
|
|
30
|
+
* it, and a step whose expect names a write request is marked `writes`. A money check keeps its
|
|
31
|
+
* number exact, and the report then says the flow is bound to the data.
|
|
32
|
+
*/
|
|
33
|
+
export declare function readyForReplay(flow: FlowFile): FlowFile;
|
|
34
|
+
/** Whether the flow can replay, and why not, by step. */
|
|
35
|
+
export declare function replayability(flow: FlowFile): Replayability;
|
|
36
|
+
/** The suite's argument and field for this, worded once. */
|
|
37
|
+
export declare const SKIP_WRITES_ARG: z.ZodOptional<z.ZodBoolean>;
|
|
38
|
+
export declare const REPLAYABILITY_OUTPUT: z.ZodOptional<z.ZodArray<z.ZodUnknown>>;
|
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a saved flow can replay at all, decided when it is saved, and what save changes so it can.
|
|
3
|
+
*
|
|
4
|
+
* Of 34 flows saved over one night, 5 replayed green. None of the misses was a defect in the app:
|
|
5
|
+
* a flow with no starting page, an anchor six buttons share, a live count ("Open 336") the next run
|
|
6
|
+
* cannot see again, or a step that WROTE real data each time it replayed. Each was found by a
|
|
7
|
+
* replay that drifted, never said when the flow was saved. This says it at save, and again with
|
|
8
|
+
* every suite verdict.
|
|
9
|
+
*
|
|
10
|
+
* Pure: a flow in, a flow or a report out. No IO, no clock.
|
|
11
|
+
*/
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
import { AnchorKind, DEGRADED_ANCHOR_ROLE, MUTATING_METHODS, PredicateKind, } from '@reticlehq/core';
|
|
14
|
+
export const Replayable = {
|
|
15
|
+
YES: 'replayable',
|
|
16
|
+
NO: 'not_replayable',
|
|
17
|
+
/** It replays, but an expect names data the next run will not see again. */
|
|
18
|
+
DATA_BOUND: 'data_bound',
|
|
19
|
+
};
|
|
20
|
+
const NUMBER = /\d[\d,.]*/g;
|
|
21
|
+
const HAS_NUMBER = /\d/;
|
|
22
|
+
/** The words of a money check. Its number IS the claim, so it is never made word-level. */
|
|
23
|
+
const MONEY = /credit|price|cost|charge|balance|paid|pay|invoice|refund|\$|€|£/i;
|
|
24
|
+
/** A fragment kept as the words of a count: at least two letters. */
|
|
25
|
+
const WORDS = /[A-Za-z]{2,}/;
|
|
26
|
+
const NUMBER_PATTERN = '\\d[\\d,.]*';
|
|
27
|
+
const MATCHES_PATTERN = 'matchesPattern';
|
|
28
|
+
const escapeRegex = (text) => text.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
|
|
29
|
+
/**
|
|
30
|
+
* A text expect with a live count, made word-level: the words stay exact, the number may change.
|
|
31
|
+
* Undefined when it cannot be: no words beside the number, a money check, or a `satisfies` already.
|
|
32
|
+
*/
|
|
33
|
+
function wordLevel(contains, money) {
|
|
34
|
+
if (money || MONEY.test(contains))
|
|
35
|
+
return undefined;
|
|
36
|
+
const words = contains
|
|
37
|
+
.split(NUMBER)
|
|
38
|
+
.map((part) => part.trim())
|
|
39
|
+
.filter((part) => WORDS.test(part))
|
|
40
|
+
.sort((a, b) => b.length - a.length)[0];
|
|
41
|
+
if (words === undefined)
|
|
42
|
+
return undefined;
|
|
43
|
+
const pattern = contains.split(NUMBER).map(escapeRegex).join(NUMBER_PATTERN);
|
|
44
|
+
return {
|
|
45
|
+
kind: PredicateKind.TEXT,
|
|
46
|
+
contains: words,
|
|
47
|
+
satisfies: { property: MATCHES_PATTERN, pattern },
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
function relax(predicate, money) {
|
|
51
|
+
if (PredicateKind.ALL_OF === predicate.kind || PredicateKind.ANY_OF === predicate.kind) {
|
|
52
|
+
return { ...predicate, predicates: predicate.predicates.map((p) => relax(p, money)) };
|
|
53
|
+
}
|
|
54
|
+
if (PredicateKind.TEXT === predicate.kind &&
|
|
55
|
+
predicate.satisfies === undefined &&
|
|
56
|
+
predicate.contains !== undefined &&
|
|
57
|
+
HAS_NUMBER.test(predicate.contains)) {
|
|
58
|
+
const relaxed = wordLevel(predicate.contains, money);
|
|
59
|
+
if (relaxed !== undefined) {
|
|
60
|
+
const { contains: _contains, ...rest } = predicate;
|
|
61
|
+
return { ...rest, ...relaxed };
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
return predicate;
|
|
65
|
+
}
|
|
66
|
+
/** Every leaf predicate under a composite, `not` included: a count is data-bound either way. */
|
|
67
|
+
function leaves(predicate) {
|
|
68
|
+
if (predicate === undefined)
|
|
69
|
+
return [];
|
|
70
|
+
if (PredicateKind.ALL_OF === predicate.kind || PredicateKind.ANY_OF === predicate.kind) {
|
|
71
|
+
return predicate.predicates.flatMap(leaves);
|
|
72
|
+
}
|
|
73
|
+
if (PredicateKind.NOT === predicate.kind)
|
|
74
|
+
return leaves(predicate.predicate);
|
|
75
|
+
return [predicate];
|
|
76
|
+
}
|
|
77
|
+
/** The write requests an expect names, as "METHOD url". */
|
|
78
|
+
function writesNamed(predicate) {
|
|
79
|
+
return leaves(predicate).flatMap((leaf) => PredicateKind.NET === leaf.kind &&
|
|
80
|
+
leaf.method !== undefined &&
|
|
81
|
+
MUTATING_METHODS.includes(leaf.method.toUpperCase())
|
|
82
|
+
? [`${leaf.method.toUpperCase()} ${leaf.urlContains ?? ''}`.trim()]
|
|
83
|
+
: []);
|
|
84
|
+
}
|
|
85
|
+
/** The live data an expect names: a number in text, in an element's name or text, or in state. */
|
|
86
|
+
function liveData(predicate) {
|
|
87
|
+
return leaves(predicate).flatMap((leaf) => {
|
|
88
|
+
if (PredicateKind.TEXT === leaf.kind && leaf.satisfies === undefined) {
|
|
89
|
+
return leaf.contains !== undefined && HAS_NUMBER.test(leaf.contains) ? [leaf.contains] : [];
|
|
90
|
+
}
|
|
91
|
+
if (PredicateKind.ELEMENT === leaf.kind) {
|
|
92
|
+
return [leaf.query.name, leaf.query.text].filter((value) => value !== undefined && HAS_NUMBER.test(value));
|
|
93
|
+
}
|
|
94
|
+
if (PredicateKind.STATE === leaf.kind && 'number' === typeof leaf.equals) {
|
|
95
|
+
return [`${leaf.path} = ${String(leaf.equals)}`];
|
|
96
|
+
}
|
|
97
|
+
return [];
|
|
98
|
+
});
|
|
99
|
+
}
|
|
100
|
+
function readyStep(step, money) {
|
|
101
|
+
const steps = step.steps?.map((sub) => readyStep(sub, money));
|
|
102
|
+
const expect = step.expect === undefined ? undefined : relax(step.expect, money);
|
|
103
|
+
const writes = true === step.writes ||
|
|
104
|
+
0 < writesNamed(step.expect).length ||
|
|
105
|
+
true === steps?.some((sub) => true === sub.writes);
|
|
106
|
+
return {
|
|
107
|
+
...step,
|
|
108
|
+
...(expect === undefined ? {} : { expect }),
|
|
109
|
+
...(steps === undefined ? {} : { steps }),
|
|
110
|
+
...(writes ? { writes: true } : {}),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* The flow as it is saved: a live count in a text expect becomes word-level where the step allows
|
|
115
|
+
* it, and a step whose expect names a write request is marked `writes`. A money check keeps its
|
|
116
|
+
* number exact, and the report then says the flow is bound to the data.
|
|
117
|
+
*/
|
|
118
|
+
export function readyForReplay(flow) {
|
|
119
|
+
const money = MONEY.test(flow.intent ?? '');
|
|
120
|
+
return { ...flow, steps: flow.steps.map((step) => readyStep(step, money)) };
|
|
121
|
+
}
|
|
122
|
+
function addressed(steps, prefix = '') {
|
|
123
|
+
return steps.flatMap((step, i) => {
|
|
124
|
+
const at = `${prefix}${String(i + 1)}`;
|
|
125
|
+
return [{ at, step }, ...addressed(step.steps ?? [], `${at}.`)];
|
|
126
|
+
});
|
|
127
|
+
}
|
|
128
|
+
/** Whether the flow can replay, and why not, by step. */
|
|
129
|
+
export function replayability(flow) {
|
|
130
|
+
const blocked = [];
|
|
131
|
+
const bound = [];
|
|
132
|
+
const writes = [];
|
|
133
|
+
if (flow.startPath === undefined || '' === flow.startPath) {
|
|
134
|
+
blocked.push('no starting page was recorded, so a replay starts wherever the tab is');
|
|
135
|
+
}
|
|
136
|
+
for (const { at, step } of addressed(flow.steps)) {
|
|
137
|
+
// A hand-written flow read without the schema can lack an anchor; it then says nothing here.
|
|
138
|
+
const anchor = step.anchor;
|
|
139
|
+
// A sequence's own anchor is a copy of a sub-step's; the sub-step answers for it.
|
|
140
|
+
const own = step.steps === undefined;
|
|
141
|
+
if (own &&
|
|
142
|
+
(true === step.degraded ||
|
|
143
|
+
(AnchorKind.ROLE === anchor?.kind && DEGRADED_ANCHOR_ROLE === anchor.role))) {
|
|
144
|
+
blocked.push(`step ${at} has no anchor a replay can find`);
|
|
145
|
+
}
|
|
146
|
+
else if (own && AnchorKind.TESTID === anchor?.kind && anchor.of !== undefined) {
|
|
147
|
+
blocked.push(`step ${at} anchors on test id '${anchor.value}', which ${String(anchor.of)} elements share`);
|
|
148
|
+
}
|
|
149
|
+
if (own &&
|
|
150
|
+
AnchorKind.ROLE === anchor?.kind &&
|
|
151
|
+
anchor.name !== undefined &&
|
|
152
|
+
HAS_NUMBER.test(anchor.name)) {
|
|
153
|
+
bound.push(`step ${at} acts on a control named '${anchor.name}', a live count`);
|
|
154
|
+
}
|
|
155
|
+
for (const data of liveData(step.expect))
|
|
156
|
+
bound.push(`step ${at} expects '${data}', live data`);
|
|
157
|
+
for (const write of own ? writesNamed(step.expect) : [])
|
|
158
|
+
writes.push(`step ${at} sends ${write}`);
|
|
159
|
+
if (own && true === step.writes && 0 === writesNamed(step.expect).length) {
|
|
160
|
+
writes.push(`step ${at} sent a write request when it was recorded`);
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
const why = [...blocked, ...bound, ...writes];
|
|
164
|
+
const status = 0 < blocked.length ? Replayable.NO : 0 < bound.length ? Replayable.DATA_BOUND : Replayable.YES;
|
|
165
|
+
return {
|
|
166
|
+
status,
|
|
167
|
+
...(0 === why.length ? {} : { why }),
|
|
168
|
+
...(0 === writes.length ? {} : { writes: true }),
|
|
169
|
+
};
|
|
170
|
+
}
|
|
171
|
+
/** The suite's argument and field for this, worded once. */
|
|
172
|
+
export const SKIP_WRITES_ARG = z
|
|
173
|
+
.boolean()
|
|
174
|
+
.optional()
|
|
175
|
+
.describe('Certify without changing data: hold back every flow with a step that sends a write request (POST, PUT, PATCH, DELETE), and name them in `skippedWrites`.');
|
|
176
|
+
export const REPLAYABILITY_OUTPUT = z
|
|
177
|
+
.array(z.unknown())
|
|
178
|
+
.optional()
|
|
179
|
+
.describe('Each flow that cannot replay as saved: not_replayable (no starting page, an anchor no replay can find or several elements share) or data_bound (live data in an expect), and writes when a step sends a write request. A drift on such a flow is the flow, not the app.');
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Replay's arrival at a flow's start page: navigate (or reload) before step 1, wait for the session
|
|
3
|
+
* the SDK reconnects as, and say what happened when it does not.
|
|
4
|
+
*/
|
|
5
|
+
import { type CommandResult, type FlowFile, type FlowReplayResult, type ReticleEvent, type StartPageWait } from '@reticlehq/core';
|
|
6
|
+
import type { ArrivalClock } from '../../surface/tools/act/navigation/navigate-arrival.js';
|
|
7
|
+
import type { SessionManager } from '../../portal/session/session-manager.js';
|
|
8
|
+
import type { Session } from '../../portal/session/session.js';
|
|
9
|
+
/** The slice of a session the start-path logic reads: the live URL plus the event buffer. */
|
|
10
|
+
interface StartPathSession {
|
|
11
|
+
url?: string;
|
|
12
|
+
eventsSince(cursor: number): ReticleEvent[];
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* When a flow records the page its journey started on (`startPath`) and the tab is currently on a
|
|
16
|
+
* different route, step 1 drifts for a reason that has nothing to do with the app regressing — the
|
|
17
|
+
* anchor simply isn't on this page yet. Detect that so the decision says "navigate there first"
|
|
18
|
+
* instead of a mystifying "a step no longer matches". Returns undefined when the routes agree or the
|
|
19
|
+
* current route is unobservable — never a false alarm. Replay normally never gets here on a
|
|
20
|
+
* wrong page (arriveAtStartPath navigates before step 1); this is the fallback when navigation
|
|
21
|
+
* was refused. A page that never reconnected is reported as unverifiable before step 1.
|
|
22
|
+
*/
|
|
23
|
+
export declare function startPathMismatchHint(flow: FlowFile, session: StartPathSession): string | undefined;
|
|
24
|
+
/** What replay learned on its way to step 0. Both fields absent = the tab was left exactly as it was. */
|
|
25
|
+
export interface StartPathArrival {
|
|
26
|
+
/** The successor session replay must continue on. Absent when nothing was navigated, or arrival timed out. */
|
|
27
|
+
session?: Session;
|
|
28
|
+
/** Set when the RESET itself is why step 1 cannot start — the reason a step-1 red is not drift. */
|
|
29
|
+
resetCost?: string;
|
|
30
|
+
/** Set when the tab was sent away and nothing reconnected: the old handle will never answer (#1129). */
|
|
31
|
+
lost?: string;
|
|
32
|
+
/** A live successor arrived on a different route, so replay must not use the dead old handle. */
|
|
33
|
+
redirected?: string;
|
|
34
|
+
/** Set when the page's loading kept replay waiting past the step budget. */
|
|
35
|
+
wait?: StartPageWait;
|
|
36
|
+
}
|
|
37
|
+
/** The replay result, with how long replay waited for its start page when that went past the budget. */
|
|
38
|
+
export declare function withStartPageWait<R extends FlowReplayResult>(result: R, arrival: StartPathArrival): R;
|
|
39
|
+
/**
|
|
40
|
+
* Replay's half of the FlowFile contract: put the tab on the flow's `startPath` before step 1, and
|
|
41
|
+
* RELOAD it if it is already there.
|
|
42
|
+
*
|
|
43
|
+
* The reload is the state contract. Replaying "add a task" twice against a tab nobody reset gives
|
|
44
|
+
* the second run a world the recording never saw, and its assertions then describe the first run
|
|
45
|
+
* rather than the app. Our own `replay-determinism.mjs` has always refreshed before every run — the
|
|
46
|
+
* determinism we measured was never the determinism a user got.
|
|
47
|
+
*
|
|
48
|
+
* `requires` is the declared opt-out, and its first caller. A flow that says it starts from state
|
|
49
|
+
* another flow established is the one flow a page load would destroy, so it is never reset — here
|
|
50
|
+
* or from the wrong page. Silence is not an opt-out: a flow that depends on leftovers without
|
|
51
|
+
* saying so is a flow whose green means nothing on a fresh machine, and CI is a fresh machine.
|
|
52
|
+
*
|
|
53
|
+
* A full-page load tears down the session socket, so the navigation must happen here — before any
|
|
54
|
+
* step runs — and the replay continues on the session the SDK reconnects as (found via the same
|
|
55
|
+
* tombstone rebind that lets `resolve(oldId)` answer after any navigation). Best-effort by design:
|
|
56
|
+
* when the flow carries no startPath, the current route is unobservable, or navigation is refused,
|
|
57
|
+
* replay proceeds on the connected session. A missing successor stops before step 1; a redirect
|
|
58
|
+
* continues on the live successor with a route-specific hint.
|
|
59
|
+
*/
|
|
60
|
+
export declare function arriveAtStartPath(sessions: SessionManager, session: StartPathSession & {
|
|
61
|
+
id: string;
|
|
62
|
+
command(name: string, args?: Record<string, unknown>): Promise<CommandResult>;
|
|
63
|
+
}, flow: FlowFile, timeoutMs?: number, clock?: ArrivalClock,
|
|
64
|
+
/** Whether the tab is still loading. Replay passes one for a pool lease, the only tab it can ask. */
|
|
65
|
+
stillLoading?: () => Promise<boolean>, loadingCapMs?: number): Promise<StartPathArrival>;
|
|
66
|
+
/**
|
|
67
|
+
* Send a tab somewhere and wait for the session that comes back.
|
|
68
|
+
*
|
|
69
|
+
* A navigation is a full page load: the session that issued it DIES and a successor connects with a
|
|
70
|
+
* new id. Every caller therefore has to wait for that successor rather than reuse the handle it
|
|
71
|
+
* already holds, and getting this wrong does not error — it leaves the caller talking to a session
|
|
72
|
+
* that will never answer again.
|
|
73
|
+
*
|
|
74
|
+
* Extracted so there is ONE of these rather than one per caller. `arriveAtStartPath` decides WHETHER
|
|
75
|
+
* to move and this decides how, which is also why the deliberate short-circuits live up there and
|
|
76
|
+
* not in here: a caller that has already decided it must move should not have to argue with them.
|
|
77
|
+
*/
|
|
78
|
+
/**
|
|
79
|
+
* How a navigate ended: target, redirect, refusal (untouched tab), or no successor. `wait` is set
|
|
80
|
+
* when the page's loading earned it time past the budget.
|
|
81
|
+
*/
|
|
82
|
+
export type NavigateOutcome = {
|
|
83
|
+
kind: 'arrived';
|
|
84
|
+
session: Session;
|
|
85
|
+
wait?: StartPageWait;
|
|
86
|
+
} | {
|
|
87
|
+
kind: 'redirected';
|
|
88
|
+
session: Session;
|
|
89
|
+
wait?: StartPageWait;
|
|
90
|
+
} | {
|
|
91
|
+
kind: 'refused';
|
|
92
|
+
} | {
|
|
93
|
+
kind: 'lost';
|
|
94
|
+
waitedMs: number;
|
|
95
|
+
stillLoading: boolean;
|
|
96
|
+
wait?: StartPageWait;
|
|
97
|
+
};
|
|
98
|
+
export declare function navigateAndAwait(sessions: SessionManager, session: {
|
|
99
|
+
id: string;
|
|
100
|
+
/** Optional because a session's URL is, and `carryReticleIdentity` already handles its absence. */
|
|
101
|
+
url?: string;
|
|
102
|
+
command(name: string, args?: Record<string, unknown>): Promise<CommandResult>;
|
|
103
|
+
}, destination: string, expectedPath: string, timeoutMs: number, clock?: ArrivalClock,
|
|
104
|
+
/** True when the destination is the page we are already on — see `arrivedSuccessor`. */
|
|
105
|
+
isReload?: boolean,
|
|
106
|
+
/** Whether the navigated page is still loading; absent when it cannot be asked. */
|
|
107
|
+
stillLoading?: () => Promise<boolean>, loadingCapMs?: number): Promise<NavigateOutcome>;
|
|
108
|
+
export {};
|