@reticlehq/server 2.11.0 → 2.13.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 +93 -111
- 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 -14
- package/dist/bridge/bridge.js +248 -165
- package/dist/bridge/bridge.test-harness.d.ts +2 -0
- package/dist/bridge/bridge.test-harness.js +8 -1
- 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 +8 -7
- package/dist/capsule/capsule-store.js +1 -1
- package/dist/capsule/causal-summary.d.ts +2 -2
- package/dist/capsule/causal-summary.js +7 -2
- package/dist/chromium-launch-options.d.ts +28 -0
- package/dist/chromium-launch-options.js +29 -0
- package/dist/cli/cli-doctor.js +39 -1
- package/dist/cli/cli-flow-commands.d.ts +3 -1
- package/dist/cli/cli-flow-commands.js +34 -4
- package/dist/cli/cli-kill.d.ts +2 -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 +17 -1
- package/dist/cli/cli-parse.js +238 -12
- package/dist/cli/cli-update-commands.js +20 -1
- package/dist/cli/cli-verify.d.ts +2 -1
- package/dist/cli/cli-verify.js +5 -4
- package/dist/cli/cloud-cli.js +428 -253
- 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.d.ts +2 -1
- 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 +12 -1
- package/dist/cli/doctor-rows.js +12 -1
- 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/gate-exit.d.ts +21 -0
- package/dist/cli/gate-exit.js +21 -0
- package/dist/cli/gate-hook-message.d.ts +33 -0
- package/dist/cli/gate-hook-message.js +46 -0
- package/dist/cli/mcp-command.d.ts +25 -0
- package/dist/cli/mcp-command.js +174 -0
- package/dist/cli/project-name.d.ts +30 -0
- package/dist/cli/project-name.js +44 -0
- package/dist/cli/sibling-ports.d.ts +37 -0
- package/dist/cli/sibling-ports.js +56 -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 +167 -186
- package/dist/cloud/cloud-config.d.ts +24 -2
- package/dist/cloud/cloud-config.js +64 -5
- package/dist/cloud/cloud-sync.d.ts +16 -5
- package/dist/cloud/cloud-sync.js +64 -1
- 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 +12 -13
- package/dist/crawl/crawl.js +25 -3
- package/dist/daemon/daemon-resolve.d.ts +122 -0
- package/dist/daemon/daemon-resolve.js +187 -0
- package/dist/daemon/dev-servers.d.ts +15 -0
- package/dist/daemon/dev-servers.js +68 -0
- package/dist/daemon/free-port.d.ts +29 -0
- package/dist/daemon/free-port.js +55 -0
- package/dist/daemon/heartbeat.d.ts +0 -4
- package/dist/daemon/heartbeat.js +2 -2
- package/dist/daemon/wake-decision.d.ts +32 -0
- package/dist/daemon/wake-decision.js +38 -0
- package/dist/dev/stale-issue-guard.d.ts +0 -2
- package/dist/dev/stale-issue-guard.js +1 -1
- package/dist/domain/domain-tools.js +2 -2
- package/dist/events/contradictions.d.ts +59 -0
- package/dist/events/contradictions.js +253 -27
- package/dist/events/declared.d.ts +17 -0
- package/dist/events/declared.js +43 -1
- package/dist/events/echo-mismatch.js +65 -1
- package/dist/events/event-filters.d.ts +8 -0
- package/dist/events/event-filters.js +19 -2
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +17 -0
- package/dist/events/predicate-asks.d.ts +13 -0
- package/dist/events/predicate-asks.js +22 -0
- package/dist/events/predicate-eval.js +117 -27
- package/dist/events/predicate-parse.d.ts +0 -6
- package/dist/events/predicate-parse.js +43 -3
- 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-schema.d.ts +44 -0
- package/dist/events/predicate-schema.js +126 -23
- package/dist/events/predicate.d.ts +20 -0
- package/dist/events/predicate.js +77 -6
- package/dist/events/split-text-miss.d.ts +30 -0
- package/dist/events/split-text-miss.js +44 -0
- package/dist/flows/coverage.d.ts +0 -8
- package/dist/flows/coverage.js +1 -1
- package/dist/flows/decision.d.ts +5 -1
- package/dist/flows/decision.js +33 -7
- package/dist/flows/flake.d.ts +6 -8
- package/dist/flows/flake.js +1 -1
- package/dist/flows/flow-intent.d.ts +52 -0
- package/dist/flows/flow-intent.js +123 -0
- 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 +263 -23
- 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-success.js +15 -3
- package/dist/flows/flow-tools.js +87 -33
- package/dist/flows/flows.d.ts +14 -1
- package/dist/flows/flows.js +502 -24
- 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 +36 -15
- 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/server-verify.js +16 -2
- package/dist/flows/verify-change-tools.js +9 -3
- package/dist/honesty/blind-spots.d.ts +51 -15
- package/dist/honesty/blind-spots.js +64 -4
- package/dist/honesty/feature-capture.d.ts +150 -0
- package/dist/honesty/feature-capture.js +233 -0
- package/dist/honesty/honesty.d.ts +24 -0
- package/dist/honesty/honesty.js +25 -1
- package/dist/honesty/instrumentation-gaps.d.ts +39 -6
- package/dist/honesty/instrumentation-gaps.js +88 -5
- package/dist/honesty/tool-hit-rate.d.ts +86 -0
- package/dist/honesty/tool-hit-rate.js +90 -0
- package/dist/honesty/undeclared-change.d.ts +51 -0
- package/dist/honesty/undeclared-change.js +56 -0
- package/dist/honesty/verified.d.ts +16 -0
- package/dist/honesty/verified.js +84 -5
- package/dist/http-server.d.ts +0 -1
- package/dist/http-server.js +13 -1
- package/dist/hunt/hunt-report.d.ts +0 -2
- package/dist/hunt/hunt-report.js +1 -1
- package/dist/impact/impact-recorder.d.ts +31 -8
- package/dist/impact/impact-recorder.js +104 -21
- package/dist/impact/impact-store.d.ts +13 -4
- package/dist/impact/impact-store.js +44 -3
- package/dist/index.d.ts +4 -1
- package/dist/index.js +113 -7
- package/dist/init/agent-rules.d.ts +30 -6
- package/dist/init/agent-rules.js +54 -13
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +28 -0
- package/dist/init/capabilities.d.ts +4 -3
- package/dist/init/capabilities.js +23 -3
- package/dist/init/closing-hint.d.ts +36 -0
- package/dist/init/closing-hint.js +120 -0
- package/dist/init/confirm.d.ts +27 -28
- package/dist/init/confirm.js +51 -11
- package/dist/init/cra.d.ts +34 -5
- package/dist/init/cra.js +96 -25
- 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 +50 -0
- package/dist/init/dev-script.js +66 -0
- 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 +17 -6
- package/dist/init/mcp.js +27 -11
- package/dist/init/node-io.js +11 -1
- package/dist/init/plan-framework.d.ts +0 -5
- package/dist/init/plan-framework.js +147 -37
- package/dist/init/plan.d.ts +30 -37
- package/dist/init/plan.js +50 -60
- package/dist/init/preflight.d.ts +28 -0
- package/dist/init/preflight.js +38 -0
- package/dist/init/refresh-rules.d.ts +39 -0
- package/dist/init/refresh-rules.js +51 -0
- package/dist/init/run.d.ts +32 -35
- package/dist/init/run.js +151 -202
- package/dist/init/slash-command.d.ts +1 -1
- package/dist/init/snippets.js +90 -31
- 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.d.ts +2 -0
- package/dist/input/real-input.js +28 -7
- package/dist/input/scroll-find.d.ts +7 -4
- package/dist/input/scroll-find.js +63 -25
- package/dist/input/scroll-tools.js +4 -6
- package/dist/input/viewport-tools.js +5 -4
- package/dist/intent/inline-intent.d.ts +37 -0
- package/dist/intent/inline-intent.js +193 -0
- 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 +49 -0
- package/dist/intent/intent-store.js +133 -0
- package/dist/intent/intent-subject.d.ts +45 -0
- package/dist/intent/intent-subject.js +177 -0
- package/dist/intent/intent-tools.d.ts +2 -0
- package/dist/intent/intent-tools.js +143 -0
- package/dist/intent/open-intents.d.ts +42 -0
- package/dist/intent/open-intents.js +40 -0
- package/dist/journal/envelope.d.ts +26 -26
- package/dist/journal/journal-recorder.d.ts +23 -0
- package/dist/journal/journal-recorder.js +35 -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 +83 -0
- package/dist/mcp/attach-memory.js +185 -0
- 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 -8
- package/dist/mcp/mcp-proxy.js +64 -62
- package/dist/mcp/mcp.d.ts +2 -0
- package/dist/mcp/mcp.js +52 -24
- 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/server-instructions.js +45 -3
- package/dist/mcp/tool-catalog-cache.d.ts +16 -0
- package/dist/mcp/tool-catalog-cache.js +22 -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/flow-instrument-gaps.d.ts +4 -4
- package/dist/oracles/flow-instrument-gaps.js +4 -5
- package/dist/oracles/propose-consequences.js +12 -3
- package/dist/oracles/self-instrument.d.ts +9 -9
- package/dist/oracles/self-instrument.js +19 -13
- package/dist/pool/browser-pool.d.ts +75 -5
- package/dist/pool/browser-pool.js +144 -5
- package/dist/pool/playwright-launcher.js +12 -1
- package/dist/project/fs-port.d.ts +3 -0
- package/dist/project/fs-port.js +3 -2
- package/dist/project/memory-fs.js +6 -1
- package/dist/project/project-tools.js +6 -35
- package/dist/project/reticle-dir.d.ts +17 -2
- package/dist/project/reticle-dir.js +22 -4
- package/dist/runs/context-tools.d.ts +2 -0
- package/dist/runs/context-tools.js +89 -0
- package/dist/runs/run-context.d.ts +40 -0
- package/dist/runs/run-context.js +158 -0
- package/dist/runs/run-diff.d.ts +2 -1
- 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 +24 -3
- 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/dev-server-probe.d.ts +0 -8
- package/dist/session/dev-server-probe.js +1 -1
- package/dist/session/last-act.d.ts +7 -1
- package/dist/session/last-act.js +2 -2
- package/dist/session/lease-visibility.d.ts +67 -0
- package/dist/session/lease-visibility.js +76 -0
- package/dist/session/live-control-tools.js +1 -42
- package/dist/session/no-session-diagnosis.d.ts +33 -0
- package/dist/session/no-session-diagnosis.js +82 -24
- package/dist/session/no-session-next-action.d.ts +12 -0
- package/dist/session/no-session-next-action.js +77 -6
- package/dist/session/no-session-watch.d.ts +18 -6
- package/dist/session/no-session-watch.js +125 -75
- package/dist/session/output-budget.js +4 -1
- 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-health.d.ts +9 -0
- package/dist/session/session-health.js +23 -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 +111 -4
- 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.d.ts +37 -0
- package/dist/session/session-successor.js +113 -0
- package/dist/session/session-tools.js +2 -2
- package/dist/session/session.d.ts +53 -3
- package/dist/session/session.js +162 -9
- 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 +60 -0
- package/dist/setup/dev-server-wait.js +65 -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 +187 -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/automation-hint.d.ts +2 -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-outbox.d.ts +2 -1
- 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 -9
- package/dist/telemetry/project-profile.js +12 -7
- package/dist/telemetry/proxy-telemetry.d.ts +3 -0
- package/dist/telemetry/proxy-telemetry.js +21 -0
- package/dist/telemetry/run-telemetry.d.ts +0 -2
- package/dist/telemetry/run-telemetry.js +1 -1
- 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/telemetry/verification-of.js +2 -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 +196 -204
- package/dist/tools/assert-source.d.ts +22 -0
- package/dist/tools/assert-source.js +53 -0
- package/dist/tools/assert-verdict.d.ts +20 -3
- package/dist/tools/assert-verdict.js +58 -20
- package/dist/tools/browser-tools.js +6 -22
- package/dist/tools/complete-snapshot.d.ts +48 -0
- package/dist/tools/complete-snapshot.js +75 -0
- package/dist/tools/coverage-tools.d.ts +10 -1
- package/dist/tools/coverage-tools.js +123 -69
- package/dist/tools/dynamic-tools.js +53 -13
- package/dist/tools/error-recovery.d.ts +25 -14
- package/dist/tools/error-recovery.js +78 -9
- package/dist/tools/feedback-tools.d.ts +1 -1
- package/dist/tools/feedback-tools.js +2 -2
- package/dist/tools/invoke-tool.js +121 -11
- package/dist/tools/lease-hint.d.ts +10 -0
- package/dist/tools/lease-hint.js +53 -4
- package/dist/tools/lease-tools.d.ts +35 -5
- package/dist/tools/lease-tools.js +191 -13
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +22 -0
- package/dist/tools/navigate-arrival.d.ts +0 -2
- package/dist/tools/navigate-arrival.js +1 -1
- package/dist/tools/numeric-bounds.d.ts +100 -0
- package/dist/tools/numeric-bounds.js +125 -0
- package/dist/tools/observe-tools.js +109 -65
- package/dist/tools/read-tools.js +31 -8
- package/dist/tools/real-input-attempt.d.ts +32 -0
- package/dist/tools/real-input-attempt.js +212 -2
- package/dist/tools/reconcile-tools.js +22 -8
- package/dist/tools/resolve-target.d.ts +0 -7
- package/dist/tools/sdk-marker-probe.d.ts +29 -0
- package/dist/tools/sdk-marker-probe.js +57 -0
- package/dist/tools/snapshot-delta.d.ts +1 -1
- package/dist/tools/tool-kit.d.ts +24 -0
- package/dist/tools/tool-kit.js +21 -0
- package/dist/tools/tool-names.d.ts +5 -0
- package/dist/tools/tool-names.js +5 -0
- package/dist/tools/tool-surface.d.ts +85 -6
- package/dist/tools/tool-surface.js +122 -2
- 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 +78 -12
- package/dist/tools/unadvertised-help.js +4 -4
- package/dist/tools/verify-next-baton.d.ts +53 -0
- package/dist/tools/verify-next-baton.js +52 -0
- 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 +25 -10
- package/dist/update/update-nudge.js +32 -3
- package/dist/update/updater.d.ts +1 -1
- 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/README.md +2 -1
- package/docs/cli/cloud.mdx +1 -1
- package/docs/cli/doctor.mdx +2 -0
- package/docs/cli/serve.mdx +4 -2
- package/docs/cli/verify.mdx +4 -5
- package/docs/cli.mdx +7 -3
- package/docs/desktop.mdx +1 -1
- package/docs/docs.json +2 -2
- package/docs/gates.md +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/browser.mdx +2 -2
- package/docs/packages/server.mdx +1 -1
- package/docs/packages.mdx +8 -6
- package/docs/platform-integration.md +17 -0
- package/docs/predicates.mdx +8 -0
- package/docs/reticle-manual.md +106 -0
- package/docs/skill-file.mdx +3 -3
- package/docs/telemetry-contract.md +108 -4
- package/docs/tools-act-sequence.mdx +16 -0
- package/docs/tools-tools-and-run.mdx +2 -4
- package/docs/troubleshooting.mdx +9 -0
- package/docs/usage.md +4 -3
- package/package.json +4 -3
- package/dist/init/cursor.d.ts +0 -24
- package/dist/init/cursor.js +0 -80
- package/dist/session/session-readiness.d.ts +0 -34
- package/dist/session/session-readiness.js +0 -36
|
@@ -1,13 +1,17 @@
|
|
|
1
|
-
import { type ImpactCounts, type ImpactScope, type ImpactSnapshot } from '@reticlehq/core';
|
|
1
|
+
import { type ImpactCounts, type ImpactDefect, type ImpactScope, type ImpactSnapshot } from '@reticlehq/core';
|
|
2
2
|
export interface ImpactPaths {
|
|
3
3
|
project: string;
|
|
4
4
|
global: string;
|
|
5
5
|
}
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
8
|
-
*
|
|
7
|
+
* Where this project's dashboard lives, if `reticle link` recorded one.
|
|
8
|
+
*
|
|
9
|
+
* Read from the link file rather than derived from the API url, because the API origin and the
|
|
10
|
+
* console origin are different hosts in every deployment that is not a laptop. Synchronous and
|
|
11
|
+
* best-effort, like every other read in this file: a missing or malformed link file means no link
|
|
12
|
+
* in the HUD, never a failed tool call.
|
|
9
13
|
*/
|
|
10
|
-
export declare function
|
|
14
|
+
export declare function readDashboardUrl(reticleRoot: string): string | undefined;
|
|
11
15
|
/** Read a scope, tolerating absence and corruption: a broken file starts over rather than throwing. */
|
|
12
16
|
export declare function readScope(path: string, now: number): ImpactScope;
|
|
13
17
|
/** YYYY-MM-DD in local time - the day boundary a person recognises, not UTC's. */
|
|
@@ -22,6 +26,11 @@ export declare function isoDay(now: number): string;
|
|
|
22
26
|
*/
|
|
23
27
|
export interface ImpactFoldMeta {
|
|
24
28
|
runMs?: number;
|
|
29
|
+
/**
|
|
30
|
+
* The defect this call caught, when it caught one. Carried beside the counters rather than in
|
|
31
|
+
* them because it is not a tally: `counts.failed` says how many, this says which.
|
|
32
|
+
*/
|
|
33
|
+
defect?: ImpactDefect;
|
|
25
34
|
}
|
|
26
35
|
/** Fold one delta into a scope: totals, today's bucket, records and streak. Pure. */
|
|
27
36
|
export declare function applyDelta(scope: ImpactScope, delta: Partial<ImpactCounts>, now: number, meta?: ImpactFoldMeta): ImpactScope;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
|
|
2
2
|
import { dirname, join } from 'node:path';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
-
import { ReticleDir, IMPACT_DAILY_BUCKETS, IMPACT_SCHEMA_VERSION, ImpactScopeSchema, addImpactCounts, emptyImpactCounts, emptyImpactRecords, estimateImpactSavings, } from '@reticlehq/core';
|
|
4
|
+
import { ReticleDir, IMPACT_DAILY_BUCKETS, IMPACT_DEFECT_LIMIT, IMPACT_SCHEMA_VERSION, ImpactScopeSchema, addImpactCounts, emptyImpactCounts, emptyImpactRecords, estimateImpactSavings, } from '@reticlehq/core';
|
|
5
5
|
/**
|
|
6
6
|
* Where Reticle keeps the record of what it has done for you.
|
|
7
7
|
*
|
|
@@ -14,16 +14,38 @@ import { ReticleDir, IMPACT_DAILY_BUCKETS, IMPACT_SCHEMA_VERSION, ImpactScopeSch
|
|
|
14
14
|
*/
|
|
15
15
|
/** Writes are debounced: a verification loop is 50-200 calls, and each one is a counter bump. */
|
|
16
16
|
const WRITE_DEBOUNCE_MS = 800;
|
|
17
|
+
/** The project's cloud binding, written by `reticle link`. Absent for an unlinked project. */
|
|
18
|
+
const CLOUD_LINK_FILE = 'cloud.json';
|
|
17
19
|
/**
|
|
18
20
|
* `reticleRoot` is the project's own `.reticle` directory (what every other store here is handed);
|
|
19
21
|
* the global scope always lives beside the daemon's own state in `~/.reticle`.
|
|
20
22
|
*/
|
|
21
|
-
|
|
23
|
+
function impactPaths(reticleRoot) {
|
|
22
24
|
return {
|
|
23
25
|
project: join(reticleRoot, ReticleDir.IMPACT_FILE),
|
|
24
26
|
global: join(homedir(), ReticleDir.ROOT, ReticleDir.IMPACT_FILE),
|
|
25
27
|
};
|
|
26
28
|
}
|
|
29
|
+
/**
|
|
30
|
+
* Where this project's dashboard lives, if `reticle link` recorded one.
|
|
31
|
+
*
|
|
32
|
+
* Read from the link file rather than derived from the API url, because the API origin and the
|
|
33
|
+
* console origin are different hosts in every deployment that is not a laptop. Synchronous and
|
|
34
|
+
* best-effort, like every other read in this file: a missing or malformed link file means no link
|
|
35
|
+
* in the HUD, never a failed tool call.
|
|
36
|
+
*/
|
|
37
|
+
export function readDashboardUrl(reticleRoot) {
|
|
38
|
+
try {
|
|
39
|
+
const raw = JSON.parse(readFileSync(join(reticleRoot, CLOUD_LINK_FILE), 'utf8'));
|
|
40
|
+
if ('object' !== typeof raw || null === raw)
|
|
41
|
+
return undefined;
|
|
42
|
+
const value = raw['dashboardUrl'];
|
|
43
|
+
return 'string' === typeof value && value.length > 0 ? value : undefined;
|
|
44
|
+
}
|
|
45
|
+
catch {
|
|
46
|
+
return undefined;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
27
49
|
function emptyScope(now) {
|
|
28
50
|
const counts = emptyImpactCounts();
|
|
29
51
|
return {
|
|
@@ -32,6 +54,7 @@ function emptyScope(now) {
|
|
|
32
54
|
records: emptyImpactRecords(),
|
|
33
55
|
savings: estimateImpactSavings(counts),
|
|
34
56
|
since: now,
|
|
57
|
+
defects: [],
|
|
35
58
|
};
|
|
36
59
|
}
|
|
37
60
|
/** Read a scope, tolerating absence and corruption: a broken file starts over rather than throwing. */
|
|
@@ -105,7 +128,21 @@ export function applyDelta(scope, delta, now, meta = {}) {
|
|
|
105
128
|
}
|
|
106
129
|
records.bestStreakDays = Math.max(records.bestStreakDays, records.streakDays);
|
|
107
130
|
records.longestRunMs = Math.max(records.longestRunMs, meta.runMs ?? 0);
|
|
108
|
-
|
|
131
|
+
/*
|
|
132
|
+
* Newest first, capped. Prepending is what makes the HUD's short list the CURRENT breakage rather
|
|
133
|
+
* than the first ten things that ever broke — which, after a week, is a list about the past.
|
|
134
|
+
*/
|
|
135
|
+
const defects = meta.defect === undefined
|
|
136
|
+
? scope.defects
|
|
137
|
+
: [meta.defect, ...scope.defects].slice(0, IMPACT_DEFECT_LIMIT);
|
|
138
|
+
return {
|
|
139
|
+
counts,
|
|
140
|
+
days,
|
|
141
|
+
records,
|
|
142
|
+
savings: estimateImpactSavings(counts),
|
|
143
|
+
since: scope.since,
|
|
144
|
+
defects,
|
|
145
|
+
};
|
|
109
146
|
}
|
|
110
147
|
/**
|
|
111
148
|
* The live impact record for one project.
|
|
@@ -117,6 +154,7 @@ export class ImpactStore {
|
|
|
117
154
|
#paths;
|
|
118
155
|
#now;
|
|
119
156
|
#projectName;
|
|
157
|
+
#dashboardUrl;
|
|
120
158
|
#project;
|
|
121
159
|
#global;
|
|
122
160
|
#timer;
|
|
@@ -125,6 +163,7 @@ export class ImpactStore {
|
|
|
125
163
|
this.#paths = impactPaths(opts.reticleRoot);
|
|
126
164
|
this.#now = opts.now ?? (() => Date.now());
|
|
127
165
|
this.#projectName = opts.projectName;
|
|
166
|
+
this.#dashboardUrl = readDashboardUrl(opts.reticleRoot);
|
|
128
167
|
const now = this.#now();
|
|
129
168
|
this.#project = readScope(this.#paths.project, now);
|
|
130
169
|
this.#global = readScope(this.#paths.global, now);
|
|
@@ -148,6 +187,8 @@ export class ImpactStore {
|
|
|
148
187
|
};
|
|
149
188
|
if (this.#projectName !== undefined)
|
|
150
189
|
snap.projectName = this.#projectName;
|
|
190
|
+
if (this.#dashboardUrl !== undefined)
|
|
191
|
+
snap.dashboardUrl = this.#dashboardUrl;
|
|
151
192
|
return snap;
|
|
152
193
|
}
|
|
153
194
|
/** Write now (process exit, tests). */
|
package/dist/index.d.ts
CHANGED
|
@@ -117,7 +117,10 @@ export interface StartOptions {
|
|
|
117
117
|
pairingTokenDir?: string;
|
|
118
118
|
/** injectable clock for contract.json's generatedAt stamp. Defaults to Date.now. */
|
|
119
119
|
now?: () => number;
|
|
120
|
-
/**
|
|
120
|
+
/**
|
|
121
|
+
* Retired profile name (`core`/`full`/…). Old values still map. The live switch is
|
|
122
|
+
* RETICLE_ADVERTISE_ALL_TOOLS=1; the default is the lean surface.
|
|
123
|
+
*/
|
|
121
124
|
toolProfile?: string;
|
|
122
125
|
/** Start the OEM/CI verify HTTP endpoint alongside the daemon (`reticle serve --http`). */
|
|
123
126
|
httpVerify?: boolean;
|
package/dist/index.js
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
import { join } from 'node:path';
|
|
2
2
|
import { existsSync, readFileSync } from 'node:fs';
|
|
3
3
|
import { homedir } from 'node:os';
|
|
4
|
-
import {
|
|
4
|
+
import { resolveProjectCloud } from './cloud/cloud-config.js';
|
|
5
|
+
import { startSyncDaemon } from './cloud/sync-daemon.js';
|
|
6
|
+
import { PROJECT_REGISTRY_FILE, emptyProjectRegistry, parseProjectRegistry, projectCandidates, } from '@reticlehq/core';
|
|
5
7
|
import { discoverProjectConfigs } from './cli/config-discovery.js';
|
|
6
8
|
import { projectCandidatesFrom, resolveArtifactRoot, } from './project/artifact-root.js';
|
|
7
9
|
import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
|
|
@@ -14,6 +16,8 @@ import { openLoopbackAlias } from './daemon/loopback-alias.js';
|
|
|
14
16
|
import { reportAppInstrumented } from './telemetry/app-instrumented.js';
|
|
15
17
|
import { resolveBridgeSecurityWithAutoToken } from './bridge/bridge-security.js';
|
|
16
18
|
import { Bridge } from './bridge/bridge.js';
|
|
19
|
+
import { sdkFixForDirectory } from './version/sdk-fix.js';
|
|
20
|
+
import { SERVER_VERSION } from './version/server-version.js';
|
|
17
21
|
import { BaselineStore } from './project/baselines.js';
|
|
18
22
|
import { RecordingStore } from './flows/recordings.js';
|
|
19
23
|
import { initImpact } from './impact/impact-recorder.js';
|
|
@@ -39,6 +43,7 @@ import { statusPayload } from './status-payload.js';
|
|
|
39
43
|
import { CdpRealInputProvider, LaunchedRealInputProvider } from './input/real-input.js';
|
|
40
44
|
import { cpus } from 'node:os';
|
|
41
45
|
import { BrowserPool } from './pool/browser-pool.js';
|
|
46
|
+
import { AGENT_ALREADY_DRIVING_ELSEWHERE, shouldGreetWithLeaseNotice, } from './session/lease-visibility.js';
|
|
42
47
|
import { playwrightLauncher, resolveMaxContexts } from './pool/playwright-launcher.js';
|
|
43
48
|
import { LeaseReaper } from './pool/lease-reaper.js';
|
|
44
49
|
import { readJournalEnabled, readProjectId } from './cli/cli-port.js';
|
|
@@ -187,7 +192,14 @@ function makeNetworkDetailRouter(bridge, driveUrl) {
|
|
|
187
192
|
function attachJournal(bridge, deps) {
|
|
188
193
|
const journalAttach = makeJournalAttach(deps);
|
|
189
194
|
const ambientStore = new AmbientStore(deps.fs, deps.reticleRoot);
|
|
195
|
+
// Built once, not per session: the resolver walks config discovery and the user-level registry,
|
|
196
|
+
// and neither changes between two tabs connecting a second apart.
|
|
197
|
+
const resolveArtifactRoot = artifactRootResolver(deps.reticleRoot);
|
|
190
198
|
bridge.attachSessionCreate((session) => {
|
|
199
|
+
// Stamp the project's own `.reticle` before ANY counter fires for this session. Without it every
|
|
200
|
+
// verdict is recorded against wherever the daemon was started, which is how one app's evidence
|
|
201
|
+
// reached a different account's production dashboard.
|
|
202
|
+
session.artifactRoot = resolveArtifactRoot(session.projectId).root;
|
|
191
203
|
journalAttach(session);
|
|
192
204
|
// Seed the learned ambient map so a fresh session starts knowing which regions churn, instead of
|
|
193
205
|
// re-learning from zero. Best-effort + async: a late seed still helps, a failure is silent.
|
|
@@ -256,6 +268,14 @@ async function resolveRealInput(options, onNavigateError, onNetworkDetail) {
|
|
|
256
268
|
return {};
|
|
257
269
|
}
|
|
258
270
|
/** Start the Reticle bridge (browser WS endpoint) and, by default, the MCP stdio server. */
|
|
271
|
+
/**
|
|
272
|
+
* The SDK-upgrade sentence for THIS project's package.json, evaluated at each HELLO so a
|
|
273
|
+
* just-edited manifest is what we name. Falls back to the framework-neutral sensor when cwd is
|
|
274
|
+
* not an app.
|
|
275
|
+
*/
|
|
276
|
+
function sdkFixForCwd() {
|
|
277
|
+
return sdkFixForDirectory(SERVER_VERSION, process.cwd());
|
|
278
|
+
}
|
|
259
279
|
/**
|
|
260
280
|
* Resolve a session's artifact root, from everything this machine knows about where projects live.
|
|
261
281
|
*
|
|
@@ -264,6 +284,39 @@ async function resolveRealInput(options, onNavigateError, onNetworkDetail) {
|
|
|
264
284
|
* this daemon is up, and a resolution that used a startup snapshot would keep answering with a map
|
|
265
285
|
* from before the project the agent is now driving existed.
|
|
266
286
|
*/
|
|
287
|
+
/**
|
|
288
|
+
* Every `.reticle` root on this machine that sync should consider, from the same two sources the
|
|
289
|
+
* artifact resolver uses.
|
|
290
|
+
*
|
|
291
|
+
* Read on every call rather than snapshotted, for the same reason: `reticle link` can run in
|
|
292
|
+
* another terminal while this daemon is up, and a startup snapshot would keep that repo silent
|
|
293
|
+
* until somebody restarted a process they have no reason to suspect.
|
|
294
|
+
*
|
|
295
|
+
* Returns directories that MIGHT be linked; the caller resolves each and skips the ones that are
|
|
296
|
+
* not. Deciding that here would mean reading every cloud.json on every tick.
|
|
297
|
+
*/
|
|
298
|
+
function knownProjectRoots() {
|
|
299
|
+
const roots = new Set();
|
|
300
|
+
try {
|
|
301
|
+
const path = join(homedir(), ReticleDir.ROOT, PROJECT_REGISTRY_FILE);
|
|
302
|
+
if (existsSync(path)) {
|
|
303
|
+
const registry = parseProjectRegistry(JSON.parse(readFileSync(path, 'utf8')));
|
|
304
|
+
for (const candidate of projectCandidates(registry))
|
|
305
|
+
roots.add(join(candidate.directory, ReticleDir.ROOT));
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
// A registry that cannot be read is an empty one — never a reason to stop syncing.
|
|
310
|
+
}
|
|
311
|
+
try {
|
|
312
|
+
for (const config of discoverProjectConfigs(process.cwd()).found)
|
|
313
|
+
roots.add(join(config.directory, ReticleDir.ROOT));
|
|
314
|
+
}
|
|
315
|
+
catch {
|
|
316
|
+
// Same: a diagnostic walk that throws must not take the sync loop with it.
|
|
317
|
+
}
|
|
318
|
+
return [...roots];
|
|
319
|
+
}
|
|
267
320
|
function artifactRootResolver(daemonRoot) {
|
|
268
321
|
return (projectId) => {
|
|
269
322
|
let registry = emptyProjectRegistry();
|
|
@@ -298,7 +351,7 @@ export async function start(options = {}) {
|
|
|
298
351
|
// "nothing recorded yet" over a month of history on disk is the worst version of this feature.
|
|
299
352
|
initImpact({ reticleRoot: options.reticleRoot ?? join(process.cwd(), ReticleDir.ROOT) });
|
|
300
353
|
const security = await resolveBridgeSecurityWithAutoToken(options);
|
|
301
|
-
const bridge = new Bridge({ port, ...security });
|
|
354
|
+
const bridge = new Bridge({ port, sdkFix: sdkFixForCwd, ...security });
|
|
302
355
|
// Server-authoritative liveness: a Node-side reaper (immune to browser throttling) ends sessions
|
|
303
356
|
// whose agent has gone idle, so a forgotten/crashed agent never leaves the HUD "running" forever.
|
|
304
357
|
const reaper = new SessionReaper(bridge.sessions);
|
|
@@ -332,6 +385,25 @@ export async function start(options = {}) {
|
|
|
332
385
|
pool = createBrowserPool(options.headless ?? true);
|
|
333
386
|
leaseReaper = new LeaseReaper(pool);
|
|
334
387
|
leaseReaper.start();
|
|
388
|
+
/*
|
|
389
|
+
* Tell a tab that ARRIVES during a lease why its HUD is silent.
|
|
390
|
+
*
|
|
391
|
+
* The acquire-time notice only reaches tabs already connected, so opening the app — or merely
|
|
392
|
+
* reloading it — while an agent held a lease landed somebody on a dark HUD with nothing
|
|
393
|
+
* explaining it. That is the more common way to hit it, because a person opens the dashboard
|
|
394
|
+
* precisely when they want to watch. Reported as "dashboard is being watched, but the agent chat
|
|
395
|
+
* shows nothing".
|
|
396
|
+
*
|
|
397
|
+
* Registered separately from the journal hook rather than folded into it: this one needs the
|
|
398
|
+
* pool, which does not exist on the no-drive path, and session-create handlers are additive.
|
|
399
|
+
*/
|
|
400
|
+
const leasePool = pool;
|
|
401
|
+
bridge.attachSessionCreate((session) => {
|
|
402
|
+
const leasedIds = leasePool.leasedSessionIds();
|
|
403
|
+
const leasedProjects = leasedIds.map((id) => bridge.sessions.get(id)?.projectId);
|
|
404
|
+
if (shouldGreetWithLeaseNotice(session, leasedIds, leasedProjects))
|
|
405
|
+
session.pushNarration(AGENT_ALREADY_DRIVING_ELSEWHERE);
|
|
406
|
+
});
|
|
335
407
|
const deps = {
|
|
336
408
|
sessions: bridge.sessions,
|
|
337
409
|
pool,
|
|
@@ -391,14 +463,19 @@ export async function startDaemon(options = {}) {
|
|
|
391
463
|
initImpact({ reticleRoot: options.reticleRoot ?? join(process.cwd(), ReticleDir.ROOT) });
|
|
392
464
|
const security = await resolveBridgeSecurityWithAutoToken(options);
|
|
393
465
|
const shared = createSharedServer(security.token === undefined ? {} : { token: security.token });
|
|
394
|
-
const bridge = new Bridge({ port, server: shared.httpServer, ...security });
|
|
466
|
+
const bridge = new Bridge({ port, server: shared.httpServer, sdkFix: sdkFixForCwd, ...security });
|
|
395
467
|
// The daemon owns listen (below), so the real bind error is reported there; absorb bridge.ready's
|
|
396
468
|
// mirror rejection so a port collision can't surface as an unhandled promise rejection.
|
|
397
469
|
void bridge.ready.catch(() => undefined);
|
|
470
|
+
// Declared before attachStatus so the closure below can report it; assigned further down, before
|
|
471
|
+
// listen — the first status request cannot arrive until after the bind.
|
|
472
|
+
let verifyHttp;
|
|
398
473
|
// `reticle status` GETs this for a live, at-a-glance view of connected tabs + their health.
|
|
399
474
|
// The same diagnosis agents get on an empty `reticle_sessions`, so `reticle status` — the
|
|
400
475
|
// most-run command in the field — stops answering "sessionCount: 0" and nothing else.
|
|
401
|
-
|
|
476
|
+
// `verifyPort` rides along so a later `serve --http` can tell whether this daemon already honours
|
|
477
|
+
// the requested `--http-port` instead of silently ignoring the flag (#687).
|
|
478
|
+
shared.attachStatus(() => statusPayload(bridge.sessions.count(), bridge.sessions.list(), bridge.sessions.noSessionHint(), verifyHttp?.port));
|
|
402
479
|
// Agent-independent presence: the daemon outlives any single agent, so when the LAST agent's MCP
|
|
403
480
|
// connection drops (it stopped, or is waiting on the human), end every session and push a clear
|
|
404
481
|
// "go to your terminal" notice to the panel — the human is on the browser and must not lose a typed
|
|
@@ -426,6 +503,23 @@ export async function startDaemon(options = {}) {
|
|
|
426
503
|
const pool = createBrowserPool(options.headless ?? true);
|
|
427
504
|
const leaseReaper = new LeaseReaper(pool);
|
|
428
505
|
leaseReaper.start();
|
|
506
|
+
/*
|
|
507
|
+
* Automatic cloud sync, for the session nobody thinks about.
|
|
508
|
+
*
|
|
509
|
+
* The daemon outlives every individual tool call and is already running for the whole session, so
|
|
510
|
+
* it is the only place "keep the dashboard current while work is happening" costs nobody an extra
|
|
511
|
+
* process to remember. Safe for an UNLINKED project: it resolves the link on every tick and does
|
|
512
|
+
* nothing until one exists, so `reticle link` takes effect without a restart.
|
|
513
|
+
*/
|
|
514
|
+
const cloudSync = startSyncDaemon({
|
|
515
|
+
reticleRoot,
|
|
516
|
+
cloud: () => resolveProjectCloud(fs, reticleRoot, homedir(), process.env),
|
|
517
|
+
// Every OTHER linked repo on this machine, not just the directory the daemon was started in.
|
|
518
|
+
// One daemon serves many projects, and pushing only its own root left the rest silently
|
|
519
|
+
// reporting nothing — indistinguishable, on the dashboard, from nobody having verified anything.
|
|
520
|
+
otherRoots: () => Promise.resolve(knownProjectRoots()),
|
|
521
|
+
cloudFor: (root) => resolveProjectCloud(fs, root, homedir(), process.env),
|
|
522
|
+
});
|
|
429
523
|
// Scope auto-selection to the active project (from .reticle.json) so a stray tab from another app is
|
|
430
524
|
// never picked when the agent omits a sessionId. Explicit per-call scope/sessionId still overrides.
|
|
431
525
|
// Scope + the no-session diagnosis: "no browser session connected" is the error that ends most
|
|
@@ -433,7 +527,7 @@ export async function startDaemon(options = {}) {
|
|
|
433
527
|
// Ordered AFTER the pool: the watch may open a browser itself the moment it finds a listening dev
|
|
434
528
|
// server for a wired project (see no-session-watch.ts), and it opens it through the pool — the same
|
|
435
529
|
// path reticle_lease takes, in this process, binding nothing.
|
|
436
|
-
wireSessionScope(bridge.sessions, readProjectId(process.cwd()), port, () => pool.
|
|
530
|
+
wireSessionScope(bridge.sessions, readProjectId(process.cwd()), port, (sessionId) => pool.wasReapedLease(sessionId), (url) => pool.acquire(url));
|
|
437
531
|
const deps = {
|
|
438
532
|
sessions: bridge.sessions,
|
|
439
533
|
pool,
|
|
@@ -444,9 +538,18 @@ export async function startDaemon(options = {}) {
|
|
|
444
538
|
project,
|
|
445
539
|
fs,
|
|
446
540
|
reticleRoot,
|
|
541
|
+
// The long-lived daemon needs this MORE than the standalone MCP process does, not less: it is
|
|
542
|
+
// the one that outlives a single project and serves every app on the machine. Omitting it here
|
|
543
|
+
// silently disabled per-session artifact resolution for every agent that attaches to a running
|
|
544
|
+
// daemon — the common case — so flows were listed, loaded and healed against wherever the
|
|
545
|
+
// daemon happened to be launched. Wired in only one of the two places, a resolver is a resolver
|
|
546
|
+
// that does not run.
|
|
547
|
+
artifactRootFor: artifactRootResolver(reticleRoot),
|
|
447
548
|
now,
|
|
448
549
|
bridgePort: port,
|
|
449
550
|
browserProbe: probeChromium,
|
|
551
|
+
// A finished verification should not sit behind a one-minute timer — see ToolDeps.onRunPersisted.
|
|
552
|
+
onRunPersisted: () => cloudSync.nudge(),
|
|
450
553
|
};
|
|
451
554
|
const profile = resolveToolSurface(options.toolProfile);
|
|
452
555
|
const effectiveDeps = realInput !== undefined ? { ...deps, realInput } : deps;
|
|
@@ -461,9 +564,11 @@ export async function startDaemon(options = {}) {
|
|
|
461
564
|
// Optional OEM/CI verify endpoint: a host platform POSTs to /verify and gets an ReticleVerificationRun,
|
|
462
565
|
// driving the same flow-replay machinery the agent uses — no MCP stdio, no human. Each verdict is
|
|
463
566
|
// persisted via RunStore. Localhost-bound + token-guarded. Off unless `reticle serve --http`.
|
|
464
|
-
|
|
567
|
+
// (`verifyHttp` itself is declared above attachStatus, which reports its port.)
|
|
465
568
|
if (true === options.httpVerify) {
|
|
466
|
-
|
|
569
|
+
// Wakes cloud sync when the HTTP verify server persists a run — that path does not push
|
|
570
|
+
// inline the way the MCP one does, so without this its runs waited for the timer.
|
|
571
|
+
const runStore = new RunStore(fs, reticleRoot, { onWrote: () => cloudSync.nudge() });
|
|
467
572
|
const runner = new ReticleRunner(createRunnerPort(effectiveDeps));
|
|
468
573
|
const token = options.httpVerifyToken ?? process.env[ReticleEnv.VERIFY_TOKEN] ?? '';
|
|
469
574
|
verifyHttp = await startVerifyServer({ runner, token, persist: (run) => runStore.write(run) }, options.httpVerifyPort ?? RETICLE_VERIFY_DEFAULT_PORT);
|
|
@@ -552,6 +657,7 @@ export async function startDaemon(options = {}) {
|
|
|
552
657
|
if (vh !== undefined)
|
|
553
658
|
await new Promise((resolve) => vh.server.close(() => resolve()));
|
|
554
659
|
leaseReaper.stop();
|
|
660
|
+
cloudSync.stop();
|
|
555
661
|
await loopbackAlias.close?.();
|
|
556
662
|
await pool.shutdown();
|
|
557
663
|
await owned?.dispose();
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `reticle init` writes a behavioral rule into the coding agent's instruction file so the agent
|
|
3
3
|
* VERIFIES a feature with Reticle after building it — not only when the user remembers to say "test
|
|
4
|
-
* it with reticle". Registering the MCP server (mcp.ts /
|
|
4
|
+
* it with reticle". Registering the MCP server (mcp.ts / mcp-clients.ts) only makes the tools AVAILABLE;
|
|
5
5
|
* this is the piece that makes the agent reach for them, every session, unprompted.
|
|
6
6
|
*
|
|
7
7
|
* It carries a SECOND standing instruction, and that one is not about this project at all: send
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* written into whichever instruction file the detected agent reads: `CLAUDE.md` (Claude Code),
|
|
16
16
|
* `.cursor/rules/reticle.mdc` (Cursor, `alwaysApply` so it stays in context), or `AGENTS.md` as the
|
|
17
17
|
* cross-agent fallback. Idempotent via a marker block — safe to append to an existing file and a
|
|
18
|
-
* re-run is a no-op. Mirrors the apply/already result shape used across init (see
|
|
18
|
+
* re-run is a no-op. Mirrors the apply/already result shape used across init (see mcp-clients.ts).
|
|
19
19
|
*/
|
|
20
20
|
/** Project-root instruction files the agent re-reads every session. */
|
|
21
21
|
export declare const CLAUDE_MD_PATH = "CLAUDE.md";
|
|
@@ -36,6 +36,15 @@ export declare const AGENTS_MD_PATH = "AGENTS.md";
|
|
|
36
36
|
export declare const RETICLE_MD_PATH = "RETICLE.md";
|
|
37
37
|
/** Cursor project rule; the frontmatter `alwaysApply` keeps it in context on every turn. */
|
|
38
38
|
export declare const CURSOR_RULE_PATH = ".cursor/rules/reticle.mdc";
|
|
39
|
+
/**
|
|
40
|
+
* Does this file already carry the managed block?
|
|
41
|
+
*
|
|
42
|
+
* Exported so callers cannot invent their own looser test. The begin marker carries explanatory
|
|
43
|
+
* text inside the comment, so a substring check for `reticle:begin` matches files that
|
|
44
|
+
* `mergeMarkedInstruction` would treat as having NO block — and the two disagreeing means a refresh
|
|
45
|
+
* silently appends a second copy instead of updating the first.
|
|
46
|
+
*/
|
|
47
|
+
export declare function hasManagedBlock(text: string): boolean;
|
|
39
48
|
/**
|
|
40
49
|
* How the agent must INVOKE the CLI.
|
|
41
50
|
*
|
|
@@ -60,13 +69,28 @@ export declare const CLI: string;
|
|
|
60
69
|
* inside a host that asks the human for permission — so a dev server it starts is visible in the
|
|
61
70
|
* transcript, attributable, and stoppable.
|
|
62
71
|
*
|
|
63
|
-
* The guards are the whole reason this is safe, so no renderer may drop them:
|
|
64
|
-
*
|
|
65
|
-
*
|
|
72
|
+
* The guards are the whole reason this is safe, so no renderer may drop them: one server at a time,
|
|
73
|
+
* read the command rather than invent one, never kill anything you did not start, and leave the
|
|
74
|
+
* permission prompt to the host. "Background it and say so" is no longer among them because the
|
|
75
|
+
* branch above now states it at the point of action, and this text is read every turn — a rule
|
|
76
|
+
* stated twice costs every agent tokens forever and is the first thing to drift.
|
|
77
|
+
*
|
|
78
|
+
* The RESTART branch outranks the rest and is stated first. It used to be an aside, while "if a dev
|
|
79
|
+
* server is already listening, use it" was a numbered guard — so an agent resolving the two
|
|
80
|
+
* reasonably reused a server started before `init` edited the build config, served a bundle with no
|
|
81
|
+
* SDK in it, and landed on an empty session list with every other step done correctly.
|
|
66
82
|
*
|
|
67
83
|
* Exported because slash-command.ts renders the same rule; there must not be two versions of it.
|
|
68
84
|
*/
|
|
69
|
-
export declare const DEV_SERVER_POLICY = "**
|
|
85
|
+
export declare const DEV_SERVER_POLICY = "**A dev server already running when `reticle init` ran does not have Reticle in its bundle.** It read the build config at boot; `init` edited it afterwards. It serves the old bundle and no session appears. In order:\n\n1. **A dev server was already running?** Restart it, then hard-reload the tab. \"Something is listening\" does not mean the right bundle is served.\n2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. `reticle_sessions` gives you this project's own dev command in `next_action`; use that, never compose one. Started after `init`, it needs no restart.\n\nStopping to ask is how a verification turn ends with nothing verified.\n\nFour guards, none optional:\n\n1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.\n2. **Never guess the command.** It comes from `package.json` scripts. No recognisable dev script means say so and stop, not invent one.\n3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.\n4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.";
|
|
86
|
+
/**
|
|
87
|
+
* The operative rules, carried by every file that loads on every turn.
|
|
88
|
+
*
|
|
89
|
+
* Short on purpose. This is the text that has to CHANGE BEHAVIOUR, so it states when to verify, when
|
|
90
|
+
* NOT to, how, and the guards against calling something proven when it is not. Everything an agent
|
|
91
|
+
* needs only at the moment it hits a specific situation lives in RETICLE.md, named at the end.
|
|
92
|
+
*/
|
|
93
|
+
export declare const RULE_BODY: string;
|
|
70
94
|
/** The full-rules file, written verbatim (no markers: `init` owns this file entirely). */
|
|
71
95
|
export declare function reticleMdFile(): string;
|
|
72
96
|
export declare const AgentRuleStatus: {
|
package/dist/init/agent-rules.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* `reticle init` writes a behavioral rule into the coding agent's instruction file so the agent
|
|
3
3
|
* VERIFIES a feature with Reticle after building it — not only when the user remembers to say "test
|
|
4
|
-
* it with reticle". Registering the MCP server (mcp.ts /
|
|
4
|
+
* it with reticle". Registering the MCP server (mcp.ts / mcp-clients.ts) only makes the tools AVAILABLE;
|
|
5
5
|
* this is the piece that makes the agent reach for them, every session, unprompted.
|
|
6
6
|
*
|
|
7
7
|
* It carries a SECOND standing instruction, and that one is not about this project at all: send
|
|
@@ -15,7 +15,7 @@
|
|
|
15
15
|
* written into whichever instruction file the detected agent reads: `CLAUDE.md` (Claude Code),
|
|
16
16
|
* `.cursor/rules/reticle.mdc` (Cursor, `alwaysApply` so it stays in context), or `AGENTS.md` as the
|
|
17
17
|
* cross-agent fallback. Idempotent via a marker block — safe to append to an existing file and a
|
|
18
|
-
* re-run is a no-op. Mirrors the apply/already result shape used across init (see
|
|
18
|
+
* re-run is a no-op. Mirrors the apply/already result shape used across init (see mcp-clients.ts).
|
|
19
19
|
*/
|
|
20
20
|
import { NPX } from './mcp.js';
|
|
21
21
|
import { RETICLE_NPM_PACKAGE } from '../version/server-version.js';
|
|
@@ -41,6 +41,17 @@ export const CURSOR_RULE_PATH = '.cursor/rules/reticle.mdc';
|
|
|
41
41
|
/** Markers delimiting the managed block so a re-run is idempotent and the block stays updatable. */
|
|
42
42
|
const RULE_BEGIN = '<!-- reticle:begin (managed by `reticle init` — edit outside these markers) -->';
|
|
43
43
|
const RULE_END = '<!-- reticle:end -->';
|
|
44
|
+
/**
|
|
45
|
+
* Does this file already carry the managed block?
|
|
46
|
+
*
|
|
47
|
+
* Exported so callers cannot invent their own looser test. The begin marker carries explanatory
|
|
48
|
+
* text inside the comment, so a substring check for `reticle:begin` matches files that
|
|
49
|
+
* `mergeMarkedInstruction` would treat as having NO block — and the two disagreeing means a refresh
|
|
50
|
+
* silently appends a second copy instead of updating the first.
|
|
51
|
+
*/
|
|
52
|
+
export function hasManagedBlock(text) {
|
|
53
|
+
return text.includes(RULE_BEGIN);
|
|
54
|
+
}
|
|
44
55
|
/**
|
|
45
56
|
* How the agent must INVOKE the CLI.
|
|
46
57
|
*
|
|
@@ -65,21 +76,32 @@ export const CLI = `${NPX} ${RETICLE_NPM_PACKAGE}`;
|
|
|
65
76
|
* inside a host that asks the human for permission — so a dev server it starts is visible in the
|
|
66
77
|
* transcript, attributable, and stoppable.
|
|
67
78
|
*
|
|
68
|
-
* The guards are the whole reason this is safe, so no renderer may drop them:
|
|
69
|
-
*
|
|
70
|
-
*
|
|
79
|
+
* The guards are the whole reason this is safe, so no renderer may drop them: one server at a time,
|
|
80
|
+
* read the command rather than invent one, never kill anything you did not start, and leave the
|
|
81
|
+
* permission prompt to the host. "Background it and say so" is no longer among them because the
|
|
82
|
+
* branch above now states it at the point of action, and this text is read every turn — a rule
|
|
83
|
+
* stated twice costs every agent tokens forever and is the first thing to drift.
|
|
84
|
+
*
|
|
85
|
+
* The RESTART branch outranks the rest and is stated first. It used to be an aside, while "if a dev
|
|
86
|
+
* server is already listening, use it" was a numbered guard — so an agent resolving the two
|
|
87
|
+
* reasonably reused a server started before `init` edited the build config, served a bundle with no
|
|
88
|
+
* SDK in it, and landed on an empty session list with every other step done correctly.
|
|
71
89
|
*
|
|
72
90
|
* Exported because slash-command.ts renders the same rule; there must not be two versions of it.
|
|
73
91
|
*/
|
|
74
|
-
export const DEV_SERVER_POLICY = `**
|
|
92
|
+
export const DEV_SERVER_POLICY = `**A dev server already running when \`reticle init\` ran does not have Reticle in its bundle.** It read the build config at boot; \`init\` edited it afterwards. It serves the old bundle and no session appears. In order:
|
|
93
|
+
|
|
94
|
+
1. **A dev server was already running?** Restart it, then hard-reload the tab. "Something is listening" does not mean the right bundle is served.
|
|
95
|
+
2. **Nothing was running?** Start it in the BACKGROUND and say so in one line. \`reticle_sessions\` gives you this project's own dev command in \`next_action\`; use that, never compose one. Started after \`init\`, it needs no restart.
|
|
75
96
|
|
|
76
|
-
|
|
97
|
+
Stopping to ask is how a verification turn ends with nothing verified.
|
|
77
98
|
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
99
|
+
Four guards, none optional:
|
|
100
|
+
|
|
101
|
+
1. **Never run two at once.** One dev server on the app's port. Restarting a stale one means stopping it first, not starting a second alongside it.
|
|
102
|
+
2. **Never guess the command.** It comes from \`package.json\` scripts. No recognisable dev script means say so and stop, not invent one.
|
|
103
|
+
3. **Never kill anything you did not start**, and never a daemon or a port holder. The one exception is the restart above, and say in one line that you did it.
|
|
104
|
+
4. **The permission prompt belongs to your host.** Never bypass, suppress or auto-approve it, and take a refusal as the answer.`;
|
|
83
105
|
/**
|
|
84
106
|
* The operative rules, carried by every file that loads on every turn.
|
|
85
107
|
*
|
|
@@ -87,7 +109,7 @@ Five guards, none optional:
|
|
|
87
109
|
* NOT to, how, and the guards against calling something proven when it is not. Everything an agent
|
|
88
110
|
* needs only at the moment it hits a specific situation lives in RETICLE.md, named at the end.
|
|
89
111
|
*/
|
|
90
|
-
const RULE_BODY = `## Verifying with Reticle
|
|
112
|
+
export const RULE_BODY = `## Verifying with Reticle
|
|
91
113
|
|
|
92
114
|
This app is instrumented by **Reticle**, an in-app verification layer exposed as \`reticle_*\` MCP tools and the \`${CLI}\` CLI (always through npx: Reticle's server is not installed into this project). Verifying is part of "done", not an optional extra.
|
|
93
115
|
|
|
@@ -103,21 +125,40 @@ This app is instrumented by **Reticle**, an in-app verification layer exposed as
|
|
|
103
125
|
- **Only \`reticle_act_and_wait\` and \`reticle_assert\` produce a verdict.** \`reticle_act\` and everything else move or read the app and prove nothing, so a session ending without one of those two has no result however many tools it used.
|
|
104
126
|
- Covered flows: \`${CLI} gate\` reports which recorded flows the changed files affect and whether they still pass.
|
|
105
127
|
|
|
128
|
+
**Setting Reticle up, or just restarted? You are mid-sequence — do not stop until a verdict exists.**
|
|
129
|
+
The whole of it is: instrument the app → get a dev server running → open the app in a browser →
|
|
130
|
+
drive one flow → report the verdict. Every step is yours to do, and none of them needs the user.
|
|
131
|
+
The ONE legitimate pause is a client restart, because a client reads its server list at startup;
|
|
132
|
+
when you come back, you are not finished, you are on the next step — resume it without being asked.
|
|
133
|
+
Stopping anywhere else leaves an app that looks installed and can verify nothing, which is the
|
|
134
|
+
single commonest way this goes wrong. \`/reticle\` carries the full recovery ladder when a step
|
|
135
|
+
does not work; use it rather than guessing, and never report the install as finished without a
|
|
136
|
+
verdict to point at.
|
|
137
|
+
|
|
106
138
|
**Nothing connected? Get the app running.**
|
|
107
139
|
|
|
108
140
|
${DEV_SERVER_POLICY}
|
|
109
141
|
|
|
110
142
|
A dev server that is already running does not pick up an edited build config or a newly created plugin file — restart it and hard-reload the tab. And if a server IS listening and still nothing connects, the cause is the SDK not loading in the page, not a missing dev server; do not tell the user to start one they are already running.
|
|
111
143
|
|
|
144
|
+
**Finish \`src/reticle-dev.ts\` before you claim setup is done.** \`init\` writes it and cannot always fill it in: a store that needs an argument only reading the code supplies (Jotai atoms, an XState actor, a TanStack \`queryClient\`) is left as a commented \`registerStore\` line. A file that registers nothing looks exactly like a finished one, and \`reticle_state\` then returns empty forever — which is indistinguishable from an app that has nothing to report, so it reads as success. Uncomment the line, complete it, and prove it by driving one flow and seeing your keys come back. If \`init\` told you to restart your client, this is the job waiting for you on the other side of that restart.
|
|
145
|
+
|
|
146
|
+
**Verify each feature as you finish it, not all of them at the end.** Asked for four, build one, drive it, get a verdict, then start the second. A red verdict after four builds has four suspects; after one it has none.
|
|
147
|
+
|
|
148
|
+
**Capture what a change is FOR while you are building it, not afterwards.** \`reticle_intent\` records the business outcome a change is meant to produce, and the only moment anybody knows it is while the change is being made. Pass \`intent\` when you save a flow, so the saved flow carries the reason it exists. A flow without one replays for months and then reports "step 3 failed" instead of what stopped being true for a user.
|
|
149
|
+
|
|
112
150
|
**Honesty, which is the whole point:**
|
|
113
151
|
|
|
114
152
|
- **\`verified: "unknown"\` is not a pass.** It means Reticle drove the app and could not tell what happened; \`verifiedReason\` says which clause decided that. Report it as unknown, never as working.
|
|
153
|
+
- **\`verified: "no-fault"\` is not a pass either.** It means nothing was DECLARED to prove: the page settled and no channel complained, but you asserted nothing, so there is no verification. You get it whenever \`until\` is omitted. Name a consequence the action changes — a signal, a request, a route, or store state — and call again.
|
|
115
154
|
- **Never weaken a check to make it green.** Downgrading, skipping or deleting an assertion is a finding, not a fix.
|
|
116
155
|
- **If Reticle cannot run** (no daemon, or this is not a running web app), say so. Do not skip verification silently.
|
|
117
156
|
- **Setup is not finished until one real flow has been driven and produced a verdict.** \`init\` exiting 0, the tools appearing, and a session being listed are all things that happen before anything has been verified.
|
|
118
157
|
|
|
119
158
|
**The \`/reticle\` skill runs this whole loop for you** — detect, connect, drive one flow, report. If your client does not have it, install it once: \`/plugin marketplace add reticlehq/reticle\` then \`/plugin install reticle@reticlehq\` in Claude Code, or \`npx skills add reticlehq/reticle\` anywhere the skills CLI works.
|
|
120
159
|
|
|
160
|
+
**A tool you need is missing? It exists.** The default surface advertises a subset; reach any other by name with \`reticle_run { tool, args }\`, and list them with \`reticle_tools\`. Two worth knowing: \`reticle_context\` returns this run's own memory — what is established, what is proven, what is still unverified — which is what you want after a compaction or when picking up work you did not start; \`reticle_intent\` records what a change was MEANT to do, while somebody still knows.
|
|
161
|
+
|
|
121
162
|
**Report Reticle's own defects with \`reticle_feedback\` the moment you notice**, then carry on with your task. You are the user Reticle is built for and the only one who can say what it cost you, and that knowledge is gone when your context is.
|
|
122
163
|
|
|
123
164
|
📄 **The rest is in [RETICLE.md](./${RETICLE_MD_PATH}): what to do when the tools are missing, when a result carries \`version_skew\` or \`update_available\`, when \`reticle_state\` comes back empty, and how to write a feedback report that can be acted on. Read it when you hit one of those, not before.**`;
|
|
@@ -15,3 +15,19 @@ import { type SourcePatch } from './patch-kind.js';
|
|
|
15
15
|
import { UiLibrary } from './detect.js';
|
|
16
16
|
export declare function patchAstroConfig(source: string): SourcePatch;
|
|
17
17
|
export declare function patchAstroLayout(source: string, port: number | undefined, projectId: string | undefined, uiLibrary?: UiLibrary): SourcePatch;
|
|
18
|
+
/** Where Astro keeps ambient types — `create-astro` ships this file. */
|
|
19
|
+
export declare const ASTRO_ENV_DTS_PATH = "src/env.d.ts";
|
|
20
|
+
/**
|
|
21
|
+
* The declarations `astro check` needs for the Vite `define` names (#677).
|
|
22
|
+
*
|
|
23
|
+
* Matching SvelteKit's `hooks.client.ts` typing: `string | undefined`, because the define can be
|
|
24
|
+
* absent when the pairing token file is missing.
|
|
25
|
+
*/
|
|
26
|
+
export declare const ASTRO_ENV_DTS_DECLARES: string;
|
|
27
|
+
/**
|
|
28
|
+
* Append the Vite-define ambient declarations to `src/env.d.ts`, or create the file.
|
|
29
|
+
*
|
|
30
|
+
* Without this, `create-astro`'s default `"astro check && astro build"` fails with four
|
|
31
|
+
* `ts(2304) Cannot find name '__RETICLE_TOKEN__'` errors after a clean init (#677).
|
|
32
|
+
*/
|
|
33
|
+
export declare function patchAstroEnvDts(existing: string | null): SourcePatch;
|
package/dist/init/astro-patch.js
CHANGED
|
@@ -270,3 +270,31 @@ export function patchAstroLayout(source, port, projectId, uiLibrary = UiLibrary.
|
|
|
270
270
|
code: `${source.slice(0, at)}${astroConnectScript(port, projectId, uiLibrary)}${source.slice(at)}`,
|
|
271
271
|
};
|
|
272
272
|
}
|
|
273
|
+
/** Where Astro keeps ambient types — `create-astro` ships this file. */
|
|
274
|
+
export const ASTRO_ENV_DTS_PATH = 'src/env.d.ts';
|
|
275
|
+
/**
|
|
276
|
+
* The declarations `astro check` needs for the Vite `define` names (#677).
|
|
277
|
+
*
|
|
278
|
+
* Matching SvelteKit's `hooks.client.ts` typing: `string | undefined`, because the define can be
|
|
279
|
+
* absent when the pairing token file is missing.
|
|
280
|
+
*/
|
|
281
|
+
export const ASTRO_ENV_DTS_DECLARES = 'declare const __RETICLE_TOKEN__: string | undefined;\n' +
|
|
282
|
+
'declare const __RETICLE_ROOT__: string | undefined;\n';
|
|
283
|
+
/** Present once either declare is in the file — both are written together. */
|
|
284
|
+
const ENV_DTS_MARKER = '__RETICLE_TOKEN__';
|
|
285
|
+
/**
|
|
286
|
+
* Append the Vite-define ambient declarations to `src/env.d.ts`, or create the file.
|
|
287
|
+
*
|
|
288
|
+
* Without this, `create-astro`'s default `"astro check && astro build"` fails with four
|
|
289
|
+
* `ts(2304) Cannot find name '__RETICLE_TOKEN__'` errors after a clean init (#677).
|
|
290
|
+
*/
|
|
291
|
+
export function patchAstroEnvDts(existing) {
|
|
292
|
+
if (null !== existing && existing.includes(ENV_DTS_MARKER)) {
|
|
293
|
+
return { kind: PatchKind.ALREADY };
|
|
294
|
+
}
|
|
295
|
+
if (null === existing || '' === existing.trim()) {
|
|
296
|
+
return { kind: PatchKind.APPLY, code: ASTRO_ENV_DTS_DECLARES };
|
|
297
|
+
}
|
|
298
|
+
const base = existing.endsWith('\n') ? existing : `${existing}\n`;
|
|
299
|
+
return { kind: PatchKind.APPLY, code: `${base}${ASTRO_ENV_DTS_DECLARES}` };
|
|
300
|
+
}
|