@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
|
@@ -1,18 +1,22 @@
|
|
|
1
1
|
import { asFlowName, asProjectId, } from '@reticlehq/core';
|
|
2
|
-
import { REDACTED_FILL, SECRET_NAME_ARG, secretEnvKey } from './fields/flow-secret-field.js';
|
|
2
|
+
import { REDACTED_FILL, SECRET_FIELD_ARG, SECRET_NAME_ARG, secretEnvKey, withDistinctSecretKeys, } from './fields/flow-secret-field.js';
|
|
3
3
|
export { REDACTED_FILL, secretEnvKey } from './fields/flow-secret-field.js';
|
|
4
4
|
import { safeProjectId } from './flow-result.js';
|
|
5
5
|
import { changeInPlace } from './narrow-write.js';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
6
|
+
import { dirname } from 'node:path';
|
|
7
|
+
import { gitTracks } from '../../machine/git-tracks.js';
|
|
8
|
+
import { AnchorKind, DEGRADED_ANCHOR_ROLE, DOCUMENT_ANCHOR_ROLE, FLOW_FILE_VERSION, flowFileVersionFor, FlowErrorCode, FlowFileSchema, FlowStepTool, QueryBy, defaultIsSensitiveKey, isGlobalPressCall, } from '@reticlehq/core';
|
|
9
|
+
import { ReticleTool, flowJsonReplacer, mainCheckoutTwin } from '@reticlehq/core';
|
|
8
10
|
import { asRecord, asString } from '@reticlehq/core';
|
|
9
11
|
import { applyHealChanges } from './heal.js';
|
|
10
12
|
import { withLearnedSources } from './learned-sources.js';
|
|
11
13
|
import { flowIntentGap, linkFlowIntent } from './flow-intent.js';
|
|
12
14
|
import { journeyFingerprint, journeyName, mergeJourney, routeClaims, withinJourney, } from './flow-journey.js';
|
|
13
15
|
import { IntentStore } from '../../memory/intent/intent-store.js';
|
|
16
|
+
import { readTextOrUndefined } from '../../memory/project/fs/fs-port.js';
|
|
14
17
|
import { flowDir, flowParentDir, flowPath, reticleDirPaths, isValidFlowName, } from '../../memory/project/dir/reticle-dir.js';
|
|
15
18
|
import { describeFlowZodFailure, parseFlowFileText } from './flow-expect-grammar.js';
|
|
19
|
+
import { readyForReplay, replayability, Replayable, } from './flow-replayable.js';
|
|
16
20
|
/**
|
|
17
21
|
* The anchor for a DEGRADED step (no resolvable testid). A volatile eXX ref is NEVER persisted —
|
|
18
22
|
* the on-disk flow carries a placeholder ROLE anchor + degraded:true instead, so a ref can never
|
|
@@ -64,6 +68,9 @@ export function anchorForStep(args) {
|
|
|
64
68
|
const source = sourceArg(args);
|
|
65
69
|
if (source !== undefined)
|
|
66
70
|
anchor.source = source;
|
|
71
|
+
const of = args['of'];
|
|
72
|
+
if ('number' === typeof of && 1 < of)
|
|
73
|
+
anchor.of = of;
|
|
67
74
|
return { anchor, degraded: false };
|
|
68
75
|
}
|
|
69
76
|
// Role + NAME is a real anchor, not a degraded placeholder.
|
|
@@ -73,6 +80,14 @@ export function anchorForStep(args) {
|
|
|
73
80
|
// that means "add a data-testid". So a step the recorder anchored by accessible name arrived here
|
|
74
81
|
// and had that name thrown away, which is precisely the anchor that distinguishes one row's
|
|
75
82
|
// control from another's when a shared JSX source location cannot.
|
|
83
|
+
// A document-key press compiled with no element (#1559): a real anchor, not a degraded one. It is
|
|
84
|
+
// nameless on purpose, because it names no element; the press is what replay dispatches.
|
|
85
|
+
if (by === QueryBy.ROLE &&
|
|
86
|
+
value === DOCUMENT_ANCHOR_ROLE &&
|
|
87
|
+
args['name'] === undefined &&
|
|
88
|
+
isGlobalPressCall({ action: args['action'], args: args['args'] })) {
|
|
89
|
+
return { anchor: { kind: AnchorKind.ROLE, role: DOCUMENT_ANCHOR_ROLE }, degraded: false };
|
|
90
|
+
}
|
|
76
91
|
if (by === QueryBy.ROLE && value !== undefined) {
|
|
77
92
|
const name = asString(args['name']);
|
|
78
93
|
if (name !== undefined && name.length > 0) {
|
|
@@ -96,7 +111,8 @@ function subStepToFlowStep(raw) {
|
|
|
96
111
|
const action = asString(sub['action']);
|
|
97
112
|
const args = asRecord(sub['args']);
|
|
98
113
|
const { anchor, degraded } = anchorForStep(sub);
|
|
99
|
-
const step = buildStep(ReticleTool.ACT, anchor, action, args, degraded);
|
|
114
|
+
const step = buildStep(ReticleTool.ACT, anchor, action, args, degraded, markedSecret(sub));
|
|
115
|
+
keepRoleSource(step, sub);
|
|
100
116
|
/*
|
|
101
117
|
* The sub-step's own declared consequence, carried rather than folded into the parent.
|
|
102
118
|
*
|
|
@@ -124,15 +140,23 @@ function subStepToFlowStep(raw) {
|
|
|
124
140
|
* `defaultIsSensitiveKey` is the same rule the network channel redacts by, so a field considered
|
|
125
141
|
* sensitive on the wire cannot be considered safe on disk.
|
|
126
142
|
*/
|
|
127
|
-
function redactSecretFill(anchor, args
|
|
143
|
+
function redactSecretFill(anchor, args,
|
|
144
|
+
/** The SDK said the target holds a secret: redact whatever the field is called. */
|
|
145
|
+
secret = false) {
|
|
128
146
|
if (typeof args['value'] !== 'string')
|
|
129
147
|
return args;
|
|
130
148
|
const field = anchorFieldName(anchor);
|
|
131
|
-
|
|
149
|
+
const sensitive = secret || (field !== undefined && defaultIsSensitiveKey(field));
|
|
150
|
+
if (!sensitive)
|
|
132
151
|
return args;
|
|
152
|
+
// ponytail: a secret field with no name (a component anchor) gets no variable; replay then refuses it.
|
|
153
|
+
if (field === undefined)
|
|
154
|
+
return { ...args, value: REDACTED_FILL };
|
|
133
155
|
// The variable that supplies it, beside the placeholder: the file alone says what to set.
|
|
134
156
|
return { ...args, value: REDACTED_FILL, [SECRET_NAME_ARG]: secretEnvKey(field) };
|
|
135
157
|
}
|
|
158
|
+
/** Whether a recorded step's args carry the SDK's secret mark. */
|
|
159
|
+
const markedSecret = (args) => true === args[SECRET_FIELD_ARG];
|
|
136
160
|
/**
|
|
137
161
|
* The recorded steps as they may be SHOWN: every credential fill carries the placeholder.
|
|
138
162
|
*
|
|
@@ -154,7 +178,7 @@ function redactNormalizedArgs(normalized) {
|
|
|
154
178
|
const inner = normalized['args'];
|
|
155
179
|
if ('object' !== typeof inner || null === inner)
|
|
156
180
|
return normalized;
|
|
157
|
-
const redacted = redactSecretFill(anchorForStep(normalized).anchor, asRecord(inner));
|
|
181
|
+
const redacted = redactSecretFill(anchorForStep(normalized).anchor, asRecord(inner), markedSecret(normalized));
|
|
158
182
|
return redacted === inner ? normalized : { ...normalized, args: redacted };
|
|
159
183
|
}
|
|
160
184
|
/**
|
|
@@ -179,8 +203,19 @@ export function anchorFieldName(anchor) {
|
|
|
179
203
|
return anchor.name;
|
|
180
204
|
return undefined;
|
|
181
205
|
}
|
|
182
|
-
|
|
183
|
-
|
|
206
|
+
/**
|
|
207
|
+
* A role anchor has no room for a source, so the stamped source goes on the step. Without it the
|
|
208
|
+
* flow named no file: the gate called the driven component unflowed, and `affected` replayed the
|
|
209
|
+
* flow for every change.
|
|
210
|
+
*/
|
|
211
|
+
function keepRoleSource(step, src) {
|
|
212
|
+
const source = sourceArg(src);
|
|
213
|
+
if (AnchorKind.ROLE === step.anchor.kind && source !== undefined) {
|
|
214
|
+
step.source = { file: source.file, line: source.line };
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
function buildStep(tool, anchor, action, args, degraded, secret = false) {
|
|
218
|
+
const step = { tool, anchor, args: redactSecretFill(anchor, args, secret) };
|
|
184
219
|
if (action !== undefined)
|
|
185
220
|
step.action = action;
|
|
186
221
|
if (degraded)
|
|
@@ -200,6 +235,8 @@ export function recordedStepToFlowStep(step) {
|
|
|
200
235
|
out.page = step.page;
|
|
201
236
|
if (step.endPage !== undefined && step.endPage !== step.page)
|
|
202
237
|
out.endPage = step.endPage;
|
|
238
|
+
if (true === step.writes)
|
|
239
|
+
out.writes = true;
|
|
203
240
|
return out;
|
|
204
241
|
}
|
|
205
242
|
function anchoredStep(step) {
|
|
@@ -235,7 +272,8 @@ function anchoredStep(step) {
|
|
|
235
272
|
const action = asString(step.args['action']);
|
|
236
273
|
const args = asRecord(step.args['args']);
|
|
237
274
|
const { anchor, degraded } = anchorForStep(step.args);
|
|
238
|
-
const out = buildStep(step.tool, anchor, action, args, degraded);
|
|
275
|
+
const out = buildStep(step.tool, anchor, action, args, degraded, markedSecret(step.args));
|
|
276
|
+
keepRoleSource(out, step.args);
|
|
239
277
|
if (step.expect !== undefined)
|
|
240
278
|
out.expect = step.expect;
|
|
241
279
|
return out;
|
|
@@ -271,11 +309,24 @@ export class FlowStore {
|
|
|
271
309
|
* new run (`RunStore` takes the same callback). Without it a flow saved with no run behind it
|
|
272
310
|
* waited for the timer, and a daemon that exited first never sent it.
|
|
273
311
|
*/
|
|
312
|
+
/**
|
|
313
|
+
* The main checkout's flows, read-only, when this store sits in a linked git worktree and git
|
|
314
|
+
* ignores `.reticle/`. A flow saved there is then still replayed here. Writes never go to it.
|
|
315
|
+
* When git tracks `.reticle/`, the worktree already has every committed flow, and reading the
|
|
316
|
+
* main checkout brought back a flow that the branch deleted.
|
|
317
|
+
*/
|
|
318
|
+
#main;
|
|
274
319
|
constructor(fs, root, clock, opts = {}) {
|
|
275
320
|
this.#fs = fs;
|
|
276
321
|
this.#root = root;
|
|
277
322
|
this.#clock = clock;
|
|
278
323
|
this.#onWrote = opts.onWrote;
|
|
324
|
+
const twin = mainCheckoutTwin(root, readTextOrUndefined);
|
|
325
|
+
// The main checkout has no twin of its own, so this never nests deeper than one level.
|
|
326
|
+
this.#main =
|
|
327
|
+
twin === undefined || gitTracks(reticleDirPaths(root).flows)
|
|
328
|
+
? undefined
|
|
329
|
+
: new FlowStore(fs, twin, clock);
|
|
279
330
|
}
|
|
280
331
|
/**
|
|
281
332
|
* The single byte-stable flow serializer: 2-space indent + one trailing newline. save,
|
|
@@ -306,12 +357,16 @@ export class FlowStore {
|
|
|
306
357
|
*/
|
|
307
358
|
#summary(flow) {
|
|
308
359
|
const gap = flowIntentGap(flow);
|
|
360
|
+
const replay = replayability(flow);
|
|
309
361
|
return {
|
|
310
362
|
name: flow.name,
|
|
311
363
|
stepCount: flow.steps.length,
|
|
312
364
|
degraded: flow.steps.filter((s) => true === s.degraded).length,
|
|
313
365
|
empty: 0 === flow.steps.length,
|
|
314
366
|
...(gap === undefined ? {} : { intentGap: gap }),
|
|
367
|
+
...(Replayable.YES === replay.status && replay.writes === undefined
|
|
368
|
+
? {}
|
|
369
|
+
: { replayability: replay }),
|
|
315
370
|
};
|
|
316
371
|
}
|
|
317
372
|
/** The on-disk flow a compiled recording becomes, before anything is written. */
|
|
@@ -336,13 +391,17 @@ export class FlowStore {
|
|
|
336
391
|
};
|
|
337
392
|
const intent = program.steps.find((step) => step.intent !== undefined)?.intent;
|
|
338
393
|
const annotated = withAnnotations(base, annotations);
|
|
339
|
-
return {
|
|
394
|
+
return readyForReplay(withDistinctSecretKeys({
|
|
340
395
|
...annotated,
|
|
341
396
|
// The action's own intent, when nobody annotated the flow — see RecordedStep.intent.
|
|
342
397
|
...(annotated.intent === undefined && intent !== undefined ? { intent } : {}),
|
|
398
|
+
// Else the sentence an auto-saved drive built from its expects, marked as built.
|
|
399
|
+
...(annotated.intent === undefined && intent === undefined && program.intent !== undefined
|
|
400
|
+
? { intent: program.intent, ...(program.intentDerived ? { intentDerived: true } : {}) }
|
|
401
|
+
: {}),
|
|
343
402
|
...routeClaims(annotated.startPath, annotated.steps),
|
|
344
403
|
...(program.author === undefined ? {} : { author: program.author }),
|
|
345
|
-
};
|
|
404
|
+
}));
|
|
346
405
|
}
|
|
347
406
|
/**
|
|
348
407
|
* Convert a CompiledProgram (testid-normalized) into an anchored, on-disk flow + write it.
|
|
@@ -458,7 +517,7 @@ export class FlowStore {
|
|
|
458
517
|
detail: describeFlowZodFailure(parsed.error),
|
|
459
518
|
};
|
|
460
519
|
}
|
|
461
|
-
const valid = await this.#linkIntent(parsed.data);
|
|
520
|
+
const valid = await this.#linkIntent(readyForReplay(parsed.data));
|
|
462
521
|
await this.#fs.mkdir(flowParentDir(this.#root, asFlowName(valid.name), pid));
|
|
463
522
|
await this.#fs.writeFile(flowPath(this.#root, asFlowName(valid.name), pid), this.#serialize(valid));
|
|
464
523
|
this.#onWrote?.();
|
|
@@ -477,8 +536,12 @@ export class FlowStore {
|
|
|
477
536
|
load: (n, p) => this.load(n, p),
|
|
478
537
|
// Branded at the boundary: the port speaks strings, the store speaks FlowName, and the
|
|
479
538
|
// name has already passed isValidFlowName inside changeInPlace.
|
|
480
|
-
|
|
481
|
-
|
|
539
|
+
// A flow read from the main checkout is changed in a copy in this worktree.
|
|
540
|
+
resolvePath: async (n, p) => (await this.#resolveReadPath(asFlowName(n), p)) ?? flowPath(this.#root, asFlowName(n), p),
|
|
541
|
+
write: async (path, contents) => {
|
|
542
|
+
await this.#fs.mkdir(dirname(path));
|
|
543
|
+
await this.#fs.writeFile(path, contents);
|
|
544
|
+
},
|
|
482
545
|
serialize: (flow) => this.#serialize(flow),
|
|
483
546
|
readRaw: (path) => this.#fs.readFile(path),
|
|
484
547
|
}, name, projectId, change);
|
|
@@ -539,6 +602,12 @@ export class FlowStore {
|
|
|
539
602
|
* name must validate first; `flowPath` takes a branded FlowName precisely so the compiler insists.
|
|
540
603
|
*/
|
|
541
604
|
async list(projectId) {
|
|
605
|
+
const own = await this.#listOwn(projectId);
|
|
606
|
+
if (this.#main === undefined)
|
|
607
|
+
return own;
|
|
608
|
+
return [...new Set([...own, ...(await this.#main.list(projectId))])].sort();
|
|
609
|
+
}
|
|
610
|
+
async #listOwn(projectId) {
|
|
542
611
|
const flowsDir = reticleDirPaths(this.#root).flows;
|
|
543
612
|
const pid = safeProjectId(projectId);
|
|
544
613
|
const legacy = await this.#namesIn(flowsDir);
|
|
@@ -604,6 +673,12 @@ export class FlowStore {
|
|
|
604
673
|
* back to a legacy flat (untagged) flow of the same name — so pre-existing flows keep loading.
|
|
605
674
|
*/
|
|
606
675
|
async load(name, projectId) {
|
|
676
|
+
const own = await this.#loadOwn(name, projectId);
|
|
677
|
+
if (own.ok || own.code !== FlowErrorCode.NOT_FOUND || this.#main === undefined)
|
|
678
|
+
return own;
|
|
679
|
+
return this.#main.load(name, projectId);
|
|
680
|
+
}
|
|
681
|
+
async #loadOwn(name, projectId) {
|
|
607
682
|
if (!isValidFlowName(name))
|
|
608
683
|
return { ok: false, code: FlowErrorCode.INVALID_NAME };
|
|
609
684
|
const path = await this.#resolveReadPath(name, safeProjectId(projectId));
|
|
@@ -6,12 +6,18 @@
|
|
|
6
6
|
* fires (heal the locator, never the intent).
|
|
7
7
|
*/
|
|
8
8
|
import { type FlowHealResult } from '@reticlehq/core';
|
|
9
|
+
import { DriftReason } from '@reticlehq/core';
|
|
9
10
|
import type { ToolDeps } from '../../surface/tools/tool-kit.js';
|
|
10
11
|
/**
|
|
11
|
-
* Why heal produced no proposal
|
|
12
|
+
* Why heal produced no proposal. Three cases.
|
|
12
13
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
14
|
+
* A testid anchor drifted, but no candidate cleared the confidence floor: UNHEALABLE.
|
|
15
|
+
* Every drift is a consequence (the anchors resolved, the assertion failed): NOT_A_REBIND.
|
|
16
|
+
* Any other drift means an anchor did not resolve, so the step did not run: ANCHOR_UNRESOLVED.
|
|
17
|
+
* That message names the nearest candidate when there is one.
|
|
18
|
+
*
|
|
19
|
+
* Exported for its own test. A reader acts on this sentence, and the wrong one sends them to
|
|
20
|
+
* lower a threshold that had no part in the refusal.
|
|
15
21
|
*/
|
|
16
|
-
export declare function unhealableMessage(reasons: readonly
|
|
22
|
+
export declare function unhealableMessage(reasons: readonly DriftReason[], nearest?: string | null): string;
|
|
17
23
|
export declare function healFlow(deps: ToolDeps, args: Record<string, unknown>): Promise<FlowHealResult>;
|
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* fires (heal the locator, never the intent).
|
|
7
7
|
*/
|
|
8
8
|
import { FLOW_SIGNAL_TIMEOUT_MS, HEAL_CONFIDENCE_MIN, HealStatus, ReplayStatus, } from '@reticlehq/core';
|
|
9
|
-
import { asString, DriftReason } from '@reticlehq/core';
|
|
9
|
+
import { asString, DriftReason, isConsequenceDrift } from '@reticlehq/core';
|
|
10
10
|
import { waitForPredicate } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
11
11
|
import { replayFlow } from './flow-replay.js';
|
|
12
12
|
import { applyHealChanges, collectProposals } from './heal.js';
|
|
@@ -30,24 +30,39 @@ const HEAL_MESSAGES = {
|
|
|
30
30
|
* questions.
|
|
31
31
|
*/
|
|
32
32
|
NOT_A_REBIND: 'drift found, but none of it is a renamed locator, so there is nothing to rebind — the anchors resolved and what failed was what the steps assert afterwards. The confidence floor was never consulted. Fix the app so the consequence fires again, or update the step expectations by hand',
|
|
33
|
+
ANCHOR_UNRESOLVED: 'drift found, but a step anchor did not resolve on the page, so the step did not run. Heal does not rebind this kind of anchor, and the confidence floor was not used. Update the step anchor by hand',
|
|
34
|
+
ANCHOR_NEAREST_PREFIX: 'The nearest candidate on the page is',
|
|
33
35
|
HEALED_UNVERIFIED: "rewrote drifted testid anchors. This flow declares its consequences per STEP rather than as a flow `success`, so the rebind was not re-verified end to end — the steps will assert on the next replay, but nothing proved the healed flow still reaches its outcome. Set the flow's `success` (reticle_annotate) to have future heals re-verified before they are written.",
|
|
34
36
|
CONSEQUENCE_BROKEN: 'rebind resolves the drifted locator to a surviving element, but the healed flow no longer satisfies its success consequence — refusing to write (a heal that loses the intent would ship a green-but-dead test). Fix by hand and verify',
|
|
35
37
|
};
|
|
36
38
|
/**
|
|
37
|
-
* Why heal produced no proposal
|
|
39
|
+
* Why heal produced no proposal. Three cases.
|
|
38
40
|
*
|
|
39
|
-
*
|
|
40
|
-
*
|
|
41
|
+
* A testid anchor drifted, but no candidate cleared the confidence floor: UNHEALABLE.
|
|
42
|
+
* Every drift is a consequence (the anchors resolved, the assertion failed): NOT_A_REBIND.
|
|
43
|
+
* Any other drift means an anchor did not resolve, so the step did not run: ANCHOR_UNRESOLVED.
|
|
44
|
+
* That message names the nearest candidate when there is one.
|
|
45
|
+
*
|
|
46
|
+
* Exported for its own test. A reader acts on this sentence, and the wrong one sends them to
|
|
47
|
+
* lower a threshold that had no part in the refusal.
|
|
41
48
|
*/
|
|
42
|
-
export function unhealableMessage(reasons) {
|
|
43
|
-
|
|
44
|
-
|
|
49
|
+
export function unhealableMessage(reasons, nearest = null) {
|
|
50
|
+
if (reasons.some((reason) => DriftReason.TESTID_NOT_FOUND === reason)) {
|
|
51
|
+
return HEAL_MESSAGES.UNHEALABLE;
|
|
52
|
+
}
|
|
53
|
+
if (reasons.every((reason) => isConsequenceDrift(reason))) {
|
|
54
|
+
return HEAL_MESSAGES.NOT_A_REBIND;
|
|
55
|
+
}
|
|
56
|
+
return null === nearest
|
|
57
|
+
? HEAL_MESSAGES.ANCHOR_UNRESOLVED
|
|
58
|
+
: `${HEAL_MESSAGES.ANCHOR_UNRESOLVED}. ${HEAL_MESSAGES.ANCHOR_NEAREST_PREFIX} "${nearest}".`;
|
|
45
59
|
}
|
|
46
60
|
function toChange(proposal) {
|
|
47
61
|
return { step: proposal.step, from: proposal.from, to: proposal.to };
|
|
48
62
|
}
|
|
49
63
|
export async function healFlow(deps, args) {
|
|
50
|
-
|
|
64
|
+
// `flow` is the alias the tool's schema offers; ignoring it healed a flow named "".
|
|
65
|
+
const name = asString(args['flowName']) ?? asString(args['flow']) ?? '';
|
|
51
66
|
const apply = true === args['apply'];
|
|
52
67
|
const target = sessionTarget(deps, asString(args['sessionId']));
|
|
53
68
|
const { projectId } = target;
|
|
@@ -91,13 +106,15 @@ export async function healFlow(deps, args) {
|
|
|
91
106
|
}
|
|
92
107
|
const proposals = collectProposals(steps);
|
|
93
108
|
if (0 === proposals.length) {
|
|
109
|
+
const drifts = steps.flatMap((step) => (step.drift === undefined ? [] : [step.drift]));
|
|
94
110
|
return {
|
|
95
111
|
name,
|
|
96
112
|
status: HealStatus.UNHEALABLE,
|
|
97
113
|
applied: false,
|
|
98
114
|
proposals: [],
|
|
99
115
|
changed: [],
|
|
100
|
-
message: unhealableMessage(
|
|
116
|
+
message: unhealableMessage(drifts.map((drift) => drift.reasonKind), drifts.find((drift) => !isConsequenceDrift(drift.reasonKind) && null !== drift.nearest)
|
|
117
|
+
?.nearest ?? null),
|
|
101
118
|
};
|
|
102
119
|
}
|
|
103
120
|
if (!apply) {
|
|
@@ -8,13 +8,7 @@ import { z } from 'zod';
|
|
|
8
8
|
declare const FlakeRecordSchema: z.ZodObject<{
|
|
9
9
|
runs: z.ZodNumber;
|
|
10
10
|
fails: z.ZodNumber;
|
|
11
|
-
},
|
|
12
|
-
runs: number;
|
|
13
|
-
fails: number;
|
|
14
|
-
}, {
|
|
15
|
-
runs: number;
|
|
16
|
-
fails: number;
|
|
17
|
-
}>;
|
|
11
|
+
}, z.core.$strip>;
|
|
18
12
|
type FlakeRecord = z.infer<typeof FlakeRecordSchema>;
|
|
19
13
|
/** Per-flow map (flow name → record). */
|
|
20
14
|
export type FlakeLedger = Record<string, FlakeRecord>;
|
|
@@ -23,26 +17,8 @@ export declare const FlakeFileSchema: z.ZodObject<{
|
|
|
23
17
|
flows: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
24
18
|
runs: z.ZodNumber;
|
|
25
19
|
fails: z.ZodNumber;
|
|
26
|
-
},
|
|
27
|
-
|
|
28
|
-
fails: number;
|
|
29
|
-
}, {
|
|
30
|
-
runs: number;
|
|
31
|
-
fails: number;
|
|
32
|
-
}>>;
|
|
33
|
-
}, "strip", z.ZodTypeAny, {
|
|
34
|
-
flows: Record<string, {
|
|
35
|
-
runs: number;
|
|
36
|
-
fails: number;
|
|
37
|
-
}>;
|
|
38
|
-
version: 1;
|
|
39
|
-
}, {
|
|
40
|
-
flows: Record<string, {
|
|
41
|
-
runs: number;
|
|
42
|
-
fails: number;
|
|
43
|
-
}>;
|
|
44
|
-
version: 1;
|
|
45
|
-
}>;
|
|
20
|
+
}, z.core.$strip>>;
|
|
21
|
+
}, z.core.$strip>;
|
|
46
22
|
export declare function emptyRecord(): FlakeRecord;
|
|
47
23
|
/** Accrue one unchanged-code replay outcome. */
|
|
48
24
|
export declare function recordOutcome(record: FlakeRecord, passed: boolean): FlakeRecord;
|
|
@@ -11,7 +11,7 @@ const FlakeRecordSchema = z.object({
|
|
|
11
11
|
});
|
|
12
12
|
export const FlakeFileSchema = z.object({
|
|
13
13
|
version: z.literal(1),
|
|
14
|
-
flows: z.record(FlakeRecordSchema),
|
|
14
|
+
flows: z.record(z.string(), FlakeRecordSchema),
|
|
15
15
|
});
|
|
16
16
|
/** Minimum unchanged-code replays before flakiness can be judged (too few = noise). */
|
|
17
17
|
const DEFAULT_MIN_FLAKE_RUNS = 5;
|
|
@@ -6,11 +6,8 @@
|
|
|
6
6
|
* exists on search. That shape is visible from the route list with no change to the flow file, so
|
|
7
7
|
* stop/save can warn instead of writing a flow that fails on the next click.
|
|
8
8
|
*/
|
|
9
|
-
import { EventType } from '@reticlehq/core';
|
|
9
|
+
import { EventType, asString } from '@reticlehq/core';
|
|
10
10
|
import { routePathOf } from '@reticlehq/engine/question/predicate/predicate-route.js';
|
|
11
|
-
function asString(value) {
|
|
12
|
-
return 'string' === typeof value ? value : undefined;
|
|
13
|
-
}
|
|
14
11
|
/**
|
|
15
12
|
* The page a recording step sat on, comparable across path routers and hash routers.
|
|
16
13
|
*
|
|
@@ -47,6 +47,8 @@ export interface RecordedStep {
|
|
|
47
47
|
* never saved silently.
|
|
48
48
|
*/
|
|
49
49
|
unkeptExpect?: string;
|
|
50
|
+
/** The step sent a write request (POST, PUT, PATCH, DELETE) while it was recorded. */
|
|
51
|
+
writes?: true;
|
|
50
52
|
}
|
|
51
53
|
interface ActiveRecording {
|
|
52
54
|
cursor: number;
|
|
@@ -92,6 +94,9 @@ export interface CompiledProgram {
|
|
|
92
94
|
routes?: string[];
|
|
93
95
|
/** Who made it — see FlowFile.author. Stamped by the caller that knows. */
|
|
94
96
|
author?: FlowFile['author'];
|
|
97
|
+
/** A sentence built from the steps' expects (an auto-saved drive): see FlowFile.intentDerived. */
|
|
98
|
+
intent?: string;
|
|
99
|
+
intentDerived?: true;
|
|
95
100
|
}
|
|
96
101
|
/**
|
|
97
102
|
* The `tool` written on an invocation step — core's constant, re-exported for this module's callers.
|
|
@@ -153,7 +158,12 @@ export declare class RecordingStore {
|
|
|
153
158
|
* they are, so the journey it belongs to is not auto-saved as a flow (#1459).
|
|
154
159
|
*/
|
|
155
160
|
markMocked(session: string | undefined, active: boolean): void;
|
|
156
|
-
|
|
161
|
+
/**
|
|
162
|
+
* `forAmbient` is the step as the ambient tape keeps it, when that differs: a journey's refuted
|
|
163
|
+
* claims come off the ambient tape (see `unassertLast`), and a recording somebody opened keeps
|
|
164
|
+
* every claim they declared, held or not.
|
|
165
|
+
*/
|
|
166
|
+
capture(step: RecordedStep, route?: string, session?: string, forAmbient?: RecordedStep): void;
|
|
157
167
|
/**
|
|
158
168
|
* Add a consequence to the last captured step of every active recording.
|
|
159
169
|
*
|
|
@@ -101,7 +101,12 @@ export class RecordingStore {
|
|
|
101
101
|
else
|
|
102
102
|
this.#mocked.delete(session ?? '');
|
|
103
103
|
}
|
|
104
|
-
|
|
104
|
+
/**
|
|
105
|
+
* `forAmbient` is the step as the ambient tape keeps it, when that differs: a journey's refuted
|
|
106
|
+
* claims come off the ambient tape (see `unassertLast`), and a recording somebody opened keeps
|
|
107
|
+
* every claim they declared, held or not.
|
|
108
|
+
*/
|
|
109
|
+
capture(step, route, session, forAmbient) {
|
|
105
110
|
this.#navigatedSinceStep = false;
|
|
106
111
|
const mocked = this.#mocked.has(session ?? '');
|
|
107
112
|
const ambient = ambientRecordingOf(session);
|
|
@@ -138,13 +143,14 @@ export class RecordingStore {
|
|
|
138
143
|
// The route rides on the AMBIENT tape only: a recording somebody opened deliberately is
|
|
139
144
|
// already one journey by construction, and stamping a route on its steps would change what a
|
|
140
145
|
// deliberate recording contains.
|
|
146
|
+
const taped = isAmbient(name) ? (forAmbient ?? step) : step;
|
|
141
147
|
rec.steps.push(isAmbient(name) && (route !== undefined || mocked)
|
|
142
148
|
? {
|
|
143
|
-
...
|
|
149
|
+
...taped,
|
|
144
150
|
...(route === undefined ? {} : { route }),
|
|
145
151
|
...(mocked ? { mocked: true } : {}),
|
|
146
152
|
}
|
|
147
|
-
:
|
|
153
|
+
: taped);
|
|
148
154
|
}
|
|
149
155
|
}
|
|
150
156
|
/**
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { type Predicate } from '@reticlehq/core';
|
|
1
|
+
import { pathOf, type Predicate, type ReticleEvent } from '@reticlehq/core';
|
|
2
2
|
import { type CommandResult } from '@reticlehq/core';
|
|
3
3
|
import type { RecordedStep, CompiledProgram } from './recording/tape/recordings.js';
|
|
4
4
|
import type { Session } from '../../portal/session/session.js';
|
|
@@ -34,7 +34,16 @@ export declare function replayActionArgs(value: unknown, confirmDangerous?: bool
|
|
|
34
34
|
* Pathname rather than the whole url, because that is what `startPath` is compared against and what
|
|
35
35
|
* a hash-routed app makes meaningless in the document location — see routeOfEvent.
|
|
36
36
|
*/
|
|
37
|
-
export
|
|
37
|
+
export { pathOf };
|
|
38
|
+
/**
|
|
39
|
+
* Did the app send a write request in this window? A step that did is saved `writes: true`, so a
|
|
40
|
+
* replay does not repeat it unasked. The dev server's own traffic is not the app's.
|
|
41
|
+
*/
|
|
42
|
+
export declare function wroteIn(events: readonly ReticleEvent[]): boolean;
|
|
43
|
+
/** `wroteIn` over a session's window, best-effort: the record must never fail the drive it records. */
|
|
44
|
+
export declare function wroteSince(session: {
|
|
45
|
+
eventsSince(since: number): readonly ReticleEvent[];
|
|
46
|
+
}, since: number): boolean;
|
|
38
47
|
/** What a saved flow could not keep, and the fix. See RecordedStep.unkeptExpect. */
|
|
39
48
|
export declare const UNKEPT_EXPECT: string;
|
|
40
49
|
/**
|
|
@@ -51,14 +60,18 @@ export declare function captureAct(recordings: {
|
|
|
51
60
|
/** Where this step ran, so the ambient tape can be cut into journeys. See RecordedStep.route. */
|
|
52
61
|
route?: string,
|
|
53
62
|
/** The session that acted: only recordings it started take the step. */
|
|
54
|
-
session?: string
|
|
63
|
+
session?: string,
|
|
64
|
+
/** The act's window sent a write request; see `wroteIn`. */
|
|
65
|
+
wrote?: boolean): void;
|
|
55
66
|
/**
|
|
56
67
|
* Capture an act_and_wait once its verdict is known, keeping `until` as the step's expectation only
|
|
57
68
|
* on a yes. Recorded before the verdict, a step kept an `until` that came back `no` or `no-fault` —
|
|
58
69
|
* a regression test asserting something never once observed to hold because of the action. The
|
|
59
70
|
* action itself is always recorded: it happened, and replay needs it to reach the next step.
|
|
60
71
|
*/
|
|
61
|
-
export declare function captureVerdictedAct(recordings: Parameters<typeof captureAct>[0], args: Record<string, unknown>, res: unknown, route: string | undefined, verified: string | undefined, session?: string
|
|
72
|
+
export declare function captureVerdictedAct(recordings: Parameters<typeof captureAct>[0], args: Record<string, unknown>, res: unknown, route: string | undefined, verified: string | undefined, session?: string,
|
|
73
|
+
/** The act's window sent a write request; see `wroteIn`. */
|
|
74
|
+
wrote?: boolean): void;
|
|
62
75
|
/** Fold a PASSING standalone assertion into the step it proved. See RecordingStore.attachExpect. */
|
|
63
76
|
export declare function captureAssertion(recordings: {
|
|
64
77
|
attachExpect: (expect: Predicate, session?: string) => void;
|
|
@@ -76,6 +89,14 @@ export declare function compileActStep(args: Record<string, unknown>, res: unkno
|
|
|
76
89
|
* every sequence unreplayable on an app without testids.
|
|
77
90
|
*/
|
|
78
91
|
export declare function compileSequenceStep(args: Record<string, unknown>, res: unknown): RecordedStep;
|
|
92
|
+
/**
|
|
93
|
+
* A compiled step that presses a document key at no element (#1559).
|
|
94
|
+
*
|
|
95
|
+
* Both halves are required. The anchor alone is not enough, because a hand-edited `role: document`
|
|
96
|
+
* on a click would then dispatch that click at nothing; and the press alone is not enough, because a
|
|
97
|
+
* recorded Escape aimed at a named element keeps that element.
|
|
98
|
+
*/
|
|
99
|
+
export declare function isDocumentPress(step: Record<string, unknown>): boolean;
|
|
79
100
|
interface ReplayStepResult {
|
|
80
101
|
tool: string;
|
|
81
102
|
ok: boolean;
|
|
@@ -103,4 +124,3 @@ via?: readonly {
|
|
|
103
124
|
flow: string;
|
|
104
125
|
step: number;
|
|
105
126
|
}[]): Promise<ReplayStepResult[]>;
|
|
106
|
-
export {};
|