@reticlehq/server 3.6.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/SKILL.md +122 -123
- 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 +18 -2
- package/dist/command/cli/adhoc-verdict.js +70 -6
- 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/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 +28 -105
- 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 +34 -4
- package/dist/command/cli/cli-verify.js +81 -12
- package/dist/command/cli/cloud-cli.d.ts +13 -0
- package/dist/command/cli/cloud-cli.js +145 -333
- 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 +15 -1
- package/dist/command/cli/cloud-login.js +67 -13
- 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/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/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 +11 -2
- 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.js +1 -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 +29 -8
- 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 -178
- 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 +14 -0
- package/dist/command/cli.js +103 -83
- package/dist/command/daemon/daemon-resilience.js +4 -4
- package/dist/command/daemon/daemon-resolve.d.ts +9 -1
- package/dist/command/daemon/daemon-resolve.js +49 -10
- 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/dev-server-log-cap.js +2 -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 +10 -1
- package/dist/command/setup/init/init-port.js +22 -2
- package/dist/command/setup/init/init-runtime.d.ts +12 -2
- package/dist/command/setup/init/init-runtime.js +96 -37
- package/dist/command/setup/node-effects.d.ts +2 -0
- package/dist/command/setup/node-effects.js +36 -8
- 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 +1 -1
- package/dist/command/setup/run-setup.d.ts +29 -9
- package/dist/command/setup/run-setup.js +34 -28
- package/dist/command/setup/setup-command.d.ts +23 -0
- package/dist/command/setup/setup-command.js +57 -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 +38 -2
- package/dist/features/crawl/crawl.js +14 -1
- package/dist/features/exhaust/ledger.d.ts +14 -14
- package/dist/features/harness/drive-report.d.ts +39 -5
- package/dist/features/harness/drive-report.js +271 -54
- 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 +1 -1
- package/dist/features/harness/drivers.js +1 -1
- 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/goals.d.ts +68 -7
- package/dist/features/harness/goals.js +289 -36
- package/dist/features/harness/harness.d.ts +30 -1
- package/dist/features/harness/harness.js +141 -7
- package/dist/features/harness/platform/local-apps.d.ts +36 -3
- package/dist/features/harness/platform/local-apps.js +81 -5
- 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 +8 -2
- package/dist/features/harness/platform/remote-drive.js +22 -9
- package/dist/features/harness/platform/script.d.ts +57 -11
- package/dist/features/harness/platform/script.js +144 -12
- package/dist/features/harness/platform/server-driver.d.ts +17 -4
- package/dist/features/harness/platform/server-driver.js +29 -26
- package/dist/features/harness/platform-config.d.ts +38 -5
- package/dist/features/harness/platform-config.js +93 -8
- package/dist/features/harness/route-guess.d.ts +13 -0
- package/dist/features/harness/route-guess.js +49 -0
- package/dist/features/harness/script/script-run.d.ts +30 -1
- package/dist/features/harness/script/script-run.js +355 -48
- 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.js +22 -14
- 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 +21 -2
- package/dist/hooks/driven-by.js +42 -2
- package/dist/hooks/hook-bus.d.ts +4 -0
- package/dist/hooks/hook-bus.js +18 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +26 -183
- 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 +20 -4
- 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.js +25 -9
- package/dist/judgement/runs/artifact/run-store.d.ts +13 -1
- package/dist/judgement/runs/artifact/run-store.js +175 -8
- 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 +53 -5
- package/dist/judgement/runs/drive-run.js +234 -20
- package/dist/judgement/runs/resume.d.ts +44 -0
- package/dist/judgement/runs/resume.js +137 -0
- package/dist/judgement/runs/reticle-runner.js +5 -2
- 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 +2 -0
- package/dist/judgement/runs/verification-sync.js +36 -15
- package/dist/language/flows/decision.js +2 -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 +7 -2
- package/dist/language/flows/flow-anchor.js +10 -3
- 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 +37 -3
- package/dist/language/flows/flow-replay-run.js +16 -18
- package/dist/language/flows/flow-replay-types.d.ts +1 -1
- package/dist/language/flows/flow-replay.d.ts +18 -1
- package/dist/language/flows/flow-replay.js +22 -7
- package/dist/language/flows/flow-result.d.ts +22 -1
- package/dist/language/flows/flow-result.js +47 -2
- package/dist/language/flows/flow-step-runners.d.ts +2 -0
- package/dist/language/flows/flow-step-runners.js +12 -6
- package/dist/language/flows/flow-store-for-session.js +5 -1
- package/dist/language/flows/flow-tools.d.ts +10 -0
- package/dist/language/flows/flow-tools.js +61 -62
- package/dist/language/flows/flows.d.ts +16 -1
- package/dist/language/flows/flows.js +69 -10
- package/dist/language/flows/narrow-write.d.ts +7 -0
- package/dist/language/flows/narrow-write.js +36 -1
- package/dist/language/flows/recording/recording-backtrack.js +14 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +29 -1
- package/dist/language/flows/recording/tape/recordings.js +60 -10
- package/dist/language/flows/replay.js +29 -6
- package/dist/language/flows/single-replay.d.ts +7 -0
- package/dist/language/flows/single-replay.js +26 -0
- package/dist/language/flows/verify-change-tools.d.ts +1 -0
- package/dist/language/flows/verify-change-tools.js +200 -193
- package/dist/memory/cloud/cloud-config.d.ts +10 -1
- package/dist/memory/cloud/cloud-config.js +19 -5
- package/dist/memory/cloud/cloud-sync.js +3 -3
- package/dist/memory/cloud/harness-config.d.ts +49 -0
- package/dist/memory/cloud/harness-config.js +16 -20
- package/dist/memory/cloud/memory-scope.d.ts +17 -0
- package/dist/memory/cloud/memory-scope.js +22 -0
- package/dist/memory/cloud/sync-cycle.d.ts +32 -4
- package/dist/memory/cloud/sync-cycle.js +113 -12
- package/dist/memory/cloud/sync-daemon.d.ts +11 -0
- package/dist/memory/cloud/sync-daemon.js +114 -4
- package/dist/memory/cloud/sync-disk.js +26 -2
- 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 +16 -1
- package/dist/memory/impact/account-watch.js +26 -1
- package/dist/memory/impact/impact-store.d.ts +1 -4
- package/dist/memory/impact/impact-store.js +32 -42
- 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 +12 -0
- package/dist/memory/intent/intent-store.d.ts +1 -0
- package/dist/memory/intent/intent-tools.js +42 -2
- 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/journal-recorder.js +46 -3
- package/dist/memory/journal/on-disk/retention.d.ts +5 -0
- package/dist/memory/journal/on-disk/retention.js +27 -2
- package/dist/memory/journal/on-disk/workspace-tiers.js +2 -0
- package/dist/memory/journal/session-end.d.ts +15 -1
- package/dist/memory/journal/session-end.js +38 -7
- package/dist/memory/project/artifact-root-resolver.js +33 -5
- package/dist/memory/project/artifact-root.d.ts +4 -3
- package/dist/memory/project/artifact-root.js +2 -2
- package/dist/memory/project/dir/reticle-dir.d.ts +14 -0
- package/dist/memory/project/dir/reticle-dir.js +23 -2
- package/dist/memory/project/link-directory.d.ts +15 -0
- package/dist/memory/project/link-directory.js +44 -0
- 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 +2 -0
- package/dist/memory/project/session-root.js +9 -1
- package/dist/memory/project/sync-status.d.ts +46 -0
- package/dist/memory/project/sync-status.js +135 -1
- package/dist/memory/recall/memory-tools.js +46 -3
- 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.js +36 -8
- package/dist/portal/bridge/bridge.d.ts +9 -5
- package/dist/portal/bridge/bridge.js +66 -23
- package/dist/portal/bridge/harness-request.d.ts +23 -0
- package/dist/portal/bridge/harness-request.js +27 -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 +2 -0
- package/dist/portal/input/real-input.js +13 -10
- package/dist/portal/pool/browser-pool.d.ts +48 -0
- package/dist/portal/pool/browser-pool.js +120 -2
- 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 +27 -5
- package/dist/portal/pool/playwright-launcher.js +59 -14
- package/dist/portal/pool/pool-contract.d.ts +21 -1
- 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.js +6 -1
- 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 +9 -0
- package/dist/portal/session/dev-server/dev-command.js +27 -1
- 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/human/live-control.d.ts +9 -2
- package/dist/portal/session/human/live-control.js +12 -3
- package/dist/portal/session/live-control-tools.js +82 -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 +1 -1
- package/dist/portal/session/no-session-diagnosis.js +31 -9
- package/dist/portal/session/no-session-next-action.d.ts +20 -0
- package/dist/portal/session/no-session-next-action.js +134 -61
- package/dist/portal/session/no-session-watch.js +179 -22
- package/dist/portal/session/presence/session-lease.js +1 -1
- package/dist/portal/session/recorded-gaps.d.ts +97 -0
- package/dist/portal/session/recorded-gaps.js +251 -0
- package/dist/portal/session/session-health.d.ts +11 -0
- package/dist/portal/session/session-health.js +3 -1
- package/dist/portal/session/session-info.js +2 -1
- package/dist/portal/session/session-manager.d.ts +18 -0
- package/dist/portal/session/session-manager.js +54 -3
- package/dist/portal/session/session-successor.d.ts +8 -0
- package/dist/portal/session/session-successor.js +1 -1
- package/dist/portal/session/session.d.ts +15 -28
- package/dist/portal/session/session.js +60 -61
- 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 +7 -1
- package/dist/start-wiring.d.ts +63 -0
- package/dist/start-wiring.js +169 -0
- package/dist/status-payload.d.ts +13 -1
- package/dist/status-payload.js +13 -1
- package/dist/surface/http-server.js +7 -1
- 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 +4 -0
- package/dist/surface/mcp/mcp-proxy.js +29 -8
- package/dist/surface/mcp/mcp.d.ts +23 -0
- package/dist/surface/mcp/mcp.js +34 -4
- 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.js +22 -14
- package/dist/surface/mcp/shared-params.js +1 -1
- 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/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-sequence-tool.js +136 -27
- package/dist/surface/tools/act-tools.d.ts +0 -9
- package/dist/surface/tools/act-tools.js +48 -34
- 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.js +25 -15
- package/dist/surface/tools/browser-tools.js +43 -1
- package/dist/surface/tools/chat-drives.d.ts +75 -0
- package/dist/surface/tools/chat-drives.js +265 -21
- 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 +10 -0
- package/dist/surface/tools/empty-session-list.js +45 -5
- package/dist/surface/tools/error-recovery.d.ts +8 -0
- package/dist/surface/tools/error-recovery.js +69 -5
- package/dist/surface/tools/explore-tools.d.ts +23 -2
- package/dist/surface/tools/explore-tools.js +377 -74
- package/dist/surface/tools/feedback-tools.d.ts +2 -3
- package/dist/surface/tools/feedback-tools.js +4 -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 +52 -73
- package/dist/surface/tools/harness-explore.js +177 -146
- 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 +5 -0
- package/dist/surface/tools/harness-plan.js +7 -0
- package/dist/surface/tools/harness-script.d.ts +22 -0
- package/dist/surface/tools/harness-script.js +256 -38
- 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 +8 -0
- package/dist/surface/tools/harness-toolset.js +27 -4
- 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 +220 -93
- 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 +20 -0
- package/dist/surface/tools/lease-seed.js +45 -1
- package/dist/surface/tools/lease-tools.d.ts +10 -1
- package/dist/surface/tools/lease-tools.js +119 -69
- package/dist/surface/tools/live-call-text.js +2 -2
- 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 +11 -1
- package/dist/surface/tools/next-step.js +73 -18
- package/dist/surface/tools/observe-tools.js +43 -5
- package/dist/surface/tools/platform-moment.d.ts +60 -0
- package/dist/surface/tools/platform-moment.js +132 -4
- package/dist/surface/tools/read-tools.js +65 -14
- 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 +68 -2
- package/dist/surface/tools/tool-kit.js +73 -1
- package/dist/surface/tools/tools.js +25 -13
- 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 +27 -6
- package/dist/telemetry/hud-metrics.js +99 -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 +26 -2
- package/dist/telemetry/telemetry.js +102 -21
- package/dist/telemetry/verification-of.d.ts +3 -1
- package/dist/telemetry/verification-of.js +12 -4
- package/dist/wire-journal.d.ts +2 -2
- package/dist/wire-journal.js +16 -5
- package/docs/README.md +2 -2
- package/docs/actions.mdx +6 -3
- package/docs/adapters.md +1 -1
- package/docs/agent-cheatsheet.md +24 -27
- package/docs/architecture.md +5 -5
- package/docs/autodrive.md +13 -12
- 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 +8 -3
- package/docs/cli/drive.mdx +12 -12
- 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 +32 -15
- 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 +13 -4
- 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 +3 -2
- package/docs/cli.mdx +110 -41
- package/docs/debugging.md +3 -3
- package/docs/deploy-checks.md +1 -1
- package/docs/desktop.mdx +5 -3
- package/docs/enterprise.md +11 -10
- package/docs/environment.mdx +5 -2
- 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 +66 -64
- package/docs/human-control.md +15 -14
- package/docs/index.mdx +15 -43
- package/docs/install-agentic.mdx +22 -37
- package/docs/install-manual.mdx +22 -12
- 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 +8 -8
- package/docs/packages/test.mdx +4 -10
- package/docs/packages/vite-plugin.mdx +11 -4
- package/docs/packages.mdx +11 -15
- package/docs/platform-integration.md +6 -5
- package/docs/predicates.mdx +40 -24
- package/docs/quickstart.mdx +58 -29
- 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 +22 -24
- 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 +13 -4
- 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 +51 -45
- 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 +7 -5
- package/docs/what-is-reticle.mdx +2 -2
- package/docs/why-reticle.mdx +1 -1
- package/package.json +6 -5
- package/dist/command/cli/demo/demo-page.d.ts +0 -78
- package/dist/command/cli/demo/demo-page.js +0 -249
- package/dist/command/cli/demo/demo-run.d.ts +0 -38
- package/dist/command/cli/demo/demo-run.js +0 -138
- 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/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
|
@@ -1,26 +1,22 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* The harness switch, cached for a HUD that reads it inline.
|
|
3
|
-
*
|
|
4
|
-
* `fetchPlatformConfig` already asks the platform and parses the answer; this adds the one thing the
|
|
5
|
-
* impact snapshot needs and the drive path does not — a SYNCHRONOUS read. The snapshot is rebuilt
|
|
6
|
-
* dozens of times a session, the answer changes about as often as somebody opens a settings page,
|
|
7
|
-
* and a panel that awaited the network on every repaint would be a panel that stutters.
|
|
8
|
-
*
|
|
9
|
-
* Deliberately the same shape as `harnessOfferSource` next door rather than a shared abstraction:
|
|
10
|
-
* two callers with the same caching problem is not yet a pattern, and the day one of them needs a
|
|
11
|
-
* different staleness rule the shared version becomes the awkward one.
|
|
12
|
-
*
|
|
13
|
-
* Every failure answers `undefined`, which the HUD must read as "we have not heard" and render as NO
|
|
14
|
-
* control — never as "off". Showing a switch that cannot be honoured is worse than showing none.
|
|
15
|
-
*
|
|
16
|
-
* The loader arrives as a PORT rather than an import. Reading the platform lives in
|
|
17
|
-
* `features/harness`, and a cloud-memory file reaching into a feature is the reach the directory
|
|
18
|
-
* guard refuses — correctly, and for the same reason it refused the tool surface reaching the other
|
|
19
|
-
* way. Whoever wires the daemon owns both sides and can hand one to the other.
|
|
20
|
-
*/
|
|
21
1
|
import { writeHarnessSwitch } from './harness-switch.js';
|
|
22
2
|
/** How long a cached answer is trusted. A person who just changed it expects the panel to notice. */
|
|
23
3
|
const FRESH_MS = 30 * 1_000;
|
|
4
|
+
const DAY_MS = 24 * 60 * 60 * 1_000;
|
|
5
|
+
/**
|
|
6
|
+
* The answer as the HUD is pushed it: the grant's end date becomes whole days left, counted on the
|
|
7
|
+
* daemon's clock (the HUD has none worth trusting for this). No end date, no days. Pure.
|
|
8
|
+
*/
|
|
9
|
+
export function configForHud(config, now) {
|
|
10
|
+
if (config.credits === undefined)
|
|
11
|
+
return config;
|
|
12
|
+
const { endsAt, ...credits } = config.credits;
|
|
13
|
+
return {
|
|
14
|
+
...config,
|
|
15
|
+
credits: endsAt === undefined
|
|
16
|
+
? credits
|
|
17
|
+
: { ...credits, daysLeft: Math.max(0, Math.ceil((endsAt - now) / DAY_MS)) },
|
|
18
|
+
};
|
|
19
|
+
}
|
|
24
20
|
export function harnessConfigSource(load, now = () => Date.now()) {
|
|
25
21
|
let cached;
|
|
26
22
|
// `undefined` rather than 0: "never asked" is a different state from "asked at the epoch", and
|
|
@@ -61,6 +61,23 @@ export interface MemoryReadScope {
|
|
|
61
61
|
projectId: string | null | undefined;
|
|
62
62
|
subject?: string | undefined;
|
|
63
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* Who a memory read is for. An agent's read names the agent and the platform counts it as a
|
|
66
|
+
* consultation; the daemon's sync names its purpose and is never counted as one.
|
|
67
|
+
*/
|
|
68
|
+
export declare const MemoryReadHeader: {
|
|
69
|
+
readonly AGENT: "x-reticle-agent";
|
|
70
|
+
readonly PURPOSE: "x-reticle-read-purpose";
|
|
71
|
+
};
|
|
72
|
+
export declare const MemoryReadPurpose: {
|
|
73
|
+
readonly SYNC: "sync";
|
|
74
|
+
};
|
|
75
|
+
/**
|
|
76
|
+
* The headers of an agent's memory read: the key, and the agent whose call made the read. A replay's
|
|
77
|
+
* read went without the agent, and the platform credited it to "an agent that did not name itself".
|
|
78
|
+
* No agent is named when no single agent made the call: a guess would credit the wrong one.
|
|
79
|
+
*/
|
|
80
|
+
export declare function memoryReadHeaders(apiKey: string): Record<string, string>;
|
|
64
81
|
/**
|
|
65
82
|
* The URL for one memory read.
|
|
66
83
|
*
|
|
@@ -37,6 +37,7 @@
|
|
|
37
37
|
* constants live, and because both readers already reach this directory: a home under `recall/` would
|
|
38
38
|
* make `flows` reach a directory it never needed.
|
|
39
39
|
*/
|
|
40
|
+
import { callingClientName } from '../../hooks/coding-agents.js';
|
|
40
41
|
/**
|
|
41
42
|
* The path this module builds, spelled once, for the same reason as the names below.
|
|
42
43
|
*
|
|
@@ -71,6 +72,27 @@ export const MemoryScopeField = {
|
|
|
71
72
|
* a cast dressed up as a conversion.
|
|
72
73
|
*/
|
|
73
74
|
const projectToName = (projectId) => 'string' === typeof projectId && projectId.length > 0 ? projectId : undefined;
|
|
75
|
+
/**
|
|
76
|
+
* Who a memory read is for. An agent's read names the agent and the platform counts it as a
|
|
77
|
+
* consultation; the daemon's sync names its purpose and is never counted as one.
|
|
78
|
+
*/
|
|
79
|
+
export const MemoryReadHeader = {
|
|
80
|
+
AGENT: 'x-reticle-agent',
|
|
81
|
+
PURPOSE: 'x-reticle-read-purpose',
|
|
82
|
+
};
|
|
83
|
+
export const MemoryReadPurpose = { SYNC: 'sync' };
|
|
84
|
+
/**
|
|
85
|
+
* The headers of an agent's memory read: the key, and the agent whose call made the read. A replay's
|
|
86
|
+
* read went without the agent, and the platform credited it to "an agent that did not name itself".
|
|
87
|
+
* No agent is named when no single agent made the call: a guess would credit the wrong one.
|
|
88
|
+
*/
|
|
89
|
+
export function memoryReadHeaders(apiKey) {
|
|
90
|
+
const agent = callingClientName();
|
|
91
|
+
return {
|
|
92
|
+
authorization: `Bearer ${apiKey}`,
|
|
93
|
+
...(agent === undefined ? {} : { [MemoryReadHeader.AGENT]: agent }),
|
|
94
|
+
};
|
|
95
|
+
}
|
|
74
96
|
/**
|
|
75
97
|
* The URL for one memory read.
|
|
76
98
|
*
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { type ScreenshotSyncState } from './sync-screenshots.js';
|
|
1
2
|
/**
|
|
2
3
|
* The derived records that ride along with runs, and the file each one lives in.
|
|
3
4
|
*
|
|
@@ -34,18 +35,20 @@ export interface SyncSource {
|
|
|
34
35
|
runId: string;
|
|
35
36
|
payload: unknown;
|
|
36
37
|
}>;
|
|
37
|
-
/** Every saved flow.
|
|
38
|
+
/** Every saved flow. Upserted by name, so the set is sent only when it changed. */
|
|
38
39
|
flows: () => readonly unknown[];
|
|
39
40
|
/**
|
|
40
41
|
* Every bug capsule on disk — the minimal failing flow that reproduces a defect, plus its evidence.
|
|
41
42
|
*
|
|
42
|
-
*
|
|
43
|
+
* Sent like flows, only when the set changed: upserted by id, and worth nothing on the
|
|
43
44
|
* machine that found the bug. A verdict count tells a dashboard THAT something broke; the capsule
|
|
44
45
|
* is the only artifact that lets somebody else make it break again.
|
|
45
46
|
*/
|
|
46
47
|
capsules: () => readonly unknown[];
|
|
47
48
|
/** One derived record, or undefined when the file is absent. */
|
|
48
49
|
derived: (kind: DerivedKind) => unknown;
|
|
50
|
+
/** One step screenshot of a run. Absent when this project keeps its screenshots local. */
|
|
51
|
+
screenshot?: (runId: string, file: string) => Uint8Array | undefined;
|
|
49
52
|
}
|
|
50
53
|
/** What the machine writes back. Separated from reads so a dry run is a source with no sink. */
|
|
51
54
|
export interface SyncSink {
|
|
@@ -66,7 +69,7 @@ export interface PulledIssues {
|
|
|
66
69
|
triage: Record<string, PulledIssue>;
|
|
67
70
|
}
|
|
68
71
|
/** `.reticle/cloud-state.json`. This machine's side of the conversation, never git-checked. */
|
|
69
|
-
export interface CloudSyncState {
|
|
72
|
+
export interface CloudSyncState extends ScreenshotSyncState {
|
|
70
73
|
/** Opaque. Handed back to the server verbatim; the machine must never parse or invent one. */
|
|
71
74
|
cursor?: string;
|
|
72
75
|
lastPushAt?: number;
|
|
@@ -104,6 +107,21 @@ export interface CloudSyncState {
|
|
|
104
107
|
*/
|
|
105
108
|
sentFlowsHash?: string;
|
|
106
109
|
sentCapsulesHash?: string;
|
|
110
|
+
/**
|
|
111
|
+
* The hash of each derived record the platform last ACCEPTED from here. A platform that reports
|
|
112
|
+
* a hash of its own form of a record never matches ours, so the same record went every cycle.
|
|
113
|
+
*/
|
|
114
|
+
sentDerivedHashes?: Record<string, string>;
|
|
115
|
+
/** The names of the flows the platform last took from here: one gone from disk is deleted there. */
|
|
116
|
+
sentFlowNames?: string[];
|
|
117
|
+
/**
|
|
118
|
+
* The link everything above was kept for: cloud, workspace and project (`credentialSlot`). A
|
|
119
|
+
* folder re-linked elsewhere starts a fresh record, so the new link gets the flows the old one
|
|
120
|
+
* already had, and none of the old link's runs.
|
|
121
|
+
*/
|
|
122
|
+
link?: string;
|
|
123
|
+
/** When this folder was re-linked: runs made before it stay here unless the person moves them. */
|
|
124
|
+
linkedAt?: number;
|
|
107
125
|
/**
|
|
108
126
|
* A flow or capsule set the platform refused, kept so the refusal stays visible on the cycles that
|
|
109
127
|
* do not resend it, and so the set is offered again once it changes or the platform reads more.
|
|
@@ -131,6 +149,8 @@ export interface SyncReport {
|
|
|
131
149
|
ok: boolean;
|
|
132
150
|
/** Runs the server accepted this cycle. */
|
|
133
151
|
runsSent: number;
|
|
152
|
+
/** Step screenshots the server took this cycle, for runs it holds. */
|
|
153
|
+
screenshotsSent?: number;
|
|
134
154
|
/** Runs it refused, with the reason, so a bad artifact is visible rather than silently stuck. */
|
|
135
155
|
runsRejected: Array<{
|
|
136
156
|
index: number;
|
|
@@ -189,6 +209,12 @@ interface SyncDeps {
|
|
|
189
209
|
url: string;
|
|
190
210
|
apiKey: string;
|
|
191
211
|
};
|
|
212
|
+
/** The link this cycle sends for (`credentialSlot`); absent for an env-only key (CI). */
|
|
213
|
+
link?: string;
|
|
214
|
+
/** Send runs made under a previous link too: only ever because the person asked. */
|
|
215
|
+
moveHistory?: boolean;
|
|
216
|
+
/** The project flows are synced for. Absent when this cycle does not send flows: none is deleted. */
|
|
217
|
+
projectId?: string;
|
|
192
218
|
source: SyncSource;
|
|
193
219
|
sink: SyncSink;
|
|
194
220
|
state: CloudSyncState;
|
|
@@ -210,7 +236,9 @@ export declare const MSG_RUNS_UNCONFIRMED = "sync 200 without a runs result: the
|
|
|
210
236
|
* Run one cycle. Never throws: the local record is already safe on disk, and a sync that can take
|
|
211
237
|
* down the thing it is backing up is worse than no sync.
|
|
212
238
|
*/
|
|
213
|
-
|
|
239
|
+
/** The command that moves a folder's earlier runs to the link it has now. */
|
|
240
|
+
export declare const MOVE_HISTORY_COMMAND = "reticle sync --move-history";
|
|
241
|
+
export declare function runSyncCycle(given: SyncDeps): Promise<SyncReport>;
|
|
214
242
|
/** One line a human can read, for the CLI and the daemon log. */
|
|
215
243
|
export declare function describeSync(report: SyncReport): string;
|
|
216
244
|
export {};
|
|
@@ -30,12 +30,14 @@
|
|
|
30
30
|
* Every dependency is injected — the clock, the fetch, the reads and writes — because this is the
|
|
31
31
|
* one piece of Reticle that talks to a network AND to a disk, and it must be provable without either.
|
|
32
32
|
*/
|
|
33
|
-
import { FlowErrorCode, ReticleDir, SYNC_BATCH_LIMITS } from '@reticlehq/core';
|
|
33
|
+
import { FlowErrorCode, ReticleDir, SYNC_BATCH_LIMITS, flowJsonReplacer } from '@reticlehq/core';
|
|
34
34
|
import { hashPayload } from './sync-hash.js';
|
|
35
|
+
import { syncScreenshots } from './sync-screenshots.js';
|
|
35
36
|
/** The server's own doors. Kept beside the code that calls them, like the other cloud paths. */
|
|
36
37
|
const SYNC_PATH = '/v1/sync';
|
|
37
38
|
const SYNC_STATUS_PATH = '/v1/sync/status';
|
|
38
39
|
const SYNC_PULL_PATH = '/v1/sync/pull';
|
|
40
|
+
const FLOWS_PATH = '/v1/flows';
|
|
39
41
|
/**
|
|
40
42
|
* The derived records that ride along with runs, and the file each one lives in.
|
|
41
43
|
*
|
|
@@ -131,7 +133,29 @@ function batchRuns(runs) {
|
|
|
131
133
|
* Run one cycle. Never throws: the local record is already safe on disk, and a sync that can take
|
|
132
134
|
* down the thing it is backing up is worse than no sync.
|
|
133
135
|
*/
|
|
134
|
-
|
|
136
|
+
/** The command that moves a folder's earlier runs to the link it has now. */
|
|
137
|
+
export const MOVE_HISTORY_COMMAND = 'reticle sync --move-history';
|
|
138
|
+
/**
|
|
139
|
+
* The record this cycle keeps, for this link. Re-linked to another cloud, workspace or project, it
|
|
140
|
+
* starts afresh from now: what the old link was sent says nothing about the new one, and the runs
|
|
141
|
+
* made under the old link are that workspace's (a person's email can be in their steps), so they go
|
|
142
|
+
* only when the person moves them. A first link, or a record from before links were kept, is
|
|
143
|
+
* adopted as it is.
|
|
144
|
+
*/
|
|
145
|
+
function stateForLink(deps) {
|
|
146
|
+
const { state, link } = deps;
|
|
147
|
+
if (link === undefined)
|
|
148
|
+
return state;
|
|
149
|
+
if (state.link === undefined || state.link === link) {
|
|
150
|
+
const { linkedAt, ...rest } = state;
|
|
151
|
+
return true === deps.moveHistory || linkedAt === undefined
|
|
152
|
+
? { ...rest, link }
|
|
153
|
+
: { ...rest, link, linkedAt };
|
|
154
|
+
}
|
|
155
|
+
return { link, ...(true === deps.moveHistory ? {} : { linkedAt: deps.now() }) };
|
|
156
|
+
}
|
|
157
|
+
export async function runSyncCycle(given) {
|
|
158
|
+
const deps = { ...given, state: stateForLink(given) };
|
|
135
159
|
const empty = {
|
|
136
160
|
ok: false,
|
|
137
161
|
runsSent: 0,
|
|
@@ -237,7 +261,14 @@ export async function runSyncCycle(deps) {
|
|
|
237
261
|
notRetried.push({ runId: run.runId, reason: prior.reason });
|
|
238
262
|
return false;
|
|
239
263
|
});
|
|
264
|
+
// Made before this folder was linked here: the previous link's, kept until the person moves it.
|
|
265
|
+
const linkedAt = deps.state.linkedAt;
|
|
266
|
+
const earlier = unsent.filter((run) => linkedAt !== undefined && !((numberAt(run.payload, 'createdAt') ?? 0) >= linkedAt));
|
|
267
|
+
if (0 < earlier.length)
|
|
268
|
+
heldBack.push(`${String(earlier.length)} run${1 === earlier.length ? '' : 's'} made before this folder was linked to this workspace stay${1 === earlier.length ? 's' : ''} on this machine (recorded under its previous link): run \`${MOVE_HISTORY_COMMAND}\` to send ${1 === earlier.length ? 'it' : 'them'} here`);
|
|
240
269
|
const sendable = unsent.filter((run) => {
|
|
270
|
+
if (earlier.includes(run))
|
|
271
|
+
return false;
|
|
241
272
|
const version = numberAt(run.payload, 'schemaVersion');
|
|
242
273
|
if (runVersions === undefined || version === undefined || runVersions.includes(version))
|
|
243
274
|
return true;
|
|
@@ -248,25 +279,51 @@ export async function runSyncCycle(deps) {
|
|
|
248
279
|
const derivedOffered = [];
|
|
249
280
|
const unsupported = [];
|
|
250
281
|
const bundle = {};
|
|
282
|
+
// A folder re-linked elsewhere keeps what it derived under the old link (its counts, defects,
|
|
283
|
+
// notes) here with the runs: those records add up the whole history and cannot be split by time.
|
|
284
|
+
// ponytail: held until `--move-history`; a per-link reset of the counters would let new ones go.
|
|
285
|
+
const derivedHeld = [];
|
|
251
286
|
for (const { kind } of DERIVED_RECORDS) {
|
|
252
287
|
const payload = deps.source.derived(kind);
|
|
253
288
|
if (payload === undefined)
|
|
254
289
|
continue;
|
|
290
|
+
if (linkedAt !== undefined) {
|
|
291
|
+
derivedHeld.push(kind);
|
|
292
|
+
continue;
|
|
293
|
+
}
|
|
255
294
|
if (!acceptedKinds.has(kind)) {
|
|
256
295
|
unsupported.push(kind);
|
|
257
296
|
continue;
|
|
258
297
|
}
|
|
259
|
-
// The one comparison the whole protocol rests on. Same hash, do not send it
|
|
260
|
-
|
|
298
|
+
// The one comparison the whole protocol rests on. Same hash, do not send it: the platform's,
|
|
299
|
+
// or the one it accepted from here while it still holds the record (a null means it does not).
|
|
300
|
+
const hash = hashPayload(payload);
|
|
301
|
+
if (hash === hashes[kind])
|
|
302
|
+
continue;
|
|
303
|
+
if ('string' === typeof hashes[kind] && hash === deps.state.sentDerivedHashes?.[kind])
|
|
261
304
|
continue;
|
|
262
305
|
bundle[kind] = payload;
|
|
263
306
|
derivedOffered.push(kind);
|
|
264
307
|
}
|
|
265
308
|
if (unsupported.length > 0)
|
|
266
309
|
heldBack.push(`this platform does not accept ${unsupported.join(', ')} yet`);
|
|
310
|
+
if (0 < derivedHeld.length)
|
|
311
|
+
heldBack.push(`the ${derivedHeld.join(', ')} record${1 === derivedHeld.length ? '' : 's'} made under this folder's previous link stay${1 === derivedHeld.length ? 's' : ''} on this machine: run \`${MOVE_HISTORY_COMMAND}\` to send ${1 === derivedHeld.length ? 'it' : 'them'} here`);
|
|
267
312
|
// Flows and capsules are upserted by name/id, so the whole set goes whenever it differs from the
|
|
268
|
-
// set the platform last answered for
|
|
269
|
-
|
|
313
|
+
// set the platform last answered for — and only then. Riding along with every run push re-sent
|
|
314
|
+
// ~1.3 MB per push on a real repo, and a POST that size timed out and failed the run with it.
|
|
315
|
+
// Made before this folder was linked here, like the runs: the previous link's, kept until moved.
|
|
316
|
+
// A flow carries the steps of whoever drove it, so it is that workspace's as much as a run is.
|
|
317
|
+
// One read for both halves: the disk source rebuilds every flow per read, so a second read's
|
|
318
|
+
// objects are never `includes` of the first's, and every held-back flow went out anyway.
|
|
319
|
+
const flowsAll = deps.source.flows();
|
|
320
|
+
const madeBefore = (flow) => linkedAt !== undefined && !((numberAt(flow, 'createdAt') ?? 0) >= linkedAt);
|
|
321
|
+
const flowsBefore = flowsAll.filter(madeBefore);
|
|
322
|
+
if (0 < flowsBefore.length)
|
|
323
|
+
heldBack.push(`${String(flowsBefore.length)} flow${1 === flowsBefore.length ? '' : 's'} made before this folder was linked to this workspace stay${1 === flowsBefore.length ? 's' : ''} on this machine: run \`${MOVE_HISTORY_COMMAND}\` to send ${1 === flowsBefore.length ? 'it' : 'them'} here`);
|
|
324
|
+
const flows = flowsAll.filter((flow, index) => {
|
|
325
|
+
if (madeBefore(flow))
|
|
326
|
+
return false;
|
|
270
327
|
const version = numberAt(flow, 'version');
|
|
271
328
|
if (flowVersions === undefined || version === undefined || flowVersions.includes(version))
|
|
272
329
|
return true;
|
|
@@ -296,10 +353,9 @@ export async function runSyncCycle(deps) {
|
|
|
296
353
|
};
|
|
297
354
|
const flowsChanged = due('flow', flowsHash, flows.length, deps.state.sentFlowsHash);
|
|
298
355
|
const capsulesChanged = due('capsule', capsulesHash, capsulesAll.length, deps.state.sentCapsulesHash);
|
|
299
|
-
|
|
300
|
-
if (ridesAlong && flows.length > 0)
|
|
356
|
+
if (flowsChanged)
|
|
301
357
|
bundle['flows'] = flows;
|
|
302
|
-
const capsules =
|
|
358
|
+
const capsules = capsulesChanged ? capsulesAll : [];
|
|
303
359
|
if (capsules.length > 0)
|
|
304
360
|
bundle['capsules'] = capsules;
|
|
305
361
|
let runsSent = 0;
|
|
@@ -321,7 +377,11 @@ export async function runSyncCycle(deps) {
|
|
|
321
377
|
const body = 0 === i ? { ...bundle } : {};
|
|
322
378
|
if (batch.length > 0)
|
|
323
379
|
body['runs'] = batch.map((r) => r.payload);
|
|
324
|
-
|
|
380
|
+
// The flows ride here too: a default flag stays out of them, as on disk.
|
|
381
|
+
const pushed = await call(SYNC_PATH, {
|
|
382
|
+
method: 'POST',
|
|
383
|
+
body: JSON.stringify(body, flowJsonReplacer),
|
|
384
|
+
});
|
|
325
385
|
if (200 !== pushed.status) {
|
|
326
386
|
pushError = `sync ${String(pushed.status)}: ${pushed.text.slice(0, 200)}`;
|
|
327
387
|
break;
|
|
@@ -388,18 +448,40 @@ export async function runSyncCycle(deps) {
|
|
|
388
448
|
const state = isRecord(answer['state']) ? answer['state'] : {};
|
|
389
449
|
for (const kind of derivedOffered) {
|
|
390
450
|
const verdict = state[kind];
|
|
391
|
-
if ('accepted' === verdict)
|
|
451
|
+
if ('accepted' === verdict) {
|
|
392
452
|
derivedSent.push(kind);
|
|
453
|
+
nextState.sentDerivedHashes = {
|
|
454
|
+
...nextState.sentDerivedHashes,
|
|
455
|
+
[kind]: hashPayload(bundle[kind]),
|
|
456
|
+
};
|
|
457
|
+
}
|
|
393
458
|
else if ('string' === typeof verdict)
|
|
394
459
|
refused.push({ part: kind, reason: `${kind}: ${verdict}` });
|
|
395
460
|
}
|
|
396
461
|
}
|
|
462
|
+
// A flow the platform took from here and that is gone from disk is deleted there by name: it
|
|
463
|
+
// does not infer a deletion from a missing name, since another clone may still hold the flow.
|
|
464
|
+
const onDisk = new Set(deps.source.flows().map(flowName));
|
|
465
|
+
const kept = [];
|
|
466
|
+
for (const name of deps.projectId === undefined ? [] : (deps.state.sentFlowNames ?? [])) {
|
|
467
|
+
if (onDisk.has(name)) {
|
|
468
|
+
kept.push(name);
|
|
469
|
+
continue;
|
|
470
|
+
}
|
|
471
|
+
const gone = await call(`${FLOWS_PATH}/${encodeURIComponent(name)}?projectId=${encodeURIComponent(deps.projectId ?? '')}`, { method: 'DELETE' });
|
|
472
|
+
if (2 !== Math.floor(gone.status / 100) && 404 !== gone.status)
|
|
473
|
+
kept.push(name);
|
|
474
|
+
}
|
|
475
|
+
if (deps.projectId !== undefined)
|
|
476
|
+
nextState.sentFlowNames = kept;
|
|
397
477
|
if (requests > 0 && pushError === undefined) {
|
|
398
478
|
nextState.lastPushAt = deps.now();
|
|
399
479
|
// The platform answered for these sets, refusals included (reported above, and not re-offered
|
|
400
480
|
// until the set changes — the same rule as a refused run).
|
|
401
|
-
if (
|
|
481
|
+
if (flowsChanged)
|
|
402
482
|
nextState.sentFlowsHash = flowsHash;
|
|
483
|
+
if (flowsChanged && deps.projectId !== undefined)
|
|
484
|
+
nextState.sentFlowNames = [...new Set([...kept, ...flows.map(flowName)])];
|
|
403
485
|
if (capsules.length > 0)
|
|
404
486
|
nextState.sentCapsulesHash = capsulesHash;
|
|
405
487
|
}
|
|
@@ -429,6 +511,22 @@ export async function runSyncCycle(deps) {
|
|
|
429
511
|
*/
|
|
430
512
|
nextState.sentRunIds = allRuns.map((r) => r.runId).filter((id) => known.has(id));
|
|
431
513
|
nextState.sentRunHashes = heldHashes(allRuns, recorded);
|
|
514
|
+
// 2b. The step screenshots of every run the platform now holds, once each.
|
|
515
|
+
let screenshotsSent = 0;
|
|
516
|
+
const readImage = deps.source.screenshot;
|
|
517
|
+
if (readImage !== undefined) {
|
|
518
|
+
const shots = await syncScreenshots({
|
|
519
|
+
runs: allRuns,
|
|
520
|
+
accepted: (runId) => known.has(runId),
|
|
521
|
+
readImage,
|
|
522
|
+
state: deps.state,
|
|
523
|
+
post: (path, body) => call(path, { method: 'POST', body }),
|
|
524
|
+
});
|
|
525
|
+
screenshotsSent = shots.sent;
|
|
526
|
+
Object.assign(nextState, shots.state);
|
|
527
|
+
if (shots.error !== undefined)
|
|
528
|
+
heldBack.push(shots.error);
|
|
529
|
+
}
|
|
432
530
|
// 3. COLLECT — always, even when there was nothing to send.
|
|
433
531
|
const query = nextState.cursor === undefined ? '' : `?since=${encodeURIComponent(nextState.cursor)}`;
|
|
434
532
|
const pull = await call(`${SYNC_PULL_PATH}${query}`);
|
|
@@ -477,6 +575,7 @@ export async function runSyncCycle(deps) {
|
|
|
477
575
|
0 === setsNotRetried.length &&
|
|
478
576
|
!heldArtifacts,
|
|
479
577
|
runsSent,
|
|
578
|
+
...(0 === screenshotsSent ? {} : { screenshotsSent }),
|
|
480
579
|
runsRejected,
|
|
481
580
|
flowsSent,
|
|
482
581
|
capsulesSent,
|
|
@@ -550,6 +649,8 @@ export function describeSync(report) {
|
|
|
550
649
|
sent.push(`${String(report.flowsSent)} flow(s)`);
|
|
551
650
|
if (report.capsulesSent > 0)
|
|
552
651
|
sent.push(`${String(report.capsulesSent)} capsule(s)`);
|
|
652
|
+
if ((report.screenshotsSent ?? 0) > 0)
|
|
653
|
+
sent.push(`${String(report.screenshotsSent)} screenshot(s)`);
|
|
553
654
|
if (report.derivedSent.length > 0)
|
|
554
655
|
sent.push(report.derivedSent.join(', '));
|
|
555
656
|
/*
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { type SyncReport } from './sync-cycle.js';
|
|
2
2
|
import { type ProjectCloud } from './cloud-config.js';
|
|
3
|
+
import { type UnsyncedRoot } from './unsynced-roots.js';
|
|
3
4
|
import type { FileSystemPort } from '../project/fs/fs-port.js';
|
|
4
5
|
interface SyncDaemonDeps {
|
|
5
6
|
reticleRoot: string;
|
|
@@ -20,6 +21,11 @@ interface SyncDaemonDeps {
|
|
|
20
21
|
cloudFor?: (root: string) => Promise<ProjectCloud>;
|
|
21
22
|
now?: () => number;
|
|
22
23
|
intervalMs?: number;
|
|
24
|
+
/**
|
|
25
|
+
* Call `onChange` when this root's link file changes; returns how to stop. A re-link was read only
|
|
26
|
+
* on the next idle tick, so a daemon kept syncing to the old link for up to a minute.
|
|
27
|
+
*/
|
|
28
|
+
watchLink?: (onChange: () => void) => () => void;
|
|
23
29
|
/** Injected for the test; the real one is `fetch`. */
|
|
24
30
|
request?: (url: string, init: {
|
|
25
31
|
method: string;
|
|
@@ -58,6 +64,11 @@ export interface SyncDaemon {
|
|
|
58
64
|
* time — the artifact is still on disk and the next daemon for this project sends it.
|
|
59
65
|
*/
|
|
60
66
|
flush: () => Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Every root this daemon knows with runs the platform does not have, as of the last cycle — linked
|
|
69
|
+
* or not. An unlinked one is the case nothing will ever send, and it used to be skipped silently.
|
|
70
|
+
*/
|
|
71
|
+
unsyncedRoots: () => readonly UnsyncedRoot[];
|
|
61
72
|
}
|
|
62
73
|
/**
|
|
63
74
|
* Start the loop. Safe to call for an UNLINKED project: it resolves the link on every tick and does
|