@reticlehq/server 3.5.0 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/SKILL.md +123 -116
- package/dist/chromium-launch-options.d.ts +3 -1
- package/dist/chromium-launch-options.js +2 -1
- package/dist/command/cli/adhoc-suite.d.ts +14 -0
- package/dist/command/cli/adhoc-suite.js +42 -7
- package/dist/command/cli/adhoc-verdict.d.ts +19 -2
- package/dist/command/cli/adhoc-verdict.js +76 -9
- package/dist/command/cli/answers/gate-exit.d.ts +23 -0
- package/dist/command/cli/answers/gate-exit.js +45 -0
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +3 -1
- package/dist/command/cli/answers/open-note.d.ts +2 -0
- package/dist/command/cli/answers/open-note.js +22 -0
- package/dist/command/cli/auth/device-flow.d.ts +13 -2
- package/dist/command/cli/auth/device-flow.js +17 -0
- package/dist/command/cli/cli-doctor.js +14 -0
- package/dist/command/cli/cli-flow-commands.d.ts +0 -11
- package/dist/command/cli/cli-flow-commands.js +31 -112
- package/dist/command/cli/cli-kill.js +3 -2
- package/dist/command/cli/cli-parse-grammar.d.ts +24 -0
- package/dist/command/cli/cli-parse-grammar.js +75 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -0
- package/dist/command/cli/cli-parse-verify.js +18 -0
- package/dist/command/cli/cli-parse.d.ts +19 -28
- package/dist/command/cli/cli-parse.js +82 -182
- package/dist/command/cli/cli-update-commands.d.ts +1 -1
- package/dist/command/cli/cli-update-commands.js +61 -9
- package/dist/command/cli/cli-usage.d.ts +33 -0
- package/dist/command/cli/cli-usage.js +287 -0
- package/dist/command/cli/cli-verify.d.ts +35 -5
- package/dist/command/cli/cli-verify.js +114 -35
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +192 -341
- package/dist/command/cli/cloud-kit.d.ts +12 -0
- package/dist/command/cli/cloud-kit.js +41 -2
- package/dist/command/cli/cloud-link.d.ts +57 -0
- package/dist/command/cli/cloud-link.js +308 -0
- package/dist/command/cli/cloud-login.d.ts +22 -0
- package/dist/command/cli/cloud-login.js +96 -8
- package/dist/command/cli/context-command.d.ts +1 -0
- package/dist/command/cli/context-command.js +33 -0
- package/dist/command/cli/daemon-start-options.d.ts +3 -0
- package/dist/command/cli/daemon-start-options.js +24 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +46 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +99 -1
- package/dist/command/cli/doctor/doctor-coverage-line.d.ts +2 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +47 -0
- package/dist/command/cli/doctor/doctor-project-line.d.ts +0 -12
- package/dist/command/cli/doctor/doctor-project-line.js +5 -4
- package/dist/command/cli/doctor/doctor-rows.d.ts +6 -0
- package/dist/command/cli/doctor/doctor-rows.js +6 -0
- package/dist/command/cli/doctor/doctor-signing-line.d.ts +38 -0
- package/dist/command/cli/doctor/doctor-signing-line.js +114 -0
- package/dist/command/cli/drive/drive-attach.d.ts +27 -2
- package/dist/command/cli/drive/drive-attach.js +71 -4
- package/dist/command/cli/drive/drive-command.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +13 -7
- package/dist/command/cli/known-regression.d.ts +13 -0
- package/dist/command/cli/known-regression.js +34 -0
- package/dist/command/cli/launch/sdk-version-match.d.ts +12 -0
- package/dist/command/cli/launch/sdk-version-match.js +25 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +15 -3
- package/dist/command/cli/mcp-command.d.ts +6 -0
- package/dist/command/cli/mcp-command.js +13 -5
- package/dist/command/cli/ports/port-holder.d.ts +10 -0
- package/dist/command/cli/ports/port-holder.js +25 -1
- package/dist/command/cli/project-name.d.ts +29 -1
- package/dist/command/cli/project-name.js +107 -2
- package/dist/command/cli/setup-mcp-cli.d.ts +17 -1
- package/dist/command/cli/setup-mcp-cli.js +35 -12
- package/dist/command/cli/status/status-lines.d.ts +1 -0
- package/dist/command/cli/status/status-lines.js +47 -2
- package/dist/command/cli/status/workspace-links.d.ts +10 -0
- package/dist/command/cli/status/workspace-links.js +29 -0
- package/dist/command/cli/try-command.d.ts +96 -0
- package/dist/command/cli/try-command.js +362 -0
- package/dist/command/cli/tutorial.d.ts +0 -100
- package/dist/command/cli/tutorial.js +0 -181
- package/dist/command/cli/verify-results.d.ts +19 -0
- package/dist/command/cli/verify-results.js +29 -0
- package/dist/command/cli-onboarding.d.ts +0 -11
- package/dist/command/cli-onboarding.js +0 -15
- package/dist/command/cli.d.ts +20 -0
- package/dist/command/cli.js +130 -104
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +2 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +1 -0
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +23 -1
- package/dist/command/daemon/daemon-resolve.js +79 -9
- package/dist/command/setup/agent-writer.d.ts +1 -1
- package/dist/command/setup/agent-writer.js +3 -2
- package/dist/command/setup/bringup/bridge-port.d.ts +3 -1
- package/dist/command/setup/bringup/bridge-port.js +13 -3
- package/dist/command/setup/bringup/connect-lease.d.ts +1 -0
- package/dist/command/setup/bringup/connect-lease.js +1 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +2 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +8 -0
- package/dist/command/setup/bringup/dev-server-wait.js +19 -0
- package/dist/command/setup/bringup/ensure-daemon.js +9 -2
- package/dist/command/setup/init/agent-restart.d.ts +23 -0
- package/dist/command/setup/init/agent-restart.js +28 -0
- package/dist/command/setup/init/init-port.d.ts +14 -1
- package/dist/command/setup/init/init-port.js +32 -2
- package/dist/command/setup/init/init-runtime.d.ts +22 -2
- package/dist/command/setup/init/init-runtime.js +114 -38
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +38 -9
- package/dist/command/setup/probe/existing-app.d.ts +12 -0
- package/dist/command/setup/probe/existing-app.js +14 -0
- package/dist/command/setup/remaining-steps.js +2 -1
- package/dist/command/setup/run-setup.d.ts +34 -9
- package/dist/command/setup/run-setup.js +65 -51
- package/dist/command/setup/setup-command.d.ts +25 -1
- package/dist/command/setup/setup-command.js +59 -4
- package/dist/command/setup/setup-mcp.js +25 -2
- package/dist/command/setup/tauri-signing.d.ts +19 -0
- package/dist/command/setup/tauri-signing.js +79 -0
- package/dist/command/setup/terminal/listeners.d.ts +10 -1
- package/dist/command/setup/terminal/listeners.js +37 -6
- package/dist/command/update/update-nudge.d.ts +9 -0
- package/dist/command/update/update-nudge.js +1 -1
- package/dist/command/update/updater.js +11 -15
- package/dist/command/version/version-nudge.js +3 -0
- package/dist/command/version/version-skew.d.ts +20 -1
- package/dist/command/version/version-skew.js +49 -4
- package/dist/features/crawl/crawl-tools.js +4 -0
- package/dist/features/crawl/crawl.d.ts +6 -0
- package/dist/features/crawl/crawl.js +23 -2
- package/dist/features/exhaust/ledger.d.ts +21 -14
- package/dist/features/exhaust/ledger.js +35 -9
- package/dist/features/harness/app-findings.d.ts +2 -0
- package/dist/features/harness/app-findings.js +52 -0
- package/dist/features/harness/drive-report.d.ts +61 -1
- package/dist/features/harness/drive-report.js +394 -26
- package/dist/features/harness/drive-runs.d.ts +120 -0
- package/dist/features/harness/drive-runs.js +289 -0
- package/dist/features/harness/drivers.d.ts +10 -14
- package/dist/features/harness/drivers.js +10 -14
- package/dist/features/harness/explore/console-pages.d.ts +15 -0
- package/dist/features/harness/explore/console-pages.js +146 -0
- package/dist/features/harness/explore/disparity.d.ts +19 -0
- package/dist/features/harness/explore/disparity.js +71 -0
- package/dist/features/harness/explore/fake-app.d.ts +16 -0
- package/dist/features/harness/explore/fake-app.js +49 -0
- package/dist/features/harness/explore/goal-search.d.ts +26 -0
- package/dist/features/harness/explore/goal-search.js +144 -0
- package/dist/features/harness/explore/page-tree.d.ts +49 -0
- package/dist/features/harness/explore/page-tree.js +148 -0
- package/dist/features/harness/explore/site-map.d.ts +34 -0
- package/dist/features/harness/explore/site-map.js +150 -0
- package/dist/features/harness/fill-values.d.ts +3 -73
- package/dist/features/harness/fill-values.js +3 -169
- package/dist/features/harness/goals.d.ts +82 -0
- package/dist/features/harness/goals.js +330 -0
- package/dist/features/harness/harness.d.ts +51 -1
- package/dist/features/harness/harness.js +207 -6
- package/dist/features/harness/platform/drive-target.d.ts +30 -0
- package/dist/features/harness/platform/drive-target.js +81 -0
- package/dist/features/harness/platform/local-apps.d.ts +127 -0
- package/dist/features/harness/platform/local-apps.js +280 -0
- package/dist/features/harness/platform/persona-credentials.d.ts +20 -0
- package/dist/features/harness/platform/persona-credentials.js +69 -0
- package/dist/features/harness/platform/platform-drives.d.ts +61 -0
- package/dist/features/harness/platform/platform-drives.js +114 -0
- package/dist/features/harness/platform/refusal.d.ts +52 -0
- package/dist/features/harness/platform/refusal.js +71 -0
- package/dist/features/harness/platform/remote-drive.d.ts +186 -0
- package/dist/features/harness/platform/remote-drive.js +378 -0
- package/dist/features/harness/platform/script.d.ts +94 -0
- package/dist/features/harness/platform/script.js +260 -0
- package/dist/features/harness/platform/server-driver.d.ts +54 -0
- package/dist/features/harness/platform/server-driver.js +182 -0
- package/dist/features/harness/platform-config.d.ts +41 -1
- package/dist/features/harness/platform-config.js +106 -9
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/app-controls.d.ts +5 -0
- package/dist/features/harness/script/app-controls.js +40 -0
- package/dist/features/harness/script/lane-ids.d.ts +14 -0
- package/dist/features/harness/script/lane-ids.js +16 -0
- package/dist/features/harness/script/script-run.d.ts +70 -0
- package/dist/features/harness/script/script-run.js +606 -0
- package/dist/features/license/license.d.ts +2 -2
- package/dist/features/visual/step-shots.d.ts +31 -0
- package/dist/features/visual/step-shots.js +231 -0
- package/dist/features/visual/visual-tools.d.ts +10 -1
- package/dist/features/visual/visual-tools.js +62 -17
- package/dist/hooks/client-directory.d.ts +18 -0
- package/dist/hooks/client-directory.js +57 -0
- package/dist/hooks/coding-agents.d.ts +34 -0
- package/dist/hooks/coding-agents.js +117 -0
- package/dist/hooks/driven-by.d.ts +23 -0
- package/dist/hooks/driven-by.js +56 -0
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/hooks/hook-commands.js +15 -4
- package/dist/hooks/tool-log.d.ts +9 -0
- package/dist/hooks/tool-log.js +29 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +80 -243
- package/dist/judgement/capsule/capsule-store.d.ts +2 -2
- package/dist/judgement/capsule/causal-summary.d.ts +15 -1
- package/dist/judgement/capsule/causal-summary.js +33 -0
- package/dist/judgement/runs/artifact/build-verification-run.d.ts +1 -1
- package/dist/judgement/runs/artifact/build-verification-run.js +25 -3
- package/dist/judgement/runs/artifact/gap-summary.d.ts +0 -18
- package/dist/judgement/runs/artifact/gap-summary.js +12 -3
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +1 -1
- package/dist/judgement/runs/artifact/replay-mapping.js +37 -11
- package/dist/judgement/runs/artifact/run-store.d.ts +14 -2
- package/dist/judgement/runs/artifact/run-store.js +195 -3
- package/dist/judgement/runs/context-tools.js +59 -1
- package/dist/judgement/runs/default-run-id.d.ts +3 -0
- package/dist/judgement/runs/default-run-id.js +16 -0
- package/dist/judgement/runs/drive-run.d.ts +71 -1
- package/dist/judgement/runs/drive-run.js +317 -5
- package/dist/judgement/runs/repair-prompt.js +1 -1
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +13 -3
- package/dist/judgement/runs/runner-port.d.ts +5 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +5 -2
- package/dist/judgement/runs/verification-sync.js +40 -18
- package/dist/language/flows/change/gate.d.ts +10 -0
- package/dist/language/flows/change/gate.js +22 -0
- package/dist/language/flows/decision.js +36 -1
- package/dist/language/flows/fields/flow-secret-field.d.ts +12 -0
- package/dist/language/flows/fields/flow-secret-field.js +25 -2
- package/dist/language/flows/flow-anchor.d.ts +61 -10
- package/dist/language/flows/flow-anchor.js +98 -6
- package/dist/language/flows/flow-cross-step.d.ts +15 -0
- package/dist/language/flows/flow-cross-step.js +21 -0
- package/dist/language/flows/flow-intent.d.ts +1 -0
- package/dist/language/flows/flow-journey.d.ts +6 -0
- package/dist/language/flows/flow-journey.js +20 -0
- package/dist/language/flows/flow-learning.d.ts +4 -0
- package/dist/language/flows/flow-learning.js +45 -14
- package/dist/language/flows/flow-mutate-tools.js +5 -3
- package/dist/language/flows/flow-replay-run.d.ts +23 -9
- package/dist/language/flows/flow-replay-run.js +115 -110
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +40 -1
- package/dist/language/flows/flow-replay.js +110 -22
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-scope.js +5 -1
- package/dist/language/flows/flow-step-runners.d.ts +22 -2
- package/dist/language/flows/flow-step-runners.js +247 -47
- package/dist/language/flows/flow-store-for-session.d.ts +2 -2
- package/dist/language/flows/flow-store-for-session.js +7 -3
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +112 -89
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +74 -12
- package/dist/language/flows/heal-run.js +6 -4
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/flake.d.ts +2 -2
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +58 -4
- package/dist/language/flows/recording/tape/recordings.js +95 -13
- package/dist/language/flows/replay-from-hud.d.ts +20 -0
- package/dist/language/flows/replay-from-hud.js +51 -0
- package/dist/language/flows/replay.d.ts +9 -5
- package/dist/language/flows/replay.js +56 -15
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/suite/suite-flakes.js +2 -0
- package/dist/language/flows/suite-selection.d.ts +2 -15
- package/dist/language/flows/suite-selection.js +4 -3
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +202 -191
- package/dist/launch-chromium.d.ts +27 -5
- package/dist/launch-chromium.js +38 -8
- package/dist/memory/cloud/cloud-config.d.ts +22 -1
- package/dist/memory/cloud/cloud-config.js +34 -5
- package/dist/memory/cloud/cloud-sync.d.ts +17 -14
- package/dist/memory/cloud/cloud-sync.js +15 -4
- package/dist/memory/cloud/harness-config.d.ts +75 -1
- package/dist/memory/cloud/harness-config.js +115 -24
- package/dist/memory/cloud/hud-notices-source.d.ts +21 -0
- package/dist/memory/cloud/hud-notices-source.js +128 -0
- package/dist/memory/cloud/memory-scope.d.ts +161 -0
- package/dist/memory/cloud/memory-scope.js +227 -0
- package/dist/memory/cloud/sync-cycle.d.ts +44 -7
- package/dist/memory/cloud/sync-cycle.js +129 -15
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +121 -9
- package/dist/memory/cloud/sync-disk.d.ts +1 -1
- package/dist/memory/cloud/sync-disk.js +31 -10
- package/dist/memory/cloud/sync-screenshots.d.ts +32 -0
- package/dist/memory/cloud/sync-screenshots.js +105 -0
- package/dist/memory/cloud/unsynced-roots.d.ts +47 -0
- package/dist/memory/cloud/unsynced-roots.js +166 -0
- package/dist/memory/impact/account-watch.d.ts +34 -0
- package/dist/memory/impact/account-watch.js +59 -0
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +12 -2
- package/dist/memory/impact/impact-store.d.ts +17 -4
- package/dist/memory/impact/impact-store.js +169 -63
- package/dist/memory/intent/inline-intent.d.ts +1 -0
- package/dist/memory/intent/intent-shard-store.js +16 -4
- package/dist/memory/intent/intent-shard.d.ts +14 -2
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +122 -4
- package/dist/memory/intent/open-intents.d.ts +6 -0
- package/dist/memory/intent/open-intents.js +10 -1
- package/dist/memory/intent/settled-words.d.ts +24 -0
- package/dist/memory/intent/settled-words.js +130 -0
- package/dist/memory/journal/drive-flow.d.ts +16 -0
- package/dist/memory/journal/drive-flow.js +34 -2
- package/dist/memory/journal/drive-run-flush.d.ts +2 -0
- package/dist/memory/journal/drive-run-flush.js +20 -5
- package/dist/memory/journal/envelope.d.ts +8 -8
- package/dist/memory/journal/journal-recorder.js +52 -3
- package/dist/memory/journal/on-disk/retention.d.ts +8 -0
- package/dist/memory/journal/on-disk/retention.js +32 -2
- package/dist/memory/journal/on-disk/startup-maintenance.js +3 -1
- package/dist/memory/journal/on-disk/workspace-tiers.js +9 -4
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +42 -9
- package/dist/memory/project/artifact-root-resolver.d.ts +26 -1
- package/dist/memory/project/artifact-root-resolver.js +125 -16
- package/dist/memory/project/artifact-root.d.ts +46 -8
- package/dist/memory/project/artifact-root.js +89 -10
- package/dist/memory/project/dir/reticle-dir.d.ts +18 -2
- package/dist/memory/project/dir/reticle-dir.js +26 -3
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- package/dist/memory/project/project-tools.js +22 -3
- package/dist/memory/project/root-claims.d.ts +6 -0
- package/dist/memory/project/root-claims.js +39 -0
- package/dist/memory/project/session-root.d.ts +26 -1
- package/dist/memory/project/session-root.js +49 -5
- package/dist/memory/project/sync-status.d.ts +85 -0
- package/dist/memory/project/sync-status.js +224 -0
- package/dist/memory/recall/memory-tools.js +47 -2
- package/dist/memory/recall/platform-memory.d.ts +34 -0
- package/dist/memory/recall/platform-memory.js +139 -0
- package/dist/memory/recall/project-memory.d.ts +19 -0
- package/dist/memory/recall/project-memory.js +80 -13
- package/dist/portal/bridge/bridge.d.ts +9 -3
- package/dist/portal/bridge/bridge.js +82 -22
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -0
- package/dist/portal/bridge/pairing-token.d.ts +9 -0
- package/dist/portal/bridge/pairing-token.js +17 -0
- package/dist/portal/bridge/wrong-path.d.ts +17 -0
- package/dist/portal/bridge/wrong-path.js +35 -0
- package/dist/portal/input/network-mock-tools.js +11 -2
- package/dist/portal/input/real-input.d.ts +83 -10
- package/dist/portal/input/real-input.js +218 -30
- package/dist/portal/input/viewport-tools.js +3 -3
- package/dist/portal/pool/browser-pool.d.ts +70 -9
- package/dist/portal/pool/browser-pool.js +190 -37
- package/dist/portal/pool/context-permissions.d.ts +33 -0
- package/dist/portal/pool/context-permissions.js +33 -0
- package/dist/portal/pool/lease-marker-stamp.d.ts +23 -0
- package/dist/portal/pool/lease-marker-stamp.js +49 -0
- package/dist/portal/pool/playwright-launcher.d.ts +35 -0
- package/dist/portal/pool/playwright-launcher.js +64 -3
- package/dist/portal/pool/pool-contract.d.ts +28 -5
- package/dist/portal/session/agent-link.d.ts +8 -0
- package/dist/portal/session/agent-link.js +17 -0
- package/dist/portal/session/command-payload.d.ts +8 -0
- package/dist/portal/session/command-payload.js +24 -0
- package/dist/portal/session/daemon-answers.d.ts +3 -3
- package/dist/portal/session/daemon-answers.js +4 -2
- package/dist/portal/session/dev-server/dev-command.d.ts +21 -0
- package/dist/portal/session/dev-server/dev-command.js +87 -12
- package/dist/portal/session/facts/departure-note.d.ts +22 -0
- package/dist/portal/session/facts/departure-note.js +47 -0
- package/dist/portal/session/facts/observed-state.d.ts +16 -18
- package/dist/portal/session/facts/observed-state.js +46 -3
- package/dist/portal/session/facts/session-replaced.d.ts +5 -0
- package/dist/portal/session/facts/session-replaced.js +5 -0
- package/dist/portal/session/first-run-wiring.d.ts +42 -0
- package/dist/portal/session/first-run-wiring.js +132 -0
- package/dist/portal/session/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/human/notes-ledger.d.ts +20 -0
- package/dist/portal/session/human/notes-ledger.js +55 -0
- package/dist/portal/session/human/review-store.d.ts +12 -0
- package/dist/portal/session/human/review-store.js +18 -10
- package/dist/portal/session/live-control-tools.d.ts +0 -13
- package/dist/portal/session/live-control-tools.js +107 -13
- package/dist/portal/session/narration-args.d.ts +5 -0
- package/dist/portal/session/narration-args.js +17 -0
- package/dist/portal/session/no-session-diagnosis.d.ts +8 -1
- package/dist/portal/session/no-session-diagnosis.js +46 -9
- package/dist/portal/session/no-session-next-action.d.ts +31 -0
- package/dist/portal/session/no-session-next-action.js +159 -60
- package/dist/portal/session/no-session-watch.d.ts +14 -1
- package/dist/portal/session/no-session-watch.js +227 -17
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/presence/session-mirror.js +3 -0
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/serving-directory.d.ts +27 -0
- package/dist/portal/session/serving-directory.js +45 -0
- package/dist/portal/session/session-health.d.ts +18 -0
- package/dist/portal/session/session-health.js +9 -1
- package/dist/portal/session/session-info.d.ts +8 -1
- package/dist/portal/session/session-info.js +8 -1
- package/dist/portal/session/session-manager.d.ts +39 -0
- package/dist/portal/session/session-manager.js +98 -11
- package/dist/portal/session/session-reaper.js +4 -1
- package/dist/portal/session/session-successor.d.ts +13 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session-tools.js +26 -3
- package/dist/portal/session/session.d.ts +22 -30
- package/dist/portal/session/session.js +81 -79
- package/dist/portal/session/timing/command-timeout.js +25 -1
- package/dist/portal/session/timing/wall-clock.d.ts +1 -1
- package/dist/portal/session/timing/wall-clock.js +1 -1
- package/dist/portal/session/zero-install-first-call.d.ts +31 -0
- package/dist/portal/session/zero-install-first-call.js +88 -0
- package/dist/start-options.d.ts +12 -0
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +23 -1
- package/dist/status-payload.js +36 -1
- package/dist/surface/http-server.js +18 -2
- package/dist/surface/mcp/attach-memory.d.ts +1 -0
- package/dist/surface/mcp/attach-memory.js +12 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +9 -0
- package/dist/surface/mcp/mcp-proxy.js +65 -13
- package/dist/surface/mcp/mcp.d.ts +34 -6
- package/dist/surface/mcp/mcp.js +61 -17
- package/dist/surface/mcp/proxy/drive-calls.d.ts +10 -0
- package/dist/surface/mcp/proxy/drive-calls.js +27 -0
- package/dist/surface/mcp/proxy/mcp-post-transport.js +5 -0
- package/dist/surface/mcp/server-instructions.d.ts +4 -2
- package/dist/surface/mcp/server-instructions.js +32 -14
- package/dist/surface/mcp/shared-params.js +2 -2
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +1 -0
- package/dist/surface/tools/account-tool.d.ts +22 -0
- package/dist/surface/tools/account-tool.js +157 -0
- package/dist/surface/tools/act/act-danger.d.ts +11 -0
- package/dist/surface/tools/act/act-danger.js +38 -1
- package/dist/surface/tools/act/act-observation.d.ts +33 -0
- package/dist/surface/tools/act/act-observation.js +57 -0
- package/dist/surface/tools/act/act-preflight.js +25 -2
- package/dist/surface/tools/act/act-target.js +8 -3
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +8 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +56 -2
- package/dist/surface/tools/act/resolve-target.d.ts +1 -1
- package/dist/surface/tools/act/resolve-target.js +18 -3
- package/dist/surface/tools/act/screen-request.d.ts +34 -0
- package/dist/surface/tools/act/screen-request.js +113 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +8 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -2
- package/dist/surface/tools/act/settle-in-flight.js +25 -3
- package/dist/surface/tools/act-sequence-tool.js +138 -29
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +71 -41
- package/dist/surface/tools/agent/app-notes-learning.d.ts +7 -0
- package/dist/surface/tools/agent/app-notes-learning.js +80 -0
- package/dist/surface/tools/agent/app-notes.d.ts +4 -0
- package/dist/surface/tools/agent/app-notes.js +48 -0
- package/dist/surface/tools/agent/build-staleness.d.ts +7 -0
- package/dist/surface/tools/agent/build-staleness.js +62 -0
- package/dist/surface/tools/agent/compact-envelope.d.ts +80 -0
- package/dist/surface/tools/agent/compact-envelope.js +374 -0
- package/dist/surface/tools/agent/for-the-agent.d.ts +12 -0
- package/dist/surface/tools/agent/for-the-agent.js +44 -0
- package/dist/surface/tools/agent/notices.d.ts +50 -0
- package/dist/surface/tools/agent/notices.js +152 -0
- package/dist/surface/tools/agent/reteach.d.ts +11 -0
- package/dist/surface/tools/agent/reteach.js +50 -0
- package/dist/surface/tools/args/alias-args.d.ts +5 -0
- package/dist/surface/tools/args/alias-args.js +10 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.d.ts +6 -0
- package/dist/surface/tools/args/confirm-dangerous-arg.js +6 -0
- package/dist/surface/tools/assert/assert-source.d.ts +15 -0
- package/dist/surface/tools/assert/assert-source.js +40 -0
- package/dist/surface/tools/assert/assert-verdict.d.ts +1 -1
- package/dist/surface/tools/assert/assert-verdict.js +42 -17
- package/dist/surface/tools/browser-tools.js +51 -2
- package/dist/surface/tools/chat-drives.d.ts +101 -0
- package/dist/surface/tools/chat-drives.js +409 -0
- package/dist/surface/tools/coverage-tools.d.ts +2 -10
- package/dist/surface/tools/coverage-tools.js +2 -53
- package/dist/surface/tools/dynamic-tools.js +29 -1
- package/dist/surface/tools/empty-session-list.d.ts +51 -0
- package/dist/surface/tools/empty-session-list.js +120 -0
- package/dist/surface/tools/error-recovery.d.ts +14 -0
- package/dist/surface/tools/error-recovery.js +105 -8
- package/dist/surface/tools/explore-tools.d.ts +31 -1
- package/dist/surface/tools/explore-tools.js +438 -66
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +18 -3
- package/dist/surface/tools/gap-novelty.d.ts +3 -1
- package/dist/surface/tools/gap-novelty.js +8 -1
- package/dist/surface/tools/harness-explore.d.ts +118 -57
- package/dist/surface/tools/harness-explore.js +344 -292
- package/dist/surface/tools/harness-gate.d.ts +88 -0
- package/dist/surface/tools/harness-gate.js +235 -0
- package/dist/surface/tools/harness-hunt.d.ts +43 -0
- package/dist/surface/tools/harness-hunt.js +215 -0
- package/dist/surface/tools/harness-plan.d.ts +17 -0
- package/dist/surface/tools/harness-plan.js +38 -0
- package/dist/surface/tools/harness-script.d.ts +30 -0
- package/dist/surface/tools/harness-script.js +560 -0
- package/dist/surface/tools/harness-tab-guard.d.ts +5 -0
- package/dist/surface/tools/harness-tab-guard.js +27 -0
- package/dist/surface/tools/harness-toolset.d.ts +22 -1
- package/dist/surface/tools/harness-toolset.js +101 -7
- package/dist/surface/tools/human-notes.d.ts +16 -0
- package/dist/surface/tools/human-notes.js +27 -0
- package/dist/surface/tools/invoke-tool.d.ts +5 -2
- package/dist/surface/tools/invoke-tool.js +263 -85
- package/dist/surface/tools/lease-hint.js +26 -5
- package/dist/surface/tools/lease-permissions.d.ts +33 -0
- package/dist/surface/tools/lease-permissions.js +73 -0
- package/dist/surface/tools/lease-readiness.d.ts +38 -0
- package/dist/surface/tools/lease-readiness.js +57 -0
- package/dist/surface/tools/lease-seed.d.ts +49 -0
- package/dist/surface/tools/lease-seed.js +167 -0
- package/dist/surface/tools/lease-tools.d.ts +13 -24
- package/dist/surface/tools/lease-tools.js +146 -197
- package/dist/surface/tools/live-call-text.js +4 -4
- package/dist/surface/tools/merge-tools.js +42 -2
- package/dist/surface/tools/merged-name-redirect.js +4 -0
- package/dist/surface/tools/next-step.d.ts +29 -0
- package/dist/surface/tools/next-step.js +214 -0
- package/dist/surface/tools/observe-tools.js +45 -9
- package/dist/surface/tools/platform-moment.d.ts +72 -0
- package/dist/surface/tools/platform-moment.js +296 -0
- package/dist/surface/tools/query-hint-schema.d.ts +7 -0
- package/dist/surface/tools/query-hint-schema.js +10 -0
- package/dist/surface/tools/read-tools.js +71 -14
- package/dist/surface/tools/real-input-attempt.js +96 -13
- package/dist/surface/tools/reticle-result.d.ts +120 -0
- package/dist/surface/tools/reticle-result.js +364 -0
- package/dist/surface/tools/tool-kit.d.ts +83 -3
- package/dist/surface/tools/tool-kit.js +77 -7
- package/dist/surface/tools/tools.js +43 -59
- package/dist/telemetry/account-envelope.d.ts +7 -0
- package/dist/telemetry/account-envelope.js +61 -0
- package/dist/telemetry/agent-client.d.ts +15 -0
- package/dist/telemetry/agent-client.js +57 -0
- package/dist/telemetry/app-instrumented.js +9 -2
- package/dist/telemetry/argument-shape.d.ts +7 -0
- package/dist/telemetry/argument-shape.js +86 -1
- package/dist/telemetry/automation-hint.d.ts +2 -3
- package/dist/telemetry/automation-hint.js +33 -8
- package/dist/telemetry/cli-telemetry.js +7 -2
- package/dist/telemetry/daemon-telemetry.js +3 -0
- package/dist/telemetry/error-fingerprint.d.ts +10 -1
- package/dist/telemetry/error-fingerprint.js +61 -5
- package/dist/telemetry/feedback-cli.d.ts +0 -13
- package/dist/telemetry/feedback-cli.js +0 -77
- package/dist/telemetry/feedback.d.ts +13 -0
- package/dist/telemetry/feedback.js +183 -17
- package/dist/telemetry/harness-run.d.ts +18 -0
- package/dist/telemetry/harness-run.js +80 -0
- package/dist/telemetry/hud-events.d.ts +16 -0
- package/dist/telemetry/hud-events.js +27 -0
- package/dist/telemetry/hud-metrics.d.ts +29 -6
- package/dist/telemetry/hud-metrics.js +116 -25
- package/dist/telemetry/init-telemetry.js +2 -2
- package/dist/telemetry/install-source.d.ts +13 -25
- package/dist/telemetry/install-source.js +44 -3
- package/dist/telemetry/mcp-connection.d.ts +0 -14
- package/dist/telemetry/mcp-connection.js +5 -1
- package/dist/telemetry/onboarding-firsts.d.ts +32 -0
- package/dist/telemetry/onboarding-firsts.js +81 -6
- package/dist/telemetry/platform-linked.d.ts +5 -0
- package/dist/telemetry/platform-linked.js +32 -0
- package/dist/telemetry/project-profile.js +5 -3
- package/dist/telemetry/proxy-telemetry.js +4 -1
- package/dist/telemetry/session-metrics.d.ts +15 -4
- package/dist/telemetry/session-metrics.js +88 -52
- package/dist/telemetry/telemetry.d.ts +38 -2
- package/dist/telemetry/telemetry.js +144 -34
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +13 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +20 -6
- package/docs/README.md +3 -3
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +25 -28
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +33 -28
- package/docs/benchmarks.md +5 -5
- package/docs/best-practices.mdx +27 -9
- package/docs/capabilities.mdx +14 -16
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +54 -75
- package/docs/cli/doctor.mdx +14 -3
- package/docs/cli/drive.mdx +20 -14
- package/docs/cli/feedback.mdx +3 -3
- package/docs/cli/gate.mdx +7 -2
- package/docs/cli/help.mdx +50 -55
- package/docs/cli/init.mdx +43 -28
- package/docs/cli/license.mdx +12 -8
- package/docs/cli/mcp.mdx +4 -4
- package/docs/cli/open.mdx +3 -3
- package/docs/cli/report.mdx +4 -2
- package/docs/cli/restart.mdx +2 -2
- package/docs/cli/rollback.mdx +14 -8
- package/docs/cli/serve.mdx +4 -4
- package/docs/cli/setup.mdx +23 -0
- package/docs/cli/status.mdx +18 -5
- package/docs/cli/stop.mdx +67 -8
- package/docs/cli/try.mdx +62 -0
- package/docs/cli/update.mdx +4 -3
- package/docs/cli/verify.mdx +17 -6
- package/docs/cli/version.mdx +5 -4
- package/docs/cli.mdx +111 -42
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +9 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +7 -8
- package/docs/faq.mdx +3 -3
- package/docs/first-drive.md +5 -4
- package/docs/flows.md +35 -27
- package/docs/for-agents.md +4 -5
- package/docs/frameworks.mdx +32 -21
- package/docs/getting-started.md +65 -61
- package/docs/human-control.md +16 -16
- package/docs/index.mdx +15 -42
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +23 -13
- package/docs/instrumentation.mdx +5 -3
- package/docs/integration-patterns.md +7 -7
- package/docs/license-activation.mdx +1 -1
- package/docs/multi-agent-testing.md +24 -6
- package/docs/packages/babel-plugin.mdx +4 -2
- package/docs/packages/browser.mdx +16 -10
- package/docs/packages/core.mdx +12 -5
- package/docs/packages/electron.mdx +3 -2
- package/docs/packages/engine.mdx +1 -1
- package/docs/packages/eslint-plugin.mdx +18 -12
- package/docs/packages/next.mdx +8 -7
- package/docs/packages/open-verification.mdx +1 -1
- package/docs/packages/server.mdx +5 -5
- package/docs/packages/tauri.mdx +9 -9
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +32 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +69 -30
- package/docs/required-checks.md +8 -7
- package/docs/reticle-manual.md +15 -5
- package/docs/skill-file.mdx +17 -79
- package/docs/skill-setup.md +9 -9
- package/docs/skill.md +200 -0
- package/docs/system-map.md +7 -7
- package/docs/telemetry.md +23 -25
- package/docs/testing.md +4 -4
- package/docs/token-efficiency.md +12 -12
- package/docs/tools/act-and-wait.mdx +9 -2
- package/docs/tools/act-sequence.mdx +6 -7
- package/docs/tools/act.mdx +2 -2
- package/docs/tools/assert.mdx +18 -17
- package/docs/tools/console.mdx +9 -9
- package/docs/tools/inspect.mdx +16 -7
- package/docs/tools/look.mdx +24 -0
- package/docs/tools/navigate.mdx +5 -3
- package/docs/tools/network.mdx +2 -2
- package/docs/tools/observe.mdx +6 -6
- package/docs/tools/overview.mdx +34 -33
- package/docs/tools/query.mdx +5 -5
- package/docs/tools/session-and-feedback.mdx +22 -13
- package/docs/tools/sessions.mdx +8 -8
- package/docs/tools/snapshot.mdx +6 -5
- package/docs/tools/state.mdx +9 -9
- package/docs/tools/tools-and-run.mdx +26 -24
- package/docs/tools/verify.mdx +28 -0
- package/docs/tools/wait-for.mdx +8 -4
- package/docs/troubleshooting.mdx +21 -6
- package/docs/usage.md +55 -46
- package/docs/use-cases.mdx +3 -3
- package/docs/vs-chrome-devtools-mcp.mdx +9 -6
- package/docs/vs-playwright-mcp.mdx +3 -1
- package/docs/what-is-recorded.md +17 -5
- package/docs/what-is-reticle.mdx +5 -3
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -241
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- package/dist/features/harness/driver.d.ts +0 -50
- package/dist/features/harness/driver.js +0 -236
- package/dist/features/harness/jev-driver.d.ts +0 -188
- package/dist/features/harness/jev-driver.js +0 -678
- package/dist/features/harness/openai-driver.d.ts +0 -58
- package/dist/features/harness/openai-driver.js +0 -206
- package/dist/judgement/hunt/hunt-report.d.ts +0 -49
- package/dist/judgement/hunt/hunt-report.js +0 -84
- package/dist/language/flows/buddy-status.d.ts +0 -25
- package/dist/language/flows/buddy-status.js +0 -32
- package/dist/language/flows/change/watch-batcher.d.ts +0 -18
- package/dist/language/flows/change/watch-batcher.js +0 -19
- package/dist/memory/cloud/harness-offer.d.ts +0 -44
- package/dist/memory/cloud/harness-offer.js +0 -145
- package/dist/memory/project/dir/fill-value-store.d.ts +0 -32
- package/dist/memory/project/dir/fill-value-store.js +0 -88
- package/dist/surface/tools/feature-capture.d.ts +0 -151
- package/dist/surface/tools/feature-capture.js +0 -235
- package/dist/surface/tools/tool-hit-rate.d.ts +0 -87
- package/dist/surface/tools/tool-hit-rate.js +0 -90
- package/dist/telemetry/harness-drive.d.ts +0 -4
- package/dist/telemetry/harness-drive.js +0 -35
- package/dist/telemetry/identify.d.ts +0 -22
- package/dist/telemetry/identify.js +0 -73
- package/docs/cli/capsules.mdx +0 -70
- package/docs/cli/hunt.mdx +0 -73
- package/docs/cli/identify.mdx +0 -76
- package/docs/cli/kill.mdx +0 -91
- package/docs/cli/watch.mdx +0 -62
- package/docs/local-registry.md +0 -143
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
import { asFlowName, asProjectId, } from '@reticlehq/core';
|
|
2
|
-
import { REDACTED_FILL } from './fields/flow-secret-field.js';
|
|
2
|
+
import { REDACTED_FILL, SECRET_NAME_ARG, secretEnvKey } 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
6
|
import { AnchorKind, DEGRADED_ANCHOR_ROLE, FLOW_FILE_VERSION, flowFileVersionFor, FlowErrorCode, FlowFileSchema, FlowStepTool, QueryBy, defaultIsSensitiveKey, } from '@reticlehq/core';
|
|
7
|
-
import { ReticleTool } from '@reticlehq/core';
|
|
7
|
+
import { ReticleTool, flowJsonReplacer } from '@reticlehq/core';
|
|
8
8
|
import { asRecord, asString } from '@reticlehq/core';
|
|
9
9
|
import { applyHealChanges } from './heal.js';
|
|
10
10
|
import { withLearnedSources } from './learned-sources.js';
|
|
11
11
|
import { flowIntentGap, linkFlowIntent } from './flow-intent.js';
|
|
12
|
-
import { journeyFingerprint, journeyName, mergeJourney, routeClaims } from './flow-journey.js';
|
|
12
|
+
import { journeyFingerprint, journeyName, mergeJourney, routeClaims, withinJourney, } from './flow-journey.js';
|
|
13
13
|
import { IntentStore } from '../../memory/intent/intent-store.js';
|
|
14
14
|
import { flowDir, flowParentDir, flowPath, reticleDirPaths, isValidFlowName, } from '../../memory/project/dir/reticle-dir.js';
|
|
15
15
|
import { describeFlowZodFailure, parseFlowFileText } from './flow-expect-grammar.js';
|
|
@@ -76,8 +76,11 @@ export function anchorForStep(args) {
|
|
|
76
76
|
if (by === QueryBy.ROLE && value !== undefined) {
|
|
77
77
|
const name = asString(args['name']);
|
|
78
78
|
if (name !== undefined && name.length > 0) {
|
|
79
|
-
//
|
|
80
|
-
|
|
79
|
+
// Provenance lives on the step, not the anchor; the position among namesakes is identity.
|
|
80
|
+
const nth = args['nth'];
|
|
81
|
+
const of = args['of'];
|
|
82
|
+
const among = 'number' === typeof nth && 'number' === typeof of ? { nth, of } : {};
|
|
83
|
+
return { anchor: { kind: AnchorKind.ROLE, role: value, name, ...among }, degraded: false };
|
|
81
84
|
}
|
|
82
85
|
}
|
|
83
86
|
if (by === QueryBy.COMPONENT) {
|
|
@@ -127,7 +130,32 @@ function redactSecretFill(anchor, args) {
|
|
|
127
130
|
const field = anchorFieldName(anchor);
|
|
128
131
|
if (field === undefined || !defaultIsSensitiveKey(field))
|
|
129
132
|
return args;
|
|
130
|
-
|
|
133
|
+
// The variable that supplies it, beside the placeholder: the file alone says what to set.
|
|
134
|
+
return { ...args, value: REDACTED_FILL, [SECRET_NAME_ARG]: secretEnvKey(field) };
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* The recorded steps as they may be SHOWN: every credential fill carries the placeholder.
|
|
138
|
+
*
|
|
139
|
+
* The same rule the saved flow is written by, applied to what a tool hands back. `record stop`
|
|
140
|
+
* returned the compiled program verbatim, so the password a saved flow never contained went into
|
|
141
|
+
* the agent's transcript instead. The store keeps the real value — an in-session replay types it.
|
|
142
|
+
*/
|
|
143
|
+
export function redactRecordedSteps(steps) {
|
|
144
|
+
return steps.map((step) => {
|
|
145
|
+
if (step.tool === ReticleTool.ACT_SEQUENCE && Array.isArray(step.args['steps'])) {
|
|
146
|
+
const subs = step.args['steps'].map((raw) => redactNormalizedArgs(asRecord(raw)));
|
|
147
|
+
return { ...step, args: { ...step.args, steps: subs } };
|
|
148
|
+
}
|
|
149
|
+
return { ...step, args: redactNormalizedArgs(step.args) };
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
/** One normalized act's args with its inner fill `args` redacted by the anchor it would save as. */
|
|
153
|
+
function redactNormalizedArgs(normalized) {
|
|
154
|
+
const inner = normalized['args'];
|
|
155
|
+
if ('object' !== typeof inner || null === inner)
|
|
156
|
+
return normalized;
|
|
157
|
+
const redacted = redactSecretFill(anchorForStep(normalized).anchor, asRecord(inner));
|
|
158
|
+
return redacted === inner ? normalized : { ...normalized, args: redacted };
|
|
131
159
|
}
|
|
132
160
|
/**
|
|
133
161
|
* What the anchor CALLS the field it points at.
|
|
@@ -166,6 +194,8 @@ function buildStep(tool, anchor, action, args, degraded) {
|
|
|
166
194
|
*/
|
|
167
195
|
export function recordedStepToFlowStep(step) {
|
|
168
196
|
const out = anchoredStep(step);
|
|
197
|
+
if (step.timeoutMs !== undefined)
|
|
198
|
+
out.timeoutMs = step.timeoutMs;
|
|
169
199
|
if (step.page !== undefined)
|
|
170
200
|
out.page = step.page;
|
|
171
201
|
if (step.endPage !== undefined && step.endPage !== step.page)
|
|
@@ -235,10 +265,17 @@ export class FlowStore {
|
|
|
235
265
|
#fs;
|
|
236
266
|
#root;
|
|
237
267
|
#clock;
|
|
238
|
-
|
|
268
|
+
#onWrote;
|
|
269
|
+
/**
|
|
270
|
+
* `onWrote` is told after a save lands, so cloud sync cycles on a new flow the way it does on a
|
|
271
|
+
* new run (`RunStore` takes the same callback). Without it a flow saved with no run behind it
|
|
272
|
+
* waited for the timer, and a daemon that exited first never sent it.
|
|
273
|
+
*/
|
|
274
|
+
constructor(fs, root, clock, opts = {}) {
|
|
239
275
|
this.#fs = fs;
|
|
240
276
|
this.#root = root;
|
|
241
277
|
this.#clock = clock;
|
|
278
|
+
this.#onWrote = opts.onWrote;
|
|
242
279
|
}
|
|
243
280
|
/**
|
|
244
281
|
* The single byte-stable flow serializer: 2-space indent + one trailing newline. save,
|
|
@@ -247,7 +284,7 @@ export class FlowStore {
|
|
|
247
284
|
*/
|
|
248
285
|
#serialize(flow) {
|
|
249
286
|
const stamped = { ...flow, version: flowFileVersionFor(flow) };
|
|
250
|
-
return `${JSON.stringify(stamped,
|
|
287
|
+
return `${JSON.stringify(stamped, flowJsonReplacer, JSON_INDENT)}\n`;
|
|
251
288
|
}
|
|
252
289
|
/**
|
|
253
290
|
* Register the flow's business goal in the intent ledger and stamp the row's id onto the flow.
|
|
@@ -321,6 +358,7 @@ export class FlowStore {
|
|
|
321
358
|
const flow = await this.#linkIntent(base);
|
|
322
359
|
await this.#fs.mkdir(flowParentDir(this.#root, program.name, pid));
|
|
323
360
|
await this.#fs.writeFile(flowPath(this.#root, program.name, pid), this.#serialize(flow));
|
|
361
|
+
this.#onWrote?.();
|
|
324
362
|
return { ok: true, value: this.#summary(flow) };
|
|
325
363
|
}
|
|
326
364
|
/**
|
|
@@ -337,19 +375,40 @@ export class FlowStore {
|
|
|
337
375
|
const pid = safeProjectId(projectId);
|
|
338
376
|
const fresh = this.#build(program, undefined, pid);
|
|
339
377
|
const saved = [];
|
|
340
|
-
|
|
378
|
+
const freshPrint = journeyFingerprint(fresh);
|
|
379
|
+
for (const name of await this.list(pid)) {
|
|
341
380
|
const loaded = await this.load(name, pid);
|
|
342
|
-
if (loaded.ok)
|
|
381
|
+
if (!loaded.ok)
|
|
382
|
+
continue;
|
|
383
|
+
if (name.startsWith(prefix))
|
|
343
384
|
saved.push(loaded.value);
|
|
385
|
+
// The agent already saved this journey under its own name: one journey, one flow. A web drive
|
|
386
|
+
// saved its named flow and an automatic `drive-saved-<email>` beside it, every time.
|
|
387
|
+
else if (journeyFingerprint(loaded.value) === freshPrint) {
|
|
388
|
+
return { ok: true, value: this.#summary(loaded.value) };
|
|
389
|
+
}
|
|
344
390
|
}
|
|
345
391
|
const byPrint = new Map();
|
|
346
392
|
for (const flow of saved) {
|
|
347
393
|
const print = journeyFingerprint(flow);
|
|
348
394
|
byPrint.set(print, [...(byPrint.get(print) ?? []), flow]);
|
|
349
395
|
}
|
|
350
|
-
const print =
|
|
396
|
+
const print = freshPrint;
|
|
351
397
|
const taken = new Map(saved.map((flow) => [flow.name, journeyFingerprint(flow)]));
|
|
352
|
-
|
|
398
|
+
// The same name holding this journey driven with a step more or less: one file, the fuller drive.
|
|
399
|
+
const same = saved.find((flow) => flow.name === fresh.name && taken.get(flow.name) !== print);
|
|
400
|
+
if (same !== undefined && withinJourney(same, fresh))
|
|
401
|
+
return { ok: true, value: this.#summary(same) };
|
|
402
|
+
const extended = same !== undefined && withinJourney(fresh, same);
|
|
403
|
+
if (extended)
|
|
404
|
+
taken.delete(fresh.name);
|
|
405
|
+
const named = {
|
|
406
|
+
...fresh,
|
|
407
|
+
...(extended && fresh.intent === undefined && same.intent !== undefined
|
|
408
|
+
? { intent: same.intent }
|
|
409
|
+
: {}),
|
|
410
|
+
name: journeyName(fresh.name, print, taken),
|
|
411
|
+
};
|
|
353
412
|
byPrint.set(print, [...(byPrint.get(print) ?? []), named]);
|
|
354
413
|
let result = named;
|
|
355
414
|
for (const [groupPrint, group] of byPrint) {
|
|
@@ -367,6 +426,7 @@ export class FlowStore {
|
|
|
367
426
|
if (groupPrint === print)
|
|
368
427
|
result = merged;
|
|
369
428
|
}
|
|
429
|
+
this.#onWrote?.();
|
|
370
430
|
return { ok: true, value: this.#summary(result) };
|
|
371
431
|
}
|
|
372
432
|
/** Write a flow where it already lives, or into its project's directory when it is new. */
|
|
@@ -401,6 +461,7 @@ export class FlowStore {
|
|
|
401
461
|
const valid = await this.#linkIntent(parsed.data);
|
|
402
462
|
await this.#fs.mkdir(flowParentDir(this.#root, asFlowName(valid.name), pid));
|
|
403
463
|
await this.#fs.writeFile(flowPath(this.#root, asFlowName(valid.name), pid), this.#serialize(valid));
|
|
464
|
+
this.#onWrote?.();
|
|
404
465
|
return { ok: true, value: this.#summary(valid) };
|
|
405
466
|
}
|
|
406
467
|
/**
|
|
@@ -419,6 +480,7 @@ export class FlowStore {
|
|
|
419
480
|
resolvePath: (n, p) => this.#resolveReadPath(asFlowName(n), p),
|
|
420
481
|
write: (path, contents) => this.#fs.writeFile(path, contents),
|
|
421
482
|
serialize: (flow) => this.#serialize(flow),
|
|
483
|
+
readRaw: (path) => this.#fs.readFile(path),
|
|
422
484
|
}, name, projectId, change);
|
|
423
485
|
}
|
|
424
486
|
/** Write back only what a replay LEARNED. See `#changeInPlace` for why it is not `saveFlow`. */
|
|
@@ -12,7 +12,8 @@ import { replayFlow } from './flow-replay.js';
|
|
|
12
12
|
import { applyHealChanges, collectProposals } from './heal.js';
|
|
13
13
|
import { healPrecondition } from './heal-precondition.js';
|
|
14
14
|
import { assertSuccess, dynamicTestids, successLabel } from './flow-success.js';
|
|
15
|
-
import { flowErrorMessage
|
|
15
|
+
import { flowErrorMessage } from './flow-replay-run.js';
|
|
16
|
+
import { sessionTarget } from '../../memory/project/session-root.js';
|
|
16
17
|
import { flowsForSession } from './flow-store-for-session.js';
|
|
17
18
|
const HEAL_MESSAGES = {
|
|
18
19
|
NOTHING: 'nothing to heal — every anchor resolved on replay',
|
|
@@ -48,8 +49,9 @@ function toChange(proposal) {
|
|
|
48
49
|
export async function healFlow(deps, args) {
|
|
49
50
|
const name = asString(args['flowName']) ?? '';
|
|
50
51
|
const apply = true === args['apply'];
|
|
51
|
-
const
|
|
52
|
-
const
|
|
52
|
+
const target = sessionTarget(deps, asString(args['sessionId']));
|
|
53
|
+
const { projectId } = target;
|
|
54
|
+
const loaded = await flowsForSession(deps, target).flows.load(name, projectId);
|
|
53
55
|
if (!loaded.ok) {
|
|
54
56
|
return {
|
|
55
57
|
name,
|
|
@@ -163,7 +165,7 @@ export async function healFlow(deps, args) {
|
|
|
163
165
|
}
|
|
164
166
|
// Healing WRITES, so it must land where the load came from — a heal that read the app's flow and
|
|
165
167
|
// wrote the daemon's copy would silently fork the two.
|
|
166
|
-
const written = await flowsForSession(deps,
|
|
168
|
+
const written = await flowsForSession(deps, target).flows.heal(name, proposals.map(toChange), projectId);
|
|
167
169
|
if (!written.ok) {
|
|
168
170
|
return {
|
|
169
171
|
name,
|
|
@@ -25,7 +25,14 @@ export interface NarrowWritePort {
|
|
|
25
25
|
resolvePath: (name: string, projectId?: ProjectId) => Promise<string | null>;
|
|
26
26
|
write: (path: string, contents: string) => Promise<void>;
|
|
27
27
|
serialize: (flow: FlowFile) => string;
|
|
28
|
+
/** The file as it is on disk, so a change lands in it and nothing else moves. */
|
|
29
|
+
readRaw?: (path: string) => Promise<string>;
|
|
28
30
|
}
|
|
31
|
+
/**
|
|
32
|
+
* `raw` with only what changed between `before` and `after` applied, everything else as written:
|
|
33
|
+
* its key order, its fields the reader fills in by default, its own spelling. Pure.
|
|
34
|
+
*/
|
|
35
|
+
export declare function withChangesOnly(raw: unknown, before: unknown, after: unknown): unknown;
|
|
29
36
|
export declare function changeInPlace<T>(port: NarrowWritePort, name: string, projectId: ProjectId | undefined, change: (flow: FlowFile) => {
|
|
30
37
|
next: FlowFile;
|
|
31
38
|
value: T;
|
|
@@ -2,6 +2,28 @@ import { FlowErrorCode, FlowFileSchema } from '@reticlehq/core';
|
|
|
2
2
|
import { describeFlowZodFailure } from './flow-expect-grammar.js';
|
|
3
3
|
import { isValidFlowName } from '../../memory/project/dir/reticle-dir.js';
|
|
4
4
|
import { safeProjectId } from './flow-result.js';
|
|
5
|
+
const isPlain = (v) => 'object' === typeof v && null !== v && !Array.isArray(v);
|
|
6
|
+
const same = (a, b) => JSON.stringify(a) === JSON.stringify(b);
|
|
7
|
+
/**
|
|
8
|
+
* `raw` with only what changed between `before` and `after` applied, everything else as written:
|
|
9
|
+
* its key order, its fields the reader fills in by default, its own spelling. Pure.
|
|
10
|
+
*/
|
|
11
|
+
export function withChangesOnly(raw, before, after) {
|
|
12
|
+
if (Array.isArray(raw) && Array.isArray(before) && Array.isArray(after))
|
|
13
|
+
return raw.length === before.length && before.length === after.length
|
|
14
|
+
? raw.map((item, i) => withChangesOnly(item, before[i], after[i]))
|
|
15
|
+
: after;
|
|
16
|
+
if (!isPlain(raw) || !isPlain(before) || !isPlain(after))
|
|
17
|
+
return after;
|
|
18
|
+
const out = { ...raw };
|
|
19
|
+
for (const key of Object.keys(after))
|
|
20
|
+
if (!same(after[key], before[key]))
|
|
21
|
+
out[key] = key in raw ? withChangesOnly(raw[key], before[key], after[key]) : after[key];
|
|
22
|
+
for (const key of Object.keys(before))
|
|
23
|
+
if (!(key in after))
|
|
24
|
+
delete out[key];
|
|
25
|
+
return out;
|
|
26
|
+
}
|
|
5
27
|
export async function changeInPlace(port, name, projectId, change) {
|
|
6
28
|
if (!isValidFlowName(name))
|
|
7
29
|
return { ok: false, code: FlowErrorCode.INVALID_NAME };
|
|
@@ -21,6 +43,19 @@ export async function changeInPlace(port, name, projectId, change) {
|
|
|
21
43
|
detail: describeFlowZodFailure(parsed.error),
|
|
22
44
|
};
|
|
23
45
|
}
|
|
24
|
-
|
|
46
|
+
// A replay that learned nothing new leaves a committed file alone: every replay used to rewrite
|
|
47
|
+
// it (keys reordered, defaults written in), and `git status` called it modified.
|
|
48
|
+
if (port.serialize(parsed.data) === port.serialize(loaded.value))
|
|
49
|
+
return { ok: true, value };
|
|
50
|
+
let raw;
|
|
51
|
+
try {
|
|
52
|
+
raw = JSON.parse((await port.readRaw?.(path)) ?? 'null');
|
|
53
|
+
}
|
|
54
|
+
catch {
|
|
55
|
+
raw = null;
|
|
56
|
+
}
|
|
57
|
+
await port.write(path, isPlain(raw)
|
|
58
|
+
? `${JSON.stringify(withChangesOnly(raw, loaded.value, parsed.data), null, 2)}\n`
|
|
59
|
+
: port.serialize(parsed.data));
|
|
25
60
|
return { ok: true, value };
|
|
26
61
|
}
|
|
@@ -31,17 +31,17 @@ export declare const FlakeFileSchema: z.ZodObject<{
|
|
|
31
31
|
fails: number;
|
|
32
32
|
}>>;
|
|
33
33
|
}, "strip", z.ZodTypeAny, {
|
|
34
|
-
version: 1;
|
|
35
34
|
flows: Record<string, {
|
|
36
35
|
runs: number;
|
|
37
36
|
fails: number;
|
|
38
37
|
}>;
|
|
39
|
-
}, {
|
|
40
38
|
version: 1;
|
|
39
|
+
}, {
|
|
41
40
|
flows: Record<string, {
|
|
42
41
|
runs: number;
|
|
43
42
|
fails: number;
|
|
44
43
|
}>;
|
|
44
|
+
version: 1;
|
|
45
45
|
}>;
|
|
46
46
|
export declare function emptyRecord(): FlakeRecord;
|
|
47
47
|
/** Accrue one unchanged-code replay outcome. */
|
|
@@ -27,6 +27,19 @@ function recordingRouteOf(pathname, hash = '') {
|
|
|
27
27
|
return routePathOf(0 === pathname.length ? '/' : pathname, fragment);
|
|
28
28
|
return pathname;
|
|
29
29
|
}
|
|
30
|
+
/**
|
|
31
|
+
* A startPath as a page key: its query dropped, hash kept. A startPath keeps the app's query so
|
|
32
|
+
* replay starts on the filtered page (#1411), but a ROUTE_CHANGE contributes only pathname and
|
|
33
|
+
* hash, so `/products?scope=X` then `/checkout` then `/products` must compare the first and last
|
|
34
|
+
* as one page or the backtrack goes unseen.
|
|
35
|
+
*/
|
|
36
|
+
function pageKeyOf(startPath) {
|
|
37
|
+
const hashAt = startPath.indexOf('#');
|
|
38
|
+
const queryAt = startPath.indexOf('?');
|
|
39
|
+
if (queryAt < 0 || (hashAt >= 0 && queryAt > hashAt))
|
|
40
|
+
return startPath;
|
|
41
|
+
return startPath.slice(0, queryAt) + (hashAt >= 0 ? startPath.slice(hashAt) : '');
|
|
42
|
+
}
|
|
30
43
|
function collapseConsecutive(routes) {
|
|
31
44
|
const out = [];
|
|
32
45
|
for (const route of routes) {
|
|
@@ -60,7 +73,7 @@ export function recordingBacktrackWarning(routes) {
|
|
|
60
73
|
export function routesFromRecording(startPath, events) {
|
|
61
74
|
const raw = [];
|
|
62
75
|
if (undefined !== startPath)
|
|
63
|
-
raw.push(recordingRouteOf(startPath));
|
|
76
|
+
raw.push(recordingRouteOf(pageKeyOf(startPath)));
|
|
64
77
|
for (const event of events) {
|
|
65
78
|
if (EventType.ROUTE_CHANGE !== event.type)
|
|
66
79
|
continue;
|
|
@@ -7,6 +7,8 @@ export interface RecordedStep {
|
|
|
7
7
|
args: Record<string, unknown>;
|
|
8
8
|
/** false if any ref could not be normalized to a testid (replay only valid in-session). */
|
|
9
9
|
stable: boolean;
|
|
10
|
+
/** The caller's per-step wait budget, when one was explicitly provided. */
|
|
11
|
+
timeoutMs?: number;
|
|
10
12
|
/** Optional post-condition annotation carried into the on-disk flow's expect. */
|
|
11
13
|
expect?: Predicate;
|
|
12
14
|
/**
|
|
@@ -27,18 +29,41 @@ export interface RecordedStep {
|
|
|
27
29
|
* `invoke` first and treats the step as a call.
|
|
28
30
|
*/
|
|
29
31
|
invoke?: string;
|
|
32
|
+
/**
|
|
33
|
+
* Network mocks were active on this step's tab when it ran. RECORDER-INTERNAL, ambient tape only,
|
|
34
|
+
* like `route`: a journey that ran against mocked responses replays against the real backend,
|
|
35
|
+
* so it is not auto-saved (#1459).
|
|
36
|
+
*/
|
|
37
|
+
mocked?: true;
|
|
30
38
|
/** The page this step ran on. Written to the saved step (unlike `route`, which cuts journeys). */
|
|
31
39
|
page?: string;
|
|
32
40
|
/** The page it ended on once it settled — see `markEnded`. */
|
|
33
41
|
endPage?: string;
|
|
34
42
|
/** Why the agent took this step: the `intent` it declared on the action. Names the saved flow. */
|
|
35
43
|
intent?: string;
|
|
44
|
+
/**
|
|
45
|
+
* Why a consequence this step PROVED is not in the flow: the flow file could not express it (a
|
|
46
|
+
* session ref such as `e12` means nothing on a later page). Said at stop, so a weaker flow is
|
|
47
|
+
* never saved silently.
|
|
48
|
+
*/
|
|
49
|
+
unkeptExpect?: string;
|
|
36
50
|
}
|
|
37
51
|
interface ActiveRecording {
|
|
38
52
|
cursor: number;
|
|
53
|
+
/**
|
|
54
|
+
* The session (tab) that started it. Only that session's steps join it: one daemon serves every
|
|
55
|
+
* agent and app on the machine, and capturing into every open recording put a click from an
|
|
56
|
+
* unrelated app into somebody else's saved flow (#988). Absent: takes every session's steps.
|
|
57
|
+
*/
|
|
58
|
+
session?: string;
|
|
39
59
|
steps: RecordedStep[];
|
|
40
60
|
/** The route the journey began on. See CompiledProgram.startPath. */
|
|
41
61
|
startPath?: string;
|
|
62
|
+
/**
|
|
63
|
+
* The document the tab was on at start. A full-page load makes a new one even when the SDK keeps
|
|
64
|
+
* its session id, and its clock is from a different connection, so this is how stop tells (#1411).
|
|
65
|
+
*/
|
|
66
|
+
document?: string;
|
|
42
67
|
/**
|
|
43
68
|
* For each recording that was ALREADY in flight when this one started, how many steps it had.
|
|
44
69
|
*
|
|
@@ -89,9 +114,20 @@ export declare const INVOKE_TOOL: string;
|
|
|
89
114
|
* buffer.
|
|
90
115
|
*/
|
|
91
116
|
export declare const AMBIENT_RECORDING = "__ambient__";
|
|
117
|
+
/**
|
|
118
|
+
* One ambient tape per tab. It was one for the whole daemon, so a drive in ANOTHER app (the console
|
|
119
|
+
* beside the repo's own app) was cut into a flow and saved into this repo's committed `flows/`, and
|
|
120
|
+
* synced to its project. A tape now holds one tab's steps, and that tab's end takes only its own.
|
|
121
|
+
*/
|
|
122
|
+
export declare const ambientRecordingOf: (session: string | undefined) => string;
|
|
123
|
+
/** Whether a recording is an ambient tape: the daemon's own, never one somebody opened. */
|
|
124
|
+
export declare const isAmbient: (name: string) => boolean;
|
|
92
125
|
export declare class RecordingStore {
|
|
93
126
|
#private;
|
|
94
|
-
|
|
127
|
+
private readonly byHarness;
|
|
128
|
+
/** `byHarness`: whether the step being captured was driven by the Harness, which tapes its own. */
|
|
129
|
+
constructor(byHarness?: () => boolean);
|
|
130
|
+
start(name: string, cursor: number, startPath?: string, session?: string, document?: string): void;
|
|
95
131
|
isRecording(name: string): boolean;
|
|
96
132
|
/**
|
|
97
133
|
* Number of steps captured so far in the named ACTIVE recording (0 if it
|
|
@@ -112,7 +148,12 @@ export declare class RecordingStore {
|
|
|
112
148
|
* Opened lazily on the first step rather than in the constructor: a store that never records
|
|
113
149
|
* anything should not carry an empty tape, and "did anything happen at all" stays answerable.
|
|
114
150
|
*/
|
|
115
|
-
|
|
151
|
+
/**
|
|
152
|
+
* Whether a tab has network mocks installed from now on. Each ambient step on it is marked while
|
|
153
|
+
* they are, so the journey it belongs to is not auto-saved as a flow (#1459).
|
|
154
|
+
*/
|
|
155
|
+
markMocked(session: string | undefined, active: boolean): void;
|
|
156
|
+
capture(step: RecordedStep, route?: string, session?: string): void;
|
|
116
157
|
/**
|
|
117
158
|
* Add a consequence to the last captured step of every active recording.
|
|
118
159
|
*
|
|
@@ -120,20 +161,31 @@ export declare class RecordingStore {
|
|
|
120
161
|
* reached the recorder — only the act tools called `capture` — so the flow kept the click and lost
|
|
121
162
|
* the proof. What the step already declared is kept; the new check joins it under `allOf`.
|
|
122
163
|
*/
|
|
123
|
-
attachExpect(expect: Predicate): void;
|
|
164
|
+
attachExpect(expect: Predicate, session?: string): void;
|
|
124
165
|
/**
|
|
125
166
|
* A navigation happened. Navigating records no step, so until the next one is captured, a check
|
|
126
167
|
* proved now is about the page the navigation opened, not about the last step — and kept on that
|
|
127
168
|
* step, replay would ask it right after the click, of a page it was never true on.
|
|
128
169
|
*/
|
|
129
170
|
markNavigated(): void;
|
|
171
|
+
/**
|
|
172
|
+
* Take the expectation off the ambient tape's last step, because the verdict on it came back no.
|
|
173
|
+
*
|
|
174
|
+
* A step is captured at dispatch, before anything is judged, so a claim that turned out false is
|
|
175
|
+
* already on the tape as that step's `expect`. Cut into a journey it becomes a flow that is red for
|
|
176
|
+
* ever, on an expectation nobody but the agent's wrong guess made. The failure is not lost: it is
|
|
177
|
+
* filed as a capsule, the artifact built for "this should hold and does not". The ACTION stays,
|
|
178
|
+
* since the steps after it ran on the page it produced. A recording somebody opened deliberately
|
|
179
|
+
* is left as they drove it.
|
|
180
|
+
*/
|
|
181
|
+
unassertLast(): void;
|
|
130
182
|
/**
|
|
131
183
|
* The page the step just captured ended on, once its action settled.
|
|
132
184
|
*
|
|
133
185
|
* Fills only a step that has none, so calling it after an action that captured nothing leaves the
|
|
134
186
|
* previous step's own answer alone.
|
|
135
187
|
*/
|
|
136
|
-
markEnded(page: string | undefined): void;
|
|
188
|
+
markEnded(page: string | undefined, session?: string): void;
|
|
137
189
|
/**
|
|
138
190
|
* Returns the active recording (cursor + steps) and clears it, or undefined if not recording.
|
|
139
191
|
*
|
|
@@ -150,6 +202,8 @@ export declare class RecordingStore {
|
|
|
150
202
|
saveCompiled(program: CompiledProgram): void;
|
|
151
203
|
getCompiled(name: string): CompiledProgram | undefined;
|
|
152
204
|
active(): string[];
|
|
205
|
+
/** The ambient tape of one tab (or of steps no tab named), taken: what its session end saves. */
|
|
206
|
+
takeAmbient(session: string | undefined): ActiveRecording | undefined;
|
|
153
207
|
/**
|
|
154
208
|
* Names of recordings that have been STOPPED and compiled.
|
|
155
209
|
*
|
|
@@ -20,6 +20,14 @@ export const INVOKE_TOOL = FlowStepTool.INVOKE;
|
|
|
20
20
|
* buffer.
|
|
21
21
|
*/
|
|
22
22
|
export const AMBIENT_RECORDING = '__ambient__';
|
|
23
|
+
/**
|
|
24
|
+
* One ambient tape per tab. It was one for the whole daemon, so a drive in ANOTHER app (the console
|
|
25
|
+
* beside the repo's own app) was cut into a flow and saved into this repo's committed `flows/`, and
|
|
26
|
+
* synced to its project. A tape now holds one tab's steps, and that tab's end takes only its own.
|
|
27
|
+
*/
|
|
28
|
+
export const ambientRecordingOf = (session) => session === undefined ? AMBIENT_RECORDING : `${AMBIENT_RECORDING}:${session}`;
|
|
29
|
+
/** Whether a recording is an ambient tape: the daemon's own, never one somebody opened. */
|
|
30
|
+
export const isAmbient = (name) => AMBIENT_RECORDING === name || name.startsWith(`${AMBIENT_RECORDING}:`);
|
|
23
31
|
/**
|
|
24
32
|
* How long a journey the ambient tape will hold.
|
|
25
33
|
*
|
|
@@ -29,21 +37,36 @@ export const AMBIENT_RECORDING = '__ambient__';
|
|
|
29
37
|
*/
|
|
30
38
|
const AMBIENT_STEP_CAP = 400;
|
|
31
39
|
export class RecordingStore {
|
|
40
|
+
byHarness;
|
|
32
41
|
#active = new Map();
|
|
33
42
|
#compiled = new Map();
|
|
43
|
+
/** The ambient tape the last step went on: the one a refuted claim is taken off. */
|
|
44
|
+
#lastAmbient;
|
|
34
45
|
/** A navigation came after the last captured step — see markNavigated. */
|
|
35
46
|
#navigatedSinceStep = false;
|
|
36
|
-
|
|
47
|
+
/** Tabs with network mocks installed now, keyed by session ('' for none named). See markMocked. */
|
|
48
|
+
#mocked = new Set();
|
|
49
|
+
/** `byHarness`: whether the step being captured was driven by the Harness, which tapes its own. */
|
|
50
|
+
constructor(byHarness = () => false) {
|
|
51
|
+
this.byHarness = byHarness;
|
|
52
|
+
}
|
|
53
|
+
start(name, cursor, startPath, session, document) {
|
|
37
54
|
const openedOver = new Map();
|
|
38
|
-
for (const [outer, rec] of this.#
|
|
55
|
+
for (const [outer, rec] of this.#targets(session))
|
|
39
56
|
openedOver.set(outer, rec.steps.length);
|
|
40
57
|
this.#active.set(name, {
|
|
41
58
|
cursor,
|
|
42
59
|
steps: [],
|
|
43
60
|
openedOver,
|
|
44
61
|
...(startPath === undefined ? {} : { startPath }),
|
|
62
|
+
...(session === undefined ? {} : { session }),
|
|
63
|
+
...(document === undefined ? {} : { document }),
|
|
45
64
|
});
|
|
46
65
|
}
|
|
66
|
+
/** The open recordings a step from `session` belongs to. See ActiveRecording.session. */
|
|
67
|
+
#targets(session) {
|
|
68
|
+
return [...this.#active].filter(([, rec]) => rec.session === undefined || session === undefined || rec.session === session);
|
|
69
|
+
}
|
|
47
70
|
isRecording(name) {
|
|
48
71
|
return this.#active.has(name);
|
|
49
72
|
}
|
|
@@ -68,23 +91,44 @@ export class RecordingStore {
|
|
|
68
91
|
* Opened lazily on the first step rather than in the constructor: a store that never records
|
|
69
92
|
* anything should not carry an empty tape, and "did anything happen at all" stays answerable.
|
|
70
93
|
*/
|
|
71
|
-
|
|
94
|
+
/**
|
|
95
|
+
* Whether a tab has network mocks installed from now on. Each ambient step on it is marked while
|
|
96
|
+
* they are, so the journey it belongs to is not auto-saved as a flow (#1459).
|
|
97
|
+
*/
|
|
98
|
+
markMocked(session, active) {
|
|
99
|
+
if (active)
|
|
100
|
+
this.#mocked.add(session ?? '');
|
|
101
|
+
else
|
|
102
|
+
this.#mocked.delete(session ?? '');
|
|
103
|
+
}
|
|
104
|
+
capture(step, route, session) {
|
|
72
105
|
this.#navigatedSinceStep = false;
|
|
73
|
-
|
|
74
|
-
|
|
106
|
+
const mocked = this.#mocked.has(session ?? '');
|
|
107
|
+
const ambient = ambientRecordingOf(session);
|
|
108
|
+
if (!this.#active.has(ambient)) {
|
|
109
|
+
this.#active.set(ambient, {
|
|
75
110
|
cursor: 0,
|
|
76
111
|
steps: [],
|
|
77
112
|
openedOver: new Map(),
|
|
113
|
+
...(session === undefined ? {} : { session }),
|
|
78
114
|
});
|
|
79
115
|
}
|
|
80
|
-
|
|
116
|
+
this.#lastAmbient = ambient;
|
|
117
|
+
for (const [name, rec] of this.#targets(session)) {
|
|
118
|
+
// Another tab's tape is that tab's journey, whatever else this step belongs to.
|
|
119
|
+
if (isAmbient(name) && name !== ambient)
|
|
120
|
+
continue;
|
|
81
121
|
// The ambient tape is opened by the system and closed by nobody, so it is the one recording
|
|
82
122
|
// with no human deciding when it has seen enough. Bounded here rather than left to grow for
|
|
83
123
|
// the length of a daemon's life. Appending STOPS at the cap instead of dropping the oldest: a
|
|
84
124
|
// flow replays from its FIRST step, so a tape missing its beginning is not a shorter journey,
|
|
85
125
|
// it is a different one that starts in a state nothing established. A recording somebody
|
|
86
126
|
// opened on purpose is not capped — they said when it starts and they say when it stops.
|
|
87
|
-
if (
|
|
127
|
+
if (isAmbient(name) && rec.steps.length >= AMBIENT_STEP_CAP)
|
|
128
|
+
continue;
|
|
129
|
+
// The Harness saves its own recordings. Taping its steps too saved every drive twice: once as
|
|
130
|
+
// the Harness's flow and again, at session end, as a `drive-*` copy with a guessed name.
|
|
131
|
+
if (isAmbient(name) && this.byHarness())
|
|
88
132
|
continue;
|
|
89
133
|
// A step nobody marked ended where the next one began.
|
|
90
134
|
const previous = rec.steps.at(-1);
|
|
@@ -94,7 +138,13 @@ export class RecordingStore {
|
|
|
94
138
|
// The route rides on the AMBIENT tape only: a recording somebody opened deliberately is
|
|
95
139
|
// already one journey by construction, and stamping a route on its steps would change what a
|
|
96
140
|
// deliberate recording contains.
|
|
97
|
-
rec.steps.push(
|
|
141
|
+
rec.steps.push(isAmbient(name) && (route !== undefined || mocked)
|
|
142
|
+
? {
|
|
143
|
+
...step,
|
|
144
|
+
...(route === undefined ? {} : { route }),
|
|
145
|
+
...(mocked ? { mocked: true } : {}),
|
|
146
|
+
}
|
|
147
|
+
: step);
|
|
98
148
|
}
|
|
99
149
|
}
|
|
100
150
|
/**
|
|
@@ -104,13 +154,20 @@ export class RecordingStore {
|
|
|
104
154
|
* reached the recorder — only the act tools called `capture` — so the flow kept the click and lost
|
|
105
155
|
* the proof. What the step already declared is kept; the new check joins it under `allOf`.
|
|
106
156
|
*/
|
|
107
|
-
attachExpect(expect) {
|
|
157
|
+
attachExpect(expect, session) {
|
|
108
158
|
if (this.#navigatedSinceStep)
|
|
109
159
|
return;
|
|
110
|
-
|
|
160
|
+
const mocked = this.#mocked.has(session ?? '');
|
|
161
|
+
for (const [name, rec] of this.#targets(session)) {
|
|
162
|
+
if (isAmbient(name) && name !== ambientRecordingOf(session))
|
|
163
|
+
continue;
|
|
111
164
|
const last = rec.steps.at(-1);
|
|
112
165
|
if (last === undefined)
|
|
113
166
|
continue;
|
|
167
|
+
// A proof read while mocks are active rests on mocked responses even when the act before it
|
|
168
|
+
// ran unmocked, so the ambient step it joins is marked too (#1459).
|
|
169
|
+
if (mocked && isAmbient(name))
|
|
170
|
+
last.mocked = true;
|
|
114
171
|
const held = last.expect;
|
|
115
172
|
last.expect =
|
|
116
173
|
held === undefined
|
|
@@ -128,16 +185,36 @@ export class RecordingStore {
|
|
|
128
185
|
markNavigated() {
|
|
129
186
|
this.#navigatedSinceStep = true;
|
|
130
187
|
}
|
|
188
|
+
/**
|
|
189
|
+
* Take the expectation off the ambient tape's last step, because the verdict on it came back no.
|
|
190
|
+
*
|
|
191
|
+
* A step is captured at dispatch, before anything is judged, so a claim that turned out false is
|
|
192
|
+
* already on the tape as that step's `expect`. Cut into a journey it becomes a flow that is red for
|
|
193
|
+
* ever, on an expectation nobody but the agent's wrong guess made. The failure is not lost: it is
|
|
194
|
+
* filed as a capsule, the artifact built for "this should hold and does not". The ACTION stays,
|
|
195
|
+
* since the steps after it ran on the page it produced. A recording somebody opened deliberately
|
|
196
|
+
* is left as they drove it.
|
|
197
|
+
*/
|
|
198
|
+
unassertLast() {
|
|
199
|
+
const tape = this.#lastAmbient === undefined ? undefined : this.#active.get(this.#lastAmbient);
|
|
200
|
+
const last = tape?.steps.at(-1);
|
|
201
|
+
if (tape === undefined || last === undefined || last.expect === undefined)
|
|
202
|
+
return;
|
|
203
|
+
const { expect: _dropped, ...kept } = last;
|
|
204
|
+
tape.steps[tape.steps.length - 1] = kept;
|
|
205
|
+
}
|
|
131
206
|
/**
|
|
132
207
|
* The page the step just captured ended on, once its action settled.
|
|
133
208
|
*
|
|
134
209
|
* Fills only a step that has none, so calling it after an action that captured nothing leaves the
|
|
135
210
|
* previous step's own answer alone.
|
|
136
211
|
*/
|
|
137
|
-
markEnded(page) {
|
|
212
|
+
markEnded(page, session) {
|
|
138
213
|
if (page === undefined)
|
|
139
214
|
return;
|
|
140
|
-
for (const rec of this.#
|
|
215
|
+
for (const [name, rec] of this.#targets(session)) {
|
|
216
|
+
if (isAmbient(name) && name !== ambientRecordingOf(session))
|
|
217
|
+
continue;
|
|
141
218
|
const last = rec.steps.at(-1);
|
|
142
219
|
if (last !== undefined && last.endPage === undefined)
|
|
143
220
|
last.endPage = page;
|
|
@@ -182,7 +259,12 @@ export class RecordingStore {
|
|
|
182
259
|
return this.#compiled.get(name);
|
|
183
260
|
}
|
|
184
261
|
active() {
|
|
185
|
-
|
|
262
|
+
// One tab's tape is that tab's: the list names what somebody opened, and the plain tape as before.
|
|
263
|
+
return [...this.#active.keys()].filter((name) => !name.startsWith(`${AMBIENT_RECORDING}:`));
|
|
264
|
+
}
|
|
265
|
+
/** The ambient tape of one tab (or of steps no tab named), taken: what its session end saves. */
|
|
266
|
+
takeAmbient(session) {
|
|
267
|
+
return this.stop(ambientRecordingOf(session));
|
|
186
268
|
}
|
|
187
269
|
/**
|
|
188
270
|
* Names of recordings that have been STOPPED and compiled.
|