@reticlehq/server 3.1.0 → 3.3.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 +30 -28
- package/dist/command/cli/adhoc-suite.d.ts +19 -0
- package/dist/command/cli/adhoc-suite.js +88 -0
- package/dist/command/cli/adhoc-verdict.d.ts +23 -2
- package/dist/command/cli/adhoc-verdict.js +18 -10
- package/dist/command/cli/auth/device-flow.d.ts +2 -2
- package/dist/command/cli/cli-doctor.js +37 -5
- package/dist/command/cli/cli-flow-commands.d.ts +2 -1
- package/dist/command/cli/cli-kill.js +1 -1
- 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 +8 -1
- package/dist/command/cli/cli-parse.js +38 -7
- package/dist/command/cli/cli-verify.d.ts +59 -0
- package/dist/command/cli/cli-verify.js +131 -19
- package/dist/command/cli/cloud-cli.js +7 -6
- package/dist/command/cli/cloud-kit.d.ts +0 -2
- package/dist/command/cli/cloud-kit.js +3 -7
- package/dist/command/cli/config/config-discovery.d.ts +12 -0
- package/dist/command/cli/config/config-discovery.js +19 -0
- package/dist/command/cli/doctor/doctor-rows.d.ts +12 -0
- package/dist/command/cli/doctor/doctor-rows.js +12 -0
- package/dist/command/cli/doctor/doctor-sessions-line.d.ts +2 -1
- package/dist/command/cli/drive/drive-command.js +1 -1
- package/dist/command/cli/launch/cli-launch.d.ts +3 -23
- package/dist/command/cli/launch/cli-launch.js +29 -70
- package/dist/command/cli/lifecycle/daemon-lifecycle.d.ts +33 -0
- package/dist/command/cli/lifecycle/daemon-lifecycle.js +198 -0
- package/dist/command/cli/mcp-command.js +5 -3
- package/dist/command/cli/ports/resolve/cli-port.d.ts +15 -1
- package/dist/command/cli/ports/resolve/cli-port.js +50 -2
- package/dist/command/cli/report-command.d.ts +16 -0
- package/dist/command/cli/report-command.js +97 -0
- package/dist/command/cli/status/status-lines.d.ts +28 -0
- package/dist/command/cli/status/status-lines.js +117 -0
- package/dist/command/cli.d.ts +1 -1
- package/dist/command/cli.js +29 -177
- package/dist/command/daemon/binding/daemon-status-probe.d.ts +32 -0
- package/dist/command/daemon/binding/daemon-status-probe.js +93 -0
- package/dist/command/daemon/binding/loopback-reach.d.ts +42 -0
- package/dist/command/daemon/binding/loopback-reach.js +63 -0
- package/dist/command/daemon/binding/port-presence.d.ts +1 -1
- package/dist/command/daemon/daemon-resilience.d.ts +13 -1
- package/dist/command/daemon/daemon-resilience.js +12 -1
- package/dist/command/daemon/daemon.d.ts +2 -11
- package/dist/command/daemon/daemon.js +8 -11
- package/dist/command/daemon/idle-shutdown.d.ts +2 -1
- package/dist/command/daemon/lifetime/heartbeat.d.ts +8 -0
- package/dist/command/daemon/lifetime/heartbeat.js +10 -0
- package/dist/command/daemon/lifetime/log-cap.d.ts +68 -0
- package/dist/command/daemon/lifetime/log-cap.js +115 -0
- package/dist/command/setup/agent-notice-memory.d.ts +16 -0
- package/dist/command/setup/agent-notice-memory.js +65 -0
- package/dist/command/setup/bringup/dev-server-wait.d.ts +1 -0
- package/dist/command/setup/bringup/dev-server-wait.js +16 -0
- package/dist/command/setup/bringup/ensure-daemon.js +1 -1
- package/dist/command/setup/init/init-host.js +8 -0
- package/dist/command/setup/init/init-runtime.js +13 -1
- package/dist/command/setup/node-effects.js +1 -1
- package/dist/command/setup/probe/page-probe.js +9 -2
- package/dist/command/setup/run-setup.d.ts +25 -7
- package/dist/command/setup/run-setup.js +51 -9
- package/dist/command/setup/setup-command.js +31 -3
- package/dist/command/setup/terminal/confirm.js +2 -1
- package/dist/command/update/updater.d.ts +27 -0
- package/dist/command/update/updater.js +35 -2
- package/dist/features/crawl/crawl-tools.js +3 -1
- package/dist/features/crawl/crawl.d.ts +2 -0
- package/dist/features/crawl/crawl.js +3 -1
- package/dist/features/harness/drive-report.d.ts +73 -0
- package/dist/features/harness/drive-report.js +196 -0
- package/dist/features/harness/driver.js +29 -8
- package/dist/features/harness/drivers.d.ts +19 -0
- package/dist/features/harness/drivers.js +19 -0
- package/dist/features/harness/fill-values.d.ts +67 -0
- package/dist/features/harness/fill-values.js +153 -0
- package/dist/features/harness/jev-driver.d.ts +188 -0
- package/dist/features/harness/jev-driver.js +661 -0
- package/dist/features/harness/openai-driver.d.ts +46 -0
- package/dist/features/harness/openai-driver.js +197 -0
- package/dist/features/harness/platform-config.d.ts +62 -0
- package/dist/features/harness/platform-config.js +97 -0
- package/dist/features/visual/visual-tools.js +26 -2
- package/dist/index.d.ts +1 -1
- package/dist/index.js +80 -130
- 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 +38 -9
- package/dist/judgement/domain/domain-tools.js +4 -2
- package/dist/judgement/outcome/assertion-integrity.d.ts +3 -3
- package/dist/judgement/phenomena/phenomena.d.ts +2 -1
- 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/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 +2 -2
- package/dist/judgement/runs/verification-sync.js +9 -2
- package/dist/language/flows/affected-tools.js +6 -3
- 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/flow-anchor.d.ts +12 -0
- package/dist/language/flows/flow-anchor.js +20 -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-learning.d.ts +3 -0
- package/dist/language/flows/flow-learning.js +39 -8
- package/dist/language/flows/flow-replay-run.d.ts +55 -10
- package/dist/language/flows/flow-replay-run.js +217 -58
- package/dist/language/flows/flow-replay-types.d.ts +9 -0
- package/dist/language/flows/flow-replay.d.ts +29 -11
- package/dist/language/flows/flow-replay.js +221 -203
- package/dist/language/flows/flow-result.d.ts +18 -1
- package/dist/language/flows/flow-result.js +18 -2
- 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-store-for-session.d.ts +2 -1
- 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 +8 -4
- package/dist/language/flows/flows.d.ts +15 -10
- package/dist/language/flows/flows.js +17 -4
- 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/narrow-write.d.ts +4 -4
- 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/tape/recordings.d.ts +2 -2
- package/dist/language/flows/replay.js +13 -9
- 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/suite-selection.d.ts +15 -1
- package/dist/language/flows/suite-selection.js +1 -1
- package/dist/language/flows/verify-change-tools.js +21 -4
- package/dist/memory/cloud/account-state.d.ts +1 -1
- package/dist/memory/cloud/account-state.js +5 -4
- package/dist/memory/cloud/cloud-config.d.ts +9 -0
- package/dist/memory/cloud/cloud-config.js +9 -0
- package/dist/memory/cloud/cloud-sync.d.ts +7 -4
- package/dist/memory/cloud/cloud-sync.js +11 -6
- package/dist/memory/cloud/harness-config.d.ts +12 -0
- package/dist/memory/cloud/harness-config.js +58 -0
- package/dist/memory/cloud/harness-offer.d.ts +44 -0
- package/dist/memory/cloud/harness-offer.js +146 -0
- package/dist/memory/cloud/harness-switch.d.ts +11 -0
- package/dist/memory/cloud/harness-switch.js +53 -0
- package/dist/memory/cloud/sync-cycle.d.ts +12 -0
- package/dist/memory/cloud/sync-cycle.js +29 -4
- package/dist/memory/cloud/sync-daemon.d.ts +35 -2
- package/dist/memory/cloud/sync-daemon.js +45 -0
- package/dist/memory/cloud/sync-disk.js +11 -6
- package/dist/memory/impact/impact-recorder.d.ts +8 -0
- package/dist/memory/impact/impact-recorder.js +2 -1
- package/dist/memory/impact/impact-store.d.ts +5 -0
- package/dist/memory/impact/impact-store.js +25 -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 +253 -141
- package/dist/memory/intent/intent-shard.d.ts +22 -23
- package/dist/memory/intent/intent-shard.js +1 -1
- 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/attach-journal.d.ts +11 -0
- package/dist/memory/journal/attach-journal.js +1 -1
- 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 +2 -2
- package/dist/memory/journal/drive-flow.js +21 -12
- package/dist/memory/journal/envelope-store.js +2 -3
- package/dist/memory/journal/journal-query.d.ts +35 -1
- package/dist/memory/journal/journal-query.js +46 -0
- package/dist/memory/journal/journal-recorder.d.ts +71 -2
- package/dist/memory/journal/journal-recorder.js +45 -7
- 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 +91 -2
- package/dist/memory/journal/on-disk/retention.js +181 -11
- 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 -2
- package/dist/memory/journal/on-disk/workspace-gitignore.js +6 -38
- package/dist/memory/journal/on-disk/workspace-tiers.d.ts +52 -0
- package/dist/memory/journal/on-disk/workspace-tiers.js +88 -0
- package/dist/memory/journal/route-template.d.ts +22 -0
- package/dist/memory/journal/route-template.js +44 -0
- package/dist/memory/journal/self-observation.d.ts +3 -0
- package/dist/memory/journal/self-observation.js +67 -0
- package/dist/memory/journal/session-end.d.ts +17 -4
- package/dist/memory/journal/session-end.js +85 -7
- package/dist/memory/journal/session-journal.d.ts +122 -5
- package/dist/memory/journal/session-journal.js +489 -32
- package/dist/memory/project/artifact-root-resolver.d.ts +3 -0
- package/dist/memory/project/artifact-root-resolver.js +89 -0
- package/dist/memory/project/artifact-root.d.ts +39 -2
- package/dist/memory/project/artifact-root.js +58 -1
- package/dist/memory/project/baselines.d.ts +1 -1
- package/dist/memory/project/dir/fill-value-store.d.ts +32 -0
- package/dist/memory/project/dir/fill-value-store.js +88 -0
- package/dist/memory/project/dir/reticle-dir.d.ts +15 -5
- package/dist/memory/project/dir/reticle-dir.js +11 -0
- package/dist/memory/project/fs/fs-port.d.ts +22 -1
- package/dist/memory/project/fs/fs-port.js +72 -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/learned-routes.d.ts +16 -2
- package/dist/memory/project/learned-routes.js +26 -10
- package/dist/memory/project/project-for-root.d.ts +30 -0
- package/dist/memory/project/project-for-root.js +43 -0
- package/dist/memory/project/project-tools.js +10 -5
- package/dist/memory/project/session-root.d.ts +35 -6
- package/dist/memory/project/session-root.js +70 -8
- 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 +9 -0
- package/dist/portal/bridge/auth-failure-reason.js +20 -3
- package/dist/portal/bridge/bridge.d.ts +6 -1
- package/dist/portal/bridge/bridge.js +36 -2
- package/dist/portal/input/real-input.js +2 -1
- 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.js +1 -0
- 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-server-probe.d.ts +2 -1
- 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/session-replaced.d.ts +19 -0
- package/dist/portal/session/facts/session-replaced.js +22 -0
- package/dist/portal/session/live-control-tools.js +48 -3
- package/dist/portal/session/no-session-diagnosis.d.ts +1 -0
- package/dist/portal/session/no-session-diagnosis.js +67 -60
- package/dist/portal/session/no-session-next-action.js +3 -2
- package/dist/portal/session/no-session-watch.js +14 -10
- package/dist/portal/session/presence/attachment-history.d.ts +13 -2
- package/dist/portal/session/rebind.d.ts +18 -0
- package/dist/portal/session/rebind.js +38 -0
- package/dist/portal/session/session-health.d.ts +61 -0
- package/dist/portal/session/session-health.js +40 -1
- package/dist/portal/session/session-info.d.ts +6 -0
- package/dist/portal/session/session-manager.d.ts +13 -0
- package/dist/portal/session/session-manager.js +42 -3
- 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 +26 -10
- package/dist/portal/session/session.js +48 -49
- package/dist/status-payload.d.ts +12 -1
- package/dist/status-payload.js +4 -1
- package/dist/surface/http-server.js +3 -5
- package/dist/surface/mcp/faults/mcp-outage.d.ts +2 -1
- package/dist/surface/mcp/faults/mcp-outage.js +20 -4
- package/dist/surface/mcp/mcp-proxy.d.ts +10 -1
- package/dist/surface/mcp/mcp-proxy.js +23 -12
- package/dist/surface/mcp/mcp.d.ts +10 -1
- package/dist/surface/mcp/mcp.js +59 -29
- package/dist/surface/mcp/proxy/proxy-daemon-probe.d.ts +15 -2
- package/dist/surface/mcp/proxy/proxy-daemon-probe.js +22 -5
- package/dist/surface/mcp/proxy/proxy-log.d.ts +5 -11
- package/dist/surface/mcp/proxy/proxy-log.js +7 -22
- package/dist/surface/mcp/proxy-idle-exit.d.ts +2 -1
- package/dist/surface/mcp/server-instructions.js +12 -1
- package/dist/surface/tools/act/act-preflight.js +6 -1
- 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/navigation/navigate-arrival.d.ts +6 -0
- package/dist/surface/tools/act/navigation/navigate-arrival.js +13 -0
- package/dist/surface/tools/act/sequence-grade.js +13 -0
- 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.js +49 -8
- package/dist/surface/tools/act-tools.js +25 -24
- 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 +14 -2
- package/dist/surface/tools/assert/assert-verdict.js +74 -21
- package/dist/surface/tools/browser-tools.js +4 -3
- package/dist/surface/tools/coverage-tools.js +5 -2
- package/dist/surface/tools/dynamic-tools.js +43 -46
- package/dist/surface/tools/error-recovery.d.ts +6 -0
- package/dist/surface/tools/error-recovery.js +15 -0
- package/dist/surface/tools/explore-tools.js +80 -7
- package/dist/surface/tools/feedback-tools.d.ts +2 -1
- package/dist/surface/tools/feedback-tools.js +50 -3
- package/dist/surface/tools/first-sentence.d.ts +24 -0
- package/dist/surface/tools/first-sentence.js +0 -0
- package/dist/surface/tools/harness-explore.d.ts +125 -1
- package/dist/surface/tools/harness-explore.js +401 -15
- package/dist/surface/tools/harness-plan.d.ts +76 -0
- package/dist/surface/tools/harness-plan.js +156 -0
- package/dist/surface/tools/harness-toolset.js +12 -1
- package/dist/surface/tools/invoke-tool.js +82 -9
- 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 +53 -5
- package/dist/surface/tools/lineage-tools.js +1 -1
- package/dist/surface/tools/live-call-text.d.ts +6 -0
- package/dist/surface/tools/live-call-text.js +36 -2
- package/dist/surface/tools/observe-tools.js +69 -15
- package/dist/surface/tools/read/query-windowed.d.ts +1 -1
- package/dist/surface/tools/read/query-windowed.js +1 -1
- package/dist/surface/tools/read-tools.js +1 -2
- 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 +23 -3
- package/dist/surface/tools/tool-kit.js +6 -1
- package/dist/surface/tools/tool-surface.js +17 -5
- package/dist/surface/tools/tools-helpers.d.ts +8 -7
- package/dist/surface/tools/tools-helpers.js +11 -13
- package/dist/surface/tools/tools.js +70 -30
- package/dist/telemetry/bug-found.js +32 -2
- package/dist/telemetry/feedback-context.js +3 -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 +6 -0
- package/dist/telemetry/harness-drive.js +39 -0
- package/dist/telemetry/hud-metrics.d.ts +32 -0
- package/dist/telemetry/hud-metrics.js +95 -0
- package/dist/telemetry/mcp-connection.d.ts +14 -1
- package/dist/telemetry/mcp-connection.js +17 -2
- package/dist/telemetry/onboarding-firsts.d.ts +30 -1
- package/dist/telemetry/onboarding-firsts.js +54 -12
- package/dist/telemetry/session-metrics.d.ts +5 -0
- package/dist/telemetry/session-metrics.js +15 -1
- package/dist/telemetry/verification-of.js +31 -3
- package/dist/wire-journal.d.ts +31 -0
- package/dist/wire-journal.js +100 -0
- package/docs/README.md +1 -0
- package/docs/agent-cheatsheet.md +7 -3
- package/docs/autodrive.md +42 -2
- package/docs/benchmarks.md +1 -1
- package/docs/capabilities.mdx +1 -1
- package/docs/cli/cloud.mdx +11 -9
- package/docs/cli/doctor.mdx +1 -0
- package/docs/cli/init.mdx +1 -0
- package/docs/cli/report.mdx +44 -0
- package/docs/cli/status.mdx +35 -20
- package/docs/cli.mdx +8 -18
- package/docs/desktop.mdx +1 -1
- package/docs/faq.mdx +1 -1
- package/docs/flows.md +11 -0
- package/docs/frameworks.mdx +113 -1
- package/docs/install-agentic.mdx +36 -0
- package/docs/install-manual.mdx +1 -1
- package/docs/packages/tauri.mdx +1 -1
- package/docs/packages.mdx +1 -1
- package/docs/predicates.mdx +144 -4
- package/docs/system-map.md +6 -4
- package/docs/telemetry.md +2 -1
- package/docs/token-efficiency.md +2 -2
- package/docs/tools/overview.mdx +1 -1
- package/docs/tools/query.mdx +10 -10
- package/docs/troubleshooting.mdx +8 -2
- package/docs/usage.md +2 -2
- package/docs/what-is-recorded.md +62 -0
- package/package.json +5 -5
- package/dist/judgement/outcome/predicate-to-expect.d.ts +0 -44
- package/dist/judgement/outcome/predicate-to-expect.js +0 -148
|
@@ -27,18 +27,12 @@ export declare function accountProxyLogWrite(bytesSinceCheck: number, written: n
|
|
|
27
27
|
/**
|
|
28
28
|
* Reclaim a proxy log that a previous process already let run away. Returns the bytes reclaimed.
|
|
29
29
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
* the cap alone does not help them: nobody should have to find one with `du`.
|
|
30
|
+
* Path-shaped wrapper over `recoverOversizedLog`, which is where the rule, the in-place truncation
|
|
31
|
+
* and the ENOSPC incident behind them are written down. Both of Reticle's logs are capped by that
|
|
32
|
+
* one function; this keeps the name and the `fileSize`/`truncateFile` deps its callers already pass.
|
|
34
33
|
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
* until that handle closes — which is why `: > ~/.reticle/proxy-4400.log` is the operation to copy
|
|
38
|
-
* here.
|
|
39
|
-
*
|
|
40
|
-
* Best-effort, in the same spirit as `rotateDaemonLog`: refusing to start the MCP server over
|
|
41
|
-
* housekeeping is strictly worse than a large file.
|
|
34
|
+
* Such files already exist on machines that ran an older build, and the cap alone does not help
|
|
35
|
+
* them: nobody should have to find one with `du`.
|
|
42
36
|
*/
|
|
43
37
|
export declare function recoverOversizedProxyLog(path: string, deps: {
|
|
44
38
|
fileSize(p: string): number;
|
|
@@ -10,7 +10,7 @@ import { homedir } from 'node:os';
|
|
|
10
10
|
import { join } from 'node:path';
|
|
11
11
|
import { ReticleDir } from '@reticlehq/core';
|
|
12
12
|
import { log } from '../../../log.js';
|
|
13
|
-
import { MAX_DAEMON_LOG_BYTES, rotateDaemonLog } from '../../../command/daemon/daemon.js';
|
|
13
|
+
import { MAX_DAEMON_LOG_BYTES, recoverOversizedLog, rotateDaemonLog, } from '../../../command/daemon/daemon.js';
|
|
14
14
|
/**
|
|
15
15
|
* Which port this proxy serves, for the log file name. Set once at startup.
|
|
16
16
|
*
|
|
@@ -46,30 +46,15 @@ export function accountProxyLogWrite(bytesSinceCheck, written, path, deps) {
|
|
|
46
46
|
/**
|
|
47
47
|
* Reclaim a proxy log that a previous process already let run away. Returns the bytes reclaimed.
|
|
48
48
|
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
* the cap alone does not help them: nobody should have to find one with `du`.
|
|
49
|
+
* Path-shaped wrapper over `recoverOversizedLog`, which is where the rule, the in-place truncation
|
|
50
|
+
* and the ENOSPC incident behind them are written down. Both of Reticle's logs are capped by that
|
|
51
|
+
* one function; this keeps the name and the `fileSize`/`truncateFile` deps its callers already pass.
|
|
53
52
|
*
|
|
54
|
-
*
|
|
55
|
-
*
|
|
56
|
-
* until that handle closes — which is why `: > ~/.reticle/proxy-4400.log` is the operation to copy
|
|
57
|
-
* here.
|
|
58
|
-
*
|
|
59
|
-
* Best-effort, in the same spirit as `rotateDaemonLog`: refusing to start the MCP server over
|
|
60
|
-
* housekeeping is strictly worse than a large file.
|
|
53
|
+
* Such files already exist on machines that ran an older build, and the cap alone does not help
|
|
54
|
+
* them: nobody should have to find one with `du`.
|
|
61
55
|
*/
|
|
62
56
|
export function recoverOversizedProxyLog(path, deps, max = MAX_DAEMON_LOG_BYTES) {
|
|
63
|
-
|
|
64
|
-
const size = deps.fileSize(path);
|
|
65
|
-
if (max >= size)
|
|
66
|
-
return 0;
|
|
67
|
-
deps.truncateFile(path);
|
|
68
|
-
return size;
|
|
69
|
-
}
|
|
70
|
-
catch {
|
|
71
|
-
return 0;
|
|
72
|
-
}
|
|
57
|
+
return recoverOversizedLog({ size: () => deps.fileSize(path), truncate: () => deps.truncateFile(path) }, max);
|
|
73
58
|
}
|
|
74
59
|
/** The real filesystem behind the two rotation helpers. */
|
|
75
60
|
const proxyLogFileOps = {
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
export declare const PROXY_IDLE_EXIT_MS: number;
|
|
11
11
|
/** The local diagnostic emitted before an abandoned proxy exits. */
|
|
12
12
|
export declare const PROXY_IDLE_EXIT_EVENT = "reticle_mcp_proxy_idle_exit";
|
|
13
|
-
|
|
13
|
+
interface ProxyIdleExitOptions {
|
|
14
14
|
/** Called once after the client link has stayed quiet for the whole grace. */
|
|
15
15
|
onExit: (idleMs: number) => void;
|
|
16
16
|
/** True while a request or queued message still needs an answer. */
|
|
@@ -43,3 +43,4 @@ export declare class ProxyIdleExit {
|
|
|
43
43
|
* zero as the explicit opt-out. Invalid values retain the conservative one-day default.
|
|
44
44
|
*/
|
|
45
45
|
export declare function resolveProxyIdleExitMs(raw: string | undefined): number;
|
|
46
|
+
export {};
|
|
@@ -31,7 +31,18 @@ import { surfaceVocabulary, listOf } from './surface-vocabulary.js';
|
|
|
31
31
|
* measured reason. A briefing that names a tool the agent was not given does not merely confuse it;
|
|
32
32
|
* it makes the agent stop using the product altogether.
|
|
33
33
|
*/
|
|
34
|
-
|
|
34
|
+
/*
|
|
35
|
+
* `reticle gate` is FOLDED INTO the done sentence rather than given a paragraph, and that is the
|
|
36
|
+
* budget rule working rather than a stylistic choice.
|
|
37
|
+
*
|
|
38
|
+
* The instruction block has a hard byte cap whose own note says a raise must be paid for with a
|
|
39
|
+
* measurement, and that if one cannot be shown the right answer is to cut an older sentence. There
|
|
40
|
+
* is no measurement for `gate`: it is built, it has anti-reward-hacking, and it appeared in no
|
|
41
|
+
* surface an agent reads, which is an argument and not a number. Cutting a measured sentence to
|
|
42
|
+
* make room for an unmeasured one would be strictly worse. So it costs about a hundred characters
|
|
43
|
+
* inside the sentence that already names the exact moment it applies to, and the cap did not move.
|
|
44
|
+
*/
|
|
45
|
+
const verdictDiscipline = (v) => `Reticle verifies a running web app from the inside: go (${v.navigate}), look (${listOf(v.look, v.find)}), act and prove in one hop (${v.actAndWait}), observe (${listOf(v.observe, v.state, v.network, v.console)}), assert (${v.assert}). Verify a user-facing change against the real app before you call it done — \`npx @reticlehq/server gate --since <ref>\` fails unless a passing artifact covers every flow your edits affect — and never weaken a check to make it pass.
|
|
35
46
|
|
|
36
47
|
Only ${v.actAndWait} and ${v.assert} produce a verdict. ${v.act.length > 0 ? `${v.act} and e` : 'E'}verything else moves or reads the app and proves nothing, so a drive that ends without one of those two has no result however many tools it used. Prefer ${v.actAndWait}({ ref, action, until }) — it names the expected consequence BEFORE the action, which is the difference between a check and a rationalisation. Only verified:"yes" is a pass — "unknown" means Reticle could not tell what happened, "no-fault" means nothing was declared to prove. Report either as not proved.
|
|
37
48
|
|
|
@@ -14,7 +14,7 @@ import { PredicateSchema } from '@reticlehq/engine/question/predicate/predicate-
|
|
|
14
14
|
import { isGlobalPressCall } from '@reticlehq/core';
|
|
15
15
|
import { SessionReplacedError } from '../../../portal/session/page-commands/pending-commands.js';
|
|
16
16
|
import { assertNativeInputSupported } from './act-danger.js';
|
|
17
|
-
import { unevaluablePredicateReason } from '@reticlehq/engine/question/predicate/predicate-precheck.js';
|
|
17
|
+
import { unevaluablePredicateReason, vacuousPredicateReason, } from '@reticlehq/engine/question/predicate/predicate-precheck.js';
|
|
18
18
|
/**
|
|
19
19
|
* Refuse a sequence whose steps cannot be addressed.
|
|
20
20
|
*
|
|
@@ -137,6 +137,11 @@ export function preflightAct(actArgs, until) {
|
|
|
137
137
|
const unevaluable = unevaluablePredicateReason(until);
|
|
138
138
|
if (unevaluable !== undefined)
|
|
139
139
|
throw new Error(unevaluable);
|
|
140
|
+
// A predicate that was already true when it was written answered `no-fault` / `already_true` —
|
|
141
|
+
// verdict-shaped, and carrying no proof of anything the action did. See vacuousPredicateReason.
|
|
142
|
+
const vacuous = vacuousPredicateReason(until);
|
|
143
|
+
if (vacuous !== undefined)
|
|
144
|
+
throw new Error(vacuous);
|
|
140
145
|
}
|
|
141
146
|
/**
|
|
142
147
|
* Dispatch a write, or report that its outcome went unobserved.
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Predicate } from '@reticlehq/engine/question/predicate/predicate-schema.js';
|
|
2
|
+
import type { PredicateSession } from '@reticlehq/engine/question/predicate/predicate-session.js';
|
|
3
|
+
import type { Baselines } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
4
|
+
/** Everything the pre-action check learned, which is three facts about one reading. */
|
|
5
|
+
export interface AlreadyTrueReading {
|
|
6
|
+
/** The consequence held BEFORE the action, so the action proved nothing about it. */
|
|
7
|
+
alreadyTrue: boolean;
|
|
8
|
+
/** That pre-existing match was against something hidden — a stronger reason to doubt the claim. */
|
|
9
|
+
alreadyTrueHiddenMatch: boolean;
|
|
10
|
+
/**
|
|
11
|
+
* WHAT was already true, kept rather than discarded.
|
|
12
|
+
*
|
|
13
|
+
* `already_true` tells an agent its assertion held before it acted; the next question is always
|
|
14
|
+
* "true how?" and it was unanswerable, because the reading decided the bit and was then thrown
|
|
15
|
+
* away. Afterwards the action has run and the state may have moved, so the one moment that
|
|
16
|
+
* mattered is gone. Present only when the answer is yes: a verdict that was genuinely caused
|
|
17
|
+
* carries its own evidence and needs no baseline beside it.
|
|
18
|
+
*/
|
|
19
|
+
alreadyTrueEvidence?: unknown;
|
|
20
|
+
/**
|
|
21
|
+
* What each comparing leaf was reading BEFORE the action — the predicate language's past tense.
|
|
22
|
+
*
|
|
23
|
+
* Taken here because this is already the one place that looks at the app before it is touched,
|
|
24
|
+
* and a second pre-action pass would be a second round trip for a reading we are standing next
|
|
25
|
+
* to. Empty unless the caller actually asked for a comparison, so nothing pays for it.
|
|
26
|
+
*/
|
|
27
|
+
baselines: Baselines;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Ask whether the declared consequence was already true, once, before the action.
|
|
31
|
+
*
|
|
32
|
+
* Only for predicates that read live DOM state. Event-based ones are floored at this act's cursor
|
|
33
|
+
* and cannot be satisfied by the past, so they need no pre-check and pay nothing. One extra query,
|
|
34
|
+
* on the path where a green is otherwise unfalsifiable.
|
|
35
|
+
*
|
|
36
|
+
* Gathered here rather than as three locals at the call site because they are three readings OF ONE
|
|
37
|
+
* THING, and `act-tools.ts` sits on the 1000-line cohesion cap: the rule says split before adding,
|
|
38
|
+
* and this is the unit that wanted splitting.
|
|
39
|
+
*/
|
|
40
|
+
export declare function readAlreadyTrue(session: PredicateSession, until: Predicate | undefined, since: number): Promise<AlreadyTrueReading>;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { evaluatePredicate } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
2
|
+
import { readsDomState } from '@reticlehq/engine/evidence/already-true.js';
|
|
3
|
+
import { alreadyTrueHiddenMatch as alreadyTrueHiddenMatchOf } from '@reticlehq/engine/evidence/already-true.js';
|
|
4
|
+
import { captureBaselines } from '@reticlehq/engine/evidence/baseline.js';
|
|
5
|
+
/**
|
|
6
|
+
* Ask whether the declared consequence was already true, once, before the action.
|
|
7
|
+
*
|
|
8
|
+
* Only for predicates that read live DOM state. Event-based ones are floored at this act's cursor
|
|
9
|
+
* and cannot be satisfied by the past, so they need no pre-check and pay nothing. One extra query,
|
|
10
|
+
* on the path where a green is otherwise unfalsifiable.
|
|
11
|
+
*
|
|
12
|
+
* Gathered here rather than as three locals at the call site because they are three readings OF ONE
|
|
13
|
+
* THING, and `act-tools.ts` sits on the 1000-line cohesion cap: the rule says split before adding,
|
|
14
|
+
* and this is the unit that wanted splitting.
|
|
15
|
+
*/
|
|
16
|
+
export async function readAlreadyTrue(session, until, since) {
|
|
17
|
+
// Before the pre-check, because the pre-check EVALUATES the predicate and a relative leaf with no
|
|
18
|
+
// baseline yet would report `inconclusive` — reading the app twice to answer a question we had
|
|
19
|
+
// not taken the reading for.
|
|
20
|
+
const baselines = await captureBaselines(session, until);
|
|
21
|
+
const precheck = until !== undefined && readsDomState(until)
|
|
22
|
+
? await evaluatePredicate(session, until, since, false, baselines)
|
|
23
|
+
: undefined;
|
|
24
|
+
const alreadyTrue = precheck?.pass ?? false;
|
|
25
|
+
if (!alreadyTrue || until === undefined) {
|
|
26
|
+
return { alreadyTrue: false, alreadyTrueHiddenMatch: false, baselines };
|
|
27
|
+
}
|
|
28
|
+
return {
|
|
29
|
+
alreadyTrue: true,
|
|
30
|
+
baselines,
|
|
31
|
+
// The pre-check evidence is already in hand, so asking whether the match was against something
|
|
32
|
+
// hidden costs nothing and lets the message name it (#889).
|
|
33
|
+
alreadyTrueHiddenMatch: alreadyTrueHiddenMatchOf(until, precheck?.evidence),
|
|
34
|
+
...(precheck?.evidence === undefined ? {} : { alreadyTrueEvidence: precheck.evidence }),
|
|
35
|
+
};
|
|
36
|
+
}
|
|
@@ -24,6 +24,12 @@ import type { NavigateArrival } from './navigate-result.js';
|
|
|
24
24
|
* and the SDK to dial back; short enough to not hang. A caller who knows the app is slower says so.
|
|
25
25
|
*/
|
|
26
26
|
export declare const ARRIVAL_TIMEOUT_MS = 5000;
|
|
27
|
+
/**
|
|
28
|
+
* The navigation target as an absolute URL, resolved against the tab being navigated — the same
|
|
29
|
+
* resolution the browser applies. An agent passes a path (`/orders?id=4`) as often as a full URL,
|
|
30
|
+
* and `samePage` cannot parse a path, so without this a relative navigation could never confirm.
|
|
31
|
+
*/
|
|
32
|
+
export declare function absoluteTarget(target: string, base: string): string;
|
|
27
33
|
/**
|
|
28
34
|
* Which session an arrival may be attributed to.
|
|
29
35
|
*
|
|
@@ -41,6 +41,19 @@ function samePage(a, b) {
|
|
|
41
41
|
return false;
|
|
42
42
|
}
|
|
43
43
|
}
|
|
44
|
+
/**
|
|
45
|
+
* The navigation target as an absolute URL, resolved against the tab being navigated — the same
|
|
46
|
+
* resolution the browser applies. An agent passes a path (`/orders?id=4`) as often as a full URL,
|
|
47
|
+
* and `samePage` cannot parse a path, so without this a relative navigation could never confirm.
|
|
48
|
+
*/
|
|
49
|
+
export function absoluteTarget(target, base) {
|
|
50
|
+
try {
|
|
51
|
+
return new URL(target, base).href;
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
return target;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
44
57
|
/**
|
|
45
58
|
* The sessions already on `target` — the set `ArrivalScope.priorIds` is built from, sampled before
|
|
46
59
|
* the navigation is dispatched.
|
|
@@ -39,6 +39,19 @@ export function gradeSequence(steps, plan = { planned: steps.length, dispatched:
|
|
|
39
39
|
because: `a declared consequence did not hold — observed ${observed}`,
|
|
40
40
|
};
|
|
41
41
|
}
|
|
42
|
+
/*
|
|
43
|
+
* `unknown` rather than `no-fault`, and the distinction is load-bearing.
|
|
44
|
+
*
|
|
45
|
+
* "Nothing was declared" is what `no-fault` means for a single action -- but the engine only says
|
|
46
|
+
* it over a SETTLED window, because no-fault claims the whole window was observed. Nothing on
|
|
47
|
+
* this path observes settledness: the caller tracks dispatch and stalls, never settle. Saying
|
|
48
|
+
* `no-fault` here would claim evidence nobody collected, in the one place this product cannot
|
|
49
|
+
* afford to overclaim.
|
|
50
|
+
*
|
|
51
|
+
* So the enum stays conservative and the SENTENCE carries the whole answer: it names declaring a
|
|
52
|
+
* consequence as the next move, which is what an agent reading `no-fault` would have done.
|
|
53
|
+
* Upgrading means plumbing `settled` from the act results through `SequencePlan`.
|
|
54
|
+
*/
|
|
42
55
|
if (0 === declared) {
|
|
43
56
|
return {
|
|
44
57
|
verified: Verified.UNKNOWN,
|
|
@@ -34,6 +34,10 @@ export interface SettleSource {
|
|
|
34
34
|
data: Record<string, unknown>;
|
|
35
35
|
}[];
|
|
36
36
|
elapsed(): number;
|
|
37
|
+
/** The page under test — what makes a request third-party. Absent: nothing is foreign. */
|
|
38
|
+
url?: string;
|
|
39
|
+
/** Same-origin endpoints the project declared as background. Absent: nothing is excluded. */
|
|
40
|
+
background?: readonly string[];
|
|
37
41
|
}
|
|
38
42
|
interface WaitOpts {
|
|
39
43
|
/** Injected so the wait is testable without real time passing (rule: never call the clock inline). */
|
|
@@ -49,7 +53,7 @@ interface WaitOpts {
|
|
|
49
53
|
export declare function inFlightRequestIds(events: readonly {
|
|
50
54
|
type: string;
|
|
51
55
|
data: Record<string, unknown>;
|
|
52
|
-
}[]): string[];
|
|
56
|
+
}[], appOrigin?: string, background?: readonly string[]): string[];
|
|
53
57
|
/**
|
|
54
58
|
* The same outstanding requests, as "METHOD url" — what an unsettled verdict has to be able to name.
|
|
55
59
|
*
|
|
@@ -61,7 +65,7 @@ export declare function inFlightRequestIds(events: readonly {
|
|
|
61
65
|
export declare function inFlightRequestLabels(events: readonly {
|
|
62
66
|
type: string;
|
|
63
67
|
data: Record<string, unknown>;
|
|
64
|
-
}[]): string[];
|
|
68
|
+
}[], appOrigin?: string, background?: readonly string[]): string[];
|
|
65
69
|
/**
|
|
66
70
|
* Endpoints called MORE THAN ONCE in this window, busiest first, as "METHOD url ×N".
|
|
67
71
|
*
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* - still in flight when the budget genuinely runs out → `unsettled`, as before, but now an honest
|
|
28
28
|
* limit instead of an early exit.
|
|
29
29
|
*/
|
|
30
|
-
import { EventType, NetInitiator, isDevToolingUrl } from '@reticlehq/core';
|
|
30
|
+
import { EventType, NetInitiator, isDevToolingUrl, isForeignTraffic } from '@reticlehq/core';
|
|
31
31
|
/**
|
|
32
32
|
* The dev toolchain talking about ITSELF is not the app finishing its work.
|
|
33
33
|
*
|
|
@@ -37,6 +37,25 @@ import { EventType, NetInitiator, isDevToolingUrl } from '@reticlehq/core';
|
|
|
37
37
|
* was graded on the strength of a Next webpack hot-update the same payload printed as ignored.
|
|
38
38
|
*/
|
|
39
39
|
const isDevTooling = (data) => isDevToolingUrl('string' === typeof data['url'] ? data['url'] : undefined);
|
|
40
|
+
/**
|
|
41
|
+
* Somebody else's host is not the app finishing its work.
|
|
42
|
+
*
|
|
43
|
+
* The comment above makes this argument for dev tooling and it holds identically here:
|
|
44
|
+
* `splitForeignTraffic` drops dev tooling AND third-party traffic, and this file dropped only the
|
|
45
|
+
* first — so the exclusion stayed cosmetic exactly where it decides a verdict, for the other half.
|
|
46
|
+
*
|
|
47
|
+
* Reported from the field repeatedly: an app embedding a wallet SDK that continuously POSTs
|
|
48
|
+
* telemetry to its vendor host never settles, so EVERY assertion on that app returns
|
|
49
|
+
* `unknown / outcome_pending` whatever the feature under test was. A third-party beacon cannot
|
|
50
|
+
* answer "has the app finished?", and nothing makes it stop, so waiting for it is waiting forever.
|
|
51
|
+
*
|
|
52
|
+
* Fails OPEN: with no known app origin nothing is foreign, because suppressing a request we cannot
|
|
53
|
+
* classify is how a verdict starts resting on evidence it discarded.
|
|
54
|
+
*
|
|
55
|
+
* SAME-ORIGIN background traffic is never guessed: nothing in a URL separates the app's telemetry
|
|
56
|
+
* from the app's work. It is excluded only when the project DECLARED it (`background`).
|
|
57
|
+
*/
|
|
58
|
+
const isForeign = (data, appOrigin, background) => isForeignTraffic('string' === typeof data['url'] ? data['url'] : undefined, appOrigin, background);
|
|
40
59
|
/**
|
|
41
60
|
* A departure records where the browser was SENT, not a request whose result we will see — the
|
|
42
61
|
* response is delivered to a document this session does not live into. It can never be matched by a
|
|
@@ -54,7 +73,7 @@ const idOf = (data) => 'string' === typeof data['id'] ? data['id'] : undefined;
|
|
|
54
73
|
* the act cursor, so a response belonging to an earlier action can land inside it, and counting that
|
|
55
74
|
* as progress would let unrelated traffic close the window early.
|
|
56
75
|
*/
|
|
57
|
-
export function inFlightRequestIds(events) {
|
|
76
|
+
export function inFlightRequestIds(events, appOrigin, background = []) {
|
|
58
77
|
const settled = new Set();
|
|
59
78
|
for (const e of events) {
|
|
60
79
|
if (e.type !== EventType.NET_REQUEST)
|
|
@@ -67,6 +86,8 @@ export function inFlightRequestIds(events) {
|
|
|
67
86
|
for (const e of events) {
|
|
68
87
|
if (e.type !== EventType.NET_PENDING || isDevTooling(e.data) || isDeparture(e.data))
|
|
69
88
|
continue;
|
|
89
|
+
if (isForeign(e.data, appOrigin, background))
|
|
90
|
+
continue;
|
|
70
91
|
const id = idOf(e.data);
|
|
71
92
|
if (id !== undefined && !settled.has(id) && !open.includes(id))
|
|
72
93
|
open.push(id);
|
|
@@ -81,8 +102,8 @@ export function inFlightRequestIds(events) {
|
|
|
81
102
|
* directly. Read off the NET_PENDING the window already holds, so this costs one pass over events
|
|
82
103
|
* that are in hand.
|
|
83
104
|
*/
|
|
84
|
-
export function inFlightRequestLabels(events) {
|
|
85
|
-
const open = new Set(inFlightRequestIds(events));
|
|
105
|
+
export function inFlightRequestLabels(events, appOrigin, background = []) {
|
|
106
|
+
const open = new Set(inFlightRequestIds(events, appOrigin, background));
|
|
86
107
|
const labels = [];
|
|
87
108
|
for (const e of events) {
|
|
88
109
|
if (e.type !== EventType.NET_PENDING)
|
|
@@ -136,7 +157,9 @@ export function repeatedRequestLabels(events) {
|
|
|
136
157
|
* timeout reaching the predicate, and a negative deadline must mean "stop", never "loop forever".
|
|
137
158
|
*/
|
|
138
159
|
export async function waitForInFlight(session, since, budgetMs, opts) {
|
|
139
|
-
|
|
160
|
+
// The verdict's own scope: waiting on a request the verdict will not count is latency for nothing.
|
|
161
|
+
const outstanding = () => inFlightRequestIds(session.eventsSince(since), session.url, session.background);
|
|
162
|
+
let open = outstanding();
|
|
140
163
|
if (0 === open.length)
|
|
141
164
|
return { settled: true, stillInFlight: [] };
|
|
142
165
|
if (budgetMs <= 0)
|
|
@@ -145,7 +168,7 @@ export async function waitForInFlight(session, since, budgetMs, opts) {
|
|
|
145
168
|
while (session.elapsed() < deadline) {
|
|
146
169
|
// Never overshoot the budget: the last sleep is trimmed to whatever is actually left.
|
|
147
170
|
await opts.sleep(Math.min(POLL_MS, deadline - session.elapsed()));
|
|
148
|
-
open =
|
|
171
|
+
open = outstanding();
|
|
149
172
|
if (0 === open.length)
|
|
150
173
|
return { settled: true, stillInFlight: [] };
|
|
151
174
|
}
|
|
@@ -10,7 +10,7 @@
|
|
|
10
10
|
* must never fail the run that found it.
|
|
11
11
|
*/
|
|
12
12
|
import { ActionType, AnchorKind } from '@reticlehq/core';
|
|
13
|
-
import { CapsuleStore, capsuleId, CAPSULE_VERSION } from '../../judgement/capsule/capsule-store.js';
|
|
13
|
+
import { CapsuleStore, capsuleFingerprint, capsuleId, CAPSULE_VERSION, } from '../../judgement/capsule/capsule-store.js';
|
|
14
14
|
import { ReticleTool } from '@reticlehq/core';
|
|
15
15
|
import { asRecord, asString } from '@reticlehq/core';
|
|
16
16
|
import { sessionRoot } from '../../memory/project/session-root.js';
|
|
@@ -19,7 +19,6 @@ export async function saveFailedAssertCapsule(inputs) {
|
|
|
19
19
|
const { deps, verdict, capsule, links, args, actResult, actedSource, root: given } = inputs;
|
|
20
20
|
if (verdict.pass || capsule === undefined)
|
|
21
21
|
return undefined;
|
|
22
|
-
const id = capsuleId(deps.now(), asString(args['ref']) ?? 'assert');
|
|
23
22
|
const expectedText = links
|
|
24
23
|
.map((l) => ('name' in l ? `${l.kind} ${String(l.name)}` : l.kind))
|
|
25
24
|
.join(' AND ');
|
|
@@ -27,11 +26,26 @@ export async function saveFailedAssertCapsule(inputs) {
|
|
|
27
26
|
// Same rule and same resolver as every other artifact: a capsule written into a sibling repo is
|
|
28
27
|
// evidence filed against a codebase that did not produce it, and it outlives the turn.
|
|
29
28
|
// The caller's answer wins; the resolver is the fallback for callers that have no session.
|
|
30
|
-
const root = given ??
|
|
31
|
-
|
|
29
|
+
const root = given ?? bestEffortRoot(deps, asString(args['sessionId']));
|
|
30
|
+
// No directory this capsule could honestly belong to, so it is not filed. The two things this
|
|
31
|
+
// must not do are write it somewhere arbitrary and throw: the assertion has already failed, the
|
|
32
|
+
// verdict is already built, and losing the capsule must never also lose the verdict.
|
|
33
|
+
if (root === undefined)
|
|
34
|
+
return undefined;
|
|
35
|
+
// Built BEFORE the id, because the id carries the fingerprint of this body — that is what lets a
|
|
36
|
+
// retry of the same broken step fold into the capsule already on disk instead of adding a file.
|
|
37
|
+
/*
|
|
38
|
+
* What this capsule is ABOUT, for its filename and its anchor.
|
|
39
|
+
*
|
|
40
|
+
* The testid is the element said in a name a human chose; `args.ref` is a volatile handle minted
|
|
41
|
+
* per session, meaningless an hour later and anywhere else. The anchor may still fall back to the
|
|
42
|
+
* ref, because the anchor has to address the element and the ref is what addressed it. The NAME
|
|
43
|
+
* must not: a capsule is durable, meant to be committed, and read by somebody who was not there.
|
|
44
|
+
*/
|
|
45
|
+
const testid = asString(asRecord(actResult.result)['testid']);
|
|
46
|
+
const action = asString(args['action']) ?? ActionType.CLICK;
|
|
47
|
+
const body = {
|
|
32
48
|
version: CAPSULE_VERSION,
|
|
33
|
-
id,
|
|
34
|
-
createdAt: deps.now(),
|
|
35
49
|
origin: 'failed-assert',
|
|
36
50
|
expected: expectedText.length > 0 ? expectedText : 'declared consequence',
|
|
37
51
|
observed: capsule.firstDivergence?.observed ?? verdict.failureReason ?? 'not observed',
|
|
@@ -40,14 +54,41 @@ export async function saveFailedAssertCapsule(inputs) {
|
|
|
40
54
|
tool: ReticleTool.ACT,
|
|
41
55
|
anchor: {
|
|
42
56
|
kind: AnchorKind.TESTID,
|
|
43
|
-
value:
|
|
57
|
+
value: testid ?? asString(args['ref']) ?? '',
|
|
44
58
|
// Carried so the saved capsule — which outlives this turn and becomes a regression flow
|
|
45
59
|
// when it goes green — still knows which file the failure came from.
|
|
46
60
|
...(actedSource === undefined ? {} : { source: actedSource }),
|
|
47
61
|
},
|
|
48
|
-
action:
|
|
62
|
+
action: action,
|
|
49
63
|
},
|
|
50
64
|
],
|
|
65
|
+
};
|
|
66
|
+
const id = capsuleId(deps.now(), testid ?? action, capsuleFingerprint(body));
|
|
67
|
+
const saved = await new CapsuleStore(deps.fs, root).save({
|
|
68
|
+
...body,
|
|
69
|
+
id,
|
|
70
|
+
createdAt: deps.now(),
|
|
51
71
|
});
|
|
52
72
|
return saved ? id : undefined;
|
|
53
73
|
}
|
|
74
|
+
/**
|
|
75
|
+
* Where this capsule goes, or nothing — never a throw and never somebody else's checkout.
|
|
76
|
+
*
|
|
77
|
+
* `sessionRoot` refuses a `sessionId` that names no session, because for a tool the agent CALLED
|
|
78
|
+
* the alternative is silently writing into the daemon's own project. Here the caller is not a tool
|
|
79
|
+
* the agent called: it is the evidence capture hanging off a verdict that has already been decided,
|
|
80
|
+
* and on this path a refusal would convert a red assertion into a tool error. Both of the answers
|
|
81
|
+
* that refusal exists to prevent are still prevented — nothing is written, and nothing is written
|
|
82
|
+
* to the wrong root — by declining to file the capsule at all.
|
|
83
|
+
*
|
|
84
|
+
* Reachable only when the act's own session AND its navigation successor are gone by the time the
|
|
85
|
+
* verdict lands, since `act_and_wait` passes the root of the session it actually drove.
|
|
86
|
+
*/
|
|
87
|
+
function bestEffortRoot(deps, sessionId) {
|
|
88
|
+
try {
|
|
89
|
+
return sessionRoot(deps, sessionId);
|
|
90
|
+
}
|
|
91
|
+
catch {
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
}
|
|
@@ -42,7 +42,6 @@ import { waitForReaction } from './act/react-grace.js';
|
|
|
42
42
|
import { decideVerified } from '@reticlehq/engine/evidence/verified.js';
|
|
43
43
|
import { honestyForVerdict } from '@reticlehq/engine/evidence/honesty.js';
|
|
44
44
|
import { declaredExpectations, declaresBodyIndependentChannel, } from '@reticlehq/engine/question/declared.js';
|
|
45
|
-
import { readsDomState, alreadyTrueHiddenMatch as alreadyTrueHiddenMatchOf, } from '@reticlehq/engine/evidence/already-true.js';
|
|
46
45
|
import { describeWaitTarget, namedNetIsInFlight } from '@reticlehq/engine/evidence/unsettled.js';
|
|
47
46
|
import { saveFailedAssertCapsule } from './act-capsule.js';
|
|
48
47
|
import { blastRadius, buildDivergenceCapsule, wireCapsule } from '../../judgement/capsule/capsule.js';
|
|
@@ -52,7 +51,8 @@ import { absenceBlindSpotNote, buildCoverageStatement, blindSpotsFromState, tran
|
|
|
52
51
|
import { acceptedWriteLabels } from '@reticlehq/engine/evidence/accepted-write.js';
|
|
53
52
|
import { unreadWriteLabels } from '@reticlehq/engine/evidence/unread-outcome.js';
|
|
54
53
|
import { evaluatePredicate, waitForPredicate, provenExpectedLinks, PredicateSchema, } from '@reticlehq/engine/question/predicate/predicate.js';
|
|
55
|
-
import {
|
|
54
|
+
import { sessionVerdictFacts } from '../../portal/session/session-verdict-facts.js';
|
|
55
|
+
import { currentOf, healthEnvelope, refuseIfThrottled } from '../../portal/session/session-health.js';
|
|
56
56
|
import { pausedShortCircuit, pausedOutputShape, withControl, PAUSED_NO_VERDICT, } from '../../portal/session/control-envelope.js';
|
|
57
57
|
import { asNumber, asRecord, asString } from '@reticlehq/core';
|
|
58
58
|
import { sourceOf } from './tools-helpers.js';
|
|
@@ -64,6 +64,7 @@ import { asActionType, gradeOf } from './act/act-helpers.js';
|
|
|
64
64
|
import { resolveActTarget } from './act/act-target.js';
|
|
65
65
|
import { tryRealInput, rewriteUploadArgs, HOVER_NEEDS_POINTER_MSG } from './real-input-attempt.js';
|
|
66
66
|
import { gradeOfPredicate } from './assert/assert-grade.js';
|
|
67
|
+
import { readAlreadyTrue } from './act/already-true.js';
|
|
67
68
|
/**
|
|
68
69
|
* Narrow the wire's `action` to a real ActionType, or undefined.
|
|
69
70
|
*
|
|
@@ -428,22 +429,10 @@ export const ACT_TOOLS = [
|
|
|
428
429
|
// A verdict that lives only in the response lives only in the agent's context window, which is
|
|
429
430
|
// exactly the copy a compaction destroys — see runs/run-context.ts.
|
|
430
431
|
let verdictEffect;
|
|
431
|
-
// Was the
|
|
432
|
-
|
|
433
|
-
// past, so they need no pre-check and pay nothing. One extra query, on the path where a green
|
|
434
|
-
// is otherwise unfalsifiable. See engine/src/evidence/already-true.ts.
|
|
435
|
-
const alreadyTruePrecheck = until !== undefined && readsDomState(until)
|
|
436
|
-
? await evaluatePredicate(session, until, since, false)
|
|
437
|
-
: undefined;
|
|
438
|
-
const alreadyTrue = alreadyTruePrecheck?.pass ?? false;
|
|
432
|
+
// Was the consequence ALREADY TRUE, and what did that reading say? See act/already-true.ts.
|
|
433
|
+
const { alreadyTrue, alreadyTrueHiddenMatch, alreadyTrueEvidence, baselines } = await readAlreadyTrue(session, until, since);
|
|
439
434
|
// Same as the ACT handler: the route this step RAN on, before the action can move the app.
|
|
440
435
|
const routeBeforeWait = pathOf(session.url);
|
|
441
|
-
// #889: the pre-check evidence is already in hand — cheap to also ask whether that match was
|
|
442
|
-
// against something hidden, so the already_true message can name it instead of leaving the
|
|
443
|
-
// agent to re-derive "was this actually showing?" from nothing.
|
|
444
|
-
const alreadyTrueHiddenMatch = alreadyTrue && until !== undefined
|
|
445
|
-
? alreadyTrueHiddenMatchOf(until, alreadyTruePrecheck?.evidence)
|
|
446
|
-
: false;
|
|
447
436
|
try {
|
|
448
437
|
// actCommand is the single interception point for upload+path rewrite.
|
|
449
438
|
//
|
|
@@ -472,8 +461,8 @@ export const ACT_TOOLS = [
|
|
|
472
461
|
let verdict = null === actResult
|
|
473
462
|
? { pass: false, observationLost: true }
|
|
474
463
|
: timeout > 0
|
|
475
|
-
? await waitForPredicate(session, until, timeout, since)
|
|
476
|
-
: await evaluatePredicate(session, until, since);
|
|
464
|
+
? await waitForPredicate(session, until, timeout, since, baselines)
|
|
465
|
+
: await evaluatePredicate(session, until, since, true, baselines);
|
|
477
466
|
// The SDK may have gone away mid-act — see act-observation.ts.
|
|
478
467
|
const followed = await followLostObservation({
|
|
479
468
|
sessions: deps.sessions,
|
|
@@ -481,7 +470,7 @@ export const ACT_TOOLS = [
|
|
|
481
470
|
verdict,
|
|
482
471
|
timeout,
|
|
483
472
|
predicateStarted,
|
|
484
|
-
reevaluate: (next, budget) => waitForPredicate(next, until, budget, 0),
|
|
473
|
+
reevaluate: (next, budget) => waitForPredicate(next, until, budget, 0, baselines),
|
|
485
474
|
});
|
|
486
475
|
if (followed.followed)
|
|
487
476
|
since = 0;
|
|
@@ -654,17 +643,17 @@ export const ACT_TOOLS = [
|
|
|
654
643
|
currentDocumentId: session.currentDocumentId,
|
|
655
644
|
currentEditEpoch: session.currentEditEpoch,
|
|
656
645
|
appOrigin: session.url,
|
|
646
|
+
background: session.background,
|
|
657
647
|
});
|
|
658
648
|
// The single field an agent reads. Everything below it is the evidence it was derived from;
|
|
659
649
|
// this is the only one that has to be interpreted, and now it interprets itself.
|
|
660
650
|
const outcomePending = acceptedWriteLabels(windowEvents);
|
|
661
651
|
const outcomeUnread = unreadWriteLabels(windowEvents);
|
|
662
|
-
const stillInFlight = inFlightRequestLabels(windowEvents);
|
|
652
|
+
const stillInFlight = inFlightRequestLabels(windowEvents, session.url, session.background);
|
|
663
653
|
const decision = decideVerified({
|
|
664
654
|
pass: verdict.pass,
|
|
665
|
-
//
|
|
666
|
-
|
|
667
|
-
...(session.sdkVersion === undefined ? {} : { sdkVersion: session.sdkVersion }),
|
|
655
|
+
// Threaded rather than looked up: decideVerified is pure and has no session.
|
|
656
|
+
...sessionVerdictFacts(session),
|
|
668
657
|
// The caller NAMED the consequence rather than defaulting to "wait for idle". A
|
|
669
658
|
// declaration made before the action is what this tool sells, and idle-settlement was
|
|
670
659
|
// overriding it — see `declaredConsequence`. An explicit `{ kind: "settled" }` is not a
|
|
@@ -770,6 +759,16 @@ export const ACT_TOOLS = [
|
|
|
770
759
|
// which is why the two are recorded apart rather than assumed alike.
|
|
771
760
|
declaredBeforeActing: true,
|
|
772
761
|
grade: gradeOfPredicate(until),
|
|
762
|
+
// What the declared consequence READ. The run fold has only the journal, so a kind absent
|
|
763
|
+
// here was being invented there as `element`. Same field, same reason, on the assert path.
|
|
764
|
+
kind: until.kind,
|
|
765
|
+
// The deciding clause, kept — and it was NOT, on this path, the commonest one. `unknown`
|
|
766
|
+
// alone cannot tell an outcome that has not arrived from a capture that could not be
|
|
767
|
+
// read, so a fold over the journal saw a verdict it could not attribute, and the
|
|
768
|
+
// attribution is the only part of an `unknown` a reader can act on. The comment above
|
|
769
|
+
// says "same field, same reason, on the assert path" and was half true. Found by the
|
|
770
|
+
// session gap summary, whose `undecidedBy` was empty for every unknown this tool made.
|
|
771
|
+
reason: decision.verifiedReason,
|
|
773
772
|
};
|
|
774
773
|
// Recorded on the session, so a later "am I done?" can answer with what is STILL missing
|
|
775
774
|
// rather than with everything that was ever missing. An empty list closes a gap, which is
|
|
@@ -777,6 +776,8 @@ export const ACT_TOOLS = [
|
|
|
777
776
|
noteSessionGaps(session, gaps);
|
|
778
777
|
return withControl(session, {
|
|
779
778
|
...decision,
|
|
779
|
+
// WHAT was already true, not only that something was (4.1) — see act/already-true.ts.
|
|
780
|
+
...(alreadyTrueEvidence === undefined ? {} : { alreadyTrueEvidence }),
|
|
780
781
|
// An unobserved act has no effect to report, and inventing an empty one would read as
|
|
781
782
|
// "the page did nothing" — a claim about the app, from a call that never saw it.
|
|
782
783
|
...(null === actResult ? {} : { effect: leanActResult(actResult.result) }),
|
|
@@ -823,7 +824,7 @@ export const ACT_TOOLS = [
|
|
|
823
824
|
...(0 === greenRadius.length ? {} : { blastRadius: greenRadius }),
|
|
824
825
|
since,
|
|
825
826
|
...(session.id === actedSessionId ? {} : { sessionId: session.id }),
|
|
826
|
-
...healthEnvelope(session),
|
|
827
|
+
...healthEnvelope(currentOf(deps.sessions, session)),
|
|
827
828
|
});
|
|
828
829
|
}
|
|
829
830
|
finally {
|
|
@@ -31,8 +31,6 @@ export declare const MAX_BLOCKING_WAIT_MS: number;
|
|
|
31
31
|
* in the name of bounding one that never worked.
|
|
32
32
|
*/
|
|
33
33
|
export declare const MAX_STATE_DEPTH = 256;
|
|
34
|
-
/** Scroll-to-find steps. Default is 20; hundreds is searching, thousands is a hang. */
|
|
35
|
-
export declare const MAX_SCROLLS = 200;
|
|
36
34
|
/** Viewport CSS px — matches the clamp the handler already applied, now as a refusal. */
|
|
37
35
|
export declare const MIN_VIEWPORT_PX = 64;
|
|
38
36
|
export declare const MAX_VIEWPORT_PX = 10000;
|
|
@@ -45,6 +43,21 @@ export declare const cursorSchema: z.ZodNumber;
|
|
|
45
43
|
* A wait budget in ms. 0 means evaluate now (documented on assert). Negative cannot be honoured.
|
|
46
44
|
*/
|
|
47
45
|
export declare const timeoutMsSchema: z.ZodNumber;
|
|
46
|
+
/**
|
|
47
|
+
* `reticle_wait_for`'s budget, which may exceed one call: it waits at most MAX_BLOCKING_WAIT_MS per
|
|
48
|
+
* call and hands back `resume_ms` for the rest (#601, from #635).
|
|
49
|
+
*/
|
|
50
|
+
export declare const waitForTimeoutMsSchema: z.ZodNumber;
|
|
51
|
+
/**
|
|
52
|
+
* What is left of a wait that stopped at the per-call limit, or undefined when there is nothing to
|
|
53
|
+
* resume: the predicate held, the whole budget fit in this call, or the wait ended for a reason
|
|
54
|
+
* waiting longer cannot change (the page went away, or the read could not be made).
|
|
55
|
+
*/
|
|
56
|
+
export declare function resumeAfter(requestedMs: number, perCallMs: number, verdict: {
|
|
57
|
+
pass: boolean;
|
|
58
|
+
observationLost?: boolean;
|
|
59
|
+
inconclusive?: string;
|
|
60
|
+
}): number | undefined;
|
|
48
61
|
/**
|
|
49
62
|
* A count / cap. 0 means "return none", which is a real request. Negative is not.
|
|
50
63
|
* Capped at the ring-buffer size so a `limit: 1e9` cannot pretend the buffer is larger than it is.
|