@reticlehq/server 3.2.0 → 3.4.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/LICENSE-ENTERPRISE +1 -1
- package/README.md +3 -3
- package/SKILL.md +23 -22
- package/dist/chromium-launch-options.d.ts +4 -3
- package/dist/chromium-launch-options.js +6 -2
- package/dist/command/cli/adhoc-suite.d.ts +41 -0
- package/dist/command/cli/adhoc-suite.js +159 -0
- package/dist/command/cli/adhoc-verdict.d.ts +58 -2
- package/dist/command/cli/adhoc-verdict.js +108 -13
- package/dist/command/cli/answers/gate-hook-message.d.ts +6 -0
- package/dist/command/cli/answers/gate-hook-message.js +6 -0
- package/dist/command/cli/auth/cloud-keystore.d.ts +0 -2
- package/dist/command/cli/auth/cloud-keystore.js +0 -3
- package/dist/command/cli/auth/cloud-session.d.ts +4 -0
- package/dist/command/cli/auth/cloud-session.js +2 -0
- package/dist/command/cli/cli-doctor.js +30 -8
- package/dist/command/cli/cli-flow-commands.d.ts +3 -6
- package/dist/command/cli/cli-flow-commands.js +67 -4
- package/dist/command/cli/cli-parse-grammar.d.ts +7 -0
- package/dist/command/cli/cli-parse-grammar.js +7 -0
- package/dist/command/cli/cli-parse-verify.d.ts +2 -5
- package/dist/command/cli/cli-parse-verify.js +86 -13
- package/dist/command/cli/cli-parse.d.ts +14 -1
- package/dist/command/cli/cli-parse.js +54 -8
- package/dist/command/cli/cli-update-commands.js +8 -1
- package/dist/command/cli/cli-verify.d.ts +80 -0
- package/dist/command/cli/cli-verify.js +181 -26
- package/dist/command/cli/cloud-cli.js +5 -2
- package/dist/command/cli/cloud-kit.d.ts +0 -2
- package/dist/command/cli/cloud-kit.js +3 -5
- package/dist/command/cli/cloud-login.js +21 -3
- package/dist/command/cli/demo/demo-page.js +6 -3
- package/dist/command/cli/doctor/browser/chromium-hint.d.ts +5 -0
- package/dist/command/cli/doctor/browser/chromium-hint.js +5 -0
- package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
- package/dist/command/cli/launch/cli-launch.d.ts +9 -29
- package/dist/command/cli/launch/cli-launch.js +27 -49
- package/dist/command/cli/launch/sdk-version-match.d.ts +84 -0
- package/dist/command/cli/launch/sdk-version-match.js +206 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +2 -16
- package/dist/command/cli/ports/resolve/cli-port.d.ts +38 -0
- package/dist/command/cli/ports/resolve/cli-port.js +169 -15
- package/dist/command/cli/report-command.d.ts +16 -0
- package/dist/command/cli/report-command.js +97 -0
- package/dist/command/cli/setup-mcp-cli.js +13 -13
- package/dist/command/cli/tutorial.d.ts +2 -2
- package/dist/command/cli/tutorial.js +21 -7
- package/dist/command/cli.js +67 -10
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +44 -2
- package/dist/command/daemon/binding/daemon-status-probe.js +79 -6
- package/dist/command/daemon/binding/port-presence.d.ts +1 -1
- package/dist/command/daemon/daemon-resolve.d.ts +9 -0
- package/dist/command/daemon/daemon-resolve.js +1 -1
- package/dist/command/daemon/idle-shutdown.d.ts +2 -1
- package/dist/command/daemon/lifetime/daemon-usefulness.d.ts +7 -1
- package/dist/command/daemon/lifetime/daemon-usefulness.js +30 -7
- package/dist/command/dev/stale-issue-guard.d.ts +3 -4
- package/dist/command/dev/stale-issue-guard.js +8 -8
- package/dist/command/setup/bringup/connect-lease.d.ts +17 -0
- package/dist/command/setup/bringup/connect-lease.js +38 -0
- package/dist/command/setup/bringup/dev-server-files.d.ts +68 -0
- package/dist/command/setup/bringup/dev-server-files.js +131 -0
- package/dist/command/setup/bringup/dev-server-log-cap.d.ts +35 -0
- package/dist/command/setup/bringup/dev-server-log-cap.js +121 -0
- package/dist/command/setup/bringup/ensure-daemon.d.ts +65 -4
- package/dist/command/setup/bringup/ensure-daemon.js +135 -16
- package/dist/command/setup/bringup/static-page-server.d.ts +35 -0
- package/dist/command/setup/bringup/static-page-server.js +151 -0
- package/dist/command/setup/desktop-shape.d.ts +4 -0
- package/dist/command/setup/desktop-shape.js +18 -2
- package/dist/command/setup/init/init-host.js +8 -0
- package/dist/command/setup/init/init-port.d.ts +15 -0
- package/dist/command/setup/init/init-port.js +44 -0
- package/dist/command/setup/init/init-runtime.d.ts +1 -1
- package/dist/command/setup/init/init-runtime.js +39 -2
- package/dist/command/setup/node-effects.d.ts +27 -14
- package/dist/command/setup/node-effects.js +80 -44
- package/dist/command/setup/probe/loopback-probe-urls.d.ts +7 -0
- package/dist/command/setup/probe/loopback-probe-urls.js +40 -0
- package/dist/command/setup/probe/page-probe.d.ts +13 -2
- package/dist/command/setup/probe/page-probe.js +18 -3
- package/dist/command/setup/run-setup.d.ts +26 -1
- package/dist/command/setup/run-setup.js +96 -13
- package/dist/command/setup/session-pick.d.ts +13 -0
- package/dist/command/setup/session-pick.js +20 -0
- package/dist/command/setup/setup-command.d.ts +2 -14
- package/dist/command/setup/setup-command.js +105 -31
- package/dist/command/setup/setup-mcp.js +3 -3
- package/dist/command/setup/terminal/wait-progress.d.ts +8 -0
- package/dist/command/setup/terminal/wait-progress.js +17 -0
- package/dist/features/crawl/crawl-empty.js +1 -1
- package/dist/features/crawl/crawl-tools.d.ts +6 -0
- package/dist/features/crawl/crawl-tools.js +57 -0
- package/dist/features/crawl/crawl.d.ts +2 -0
- package/dist/features/crawl/crawl.js +171 -156
- package/dist/features/exhaust/app-coverage.d.ts +33 -0
- package/dist/features/exhaust/app-coverage.js +31 -0
- package/dist/features/exhaust/code-coverage.d.ts +47 -0
- package/dist/features/exhaust/code-coverage.js +77 -0
- package/dist/features/exhaust/exhaust-run.d.ts +33 -0
- package/dist/features/exhaust/exhaust-run.js +82 -0
- package/dist/features/exhaust/explorer.d.ts +103 -0
- package/dist/features/exhaust/explorer.js +195 -0
- package/dist/features/exhaust/failure-branches.d.ts +33 -0
- package/dist/features/exhaust/failure-branches.js +92 -0
- package/dist/features/exhaust/ledger.d.ts +202 -0
- package/dist/features/exhaust/ledger.js +252 -0
- package/dist/features/exhaust/session-fold.d.ts +31 -0
- package/dist/features/exhaust/session-fold.js +79 -0
- package/dist/features/exhaust/session-port.d.ts +36 -0
- package/dist/features/exhaust/session-port.js +102 -0
- package/dist/features/harness/drive-report.d.ts +0 -9
- package/dist/features/harness/drive-report.js +18 -0
- package/dist/features/harness/driver.js +4 -7
- package/dist/features/harness/fill-values.d.ts +6 -0
- package/dist/features/harness/fill-values.js +3 -0
- package/dist/features/harness/jev-driver.js +36 -22
- package/dist/features/harness/openai-driver.js +4 -7
- package/dist/features/harness/platform-config.d.ts +10 -0
- package/dist/features/harness/platform-config.js +13 -6
- package/dist/index.d.ts +10 -1
- package/dist/index.js +78 -104
- package/dist/judgement/capsule/capsule-store.d.ts +31 -2
- package/dist/judgement/capsule/capsule-store.js +58 -6
- package/dist/judgement/capsule/capsule.js +5 -0
- package/dist/judgement/capsule/causal-summary.d.ts +13 -1
- package/dist/judgement/capsule/causal-summary.js +7 -0
- package/dist/judgement/domain/domain-model.js +40 -9
- package/dist/judgement/oracles/self-instrument.js +4 -2
- package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
- package/dist/judgement/runs/artifact/gap-report.d.ts +17 -0
- package/dist/judgement/runs/artifact/gap-report.js +46 -0
- package/dist/judgement/runs/artifact/gap-summary.d.ts +58 -0
- package/dist/judgement/runs/artifact/gap-summary.js +85 -0
- package/dist/judgement/runs/artifact/render-report.js +4 -1
- package/dist/judgement/runs/artifact/replay-mapping.d.ts +2 -2
- package/dist/judgement/runs/artifact/replay-mapping.js +44 -9
- package/dist/judgement/runs/artifact/to-artifact.d.ts +7 -2
- package/dist/judgement/runs/artifact/to-artifact.js +1 -1
- package/dist/judgement/runs/context-tools.js +21 -3
- package/dist/judgement/runs/drive-run.js +7 -2
- package/dist/judgement/runs/verification-sync.d.ts +3 -1
- package/dist/judgement/runs/verification-sync.js +1 -1
- package/dist/language/flows/annotate-notes/annotate.d.ts +0 -15
- package/dist/language/flows/annotate-notes/annotate.js +66 -18
- package/dist/language/flows/change/affected.d.ts +9 -0
- package/dist/language/flows/change/affected.js +35 -0
- package/dist/language/flows/change/gate.d.ts +20 -0
- package/dist/language/flows/change/gate.js +12 -1
- package/dist/language/flows/flow-anchor.d.ts +12 -0
- package/dist/language/flows/flow-anchor.js +20 -0
- package/dist/language/flows/flow-author.d.ts +7 -0
- package/dist/language/flows/flow-author.js +19 -0
- package/dist/language/flows/flow-expect-grammar.d.ts +2 -2
- package/dist/language/flows/flow-expect-grammar.js +92 -11
- package/dist/language/flows/flow-intent.js +1 -1
- package/dist/language/flows/flow-journey.d.ts +54 -0
- package/dist/language/flows/flow-journey.js +119 -0
- package/dist/language/flows/flow-learning.d.ts +3 -0
- package/dist/language/flows/flow-learning.js +39 -8
- package/dist/language/flows/flow-replay-run.d.ts +33 -12
- package/dist/language/flows/flow-replay-run.js +131 -52
- package/dist/language/flows/flow-replay-types.d.ts +9 -0
- package/dist/language/flows/flow-replay.d.ts +27 -12
- package/dist/language/flows/flow-replay.js +127 -111
- package/dist/language/flows/flow-result.d.ts +2 -0
- package/dist/language/flows/flow-result.js +25 -0
- package/dist/language/flows/flow-step-runners.d.ts +26 -10
- package/dist/language/flows/flow-step-runners.js +20 -4
- package/dist/language/flows/flow-success.d.ts +21 -6
- package/dist/language/flows/flow-success.js +50 -138
- package/dist/language/flows/flow-tools.js +17 -5
- package/dist/language/flows/flows.d.ts +18 -5
- package/dist/language/flows/flows.js +101 -16
- package/dist/language/flows/heal.d.ts +9 -1
- package/dist/language/flows/heal.js +24 -2
- package/dist/language/flows/learned-sources.d.ts +21 -0
- package/dist/language/flows/learned-sources.js +84 -0
- package/dist/language/flows/recording/recording-backtrack.d.ts +0 -7
- package/dist/language/flows/recording/recording-backtrack.js +1 -1
- package/dist/language/flows/recording/replay-halt.d.ts +2 -1
- package/dist/language/flows/recording/replay-halt.js +3 -1
- package/dist/language/flows/recording/tape/recordings.d.ts +31 -2
- package/dist/language/flows/recording/tape/recordings.js +55 -1
- package/dist/language/flows/replay.d.ts +19 -0
- package/dist/language/flows/replay.js +53 -13
- package/dist/language/flows/stores/annotation-store.d.ts +5 -5
- package/dist/language/flows/stores/assertion-tiers-store.js +2 -3
- package/dist/language/flows/stores/flake-store.js +2 -3
- package/dist/language/flows/suite/coverage.d.ts +1 -1
- package/dist/language/flows/suite/parallel-suite.d.ts +2 -1
- package/dist/language/flows/verify-change-tools.js +19 -2
- package/dist/launch-chromium.d.ts +80 -0
- package/dist/launch-chromium.js +218 -0
- package/dist/memory/cloud/cloud-config.d.ts +11 -2
- package/dist/memory/cloud/cloud-config.js +47 -7
- package/dist/memory/cloud/cloud-sync.d.ts +4 -3
- package/dist/memory/cloud/cloud-sync.js +7 -10
- package/dist/memory/cloud/harness-config.d.ts +2 -0
- package/dist/memory/cloud/harness-offer.js +5 -6
- package/dist/memory/cloud/harness-switch.js +5 -6
- package/dist/memory/cloud/sync-cycle.d.ts +78 -1
- package/dist/memory/cloud/sync-cycle.js +321 -53
- package/dist/memory/cloud/sync-daemon.d.ts +13 -0
- package/dist/memory/cloud/sync-daemon.js +45 -20
- package/dist/memory/cloud/sync-disk.js +27 -8
- package/dist/memory/impact/impact-store.js +6 -0
- package/dist/memory/intent/inline-intent.js +8 -3
- package/dist/memory/intent/intent-shard-store.d.ts +33 -47
- package/dist/memory/intent/intent-shard-store.js +252 -140
- package/dist/memory/intent/intent-shard.d.ts +0 -23
- package/dist/memory/intent/intent-shard.js +1 -11
- package/dist/memory/intent/intent-store.d.ts +13 -8
- package/dist/memory/intent/intent-store.js +46 -90
- package/dist/memory/intent/intent-tools.js +34 -23
- package/dist/memory/journal/ambient-store.js +2 -3
- package/dist/memory/journal/deviation-report.js +4 -1
- package/dist/memory/journal/deviation-service.js +10 -2
- package/dist/memory/journal/drive-flow.d.ts +19 -14
- package/dist/memory/journal/drive-flow.js +65 -48
- package/dist/memory/journal/envelope-store.js +2 -3
- package/dist/memory/journal/journal-recorder.d.ts +21 -0
- package/dist/memory/journal/on-disk/retain-policy.d.ts +34 -0
- package/dist/memory/journal/on-disk/retain-policy.js +44 -0
- package/dist/memory/journal/on-disk/retention.d.ts +14 -10
- package/dist/memory/journal/on-disk/retention.js +13 -12
- package/dist/memory/journal/on-disk/startup-maintenance.d.ts +42 -0
- package/dist/memory/journal/on-disk/startup-maintenance.js +14 -0
- package/dist/memory/journal/on-disk/workspace-gitignore.d.ts +0 -11
- package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -45
- package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
- package/dist/memory/journal/on-disk/workspace-tiers.js +90 -0
- package/dist/memory/journal/route-template.d.ts +22 -0
- package/dist/memory/journal/route-template.js +44 -0
- package/dist/memory/journal/session-end.d.ts +13 -2
- package/dist/memory/journal/session-end.js +88 -18
- package/dist/memory/journal/session-journal.d.ts +8 -1
- package/dist/memory/journal/session-journal.js +10 -0
- package/dist/memory/project/baselines.d.ts +1 -1
- package/dist/memory/project/dir/reticle-dir.d.ts +3 -1
- package/dist/memory/project/dir/reticle-dir.js +1 -0
- package/dist/memory/project/fs/fs-port.js +44 -5
- package/dist/memory/project/fs/write-atomic.d.ts +26 -0
- package/dist/memory/project/fs/write-atomic.js +48 -0
- package/dist/memory/project/project-tools.js +3 -1
- package/dist/memory/recall/prior/connection-memory.d.ts +6 -0
- package/dist/memory/recall/prior/connection-memory.js +8 -0
- package/dist/memory/recall/registered-projects.d.ts +2 -1
- package/dist/portal/bridge/auth-failure-reason.d.ts +1 -1
- package/dist/portal/bridge/auth-failure-reason.js +9 -4
- package/dist/portal/bridge/bridge.d.ts +8 -0
- package/dist/portal/bridge/bridge.js +43 -2
- package/dist/portal/input/js-coverage.d.ts +25 -0
- package/dist/portal/input/js-coverage.js +30 -0
- package/dist/portal/input/real-input.d.ts +11 -0
- package/dist/portal/input/real-input.js +31 -5
- package/dist/portal/pool/browser-pool.d.ts +10 -0
- package/dist/portal/pool/browser-pool.js +10 -0
- package/dist/portal/pool/playwright-launcher.d.ts +6 -0
- package/dist/portal/pool/playwright-launcher.js +21 -13
- package/dist/portal/pool/pool-contract.d.ts +2 -0
- package/dist/portal/pool/storage-seed.d.ts +2 -1
- package/dist/portal/pool/zero-install.d.ts +27 -0
- package/dist/portal/pool/zero-install.js +54 -0
- package/dist/portal/realm/web-realm.js +6 -0
- package/dist/portal/session/dev-server/dev-command.d.ts +2 -2
- package/dist/portal/session/dev-server/dev-command.js +30 -12
- package/dist/portal/session/dev-server/dev-server-probe.d.ts +2 -1
- package/dist/portal/session/dev-server/dev-server-probe.js +17 -1
- package/dist/portal/session/dev-server/route-status-probe.d.ts +24 -0
- package/dist/portal/session/dev-server/route-status-probe.js +57 -0
- package/dist/portal/session/dev-server/served-document.d.ts +21 -0
- package/dist/portal/session/dev-server/served-document.js +57 -0
- package/dist/portal/session/facts/background-traffic.d.ts +9 -0
- package/dist/portal/session/facts/background-traffic.js +25 -0
- package/dist/portal/session/facts/observed-state.d.ts +11 -0
- package/dist/portal/session/facts/observed-state.js +34 -0
- package/dist/portal/session/live-control-tools.js +48 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +29 -0
- package/dist/portal/session/no-session-diagnosis.js +62 -5
- package/dist/portal/session/no-session-next-action.d.ts +13 -0
- package/dist/portal/session/no-session-next-action.js +48 -9
- package/dist/portal/session/no-session-watch.d.ts +18 -0
- package/dist/portal/session/no-session-watch.js +88 -2
- package/dist/portal/session/presence/attachment-history.d.ts +13 -2
- package/dist/portal/session/session-health.d.ts +61 -0
- package/dist/portal/session/session-health.js +43 -3
- package/dist/portal/session/session-info.d.ts +6 -0
- package/dist/portal/session/session-manager.d.ts +29 -6
- package/dist/portal/session/session-manager.js +42 -5
- package/dist/portal/session/session-reaper.d.ts +28 -0
- package/dist/portal/session/session-reaper.js +49 -1
- package/dist/portal/session/session-successor.d.ts +11 -0
- package/dist/portal/session/session-successor.js +14 -1
- package/dist/portal/session/session-verdict-facts.d.ts +28 -0
- package/dist/portal/session/session-verdict-facts.js +15 -0
- package/dist/portal/session/session.d.ts +10 -0
- package/dist/portal/session/session.js +34 -26
- package/dist/surface/http-server.d.ts +2 -1
- package/dist/surface/http-server.js +4 -2
- package/dist/surface/mcp/mcp-proxy.d.ts +2 -2
- package/dist/surface/mcp/mcp-proxy.js +5 -5
- package/dist/surface/mcp/mcp.js +4 -2
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +13 -1
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +27 -2
- package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
- package/dist/surface/mcp/server-instructions.js +21 -8
- package/dist/surface/tools/act/after-match.d.ts +17 -0
- package/dist/surface/tools/act/after-match.js +30 -0
- package/dist/surface/tools/act/already-true.d.ts +40 -0
- package/dist/surface/tools/act/already-true.js +36 -0
- package/dist/surface/tools/act/durable.d.ts +69 -0
- package/dist/surface/tools/act/durable.js +139 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.d.ts +19 -6
- package/dist/surface/tools/act/navigation/navigate-arrival.js +60 -10
- package/dist/surface/tools/act/navigation/navigate-result.d.ts +1 -12
- package/dist/surface/tools/act/navigation/navigate-result.js +21 -3
- package/dist/surface/tools/act/proved-controls.d.ts +9 -0
- package/dist/surface/tools/act/proved-controls.js +11 -0
- package/dist/surface/tools/act/sequence-grade.d.ts +5 -0
- package/dist/surface/tools/act/sequence-grade.js +32 -1
- package/dist/surface/tools/act/settle-in-flight.d.ts +6 -2
- package/dist/surface/tools/act/settle-in-flight.js +29 -6
- package/dist/surface/tools/act-capsule.d.ts +7 -0
- package/dist/surface/tools/act-capsule.js +68 -8
- package/dist/surface/tools/act-sequence-tool.js +25 -8
- package/dist/surface/tools/act-tools.js +51 -74
- package/dist/surface/tools/args/numeric-bounds.d.ts +15 -2
- package/dist/surface/tools/args/numeric-bounds.js +30 -3
- package/dist/surface/tools/assert/assert-grade.js +26 -3
- package/dist/surface/tools/assert/assert-verdict.js +32 -6
- package/dist/surface/tools/browser-tools.js +17 -4
- package/dist/surface/tools/coverage-tools.js +27 -1
- package/dist/surface/tools/dynamic-tools.js +6 -0
- package/dist/surface/tools/error-recovery.js +4 -4
- package/dist/surface/tools/feedback-invite.js +6 -4
- package/dist/surface/tools/feedback-tools.d.ts +2 -1
- package/dist/surface/tools/feedback-tools.js +1 -1
- package/dist/surface/tools/harness-explore.d.ts +3 -2
- package/dist/surface/tools/harness-explore.js +7 -6
- package/dist/surface/tools/invoke-tool.js +17 -4
- package/dist/surface/tools/lease-hint.d.ts +8 -0
- package/dist/surface/tools/lease-hint.js +10 -0
- package/dist/surface/tools/lease-tools.d.ts +16 -28
- package/dist/surface/tools/lease-tools.js +68 -11
- package/dist/surface/tools/lineage-tools.js +1 -1
- package/dist/surface/tools/live-call-text.js +4 -1
- package/dist/surface/tools/observe-tools.js +23 -7
- package/dist/surface/tools/real-input-attempt.d.ts +0 -5
- package/dist/surface/tools/real-input-attempt.js +1 -1
- package/dist/surface/tools/tool-kit.d.ts +5 -0
- package/dist/surface/tools/tool-kit.js +6 -1
- package/dist/surface/tools/tool-surface.js +17 -5
- package/dist/surface/tools/tools.js +68 -29
- package/dist/telemetry/argument-shape.d.ts +0 -2
- package/dist/telemetry/argument-shape.js +0 -4
- package/dist/telemetry/error-class.d.ts +2 -3
- package/dist/telemetry/error-class.js +2 -3
- package/dist/telemetry/feedback-local.d.ts +1 -0
- package/dist/telemetry/feedback-local.js +1 -3
- package/dist/telemetry/feedback.d.ts +1 -1
- package/dist/telemetry/harness-drive.d.ts +0 -2
- package/dist/telemetry/harness-drive.js +0 -4
- package/dist/telemetry/hud-metrics.d.ts +32 -0
- package/dist/telemetry/hud-metrics.js +95 -0
- package/dist/telemetry/session-metrics.d.ts +5 -0
- package/dist/telemetry/session-metrics.js +15 -1
- package/dist/wire-journal.d.ts +34 -0
- package/dist/wire-journal.js +104 -0
- package/dist/workspace-packages.d.ts +0 -2
- package/dist/workspace-packages.js +1 -9
- package/docs/README.md +5 -2
- package/docs/actions.mdx +3 -3
- package/docs/agent-cheatsheet.md +4 -4
- package/docs/architecture.md +6 -6
- package/docs/best-practices.mdx +1 -1
- package/docs/capabilities.mdx +32 -1
- package/docs/cli/cloud.mdx +21 -9
- package/docs/cli/doctor.mdx +4 -0
- package/docs/cli/feedback.mdx +2 -2
- package/docs/cli/gate.mdx +9 -4
- package/docs/cli/init.mdx +1 -0
- package/docs/cli/report.mdx +44 -0
- package/docs/cli/update.mdx +10 -0
- package/docs/cli.mdx +9 -0
- package/docs/desktop.mdx +14 -10
- package/docs/environment.mdx +87 -0
- package/docs/faq.mdx +18 -16
- package/docs/first-drive.md +5 -13
- package/docs/flows.md +32 -2
- package/docs/frameworks.mdx +140 -9
- package/docs/getting-started.md +3 -3
- package/docs/http-transport.md +6 -3
- package/docs/human-control.md +2 -2
- package/docs/index.mdx +16 -6
- package/docs/install-agentic.mdx +37 -1
- package/docs/install-manual.mdx +1 -1
- package/docs/integration-patterns.md +3 -3
- package/docs/multi-agent-testing.md +1 -1
- package/docs/packages/babel-plugin.mdx +1 -1
- package/docs/packages/browser.mdx +2 -2
- package/docs/packages/react.mdx +2 -2
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages/vite-plugin.mdx +2 -2
- package/docs/packages.mdx +9 -9
- package/docs/predicates.mdx +176 -7
- package/docs/quickstart.mdx +2 -2
- package/docs/recipes.mdx +2 -2
- package/docs/state-management.mdx +2 -2
- package/docs/system-map.md +1 -1
- package/docs/telemetry.md +1 -1
- package/docs/token-efficiency.md +3 -3
- package/docs/tools/act-and-wait.mdx +1 -0
- package/docs/tools/act-sequence.mdx +1 -1
- package/docs/tools/console.mdx +1 -1
- package/docs/tools/inspect.mdx +1 -1
- package/docs/tools/network.mdx +1 -1
- package/docs/tools/query.mdx +11 -11
- package/docs/tools/sessions.mdx +1 -1
- package/docs/tools/snapshot.mdx +1 -1
- package/docs/tools/state.mdx +1 -1
- package/docs/tools/wait-for.mdx +1 -1
- package/docs/usage.md +8 -7
- package/docs/use-cases.mdx +157 -0
- package/docs/vs-screenshots.mdx +3 -3
- package/docs/what-is-recorded.md +62 -0
- package/docs/what-is-reticle.mdx +17 -20
- package/docs/why-reticle.mdx +14 -21
- package/package.json +11 -10
- package/dist/judgement/capsule/minimize.d.ts +0 -12
- package/dist/judgement/capsule/minimize.js +0 -22
- package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
- package/dist/judgement/outcome/predicate-to-expect.js +0 -148
- package/dist/judgement/phenomena/phenomena.d.ts +0 -26
- package/dist/judgement/phenomena/phenomena.js +0 -101
- package/dist/language/flows/flow-report.d.ts +0 -22
- package/dist/language/flows/flow-report.js +0 -106
|
@@ -7,7 +7,7 @@ import { z } from 'zod';
|
|
|
7
7
|
import { aliasParam } from './args/alias-args.js';
|
|
8
8
|
import { CONSOLE_ATTACH_NOTE, CONSOLE_LEVELS, ReticleCommand, DEFAULT_ASSERT_TIMEOUT_MS, PredicateKind, Verified, } from '@reticlehq/core';
|
|
9
9
|
import { ReticleTool } from '@reticlehq/core';
|
|
10
|
-
import { countSchema, cursorSchema, httpStatusSchema, timeoutMsSchema, windowMsSchema, } from './args/numeric-bounds.js';
|
|
10
|
+
import { countSchema, cursorSchema, httpStatusSchema, timeoutMsSchema, waitForTimeoutMsSchema, resumeAfter, MAX_BLOCKING_WAIT_MS, windowMsSchema, } from './args/numeric-bounds.js';
|
|
11
11
|
import { buildReactionReport } from '@reticlehq/engine/question/reaction.js';
|
|
12
12
|
import { findContradictions } from '@reticlehq/engine/disagreement/contradictions.js';
|
|
13
13
|
import { evaluatePredicate, waitForPredicate, PredicateSchema, } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
@@ -16,7 +16,7 @@ import { WALL_CLOCK } from '../../portal/session/timing/wall-clock.js';
|
|
|
16
16
|
import { parsePredicate } from '@reticlehq/engine/question/predicate/predicate-parse.js';
|
|
17
17
|
import { matchNet, matchConsole, isConsoleEvent, eventMatchesFilters, netEmptyHint, consoleEmptyHint, reconcileNet, projectNetCall, projectConsoleLog, withoutUrlRaw, } from '@reticlehq/engine/window/event-filters.js';
|
|
18
18
|
import { applyEventBudget, costHint, withSizeCost, DEFAULT_OBSERVE_EVENT_LIMIT, DEFAULT_QUERY_LIMIT, } from '../../portal/session/output-budget.js';
|
|
19
|
-
import { annotateStarvedFailure, healthEnvelope, bufferEnvelope, } from '../../portal/session/session-health.js';
|
|
19
|
+
import { annotateStarvedFailure, currentOf, healthEnvelope, bufferEnvelope, } from '../../portal/session/session-health.js';
|
|
20
20
|
import { assertsDerivedIpcStatus, DERIVED_IPC_STATUS_ADVICE, isPresenceOnlyAssertion, PRESENCE_ONLY_ADVICE, } from './assert/assert-grade.js';
|
|
21
21
|
import { assertVerdict } from './assert/assert-verdict.js';
|
|
22
22
|
import { followLostObservation } from './act/act-observation.js';
|
|
@@ -33,6 +33,7 @@ import { withControl } from '../../portal/session/control-envelope.js';
|
|
|
33
33
|
import { asNumber, asRecord, asString } from '@reticlehq/core';
|
|
34
34
|
import { intentArg, sessionIdShape, commandOrThrow } from './tool-kit.js';
|
|
35
35
|
import { gradeOfPredicate } from './assert/assert-grade.js';
|
|
36
|
+
import { captureAssertion } from '../../language/flows/replay.js';
|
|
36
37
|
/**
|
|
37
38
|
* Evidence-completeness block: present on observe/network/console only when the ring buffer has
|
|
38
39
|
* evicted events, so a "no such event" answer is distinguishable from "I dropped it" (issue #27).
|
|
@@ -172,6 +173,7 @@ export const OBSERVE_TOOLS = [
|
|
|
172
173
|
currentDocumentId: session.currentDocumentId,
|
|
173
174
|
currentEditEpoch: session.currentEditEpoch,
|
|
174
175
|
appOrigin: session.url,
|
|
176
|
+
background: session.background,
|
|
175
177
|
...(judgingTheAct ? { ...session.lastAct.effect(), actionSince: actCursor } : {}),
|
|
176
178
|
});
|
|
177
179
|
// carry session health — a throttled tab means the observed timeline may be incomplete.
|
|
@@ -193,15 +195,19 @@ export const OBSERVE_TOOLS = [
|
|
|
193
195
|
predicate: PredicateSchema.optional().describe('Predicate to wait for: { signal }, { net }, { element }, { kind: "net", ok: false } (assert on the OUTCOME — the honest field for IPC, which has no status code), { kind: "state", store, path, equals } (assert a registered store\'s value directly — the source of truth no DOM read can reach; equals takes a literal or { $gte | $contains | $length } pattern), { kind: "settled", quietMs } (deterministic network + DOM idle — prefer this over a fixed sleep), or a combination via allOf/anyOf.'),
|
|
194
196
|
// Same concept, the neighbouring tool's name. See alias-args.ts.
|
|
195
197
|
until: PredicateSchema.optional().describe("Alias for `predicate` (act_and_wait's name)."),
|
|
196
|
-
timeout_ms:
|
|
198
|
+
timeout_ms: waitForTimeoutMsSchema
|
|
197
199
|
.optional()
|
|
198
|
-
.describe(
|
|
200
|
+
.describe(`Maximum wait in milliseconds. Default: 4000, up to 600000. One call waits at most ${String(MAX_BLOCKING_WAIT_MS)} ms, because your MCP client aborts a longer request; past that it returns resume_ms, and you call again with timeout_ms: resume_ms and the same since to keep waiting.`),
|
|
199
201
|
since: cursorSchema
|
|
200
202
|
.optional()
|
|
201
203
|
.describe('Cursor from a prior reticle_act — scopes the wait to events after that act.'),
|
|
202
204
|
...sessionIdShape,
|
|
203
205
|
},
|
|
204
206
|
outputSchema: {
|
|
207
|
+
resume_ms: z
|
|
208
|
+
.number()
|
|
209
|
+
.optional()
|
|
210
|
+
.describe('Present when this call stopped at the per-call limit before the predicate was seen. Call again with timeout_ms set to this, the same predicate and the same since, to keep waiting.'),
|
|
205
211
|
pass: z.boolean(),
|
|
206
212
|
evidence: z.unknown().optional(),
|
|
207
213
|
failureReason: z.string().optional(),
|
|
@@ -239,7 +245,9 @@ export const OBSERVE_TOOLS = [
|
|
|
239
245
|
.describe('Where the code behind this verdict lives, as `file:line`. For an element/text assertion it is the matched element itself; for a FAILING signal/net/state assertion — which has no element to point at — it is the control last acted on, where the handler that should have fired lives. OMITTED when neither is known: this tool never borrows an unrelated location.'),
|
|
240
246
|
},
|
|
241
247
|
handler: async (deps, args) => {
|
|
242
|
-
const
|
|
248
|
+
const requestedMs = asNumber(args['timeout_ms']) ?? DEFAULT_ASSERT_TIMEOUT_MS;
|
|
249
|
+
// One call never blocks past what the client allows; the rest comes back as resume_ms.
|
|
250
|
+
const waitBudget = Math.min(requestedMs, MAX_BLOCKING_WAIT_MS);
|
|
243
251
|
// Spend the budget waiting for the APP as well as for the predicate. See resolve-within.
|
|
244
252
|
let session = await resolveSessionWithin(deps.sessions, asString(args['sessionId']), waitBudget, WALL_CLOCK);
|
|
245
253
|
// `until` is act_and_wait's name for this — see alias-args.ts.
|
|
@@ -275,6 +283,7 @@ export const OBSERVE_TOOLS = [
|
|
|
275
283
|
...annotateStarvedFailure(session, verdict),
|
|
276
284
|
...assertionSource(session, predicate, verdict),
|
|
277
285
|
...(followed.followed ? { sessionId: session.id } : {}),
|
|
286
|
+
...((resume) => (resume === undefined ? {} : { resume_ms: resume }))(resumeAfter(requestedMs, waitBudget, verdict)),
|
|
278
287
|
...healthEnvelope(session),
|
|
279
288
|
...bufferEnvelope(session),
|
|
280
289
|
});
|
|
@@ -294,7 +303,7 @@ export const OBSERVE_TOOLS = [
|
|
|
294
303
|
'{ net, urlContains|method|status|count|bodyMatches|bodyContains|requestBodyContains|requestBodyMatches } ' +
|
|
295
304
|
'{ state, path|equals } { route, pathname (exact) | contains (path+query+hash) } ' +
|
|
296
305
|
'{ element, testid|role|text } { text } { console, level|contains|absent } { animation, name } ' +
|
|
297
|
-
'{ settled } — combine with { allOf | anyOf | not }. Prefer a signal/net/state consequence ' +
|
|
306
|
+
'{ settled } { compare, left, right } — combine with { allOf | anyOf | not }. Prefer a signal/net/state consequence ' +
|
|
298
307
|
'over element/text presence.'),
|
|
299
308
|
until: PredicateSchema.optional().describe("Alias for `predicate` (act_and_wait's name)."),
|
|
300
309
|
timeout_ms: timeoutMsSchema
|
|
@@ -438,6 +447,13 @@ export const OBSERVE_TOOLS = [
|
|
|
438
447
|
// destroys — see runs/run-context.ts. Recorded WITHOUT an attribution window: this tool drives
|
|
439
448
|
// nothing, so no event it observed was caused by it.
|
|
440
449
|
session.recordAction(ReticleTool.ASSERT, asRecord(args), verdictEffect);
|
|
450
|
+
// A passing check over the default window (since the last act) is proof of that act, so it
|
|
451
|
+
// joins that step in the recording — otherwise "act, then assert" saves a bare click. An
|
|
452
|
+
// explicit `since` may reach back past the last step, where replay would not find it. The
|
|
453
|
+
// store itself refuses when a navigation came after that step: see RecordingStore.markNavigated.
|
|
454
|
+
if (Verified.YES === decision['verified'] && args['since'] === undefined) {
|
|
455
|
+
captureAssertion(deps.recordings, predicate);
|
|
456
|
+
}
|
|
441
457
|
return withControl(session, {
|
|
442
458
|
...decision,
|
|
443
459
|
...annotateStarvedFailure(session, verdict),
|
|
@@ -454,7 +470,7 @@ export const OBSERVE_TOOLS = [
|
|
|
454
470
|
...coverage,
|
|
455
471
|
// The SAME pointer the journal keeps, not a second lookup — one verdict, one file:line.
|
|
456
472
|
...(verdictEffect.source === undefined ? {} : { source: verdictEffect.source }),
|
|
457
|
-
...healthEnvelope(session),
|
|
473
|
+
...healthEnvelope(currentOf(deps.sessions, session)),
|
|
458
474
|
...bufferEnvelope(session),
|
|
459
475
|
});
|
|
460
476
|
},
|
|
@@ -22,11 +22,6 @@
|
|
|
22
22
|
import { ActionType, InputModeReason } from '@reticlehq/core';
|
|
23
23
|
import type { Session } from '../../portal/session/session.js';
|
|
24
24
|
import { type ToolDeps } from './tool-kit.js';
|
|
25
|
-
/**
|
|
26
|
-
* Expand a leading `~` against the caller's home directory. Absolute and relative paths pass
|
|
27
|
-
* through unchanged. `home` is injected so unit tests do not depend on the machine's real home.
|
|
28
|
-
*/
|
|
29
|
-
export declare function expandUserPath(rawPath: string, home: string): string;
|
|
30
25
|
/**
|
|
31
26
|
* If the action is `upload` AND the inner args carry `path`, read the file from disk and rewrite
|
|
32
27
|
* the args to `{ content, name, type, __base64: true }` before the ACT command reaches the browser.
|
|
@@ -99,7 +99,7 @@ const UPLOAD_MAX_BYTES = Math.floor((TRANSPORT_LIMITS.MAX_MESSAGE_BYTES / (4 / 3
|
|
|
99
99
|
* Expand a leading `~` against the caller's home directory. Absolute and relative paths pass
|
|
100
100
|
* through unchanged. `home` is injected so unit tests do not depend on the machine's real home.
|
|
101
101
|
*/
|
|
102
|
-
|
|
102
|
+
function expandUserPath(rawPath, home) {
|
|
103
103
|
if ('~' === rawPath)
|
|
104
104
|
return home;
|
|
105
105
|
if (rawPath.startsWith('~/') || rawPath.startsWith('~\\'))
|
|
@@ -222,6 +222,11 @@ export declare const EnvelopeKey: {
|
|
|
222
222
|
readonly VERIFY_NEXT: "verify_next";
|
|
223
223
|
/** The contextual "tell us what just went wrong" invitation. Same story, same release. */
|
|
224
224
|
readonly FEEDBACK_INVITE: "feedback_invite";
|
|
225
|
+
/**
|
|
226
|
+
* The same moment, for the HUMAN: a call with the founder, or an email through `identify`. The
|
|
227
|
+
* agent is told to offer it and never to book or submit anything itself.
|
|
228
|
+
*/
|
|
229
|
+
readonly TALK_TO_US: "talk_to_us";
|
|
225
230
|
/** SDK/daemon version skew — often the one fact that explains everything else in the session. */
|
|
226
231
|
readonly VERSION_SKEW: "version_skew";
|
|
227
232
|
/** A feedback report that was accepted and then failed to send. Only the reporter can act on it. */
|
|
@@ -28,7 +28,7 @@ export const intentArg = z
|
|
|
28
28
|
'BAD: "P1 step 5", "drive 2 of 2", "same as before the fix", "the board renders cleanly" — these name a session, ' +
|
|
29
29
|
'a step number or nothing checkable, and the person reading them later has none of that context. ' +
|
|
30
30
|
'This is shared memory: it is pooled per project and later agents read it back to avoid re-deriving what you just established. ' +
|
|
31
|
-
'Recorded in .reticle/intent
|
|
31
|
+
'Recorded in .reticle/intent/, the same ledger reticle_intent writes, and marked proved by this verdict if it passes.');
|
|
32
32
|
export const sessionIdShape = {
|
|
33
33
|
sessionId: z
|
|
34
34
|
.string()
|
|
@@ -75,6 +75,11 @@ export const EnvelopeKey = {
|
|
|
75
75
|
VERIFY_NEXT: 'verify_next',
|
|
76
76
|
/** The contextual "tell us what just went wrong" invitation. Same story, same release. */
|
|
77
77
|
FEEDBACK_INVITE: 'feedback_invite',
|
|
78
|
+
/**
|
|
79
|
+
* The same moment, for the HUMAN: a call with the founder, or an email through `identify`. The
|
|
80
|
+
* agent is told to offer it and never to book or submit anything itself.
|
|
81
|
+
*/
|
|
82
|
+
TALK_TO_US: 'talk_to_us',
|
|
78
83
|
/** SDK/daemon version skew — often the one fact that explains everything else in the session. */
|
|
79
84
|
VERSION_SKEW: 'version_skew',
|
|
80
85
|
/** A feedback report that was accepted and then failed to send. Only the reporter can act on it. */
|
|
@@ -395,11 +395,23 @@ export function describeToolSurface(active, requested) {
|
|
|
395
395
|
export function defaultAdvertisedNames() {
|
|
396
396
|
const surface = resolveToolSurface();
|
|
397
397
|
const names = [...filterToolNames(surface)];
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
398
|
+
/*
|
|
399
|
+
* Both meta tools, on every surface, because that is what the MCP actually advertises.
|
|
400
|
+
*
|
|
401
|
+
* This used to withhold `reticle_run` from the merged surface, reasoning that "naming a hatch
|
|
402
|
+
* that is not there is the same defect one level in". The reasoning is sound and the premise was
|
|
403
|
+
* false: `buildDynamicTools` returns `[reticle_tools, reticle_run]` unconditionally and
|
|
404
|
+
* `advertisedTools` appends both to every surface, so the hatch has always been there. Measured
|
|
405
|
+
* against a live daemon on the default surface: `reticle_run` is advertised, and
|
|
406
|
+
* `reticle_run { tool: "reticle_lease" }` reaches `reticle_lease`.
|
|
407
|
+
*
|
|
408
|
+
* Two functions answering one question, and this was the one the MCP never called. It is read by
|
|
409
|
+
* `server-instructions`, which gates "Everything else is one hop: reticle_tools lists it,
|
|
410
|
+
* reticle_run calls it" on this list - so agents were told the hatch was absent from a surface
|
|
411
|
+
* carrying it, and six recovery messages were later rewritten to match the lie.
|
|
412
|
+
* `advertised-names-are-real.test.ts` now pins this to `advertisedTools` itself.
|
|
413
|
+
*/
|
|
414
|
+
return [...names, ReticleTool.TOOLS, ReticleTool.RUN];
|
|
403
415
|
}
|
|
404
416
|
/** The advertised NAME set for a surface, without needing the tool table. */
|
|
405
417
|
function filterToolNames(surface) {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { z } from 'zod';
|
|
2
|
-
import { NoSessionAction, QueryBy, ReticleCommand, SnapshotMode } from '@reticlehq/core';
|
|
2
|
+
import { DiscoveryInvite, AttrNamesSchema, EventType, NoSessionAction, QueryBy, ReticleCommand, SnapshotMode, } from '@reticlehq/core';
|
|
3
3
|
import { ReticleTool } from '@reticlehq/core';
|
|
4
4
|
import { withSizeCost } from '../../portal/session/output-budget.js';
|
|
5
5
|
import { applySnapshotDelta, SnapshotCache } from './read/snapshot-delta.js';
|
|
@@ -109,7 +109,7 @@ export const RAW_TOOLS = [
|
|
|
109
109
|
lastOutage: z.object({ startedMs: z.number(), durationMs: z.number() }).optional(),
|
|
110
110
|
})
|
|
111
111
|
.optional()
|
|
112
|
-
.describe('
|
|
112
|
+
.describe('Continuity of the SDK-to-daemon LINK for this tab, present for any tab the daemon has a record of: how long this attachment has lasted, how many times it dropped and came back, and when the last gap started and how long it lasted. `outages > 0` means a verdict over this window spans a gap where nothing was observed. These are link counters, NOT app health: they say nothing about whether the page origin is still serving, so a tab whose dev server has died reports `outages: 0` with a growing `connectedSinceMs` and is not evidence the app is up.'),
|
|
113
113
|
}))
|
|
114
114
|
.describe('Connected browser sessions with health state. `projectId` groups sessions by app (stable across port changes); `leased` marks a pool-managed headless context vs a human tab.'),
|
|
115
115
|
why: z
|
|
@@ -125,6 +125,10 @@ export const RAW_TOOLS = [
|
|
|
125
125
|
})
|
|
126
126
|
.optional()
|
|
127
127
|
.describe("Present ONLY when `sessions` is empty: the same answer as `why`, executable. `command` is the LITERAL command to run, sourced from this project's own package.json scripts and lockfile — it is absent, never guessed, when the project declares no dev script. `action` is one of daemon_split | start_dev_server | run_init | open_app | reopen_app. `daemon_split` outranks the rest and means the app IS running and instrumented, on a DIFFERENT daemon than the one you are attached to — do not start or re-init anything, read `reason`."),
|
|
128
|
+
talk_to_us: z
|
|
129
|
+
.string()
|
|
130
|
+
.optional()
|
|
131
|
+
.describe('Present ONLY when `sessions` is empty: a call with the founder for the person you are working with. Offer it; never act on it.'),
|
|
128
132
|
lastKnown: z
|
|
129
133
|
.object({
|
|
130
134
|
sessionId: z.string(),
|
|
@@ -158,6 +162,8 @@ export const RAW_TOOLS = [
|
|
|
158
162
|
...(why === undefined ? {} : { why }),
|
|
159
163
|
...(next === undefined ? {} : { next_action: next }),
|
|
160
164
|
...(undefined === lastKnown ? {} : { lastKnown }),
|
|
165
|
+
// Setup that never connects is where most people give up; it is the talk worth having.
|
|
166
|
+
talk_to_us: DiscoveryInvite.AGENT,
|
|
161
167
|
};
|
|
162
168
|
}
|
|
163
169
|
return { sessions };
|
|
@@ -230,6 +236,10 @@ export const RAW_TOOLS = [
|
|
|
230
236
|
.boolean()
|
|
231
237
|
.optional()
|
|
232
238
|
.describe('True when the page exceeded the snapshot cap. The tree is then a document-order PREFIX: an element being absent from it does NOT mean it is absent from the page.'),
|
|
239
|
+
// The refs a capped read never entered — re-read one with `scope`. Undeclared, a validating
|
|
240
|
+
// client stripped it, and a truncated tree arrived with no way to finish reading it.
|
|
241
|
+
unread: z.array(z.string()).optional(),
|
|
242
|
+
unreadOverflow: z.boolean().optional(),
|
|
233
243
|
note: z
|
|
234
244
|
.string()
|
|
235
245
|
.optional()
|
|
@@ -261,7 +271,7 @@ export const RAW_TOOLS = [
|
|
|
261
271
|
scope: asString(args['scope']) ?? '',
|
|
262
272
|
mode,
|
|
263
273
|
diff: true === args['diff'],
|
|
264
|
-
}, deps.snapshots ?? SNAPSHOT_CACHE), mode), mode), mode)));
|
|
274
|
+
}, deps.snapshots ?? SNAPSHOT_CACHE), mode), mode), mode, resolved)));
|
|
265
275
|
},
|
|
266
276
|
},
|
|
267
277
|
{
|
|
@@ -290,10 +300,7 @@ export const RAW_TOOLS = [
|
|
|
290
300
|
.boolean()
|
|
291
301
|
.optional()
|
|
292
302
|
.describe('Return the `scope` element ITSELF instead of searching inside it. Use when the target is a plain layout container with no role, name, testid or text of its own — which is routinely the element that carries the handler, and is otherwise unreachable because every query excludes its own scope root. Requires `scope`.'),
|
|
293
|
-
attrs:
|
|
294
|
-
.array(z.string())
|
|
295
|
-
.optional()
|
|
296
|
-
.describe("Attribute names to return per match, e.g. ['href'] to inventory links or ['src'] for images. Absent attributes are omitted; credential-bearing names are redacted."),
|
|
303
|
+
attrs: AttrNamesSchema.optional().describe("Attribute NAMES to return per match, e.g. ['href'] for links, ['src'] for images. Projects, never filters: 'name=value' is refused. Absent omitted; credentials redacted."),
|
|
297
304
|
limit: countSchema
|
|
298
305
|
.optional()
|
|
299
306
|
.describe('Cap the returned descriptors to the first N (cuts tokens on broad queries). If more matched, the result carries total + truncated:true so the trim is never silent — narrow with name/scope.'),
|
|
@@ -371,6 +378,12 @@ export const RAW_TOOLS = [
|
|
|
371
378
|
.optional()
|
|
372
379
|
.describe('Structural clusters on the page — what IS here, to diagnose the miss.'),
|
|
373
380
|
presentTestids: z.array(z.string()).optional(),
|
|
381
|
+
// Declared for the same reason presentRegions had to be: undeclared here, it is stripped
|
|
382
|
+
// from structuredContent without a word — and this field exists precisely to say a word.
|
|
383
|
+
presentTestidsTotal: z
|
|
384
|
+
.number()
|
|
385
|
+
.optional()
|
|
386
|
+
.describe('Present only when presentTestids was cut at its cap: how many there were. The list is document order, so a region low on the page is what got dropped — absence from the list proves nothing.'),
|
|
374
387
|
knownEmptyState: z.boolean(),
|
|
375
388
|
splitText: z
|
|
376
389
|
.object({
|
|
@@ -614,24 +627,31 @@ function noteEmptyLeanTree(result, mode) {
|
|
|
614
627
|
* wrapper or two is ordinary, so this is deliberately not `=== 0`.
|
|
615
628
|
*/
|
|
616
629
|
const UNMOUNTED_ROOT_MAX_ELEMENTS = 3;
|
|
617
|
-
|
|
618
|
-
|
|
619
|
-
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
630
|
+
function crashEvidence(session) {
|
|
631
|
+
const since = asRecord(session)['eventsSince'];
|
|
632
|
+
if ('function' !== typeof since)
|
|
633
|
+
return undefined;
|
|
634
|
+
let events;
|
|
635
|
+
try {
|
|
636
|
+
events = since.call(session, 0);
|
|
637
|
+
}
|
|
638
|
+
catch {
|
|
639
|
+
return undefined;
|
|
640
|
+
}
|
|
641
|
+
if (!Array.isArray(events))
|
|
642
|
+
return undefined;
|
|
643
|
+
const errors = events.filter((e) => {
|
|
644
|
+
const type = asString(asRecord(e)['type']);
|
|
645
|
+
return EventType.CONSOLE_ERROR === type || EventType.ERROR_UNCAUGHT === type;
|
|
646
|
+
});
|
|
647
|
+
if (0 === errors.length)
|
|
648
|
+
return undefined;
|
|
649
|
+
const first = errors
|
|
650
|
+
.map((e) => asString(asRecord(asRecord(e)['data'])['message']))
|
|
651
|
+
.find((m) => undefined !== m && '' !== m);
|
|
652
|
+
return { count: errors.length, first: first ?? '' };
|
|
653
|
+
}
|
|
654
|
+
function noteUnmountedRoot(result, mode, session) {
|
|
635
655
|
if (SnapshotMode.STATUS === mode)
|
|
636
656
|
return result;
|
|
637
657
|
const row = asRecord(result);
|
|
@@ -642,12 +662,31 @@ function noteUnmountedRoot(result, mode) {
|
|
|
642
662
|
const elements = asNumber(row['domElements']);
|
|
643
663
|
if (elements === undefined || elements > UNMOUNTED_ROOT_MAX_ELEMENTS)
|
|
644
664
|
return result;
|
|
665
|
+
const mount = `the tree is empty because there is almost nothing in the DOM: ${String(elements)} ` +
|
|
666
|
+
`element(s) under this scope. That is a mount container with nothing rendered into it, not a ` +
|
|
667
|
+
`page whose contents were skipped — so the app is UNMOUNTED rather than slow, and waiting ` +
|
|
668
|
+
`will not change it. `;
|
|
669
|
+
// An uncaught error beside an empty mount container is the difference between "has not started"
|
|
670
|
+
// and "started and died", which are the two readings of this count and want opposite next moves.
|
|
671
|
+
// Nothing here is framework-specific, and deliberately so: the condition is a known mount
|
|
672
|
+
// container that holds nothing with an uncaught error beside it, which is as true of a Vue or
|
|
673
|
+
// Svelte root as a React one.
|
|
674
|
+
const crash = crashEvidence(session);
|
|
675
|
+
if (crash !== undefined) {
|
|
676
|
+
return {
|
|
677
|
+
...row,
|
|
678
|
+
note: mount +
|
|
679
|
+
`The app did not merely fail to start — it CRASHED: ${String(crash.count)} uncaught ` +
|
|
680
|
+
`error(s) were logged in this session` +
|
|
681
|
+
('' === crash.first ? '' : `, the first: "${crash.first}"`) +
|
|
682
|
+
`. Read reticle_console for the rest, and check anything that runs inside a framework ` +
|
|
683
|
+
`commit phase. Loading the app again will reproduce it rather than fix it.`,
|
|
684
|
+
};
|
|
685
|
+
}
|
|
645
686
|
return {
|
|
646
687
|
...row,
|
|
647
|
-
note:
|
|
648
|
-
`
|
|
649
|
-
`page whose contents were skipped — so the app is UNMOUNTED rather than slow, and waiting ` +
|
|
650
|
-
`will not change it. An app that was rendering and then stopped has usually thrown: read ` +
|
|
688
|
+
note: mount +
|
|
689
|
+
`An app that was rendering and then stopped has usually thrown: read ` +
|
|
651
690
|
`reticle_console for an uncaught error, and check anything that runs inside a framework ` +
|
|
652
691
|
`commit phase. If the app has genuinely not started yet, load it and snapshot again.`,
|
|
653
692
|
};
|
|
@@ -19,8 +19,6 @@
|
|
|
19
19
|
* never quietly start forwarding free text.
|
|
20
20
|
*/
|
|
21
21
|
export declare const OTHER_VALUE = "other";
|
|
22
|
-
/** True for anything we are willing to report a value for. */
|
|
23
|
-
export declare function isSafeEnumParam(name: string): boolean;
|
|
24
22
|
/**
|
|
25
23
|
* The reportable form of one parameter: `name` on its own, or `name:value` when the parameter is a
|
|
26
24
|
* known enum. Never the raw value of anything else.
|
|
@@ -41,10 +41,6 @@ const SAFE_ENUM_PARAMS = new Map([
|
|
|
41
41
|
['level', new Set(['error', 'warn', 'info', 'log', 'debug'])],
|
|
42
42
|
]);
|
|
43
43
|
export const OTHER_VALUE = 'other';
|
|
44
|
-
/** True for anything we are willing to report a value for. */
|
|
45
|
-
export function isSafeEnumParam(name) {
|
|
46
|
-
return SAFE_ENUM_PARAMS.has(name);
|
|
47
|
-
}
|
|
48
44
|
/**
|
|
49
45
|
* The reportable form of one parameter: `name` on its own, or `name:value` when the parameter is a
|
|
50
46
|
* known enum. Never the raw value of anything else.
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Whose defect was that tool error?
|
|
3
3
|
*
|
|
4
4
|
* `toolErrors` was one number covering three failures with three different fixes, so the top-line
|
|
5
|
-
* count could be acted on only by unpacking `errors[]` by hand and reading the prose.
|
|
6
|
-
*
|
|
7
|
-
* Read as "126 tool errors" that hides the sixth of them where OUR schema failed to explain itself —
|
|
5
|
+
* count could be acted on only by unpacking `errors[]` by hand and reading the prose. Read as one
|
|
6
|
+
* number, it hides the share where OUR schema failed to explain itself (serialized zod arrays),
|
|
8
7
|
* which is the only bucket we can fix by writing better descriptions.
|
|
9
8
|
*
|
|
10
9
|
* Classified from the message SHAPE, never stored raw: this returns a bucket, and the caller keeps
|
|
@@ -2,9 +2,8 @@
|
|
|
2
2
|
* Whose defect was that tool error?
|
|
3
3
|
*
|
|
4
4
|
* `toolErrors` was one number covering three failures with three different fixes, so the top-line
|
|
5
|
-
* count could be acted on only by unpacking `errors[]` by hand and reading the prose.
|
|
6
|
-
*
|
|
7
|
-
* Read as "126 tool errors" that hides the sixth of them where OUR schema failed to explain itself —
|
|
5
|
+
* count could be acted on only by unpacking `errors[]` by hand and reading the prose. Read as one
|
|
6
|
+
* number, it hides the share where OUR schema failed to explain itself (serialized zod arrays),
|
|
8
7
|
* which is the only bucket we can fix by writing better descriptions.
|
|
9
8
|
*
|
|
10
9
|
* Classified from the message SHAPE, never stored raw: this returns a bucket, and the caller keeps
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import type { Feedback } from '@reticlehq/core/telemetry';
|
|
2
|
+
/** Reports live beside the rest of the workspace, not in a temp dir somebody has to be told about. */
|
|
2
3
|
interface SavedFeedback {
|
|
3
4
|
path: string;
|
|
4
5
|
/** A ready-to-run command that turns the file into an issue. */
|
|
@@ -13,8 +13,6 @@
|
|
|
13
13
|
import { mkdirSync, writeFileSync } from 'node:fs';
|
|
14
14
|
import { join } from 'node:path';
|
|
15
15
|
import { ReticleDir } from '@reticlehq/core';
|
|
16
|
-
/** Reports live beside the rest of the workspace, not in a temp dir somebody has to be told about. */
|
|
17
|
-
const FEEDBACK_SUBDIR = 'feedback';
|
|
18
16
|
/** Filesystem-safe, sortable, and unique enough for one report per second per kind. */
|
|
19
17
|
const stamp = (now) => new Date(now).toISOString().replace(/[:.]/g, '-').replace('Z', '');
|
|
20
18
|
const asMarkdown = (input, text, context) => {
|
|
@@ -39,7 +37,7 @@ const asMarkdown = (input, text, context) => {
|
|
|
39
37
|
*/
|
|
40
38
|
export function saveFeedbackLocally(cwd, input, text, context, now = Date.now()) {
|
|
41
39
|
try {
|
|
42
|
-
const dir = join(cwd, ReticleDir.ROOT, FEEDBACK_SUBDIR);
|
|
40
|
+
const dir = join(cwd, ReticleDir.ROOT, ReticleDir.FEEDBACK_SUBDIR);
|
|
43
41
|
mkdirSync(dir, { recursive: true });
|
|
44
42
|
const path = join(dir, `${stamp(now)}-${input.kind ?? 'note'}.md`);
|
|
45
43
|
writeFileSync(path, asMarkdown(input, text, context), 'utf8');
|
|
@@ -27,7 +27,7 @@ import { type SessionFacts } from './feedback-context.js';
|
|
|
27
27
|
export declare const FEEDBACK_ENV = "RETICLE_FEEDBACK";
|
|
28
28
|
/** What replaces a redacted match. Visible on purpose: a reader must see that something was removed. */
|
|
29
29
|
export declare const REDACTED = "[redacted]";
|
|
30
|
-
|
|
30
|
+
interface Redaction {
|
|
31
31
|
text: string;
|
|
32
32
|
/** Which rules fired, deduped. Surfaced back to the author so a redaction is never silent. */
|
|
33
33
|
removed: string[];
|
|
@@ -2,5 +2,3 @@
|
|
|
2
2
|
export declare function withHarnessDrive<T>(drive: () => Promise<T>): Promise<T>;
|
|
3
3
|
/** True while a harness drive is in progress. */
|
|
4
4
|
export declare function harnessDriving(): boolean;
|
|
5
|
-
/** Tests only — a leaked span would mis-attribute every verdict after it. */
|
|
6
|
-
export declare function resetHarnessDrive(): void;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { HudPanel, HudView, type HudUseData } from '@reticlehq/core';
|
|
2
|
+
/**
|
|
3
|
+
* How people use the in-page HUD, rolled into the session summary.
|
|
4
|
+
*
|
|
5
|
+
* Windowed like the tool histograms beside it: a periodic flush reports what happened since the
|
|
6
|
+
* last one, so a dashboard sums across a session's events. Names only — every key is a control id
|
|
7
|
+
* the wire schema already checked against core's closed list.
|
|
8
|
+
*/
|
|
9
|
+
/** How many steps of the journey one window keeps. A journey longer than this is cut, and says so. */
|
|
10
|
+
export declare const HUD_JOURNEY_MAX = 60;
|
|
11
|
+
export interface HudSummary {
|
|
12
|
+
/** Presses per control; a toggle counts under `id:on` / `id:off` so a switch reads both ways. */
|
|
13
|
+
hudControls?: Record<string, number>;
|
|
14
|
+
/** Milliseconds the HUD spent in each view during the window. */
|
|
15
|
+
hudViewMs?: Partial<Record<HudView, number>>;
|
|
16
|
+
/** Milliseconds each panel was showing during the window. */
|
|
17
|
+
hudPanelMs?: Partial<Record<HudPanel, number>>;
|
|
18
|
+
/** The window's presses and view changes, in order, cut at HUD_JOURNEY_MAX. */
|
|
19
|
+
hudJourney?: string[];
|
|
20
|
+
/** Present, and true, only when the journey was cut. */
|
|
21
|
+
hudJourneyCut?: true;
|
|
22
|
+
}
|
|
23
|
+
export declare class HudMetrics {
|
|
24
|
+
#private;
|
|
25
|
+
constructor(now: () => number);
|
|
26
|
+
record(use: HudUseData): void;
|
|
27
|
+
get empty(): boolean;
|
|
28
|
+
/** The window so far. Open view and panel are counted up to now, and keep running after. */
|
|
29
|
+
summarize(): HudSummary;
|
|
30
|
+
/** Start the next window. The current view and panel carry over, timed from now. */
|
|
31
|
+
reset(): void;
|
|
32
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { isHudControl } from '@reticlehq/core/hud';
|
|
2
|
+
import { HudPanel, HudView } from '@reticlehq/core';
|
|
3
|
+
/**
|
|
4
|
+
* How people use the in-page HUD, rolled into the session summary.
|
|
5
|
+
*
|
|
6
|
+
* Windowed like the tool histograms beside it: a periodic flush reports what happened since the
|
|
7
|
+
* last one, so a dashboard sums across a session's events. Names only — every key is a control id
|
|
8
|
+
* the wire schema already checked against core's closed list.
|
|
9
|
+
*/
|
|
10
|
+
/** How many steps of the journey one window keeps. A journey longer than this is cut, and says so. */
|
|
11
|
+
export const HUD_JOURNEY_MAX = 60;
|
|
12
|
+
export class HudMetrics {
|
|
13
|
+
#now;
|
|
14
|
+
#controls = new Map();
|
|
15
|
+
#viewMs = new Map();
|
|
16
|
+
#panelMs = new Map();
|
|
17
|
+
#journey = [];
|
|
18
|
+
#cut = false;
|
|
19
|
+
/** Did anything happen this window. A HUD merely sitting open is not worth a flush of its own. */
|
|
20
|
+
#changed = false;
|
|
21
|
+
#view;
|
|
22
|
+
#panel;
|
|
23
|
+
constructor(now) {
|
|
24
|
+
this.#now = now;
|
|
25
|
+
}
|
|
26
|
+
record(use) {
|
|
27
|
+
// A control the HUD never rendered is dropped here, the one place HUD use is counted, so free
|
|
28
|
+
// text cannot ride in on the id.
|
|
29
|
+
const control = use.control !== undefined && isHudControl(use.control) ? use.control : undefined;
|
|
30
|
+
if (control === undefined && use.view === undefined && use.panel === undefined)
|
|
31
|
+
return;
|
|
32
|
+
this.#changed = true;
|
|
33
|
+
if (control !== undefined) {
|
|
34
|
+
const key = use.toggle === undefined ? control : `${control}:${use.toggle}`;
|
|
35
|
+
this.#controls.set(key, (this.#controls.get(key) ?? 0) + 1);
|
|
36
|
+
this.#step(key);
|
|
37
|
+
}
|
|
38
|
+
if (use.view !== undefined && use.view !== this.#view?.value) {
|
|
39
|
+
this.#close(this.#view, this.#viewMs);
|
|
40
|
+
this.#view = { value: use.view, since: this.#now() };
|
|
41
|
+
this.#step(`view:${use.view}`);
|
|
42
|
+
}
|
|
43
|
+
if (use.panel !== undefined && use.panel !== this.#panel?.value) {
|
|
44
|
+
this.#close(this.#panel, this.#panelMs);
|
|
45
|
+
this.#panel = { value: use.panel, since: this.#now() };
|
|
46
|
+
if (use.panel !== HudPanel.NONE)
|
|
47
|
+
this.#step(`panel:${use.panel}`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
get empty() {
|
|
51
|
+
return !this.#changed;
|
|
52
|
+
}
|
|
53
|
+
/** The window so far. Open view and panel are counted up to now, and keep running after. */
|
|
54
|
+
summarize() {
|
|
55
|
+
const viewMs = this.#withOpen(this.#view, this.#viewMs);
|
|
56
|
+
const panelMs = this.#withOpen(this.#panel, this.#panelMs);
|
|
57
|
+
return {
|
|
58
|
+
...(this.#controls.size > 0 ? { hudControls: Object.fromEntries(this.#controls) } : {}),
|
|
59
|
+
...(viewMs.size > 0 ? { hudViewMs: Object.fromEntries(viewMs) } : {}),
|
|
60
|
+
...(panelMs.size > 0 ? { hudPanelMs: Object.fromEntries(panelMs) } : {}),
|
|
61
|
+
...(this.#journey.length > 0 ? { hudJourney: [...this.#journey] } : {}),
|
|
62
|
+
...(this.#cut ? { hudJourneyCut: true } : {}),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
/** Start the next window. The current view and panel carry over, timed from now. */
|
|
66
|
+
reset() {
|
|
67
|
+
const at = this.#now();
|
|
68
|
+
this.#controls.clear();
|
|
69
|
+
this.#viewMs.clear();
|
|
70
|
+
this.#panelMs.clear();
|
|
71
|
+
this.#journey.length = 0;
|
|
72
|
+
this.#cut = false;
|
|
73
|
+
this.#changed = false;
|
|
74
|
+
if (this.#view !== undefined)
|
|
75
|
+
this.#view = { ...this.#view, since: at };
|
|
76
|
+
if (this.#panel !== undefined)
|
|
77
|
+
this.#panel = { ...this.#panel, since: at };
|
|
78
|
+
}
|
|
79
|
+
#step(entry) {
|
|
80
|
+
if (this.#journey.length < HUD_JOURNEY_MAX)
|
|
81
|
+
this.#journey.push(entry);
|
|
82
|
+
else
|
|
83
|
+
this.#cut = true;
|
|
84
|
+
}
|
|
85
|
+
#close(open, into) {
|
|
86
|
+
if (open === undefined)
|
|
87
|
+
return;
|
|
88
|
+
into.set(open.value, (into.get(open.value) ?? 0) + Math.max(0, this.#now() - open.since));
|
|
89
|
+
}
|
|
90
|
+
#withOpen(open, closed) {
|
|
91
|
+
const out = new Map(closed);
|
|
92
|
+
this.#close(open, out);
|
|
93
|
+
return out;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
@@ -16,6 +16,7 @@
|
|
|
16
16
|
* than a rule saying it shouldn't.
|
|
17
17
|
*/
|
|
18
18
|
import { BrowserLaunchKind, type ConnectFailure, type SessionSummary } from '@reticlehq/core/telemetry';
|
|
19
|
+
import type { HudUseData } from '@reticlehq/core';
|
|
19
20
|
/**
|
|
20
21
|
* Mutable counters for one daemon lifetime. A plain class, not a store: it is process-local, it never
|
|
21
22
|
* persists, and it dies with the daemon.
|
|
@@ -24,6 +25,8 @@ export declare class SessionMetrics {
|
|
|
24
25
|
#private;
|
|
25
26
|
/** Clock injected — this file must stay testable without a real one, per the repo's clock rule. */
|
|
26
27
|
constructor(now: () => number);
|
|
28
|
+
/** A person used the HUD. Names only; the wire schema has already narrowed it. */
|
|
29
|
+
recordHudUse(use: HudUseData): void;
|
|
27
30
|
/**
|
|
28
31
|
* Record a call starting. Returns a function to call when it finishes — that closure is what makes
|
|
29
32
|
* timing correct under CONCURRENCY: several agents can be inside `runTool` at once, so a single
|
|
@@ -162,5 +165,7 @@ export declare const recordSdkFailure: (failure: {
|
|
|
162
165
|
site: string;
|
|
163
166
|
message: string;
|
|
164
167
|
}) => void;
|
|
168
|
+
/** Narrow-and-record one HUD use. Keeps the session hot path to a single call. */
|
|
169
|
+
export declare const recordHudUse: (use: HudUseData) => void;
|
|
165
170
|
/** Tests only — drop the singleton so each case starts from zero. */
|
|
166
171
|
export declare const resetSessionMetrics: () => void;
|