@reticlehq/server 2.12.0 → 2.13.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/SKILL.md +67 -109
- package/dist/bridge/auth-failure-reason.d.ts +6 -2
- package/dist/bridge/auth-failure-reason.js +15 -8
- package/dist/bridge/bridge.d.ts +18 -1
- package/dist/bridge/bridge.js +247 -164
- package/dist/bridge/pairing-token.d.ts +5 -0
- package/dist/bridge/pairing-token.js +28 -0
- package/dist/bridge/protocol-skew.d.ts +37 -0
- package/dist/bridge/protocol-skew.js +45 -0
- package/dist/capsule/capsule-store.d.ts +6 -6
- package/dist/capsule/causal-summary.js +7 -2
- package/dist/cli/cli-doctor.js +31 -1
- package/dist/cli/cli-launch.d.ts +11 -1
- package/dist/cli/cli-launch.js +59 -10
- package/dist/cli/cli-parse.d.ts +15 -1
- package/dist/cli/cli-parse.js +212 -8
- package/dist/cli/cli-verify.d.ts +1 -0
- package/dist/cli/cli-verify.js +3 -2
- package/dist/cli/cloud-cli.js +428 -259
- package/dist/cli/cloud-keystore.d.ts +37 -0
- package/dist/cli/cloud-keystore.js +97 -0
- package/dist/cli/cloud-kit.d.ts +37 -0
- package/dist/cli/cloud-kit.js +121 -0
- package/dist/cli/cloud-login.d.ts +17 -0
- package/dist/cli/cloud-login.js +183 -0
- package/dist/cli/cloud-session.d.ts +48 -0
- package/dist/cli/cloud-session.js +53 -0
- package/dist/cli/config-discovery.js +1 -0
- package/dist/cli/daemon-start-options.d.ts +32 -0
- package/dist/cli/daemon-start-options.js +38 -0
- package/dist/cli/device-flow.d.ts +76 -0
- package/dist/cli/device-flow.js +56 -0
- package/dist/cli/doctor-rows.d.ts +9 -0
- package/dist/cli/doctor-rows.js +9 -0
- package/dist/cli/drive-attach.d.ts +13 -0
- package/dist/cli/drive-attach.js +18 -0
- package/dist/cli/drive-command.js +7 -3
- package/dist/cli/mcp-command.js +51 -20
- package/dist/cli/project-name.d.ts +30 -0
- package/dist/cli/project-name.js +44 -0
- package/dist/cli/status-next-action.d.ts +14 -0
- package/dist/cli/status-next-action.js +4 -4
- package/dist/cli.d.ts +1 -0
- package/dist/cli.js +134 -80
- package/dist/cloud/cloud-config.d.ts +22 -1
- package/dist/cloud/cloud-config.js +64 -5
- package/dist/cloud/cloud-sync.d.ts +5 -5
- package/dist/cloud/cloud-sync.js +33 -2
- package/dist/cloud/sync-cycle.d.ts +110 -0
- package/dist/cloud/sync-cycle.js +270 -0
- package/dist/cloud/sync-daemon.d.ts +69 -0
- package/dist/cloud/sync-daemon.js +260 -0
- package/dist/cloud/sync-disk.d.ts +9 -0
- package/dist/cloud/sync-disk.js +191 -0
- package/dist/cloud/sync-hash.d.ts +2 -0
- package/dist/cloud/sync-hash.js +35 -0
- package/dist/crawl/crawl-tools.js +5 -3
- package/dist/crawl/crawl.d.ts +3 -0
- package/dist/crawl/crawl.js +5 -0
- package/dist/daemon/daemon-resolve.d.ts +43 -0
- package/dist/daemon/daemon-resolve.js +69 -0
- package/dist/daemon/dev-servers.d.ts +15 -0
- package/dist/daemon/dev-servers.js +68 -0
- package/dist/daemon/wake-decision.d.ts +32 -0
- package/dist/daemon/wake-decision.js +38 -0
- package/dist/domain/domain-tools.js +2 -2
- package/dist/events/contradictions.d.ts +18 -0
- package/dist/events/contradictions.js +134 -21
- package/dist/events/declared.d.ts +7 -4
- package/dist/events/declared.js +15 -6
- package/dist/events/echo-mismatch.js +64 -14
- package/dist/events/event-filters.d.ts +8 -0
- package/dist/events/event-filters.js +19 -2
- package/dist/events/predicate-eval.js +53 -5
- package/dist/events/predicate-precheck.d.ts +8 -0
- package/dist/events/predicate-precheck.js +41 -0
- package/dist/events/predicate-route.d.ts +14 -0
- package/dist/events/predicate-route.js +36 -8
- package/dist/events/predicate.d.ts +5 -0
- package/dist/events/predicate.js +37 -5
- package/dist/events/split-text-miss.d.ts +30 -0
- package/dist/events/split-text-miss.js +44 -0
- package/dist/flows/flake.d.ts +6 -6
- package/dist/flows/flow-memory-consult.d.ts +55 -0
- package/dist/flows/flow-memory-consult.js +38 -0
- package/dist/flows/flow-replay-run.d.ts +18 -7
- package/dist/flows/flow-replay-run.js +239 -22
- package/dist/flows/flow-replay.js +11 -2
- package/dist/flows/flow-step-runners.d.ts +8 -0
- package/dist/flows/flow-step-runners.js +8 -2
- package/dist/flows/flow-store-for-session.d.ts +31 -0
- package/dist/flows/flow-store-for-session.js +33 -0
- package/dist/flows/flow-tools.js +58 -32
- package/dist/flows/flows.d.ts +8 -0
- package/dist/flows/flows.js +468 -2
- package/dist/flows/heal-run.js +5 -2
- package/dist/flows/predicate-to-expect.d.ts +17 -12
- package/dist/flows/predicate-to-expect.js +30 -12
- package/dist/flows/recordings.d.ts +13 -1
- package/dist/flows/recordings.js +17 -2
- package/dist/flows/replay.d.ts +22 -2
- package/dist/flows/replay.js +28 -2
- package/dist/flows/verify-change-tools.js +5 -2
- package/dist/honesty/blind-spots.d.ts +55 -2
- package/dist/honesty/blind-spots.js +63 -3
- package/dist/honesty/honesty.d.ts +24 -0
- package/dist/honesty/honesty.js +25 -1
- package/dist/honesty/instrumentation-gaps.d.ts +9 -0
- package/dist/honesty/instrumentation-gaps.js +29 -2
- package/dist/honesty/verified.d.ts +2 -1
- package/dist/honesty/verified.js +16 -1
- package/dist/http-server.js +12 -0
- package/dist/impact/impact-recorder.d.ts +31 -8
- package/dist/impact/impact-recorder.js +104 -21
- package/dist/impact/impact-store.d.ts +15 -1
- package/dist/impact/impact-store.js +43 -2
- package/dist/index.js +113 -7
- package/dist/init/agent-rules.d.ts +13 -6
- package/dist/init/agent-rules.js +23 -12
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +28 -0
- package/dist/init/capabilities.d.ts +4 -1
- package/dist/init/capabilities.js +22 -2
- package/dist/init/confirm.d.ts +31 -7
- package/dist/init/confirm.js +48 -8
- package/dist/init/cra.d.ts +20 -4
- package/dist/init/cra.js +57 -17
- package/dist/init/csp-check.js +17 -2
- package/dist/init/csp-doctor.d.ts +8 -1
- package/dist/init/csp-doctor.js +8 -3
- package/dist/init/dev-script.d.ts +3 -1
- package/dist/init/dev-script.js +8 -5
- package/dist/init/format-generated.d.ts +18 -0
- package/dist/init/format-generated.js +39 -0
- package/dist/init/install-hint.d.ts +9 -0
- package/dist/init/install-hint.js +29 -0
- package/dist/init/mcp-clients.d.ts +7 -0
- package/dist/init/mcp-clients.js +7 -0
- package/dist/init/mcp.d.ts +1 -1
- package/dist/init/mcp.js +1 -1
- package/dist/init/node-io.js +11 -1
- package/dist/init/plan-framework.js +81 -45
- package/dist/init/plan.d.ts +20 -7
- package/dist/init/plan.js +20 -45
- package/dist/init/preflight.d.ts +28 -0
- package/dist/init/preflight.js +38 -0
- package/dist/init/run.d.ts +32 -9
- package/dist/init/run.js +141 -119
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/snippets.js +41 -25
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +39 -25
- package/dist/init/workspace-apps.d.ts +17 -10
- package/dist/init/workspace-apps.js +110 -0
- package/dist/input/network-mock-tools.js +3 -6
- package/dist/input/real-input.js +25 -5
- package/dist/input/scroll-tools.js +4 -6
- package/dist/input/viewport-tools.js +5 -4
- package/dist/intent/inline-intent.d.ts +10 -19
- package/dist/intent/inline-intent.js +91 -1
- package/dist/intent/intent-shard-store.d.ts +72 -0
- package/dist/intent/intent-shard-store.js +203 -0
- package/dist/intent/intent-shard.d.ts +411 -0
- package/dist/intent/intent-shard.js +176 -0
- package/dist/intent/intent-store.d.ts +12 -0
- package/dist/intent/intent-store.js +21 -0
- package/dist/intent/intent-subject.d.ts +45 -0
- package/dist/intent/intent-subject.js +177 -0
- package/dist/intent/intent-tools.js +65 -2
- package/dist/intent/open-intents.d.ts +21 -0
- package/dist/intent/open-intents.js +15 -0
- package/dist/license/license-env.d.ts +29 -0
- package/dist/license/license-env.js +148 -0
- package/dist/loopback-agent.d.ts +31 -0
- package/dist/loopback-agent.js +57 -0
- package/dist/mcp/attach-memory.d.ts +18 -2
- package/dist/mcp/attach-memory.js +50 -7
- package/dist/mcp/client-identity.d.ts +31 -0
- package/dist/mcp/client-identity.js +51 -0
- package/dist/mcp/mcp-post-transport.d.ts +26 -0
- package/dist/mcp/mcp-post-transport.js +109 -0
- package/dist/mcp/mcp-proxy.d.ts +2 -1
- package/dist/mcp/mcp-proxy.js +52 -62
- package/dist/mcp/mcp.js +7 -1
- package/dist/mcp/proxy-backoff.d.ts +11 -0
- package/dist/mcp/proxy-backoff.js +13 -0
- package/dist/mcp/proxy-daemon-probe.d.ts +1 -0
- package/dist/mcp/proxy-daemon-probe.js +7 -1
- package/dist/mcp/proxy-handshake.d.ts +23 -0
- package/dist/mcp/proxy-handshake.js +31 -0
- package/dist/mcp/tool-catalog-cache.d.ts +8 -0
- package/dist/mcp/tool-catalog-cache.js +12 -0
- package/dist/memory/memory-tools.d.ts +2 -0
- package/dist/memory/memory-tools.js +82 -0
- package/dist/memory/project-memory.d.ts +34 -0
- package/dist/memory/project-memory.js +96 -0
- package/dist/oracles/propose-consequences.js +12 -3
- package/dist/pool/browser-pool.d.ts +63 -4
- package/dist/pool/browser-pool.js +113 -4
- package/dist/pool/playwright-launcher.js +9 -0
- package/dist/project/project-tools.js +3 -3
- package/dist/project/reticle-dir.d.ts +15 -2
- package/dist/project/reticle-dir.js +21 -4
- package/dist/runs/run-store.d.ts +10 -0
- package/dist/runs/run-store.js +10 -0
- package/dist/runs/verification-sync.d.ts +0 -11
- package/dist/runs/verification-sync.js +22 -1
- package/dist/runs/verify-server.d.ts +8 -1
- package/dist/runs/verify-server.js +14 -2
- package/dist/session/command-timeout.d.ts +5 -2
- package/dist/session/command-timeout.js +5 -4
- package/dist/session/lease-visibility.d.ts +67 -0
- package/dist/session/lease-visibility.js +76 -0
- package/dist/session/no-session-diagnosis.d.ts +23 -0
- package/dist/session/no-session-diagnosis.js +58 -17
- package/dist/session/no-session-next-action.d.ts +7 -0
- package/dist/session/no-session-next-action.js +42 -3
- package/dist/session/no-session-watch.d.ts +10 -6
- package/dist/session/no-session-watch.js +51 -19
- package/dist/session/pending-commands.d.ts +11 -1
- package/dist/session/pending-commands.js +12 -2
- package/dist/session/resolve-within.d.ts +34 -0
- package/dist/session/resolve-within.js +53 -0
- package/dist/session/session-info.d.ts +18 -0
- package/dist/session/session-info.js +11 -0
- package/dist/session/session-manager.d.ts +14 -0
- package/dist/session/session-manager.js +61 -3
- package/dist/session/session-mirror.d.ts +16 -0
- package/dist/session/session-mirror.js +22 -0
- package/dist/session/session-recommendation.d.ts +19 -5
- package/dist/session/session-recommendation.js +25 -9
- package/dist/session/session-successor.js +36 -1
- package/dist/session/session-tools.js +2 -2
- package/dist/session/session.d.ts +22 -2
- package/dist/session/session.js +87 -7
- package/dist/session/wall-clock.d.ts +12 -0
- package/dist/session/wall-clock.js +14 -0
- package/dist/setup/agent-configs.d.ts +96 -0
- package/dist/setup/agent-configs.js +333 -0
- package/dist/setup/agent-io.d.ts +9 -0
- package/dist/setup/agent-io.js +16 -0
- package/dist/setup/agent-writer.d.ts +51 -0
- package/dist/setup/agent-writer.js +115 -0
- package/dist/setup/approval-migration.d.ts +47 -0
- package/dist/setup/approval-migration.js +68 -0
- package/dist/setup/auto-approve.d.ts +85 -0
- package/dist/setup/auto-approve.js +150 -0
- package/dist/setup/bridge-port.d.ts +15 -0
- package/dist/setup/bridge-port.js +24 -0
- package/dist/setup/desktop-shape.d.ts +57 -0
- package/dist/setup/desktop-shape.js +63 -0
- package/dist/setup/dev-server-wait.d.ts +68 -0
- package/dist/setup/dev-server-wait.js +67 -0
- package/dist/setup/drive-agent.d.ts +71 -0
- package/dist/setup/drive-agent.js +171 -0
- package/dist/setup/drive-plan.d.ts +68 -0
- package/dist/setup/drive-plan.js +130 -0
- package/dist/setup/ensure-daemon.d.ts +29 -0
- package/dist/setup/ensure-daemon.js +58 -0
- package/dist/setup/init-runtime.d.ts +47 -0
- package/dist/setup/init-runtime.js +160 -0
- package/dist/setup/interrupt.d.ts +25 -0
- package/dist/setup/interrupt.js +40 -0
- package/dist/setup/license-key.d.ts +39 -0
- package/dist/setup/license-key.js +72 -0
- package/dist/setup/listeners.d.ts +37 -0
- package/dist/setup/listeners.js +85 -0
- package/dist/setup/node-effects.d.ts +60 -0
- package/dist/setup/node-effects.js +210 -0
- package/dist/setup/page-probe.d.ts +39 -0
- package/dist/setup/page-probe.js +49 -0
- package/dist/setup/relaunch.d.ts +36 -0
- package/dist/setup/relaunch.js +57 -0
- package/dist/setup/remaining-steps.d.ts +19 -0
- package/dist/setup/remaining-steps.js +31 -0
- package/dist/setup/run-setup.d.ts +99 -0
- package/dist/setup/run-setup.js +203 -0
- package/dist/setup/session-pick.d.ts +47 -0
- package/dist/setup/session-pick.js +51 -0
- package/dist/setup/setup-command.d.ts +45 -0
- package/dist/setup/setup-command.js +199 -0
- package/dist/setup/setup-options.d.ts +74 -0
- package/dist/setup/setup-options.js +67 -0
- package/dist/setup/transcripts.d.ts +16 -0
- package/dist/setup/transcripts.js +43 -0
- package/dist/status-payload.d.ts +14 -1
- package/dist/status-payload.js +23 -1
- package/dist/telemetry/daemon-telemetry.d.ts +8 -1
- package/dist/telemetry/daemon-telemetry.js +52 -5
- package/dist/telemetry/error-class.js +1 -1
- package/dist/telemetry/feedback-context.d.ts +9 -1
- package/dist/telemetry/feedback-context.js +60 -29
- package/dist/telemetry/feedback-local.d.ts +15 -0
- package/dist/telemetry/feedback-local.js +56 -0
- package/dist/telemetry/feedback.d.ts +11 -0
- package/dist/telemetry/feedback.js +19 -6
- package/dist/telemetry/init-telemetry.d.ts +2 -0
- package/dist/telemetry/init-telemetry.js +2 -0
- package/dist/telemetry/install-source.d.ts +14 -0
- package/dist/telemetry/install-source.js +30 -0
- package/dist/telemetry/license-activation.d.ts +7 -1
- package/dist/telemetry/license-activation.js +9 -5
- package/dist/telemetry/mcp-connection.js +7 -0
- package/dist/telemetry/project-profile.d.ts +12 -1
- package/dist/telemetry/project-profile.js +11 -6
- package/dist/telemetry/proxy-telemetry.d.ts +3 -0
- package/dist/telemetry/proxy-telemetry.js +21 -0
- package/dist/telemetry/session-metrics.d.ts +12 -0
- package/dist/telemetry/session-metrics.js +35 -1
- package/dist/telemetry/telemetry.js +17 -2
- package/dist/telemetry/tool-refused.d.ts +3 -1
- package/dist/telemetry/tool-refused.js +34 -2
- package/dist/tools/act-capsule.d.ts +10 -0
- package/dist/tools/act-capsule.js +8 -2
- package/dist/tools/act-danger.d.ts +2 -1
- package/dist/tools/act-danger.js +11 -3
- package/dist/tools/act-observation.d.ts +41 -0
- package/dist/tools/act-observation.js +36 -0
- package/dist/tools/act-preflight.d.ts +20 -0
- package/dist/tools/act-preflight.js +98 -0
- package/dist/tools/act-sequence-retry.d.ts +45 -0
- package/dist/tools/act-sequence-retry.js +58 -0
- package/dist/tools/act-sequence-tool.d.ts +13 -0
- package/dist/tools/act-sequence-tool.js +135 -0
- package/dist/tools/act-target.d.ts +14 -0
- package/dist/tools/act-target.js +47 -0
- package/dist/tools/act-tools.d.ts +21 -1
- package/dist/tools/act-tools.js +100 -213
- package/dist/tools/assert-verdict.js +22 -16
- package/dist/tools/browser-tools.js +6 -2
- package/dist/tools/dynamic-tools.js +24 -5
- package/dist/tools/error-recovery.d.ts +1 -0
- package/dist/tools/error-recovery.js +8 -0
- package/dist/tools/invoke-tool.js +59 -9
- package/dist/tools/lease-tools.d.ts +30 -4
- package/dist/tools/lease-tools.js +169 -5
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +22 -0
- package/dist/tools/numeric-bounds.d.ts +100 -0
- package/dist/tools/numeric-bounds.js +125 -0
- package/dist/tools/observe-tools.js +47 -40
- package/dist/tools/read-tools.js +28 -7
- package/dist/tools/real-input-attempt.d.ts +10 -0
- package/dist/tools/real-input-attempt.js +59 -1
- package/dist/tools/reconcile-tools.js +4 -4
- package/dist/tools/tool-kit.d.ts +12 -0
- package/dist/tools/tool-kit.js +6 -1
- package/dist/tools/tool-names.d.ts +2 -0
- package/dist/tools/tool-names.js +2 -0
- package/dist/tools/tools-helpers.d.ts +19 -0
- package/dist/tools/tools-helpers.js +46 -0
- package/dist/tools/tools.d.ts +2 -0
- package/dist/tools/tools.js +56 -8
- package/dist/update/reticle-deps.d.ts +9 -0
- package/dist/update/reticle-deps.js +27 -0
- package/dist/update/sdk-sync.d.ts +1 -2
- package/dist/update/sdk-sync.js +1 -21
- package/dist/update/update-nudge.d.ts +18 -0
- package/dist/update/update-nudge.js +20 -0
- package/dist/version/peer-announce.js +4 -2
- package/dist/version/sdk-fix.d.ts +47 -0
- package/dist/version/sdk-fix.js +127 -0
- package/dist/version/version-nudge.d.ts +14 -0
- package/dist/version/version-nudge.js +21 -0
- package/dist/version/version-skew.d.ts +38 -3
- package/dist/version/version-skew.js +83 -7
- package/dist/visual/visual-store.d.ts +6 -6
- package/dist/visual/visual-store.js +18 -16
- package/dist/visual/visual-tools.js +57 -12
- package/docs/cli/doctor.mdx +1 -0
- package/docs/cli/serve.mdx +4 -2
- package/docs/cli.mdx +7 -3
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +1 -1
- package/docs/getting-started.md +19 -3
- package/docs/index.mdx +9 -6
- package/docs/install-agentic.mdx +38 -12
- package/docs/install-manual.mdx +1 -1
- package/docs/packages.mdx +1 -1
- package/docs/skill-file.mdx +3 -3
- package/docs/telemetry-contract.md +108 -4
- package/docs/tools-act-sequence.mdx +16 -0
- package/docs/usage.md +1 -1
- package/package.json +4 -3
- package/dist/init/cursor.d.ts +0 -24
- package/dist/init/cursor.js +0 -80
package/dist/tools/act-tools.js
CHANGED
|
@@ -1,15 +1,11 @@
|
|
|
1
|
-
import { normalizeQueryArgs } from './query-shape.js';
|
|
2
|
-
import { resolveTargetRef } from './resolve-target.js';
|
|
3
|
-
/**
|
|
4
|
-
* Action tools — reticle_act, reticle_act_sequence, reticle_act_and_wait. Split out of tools.ts to keep
|
|
5
|
-
* that file under the line cap and assembled back into the tool list there via ...ACT_TOOLS; the
|
|
6
|
-
* native-input attempt itself lives in real-input-attempt.ts for the same reason.
|
|
7
|
-
*/
|
|
8
1
|
import { z } from 'zod';
|
|
9
2
|
import { aliasParam } from './alias-args.js';
|
|
10
|
-
import {
|
|
3
|
+
import { resolveSessionWithin } from '../session/resolve-within.js';
|
|
4
|
+
import { WALL_CLOCK } from '../session/wall-clock.js';
|
|
5
|
+
import { ACT_SEQUENCE_TOOL } from './act-sequence-tool.js';
|
|
6
|
+
import { timeoutMsSchema } from './numeric-bounds.js';
|
|
7
|
+
import { captureAct } from '../flows/replay.js';
|
|
11
8
|
import { ActionType, ActionWarning, CaptureLoss, DEFAULT_ASSERT_TIMEOUT_MS, InputMode, ReticleCommand, Verified, VerifiedReason, PredicateKind, } from '@reticlehq/core';
|
|
12
|
-
import { assertNativeInputSupported } from './act-danger.js';
|
|
13
9
|
import { leanActResult, mutatedWithin } from './act-view.js';
|
|
14
10
|
import { ReticleTool } from './tool-names.js';
|
|
15
11
|
import { buildReactionReport, summarizeReaction } from '../events/reaction.js';
|
|
@@ -19,13 +15,14 @@ import { findContradictions } from '../events/contradictions.js';
|
|
|
19
15
|
import { gapsForAction } from '../honesty/instrumentation-gaps.js';
|
|
20
16
|
import { noteSessionGaps } from '../honesty/gap-ledger.js';
|
|
21
17
|
import { isChangeUndeclared } from '../honesty/undeclared-change.js';
|
|
22
|
-
import { openSessionIntents } from '../intent/open-intents.js';
|
|
18
|
+
import { intentDebt, openSessionIntents } from '../intent/open-intents.js';
|
|
23
19
|
import { dischargeInlineIntent, inlineVerdictId, linkInlineIntent, } from '../intent/inline-intent.js';
|
|
24
20
|
import { declaresState } from '../events/predicate-asks.js';
|
|
25
21
|
import { isStateUnwatched } from '../honesty/blind-spots.js';
|
|
26
22
|
import { inFlightRequestLabels, repeatedRequestLabels, waitForInFlight, } from './settle-in-flight.js';
|
|
27
23
|
import { waitForReaction } from './react-grace.js';
|
|
28
24
|
import { decideVerified } from '../honesty/verified.js';
|
|
25
|
+
import { honestyForVerdict } from '../honesty/honesty.js';
|
|
29
26
|
import { declaredExpectations, declaresBodyIndependentChannel } from '../events/declared.js';
|
|
30
27
|
import { readsDomState } from '../honesty/already-true.js';
|
|
31
28
|
import { describeWaitTarget } from '../honesty/unsettled.js';
|
|
@@ -33,17 +30,19 @@ import { saveFailedAssertCapsule } from './act-capsule.js';
|
|
|
33
30
|
import { buildDivergenceCapsule } from '../capsule/capsule.js';
|
|
34
31
|
import { predicateToExpectedLinks } from '../capsule/predicate-to-links.js';
|
|
35
32
|
import { buildHonestyBlock } from '../honesty/honesty.js';
|
|
36
|
-
import { buildCoverageStatement, blindSpotsFromState, transportGapNote, Coverage, impeachesCapture, } from '../honesty/blind-spots.js';
|
|
33
|
+
import { absenceBlindSpotNote, buildCoverageStatement, blindSpotsFromState, transportGapNote, Coverage, impeachesCapture, } from '../honesty/blind-spots.js';
|
|
37
34
|
import { hasAcceptedWrite } from '../honesty/accepted-write.js';
|
|
38
35
|
import { unreadWriteLabels } from '../honesty/unread-outcome.js';
|
|
39
36
|
import { evaluatePredicate, waitForPredicate, provenExpectedLinks, PredicateSchema, } from '../events/predicate.js';
|
|
40
|
-
import { awaitDocumentSuccessor } from '../session/session-successor.js';
|
|
41
37
|
import { healthEnvelope, refuseIfThrottled } from '../session/session-health.js';
|
|
42
38
|
import { pausedShortCircuit, pausedOutputShape, withControl, PAUSED_NO_VERDICT, } from '../session/control-envelope.js';
|
|
43
39
|
import { asString, asNumber, asRecord, sourceOf } from './tools-helpers.js';
|
|
40
|
+
import { dispatchAct, preflightAct } from './act-preflight.js';
|
|
41
|
+
import { followLostObservation } from './act-observation.js';
|
|
44
42
|
import { intentArg, sessionIdShape } from './tool-kit.js';
|
|
45
43
|
import { asActionType, gradeOf } from './act-helpers.js';
|
|
46
|
-
import {
|
|
44
|
+
import { resolveActTarget } from './act-target.js';
|
|
45
|
+
import { tryRealInput, rewriteUploadArgs, HOVER_NEEDS_POINTER_MSG } from './real-input-attempt.js';
|
|
47
46
|
/**
|
|
48
47
|
* Single dispatch point for every ACT and ACT_SEQUENCE command.
|
|
49
48
|
*
|
|
@@ -55,8 +54,25 @@ import { tryRealInput, rewriteUploadArgs } from './real-input-attempt.js';
|
|
|
55
54
|
* the agent actually wrote) rather than the base64 blob — replay would otherwise send 750 KiB of
|
|
56
55
|
* base64 to the browser as if it were an inline content call.
|
|
57
56
|
*/
|
|
58
|
-
async function actCommand(deps, session, actArgs, timeoutMs) {
|
|
57
|
+
export async function actCommand(deps, session, actArgs, timeoutMs) {
|
|
59
58
|
const rewritten = await rewriteUploadArgs(deps, 'string' === typeof actArgs['action'] ? actArgs['action'] : '', asRecord(actArgs['args']));
|
|
59
|
+
// Sequence and act_and_wait dispatch through here without the ACT handler's tryRealInput.
|
|
60
|
+
// A synthetic hover reports dispatched/settled while CSS :hover never applies — drive a real
|
|
61
|
+
// pointer when one is available, otherwise refuse rather than lie.
|
|
62
|
+
if (ActionType.HOVER === actArgs['action']) {
|
|
63
|
+
const ref = asString(actArgs['ref']);
|
|
64
|
+
if (ref === undefined)
|
|
65
|
+
throw new Error(HOVER_NEEDS_POINTER_MSG);
|
|
66
|
+
const real = await tryRealInput(deps, session, ref, ActionType.HOVER, actArgs);
|
|
67
|
+
if (real.result === undefined)
|
|
68
|
+
throw new Error(HOVER_NEEDS_POINTER_MSG);
|
|
69
|
+
return {
|
|
70
|
+
kind: 'command_result',
|
|
71
|
+
id: 'hover',
|
|
72
|
+
ok: true,
|
|
73
|
+
result: { dispatched: true, settled: real.settled, ...asRecord(real.result) },
|
|
74
|
+
};
|
|
75
|
+
}
|
|
60
76
|
const bridgeArgs = { ...actArgs, args: rewritten };
|
|
61
77
|
return timeoutMs !== undefined
|
|
62
78
|
? session.command(ReticleCommand.ACT, bridgeArgs, timeoutMs)
|
|
@@ -82,41 +98,7 @@ async function actCommand(deps, session, actArgs, timeoutMs) {
|
|
|
82
98
|
*/
|
|
83
99
|
const ACTION_TYPE_VALUES = Object.values(ActionType);
|
|
84
100
|
const ACTION_TYPE_LIST = ACTION_TYPE_VALUES.join(' | ');
|
|
85
|
-
const actionTypeEnum = z.enum(ACTION_TYPE_VALUES);
|
|
86
|
-
/**
|
|
87
|
-
* Resolve an action's element: an explicit `ref`, or a `target` query resolved in the SAME call.
|
|
88
|
-
*
|
|
89
|
-
* Requiring a ref meant every verification paid a `reticle_query` turn first just to learn one
|
|
90
|
-
* string, and the advertised tool surface is re-sent on every turn — measured on the wire, a
|
|
91
|
-
* two-turn verification spent 10,756 of 11,235 tokens on schema and 479 on the actual answers. The
|
|
92
|
-
* lookup still happens; it just stops costing a round trip through the model.
|
|
93
|
-
*
|
|
94
|
-
* `ref` wins when both are given, because it is the more specific instruction and silently
|
|
95
|
-
* preferring the query would act on something the caller did not name.
|
|
96
|
-
*/
|
|
97
|
-
async function resolveActTarget(session, args) {
|
|
98
|
-
const ref = asString(args['ref']);
|
|
99
|
-
if (ref !== undefined && ref.length > 0)
|
|
100
|
-
return { kind: 'ref', ref };
|
|
101
|
-
const target = args['target'];
|
|
102
|
-
if (target === undefined) {
|
|
103
|
-
return {
|
|
104
|
-
kind: 'error',
|
|
105
|
-
message: 'pass `ref` (from reticle_query/reticle_snapshot) or `target` (e.g. { testid } or { role, name }).',
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
const q = normalizeQueryArgs(asRecord(target));
|
|
109
|
-
const out = await session.command(ReticleCommand.QUERY, {
|
|
110
|
-
by: q['by'],
|
|
111
|
-
value: q['value'],
|
|
112
|
-
name: q['name'],
|
|
113
|
-
scope: q['scope'],
|
|
114
|
-
});
|
|
115
|
-
if (!out.ok)
|
|
116
|
-
return { kind: 'error', message: out.error ?? 'target query failed' };
|
|
117
|
-
const elements = asRecord(out.result)['elements'];
|
|
118
|
-
return resolveTargetRef(Array.isArray(elements) ? elements : []);
|
|
119
|
-
}
|
|
101
|
+
export const actionTypeEnum = z.enum(ACTION_TYPE_VALUES);
|
|
120
102
|
export const ACT_TOOLS = [
|
|
121
103
|
{
|
|
122
104
|
name: ReticleTool.ACT,
|
|
@@ -249,127 +231,6 @@ export const ACT_TOOLS = [
|
|
|
249
231
|
}
|
|
250
232
|
},
|
|
251
233
|
},
|
|
252
|
-
{
|
|
253
|
-
name: ReticleTool.ACT_SEQUENCE,
|
|
254
|
-
// The example is required for a core tool, and this one carries weight: the measured loop it
|
|
255
|
-
// replaces is literally a login form driven as three separate reticle_act calls (98 clicks and
|
|
256
|
-
// 21 fills inside looping sessions, 2026-08-10/11). Showing fill -> fill -> click is showing the
|
|
257
|
-
// exact shape an agent otherwise spends three round trips on.
|
|
258
|
-
example: {
|
|
259
|
-
steps: [
|
|
260
|
-
{ ref: 'e12', action: 'fill', args: { value: 'a@b.com' } },
|
|
261
|
-
{ ref: 'e13', action: 'fill', args: { value: 'hunter2' } },
|
|
262
|
-
{ ref: 'e14', action: 'click' },
|
|
263
|
-
],
|
|
264
|
-
},
|
|
265
|
-
description: 'Run multiple actions in order (fill -> fill -> submit) in ONE round-trip. Prefer this over repeating reticle_act for a multi-step journey, then assert its consequence once. Returns per-step effects[] (see reticle_act).',
|
|
266
|
-
inputSchema: {
|
|
267
|
-
steps: z
|
|
268
|
-
.array(z.record(z.unknown()))
|
|
269
|
-
.describe('Ordered list of { ref, action, args? } objects. Each step is equivalent to one reticle_act call; put confirmDangerous:true in a destructive step args object.'),
|
|
270
|
-
timeout_ms: z
|
|
271
|
-
.number()
|
|
272
|
-
.optional()
|
|
273
|
-
.describe('Per-step timeout in milliseconds. Default: 8000. Each step gets this budget independently.'),
|
|
274
|
-
...sessionIdShape,
|
|
275
|
-
},
|
|
276
|
-
outputSchema: {
|
|
277
|
-
since: z.number(),
|
|
278
|
-
dispatched: z.boolean(),
|
|
279
|
-
completed: z.number(),
|
|
280
|
-
stalled_at: z.number().optional(),
|
|
281
|
-
steps: z.array(z.record(z.unknown())).optional(),
|
|
282
|
-
result: z.unknown().optional(),
|
|
283
|
-
session: z
|
|
284
|
-
.object({ lastSeenMs: z.number(), throttled: z.boolean(), focused: z.boolean() })
|
|
285
|
-
.optional(),
|
|
286
|
-
// Short-circuits to pausedShortCircuit while paused — declare its fields (drained-once guidance).
|
|
287
|
-
...pausedOutputShape,
|
|
288
|
-
},
|
|
289
|
-
handler: async (deps, args) => {
|
|
290
|
-
const session = deps.sessions.resolve(asString(args['sessionId']));
|
|
291
|
-
const paused = pausedShortCircuit(session);
|
|
292
|
-
if (paused !== undefined)
|
|
293
|
-
return paused;
|
|
294
|
-
const since = session.elapsed();
|
|
295
|
-
session.beginAction(ReticleTool.ACT_SEQUENCE, asRecord(args));
|
|
296
|
-
try {
|
|
297
|
-
const inputSteps = Array.isArray(args['steps']) ? args['steps'] : [];
|
|
298
|
-
const perStepTimeout = 'number' === typeof args['timeout_ms'] ? args['timeout_ms'] : 8000;
|
|
299
|
-
const stepResults = [];
|
|
300
|
-
let stalledAt;
|
|
301
|
-
// DIVERGENCE: live sends N individual ACT commands (for per-step timeout + progress);
|
|
302
|
-
// replay sends one batched ACT_SEQUENCE command (flows/replay.ts:294). A bug in either is
|
|
303
|
-
// invisible from the other — cover both when changing sequence semantics.
|
|
304
|
-
for (let i = 0; i < inputSteps.length; i++) {
|
|
305
|
-
const step = asRecord(inputSteps[i]);
|
|
306
|
-
try {
|
|
307
|
-
const result = await actCommand(deps, session, { ref: step['ref'], action: step['action'], args: step['args'] ?? {} }, perStepTimeout);
|
|
308
|
-
if (!result.ok) {
|
|
309
|
-
stalledAt = i;
|
|
310
|
-
stepResults.push({
|
|
311
|
-
ref: step['ref'],
|
|
312
|
-
action: step['action'],
|
|
313
|
-
dispatched: false,
|
|
314
|
-
error: result.error ?? 'step failed',
|
|
315
|
-
});
|
|
316
|
-
break;
|
|
317
|
-
}
|
|
318
|
-
const r = asRecord(result.result);
|
|
319
|
-
const stepResult = {
|
|
320
|
-
ref: r['ref'] ?? step['ref'],
|
|
321
|
-
action: r['action'] ?? step['action'],
|
|
322
|
-
dispatched: r['dispatched'] ?? true,
|
|
323
|
-
settled: r['settled'] ?? null,
|
|
324
|
-
settleReason: r['settleReason'] ?? null,
|
|
325
|
-
};
|
|
326
|
-
if (r['testid'] !== undefined)
|
|
327
|
-
stepResult['testid'] = r['testid'];
|
|
328
|
-
if (r['component'] !== undefined)
|
|
329
|
-
stepResult['component'] = r['component'];
|
|
330
|
-
if (r['role'] !== undefined)
|
|
331
|
-
stepResult['role'] = r['role'];
|
|
332
|
-
if (r['name'] !== undefined)
|
|
333
|
-
stepResult['name'] = r['name'];
|
|
334
|
-
if (r['source'] !== undefined)
|
|
335
|
-
stepResult['source'] = r['source'];
|
|
336
|
-
if (r['warning'] !== undefined)
|
|
337
|
-
stepResult['warning'] = r['warning'];
|
|
338
|
-
stepResults.push(stepResult);
|
|
339
|
-
}
|
|
340
|
-
catch (err) {
|
|
341
|
-
stalledAt = i;
|
|
342
|
-
stepResults.push({
|
|
343
|
-
ref: step['ref'],
|
|
344
|
-
action: step['action'],
|
|
345
|
-
dispatched: null,
|
|
346
|
-
timedOut: true,
|
|
347
|
-
error: err instanceof Error ? err.message : 'step timed out',
|
|
348
|
-
});
|
|
349
|
-
break;
|
|
350
|
-
}
|
|
351
|
-
}
|
|
352
|
-
const completed = stalledAt ?? inputSteps.length;
|
|
353
|
-
if (completed > 0) {
|
|
354
|
-
session.lastAct.markActed(since, undefined, undefined);
|
|
355
|
-
}
|
|
356
|
-
if (deps.recordings.active().length > 0 && stalledAt === undefined) {
|
|
357
|
-
deps.recordings.capture(compileSequenceStep(args, { count: inputSteps.length, steps: stepResults }));
|
|
358
|
-
}
|
|
359
|
-
return withControl(session, {
|
|
360
|
-
since,
|
|
361
|
-
dispatched: completed > 0,
|
|
362
|
-
completed,
|
|
363
|
-
...(stalledAt !== undefined ? { stalled_at: stalledAt } : {}),
|
|
364
|
-
steps: stepResults,
|
|
365
|
-
...healthEnvelope(session),
|
|
366
|
-
});
|
|
367
|
-
}
|
|
368
|
-
finally {
|
|
369
|
-
session.finishAction();
|
|
370
|
-
}
|
|
371
|
-
},
|
|
372
|
-
},
|
|
373
234
|
{
|
|
374
235
|
name: ReticleTool.ACT_AND_WAIT,
|
|
375
236
|
example: {
|
|
@@ -399,8 +260,7 @@ export const ACT_TOOLS = [
|
|
|
399
260
|
.describe('Action-specific arguments: { value } for fill/select, { text } for type/press (the key NAME, e.g. Escape or Tab), { modifiers: ["Meta","Shift"] } for a press shortcut (Meta/Control/Shift/Alt), { toRef } for drag (the ref to drop ON — without it the drag lands nowhere), { confirmDangerous: true } for a potentially destructive control. For upload: { path } is a path on disk (absolute or relative to project root; daemon reads real bytes) or { name, content?, type? } for inline bytes.'),
|
|
400
261
|
predicate: PredicateSchema.optional().describe('Alias for `until` (the name reticle_assert / reticle_wait_for use).'),
|
|
401
262
|
until: PredicateSchema.optional().describe('Predicate to wait for after the action completes (same shape as reticle_assert). OMIT to wait for the page to SETTLE — network + DOM idle — the deterministic default instead of a sleep. To assert a consequence AND settle, allOf them: { kind: "allOf", predicates: [<your predicate>, { kind: "settled" }] }.'),
|
|
402
|
-
timeout_ms:
|
|
403
|
-
.number()
|
|
263
|
+
timeout_ms: timeoutMsSchema
|
|
404
264
|
.optional()
|
|
405
265
|
.describe('Maximum wait time in milliseconds. 0 = evaluate once without waiting. Default: 4000.'),
|
|
406
266
|
refuseWhenThrottled: z
|
|
@@ -422,6 +282,10 @@ export const ACT_TOOLS = [
|
|
|
422
282
|
.boolean()
|
|
423
283
|
.optional()
|
|
424
284
|
.describe('The tab disconnected mid-wait, so this was never observed — the verdict is UNKNOWN, not a failure of the app.'),
|
|
285
|
+
inconclusive: z
|
|
286
|
+
.string()
|
|
287
|
+
.optional()
|
|
288
|
+
.describe('The wait could not be graded as a product failure — e.g. the tab is throttled and may never have rendered. The verdict is UNKNOWN, not "the UI is absent".'),
|
|
425
289
|
// The STRUCTURED cause — observed / expected / assertion — is what the repair literature ranks
|
|
426
290
|
// above the prose failureReason (structured feedback beat narrative by 10.5pp) and above a bare
|
|
427
291
|
// pointer. `verdict` is `await waitForPredicate(...)`, whose EvalResult carries these on a
|
|
@@ -482,7 +346,10 @@ export const ACT_TOOLS = [
|
|
|
482
346
|
...pausedOutputShape,
|
|
483
347
|
},
|
|
484
348
|
handler: async (deps, args) => {
|
|
485
|
-
|
|
349
|
+
// Spend the caller's budget waiting for the APP too, not only for the consequence. This tool
|
|
350
|
+
// is the one an agent reaches for straight after `init` and a dev-server restart, which is
|
|
351
|
+
// exactly when there is no session yet and one is seconds away. See resolve-within.
|
|
352
|
+
let session = await resolveSessionWithin(deps.sessions, asString(args['sessionId']), asNumber(args['timeout_ms']) ?? DEFAULT_ASSERT_TIMEOUT_MS, WALL_CLOCK);
|
|
486
353
|
const acted = session;
|
|
487
354
|
const actedSessionId = session.id;
|
|
488
355
|
// Live-control: refuse to drive the page (no act, no predicate eval) while paused.
|
|
@@ -507,9 +374,8 @@ export const ACT_TOOLS = [
|
|
|
507
374
|
// the undeclared-change gap silent on THIS verdict rather than the next one: it reads the
|
|
508
375
|
// ledger below and finds something open. The discharge comes after that read.
|
|
509
376
|
const intentId = await linkInlineIntent(deps, asString(args['sessionId']), asString(args['intent']), PredicateKind.SETTLED === until.kind ? undefined : until);
|
|
510
|
-
//
|
|
511
|
-
|
|
512
|
-
assertNativeInputSupported(asRecord(args['args']));
|
|
377
|
+
// Everything refusable without touching the page — see act-preflight.ts.
|
|
378
|
+
preflightAct(asRecord(args['args']), until);
|
|
513
379
|
// Resolve `target` to a ref BEFORE the action window opens, so the lookup is not attributed to
|
|
514
380
|
// the act and cannot be mistaken for something the action caused.
|
|
515
381
|
const resolved = await resolveActTarget(session, args);
|
|
@@ -535,41 +401,47 @@ export const ACT_TOOLS = [
|
|
|
535
401
|
: false;
|
|
536
402
|
try {
|
|
537
403
|
// actCommand is the single interception point for upload+path rewrite.
|
|
538
|
-
|
|
404
|
+
//
|
|
405
|
+
// A replacement can land BETWEEN resolving the target and dispatching, and the tool used to
|
|
406
|
+
// throw that transport fact at the agent verbatim: no verdict at all, from the layer whose
|
|
407
|
+
// whole job is to answer in verdicts, worded as though the app were at fault. `dispatchAct`
|
|
408
|
+
// returns null instead (see act-preflight.ts for why a write is never re-sent), and the
|
|
409
|
+
// successor block below then asks whether the consequence held on the NEW document — a
|
|
410
|
+
// green if it did, an honest observation_lost if it did not.
|
|
411
|
+
const actResult = await dispatchAct(() => actCommand(deps, session, {
|
|
539
412
|
ref: resolved.ref,
|
|
540
413
|
action: args['action'],
|
|
541
414
|
args: args['args'] ?? {},
|
|
542
|
-
});
|
|
543
|
-
if (
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
415
|
+
}));
|
|
416
|
+
if (actResult !== null) {
|
|
417
|
+
if (!actResult.ok)
|
|
418
|
+
throw new Error(actResult.error ?? 'act failed');
|
|
419
|
+
captureAct(deps.recordings, args, actResult.result);
|
|
420
|
+
// Dispatched — now this act owns the cursor and the effect. Marking its OWN measurement
|
|
421
|
+
// also stops the spread below from inheriting an earlier reticle_act's action and
|
|
422
|
+
// mutation count.
|
|
423
|
+
session.lastAct.markActed(since, asString(args['action']), mutatedWithin(asRecord(actResult.result)), asString(args['ref']));
|
|
424
|
+
}
|
|
549
425
|
// Honesty: floor the predicate at this act's cursor so a stale buffered event can't satisfy it.
|
|
550
426
|
const predicateStarted = session.elapsed();
|
|
551
|
-
let verdict =
|
|
552
|
-
?
|
|
553
|
-
:
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
//
|
|
557
|
-
|
|
558
|
-
|
|
559
|
-
|
|
560
|
-
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
verdict = await waitForPredicate(session, until, leftover, since);
|
|
570
|
-
}
|
|
571
|
-
}
|
|
572
|
-
}
|
|
427
|
+
let verdict = null === actResult
|
|
428
|
+
? { pass: false, observationLost: true }
|
|
429
|
+
: timeout > 0
|
|
430
|
+
? await waitForPredicate(session, until, timeout, since)
|
|
431
|
+
: await evaluatePredicate(session, until, since);
|
|
432
|
+
// The SDK may have gone away mid-act — see act-observation.ts.
|
|
433
|
+
const followed = await followLostObservation({
|
|
434
|
+
sessions: deps.sessions,
|
|
435
|
+
session,
|
|
436
|
+
verdict,
|
|
437
|
+
timeout,
|
|
438
|
+
predicateStarted,
|
|
439
|
+
reevaluate: (next, budget) => waitForPredicate(next, until, budget, 0),
|
|
440
|
+
});
|
|
441
|
+
if (followed.followed)
|
|
442
|
+
since = 0;
|
|
443
|
+
session = followed.session;
|
|
444
|
+
verdict = followed.verdict;
|
|
573
445
|
// The predicate resolves the INSTANT it holds, which on an optimistically-navigating app is
|
|
574
446
|
// while the write is still in flight — so the verdict was taken over a window the app had not
|
|
575
447
|
// finished, and came back `unknown / unsettled` asking the CALLER to re-check. A login that
|
|
@@ -599,7 +471,7 @@ export const ACT_TOOLS = [
|
|
|
599
471
|
// moved after it — and short enough that a genuinely dropped response is still reported.
|
|
600
472
|
await waitForReaction(session, since, spent(), sleep);
|
|
601
473
|
}
|
|
602
|
-
const r = asRecord(actResult
|
|
474
|
+
const r = asRecord(actResult?.result);
|
|
603
475
|
if ('boolean' === typeof r['settled'])
|
|
604
476
|
settledOutcome = r['settled'];
|
|
605
477
|
// Where the acted element is written. Captured at act time alongside the anchor, so it is
|
|
@@ -626,8 +498,9 @@ export const ACT_TOOLS = [
|
|
|
626
498
|
// stronger than this block. Grade from the strongest asserted consequence; integrity from evictions.
|
|
627
499
|
// Coverage: cross-origin frames / other blind spots the SDK reported during this window mean the
|
|
628
500
|
// verdict didn't see everything — say so, never imply full coverage.
|
|
629
|
-
const spots = blindSpotsFromState(session.blindSpots());
|
|
501
|
+
const spots = blindSpotsFromState(session.blindSpots(), session.runtime);
|
|
630
502
|
const coverage = buildCoverageStatement(spots);
|
|
503
|
+
const absenceBlindSpot = absenceBlindSpotNote(until, spots);
|
|
631
504
|
// Nothing subscribed ⇒ the state channel is dark, and the summary must say so rather than
|
|
632
505
|
// report an empty diff list that reads like a fact about the app. See CausalSummary.
|
|
633
506
|
const stateUnwatched = isStateUnwatched(spots);
|
|
@@ -665,6 +538,7 @@ export const ACT_TOOLS = [
|
|
|
665
538
|
// evictions that happened outside the window they impeached.
|
|
666
539
|
truncated: bufferLost,
|
|
667
540
|
coveragePartial: Coverage.PARTIAL === coverage.coverage,
|
|
541
|
+
...(coverage.note === undefined ? {} : { coverageNote: coverage.note }),
|
|
668
542
|
// Settlement no longer vetoes a declared consequence that held, so the fact is carried
|
|
669
543
|
// here instead of only in the verdict it used to decide. Omitted when never measured.
|
|
670
544
|
...(settledOutcome === undefined ? {} : { settled: settledOutcome }),
|
|
@@ -677,7 +551,11 @@ export const ACT_TOOLS = [
|
|
|
677
551
|
capsule,
|
|
678
552
|
links,
|
|
679
553
|
args,
|
|
680
|
-
|
|
554
|
+
// The session actually driven — after any navigation follow — so the capsule is filed
|
|
555
|
+
// against the codebase that produced the failure, not wherever the daemon stands.
|
|
556
|
+
root: session.artifactRoot,
|
|
557
|
+
// No dispatch result to capture when the transport was displaced mid-write.
|
|
558
|
+
actResult: actResult ?? {},
|
|
681
559
|
...(actedSource === undefined ? {} : { actedSource }),
|
|
682
560
|
});
|
|
683
561
|
// Pass the action: an EMPTY window then reads as "the target does not react" rather than as a
|
|
@@ -710,6 +588,7 @@ export const ACT_TOOLS = [
|
|
|
710
588
|
...session.lastAct.effect(),
|
|
711
589
|
currentDocumentId: session.currentDocumentId,
|
|
712
590
|
currentEditEpoch: session.currentEditEpoch,
|
|
591
|
+
appOrigin: session.url,
|
|
713
592
|
});
|
|
714
593
|
// The single field an agent reads. Everything below it is the evidence it was derived from;
|
|
715
594
|
// this is the only one that has to be interpreted, and now it interprets itself.
|
|
@@ -732,6 +611,7 @@ export const ACT_TOOLS = [
|
|
|
732
611
|
// the measured false red: a reload mid-wait, graded assertion_failed at the clicked
|
|
733
612
|
// component's own file and line.
|
|
734
613
|
...(true === verdict.observationLost ? { observationLost: true } : {}),
|
|
614
|
+
...(absenceBlindSpot === undefined ? {} : { absenceBlindSpot }),
|
|
735
615
|
honesty,
|
|
736
616
|
contradictions,
|
|
737
617
|
...(outcomePending ? { outcomePending } : {}),
|
|
@@ -778,7 +658,7 @@ export const ACT_TOOLS = [
|
|
|
778
658
|
// "1 declared intent(s) are still unproved" while the ledger recorded it `proved`. A gap
|
|
779
659
|
// that fires on the one path doing everything right is noise, and noise is what gets
|
|
780
660
|
// filtered out — taking the honest gaps with it.
|
|
781
|
-
|
|
661
|
+
...intentDebt(openIntents, intentId !== undefined && Verified.YES === decision.verified ? intentId : undefined, deps.now()),
|
|
782
662
|
domMutated: (session.lastAct.effect().mutatedWithin ?? 0) > 0,
|
|
783
663
|
signalsFired: actionSummary.signals.length,
|
|
784
664
|
routeChanged: actionSummary.route !== undefined,
|
|
@@ -794,7 +674,10 @@ export const ACT_TOOLS = [
|
|
|
794
674
|
verdictId: inlineVerdictId(ReticleTool.ACT_AND_WAIT, deps.now()),
|
|
795
675
|
grade,
|
|
796
676
|
at: deps.now(),
|
|
797
|
-
}
|
|
677
|
+
},
|
|
678
|
+
// Where the acted element is written, so the record can name a file somebody would open
|
|
679
|
+
// to change the thing it describes.
|
|
680
|
+
actedSourceLabel);
|
|
798
681
|
}
|
|
799
682
|
verdictEffect = {
|
|
800
683
|
claim: describeWaitTarget(until),
|
|
@@ -807,7 +690,9 @@ export const ACT_TOOLS = [
|
|
|
807
690
|
noteSessionGaps(session, gaps);
|
|
808
691
|
return withControl(session, {
|
|
809
692
|
...decision,
|
|
810
|
-
effect
|
|
693
|
+
// An unobserved act has no effect to report, and inventing an empty one would read as
|
|
694
|
+
// "the page did nothing" — a claim about the app, from a call that never saw it.
|
|
695
|
+
...(null === actResult ? {} : { effect: leanActResult(actResult.result) }),
|
|
811
696
|
verdict,
|
|
812
697
|
// Promoted out of `effect` on red only. On green nobody needs it and it is noise; on red it
|
|
813
698
|
// is the first thing the agent wants, and burying a file:line inside the effect block is
|
|
@@ -831,7 +716,7 @@ export const ACT_TOOLS = [
|
|
|
831
716
|
// agent cannot miss it by not asking. Omitted entirely when clean, so a healthy action
|
|
832
717
|
// pays nothing.
|
|
833
718
|
...(contradictions.length > 0 ? { contradictions } : {}),
|
|
834
|
-
honesty,
|
|
719
|
+
honesty: honestyForVerdict(String(decision.verified), honesty),
|
|
835
720
|
...(capsule === undefined ? {} : { capsule }),
|
|
836
721
|
since,
|
|
837
722
|
...(session.id === actedSessionId ? {} : { sessionId: session.id }),
|
|
@@ -843,4 +728,6 @@ export const ACT_TOOLS = [
|
|
|
843
728
|
}
|
|
844
729
|
},
|
|
845
730
|
},
|
|
731
|
+
// Split into its own module for size; still shipped as one of the acting tools.
|
|
732
|
+
ACT_SEQUENCE_TOOL,
|
|
846
733
|
];
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { CaptureLoss, PredicateKind } from '@reticlehq/core';
|
|
2
2
|
import { gapsForAction } from '../honesty/instrumentation-gaps.js';
|
|
3
3
|
import { noteSessionGaps } from '../honesty/gap-ledger.js';
|
|
4
4
|
import { declaresState } from '../events/predicate-asks.js';
|
|
5
5
|
import { isStateUnwatched } from '../honesty/blind-spots.js';
|
|
6
6
|
import { findContradictions } from '../events/contradictions.js';
|
|
7
7
|
import { declaredExpectations, declaresBodyIndependentChannel } from '../events/declared.js';
|
|
8
|
-
import { blindSpotsFromState, buildCoverageStatement, Coverage, impeachesCapture, transportGapNote, } from '../honesty/blind-spots.js';
|
|
8
|
+
import { absenceBlindSpotNote, blindSpotsFromState, buildCoverageStatement, restsOnCompleteWindow, Coverage, impeachesCapture, transportGapNote, } from '../honesty/blind-spots.js';
|
|
9
9
|
import { buildHonestyBlock } from '../honesty/honesty.js';
|
|
10
10
|
import { hasAcceptedWrite } from '../honesty/accepted-write.js';
|
|
11
11
|
import { unreadWriteLabels } from '../honesty/unread-outcome.js';
|
|
@@ -14,17 +14,6 @@ import { describeWaitTarget } from '../honesty/unsettled.js';
|
|
|
14
14
|
import { inFlightRequestLabels, repeatedRequestLabels } from './settle-in-flight.js';
|
|
15
15
|
import { gradeOfPredicate } from './assert-grade.js';
|
|
16
16
|
import { assertSource } from './assert-source.js';
|
|
17
|
-
function absenceBlindSpotNote(predicate, spots) {
|
|
18
|
-
if (predicate.kind !== 'element' || predicate.absent !== true)
|
|
19
|
-
return undefined;
|
|
20
|
-
const relevant = spots.filter((spot) => spot.count > 0 &&
|
|
21
|
-
spot.kind === BlindSpotKind.CROSS_ORIGIN_IFRAME &&
|
|
22
|
-
undefined !== predicate.query.scope);
|
|
23
|
-
if (0 === relevant.length)
|
|
24
|
-
return undefined;
|
|
25
|
-
const statement = buildCoverageStatement(relevant);
|
|
26
|
-
return `the absence assertion targeted a region Reticle could not observe (${statement.note ?? 'partial coverage'}), so a passing DOM check cannot prove absence`;
|
|
27
|
-
}
|
|
28
17
|
/**
|
|
29
18
|
* The honesty verdict for a plain `reticle_assert`.
|
|
30
19
|
*
|
|
@@ -63,7 +52,7 @@ changeUndeclared) {
|
|
|
63
52
|
// in that session partial — including ones about a region it cannot affect. That errs toward
|
|
64
53
|
// over-warning, which is the correct direction here: the failure this guards against is a green
|
|
65
54
|
// that implies coverage it never had, and a needless caveat costs the agent a sentence.
|
|
66
|
-
const spots = blindSpotsFromState(session.blindSpots());
|
|
55
|
+
const spots = blindSpotsFromState(session.blindSpots(), session.runtime);
|
|
67
56
|
const statement = buildCoverageStatement(spots);
|
|
68
57
|
const absenceBlindSpot = absenceBlindSpotNote(predicate, spots);
|
|
69
58
|
// Omitted entirely when coverage is full, so an intact page pays nothing and the field's PRESENCE
|
|
@@ -94,6 +83,7 @@ changeUndeclared) {
|
|
|
94
83
|
prior,
|
|
95
84
|
currentDocumentId: session.currentDocumentId,
|
|
96
85
|
currentEditEpoch: session.currentEditEpoch,
|
|
86
|
+
appOrigin: session.url,
|
|
97
87
|
expectedFailures: declared.netFailures,
|
|
98
88
|
renderProved: pass && declared.rendersContent,
|
|
99
89
|
...(actCursor !== undefined && actCursor >= since ? { actionSince: actCursor } : {}),
|
|
@@ -121,11 +111,27 @@ changeUndeclared) {
|
|
|
121
111
|
honesty: buildHonestyBlock({
|
|
122
112
|
grade: gradeOfPredicate(predicate),
|
|
123
113
|
attribution: 'window',
|
|
114
|
+
// Did the buffer evict SCARCE evidence belonging to this window, AND does a green here rest on
|
|
115
|
+
// the window being complete. assert never consulted the buffer at all, on the reasoning that it
|
|
116
|
+
// "observes an already-open window" — but eviction happens on push regardless of who opened the
|
|
117
|
+
// window, so `{ console, absent: true }` returned `yes` over a window whose evidence was gone,
|
|
118
|
+
// which is absence of evidence read as evidence of absence.
|
|
119
|
+
//
|
|
120
|
+
// The second half of the condition is not a refinement, it is what keeps this usable. Scarce
|
|
121
|
+
// loss is recorded for AGE eviction too, so `lostSince(0)` is true on any session past the 60s
|
|
122
|
+
// cutoff, and assert takes a caller-chosen `since` that is often 0. Impeaching every verdict
|
|
123
|
+
// over a wide window would make `unknown` the answer to everything — the failure this repo has
|
|
124
|
+
// already paid for once, when `unclean_capture` became the dominant cause of `unknown` in the
|
|
125
|
+
// field. The act path needs no such guard: its cursor is the action's own.
|
|
126
|
+
truncated: session.lostSince(since) && restsOnCompleteWindow(predicate),
|
|
124
127
|
coveragePartial: Coverage.PARTIAL === statement.coverage,
|
|
128
|
+
...(statement.note === undefined ? {} : { coverageNote: statement.note }),
|
|
125
129
|
...(0 === impeachingNotes.length ? {} : { blindSpots: impeachingNotes }),
|
|
126
|
-
// Which loss, as an enum, beside the prose.
|
|
127
|
-
// consults the ring buffer's health, so `buffer_loss` is not one of its answers.
|
|
130
|
+
// Which loss, as an enum, beside the prose.
|
|
128
131
|
losses: [
|
|
132
|
+
...(session.lostSince(since) && restsOnCompleteWindow(predicate)
|
|
133
|
+
? [CaptureLoss.BUFFER_LOSS]
|
|
134
|
+
: []),
|
|
129
135
|
...(gap === undefined ? [] : [CaptureLoss.TRANSPORT_GAP]),
|
|
130
136
|
...(impeaching.note === undefined ? [] : [CaptureLoss.BLIND_SPOT]),
|
|
131
137
|
],
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { carryReticleIdentity } from './lease-tools.js';
|
|
1
2
|
import { z } from 'zod';
|
|
2
3
|
import { navigateResult } from './navigate-result.js';
|
|
3
4
|
import { awaitArrival } from './navigate-arrival.js';
|
|
@@ -64,12 +65,15 @@ export const BROWSER_TOOLS = [
|
|
|
64
65
|
// likely to need it. See reload-result.
|
|
65
66
|
return reloadResult(back);
|
|
66
67
|
}
|
|
67
|
-
const
|
|
68
|
-
if (
|
|
68
|
+
const requested = asString(args['url']);
|
|
69
|
+
if (requested === undefined || 0 === requested.length)
|
|
69
70
|
return { ok: false, reason: 'url required' };
|
|
70
71
|
// Record navigate as an action. Its window is usually empty (the page unloads and the SDK
|
|
71
72
|
// reconnects), but the action record itself — "navigated to X" — is the causal fact worth keeping.
|
|
72
73
|
const session = deps.sessions.resolve(asString(args['sessionId']));
|
|
74
|
+
// A leased tab is addressed by a URL param, so navigating away from it used to strand the
|
|
75
|
+
// lease — see carryReticleIdentity. A tab that claims no identity is untouched.
|
|
76
|
+
const url = carryReticleIdentity(session.url, requested);
|
|
73
77
|
session.beginAction(ReticleTool.NAVIGATE, { url });
|
|
74
78
|
// Same floor as the reload path above, for the same reason: going to a new URL replaces the
|
|
75
79
|
// document just as thoroughly. `beginAction` attributes events to this action; it does not move
|