@reticlehq/server 3.7.0 → 3.8.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +59 -68
- package/bin/reticle.js +9 -2
- package/dist/command/cli/adhoc-suite.js +1 -1
- package/dist/command/cli/adhoc-verdict.d.ts +12 -0
- package/dist/command/cli/adhoc-verdict.js +62 -4
- package/dist/command/cli/answers/gate-hook-message.d.ts +2 -0
- package/dist/command/cli/answers/gate-hook-message.js +5 -1
- package/dist/command/cli/auth/cloud-session.d.ts +11 -19
- package/dist/command/cli/auth/cloud-session.js +23 -0
- package/dist/command/cli/auth/device-flow.d.ts +3 -37
- package/dist/command/cli/cli-doctor.js +66 -21
- package/dist/command/cli/cli-flow-commands.js +53 -11
- package/dist/command/cli/cli-kill.d.ts +8 -0
- package/dist/command/cli/cli-kill.js +43 -3
- package/dist/command/cli/cli-parse-feedback.d.ts +4 -0
- package/dist/command/cli/cli-parse-feedback.js +13 -1
- package/dist/command/cli/cli-parse-grammar.d.ts +1 -2
- package/dist/command/cli/cli-parse-grammar.js +1 -6
- package/dist/command/cli/cli-parse-serve.d.ts +24 -0
- package/dist/command/cli/cli-parse-serve.js +124 -0
- package/dist/command/cli/cli-parse.d.ts +12 -11
- package/dist/command/cli/cli-parse.js +100 -123
- package/dist/command/cli/cli-usage.d.ts +0 -11
- package/dist/command/cli/cli-usage.js +43 -16
- package/dist/command/cli/cli-verify.d.ts +1 -1
- package/dist/command/cli/cli-verify.js +29 -14
- package/dist/command/cli/cloud-cli.js +27 -9
- package/dist/command/cli/cloud-kit.js +3 -3
- package/dist/command/cli/cloud-link.d.ts +1 -20
- package/dist/command/cli/cloud-link.js +2 -0
- package/dist/command/cli/cloud-login.d.ts +6 -2
- package/dist/command/cli/cloud-login.js +13 -41
- package/dist/command/cli/config/checkout.d.ts +10 -0
- package/dist/command/cli/config/checkout.js +78 -0
- package/dist/command/cli/doctor/doctor-agent-link.d.ts +23 -0
- package/dist/command/cli/doctor/doctor-agent-link.js +28 -0
- package/dist/command/cli/doctor/doctor-coverage-line.js +1 -7
- package/dist/command/cli/doctor/doctor-rows.d.ts +4 -0
- package/dist/command/cli/doctor/doctor-rows.js +4 -0
- package/dist/command/cli/drive/drive-attach.d.ts +5 -0
- package/dist/command/cli/drive/drive-attach.js +21 -1
- package/dist/command/cli/hook/codex-transcript.d.ts +20 -0
- package/dist/command/cli/hook/codex-transcript.js +224 -0
- package/dist/command/cli/hook/episode-structure.d.ts +24 -0
- package/dist/command/cli/hook/episode-structure.js +138 -0
- package/dist/command/cli/hook/hook-command.d.ts +9 -0
- package/dist/command/cli/hook/hook-command.js +211 -0
- package/dist/command/cli/hook/hook-fast.d.ts +31 -0
- package/dist/command/cli/hook/hook-fast.js +136 -0
- package/dist/command/cli/hook/prompt-hook.d.ts +30 -0
- package/dist/command/cli/hook/prompt-hook.js +199 -0
- package/dist/command/cli/hook/tool-hook.d.ts +21 -0
- package/dist/command/cli/hook/tool-hook.js +259 -0
- package/dist/command/cli/launch/cli-launch.d.ts +2 -0
- package/dist/command/cli/launch/cli-launch.js +22 -2
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +28 -2
- package/dist/command/cli/mcp-command.d.ts +9 -0
- package/dist/command/cli/mcp-command.js +127 -41
- package/dist/command/cli/open-navigate.d.ts +43 -0
- package/dist/command/cli/open-navigate.js +85 -0
- package/dist/command/cli/ports/port-holder.d.ts +16 -4
- package/dist/command/cli/ports/port-holder.js +58 -12
- package/dist/command/cli/ports/resolve/cli-port.js +18 -2
- package/dist/command/cli/project-name.d.ts +1 -7
- package/dist/command/cli/project-name.js +1 -0
- package/dist/command/cli/report-command.d.ts +8 -2
- package/dist/command/cli/report-command.js +95 -18
- package/dist/command/cli/status-fields.d.ts +9 -2
- package/dist/command/cli/status-fields.js +148 -4
- package/dist/command/cli/try-command.d.ts +3 -4
- package/dist/command/cli/try-command.js +6 -11
- package/dist/command/cli/verify-results.d.ts +4 -1
- package/dist/command/cli/verify-results.js +3 -1
- package/dist/command/cli.d.ts +1 -7
- package/dist/command/cli.js +79 -160
- package/dist/command/daemon/daemon-resilience.d.ts +6 -1
- package/dist/command/daemon/daemon-resilience.js +31 -18
- package/dist/command/daemon/daemon.d.ts +11 -0
- package/dist/command/daemon/daemon.js +70 -2
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +2 -0
- package/dist/command/daemon/lifetime/daemon-usefulness.js +13 -2
- package/dist/command/daemon/wake-decision.js +4 -2
- package/dist/command/daemon/win32-escape.d.ts +32 -0
- package/dist/command/daemon/win32-escape.js +119 -0
- package/dist/command/setup/agent-configs.d.ts +9 -0
- package/dist/command/setup/agent-configs.js +9 -0
- package/dist/command/setup/auto-approve.d.ts +10 -3
- package/dist/command/setup/auto-approve.js +51 -3
- package/dist/command/setup/bringup/dev-server-files.d.ts +1 -9
- package/dist/command/setup/bringup/dev-server-wait.js +5 -1
- package/dist/command/setup/bringup/ensure-daemon.js +4 -7
- package/dist/command/setup/init/init-host.js +6 -0
- package/dist/command/setup/init/init-port.js +5 -4
- package/dist/command/setup/init/init-runtime.js +7 -1
- package/dist/command/setup/node-effects.d.ts +8 -0
- package/dist/command/setup/node-effects.js +36 -4
- package/dist/command/setup/probe/dev-port.d.ts +26 -0
- package/dist/command/setup/probe/dev-port.js +117 -0
- package/dist/command/setup/probe/page-probe.d.ts +1 -1
- package/dist/command/setup/probe/page-probe.js +11 -3
- package/dist/command/setup/remaining-steps.d.ts +0 -7
- package/dist/command/setup/remaining-steps.js +3 -2
- package/dist/command/setup/run-setup.d.ts +11 -0
- package/dist/command/setup/run-setup.js +33 -5
- package/dist/command/setup/setup-command.d.ts +2 -0
- package/dist/command/setup/setup-command.js +22 -4
- package/dist/command/update/updater.d.ts +1 -6
- package/dist/command/update/updater.js +4 -5
- package/dist/command/update/version-seen.d.ts +24 -0
- package/dist/command/update/version-seen.js +65 -0
- package/dist/command/version/peer-announce.d.ts +9 -1
- package/dist/command/version/peer-announce.js +25 -2
- package/dist/command/version/sdk-fix.d.ts +5 -6
- package/dist/command/version/sdk-fix.js +17 -32
- package/dist/command/version/version-skew.d.ts +16 -1
- package/dist/command/version/version-skew.js +84 -10
- package/dist/features/crawl/crawl-tools.js +2 -2
- package/dist/features/crawl/crawl.js +2 -0
- package/dist/features/exhaust/ledger.d.ts +15 -96
- package/dist/features/exhaust/ledger.js +3 -3
- package/dist/features/harness/drive-runs.d.ts +28 -4
- package/dist/features/harness/drive-runs.js +99 -7
- package/dist/features/harness/drivers.d.ts +1 -1
- package/dist/features/harness/drivers.js +1 -1
- package/dist/features/harness/harness.d.ts +5 -0
- package/dist/features/harness/harness.js +24 -12
- package/dist/features/harness/platform/platform-drives.d.ts +7 -1
- package/dist/features/harness/platform/platform-drives.js +12 -7
- package/dist/features/harness/platform/refusal.d.ts +1 -1
- package/dist/features/harness/platform/refusal.js +4 -4
- package/dist/features/harness/platform/remote-drive.js +70 -28
- package/dist/features/harness/platform/server-driver.js +22 -1
- package/dist/features/harness/platform-config.d.ts +1 -10
- package/dist/features/harness/platform-config.js +0 -20
- package/dist/features/license/license.d.ts +2 -14
- package/dist/features/visual/step-shots.d.ts +33 -1
- package/dist/features/visual/step-shots.js +155 -1
- package/dist/features/visual/visual-tools.js +12 -4
- package/dist/hooks/coding-agents.d.ts +6 -0
- package/dist/hooks/coding-agents.js +24 -3
- package/dist/hooks/episode-stamp.d.ts +32 -0
- package/dist/hooks/episode-stamp.js +61 -0
- package/dist/hooks/hook-commands.js +19 -9
- package/dist/index.d.ts +5 -1
- package/dist/index.js +66 -24
- package/dist/judgement/app-graph/journal-steps.d.ts +8 -0
- package/dist/judgement/app-graph/journal-steps.js +92 -0
- package/dist/judgement/capsule/capsule-store.d.ts +2 -39
- package/dist/judgement/domain/domain-model.js +1 -10
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/runs/artifact/run-store.d.ts +28 -8
- package/dist/judgement/runs/artifact/run-store.js +153 -28
- package/dist/judgement/runs/default-run-id.d.ts +3 -1
- package/dist/judgement/runs/default-run-id.js +15 -3
- package/dist/judgement/runs/drive-run.d.ts +3 -3
- package/dist/judgement/runs/drive-run.js +11 -7
- package/dist/judgement/runs/run-ledger.d.ts +21 -0
- package/dist/judgement/runs/run-ledger.js +143 -0
- package/dist/judgement/runs/runner-port.d.ts +1 -1
- package/dist/judgement/runs/runner-port.js +8 -2
- package/dist/judgement/runs/verification-sync.d.ts +4 -3
- package/dist/judgement/runs/verification-sync.js +27 -5
- package/dist/language/flows/affected-tools.js +2 -1
- package/dist/language/flows/annotate-notes/annotate.js +8 -3
- package/dist/language/flows/annotate-tools.js +1 -1
- package/dist/language/flows/change/affected.d.ts +8 -0
- package/dist/language/flows/change/affected.js +20 -7
- package/dist/language/flows/decision.js +19 -4
- package/dist/language/flows/fields/flow-secret-field.d.ts +9 -0
- package/dist/language/flows/fields/flow-secret-field.js +67 -5
- package/dist/language/flows/flow-anchor.d.ts +5 -0
- package/dist/language/flows/flow-anchor.js +4 -0
- package/dist/language/flows/flow-cross-step.d.ts +7 -1
- package/dist/language/flows/flow-cross-step.js +9 -0
- package/dist/language/flows/flow-expect-grammar.js +15 -10
- package/dist/language/flows/flow-intent.js +6 -1
- package/dist/language/flows/flow-journey.d.ts +8 -0
- package/dist/language/flows/flow-journey.js +13 -0
- package/dist/language/flows/flow-lease.d.ts +27 -0
- package/dist/language/flows/flow-lease.js +59 -0
- package/dist/language/flows/flow-replay-run.d.ts +1 -87
- package/dist/language/flows/flow-replay-run.js +111 -310
- package/dist/language/flows/flow-replay.js +21 -19
- package/dist/language/flows/flow-replayable.d.ts +38 -0
- package/dist/language/flows/flow-replayable.js +179 -0
- package/dist/language/flows/flow-start-path.d.ts +108 -0
- package/dist/language/flows/flow-start-path.js +313 -0
- package/dist/language/flows/flow-step-runners.d.ts +23 -2
- package/dist/language/flows/flow-step-runners.js +191 -32
- package/dist/language/flows/flow-store-for-session.d.ts +8 -1
- package/dist/language/flows/flow-store-for-session.js +6 -0
- package/dist/language/flows/flow-tools.d.ts +2 -23
- package/dist/language/flows/flow-tools.js +63 -113
- package/dist/language/flows/flows.d.ts +4 -6
- package/dist/language/flows/flows.js +90 -15
- package/dist/language/flows/heal-run.d.ts +10 -4
- package/dist/language/flows/heal-run.js +26 -9
- package/dist/language/flows/recording/flake.d.ts +3 -27
- package/dist/language/flows/recording/flake.js +1 -1
- package/dist/language/flows/recording/recording-backtrack.js +1 -4
- package/dist/language/flows/recording/tape/recordings.d.ts +11 -1
- package/dist/language/flows/recording/tape/recordings.js +9 -3
- package/dist/language/flows/replay.d.ts +25 -5
- package/dist/language/flows/replay.js +83 -16
- package/dist/language/flows/stores/assertion-tiers-store.js +1 -1
- package/dist/language/flows/suite/coverage.d.ts +9 -0
- package/dist/language/flows/suite/coverage.js +12 -1
- package/dist/language/flows/suite-selection.d.ts +25 -0
- package/dist/language/flows/suite-selection.js +41 -9
- package/dist/machine/git-tracks.d.ts +6 -0
- package/dist/machine/git-tracks.js +36 -0
- package/dist/memory/cloud/background-sync.d.ts +25 -0
- package/dist/memory/cloud/background-sync.js +79 -0
- package/dist/memory/cloud/cloud-config.d.ts +12 -1
- package/dist/memory/cloud/cloud-config.js +39 -13
- package/dist/memory/cloud/cloud-sync.d.ts +3 -24
- package/dist/memory/cloud/cloud-sync.js +5 -2
- package/dist/memory/cloud/harness-config.d.ts +0 -7
- package/dist/memory/cloud/memory-scope.d.ts +19 -0
- package/dist/memory/cloud/memory-scope.js +48 -0
- package/dist/memory/cloud/sync-answer.d.ts +43 -0
- package/dist/memory/cloud/sync-answer.js +42 -0
- package/dist/memory/cloud/sync-cycle.d.ts +40 -10
- package/dist/memory/cloud/sync-cycle.js +97 -144
- package/dist/memory/cloud/sync-daemon.d.ts +50 -3
- package/dist/memory/cloud/sync-daemon.js +473 -83
- package/dist/memory/cloud/sync-describe.d.ts +28 -0
- package/dist/memory/cloud/sync-describe.js +92 -0
- package/dist/memory/cloud/sync-disk.d.ts +9 -1
- package/dist/memory/cloud/sync-disk.js +137 -33
- package/dist/memory/cloud/sync-flow-versions.d.ts +26 -0
- package/dist/memory/cloud/sync-flow-versions.js +42 -0
- package/dist/memory/impact/impact-store.js +32 -15
- package/dist/memory/intent/intent-shard.d.ts +41 -266
- package/dist/memory/intent/intent-tools.js +20 -61
- package/dist/memory/intent/record-request.d.ts +27 -0
- package/dist/memory/intent/record-request.js +88 -0
- package/dist/memory/intent/settled-words.js +9 -1
- package/dist/memory/journal/drive-flow.d.ts +3 -0
- package/dist/memory/journal/drive-flow.js +11 -41
- package/dist/memory/journal/envelope-store.js +1 -1
- package/dist/memory/journal/envelope.d.ts +6 -154
- package/dist/memory/journal/episode-log.d.ts +107 -0
- package/dist/memory/journal/episode-log.js +302 -0
- package/dist/memory/journal/journal-recorder.d.ts +7 -0
- package/dist/memory/journal/journal-recorder.js +22 -9
- package/dist/memory/journal/on-disk/ambient-file.d.ts +1 -7
- package/dist/memory/journal/on-disk/ambient-file.js +1 -1
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +24 -3
- package/dist/memory/journal/on-disk/workspace-gitignore.js +38 -7
- package/dist/memory/journal/on-disk/workspace-tiers.js +7 -0
- package/dist/memory/journal/self-observation.js +3 -1
- package/dist/memory/journal/session-end.js +23 -9
- package/dist/memory/journal/session-journal.js +39 -20
- package/dist/memory/project/artifact-root-resolver.d.ts +14 -1
- package/dist/memory/project/artifact-root-resolver.js +68 -23
- package/dist/memory/project/artifact-root.d.ts +17 -3
- package/dist/memory/project/artifact-root.js +47 -9
- package/dist/memory/project/fs/fs-port.d.ts +5 -0
- package/dist/memory/project/fs/fs-port.js +13 -0
- package/dist/memory/project/learned-routes.d.ts +3 -4
- package/dist/memory/project/learned-routes.js +3 -11
- package/dist/memory/project/link-directory.js +5 -2
- package/dist/memory/project/root-claims.d.ts +3 -1
- package/dist/memory/project/root-claims.js +41 -7
- package/dist/memory/project/session-root.d.ts +1 -1
- package/dist/memory/project/session-root.js +1 -15
- package/dist/memory/project/sync-status.js +5 -6
- package/dist/memory/recall/memory-tools.js +2 -2
- package/dist/memory/recall/platform-memory.d.ts +3 -1
- package/dist/memory/recall/platform-memory.js +9 -1
- package/dist/memory/recall/project-memory.js +15 -19
- package/dist/portal/bridge/auth-failure-reason.d.ts +13 -0
- package/dist/portal/bridge/auth-failure-reason.js +19 -0
- package/dist/portal/bridge/bridge.d.ts +19 -4
- package/dist/portal/bridge/bridge.js +150 -177
- package/dist/portal/bridge/harness-request.d.ts +15 -0
- package/dist/portal/bridge/harness-request.js +19 -0
- package/dist/portal/bridge/origin/origin-follow.d.ts +46 -0
- package/dist/portal/bridge/origin/origin-follow.js +110 -0
- package/dist/portal/bridge/pairing-token.d.ts +6 -0
- package/dist/portal/bridge/pairing-token.js +47 -16
- package/dist/portal/bridge/protocol-skew.d.ts +27 -2
- package/dist/portal/bridge/protocol-skew.js +66 -2
- package/dist/portal/bridge/session-nonces.d.ts +46 -0
- package/dist/portal/bridge/session-nonces.js +72 -0
- package/dist/portal/input/viewport-tools.d.ts +31 -0
- package/dist/portal/input/viewport-tools.js +106 -15
- package/dist/portal/pool/bounded-close.d.ts +23 -0
- package/dist/portal/pool/bounded-close.js +38 -0
- package/dist/portal/pool/browser-pool.d.ts +44 -39
- package/dist/portal/pool/browser-pool.js +247 -95
- package/dist/portal/pool/context-permissions.d.ts +9 -1
- package/dist/portal/pool/context-permissions.js +26 -0
- package/dist/portal/pool/lease-emulation.d.ts +37 -0
- package/dist/portal/pool/lease-emulation.js +29 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +74 -7
- package/dist/portal/pool/pool-contract.d.ts +23 -1
- package/dist/portal/pool/pool-lease.d.ts +128 -0
- package/dist/portal/pool/pool-lease.js +49 -0
- package/dist/portal/pool/zero-install.d.ts +8 -1
- package/dist/portal/pool/zero-install.js +24 -2
- package/dist/portal/production/production-activation.d.ts +136 -0
- package/dist/portal/production/production-activation.js +173 -0
- package/dist/portal/production/production-drive.d.ts +52 -0
- package/dist/portal/production/production-drive.js +301 -0
- package/dist/portal/production/production-hello.d.ts +23 -0
- package/dist/portal/production/production-hello.js +23 -0
- package/dist/portal/realm/web-realm.js +42 -15
- package/dist/portal/session/control-envelope.d.ts +1 -1
- package/dist/portal/session/dev-server/served-document.d.ts +0 -5
- package/dist/portal/session/dev-server/served-document.js +6 -8
- package/dist/portal/session/facts/handshake-facts.d.ts +8 -1
- package/dist/portal/session/first-run-wiring.d.ts +3 -36
- package/dist/portal/session/first-run-wiring.js +10 -103
- package/dist/portal/session/live-control-tools.js +61 -19
- package/dist/portal/session/no-session-next-action.d.ts +11 -0
- package/dist/portal/session/no-session-next-action.js +40 -15
- package/dist/portal/session/no-session-watch.d.ts +7 -0
- package/dist/portal/session/no-session-watch.js +67 -23
- package/dist/portal/session/output-budget.d.ts +10 -0
- package/dist/portal/session/output-budget.js +16 -0
- package/dist/portal/session/presence/session-lease.d.ts +2 -0
- package/dist/portal/session/presence/session-lease.js +8 -0
- package/dist/portal/session/recorded-gaps.d.ts +15 -11
- package/dist/portal/session/recorded-gaps.js +39 -18
- package/dist/portal/session/serving-directory.d.ts +24 -2
- package/dist/portal/session/serving-directory.js +93 -5
- package/dist/portal/session/session-info.d.ts +26 -0
- package/dist/portal/session/session-info.js +20 -0
- package/dist/portal/session/session-manager.d.ts +35 -3
- package/dist/portal/session/session-manager.js +69 -14
- package/dist/portal/session/session-successor.js +1 -9
- package/dist/portal/session/session-tools.js +22 -4
- package/dist/portal/session/session.d.ts +10 -10
- package/dist/portal/session/session.js +37 -29
- package/dist/portal/session/zero-install-first-call.d.ts +7 -2
- package/dist/portal/session/zero-install-first-call.js +43 -20
- package/dist/start-wiring.d.ts +2 -2
- package/dist/start-wiring.js +17 -3
- package/dist/status-payload.d.ts +11 -1
- package/dist/status-payload.js +7 -1
- package/dist/surface/agent-presence-grace.d.ts +11 -0
- package/dist/surface/agent-presence-grace.js +34 -0
- package/dist/surface/http-server.d.ts +12 -1
- package/dist/surface/http-server.js +64 -15
- package/dist/surface/mcp/faults/mcp-outage.d.ts +12 -2
- package/dist/surface/mcp/faults/mcp-outage.js +19 -1
- package/dist/surface/mcp/mcp-proxy.d.ts +17 -74
- package/dist/surface/mcp/mcp-proxy.js +194 -267
- package/dist/surface/mcp/mcp.d.ts +20 -3
- package/dist/surface/mcp/mcp.js +88 -25
- package/dist/surface/mcp/proxy/drive-calls.d.ts +44 -0
- package/dist/surface/mcp/proxy/drive-calls.js +114 -5
- package/dist/surface/mcp/proxy/proxy-boot.d.ts +11 -0
- package/dist/surface/mcp/proxy/proxy-boot.js +1 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +6 -0
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +14 -1
- package/dist/surface/mcp/proxy/proxy-handshake.d.ts +34 -2
- package/dist/surface/mcp/proxy/proxy-handshake.js +76 -8
- package/dist/surface/mcp/server-instructions.js +35 -16
- package/dist/surface/mcp/shared-params.d.ts +8 -0
- package/dist/surface/mcp/shared-params.js +15 -1
- package/dist/surface/mcp/sse-frame-parser.d.ts +11 -0
- package/dist/surface/mcp/sse-frame-parser.js +18 -0
- package/dist/surface/mcp/surface-vocabulary.d.ts +2 -0
- package/dist/surface/mcp/surface-vocabulary.js +13 -0
- package/dist/surface/mcp/tool-catalog-cache.d.ts +2 -0
- package/dist/surface/mcp/tool-catalog-cache.js +14 -4
- package/dist/surface/tools/account-tool.d.ts +4 -3
- package/dist/surface/tools/account-tool.js +20 -31
- package/dist/surface/tools/act/act-danger.d.ts +2 -0
- package/dist/surface/tools/act/act-danger.js +41 -14
- package/dist/surface/tools/act/act-observation.d.ts +11 -0
- package/dist/surface/tools/act/act-observation.js +33 -0
- package/dist/surface/tools/act/act-preflight.js +10 -3
- package/dist/surface/tools/act/act-sequence-retry.js +2 -1
- package/dist/surface/tools/act/act-target.js +19 -5
- package/dist/surface/tools/act/durable.js +1 -1
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +9 -7
- package/dist/surface/tools/act/navigation/navigate-arrival.js +11 -14
- package/dist/surface/tools/act/unsettled-find.d.ts +36 -0
- package/dist/surface/tools/act/unsettled-find.js +71 -0
- package/dist/surface/tools/act-sequence-tool.js +53 -24
- package/dist/surface/tools/act-tools.d.ts +2 -3
- package/dist/surface/tools/act-tools.js +49 -47
- package/dist/surface/tools/agent/compact-envelope.d.ts +2 -2
- package/dist/surface/tools/agent/for-the-agent.js +41 -3
- package/dist/surface/tools/assert/assert-grade.js +8 -3
- package/dist/surface/tools/assert/assert-verdict.js +4 -2
- package/dist/surface/tools/browser-tools.js +7 -4
- package/dist/surface/tools/chat-drives.js +50 -25
- package/dist/surface/tools/coverage-tools.js +1 -1
- package/dist/surface/tools/dynamic-tools.d.ts +8 -0
- package/dist/surface/tools/dynamic-tools.js +89 -34
- package/dist/surface/tools/empty-session-list.d.ts +18 -25
- package/dist/surface/tools/empty-session-list.js +67 -38
- package/dist/surface/tools/error-recovery.d.ts +17 -7
- package/dist/surface/tools/error-recovery.js +53 -20
- package/dist/surface/tools/explore-tools.d.ts +10 -0
- package/dist/surface/tools/explore-tools.js +72 -19
- package/dist/surface/tools/feedback-tools.js +23 -2
- package/dist/surface/tools/gap-novelty.d.ts +6 -0
- package/dist/surface/tools/gap-novelty.js +9 -0
- package/dist/surface/tools/gaps/capability-absences.js +4 -3
- package/dist/surface/tools/harness-explore.d.ts +1 -1
- package/dist/surface/tools/harness-explore.js +6 -4
- package/dist/surface/tools/harness-gate.d.ts +43 -21
- package/dist/surface/tools/harness-gate.js +55 -81
- package/dist/surface/tools/harness-script.d.ts +2 -0
- package/dist/surface/tools/harness-script.js +11 -6
- package/dist/surface/tools/harness-toolset.js +3 -4
- package/dist/surface/tools/invoke-tool.d.ts +0 -8
- package/dist/surface/tools/invoke-tool.js +164 -178
- package/dist/surface/tools/lease-hint.d.ts +9 -0
- package/dist/surface/tools/lease-hint.js +22 -3
- package/dist/surface/tools/lease-permissions.d.ts +1 -1
- package/dist/surface/tools/lease-readiness.d.ts +55 -0
- package/dist/surface/tools/lease-readiness.js +150 -2
- package/dist/surface/tools/lease-tools.d.ts +3 -75
- package/dist/surface/tools/lease-tools.js +124 -188
- package/dist/surface/tools/map-tools.d.ts +20 -0
- package/dist/surface/tools/map-tools.js +145 -0
- package/dist/surface/tools/merge-tools.js +11 -7
- package/dist/surface/tools/next-step.js +6 -3
- package/dist/surface/tools/observe-tools.js +46 -35
- package/dist/surface/tools/platform-moment.d.ts +3 -12
- package/dist/surface/tools/platform-moment.js +12 -24
- package/dist/surface/tools/read/complete-snapshot.d.ts +7 -1
- package/dist/surface/tools/read/complete-snapshot.js +13 -2
- package/dist/surface/tools/read/query-paginate.js +6 -0
- package/dist/surface/tools/read/query-shape.d.ts +9 -0
- package/dist/surface/tools/read/query-shape.js +15 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.d.ts +1 -0
- package/dist/surface/tools/read/snapshot-unmounted-note.js +73 -0
- package/dist/surface/tools/read-tools.js +5 -5
- package/dist/surface/tools/real-input-attempt.d.ts +11 -0
- package/dist/surface/tools/real-input-attempt.js +206 -38
- package/dist/surface/tools/reconcile-tools.js +21 -8
- package/dist/surface/tools/reticle-result.d.ts +3 -0
- package/dist/surface/tools/reticle-result.js +8 -1
- package/dist/surface/tools/run-report.d.ts +22 -0
- package/dist/surface/tools/run-report.js +141 -0
- package/dist/surface/tools/session-ports.d.ts +57 -0
- package/dist/surface/tools/session-ports.js +102 -0
- package/dist/surface/tools/tool-kit.d.ts +58 -4
- package/dist/surface/tools/tool-kit.js +140 -6
- package/dist/surface/tools/tool-surface.d.ts +2 -0
- package/dist/surface/tools/tool-surface.js +45 -0
- package/dist/surface/tools/tools.js +49 -87
- package/dist/telemetry/automation-hint.d.ts +5 -0
- package/dist/telemetry/automation-hint.js +7 -0
- package/dist/telemetry/cli-telemetry.d.ts +22 -0
- package/dist/telemetry/cli-telemetry.js +80 -11
- package/dist/telemetry/daemon-telemetry.d.ts +3 -1
- package/dist/telemetry/daemon-telemetry.js +9 -2
- package/dist/telemetry/feedback-cli.d.ts +1 -1
- package/dist/telemetry/feedback-cli.js +8 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/feedback.js +51 -4
- package/dist/telemetry/harness-run.d.ts +3 -3
- package/dist/telemetry/harness-run.js +18 -7
- package/dist/telemetry/hud-events.d.ts +1 -1
- package/dist/telemetry/hud-metrics.d.ts +6 -3
- package/dist/telemetry/hud-metrics.js +20 -8
- package/dist/telemetry/install-source.js +1 -1
- package/dist/telemetry/mcp-connection.d.ts +1 -1
- package/dist/telemetry/mcp-connection.js +21 -2
- package/dist/telemetry/onboarding-firsts.d.ts +6 -1
- package/dist/telemetry/onboarding-firsts.js +41 -1
- package/dist/telemetry/proxy-telemetry.d.ts +42 -0
- package/dist/telemetry/proxy-telemetry.js +70 -1
- package/dist/telemetry/session-metrics.d.ts +1 -3
- package/dist/telemetry/session-metrics.js +16 -12
- package/dist/telemetry/telemetry.d.ts +9 -1
- package/dist/telemetry/telemetry.js +16 -1
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +7 -1
- package/dist/wire-journal.js +12 -2
- package/docs/README.md +4 -2
- package/docs/actions.mdx +7 -6
- package/docs/adapters.md +2 -1
- package/docs/agent-cheatsheet.md +19 -5
- package/docs/architecture.md +13 -10
- package/docs/autodrive.md +6 -5
- package/docs/benchmarks.md +2 -2
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/affected.mdx +1 -1
- package/docs/cli/cloud.mdx +6 -6
- package/docs/cli/doctor.mdx +3 -1
- package/docs/cli/feedback.mdx +11 -7
- package/docs/cli/gate.mdx +1 -1
- package/docs/cli/help.mdx +1 -1
- package/docs/cli/init.mdx +20 -16
- package/docs/cli/mcp.mdx +5 -2
- package/docs/cli/open.mdx +5 -2
- package/docs/cli/report.mdx +1 -1
- package/docs/cli/restart.mdx +1 -1
- package/docs/cli/rollback.mdx +4 -4
- package/docs/cli/serve.mdx +7 -5
- package/docs/cli/setup.mdx +1 -1
- package/docs/cli/status.mdx +6 -2
- package/docs/cli/stop.mdx +3 -3
- package/docs/cli/telemetry.mdx +5 -1
- package/docs/cli/try.mdx +8 -8
- package/docs/cli/update.mdx +8 -5
- package/docs/cli/verify.mdx +12 -5
- package/docs/cli/version.mdx +1 -1
- package/docs/cli.mdx +10 -6
- package/docs/debugging.md +1 -1
- package/docs/deploy-checks.md +8 -6
- package/docs/desktop.mdx +14 -18
- package/docs/enterprise.md +6 -6
- package/docs/environment.mdx +5 -3
- package/docs/faq.mdx +9 -6
- package/docs/first-drive.md +19 -9
- package/docs/flows.md +3 -4
- package/docs/for-agents.md +1 -1
- package/docs/frameworks.mdx +34 -11
- package/docs/getting-started.md +46 -29
- package/docs/http-transport.md +2 -2
- package/docs/human-control.md +8 -8
- package/docs/index.mdx +2 -2
- package/docs/install-agentic.mdx +18 -19
- package/docs/install-manual.mdx +8 -4
- package/docs/integration-patterns.md +5 -5
- package/docs/multi-agent-testing.md +7 -5
- package/docs/packages/browser.mdx +34 -2
- package/docs/packages/core.mdx +2 -1
- package/docs/packages/electron.mdx +15 -3
- package/docs/packages/eslint-plugin.mdx +1 -1
- package/docs/packages/next.mdx +17 -5
- package/docs/packages/react.mdx +8 -1
- package/docs/packages/server.mdx +3 -3
- package/docs/packages/tauri.mdx +3 -3
- package/docs/packages/vite-plugin.mdx +1 -1
- package/docs/packages.mdx +19 -6
- package/docs/platform-integration.md +12 -4
- package/docs/predicates.mdx +18 -7
- package/docs/production-mode.md +108 -0
- package/docs/prompt-capture.md +99 -0
- package/docs/quickstart.mdx +14 -12
- package/docs/recipes.mdx +9 -8
- package/docs/required-checks.md +3 -2
- package/docs/skill-file.mdx +4 -3
- package/docs/skill-setup.md +2 -2
- package/docs/skill.md +62 -70
- package/docs/state-files.md +1 -0
- package/docs/state-management.mdx +11 -9
- package/docs/system-map.md +14 -13
- package/docs/telemetry.md +32 -24
- package/docs/testing.md +9 -5
- package/docs/tools/act-and-wait.mdx +17 -13
- package/docs/tools/act-sequence.mdx +40 -66
- package/docs/tools/act.mdx +7 -5
- package/docs/tools/assert.mdx +1 -1
- package/docs/tools/look.mdx +1 -1
- package/docs/tools/navigate.mdx +1 -1
- package/docs/tools/network.mdx +13 -11
- package/docs/tools/overview.mdx +3 -3
- package/docs/tools/query.mdx +3 -3
- package/docs/tools/session-and-feedback.mdx +9 -6
- package/docs/tools/sessions.mdx +7 -0
- package/docs/tools/snapshot.mdx +9 -7
- package/docs/tools/tools-and-run.mdx +11 -10
- package/docs/tools/verify.mdx +1 -1
- package/docs/troubleshooting.mdx +21 -9
- package/docs/usage.md +58 -43
- package/docs/use-cases.mdx +2 -2
- package/docs/vs-chrome-devtools-mcp.mdx +5 -5
- package/docs/vs-playwright-mcp.mdx +5 -4
- package/docs/what-is-recorded.md +12 -7
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +9 -12
- package/dist/command/dev/stale-issue-guard.d.ts +0 -34
- package/dist/command/dev/stale-issue-guard.js +0 -69
|
@@ -5,10 +5,13 @@
|
|
|
5
5
|
* individual run to a deploy. The run is already clock-stamped by buildVerificationRun, so the store
|
|
6
6
|
* needs no clock.
|
|
7
7
|
*/
|
|
8
|
-
import {
|
|
8
|
+
import { callingAttachId } from '../../../hooks/coding-agents.js';
|
|
9
|
+
import { episodeStampFor } from '../../../hooks/episode-stamp.js';
|
|
10
|
+
import { asRunId, checkoutOf, ReticleDir, ReticleVerificationRunSchema, RUN_RETENTION, RUN_RETENTION_SLACK, RunReadError, RunScreenshotSchema, STEP_SCREENSHOT, } from '@reticlehq/core';
|
|
9
11
|
import { PromptContextSchema } from '@reticlehq/core/artifacts';
|
|
12
|
+
import { readTextOrUndefined } from '../../../memory/project/fs/fs-port.js';
|
|
10
13
|
import { reticleDirPaths, isValidRunId, runPath, stepShotDir, } from '../../../memory/project/dir/reticle-dir.js';
|
|
11
|
-
import { join } from 'node:path';
|
|
14
|
+
import { dirname, join } from 'node:path';
|
|
12
15
|
const JSON_INDENT = 2;
|
|
13
16
|
const JSON_EXT = '.json';
|
|
14
17
|
const TMP_EXT = '.tmp';
|
|
@@ -34,18 +37,53 @@ export class RunStore {
|
|
|
34
37
|
* Guards runId as a safe path segment BEFORE building the path — a runId can originate from a caller
|
|
35
38
|
* (an OEM may set it), so an unsafe value must never escape .reticle/runs/ (mirrors the read guard).
|
|
36
39
|
*/
|
|
37
|
-
|
|
40
|
+
/**
|
|
41
|
+
* The branch of the checkout that holds these runs. None for a folder inside Reticle's own
|
|
42
|
+
* storage (`~/.reticle/unmatched/<id>`): the walk up from there finds the home folder, which can be
|
|
43
|
+
* a dotfiles repository, and its branch says nothing about the app.
|
|
44
|
+
*/
|
|
45
|
+
#branch() {
|
|
46
|
+
const project = dirname(this.#root);
|
|
47
|
+
if (project.split(/[\\/]/).includes(ReticleDir.ROOT)) {
|
|
48
|
+
return undefined;
|
|
49
|
+
}
|
|
50
|
+
return checkoutOf(project, readTextOrUndefined)?.branch;
|
|
51
|
+
}
|
|
52
|
+
async write(given,
|
|
53
|
+
/** The tab the run came from, so a run written outside any call still finds its episode. */
|
|
54
|
+
hint = {}) {
|
|
38
55
|
let run = given;
|
|
39
56
|
if (!isValidRunId(run.runId)) {
|
|
40
57
|
throw new Error(`refusing to write run with unsafe runId: ${JSON.stringify(run.runId)}`);
|
|
41
58
|
}
|
|
42
59
|
await this.#fs.mkdir(reticleDirPaths(this.#root).runs);
|
|
43
|
-
const context = run.context ??
|
|
44
|
-
|
|
60
|
+
const context = run.context ??
|
|
61
|
+
(await this.#recentRequest(run.createdAt, run.runId)) ??
|
|
62
|
+
(await this.#heldContext(run.runId));
|
|
63
|
+
if (context !== undefined) {
|
|
45
64
|
run = { ...run, context };
|
|
65
|
+
}
|
|
66
|
+
// The episode this run came from, the agent session behind it, and the commit it ran against,
|
|
67
|
+
// so it joins exactly.
|
|
68
|
+
const episode = episodeStampFor(this.#root, callingAttachId(), hint.sessionId);
|
|
69
|
+
if (episode !== undefined) {
|
|
70
|
+
const commit = run.project.commit ?? episode.head;
|
|
71
|
+
run = {
|
|
72
|
+
...run,
|
|
73
|
+
episodeId: episode.episodeId,
|
|
74
|
+
...(episode.agentSession === undefined ? {} : { agentSession: episode.agentSession }),
|
|
75
|
+
project: { ...run.project, ...(commit === undefined ? {} : { commit }) },
|
|
76
|
+
};
|
|
77
|
+
}
|
|
46
78
|
// The step screenshots taken for this run, the last of which may still be landing.
|
|
47
79
|
await shotsLanded(this.#root, run.runId);
|
|
48
80
|
run = withScreenshots(run, await readStepShots(this.#fs, this.#root, run.runId));
|
|
81
|
+
// Several agents drive one project at once, each in its own git worktree. Every run kind is
|
|
82
|
+
// written here, so here the run learns which branch it belongs to.
|
|
83
|
+
const branch = run.project.branch ?? this.#branch();
|
|
84
|
+
if (branch !== undefined) {
|
|
85
|
+
run = { ...run, project: { ...run.project, branch } };
|
|
86
|
+
}
|
|
49
87
|
// Atomic publish: write a temp file then rename, so a crash mid-write never leaves a half-written
|
|
50
88
|
// artifact (a partial.json would otherwise read back as MALFORMED).
|
|
51
89
|
const path = runPath(this.#root, run.runId);
|
|
@@ -71,16 +109,19 @@ export class RunStore {
|
|
|
71
109
|
const path = reticleDirPaths(this.#root).request;
|
|
72
110
|
const raw = JSON.parse(await this.#fs.readFile(path));
|
|
73
111
|
const parsed = PromptContextSchema.safeParse(raw);
|
|
74
|
-
if (!parsed.success)
|
|
112
|
+
if (!parsed.success) {
|
|
75
113
|
return undefined;
|
|
114
|
+
}
|
|
76
115
|
const given = parsed.data.at;
|
|
77
|
-
if (given === undefined || at - given < 0 || REQUEST_RELEVANT_MS < at - given)
|
|
116
|
+
if (given === undefined || at - given < 0 || REQUEST_RELEVANT_MS < at - given) {
|
|
78
117
|
return undefined;
|
|
118
|
+
}
|
|
79
119
|
// The first run written for a request answers it; a later run (the next agent session in the
|
|
80
120
|
// same tab) inherited it and showed a goal it never had. Its own rewrite keeps it.
|
|
81
121
|
const answeredBy = raw[REQUEST_RUN_KEY];
|
|
82
|
-
if ('string' === typeof answeredBy)
|
|
122
|
+
if ('string' === typeof answeredBy) {
|
|
83
123
|
return answeredBy === runId ? parsed.data : undefined;
|
|
124
|
+
}
|
|
84
125
|
await this.#fs.writeFile(path, `${JSON.stringify({ ...raw, [REQUEST_RUN_KEY]: runId }, null, JSON_INDENT)}\n`);
|
|
85
126
|
return parsed.data;
|
|
86
127
|
}
|
|
@@ -88,14 +129,30 @@ export class RunStore {
|
|
|
88
129
|
return undefined; // no request recorded: the common case
|
|
89
130
|
}
|
|
90
131
|
}
|
|
132
|
+
/**
|
|
133
|
+
* The request this run already carries on disk. A tab's run is written again after every verdict,
|
|
134
|
+
* and the prompt hook replaces request.json on every prompt: a newer prompt made the rewrite find
|
|
135
|
+
* no request of its own and drop the one it had, on this machine and on the platform.
|
|
136
|
+
*/
|
|
137
|
+
async #heldContext(runId) {
|
|
138
|
+
try {
|
|
139
|
+
const held = JSON.parse(await this.#fs.readFile(runPath(this.#root, runId)));
|
|
140
|
+
const parsed = PromptContextSchema.safeParse(held.context);
|
|
141
|
+
return parsed.success ? parsed.data : undefined;
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return undefined; // a first write: nothing held yet
|
|
145
|
+
}
|
|
146
|
+
}
|
|
91
147
|
/**
|
|
92
148
|
* Keep .reticle/runs/ bounded. Only acts once the count exceeds RUN_RETENTION + SLACK, then deletes the
|
|
93
149
|
* oldest (by createdAt) back down to RUN_RETENTION — so the read-all is amortized, not per-write.
|
|
94
150
|
*/
|
|
95
151
|
async #pruneOld() {
|
|
96
152
|
const ids = await this.list();
|
|
97
|
-
if (ids.length <= this.#retention + this.#slack)
|
|
153
|
+
if (ids.length <= this.#retention + this.#slack) {
|
|
98
154
|
return;
|
|
155
|
+
}
|
|
99
156
|
// `id: RunId`, not `string`. `list()` already returns RunId[]; annotating the local as string
|
|
100
157
|
// silently discarded the brand and handed a bare string to runPath — which is the transposition
|
|
101
158
|
// the brand exists to prevent, reintroduced by a type annotation rather than by a bad call.
|
|
@@ -111,11 +168,13 @@ export class RunStore {
|
|
|
111
168
|
}
|
|
112
169
|
/** Never throws. Invalid id / missing → MISSING; bad JSON or failed schema → MALFORMED. */
|
|
113
170
|
async read(runId) {
|
|
114
|
-
if (!isValidRunId(runId))
|
|
171
|
+
if (!isValidRunId(runId)) {
|
|
115
172
|
return { ok: false, reason: RunReadError.MISSING };
|
|
173
|
+
}
|
|
116
174
|
const path = runPath(this.#root, runId);
|
|
117
|
-
if (!(await this.#fs.exists(path)))
|
|
175
|
+
if (!(await this.#fs.exists(path))) {
|
|
118
176
|
return { ok: false, reason: RunReadError.MISSING };
|
|
177
|
+
}
|
|
119
178
|
let text;
|
|
120
179
|
try {
|
|
121
180
|
text = await this.#fs.readFile(path);
|
|
@@ -134,15 +193,17 @@ export class RunStore {
|
|
|
134
193
|
return { ok: false, reason: RunReadError.MALFORMED };
|
|
135
194
|
}
|
|
136
195
|
const result = ReticleVerificationRunSchema.safeParse(parsed);
|
|
137
|
-
if (!result.success)
|
|
196
|
+
if (!result.success) {
|
|
138
197
|
return { ok: false, reason: RunReadError.MALFORMED };
|
|
198
|
+
}
|
|
139
199
|
return { ok: true, run: result.data };
|
|
140
200
|
}
|
|
141
201
|
/** List run ids on disk (filenames minus.json). Empty when the runs dir is absent. */
|
|
142
202
|
async list() {
|
|
143
203
|
const dir = reticleDirPaths(this.#root).runs;
|
|
144
|
-
if (!(await this.#fs.exists(dir)))
|
|
204
|
+
if (!(await this.#fs.exists(dir))) {
|
|
145
205
|
return [];
|
|
206
|
+
}
|
|
146
207
|
let entries;
|
|
147
208
|
try {
|
|
148
209
|
entries = await this.#fs.readdir(dir);
|
|
@@ -154,6 +215,17 @@ export class RunStore {
|
|
|
154
215
|
.filter((e) => e.endsWith(JSON_EXT))
|
|
155
216
|
.map((e) => asRunId(e.slice(0, -JSON_EXT.length)));
|
|
156
217
|
}
|
|
218
|
+
/** Every readable run. Retention bounds how many there are. */
|
|
219
|
+
async all() {
|
|
220
|
+
const runs = [];
|
|
221
|
+
for (const id of await this.list()) {
|
|
222
|
+
const result = await this.read(id);
|
|
223
|
+
if (result.ok) {
|
|
224
|
+
runs.push(result.run);
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
return runs;
|
|
228
|
+
}
|
|
157
229
|
/** The most-recent run by createdAt (undefined when none). Powers reticle_run_export's default. */
|
|
158
230
|
async latest() {
|
|
159
231
|
const ids = await this.list();
|
|
@@ -166,6 +238,44 @@ export class RunStore {
|
|
|
166
238
|
}
|
|
167
239
|
return best;
|
|
168
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* The newest recorded result for each flow name, taken across every readable run, with the time
|
|
243
|
+
* and id of the run it came from. A run that carries no flows (a drive or an export) says nothing
|
|
244
|
+
* about any flow, so it can neither supply nor erase a result: judging coverage from `latest()`
|
|
245
|
+
* alone let one such run hide every earlier replay. Equal times break on the run id, so the answer
|
|
246
|
+
* never depends on the order `list()` returns.
|
|
247
|
+
*/
|
|
248
|
+
async latestPerFlow() {
|
|
249
|
+
const newest = new Map();
|
|
250
|
+
for (const id of await this.list()) {
|
|
251
|
+
const read = await this.read(id);
|
|
252
|
+
if (!read.ok) {
|
|
253
|
+
continue;
|
|
254
|
+
}
|
|
255
|
+
const createdAt = read.run.createdAt;
|
|
256
|
+
for (const result of read.run.flows) {
|
|
257
|
+
const s = newest.get(result.name);
|
|
258
|
+
if (!s || createdAt > s.createdAt || (createdAt === s.createdAt && id > s.id)) {
|
|
259
|
+
newest.set(result.name, { result, createdAt, id });
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return newest;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* The names `credit` (the gate's passing rule) gives each flow's newest result, each with the time
|
|
267
|
+
* of that result, so a caller can refuse a pass that predates an edit. The rule is passed in, so
|
|
268
|
+
* the run store does not reach into the flow language.
|
|
269
|
+
*/
|
|
270
|
+
async passingFlowTimes(credit) {
|
|
271
|
+
const passing = new Map();
|
|
272
|
+
for (const { result, createdAt } of (await this.latestPerFlow()).values()) {
|
|
273
|
+
for (const name of credit([result])) {
|
|
274
|
+
passing.set(name, Math.max(passing.get(name) ?? createdAt, createdAt));
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
return passing;
|
|
278
|
+
}
|
|
169
279
|
/**
|
|
170
280
|
* The two most-recent runs by createdAt as `[previous, current]` (oldest-first), or undefined when
|
|
171
281
|
* fewer than two readable runs exist. Powers reticle_run_export's `format:"diff"` (run-to-run deltas).
|
|
@@ -174,16 +284,19 @@ export class RunStore {
|
|
|
174
284
|
const runs = [];
|
|
175
285
|
for (const id of await this.list()) {
|
|
176
286
|
const result = await this.read(id);
|
|
177
|
-
if (result.ok)
|
|
287
|
+
if (result.ok) {
|
|
178
288
|
runs.push(result.run);
|
|
289
|
+
}
|
|
179
290
|
}
|
|
180
|
-
if (runs.length < 2)
|
|
291
|
+
if (runs.length < 2) {
|
|
181
292
|
return undefined;
|
|
293
|
+
}
|
|
182
294
|
runs.sort((a, b) => a.createdAt - b.createdAt);
|
|
183
295
|
const previous = runs[runs.length - 2];
|
|
184
296
|
const current = runs[runs.length - 1];
|
|
185
|
-
if (previous === undefined || current === undefined)
|
|
297
|
+
if (previous === undefined || current === undefined) {
|
|
186
298
|
return undefined;
|
|
299
|
+
}
|
|
187
300
|
return [previous, current];
|
|
188
301
|
}
|
|
189
302
|
}
|
|
@@ -205,11 +318,13 @@ export function noteLanding(dir, land) {
|
|
|
205
318
|
}
|
|
206
319
|
/** Wait for this run's screenshots still landing, so a run written now can list them. Bounded. */
|
|
207
320
|
export async function shotsLanded(root, runId) {
|
|
208
|
-
if (!isValidRunId(runId))
|
|
321
|
+
if (!isValidRunId(runId)) {
|
|
209
322
|
return;
|
|
323
|
+
}
|
|
210
324
|
const pending = landing.get(stepShotDir(root, runId));
|
|
211
|
-
if (pending === undefined || 0 === pending.size)
|
|
325
|
+
if (pending === undefined || 0 === pending.size) {
|
|
212
326
|
return;
|
|
327
|
+
}
|
|
213
328
|
let timer;
|
|
214
329
|
await Promise.race([
|
|
215
330
|
Promise.allSettled([...pending]),
|
|
@@ -217,8 +332,9 @@ export async function shotsLanded(root, runId) {
|
|
|
217
332
|
timer = setTimeout(resolve, LANDING_WAIT_MS);
|
|
218
333
|
}),
|
|
219
334
|
]);
|
|
220
|
-
if (timer !== undefined)
|
|
335
|
+
if (timer !== undefined) {
|
|
221
336
|
clearTimeout(timer);
|
|
337
|
+
}
|
|
222
338
|
}
|
|
223
339
|
/** One line of a run's record, read back; anything malformed is skipped. */
|
|
224
340
|
function parseLine(line) {
|
|
@@ -232,8 +348,9 @@ function parseLine(line) {
|
|
|
232
348
|
}
|
|
233
349
|
/** Every screenshot a run has landed, in the order they were taken (by seq). Never throws. */
|
|
234
350
|
export async function readStepShots(fs, root, runId) {
|
|
235
|
-
if (!isValidRunId(runId))
|
|
351
|
+
if (!isValidRunId(runId)) {
|
|
236
352
|
return [];
|
|
353
|
+
}
|
|
237
354
|
try {
|
|
238
355
|
const text = await fs.readFile(join(stepShotDir(root, runId), STEP_SCREENSHOT.MANIFEST_FILE));
|
|
239
356
|
return (text
|
|
@@ -256,9 +373,11 @@ function stepShotOf(shot) {
|
|
|
256
373
|
/** An id that occurs once in the list; a repeated one (a reload restarts the count) pairs nothing. */
|
|
257
374
|
function uniqueIds(ids) {
|
|
258
375
|
const seen = new Map();
|
|
259
|
-
for (const id of ids)
|
|
260
|
-
if (id !== undefined)
|
|
376
|
+
for (const id of ids) {
|
|
377
|
+
if (id !== undefined) {
|
|
261
378
|
seen.set(id, (seen.get(id) ?? 0) + 1);
|
|
379
|
+
}
|
|
380
|
+
}
|
|
262
381
|
return new Set([...seen].filter(([, n]) => 1 === n).map(([id]) => id));
|
|
263
382
|
}
|
|
264
383
|
/**
|
|
@@ -268,8 +387,9 @@ function uniqueIds(ids) {
|
|
|
268
387
|
*/
|
|
269
388
|
function pairByAction(run, shots) {
|
|
270
389
|
const verdictShots = shots.filter((shot) => true === shot.verdict && shot.actionId !== undefined);
|
|
271
|
-
if (0 === verdictShots.length || run.checks.every((check) => check.actionId === undefined))
|
|
390
|
+
if (0 === verdictShots.length || run.checks.every((check) => check.actionId === undefined)) {
|
|
272
391
|
return undefined;
|
|
392
|
+
}
|
|
273
393
|
const okChecks = uniqueIds(run.checks.map((check) => check.actionId));
|
|
274
394
|
const okShots = uniqueIds(verdictShots.map((shot) => shot.actionId));
|
|
275
395
|
const shotOf = new Map(verdictShots.flatMap((shot) => shot.actionId !== undefined && okShots.has(shot.actionId) && okChecks.has(shot.actionId)
|
|
@@ -278,10 +398,12 @@ function pairByAction(run, shots) {
|
|
|
278
398
|
const checkIdOf = new Map();
|
|
279
399
|
const checks = run.checks.map((check) => {
|
|
280
400
|
const shot = check.actionId === undefined ? undefined : shotOf.get(check.actionId);
|
|
281
|
-
if (shot === undefined)
|
|
401
|
+
if (shot === undefined) {
|
|
282
402
|
return check;
|
|
283
|
-
|
|
403
|
+
}
|
|
404
|
+
if (check.checkId !== undefined) {
|
|
284
405
|
checkIdOf.set(shot, check.checkId);
|
|
406
|
+
}
|
|
285
407
|
return { ...check, screenshot: stepShotOf(shot) };
|
|
286
408
|
});
|
|
287
409
|
return {
|
|
@@ -300,13 +422,15 @@ function pairByAction(run, shots) {
|
|
|
300
422
|
*/
|
|
301
423
|
function pairWithChecks(run, shots) {
|
|
302
424
|
const byAction = pairByAction(run, shots);
|
|
303
|
-
if (byAction !== undefined)
|
|
425
|
+
if (byAction !== undefined) {
|
|
304
426
|
return byAction;
|
|
427
|
+
}
|
|
305
428
|
const verdictShots = shots.filter((shot) => true === shot.verdict);
|
|
306
429
|
if (0 === verdictShots.length ||
|
|
307
430
|
verdictShots.length !== run.checks.length ||
|
|
308
|
-
run.checks.some((check) => check.checkId === undefined))
|
|
431
|
+
run.checks.some((check) => check.checkId === undefined)) {
|
|
309
432
|
return { checks: run.checks, shots: [...shots] };
|
|
433
|
+
}
|
|
310
434
|
const checkIdOf = new Map(verdictShots.map((shot, i) => [shot, run.checks[i]?.checkId]));
|
|
311
435
|
return {
|
|
312
436
|
checks: run.checks.map((check, i) => {
|
|
@@ -325,8 +449,9 @@ function pairWithChecks(run, shots) {
|
|
|
325
449
|
* back unchanged.
|
|
326
450
|
*/
|
|
327
451
|
export function withScreenshots(run, taken) {
|
|
328
|
-
if (0 === taken.length)
|
|
452
|
+
if (0 === taken.length) {
|
|
329
453
|
return run;
|
|
454
|
+
}
|
|
330
455
|
const { checks, shots } = pairWithChecks(run, taken);
|
|
331
456
|
const byStep = new Map(shots.flatMap((shot) => (shot.step === undefined ? [] : [[shot.step, shot]])));
|
|
332
457
|
const flows = run.flows.map((flow) => flow.stepResults === undefined
|
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { type RunId } from '@reticlehq/core';
|
|
2
2
|
/**
|
|
3
|
-
* The default run-id generator —
|
|
3
|
+
* The default run-id generator — 16 random hex characters.
|
|
4
4
|
*
|
|
5
5
|
* A leaf on purpose: `verification-sync.ts` wants this one function, and reaching it through the
|
|
6
6
|
* flow-replay stack would be a cycle.
|
|
7
7
|
*/
|
|
8
8
|
export declare function defaultRunId(): RunId;
|
|
9
|
+
/** A short id that is always the same for `key`, and always a safe path segment. */
|
|
10
|
+
export declare function stableRunId(key: string): string;
|
|
9
11
|
export declare function withShotRun<T>(runId: string, fn: () => Promise<T>): Promise<T>;
|
|
10
12
|
/** The run being replayed now, or undefined outside a verify. */
|
|
11
13
|
export declare function currentShotRun(): string | undefined;
|
|
@@ -1,14 +1,26 @@
|
|
|
1
1
|
import { AsyncLocalStorage } from 'node:async_hooks';
|
|
2
|
-
import {
|
|
2
|
+
import { createHash, randomBytes } from 'node:crypto';
|
|
3
3
|
import { asRunId } from '@reticlehq/core';
|
|
4
4
|
/**
|
|
5
|
-
*
|
|
5
|
+
* How many hex characters a new run id has: 64 bits.
|
|
6
|
+
*
|
|
7
|
+
* Each step screenshot path that an agent reads contains the run id, so a 36-character uuid cost
|
|
8
|
+
* tokens on every action. 64 bits keeps a collision in one organisation's runs improbable. Old
|
|
9
|
+
* uuid ids stay valid: a run id is any safe path segment, and nothing reads its shape.
|
|
10
|
+
*/
|
|
11
|
+
const RUN_ID_HEX = 16;
|
|
12
|
+
/**
|
|
13
|
+
* The default run-id generator — 16 random hex characters.
|
|
6
14
|
*
|
|
7
15
|
* A leaf on purpose: `verification-sync.ts` wants this one function, and reaching it through the
|
|
8
16
|
* flow-replay stack would be a cycle.
|
|
9
17
|
*/
|
|
10
18
|
export function defaultRunId() {
|
|
11
|
-
return asRunId(
|
|
19
|
+
return asRunId(randomBytes(RUN_ID_HEX / 2).toString('hex'));
|
|
20
|
+
}
|
|
21
|
+
/** A short id that is always the same for `key`, and always a safe path segment. */
|
|
22
|
+
export function stableRunId(key) {
|
|
23
|
+
return createHash('sha256').update(key).digest('hex').slice(0, RUN_ID_HEX);
|
|
12
24
|
}
|
|
13
25
|
/**
|
|
14
26
|
* The run a replay's step screenshots belong to, carried across every await under it.
|
|
@@ -66,9 +66,9 @@ export declare function checkWords(verdict: {
|
|
|
66
66
|
* reload, each a superset of the last, and the dashboard would fill with overlapping copies of one
|
|
67
67
|
* drive. Derived from the session instead, so the fold is idempotent.
|
|
68
68
|
*
|
|
69
|
-
* A session id is a free string on the wire,
|
|
70
|
-
*
|
|
71
|
-
*
|
|
69
|
+
* A hash of the session id, not the id itself. A session id is a free string on the wire, and a
|
|
70
|
+
* uuid one put 36 characters into every step screenshot path. The hash is short, stable and always
|
|
71
|
+
* a safe path segment. A run that an older daemon wrote keeps its long id and stays readable.
|
|
72
72
|
*/
|
|
73
73
|
export declare function driveRunId(sessionId: string): string;
|
|
74
74
|
/** The run the agent's session now open in this tab is kept under. */
|
|
@@ -25,7 +25,7 @@
|
|
|
25
25
|
import { supersededChecks } from '@reticlehq/engine/evidence/superseded-checks.js';
|
|
26
26
|
import { isValidRunId } from '../../memory/project/dir/reticle-dir.js';
|
|
27
27
|
import { defaultRunId } from './runner-port.js';
|
|
28
|
-
import { currentShotRun } from './default-run-id.js';
|
|
28
|
+
import { currentShotRun, stableRunId } from './default-run-id.js';
|
|
29
29
|
import { currentDrivenBy } from '../../hooks/driven-by.js';
|
|
30
30
|
import { JournalVerdictEffectSchema, RunAgentKind, asRecord, asString, RunFramework, RunProfile, RunTrigger, PredicateKind, Verified, VerifiedReason, driveFlowStatus, } from '@reticlehq/core';
|
|
31
31
|
import { withCorrections } from './late-answer.js';
|
|
@@ -79,13 +79,12 @@ const DRIVE_RUN_PREFIX = 'drive-';
|
|
|
79
79
|
* reload, each a superset of the last, and the dashboard would fill with overlapping copies of one
|
|
80
80
|
* drive. Derived from the session instead, so the fold is idempotent.
|
|
81
81
|
*
|
|
82
|
-
* A session id is a free string on the wire,
|
|
83
|
-
*
|
|
84
|
-
*
|
|
82
|
+
* A hash of the session id, not the id itself. A session id is a free string on the wire, and a
|
|
83
|
+
* uuid one put 36 characters into every step screenshot path. The hash is short, stable and always
|
|
84
|
+
* a safe path segment. A run that an older daemon wrote keeps its long id and stays readable.
|
|
85
85
|
*/
|
|
86
86
|
export function driveRunId(sessionId) {
|
|
87
|
-
|
|
88
|
-
return isValidRunId(candidate) ? candidate : defaultRunId();
|
|
87
|
+
return `${DRIVE_RUN_PREFIX}${stableRunId(sessionId)}`;
|
|
89
88
|
}
|
|
90
89
|
/** The run of the `segment`th agent session in a tab: the tab's id first, then `-2`, `-3`… */
|
|
91
90
|
function segmentRunId(base, segment) {
|
|
@@ -179,12 +178,17 @@ export function driveRunFrom(actions, deps) {
|
|
|
179
178
|
const intentOf = new Map(actions.map((a) => [a.actionId, asString(asRecord(a.args)['intent'])]));
|
|
180
179
|
const checks = [];
|
|
181
180
|
for (const verdict of found) {
|
|
182
|
-
|
|
181
|
+
// The agent's own words on the call win; else the sentence the verdict recorded.
|
|
182
|
+
const given = intentOf.get(verdict.actionId);
|
|
183
|
+
const own = given !== undefined && 0 < given.length;
|
|
184
|
+
const intent = own ? given : verdict.intent;
|
|
183
185
|
checks.push({
|
|
184
186
|
predicate: verdict.claim,
|
|
185
187
|
status: verdict.verified,
|
|
186
188
|
actionId: verdict.actionId,
|
|
187
189
|
...(intent === undefined || 0 === intent.length ? {} : { intent }),
|
|
190
|
+
...(!own && true === verdict.intentDerived ? { intentDerived: true } : {}),
|
|
191
|
+
...(verdict.failedPart === undefined ? {} : { failedPart: verdict.failedPart }),
|
|
188
192
|
// Where it was written, and on a miss the calls of its window: what an issue page shows.
|
|
189
193
|
...(verdict.source === undefined && verdict.net === undefined
|
|
190
194
|
? {}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { Verified, type JournalAction, type RunReport } from '@reticlehq/core';
|
|
2
|
+
export declare class RunLedger {
|
|
3
|
+
#private;
|
|
4
|
+
/** An agent call starts. The first one starts the run, and a call from another agent starts a new one. */
|
|
5
|
+
begin(now: number, owner: string): void;
|
|
6
|
+
/** An agent call ended. The first one that left a verdict sets the time to the first verdict. */
|
|
7
|
+
after(now: number): void;
|
|
8
|
+
/** A journal record from the agent's own call. A record with no verdict is not a claim. */
|
|
9
|
+
verdict(action: JournalAction): void;
|
|
10
|
+
flowSaved(name: string): void;
|
|
11
|
+
/** The last replay of a flow in this run is its verdict. */
|
|
12
|
+
replayed(name: string, verified: Verified): void;
|
|
13
|
+
memoryWritten(count?: number): void;
|
|
14
|
+
/** Notes given to the agent. Each one counts once, however often it is shown. */
|
|
15
|
+
memoryRead(notes: readonly string[]): void;
|
|
16
|
+
isEmpty(): boolean;
|
|
17
|
+
/** The report, without the cloud line (the caller knows the project). Empties the ledger. */
|
|
18
|
+
take(now: number): RunReport;
|
|
19
|
+
}
|
|
20
|
+
/** The daemon's ledger. */
|
|
21
|
+
export declare const runLedger: RunLedger;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The run ledger: what one agent run checked, saved and read, kept until its report is taken.
|
|
3
|
+
*
|
|
4
|
+
* A run is the agent's calls from its first Reticle call to the call that ends it (a session end, a
|
|
5
|
+
* yield, a released tab). The verdicts come from the journal records the agent's own calls wrote;
|
|
6
|
+
* the Harness's are never counted. Taking the report empties the ledger, so the next run starts at
|
|
7
|
+
* zero.
|
|
8
|
+
*
|
|
9
|
+
* A call from another agent (another MCP attach id) starts a new run. An agent that stops without a
|
|
10
|
+
* call that ends its run then does not leak its claims into the next agent's report.
|
|
11
|
+
*
|
|
12
|
+
* ponytail: one ledger for each daemon, not for each agent. Two agents that call at the same time
|
|
13
|
+
* restart each other's run. Key the ledger by attach id when that happens.
|
|
14
|
+
*/
|
|
15
|
+
import { supersededChecks } from '@reticlehq/engine/evidence/superseded-checks.js';
|
|
16
|
+
import { JournalVerdictEffectSchema, ReticleTool, Verified, } from '@reticlehq/core';
|
|
17
|
+
const SAW = 'saw ';
|
|
18
|
+
const FLOW = 'flow ';
|
|
19
|
+
/** One piece of evidence for a claim: what the check saw, else the source line it drove. */
|
|
20
|
+
function evidenceOf(effect) {
|
|
21
|
+
if (effect.observed !== undefined)
|
|
22
|
+
return `${SAW}${effect.observed}`;
|
|
23
|
+
return effect.source;
|
|
24
|
+
}
|
|
25
|
+
/** `no` when anything failed, `yes` only when something held and nothing was undecided. */
|
|
26
|
+
function runVerified(all) {
|
|
27
|
+
if (all.includes(Verified.NO))
|
|
28
|
+
return Verified.NO;
|
|
29
|
+
if (0 === all.length || all.some((v) => Verified.YES !== v))
|
|
30
|
+
return Verified.UNKNOWN;
|
|
31
|
+
return Verified.YES;
|
|
32
|
+
}
|
|
33
|
+
export class RunLedger {
|
|
34
|
+
#owner;
|
|
35
|
+
#startedAt;
|
|
36
|
+
#firstVerdictAt;
|
|
37
|
+
#verdicts = [];
|
|
38
|
+
#saved = new Set();
|
|
39
|
+
#replayed = new Map();
|
|
40
|
+
#written = 0;
|
|
41
|
+
#read = new Set();
|
|
42
|
+
/** An agent call starts. The first one starts the run, and a call from another agent starts a new one. */
|
|
43
|
+
begin(now, owner) {
|
|
44
|
+
if (this.#owner !== owner)
|
|
45
|
+
this.#reset();
|
|
46
|
+
this.#owner = owner;
|
|
47
|
+
this.#startedAt ??= now;
|
|
48
|
+
}
|
|
49
|
+
/** An agent call ended. The first one that left a verdict sets the time to the first verdict. */
|
|
50
|
+
after(now) {
|
|
51
|
+
if (0 < this.#verdicts.length || 0 < this.#replayed.size)
|
|
52
|
+
this.#firstVerdictAt ??= now;
|
|
53
|
+
}
|
|
54
|
+
/** A journal record from the agent's own call. A record with no verdict is not a claim. */
|
|
55
|
+
verdict(action) {
|
|
56
|
+
if (this.#idle() || action.drivenBy !== undefined)
|
|
57
|
+
return;
|
|
58
|
+
// A replay is counted once, as a flow, decided as its run decides it (`replayed`). Its journal
|
|
59
|
+
// record said `unknown` where the run said `no`, and one report gave both answers.
|
|
60
|
+
if (ReticleTool.FLOW_REPLAY === action.tool)
|
|
61
|
+
return;
|
|
62
|
+
const parsed = JournalVerdictEffectSchema.safeParse(action.effect);
|
|
63
|
+
if (parsed.success)
|
|
64
|
+
this.#verdicts.push(parsed.data);
|
|
65
|
+
}
|
|
66
|
+
flowSaved(name) {
|
|
67
|
+
if (!this.#idle())
|
|
68
|
+
this.#saved.add(name);
|
|
69
|
+
}
|
|
70
|
+
/** The last replay of a flow in this run is its verdict. */
|
|
71
|
+
replayed(name, verified) {
|
|
72
|
+
if (!this.#idle())
|
|
73
|
+
this.#replayed.set(name, verified);
|
|
74
|
+
}
|
|
75
|
+
memoryWritten(count = 1) {
|
|
76
|
+
if (!this.#idle())
|
|
77
|
+
this.#written += count;
|
|
78
|
+
}
|
|
79
|
+
/** Notes given to the agent. Each one counts once, however often it is shown. */
|
|
80
|
+
memoryRead(notes) {
|
|
81
|
+
if (this.#idle())
|
|
82
|
+
return;
|
|
83
|
+
for (const note of notes)
|
|
84
|
+
this.#read.add(note);
|
|
85
|
+
}
|
|
86
|
+
isEmpty() {
|
|
87
|
+
return this.#idle();
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* No agent run is open. A CLI `reticle verify` replays through the same code, and what it did is
|
|
91
|
+
* not the next agent's run, so nothing is kept until an agent call begins one.
|
|
92
|
+
*/
|
|
93
|
+
#idle() {
|
|
94
|
+
return this.#startedAt === undefined;
|
|
95
|
+
}
|
|
96
|
+
/** The report, without the cloud line (the caller knows the project). Empties the ledger. */
|
|
97
|
+
take(now) {
|
|
98
|
+
const started = this.#startedAt ?? now;
|
|
99
|
+
// A passive check that read too early is not counted: the rule every fold applies.
|
|
100
|
+
const superseded = supersededChecks(this.#verdicts.map((v) => ({
|
|
101
|
+
key: v.claim,
|
|
102
|
+
passive: false === v.declaredBeforeActing,
|
|
103
|
+
held: Verified.YES === v.verified,
|
|
104
|
+
failed: Verified.NO === v.verified,
|
|
105
|
+
})));
|
|
106
|
+
const counted = this.#verdicts.filter((_, at) => !superseded.has(at));
|
|
107
|
+
const claims = counted.map((v) => {
|
|
108
|
+
const evidence = evidenceOf(v);
|
|
109
|
+
return evidence === undefined
|
|
110
|
+
? { claim: v.claim, verified: v.verified }
|
|
111
|
+
: { claim: v.claim, verified: v.verified, evidence };
|
|
112
|
+
});
|
|
113
|
+
const replayed = [...this.#replayed].map(([name, verified]) => ({ name, verified }));
|
|
114
|
+
const report = {
|
|
115
|
+
verified: runVerified([...claims.map((c) => c.verified), ...replayed.map((r) => r.verified)]),
|
|
116
|
+
claims,
|
|
117
|
+
caught: [
|
|
118
|
+
...claims.filter((c) => Verified.NO === c.verified).map((c) => c.claim),
|
|
119
|
+
...replayed.filter((r) => Verified.NO === r.verified).map((r) => `${FLOW}${r.name}`),
|
|
120
|
+
],
|
|
121
|
+
flows: { saved: [...this.#saved], replayed },
|
|
122
|
+
memory: { written: this.#written, read: this.#read.size },
|
|
123
|
+
wallMs: Math.max(0, now - started),
|
|
124
|
+
...(this.#firstVerdictAt === undefined
|
|
125
|
+
? {}
|
|
126
|
+
: { firstVerdictMs: Math.max(0, this.#firstVerdictAt - started) }),
|
|
127
|
+
};
|
|
128
|
+
this.#reset();
|
|
129
|
+
return report;
|
|
130
|
+
}
|
|
131
|
+
#reset() {
|
|
132
|
+
this.#owner = undefined;
|
|
133
|
+
this.#startedAt = undefined;
|
|
134
|
+
this.#firstVerdictAt = undefined;
|
|
135
|
+
this.#verdicts = [];
|
|
136
|
+
this.#saved = new Set();
|
|
137
|
+
this.#replayed = new Map();
|
|
138
|
+
this.#written = 0;
|
|
139
|
+
this.#read = new Set();
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
/** The daemon's ledger. */
|
|
143
|
+
export const runLedger = new RunLedger();
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The live adapter: build a RunnerPort from the real ToolDeps so ReticleRunner drives actual flow
|
|
3
|
-
* replays against the connected app. Thin glue — it wires
|
|
3
|
+
* replays against the connected app. Thin glue — it wires the session's flow list, replayNamedFlow, deps.now,
|
|
4
4
|
* and a uuid generator. The ReticleRunner core (tested with a fake port) holds all the orchestration and
|
|
5
5
|
* verdict logic, so this layer carries no decisions.
|
|
6
6
|
*/
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* The live adapter: build a RunnerPort from the real ToolDeps so ReticleRunner drives actual flow
|
|
3
|
-
* replays against the connected app. Thin glue — it wires
|
|
3
|
+
* replays against the connected app. Thin glue — it wires the session's flow list, replayNamedFlow, deps.now,
|
|
4
4
|
* and a uuid generator. The ReticleRunner core (tested with a fake port) holds all the orchestration and
|
|
5
5
|
* verdict logic, so this layer carries no decisions.
|
|
6
6
|
*/
|
|
7
7
|
import { replayAndLearn } from '../../language/flows/flow-learning.js';
|
|
8
|
+
import { flowsForSession } from '../../language/flows/flow-store-for-session.js';
|
|
9
|
+
import { safeSessionTarget } from '../../memory/project/session-root.js';
|
|
8
10
|
import { defaultRunId } from './default-run-id.js';
|
|
9
11
|
export { defaultRunId } from './default-run-id.js';
|
|
10
12
|
/** Wire a RunnerPort to the live session. Pass sessionId to disambiguate when several tabs are open. */
|
|
@@ -12,7 +14,11 @@ export function createRunnerPort(deps, sessionId,
|
|
|
12
14
|
/** `reticle verify --confirm-dangerous`: this run acknowledges the steps held as destructive. */
|
|
13
15
|
opts = {}) {
|
|
14
16
|
return {
|
|
15
|
-
|
|
17
|
+
// Resolved as replay resolves it, so every listed name is one replay can load.
|
|
18
|
+
listFlows: () => {
|
|
19
|
+
const target = safeSessionTarget(deps, sessionId);
|
|
20
|
+
return flowsForSession(deps, target).flows.list(target.projectId);
|
|
21
|
+
},
|
|
16
22
|
replayFlow: (name) => replayAndLearn(deps, {
|
|
17
23
|
flowName: name,
|
|
18
24
|
...(sessionId === undefined ? {} : { sessionId }),
|