@reticlehq/server 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bridge-security.d.ts +0 -1
- package/dist/bridge-security.js +0 -1
- package/dist/bridge.d.ts +0 -1
- package/dist/bridge.js +102 -12
- package/dist/bridge.test-harness.d.ts +5 -1
- package/dist/bridge.test-harness.js +12 -1
- package/dist/capsule/capsule-store.d.ts +2 -3
- package/dist/capsule/capsule-store.js +0 -1
- package/dist/capsule/capsule.d.ts +0 -1
- package/dist/capsule/capsule.js +0 -1
- package/dist/capsule/causal-summary.d.ts +21 -1
- package/dist/capsule/causal-summary.js +20 -2
- package/dist/capsule/divergence.d.ts +0 -1
- package/dist/capsule/divergence.js +0 -1
- package/dist/capsule/minimize.d.ts +0 -1
- package/dist/capsule/minimize.js +0 -1
- package/dist/capsule/predicate-to-links.d.ts +0 -1
- package/dist/capsule/predicate-to-links.js +0 -1
- package/dist/cli-doctor.d.ts +6 -0
- package/dist/cli-doctor.js +60 -0
- package/dist/cli-flow-commands.d.ts +0 -1
- package/dist/cli-flow-commands.js +0 -1
- package/dist/cli-launch.d.ts +0 -1
- package/dist/cli-launch.js +7 -3
- package/dist/cli-parse.d.ts +47 -3
- package/dist/cli-parse.js +147 -13
- package/dist/cli-port.d.ts +3 -1
- package/dist/cli-port.js +21 -1
- package/dist/cli-verify.d.ts +0 -1
- package/dist/cli-verify.js +1 -2
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +88 -69
- package/dist/cloud/cloud-config.d.ts +0 -1
- package/dist/cloud/cloud-config.js +0 -1
- package/dist/cloud/cloud-sync.d.ts +4 -5
- package/dist/cloud/cloud-sync.js +0 -1
- package/dist/cloud-cli.d.ts +0 -1
- package/dist/cloud-cli.js +9 -2
- package/dist/crawl/crawl-tools.d.ts +0 -1
- package/dist/crawl/crawl-tools.js +1 -2
- package/dist/crawl/crawl.d.ts +17 -3
- package/dist/crawl/crawl.js +43 -4
- package/dist/daemon-resilience.d.ts +6 -1
- package/dist/daemon-resilience.js +63 -1
- package/dist/daemon.d.ts +23 -3
- package/dist/daemon.js +36 -24
- package/dist/domain/domain-model.d.ts +0 -1
- package/dist/domain/domain-model.js +1 -2
- package/dist/domain/domain-tools.d.ts +0 -7
- package/dist/domain/domain-tools.js +21 -4
- package/dist/domain/flow-risk.d.ts +0 -1
- package/dist/domain/flow-risk.js +0 -1
- package/dist/ee/audit-log.d.ts +0 -1
- package/dist/ee/audit-log.js +0 -1
- package/dist/events/body-failures.d.ts +4 -0
- package/dist/events/body-failures.js +113 -0
- package/dist/events/contradictions.d.ts +53 -0
- package/dist/events/contradictions.js +282 -0
- package/dist/events/echo-mismatch.d.ts +4 -0
- package/dist/events/echo-mismatch.js +138 -0
- package/dist/events/event-filters.d.ts +17 -3
- package/dist/events/event-filters.js +13 -3
- package/dist/events/json-salvage.d.ts +32 -0
- package/dist/events/json-salvage.js +96 -0
- package/dist/events/predicate-eval.d.ts +2 -1
- package/dist/events/predicate-eval.js +56 -9
- package/dist/events/predicate.d.ts +0 -1
- package/dist/events/predicate.js +56 -2
- package/dist/events/reaction.d.ts +0 -1
- package/dist/events/reaction.js +0 -1
- package/dist/events/reconcile.d.ts +39 -0
- package/dist/events/reconcile.js +211 -0
- package/dist/events/ring-buffer.d.ts +0 -1
- package/dist/events/ring-buffer.js +0 -1
- package/dist/events/stale-response.d.ts +4 -0
- package/dist/events/stale-response.js +139 -0
- package/dist/events/unit-mismatch.d.ts +16 -0
- package/dist/events/unit-mismatch.js +167 -0
- package/dist/flows/affected-tools.d.ts +18 -0
- package/dist/flows/affected-tools.js +52 -0
- package/dist/flows/affected.d.ts +0 -1
- package/dist/flows/affected.js +0 -1
- package/dist/flows/annotate-tools.d.ts +0 -1
- package/dist/flows/annotate-tools.js +21 -3
- package/dist/flows/annotate.d.ts +0 -1
- package/dist/flows/annotate.js +0 -1
- package/dist/flows/annotation-store.d.ts +0 -1
- package/dist/flows/annotation-store.js +0 -1
- package/dist/flows/assertion-integrity.d.ts +0 -1
- package/dist/flows/assertion-integrity.js +0 -1
- package/dist/flows/assertion-tiers-store.d.ts +0 -1
- package/dist/flows/assertion-tiers-store.js +0 -1
- package/dist/flows/buddy-status.d.ts +0 -1
- package/dist/flows/buddy-status.js +0 -1
- package/dist/flows/coverage.d.ts +0 -1
- package/dist/flows/coverage.js +0 -1
- package/dist/flows/decision.d.ts +0 -7
- package/dist/flows/decision.js +47 -7
- package/dist/flows/flake-store.d.ts +0 -1
- package/dist/flows/flake-store.js +0 -1
- package/dist/flows/flake.d.ts +0 -1
- package/dist/flows/flake.js +0 -1
- package/dist/flows/flow-classify.d.ts +0 -1
- package/dist/flows/flow-classify.js +0 -1
- package/dist/flows/flow-replay-run.d.ts +0 -1
- package/dist/flows/flow-replay-run.js +2 -3
- package/dist/flows/flow-replay.d.ts +20 -4
- package/dist/flows/flow-replay.js +9 -43
- package/dist/flows/flow-report.d.ts +0 -1
- package/dist/flows/flow-report.js +0 -1
- package/dist/flows/flow-scope.d.ts +0 -1
- package/dist/flows/flow-scope.js +0 -1
- package/dist/flows/flow-sources.d.ts +0 -1
- package/dist/flows/flow-sources.js +0 -1
- package/dist/flows/flow-step-runners.d.ts +23 -0
- package/dist/flows/flow-step-runners.js +102 -0
- package/dist/flows/flow-success.d.ts +0 -1
- package/dist/flows/flow-success.js +0 -1
- package/dist/flows/flow-tools.d.ts +0 -1
- package/dist/flows/flow-tools.js +44 -14
- package/dist/flows/flows.d.ts +6 -2
- package/dist/flows/flows.js +15 -2
- package/dist/flows/gate.d.ts +0 -1
- package/dist/flows/gate.js +0 -1
- package/dist/flows/git-changed.d.ts +0 -1
- package/dist/flows/git-changed.js +0 -1
- package/dist/flows/heal-run.d.ts +0 -1
- package/dist/flows/heal-run.js +0 -1
- package/dist/flows/heal.d.ts +0 -1
- package/dist/flows/heal.js +0 -1
- package/dist/flows/parallel-suite.d.ts +0 -1
- package/dist/flows/parallel-suite.js +0 -1
- package/dist/flows/recordings.d.ts +0 -1
- package/dist/flows/recordings.js +0 -1
- package/dist/flows/replay.d.ts +0 -1
- package/dist/flows/replay.js +71 -4
- package/dist/flows/server-verify.d.ts +0 -1
- package/dist/flows/server-verify.js +0 -1
- package/dist/flows/verify-change-tools.d.ts +2 -0
- package/dist/flows/verify-change-tools.js +187 -0
- package/dist/flows/watch-batcher.d.ts +0 -1
- package/dist/flows/watch-batcher.js +0 -1
- package/dist/honesty/accepted-write.d.ts +14 -0
- package/dist/honesty/accepted-write.js +17 -0
- package/dist/honesty/blind-spots.d.ts +18 -1
- package/dist/honesty/blind-spots.js +47 -5
- package/dist/honesty/honesty.d.ts +0 -1
- package/dist/honesty/honesty.js +0 -1
- package/dist/honesty/uncaptured-bodies.d.ts +19 -0
- package/dist/honesty/uncaptured-bodies.js +30 -0
- package/dist/honesty/unread-outcome.d.ts +2 -0
- package/dist/honesty/unread-outcome.js +50 -0
- package/dist/honesty/verified.d.ts +40 -0
- package/dist/honesty/verified.js +86 -0
- package/dist/http-server.d.ts +0 -1
- package/dist/http-server.js +5 -1
- package/dist/hunt/hunt-report.d.ts +50 -0
- package/dist/hunt/hunt-report.js +84 -0
- package/dist/idle-shutdown.d.ts +0 -1
- package/dist/idle-shutdown.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/init/agent-rules.d.ts +0 -1
- package/dist/init/agent-rules.js +4 -2
- package/dist/init/capabilities.d.ts +17 -0
- package/dist/init/capabilities.js +51 -0
- package/dist/init/cursor.d.ts +0 -1
- package/dist/init/cursor.js +0 -1
- package/dist/init/desktop-doctor.d.ts +40 -0
- package/dist/init/desktop-doctor.js +198 -0
- package/dist/init/detect.d.ts +25 -1
- package/dist/init/detect.js +65 -4
- package/dist/init/mcp.d.ts +0 -1
- package/dist/init/mcp.js +0 -1
- package/dist/init/next-patch.d.ts +41 -0
- package/dist/init/next-patch.js +106 -0
- package/dist/init/node-io.d.ts +0 -1
- package/dist/init/node-io.js +25 -1
- package/dist/init/patch-kind.d.ts +20 -0
- package/dist/init/patch-kind.js +10 -0
- package/dist/init/plan-framework.d.ts +35 -0
- package/dist/init/plan-framework.js +217 -0
- package/dist/init/plan.d.ts +55 -4
- package/dist/init/plan.js +130 -112
- package/dist/init/project-id.d.ts +0 -1
- package/dist/init/project-id.js +0 -1
- package/dist/init/run.d.ts +17 -1
- package/dist/init/run.js +237 -18
- package/dist/init/slash-command.d.ts +18 -0
- package/dist/init/slash-command.js +52 -0
- package/dist/init/snippets.d.ts +48 -3
- package/dist/init/snippets.js +156 -6
- package/dist/init/vite-config.d.ts +4 -11
- package/dist/init/vite-config.js +15 -8
- package/dist/input/driven-redaction.d.ts +15 -0
- package/dist/input/driven-redaction.js +76 -0
- package/dist/input/network-detail.d.ts +9 -4
- package/dist/input/network-detail.js +35 -16
- package/dist/input/network-mock-tools.d.ts +0 -1
- package/dist/input/network-mock-tools.js +3 -4
- package/dist/input/network-mock.d.ts +0 -1
- package/dist/input/network-mock.js +0 -1
- package/dist/input/real-input.d.ts +14 -1
- package/dist/input/real-input.js +45 -3
- package/dist/input/scroll-find.d.ts +0 -1
- package/dist/input/scroll-find.js +0 -1
- package/dist/input/scroll-tools.d.ts +0 -1
- package/dist/input/scroll-tools.js +0 -1
- package/dist/input/viewport-tools.d.ts +0 -1
- package/dist/input/viewport-tools.js +3 -4
- package/dist/journal/ambient-store.d.ts +0 -1
- package/dist/journal/ambient-store.js +0 -1
- package/dist/journal/ambient.d.ts +0 -1
- package/dist/journal/ambient.js +0 -1
- package/dist/journal/attach-journal.d.ts +0 -1
- package/dist/journal/attach-journal.js +0 -1
- package/dist/journal/deviation-report.d.ts +0 -1
- package/dist/journal/deviation-report.js +0 -1
- package/dist/journal/deviation-service.d.ts +0 -1
- package/dist/journal/deviation-service.js +0 -1
- package/dist/journal/envelope-store.d.ts +0 -1
- package/dist/journal/envelope-store.js +0 -1
- package/dist/journal/envelope.d.ts +8 -9
- package/dist/journal/envelope.js +0 -1
- package/dist/journal/journal-query.d.ts +0 -1
- package/dist/journal/journal-query.js +0 -1
- package/dist/journal/journal-recorder.d.ts +0 -1
- package/dist/journal/journal-recorder.js +0 -1
- package/dist/journal/retention.d.ts +0 -1
- package/dist/journal/retention.js +0 -1
- package/dist/journal/rollups.d.ts +0 -1
- package/dist/journal/rollups.js +0 -1
- package/dist/journal/session-end.d.ts +0 -1
- package/dist/journal/session-end.js +0 -1
- package/dist/journal/session-journal.d.ts +0 -1
- package/dist/journal/session-journal.js +0 -1
- package/dist/license/license.d.ts +0 -1
- package/dist/license/license.js +0 -1
- package/dist/log.d.ts +0 -1
- package/dist/log.js +0 -1
- package/dist/mcp-proxy.d.ts +35 -4
- package/dist/mcp-proxy.js +174 -28
- package/dist/mcp.d.ts +15 -1
- package/dist/mcp.js +145 -17
- package/dist/oracles/flow-instrument-gaps.d.ts +0 -1
- package/dist/oracles/flow-instrument-gaps.js +0 -1
- package/dist/oracles/propose-consequences.d.ts +0 -1
- package/dist/oracles/propose-consequences.js +0 -1
- package/dist/oracles/self-instrument.d.ts +0 -1
- package/dist/oracles/self-instrument.js +0 -1
- package/dist/pairing-token.d.ts +0 -1
- package/dist/pairing-token.js +0 -1
- package/dist/phenomena/phenomena.d.ts +0 -1
- package/dist/phenomena/phenomena.js +0 -1
- package/dist/pool/browser-pool.d.ts +0 -1
- package/dist/pool/browser-pool.js +0 -1
- package/dist/pool/lease-reaper.d.ts +0 -1
- package/dist/pool/lease-reaper.js +0 -1
- package/dist/pool/playwright-launcher.d.ts +0 -1
- package/dist/pool/playwright-launcher.js +10 -2
- package/dist/project/baselines.d.ts +0 -1
- package/dist/project/baselines.js +0 -1
- package/dist/project/file-lock.d.ts +2 -1
- package/dist/project/file-lock.js +12 -2
- package/dist/project/fs-port.d.ts +0 -1
- package/dist/project/fs-port.js +0 -1
- package/dist/project/project-store.d.ts +0 -1
- package/dist/project/project-store.js +0 -1
- package/dist/project/project-tools.d.ts +0 -1
- package/dist/project/project-tools.js +29 -4
- package/dist/project/reticle-dir.d.ts +0 -1
- package/dist/project/reticle-dir.js +0 -1
- package/dist/runs/build-verification-run.d.ts +0 -1
- package/dist/runs/build-verification-run.js +0 -1
- package/dist/runs/profile-redact.d.ts +0 -1
- package/dist/runs/profile-redact.js +0 -1
- package/dist/runs/render-report.d.ts +0 -1
- package/dist/runs/render-report.js +0 -1
- package/dist/runs/repair-prompt.d.ts +0 -1
- package/dist/runs/repair-prompt.js +0 -1
- package/dist/runs/replay-mapping.d.ts +0 -1
- package/dist/runs/replay-mapping.js +0 -1
- package/dist/runs/reticle-runner.d.ts +0 -1
- package/dist/runs/reticle-runner.js +4 -2
- package/dist/runs/risk-classify.d.ts +0 -1
- package/dist/runs/risk-classify.js +0 -1
- package/dist/runs/run-diff.d.ts +0 -1
- package/dist/runs/run-diff.js +0 -1
- package/dist/runs/run-store.d.ts +0 -1
- package/dist/runs/run-store.js +0 -1
- package/dist/runs/run-tools.d.ts +0 -1
- package/dist/runs/run-tools.js +0 -1
- package/dist/runs/runner-port.d.ts +0 -1
- package/dist/runs/runner-port.js +0 -1
- package/dist/runs/verification-sync.d.ts +0 -1
- package/dist/runs/verification-sync.js +0 -1
- package/dist/runs/verify-http.d.ts +0 -1
- package/dist/runs/verify-http.js +0 -1
- package/dist/runs/verify-server.d.ts +0 -1
- package/dist/runs/verify-server.js +0 -1
- package/dist/server-version.d.ts +0 -1
- package/dist/server-version.js +0 -1
- package/dist/session/command-timeout.d.ts +35 -0
- package/dist/session/command-timeout.js +41 -0
- package/dist/session/control-envelope.d.ts +2 -3
- package/dist/session/control-envelope.js +2 -3
- package/dist/session/last-act.d.ts +31 -0
- package/dist/session/last-act.js +24 -0
- package/dist/session/live-control-tools.d.ts +0 -1
- package/dist/session/live-control-tools.js +3 -4
- package/dist/session/live-control.d.ts +0 -1
- package/dist/session/live-control.js +0 -1
- package/dist/session/observed-state.d.ts +12 -2
- package/dist/session/observed-state.js +29 -2
- package/dist/session/output-budget.d.ts +0 -1
- package/dist/session/output-budget.js +0 -1
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +36 -0
- package/dist/session/presenter-args.d.ts +0 -1
- package/dist/session/presenter-args.js +0 -1
- package/dist/session/review-store.d.ts +0 -1
- package/dist/session/review-store.js +0 -1
- package/dist/session/session-health.d.ts +26 -2
- package/dist/session/session-health.js +13 -1
- package/dist/session/session-info.d.ts +29 -0
- package/dist/session/session-info.js +1 -0
- package/dist/session/session-lease.d.ts +25 -0
- package/dist/session/session-lease.js +14 -0
- package/dist/session/session-manager.d.ts +7 -19
- package/dist/session/session-manager.js +35 -2
- package/dist/session/session-readiness.d.ts +0 -1
- package/dist/session/session-readiness.js +3 -4
- package/dist/session/session-reaper.d.ts +0 -1
- package/dist/session/session-reaper.js +0 -1
- package/dist/session/session-recommendation.d.ts +0 -1
- package/dist/session/session-recommendation.js +0 -1
- package/dist/session/session-tools.d.ts +0 -1
- package/dist/session/session-tools.js +2 -3
- package/dist/session/session.d.ts +33 -53
- package/dist/session/session.js +102 -66
- package/dist/session/state-select.d.ts +0 -1
- package/dist/session/state-select.js +0 -1
- package/dist/telemetry/argument-shape.d.ts +41 -0
- package/dist/telemetry/argument-shape.js +87 -0
- package/dist/telemetry/bug-found.d.ts +33 -0
- package/dist/telemetry/bug-found.js +95 -0
- package/dist/telemetry/cli-telemetry.d.ts +13 -0
- package/dist/telemetry/cli-telemetry.js +43 -0
- package/dist/telemetry/connect-failure.d.ts +16 -0
- package/dist/telemetry/connect-failure.js +44 -0
- package/dist/telemetry/daemon-telemetry.d.ts +19 -0
- package/dist/telemetry/daemon-telemetry.js +76 -0
- package/dist/telemetry/dev-repo.d.ts +10 -0
- package/dist/telemetry/dev-repo.js +80 -0
- package/dist/telemetry/error-fingerprint.d.ts +24 -0
- package/dist/telemetry/error-fingerprint.js +88 -0
- package/dist/telemetry/feedback-cli.d.ts +31 -0
- package/dist/telemetry/feedback-cli.js +102 -0
- package/dist/telemetry/feedback-context.d.ts +32 -0
- package/dist/telemetry/feedback-context.js +143 -0
- package/dist/telemetry/feedback.d.ts +66 -0
- package/dist/telemetry/feedback.js +175 -0
- package/dist/telemetry/git-facts.d.ts +21 -0
- package/dist/telemetry/git-facts.js +109 -0
- package/dist/telemetry/identify.d.ts +22 -0
- package/dist/telemetry/identify.js +73 -0
- package/dist/telemetry/init-telemetry.d.ts +26 -0
- package/dist/telemetry/init-telemetry.js +33 -0
- package/dist/telemetry/machine-snapshot.d.ts +6 -0
- package/dist/telemetry/machine-snapshot.js +39 -0
- package/dist/telemetry/mcp-connection.d.ts +5 -0
- package/dist/telemetry/mcp-connection.js +44 -0
- package/dist/telemetry/project-profile.d.ts +44 -0
- package/dist/telemetry/project-profile.js +205 -0
- package/dist/telemetry/run-telemetry.d.ts +21 -0
- package/dist/telemetry/run-telemetry.js +62 -0
- package/dist/telemetry/session-metrics.d.ts +103 -0
- package/dist/telemetry/session-metrics.js +329 -0
- package/dist/telemetry/telemetry.d.ts +35 -8
- package/dist/telemetry/telemetry.js +105 -12
- package/dist/token-auth.d.ts +0 -1
- package/dist/token-auth.js +0 -1
- package/dist/tools/act-capsule.d.ts +23 -0
- package/dist/tools/act-capsule.js +47 -0
- package/dist/tools/act-danger.d.ts +7 -0
- package/dist/tools/act-danger.js +44 -0
- package/dist/tools/act-helpers.d.ts +17 -0
- package/dist/tools/act-helpers.js +40 -0
- package/dist/tools/act-tools.d.ts +8 -1
- package/dist/tools/act-tools.js +96 -98
- package/dist/tools/act-view.d.ts +7 -1
- package/dist/tools/act-view.js +13 -1
- package/dist/tools/assert-grade.d.ts +22 -1
- package/dist/tools/assert-grade.js +46 -1
- package/dist/tools/assert-verdict.d.ts +21 -0
- package/dist/tools/assert-verdict.js +62 -0
- package/dist/tools/browser-tools.d.ts +0 -1
- package/dist/tools/browser-tools.js +2 -2
- package/dist/tools/contract-tools.d.ts +0 -1
- package/dist/tools/contract-tools.js +0 -1
- package/dist/tools/coverage-tools.d.ts +9 -0
- package/dist/tools/coverage-tools.js +92 -0
- package/dist/tools/dynamic-tools.d.ts +0 -1
- package/dist/tools/dynamic-tools.js +21 -2
- package/dist/tools/error-recovery.d.ts +18 -2
- package/dist/tools/error-recovery.js +42 -7
- package/dist/tools/feedback-tools.d.ts +24 -0
- package/dist/tools/feedback-tools.js +180 -0
- package/dist/tools/invoke-tool.d.ts +0 -1
- package/dist/tools/invoke-tool.js +115 -5
- package/dist/tools/lease-tools.d.ts +0 -1
- package/dist/tools/lease-tools.js +6 -5
- package/dist/tools/merge-tools.d.ts +0 -1
- package/dist/tools/merge-tools.js +0 -1
- package/dist/tools/observe-tools.d.ts +0 -1
- package/dist/tools/observe-tools.js +91 -39
- package/dist/tools/profiles.d.ts +1 -2
- package/dist/tools/profiles.js +43 -16
- package/dist/tools/query-paginate.d.ts +0 -1
- package/dist/tools/query-paginate.js +0 -1
- package/dist/tools/read-tools.d.ts +0 -1
- package/dist/tools/read-tools.js +14 -8
- package/dist/tools/reconcile-tools.d.ts +2 -0
- package/dist/tools/reconcile-tools.js +111 -0
- package/dist/tools/snapshot-delta.d.ts +0 -1
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/tool-invoker.d.ts +0 -1
- package/dist/tools/tool-invoker.js +0 -1
- package/dist/tools/tool-kit.d.ts +16 -1
- package/dist/tools/tool-kit.js +8 -2
- package/dist/tools/tool-names.d.ts +6 -1
- package/dist/tools/tool-names.js +6 -1
- package/dist/tools/tools-helpers.d.ts +0 -1
- package/dist/tools/tools-helpers.js +0 -1
- package/dist/tools/tools.d.ts +0 -1
- package/dist/tools/tools.js +24 -4
- package/dist/update/update-checker.d.ts +0 -1
- package/dist/update/update-checker.js +0 -1
- package/dist/update/update-nudge.d.ts +20 -0
- package/dist/update/update-nudge.js +72 -0
- package/dist/update/updater.d.ts +14 -1
- package/dist/update/updater.js +33 -2
- package/dist/visual/visual-diff.d.ts +0 -1
- package/dist/visual/visual-diff.js +0 -1
- package/dist/visual/visual-store.d.ts +0 -1
- package/dist/visual/visual-store.js +0 -1
- package/dist/visual/visual-tools.d.ts +0 -1
- package/dist/visual/visual-tools.js +103 -16
- package/package.json +2 -2
- package/dist/bridge-security.d.ts.map +0 -1
- package/dist/bridge-security.js.map +0 -1
- package/dist/bridge.d.ts.map +0 -1
- package/dist/bridge.js.map +0 -1
- package/dist/bridge.test-harness.d.ts.map +0 -1
- package/dist/bridge.test-harness.js.map +0 -1
- package/dist/capsule/capsule-store.d.ts.map +0 -1
- package/dist/capsule/capsule-store.js.map +0 -1
- package/dist/capsule/capsule.d.ts.map +0 -1
- package/dist/capsule/capsule.js.map +0 -1
- package/dist/capsule/causal-summary.d.ts.map +0 -1
- package/dist/capsule/causal-summary.js.map +0 -1
- package/dist/capsule/divergence.d.ts.map +0 -1
- package/dist/capsule/divergence.js.map +0 -1
- package/dist/capsule/minimize.d.ts.map +0 -1
- package/dist/capsule/minimize.js.map +0 -1
- package/dist/capsule/predicate-to-links.d.ts.map +0 -1
- package/dist/capsule/predicate-to-links.js.map +0 -1
- package/dist/cli-flow-commands.d.ts.map +0 -1
- package/dist/cli-flow-commands.js.map +0 -1
- package/dist/cli-launch.d.ts.map +0 -1
- package/dist/cli-launch.js.map +0 -1
- package/dist/cli-parse.d.ts.map +0 -1
- package/dist/cli-parse.js.map +0 -1
- package/dist/cli-port.d.ts.map +0 -1
- package/dist/cli-port.js.map +0 -1
- package/dist/cli-verify.d.ts.map +0 -1
- package/dist/cli-verify.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cloud/cloud-config.d.ts.map +0 -1
- package/dist/cloud/cloud-config.js.map +0 -1
- package/dist/cloud/cloud-sync.d.ts.map +0 -1
- package/dist/cloud/cloud-sync.js.map +0 -1
- package/dist/cloud-cli.d.ts.map +0 -1
- package/dist/cloud-cli.js.map +0 -1
- package/dist/crawl/crawl-tools.d.ts.map +0 -1
- package/dist/crawl/crawl-tools.js.map +0 -1
- package/dist/crawl/crawl.d.ts.map +0 -1
- package/dist/crawl/crawl.js.map +0 -1
- package/dist/daemon-resilience.d.ts.map +0 -1
- package/dist/daemon-resilience.js.map +0 -1
- package/dist/daemon.d.ts.map +0 -1
- package/dist/daemon.js.map +0 -1
- package/dist/domain/domain-model.d.ts.map +0 -1
- package/dist/domain/domain-model.js.map +0 -1
- package/dist/domain/domain-tools.d.ts.map +0 -1
- package/dist/domain/domain-tools.js.map +0 -1
- package/dist/domain/flow-risk.d.ts.map +0 -1
- package/dist/domain/flow-risk.js.map +0 -1
- package/dist/ee/audit-log.d.ts.map +0 -1
- package/dist/ee/audit-log.js.map +0 -1
- package/dist/events/event-filters.d.ts.map +0 -1
- package/dist/events/event-filters.js.map +0 -1
- package/dist/events/predicate-eval.d.ts.map +0 -1
- package/dist/events/predicate-eval.js.map +0 -1
- package/dist/events/predicate.d.ts.map +0 -1
- package/dist/events/predicate.js.map +0 -1
- package/dist/events/reaction.d.ts.map +0 -1
- package/dist/events/reaction.js.map +0 -1
- package/dist/events/ring-buffer.d.ts.map +0 -1
- package/dist/events/ring-buffer.js.map +0 -1
- package/dist/flows/affected.d.ts.map +0 -1
- package/dist/flows/affected.js.map +0 -1
- package/dist/flows/annotate-tools.d.ts.map +0 -1
- package/dist/flows/annotate-tools.js.map +0 -1
- package/dist/flows/annotate.d.ts.map +0 -1
- package/dist/flows/annotate.js.map +0 -1
- package/dist/flows/annotation-store.d.ts.map +0 -1
- package/dist/flows/annotation-store.js.map +0 -1
- package/dist/flows/assertion-integrity.d.ts.map +0 -1
- package/dist/flows/assertion-integrity.js.map +0 -1
- package/dist/flows/assertion-tiers-store.d.ts.map +0 -1
- package/dist/flows/assertion-tiers-store.js.map +0 -1
- package/dist/flows/buddy-status.d.ts.map +0 -1
- package/dist/flows/buddy-status.js.map +0 -1
- package/dist/flows/coverage.d.ts.map +0 -1
- package/dist/flows/coverage.js.map +0 -1
- package/dist/flows/decision.d.ts.map +0 -1
- package/dist/flows/decision.js.map +0 -1
- package/dist/flows/flake-store.d.ts.map +0 -1
- package/dist/flows/flake-store.js.map +0 -1
- package/dist/flows/flake.d.ts.map +0 -1
- package/dist/flows/flake.js.map +0 -1
- package/dist/flows/flow-classify.d.ts.map +0 -1
- package/dist/flows/flow-classify.js.map +0 -1
- package/dist/flows/flow-replay-run.d.ts.map +0 -1
- package/dist/flows/flow-replay-run.js.map +0 -1
- package/dist/flows/flow-replay.d.ts.map +0 -1
- package/dist/flows/flow-replay.js.map +0 -1
- package/dist/flows/flow-report.d.ts.map +0 -1
- package/dist/flows/flow-report.js.map +0 -1
- package/dist/flows/flow-scope.d.ts.map +0 -1
- package/dist/flows/flow-scope.js.map +0 -1
- package/dist/flows/flow-sources.d.ts.map +0 -1
- package/dist/flows/flow-sources.js.map +0 -1
- package/dist/flows/flow-success.d.ts.map +0 -1
- package/dist/flows/flow-success.js.map +0 -1
- package/dist/flows/flow-tools.d.ts.map +0 -1
- package/dist/flows/flow-tools.js.map +0 -1
- package/dist/flows/flows.d.ts.map +0 -1
- package/dist/flows/flows.js.map +0 -1
- package/dist/flows/gate.d.ts.map +0 -1
- package/dist/flows/gate.js.map +0 -1
- package/dist/flows/git-changed.d.ts.map +0 -1
- package/dist/flows/git-changed.js.map +0 -1
- package/dist/flows/heal-run.d.ts.map +0 -1
- package/dist/flows/heal-run.js.map +0 -1
- package/dist/flows/heal.d.ts.map +0 -1
- package/dist/flows/heal.js.map +0 -1
- package/dist/flows/parallel-suite.d.ts.map +0 -1
- package/dist/flows/parallel-suite.js.map +0 -1
- package/dist/flows/recordings.d.ts.map +0 -1
- package/dist/flows/recordings.js.map +0 -1
- package/dist/flows/replay.d.ts.map +0 -1
- package/dist/flows/replay.js.map +0 -1
- package/dist/flows/server-verify.d.ts.map +0 -1
- package/dist/flows/server-verify.js.map +0 -1
- package/dist/flows/watch-batcher.d.ts.map +0 -1
- package/dist/flows/watch-batcher.js.map +0 -1
- package/dist/honesty/blind-spots.d.ts.map +0 -1
- package/dist/honesty/blind-spots.js.map +0 -1
- package/dist/honesty/honesty.d.ts.map +0 -1
- package/dist/honesty/honesty.js.map +0 -1
- package/dist/http-server.d.ts.map +0 -1
- package/dist/http-server.js.map +0 -1
- package/dist/idle-shutdown.d.ts.map +0 -1
- package/dist/idle-shutdown.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init/agent-rules.d.ts.map +0 -1
- package/dist/init/agent-rules.js.map +0 -1
- package/dist/init/cursor.d.ts.map +0 -1
- package/dist/init/cursor.js.map +0 -1
- package/dist/init/detect.d.ts.map +0 -1
- package/dist/init/detect.js.map +0 -1
- package/dist/init/mcp.d.ts.map +0 -1
- package/dist/init/mcp.js.map +0 -1
- package/dist/init/node-io.d.ts.map +0 -1
- package/dist/init/node-io.js.map +0 -1
- package/dist/init/plan.d.ts.map +0 -1
- package/dist/init/plan.js.map +0 -1
- package/dist/init/project-id.d.ts.map +0 -1
- package/dist/init/project-id.js.map +0 -1
- package/dist/init/run.d.ts.map +0 -1
- package/dist/init/run.js.map +0 -1
- package/dist/init/snippets.d.ts.map +0 -1
- package/dist/init/snippets.js.map +0 -1
- package/dist/init/vite-config.d.ts.map +0 -1
- package/dist/init/vite-config.js.map +0 -1
- package/dist/input/network-detail.d.ts.map +0 -1
- package/dist/input/network-detail.js.map +0 -1
- package/dist/input/network-mock-tools.d.ts.map +0 -1
- package/dist/input/network-mock-tools.js.map +0 -1
- package/dist/input/network-mock.d.ts.map +0 -1
- package/dist/input/network-mock.js.map +0 -1
- package/dist/input/real-input.d.ts.map +0 -1
- package/dist/input/real-input.js.map +0 -1
- package/dist/input/scroll-find.d.ts.map +0 -1
- package/dist/input/scroll-find.js.map +0 -1
- package/dist/input/scroll-tools.d.ts.map +0 -1
- package/dist/input/scroll-tools.js.map +0 -1
- package/dist/input/viewport-tools.d.ts.map +0 -1
- package/dist/input/viewport-tools.js.map +0 -1
- package/dist/journal/ambient-store.d.ts.map +0 -1
- package/dist/journal/ambient-store.js.map +0 -1
- package/dist/journal/ambient.d.ts.map +0 -1
- package/dist/journal/ambient.js.map +0 -1
- package/dist/journal/attach-journal.d.ts.map +0 -1
- package/dist/journal/attach-journal.js.map +0 -1
- package/dist/journal/deviation-report.d.ts.map +0 -1
- package/dist/journal/deviation-report.js.map +0 -1
- package/dist/journal/deviation-service.d.ts.map +0 -1
- package/dist/journal/deviation-service.js.map +0 -1
- package/dist/journal/envelope-store.d.ts.map +0 -1
- package/dist/journal/envelope-store.js.map +0 -1
- package/dist/journal/envelope.d.ts.map +0 -1
- package/dist/journal/envelope.js.map +0 -1
- package/dist/journal/journal-query.d.ts.map +0 -1
- package/dist/journal/journal-query.js.map +0 -1
- package/dist/journal/journal-recorder.d.ts.map +0 -1
- package/dist/journal/journal-recorder.js.map +0 -1
- package/dist/journal/retention.d.ts.map +0 -1
- package/dist/journal/retention.js.map +0 -1
- package/dist/journal/rollups.d.ts.map +0 -1
- package/dist/journal/rollups.js.map +0 -1
- package/dist/journal/session-end.d.ts.map +0 -1
- package/dist/journal/session-end.js.map +0 -1
- package/dist/journal/session-journal.d.ts.map +0 -1
- package/dist/journal/session-journal.js.map +0 -1
- package/dist/license/license.d.ts.map +0 -1
- package/dist/license/license.js.map +0 -1
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js.map +0 -1
- package/dist/mcp-proxy.d.ts.map +0 -1
- package/dist/mcp-proxy.js.map +0 -1
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js.map +0 -1
- package/dist/oracles/flow-instrument-gaps.d.ts.map +0 -1
- package/dist/oracles/flow-instrument-gaps.js.map +0 -1
- package/dist/oracles/propose-consequences.d.ts.map +0 -1
- package/dist/oracles/propose-consequences.js.map +0 -1
- package/dist/oracles/self-instrument.d.ts.map +0 -1
- package/dist/oracles/self-instrument.js.map +0 -1
- package/dist/pairing-token.d.ts.map +0 -1
- package/dist/pairing-token.js.map +0 -1
- package/dist/phenomena/phenomena.d.ts.map +0 -1
- package/dist/phenomena/phenomena.js.map +0 -1
- package/dist/pool/browser-pool.d.ts.map +0 -1
- package/dist/pool/browser-pool.js.map +0 -1
- package/dist/pool/lease-reaper.d.ts.map +0 -1
- package/dist/pool/lease-reaper.js.map +0 -1
- package/dist/pool/playwright-launcher.d.ts.map +0 -1
- package/dist/pool/playwright-launcher.js.map +0 -1
- package/dist/project/baselines.d.ts.map +0 -1
- package/dist/project/baselines.js.map +0 -1
- package/dist/project/file-lock.d.ts.map +0 -1
- package/dist/project/file-lock.js.map +0 -1
- package/dist/project/fs-port.d.ts.map +0 -1
- package/dist/project/fs-port.js.map +0 -1
- package/dist/project/project-store.d.ts.map +0 -1
- package/dist/project/project-store.js.map +0 -1
- package/dist/project/project-tools.d.ts.map +0 -1
- package/dist/project/project-tools.js.map +0 -1
- package/dist/project/reticle-dir.d.ts.map +0 -1
- package/dist/project/reticle-dir.js.map +0 -1
- package/dist/runs/build-verification-run.d.ts.map +0 -1
- package/dist/runs/build-verification-run.js.map +0 -1
- package/dist/runs/profile-redact.d.ts.map +0 -1
- package/dist/runs/profile-redact.js.map +0 -1
- package/dist/runs/render-report.d.ts.map +0 -1
- package/dist/runs/render-report.js.map +0 -1
- package/dist/runs/repair-prompt.d.ts.map +0 -1
- package/dist/runs/repair-prompt.js.map +0 -1
- package/dist/runs/replay-mapping.d.ts.map +0 -1
- package/dist/runs/replay-mapping.js.map +0 -1
- package/dist/runs/reticle-runner.d.ts.map +0 -1
- package/dist/runs/reticle-runner.js.map +0 -1
- package/dist/runs/risk-classify.d.ts.map +0 -1
- package/dist/runs/risk-classify.js.map +0 -1
- package/dist/runs/run-diff.d.ts.map +0 -1
- package/dist/runs/run-diff.js.map +0 -1
- package/dist/runs/run-store.d.ts.map +0 -1
- package/dist/runs/run-store.js.map +0 -1
- package/dist/runs/run-tools.d.ts.map +0 -1
- package/dist/runs/run-tools.js.map +0 -1
- package/dist/runs/runner-port.d.ts.map +0 -1
- package/dist/runs/runner-port.js.map +0 -1
- package/dist/runs/verification-sync.d.ts.map +0 -1
- package/dist/runs/verification-sync.js.map +0 -1
- package/dist/runs/verify-http.d.ts.map +0 -1
- package/dist/runs/verify-http.js.map +0 -1
- package/dist/runs/verify-server.d.ts.map +0 -1
- package/dist/runs/verify-server.js.map +0 -1
- package/dist/server-version.d.ts.map +0 -1
- package/dist/server-version.js.map +0 -1
- package/dist/session/control-envelope.d.ts.map +0 -1
- package/dist/session/control-envelope.js.map +0 -1
- package/dist/session/live-control-tools.d.ts.map +0 -1
- package/dist/session/live-control-tools.js.map +0 -1
- package/dist/session/live-control.d.ts.map +0 -1
- package/dist/session/live-control.js.map +0 -1
- package/dist/session/observed-state.d.ts.map +0 -1
- package/dist/session/observed-state.js.map +0 -1
- package/dist/session/output-budget.d.ts.map +0 -1
- package/dist/session/output-budget.js.map +0 -1
- package/dist/session/presenter-args.d.ts.map +0 -1
- package/dist/session/presenter-args.js.map +0 -1
- package/dist/session/review-store.d.ts.map +0 -1
- package/dist/session/review-store.js.map +0 -1
- package/dist/session/session-health.d.ts.map +0 -1
- package/dist/session/session-health.js.map +0 -1
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/session/session-manager.js.map +0 -1
- package/dist/session/session-readiness.d.ts.map +0 -1
- package/dist/session/session-readiness.js.map +0 -1
- package/dist/session/session-reaper.d.ts.map +0 -1
- package/dist/session/session-reaper.js.map +0 -1
- package/dist/session/session-recommendation.d.ts.map +0 -1
- package/dist/session/session-recommendation.js.map +0 -1
- package/dist/session/session-tools.d.ts.map +0 -1
- package/dist/session/session-tools.js.map +0 -1
- package/dist/session/session.d.ts.map +0 -1
- package/dist/session/session.js.map +0 -1
- package/dist/session/state-select.d.ts.map +0 -1
- package/dist/session/state-select.js.map +0 -1
- package/dist/telemetry/telemetry.d.ts.map +0 -1
- package/dist/telemetry/telemetry.js.map +0 -1
- package/dist/token-auth.d.ts.map +0 -1
- package/dist/token-auth.js.map +0 -1
- package/dist/tools/act-tools.d.ts.map +0 -1
- package/dist/tools/act-tools.js.map +0 -1
- package/dist/tools/act-view.d.ts.map +0 -1
- package/dist/tools/act-view.js.map +0 -1
- package/dist/tools/assert-grade.d.ts.map +0 -1
- package/dist/tools/assert-grade.js.map +0 -1
- package/dist/tools/browser-tools.d.ts.map +0 -1
- package/dist/tools/browser-tools.js.map +0 -1
- package/dist/tools/contract-tools.d.ts.map +0 -1
- package/dist/tools/contract-tools.js.map +0 -1
- package/dist/tools/dynamic-tools.d.ts.map +0 -1
- package/dist/tools/dynamic-tools.js.map +0 -1
- package/dist/tools/error-recovery.d.ts.map +0 -1
- package/dist/tools/error-recovery.js.map +0 -1
- package/dist/tools/invoke-tool.d.ts.map +0 -1
- package/dist/tools/invoke-tool.js.map +0 -1
- package/dist/tools/lease-tools.d.ts.map +0 -1
- package/dist/tools/lease-tools.js.map +0 -1
- package/dist/tools/merge-tools.d.ts.map +0 -1
- package/dist/tools/merge-tools.js.map +0 -1
- package/dist/tools/observe-tools.d.ts.map +0 -1
- package/dist/tools/observe-tools.js.map +0 -1
- package/dist/tools/profiles.d.ts.map +0 -1
- package/dist/tools/profiles.js.map +0 -1
- package/dist/tools/query-paginate.d.ts.map +0 -1
- package/dist/tools/query-paginate.js.map +0 -1
- package/dist/tools/read-tools.d.ts.map +0 -1
- package/dist/tools/read-tools.js.map +0 -1
- package/dist/tools/snapshot-delta.d.ts.map +0 -1
- package/dist/tools/snapshot-delta.js.map +0 -1
- package/dist/tools/tool-invoker.d.ts.map +0 -1
- package/dist/tools/tool-invoker.js.map +0 -1
- package/dist/tools/tool-kit.d.ts.map +0 -1
- package/dist/tools/tool-kit.js.map +0 -1
- package/dist/tools/tool-names.d.ts.map +0 -1
- package/dist/tools/tool-names.js.map +0 -1
- package/dist/tools/tools-helpers.d.ts.map +0 -1
- package/dist/tools/tools-helpers.js.map +0 -1
- package/dist/tools/tools.d.ts.map +0 -1
- package/dist/tools/tools.js.map +0 -1
- package/dist/update/update-checker.d.ts.map +0 -1
- package/dist/update/update-checker.js.map +0 -1
- package/dist/update/updater.d.ts.map +0 -1
- package/dist/update/updater.js.map +0 -1
- package/dist/visual/visual-diff.d.ts.map +0 -1
- package/dist/visual/visual-diff.js.map +0 -1
- package/dist/visual/visual-store.d.ts.map +0 -1
- package/dist/visual/visual-store.js.map +0 -1
- package/dist/visual/visual-tools.d.ts.map +0 -1
- package/dist/visual/visual-tools.js.map +0 -1
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import { Verified } from '@reticlehq/core';
|
|
2
|
+
import { HonestyGrade } from './honesty.js';
|
|
3
|
+
export function decideVerified(inputs) {
|
|
4
|
+
const { pass, honesty, contradictions = [], settled, outcomePending, outcomeUnread } = inputs;
|
|
5
|
+
// A failed assertion is the most actionable fact there is; it leads.
|
|
6
|
+
if (pass === false) {
|
|
7
|
+
return { verified: Verified.NO, because: 'the declared consequence did not hold' };
|
|
8
|
+
}
|
|
9
|
+
// A contradiction outranks a passing assertion, and that inversion is the whole point: the case
|
|
10
|
+
// this product exists to catch is a green assertion sitting on top of a failed write. Measured on
|
|
11
|
+
// the bench app — `ui-advanced-request-failed` arrived with verdict.pass true and every other
|
|
12
|
+
// channel agreeing. Letting `pass` win there would report exactly the false green being detected.
|
|
13
|
+
if (contradictions.length > 0) {
|
|
14
|
+
const kinds = contradictions.map((c) => c.kind).join(', ');
|
|
15
|
+
return {
|
|
16
|
+
verified: Verified.NO,
|
|
17
|
+
because: `channels disagree about this action (${kinds}) even though the assertion passed`,
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
// Dirty capture is NOT failure. The layer could not see part of the window, so any green is a
|
|
21
|
+
// statement about what it happened to observe — which is precisely the thing that must not be
|
|
22
|
+
// reported as proof.
|
|
23
|
+
if (!honesty.integrity.clean) {
|
|
24
|
+
return {
|
|
25
|
+
verified: Verified.UNKNOWN,
|
|
26
|
+
because: `capture was not clean (${honesty.integrity.issues.join('; ')}), so a green here would only describe what was observed`,
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
// A vacuous green: nothing was actually proved. Grade NONE means no signal, no request, no state
|
|
30
|
+
// change and no element was pinned — the assertion could not have failed, which makes passing it
|
|
31
|
+
// evidence of nothing.
|
|
32
|
+
if (honesty.grade === HonestyGrade.NONE) {
|
|
33
|
+
return {
|
|
34
|
+
verified: Verified.UNKNOWN,
|
|
35
|
+
because: 'nothing was asserted at a real grade, so passing proves nothing — assert a signal, request, or state path',
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
// A `202 Accepted` is the server saying, in the only word HTTP has for it, that the outcome does
|
|
39
|
+
// not exist yet. Treating 2xx as success makes every asynchronous workflow verifiable at exactly
|
|
40
|
+
// the moment nothing has been decided.
|
|
41
|
+
//
|
|
42
|
+
// Measured on a logistics console with server-side reconciliation: a dispatch answered 202, the row
|
|
43
|
+
// optimistically rendered "dispatched", the page settled, and the verdict came back `yes` — then
|
|
44
|
+
// the server REVERTED it to `held` 1.2s later. Every channel agreed, and every channel was early.
|
|
45
|
+
// UNKNOWN rather than NO: nothing has failed, and saying it has would be its own false report.
|
|
46
|
+
if (outcomePending === true) {
|
|
47
|
+
return {
|
|
48
|
+
verified: Verified.UNKNOWN,
|
|
49
|
+
because: 'a write returned 202 Accepted, so the server has not finished processing it — this window cannot contain the outcome; re-check once it reconciles',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
// A write answered 2xx and its payload went unread, so the one channel that could contradict the
|
|
53
|
+
// screen was never opened. Reporting `yes` here means "no channel disagreed" — true only because a
|
|
54
|
+
// channel was closed. Measured on a shipments console: `POST /api/bulk-hold` → 200 with three of
|
|
55
|
+
// nine items failed inside the body, banner reading "9 shipments held", verdict `yes`.
|
|
56
|
+
//
|
|
57
|
+
// UNKNOWN, not NO: nothing is known to have failed. The remedy is in the sentence, because an
|
|
58
|
+
// agent that cannot act on a caveat will learn to skip it.
|
|
59
|
+
if (outcomeUnread === true) {
|
|
60
|
+
return {
|
|
61
|
+
verified: Verified.UNKNOWN,
|
|
62
|
+
because: 'a write returned 2xx with a response body that was never recorded, so its outcome is unread — a 200 describes the transport, not the result (a batch reports per-item failures in the body, and every GraphQL error is a 200). Enable it where your app calls connect(): `reticle.connect({ captureNetworkBodies: true })`, then re-run',
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
// Never settled: the page may still be moving, so the observation window may have closed early.
|
|
66
|
+
if (settled === false) {
|
|
67
|
+
return {
|
|
68
|
+
verified: Verified.UNKNOWN,
|
|
69
|
+
because: 'the page never settled, so the reaction window may have closed before the app finished',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// Partial coverage is a real caveat but not a blocker — it is reported in `honesty.coverage` and
|
|
73
|
+
// does not by itself make a graded, clean, uncontradicted pass untrustworthy.
|
|
74
|
+
//
|
|
75
|
+
// It must not be described as clean, though. This sentence said "over a clean capture" regardless,
|
|
76
|
+
// so a verdict could read `verified: yes ... over a clean capture` directly beside `coverage:
|
|
77
|
+
// partial` — the prose contradicting the evidence block next to it. Whichever a reader believes,
|
|
78
|
+
// one of them lied, and the whole point of this layer is that the sentence can be trusted on its
|
|
79
|
+
// own. Seen on a one-way IPC send: coverage said the outcome was unobservable, `because` said clean.
|
|
80
|
+
return {
|
|
81
|
+
verified: Verified.YES,
|
|
82
|
+
because: honesty.coverage?.partial === true
|
|
83
|
+
? `assertion held at ${honesty.grade} grade with no channel disagreeing, but coverage was PARTIAL — see \`coverage\` for what went unobserved`
|
|
84
|
+
: `assertion held at ${honesty.grade} grade over a clean capture with no channel disagreeing`,
|
|
85
|
+
};
|
|
86
|
+
}
|
package/dist/http-server.d.ts
CHANGED
package/dist/http-server.js
CHANGED
|
@@ -2,6 +2,7 @@ import * as http from 'node:http';
|
|
|
2
2
|
import { SSEServerTransport } from '@modelcontextprotocol/sdk/server/sse.js';
|
|
3
3
|
import { MCP_SSE_PATH, MCP_MESSAGE_PATH, STATUS_PATH } from '@reticlehq/core';
|
|
4
4
|
import { log } from './log.js';
|
|
5
|
+
import { reportMcpConnected } from './telemetry/mcp-connection.js';
|
|
5
6
|
import { isLoopbackHost, isLocalWebOrigin, isLoopbackPeer, requestToken, tokensMatch, } from './token-auth.js';
|
|
6
7
|
/**
|
|
7
8
|
* Creates a shared HTTP server that handles both the WebSocket bridge (browser SDK) and the
|
|
@@ -84,6 +85,10 @@ export function createSharedServer(options = {}) {
|
|
|
84
85
|
.connect(transport)
|
|
85
86
|
.then(() => {
|
|
86
87
|
log('mcp_client_connected', { sessionId: sid });
|
|
88
|
+
// The one signal that separates "Reticle is running" from "somebody is USING it": a daemon
|
|
89
|
+
// can sit up for days with nothing attached. It also exposes reconnect churn, which is
|
|
90
|
+
// indistinguishable from healthy usage in every other metric.
|
|
91
|
+
reportMcpConnected();
|
|
87
92
|
})
|
|
88
93
|
.catch((err) => {
|
|
89
94
|
const message = err instanceof Error ? err.message : String(err);
|
|
@@ -138,4 +143,3 @@ export function createSharedServer(options = {}) {
|
|
|
138
143
|
}
|
|
139
144
|
return { httpServer, attachMcp, attachStatus, attachAgentPresence, close };
|
|
140
145
|
}
|
|
141
|
-
//# sourceMappingURL=http-server.js.map
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate many crawl runs into the one number the core claim needs.
|
|
3
|
+
*
|
|
4
|
+
* Detection already exists: `reticle_crawl` drives every reachable control and reports contradictions
|
|
5
|
+
* — two channels disagreeing about the same click. It found `swallowed-500-login` and, separately,
|
|
6
|
+
* `ui-advanced-request-failed` on a control whose assertion was green, neither of them planted.
|
|
7
|
+
*
|
|
8
|
+
* What was missing is the arithmetic that turns those into evidence. The claim worth making is not
|
|
9
|
+
* "Reticle can find bugs"; it is:
|
|
10
|
+
*
|
|
11
|
+
* "Run over N already-merged, already-green changes, it found X real bugs their own tests
|
|
12
|
+
* certified as passing."
|
|
13
|
+
*
|
|
14
|
+
* That needs no control arm, which is why it is the cheapest credible proof available: the
|
|
15
|
+
* counterfactual is already established, because those changes SHIPPED. An A/B is the second study,
|
|
16
|
+
* and this tells you where to point it.
|
|
17
|
+
*
|
|
18
|
+
* Pure functions over already-collected reports — the driving is `reticle_crawl`'s job, and running
|
|
19
|
+
* it across a commit range is a shell loop. This is only the part that must not be done by eye.
|
|
20
|
+
*/
|
|
21
|
+
/** The contradiction kinds — cross-channel disagreement, as opposed to a single-channel fault. */
|
|
22
|
+
export declare const CONTRADICTION_KINDS: readonly string[];
|
|
23
|
+
export interface HuntAnomaly {
|
|
24
|
+
kind: string;
|
|
25
|
+
ref?: string;
|
|
26
|
+
desc?: string;
|
|
27
|
+
detail?: string;
|
|
28
|
+
}
|
|
29
|
+
/** One crawl over one checkout. `label` is whatever identifies it — a commit sha, a PR number. */
|
|
30
|
+
export interface HuntRun {
|
|
31
|
+
label: string;
|
|
32
|
+
anomalies: readonly HuntAnomaly[];
|
|
33
|
+
/** Controls actually driven. A run that drove nothing proves nothing and is reported separately. */
|
|
34
|
+
stepsRun?: number;
|
|
35
|
+
}
|
|
36
|
+
export interface HuntSummary {
|
|
37
|
+
runs: number;
|
|
38
|
+
/** Runs that actually drove at least one control. The denominator that can honestly be quoted. */
|
|
39
|
+
runsWithCoverage: number;
|
|
40
|
+
/** Runs where at least one CONTRADICTION was found — the headline numerator. */
|
|
41
|
+
runsWithContradictions: number;
|
|
42
|
+
contradictions: number;
|
|
43
|
+
/** Single-channel faults (console errors, failed requests, dead controls). Context, not the claim. */
|
|
44
|
+
singleChannelFaults: number;
|
|
45
|
+
byKind: Record<string, number>;
|
|
46
|
+
/** Labels with contradictions, so each one can be confirmed by hand before it is counted. */
|
|
47
|
+
flagged: string[];
|
|
48
|
+
headline: string;
|
|
49
|
+
}
|
|
50
|
+
export declare function summarizeHunt(runs: readonly HuntRun[]): HuntSummary;
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Aggregate many crawl runs into the one number the core claim needs.
|
|
3
|
+
*
|
|
4
|
+
* Detection already exists: `reticle_crawl` drives every reachable control and reports contradictions
|
|
5
|
+
* — two channels disagreeing about the same click. It found `swallowed-500-login` and, separately,
|
|
6
|
+
* `ui-advanced-request-failed` on a control whose assertion was green, neither of them planted.
|
|
7
|
+
*
|
|
8
|
+
* What was missing is the arithmetic that turns those into evidence. The claim worth making is not
|
|
9
|
+
* "Reticle can find bugs"; it is:
|
|
10
|
+
*
|
|
11
|
+
* "Run over N already-merged, already-green changes, it found X real bugs their own tests
|
|
12
|
+
* certified as passing."
|
|
13
|
+
*
|
|
14
|
+
* That needs no control arm, which is why it is the cheapest credible proof available: the
|
|
15
|
+
* counterfactual is already established, because those changes SHIPPED. An A/B is the second study,
|
|
16
|
+
* and this tells you where to point it.
|
|
17
|
+
*
|
|
18
|
+
* Pure functions over already-collected reports — the driving is `reticle_crawl`'s job, and running
|
|
19
|
+
* it across a commit range is a shell loop. This is only the part that must not be done by eye.
|
|
20
|
+
*/
|
|
21
|
+
/** The contradiction kinds — cross-channel disagreement, as opposed to a single-channel fault. */
|
|
22
|
+
export const CONTRADICTION_KINDS = [
|
|
23
|
+
'ui-advanced-request-failed',
|
|
24
|
+
'signal-contradicted',
|
|
25
|
+
'response-ignored',
|
|
26
|
+
'duplicate-request',
|
|
27
|
+
'request-never-settled',
|
|
28
|
+
'failure-misattributed',
|
|
29
|
+
];
|
|
30
|
+
const isContradiction = (kind) => CONTRADICTION_KINDS.includes(kind);
|
|
31
|
+
export function summarizeHunt(runs) {
|
|
32
|
+
const byKind = {};
|
|
33
|
+
const flagged = [];
|
|
34
|
+
let contradictions = 0;
|
|
35
|
+
let singleChannelFaults = 0;
|
|
36
|
+
let runsWithCoverage = 0;
|
|
37
|
+
for (const run of runs) {
|
|
38
|
+
// A run that drove nothing is not evidence of cleanliness. Counting it in the denominator would
|
|
39
|
+
// dilute the rate with checkouts where the app never even came up — the arithmetic equivalent of
|
|
40
|
+
// reporting a green because no test ran.
|
|
41
|
+
if ((run.stepsRun ?? 0) > 0)
|
|
42
|
+
runsWithCoverage += 1;
|
|
43
|
+
let flaggedThisRun = false;
|
|
44
|
+
for (const anomaly of run.anomalies) {
|
|
45
|
+
byKind[anomaly.kind] = (byKind[anomaly.kind] ?? 0) + 1;
|
|
46
|
+
if (isContradiction(anomaly.kind)) {
|
|
47
|
+
contradictions += 1;
|
|
48
|
+
flaggedThisRun = true;
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
singleChannelFaults += 1;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (flaggedThisRun)
|
|
55
|
+
flagged.push(run.label);
|
|
56
|
+
}
|
|
57
|
+
return {
|
|
58
|
+
runs: runs.length,
|
|
59
|
+
runsWithCoverage,
|
|
60
|
+
runsWithContradictions: flagged.length,
|
|
61
|
+
contradictions,
|
|
62
|
+
singleChannelFaults,
|
|
63
|
+
byKind,
|
|
64
|
+
flagged,
|
|
65
|
+
headline: buildHeadline(runsWithCoverage, flagged.length, contradictions),
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* The sentence that goes in front of someone, phrased so it cannot overstate itself.
|
|
70
|
+
*
|
|
71
|
+
* It counts CHECKOUTS with a finding rather than raw findings, because one broken control clicked
|
|
72
|
+
* five times is one bug and five anomalies. It also says "candidate": every flag still has to be
|
|
73
|
+
* confirmed by hand before it is a bug, and a number that skips that step is the kind of evidence
|
|
74
|
+
* this project exists to distrust.
|
|
75
|
+
*/
|
|
76
|
+
function buildHeadline(withCoverage, flaggedRuns, contradictions) {
|
|
77
|
+
if (withCoverage === 0) {
|
|
78
|
+
return 'no run drove a single control — nothing was measured, which is not the same as nothing being wrong';
|
|
79
|
+
}
|
|
80
|
+
if (flaggedRuns === 0) {
|
|
81
|
+
return `${String(withCoverage)} merged changes crawled, no cross-channel contradictions found — confirm coverage was real before reading this as clean`;
|
|
82
|
+
}
|
|
83
|
+
return `${String(flaggedRuns)} of ${String(withCoverage)} merged, already-green changes carried a candidate false green (${String(contradictions)} contradictions) — each needs manual confirmation before it is counted`;
|
|
84
|
+
}
|
package/dist/idle-shutdown.d.ts
CHANGED
package/dist/idle-shutdown.js
CHANGED
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
|
@@ -35,4 +35,3 @@ export declare function markedBlock(): string;
|
|
|
35
35
|
export declare function mergeMarkedInstruction(existing: string | null | undefined): AgentRuleResult;
|
|
36
36
|
/** The Cursor rule file (.mdc): `alwaysApply` keeps the rule in every turn's context. */
|
|
37
37
|
export declare function cursorRuleFile(): string;
|
|
38
|
-
//# sourceMappingURL=agent-rules.d.ts.map
|
package/dist/init/agent-rules.js
CHANGED
|
@@ -27,7 +27,10 @@ This app is instrumented by **Reticle** — an in-app verification layer exposed
|
|
|
27
27
|
- **How:** drive the actual flow (\`reticle_act\` / \`reticle_act_and_wait\`), then read the observable effect (\`reticle_assert\`, \`reticle_snapshot\`, \`reticle_state\`, \`reticle_network\`). Confirm the change produced the effect it was meant to, with no new console errors or failed requests.
|
|
28
28
|
- **Covered flows:** run \`reticle gate\` — it reports which recorded flows the changed files affect and whether they still pass.
|
|
29
29
|
- **Never weaken a check to make it green.** Downgrading, skipping, or deleting an assertion is a finding, not a fix.
|
|
30
|
-
- **If Reticle can't run** (no daemon, or this is not a running web app), say so — do not skip verification silently
|
|
30
|
+
- **If Reticle can't run** (no daemon, or this is not a running web app), say so — do not skip verification silently.
|
|
31
|
+
- **If a tool result carries \`update_available\`, say so.** Reticle checked npm and a newer version exists. Tell the human the version numbers and offer to run \`reticle update\` — between tasks, never mid-verification, because it restarts the daemon and drops the session. Finish what you are doing first.
|
|
32
|
+
- **Wish Reticle could do something? Ask for it with \`reticle_feedback\`.** Reticle is built for agents, so what you find awkward or missing is what decides the roadmap — and you are the only one who can report it, because that thought disappears when your context does. File \`feature_request\` for something that does not exist, \`improvement\` for something that works but costs too many calls. Say what you are actually trying to achieve (\`need\`) and how you work around it today (\`currentApproach\`), and set \`model\` to the model you are running. File it the moment you notice, then carry on — nothing is too minor.
|
|
33
|
+
- **If Reticle itself fails you, tell its maintainers with \`reticle_feedback\`.** A tool that returned something wrong, a thing Reticle could not observe at all, or a verdict you could not act on — file it with a root-cause analysis and the call trace, then carry on with the task. Working around a broken tool in silence is how the same defect survives. This is about defects in *Reticle*; a bug you find in *this app* is Reticle working, and belongs in your report to the user instead.`;
|
|
31
34
|
export const AgentRuleStatus = {
|
|
32
35
|
APPLY: 'apply',
|
|
33
36
|
ALREADY: 'already',
|
|
@@ -62,4 +65,3 @@ alwaysApply: true
|
|
|
62
65
|
${RULE_BODY}
|
|
63
66
|
`;
|
|
64
67
|
}
|
|
65
|
-
//# sourceMappingURL=agent-rules.js.map
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the app can be driven by: its `data-testid` values, and which state library holds its truth.
|
|
3
|
+
*
|
|
4
|
+
* `init` wired none of this, so every app came up with `hasCapabilities: false`, empty capabilities,
|
|
5
|
+
* and a `reticle_state` holding nothing but `__reticle_renders` — the state-truth read that SKILL.md
|
|
6
|
+
* calls the highest-value line was unavailable on every app out of the box. Measured across six.
|
|
7
|
+
*
|
|
8
|
+
* Testids are scanned rather than asked for. Stores are NAMED but not wired: detecting that an app
|
|
9
|
+
* depends on zustand is easy, knowing which module exports the store instance is not, and generating
|
|
10
|
+
* a wrong import would break the dev module that everything else now hangs off.
|
|
11
|
+
*/
|
|
12
|
+
/** Cap the generated list. A capabilities block is a hint for an agent, not an inventory. */
|
|
13
|
+
export declare const MAX_TESTIDS = 60;
|
|
14
|
+
/** Every distinct `data-testid` literal in the given sources, in first-seen order. */
|
|
15
|
+
export declare function scanTestids(sources: readonly string[]): string[];
|
|
16
|
+
/** The store libraries this app depends on, as ready-to-uncomment registration lines. */
|
|
17
|
+
export declare function storeHints(deps: ReadonlySet<string>): string[];
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the app can be driven by: its `data-testid` values, and which state library holds its truth.
|
|
3
|
+
*
|
|
4
|
+
* `init` wired none of this, so every app came up with `hasCapabilities: false`, empty capabilities,
|
|
5
|
+
* and a `reticle_state` holding nothing but `__reticle_renders` — the state-truth read that SKILL.md
|
|
6
|
+
* calls the highest-value line was unavailable on every app out of the box. Measured across six.
|
|
7
|
+
*
|
|
8
|
+
* Testids are scanned rather than asked for. Stores are NAMED but not wired: detecting that an app
|
|
9
|
+
* depends on zustand is easy, knowing which module exports the store instance is not, and generating
|
|
10
|
+
* a wrong import would break the dev module that everything else now hangs off.
|
|
11
|
+
*/
|
|
12
|
+
/** `data-testid="foo"` / `data-testid='foo'` / `data-testid={"foo"}` — the forms people actually write. */
|
|
13
|
+
const TESTID_ATTR = /data-testid\s*=\s*[{]?\s*["'`]([^"'`]+)["'`]/g;
|
|
14
|
+
/** Cap the generated list. A capabilities block is a hint for an agent, not an inventory. */
|
|
15
|
+
export const MAX_TESTIDS = 60;
|
|
16
|
+
/** Every distinct `data-testid` literal in the given sources, in first-seen order. */
|
|
17
|
+
export function scanTestids(sources) {
|
|
18
|
+
const found = new Set();
|
|
19
|
+
for (const src of sources) {
|
|
20
|
+
for (const m of src.matchAll(TESTID_ATTR)) {
|
|
21
|
+
const id = m[1];
|
|
22
|
+
if (id !== undefined && id.length > 0)
|
|
23
|
+
found.add(id);
|
|
24
|
+
if (found.size >= MAX_TESTIDS)
|
|
25
|
+
return [...found];
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return [...found];
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* State libraries the browser SDK has an adapter for, in the order we would recommend registering
|
|
32
|
+
* them. TanStack Query is first on purpose: a stale cache served as fresh fires NO network request,
|
|
33
|
+
* so the network log shows silence and the DOM shows a plausible number — the cache is the only
|
|
34
|
+
* witness, which makes it the highest-value store in the list and the least obvious one to add.
|
|
35
|
+
*/
|
|
36
|
+
const STORE_LIBRARIES = [
|
|
37
|
+
['@tanstack/react-query', "registerStore('queries', tanstackQueryStore(queryClient))"],
|
|
38
|
+
['zustand', "registerStore('app', useStore) // pass the store itself, not () => store.getState()"],
|
|
39
|
+
['@reduxjs/toolkit', "registerStore('app', store)"],
|
|
40
|
+
['redux', "registerStore('app', store)"],
|
|
41
|
+
['jotai', "registerStore('app', jotaiStore(getDefaultStore(), { cart, user }))"],
|
|
42
|
+
['valtio', "registerStore('app', valtioStore(state))"],
|
|
43
|
+
['mobx', "registerStore('app', mobxStore(state))"],
|
|
44
|
+
['xstate', "registerStore('machine', xstateStore(actor))"],
|
|
45
|
+
['pinia', "registerStore('cart', piniaStore(useCartStore()))"],
|
|
46
|
+
['svelte', "registerStore('cart', svelteStore(cartStore))"],
|
|
47
|
+
];
|
|
48
|
+
/** The store libraries this app depends on, as ready-to-uncomment registration lines. */
|
|
49
|
+
export function storeHints(deps) {
|
|
50
|
+
return STORE_LIBRARIES.filter(([dep]) => deps.has(dep)).map(([, hint]) => hint);
|
|
51
|
+
}
|
package/dist/init/cursor.d.ts
CHANGED
package/dist/init/cursor.js
CHANGED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Setup RCA for desktop apps.
|
|
3
|
+
*
|
|
4
|
+
* Every failure this catches is SILENT. A Tauri app with the default CSP runs perfectly and simply
|
|
5
|
+
* never appears in `reticle status` — the WebSocket is blocked before it opens, and nothing in the
|
|
6
|
+
* app's own console says so. An Electron app missing the preload line works fine and reports zero
|
|
7
|
+
* network activity forever, which reads as "the app makes no backend calls" rather than "you are
|
|
8
|
+
* blind to all of them".
|
|
9
|
+
*
|
|
10
|
+
* Silent misconfiguration is the same disease as a false green: the tool answers confidently and the
|
|
11
|
+
* answer is wrong. So the diagnosis names the file, the reason, and the exact line to add.
|
|
12
|
+
*
|
|
13
|
+
* Pure: a `read` function in, findings out. No fs, no cwd, no process.
|
|
14
|
+
*/
|
|
15
|
+
export declare const DesktopFinding: {
|
|
16
|
+
/** Tauri's CSP will block the bridge WebSocket — the app will never connect, with no error. */
|
|
17
|
+
readonly TAURI_CSP_BLOCKS_BRIDGE: "tauri-csp-blocks-bridge";
|
|
18
|
+
/** A custom CSP dropped the `ipc:` source Tauri needs for `invoke` itself. */
|
|
19
|
+
readonly TAURI_CSP_BLOCKS_IPC: "tauri-csp-blocks-ipc";
|
|
20
|
+
/** The preload never requires the shim, so every IPC call is invisible. */
|
|
21
|
+
readonly ELECTRON_PRELOAD_MISSING: "electron-preload-missing";
|
|
22
|
+
/** The main process never installs the capture helper, so screenshots are unavailable. */
|
|
23
|
+
readonly ELECTRON_CAPTURE_MISSING: "electron-capture-missing";
|
|
24
|
+
};
|
|
25
|
+
export type DesktopFinding = (typeof DesktopFinding)[keyof typeof DesktopFinding];
|
|
26
|
+
export interface DesktopDiagnosis {
|
|
27
|
+
code: DesktopFinding;
|
|
28
|
+
/** Which file to look at. */
|
|
29
|
+
file: string;
|
|
30
|
+
/** What is wrong, in one line. */
|
|
31
|
+
problem: string;
|
|
32
|
+
/** Exactly what to add — copy-pasteable, with the port actually in use. */
|
|
33
|
+
fix: string;
|
|
34
|
+
}
|
|
35
|
+
/** Reads a project-relative path. Undefined means the file does not exist. */
|
|
36
|
+
export type ReadFile = (path: string) => string | undefined;
|
|
37
|
+
/** Is this project a desktop shell at all? Used to print a positive result instead of silence. */
|
|
38
|
+
export declare function isDesktopProject(read: ReadFile): boolean;
|
|
39
|
+
/** Which desktop shell (if any) this project is, and what is missing from its Reticle wiring. */
|
|
40
|
+
export declare function diagnoseDesktop(read: ReadFile, port: number): DesktopDiagnosis[];
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
import { RETICLE_IPC_GLOBAL } from '@reticlehq/core';
|
|
2
|
+
/**
|
|
3
|
+
* Setup RCA for desktop apps.
|
|
4
|
+
*
|
|
5
|
+
* Every failure this catches is SILENT. A Tauri app with the default CSP runs perfectly and simply
|
|
6
|
+
* never appears in `reticle status` — the WebSocket is blocked before it opens, and nothing in the
|
|
7
|
+
* app's own console says so. An Electron app missing the preload line works fine and reports zero
|
|
8
|
+
* network activity forever, which reads as "the app makes no backend calls" rather than "you are
|
|
9
|
+
* blind to all of them".
|
|
10
|
+
*
|
|
11
|
+
* Silent misconfiguration is the same disease as a false green: the tool answers confidently and the
|
|
12
|
+
* answer is wrong. So the diagnosis names the file, the reason, and the exact line to add.
|
|
13
|
+
*
|
|
14
|
+
* Pure: a `read` function in, findings out. No fs, no cwd, no process.
|
|
15
|
+
*/
|
|
16
|
+
export const DesktopFinding = {
|
|
17
|
+
/** Tauri's CSP will block the bridge WebSocket — the app will never connect, with no error. */
|
|
18
|
+
TAURI_CSP_BLOCKS_BRIDGE: 'tauri-csp-blocks-bridge',
|
|
19
|
+
/** A custom CSP dropped the `ipc:` source Tauri needs for `invoke` itself. */
|
|
20
|
+
TAURI_CSP_BLOCKS_IPC: 'tauri-csp-blocks-ipc',
|
|
21
|
+
/** The preload never requires the shim, so every IPC call is invisible. */
|
|
22
|
+
ELECTRON_PRELOAD_MISSING: 'electron-preload-missing',
|
|
23
|
+
/** The main process never installs the capture helper, so screenshots are unavailable. */
|
|
24
|
+
ELECTRON_CAPTURE_MISSING: 'electron-capture-missing',
|
|
25
|
+
};
|
|
26
|
+
const TAURI_CONF = 'src-tauri/tauri.conf.json';
|
|
27
|
+
const PRELOAD_REQUIRE = '@reticlehq/electron/preload';
|
|
28
|
+
const CAPTURE_REQUIRE = '@reticlehq/electron/main';
|
|
29
|
+
function parseJson(text) {
|
|
30
|
+
if (text === undefined)
|
|
31
|
+
return undefined;
|
|
32
|
+
try {
|
|
33
|
+
const parsed = JSON.parse(text);
|
|
34
|
+
return typeof parsed === 'object' && parsed !== null
|
|
35
|
+
? parsed
|
|
36
|
+
: undefined;
|
|
37
|
+
}
|
|
38
|
+
catch {
|
|
39
|
+
return undefined; // a malformed config is the app's problem, not something to crash the doctor on
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
function record(value) {
|
|
43
|
+
return typeof value === 'object' && value !== null ? value : {};
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Does this CSP permit the bridge WebSocket on `port`?
|
|
47
|
+
*
|
|
48
|
+
* A MISSING csp key is treated as blocking, not permissive: Tauri applies a restrictive default, so
|
|
49
|
+
* reporting "no CSP, therefore fine" would be precisely the false green this tool exists to prevent.
|
|
50
|
+
*/
|
|
51
|
+
function cspAllowsBridge(csp, port) {
|
|
52
|
+
if (csp === undefined)
|
|
53
|
+
return false;
|
|
54
|
+
const exact = `ws://localhost:${String(port)}`;
|
|
55
|
+
const loopback = `ws://127.0.0.1:${String(port)}`;
|
|
56
|
+
// A BARE `ws:` scheme source allows any ws origin. It must be matched as a whole source, not as a
|
|
57
|
+
// substring: `includes('ws:')` also matches `ws://localhost:4400`, which would make every port
|
|
58
|
+
// look allowed and silently defeat the port check this function exists to perform.
|
|
59
|
+
const bareScheme = /(^|[\s;])ws:(?!\/\/)/.test(csp);
|
|
60
|
+
return (csp.includes(exact) ||
|
|
61
|
+
csp.includes(loopback) ||
|
|
62
|
+
csp.includes('ws://localhost:*') ||
|
|
63
|
+
csp.includes('ws://127.0.0.1:*') ||
|
|
64
|
+
bareScheme);
|
|
65
|
+
}
|
|
66
|
+
/** Tauri v2 needs `ipc:`/`http://ipc.localhost` in connect-src for `invoke` to work at all. */
|
|
67
|
+
function cspAllowsIpc(csp) {
|
|
68
|
+
return csp.includes('ipc:') || csp.includes('ipc.localhost');
|
|
69
|
+
}
|
|
70
|
+
function diagnoseTauri(read, port) {
|
|
71
|
+
const conf = parseJson(read(TAURI_CONF));
|
|
72
|
+
if (conf === undefined)
|
|
73
|
+
return [];
|
|
74
|
+
const security = record(record(conf['app'])['security']);
|
|
75
|
+
const csp = typeof security['csp'] === 'string' ? security['csp'] : undefined;
|
|
76
|
+
const findings = [];
|
|
77
|
+
if (!cspAllowsBridge(csp, port)) {
|
|
78
|
+
findings.push({
|
|
79
|
+
code: DesktopFinding.TAURI_CSP_BLOCKS_BRIDGE,
|
|
80
|
+
file: TAURI_CONF,
|
|
81
|
+
problem: csp === undefined
|
|
82
|
+
? "no `app.security.csp` set, so Tauri's restrictive default applies and blocks the Reticle bridge — the app will run normally and never connect"
|
|
83
|
+
: 'the CSP `connect-src` does not allow the Reticle bridge WebSocket — the app will run normally and never connect',
|
|
84
|
+
fix: `add to app.security.csp connect-src: ws://localhost:${String(port)}`,
|
|
85
|
+
});
|
|
86
|
+
}
|
|
87
|
+
if (csp !== undefined && !cspAllowsIpc(csp)) {
|
|
88
|
+
findings.push({
|
|
89
|
+
code: DesktopFinding.TAURI_CSP_BLOCKS_IPC,
|
|
90
|
+
file: TAURI_CONF,
|
|
91
|
+
problem: 'the CSP dropped the `ipc:` source Tauri needs — `invoke` itself will fail',
|
|
92
|
+
fix: 'add to app.security.csp connect-src: ipc: http://ipc.localhost',
|
|
93
|
+
});
|
|
94
|
+
}
|
|
95
|
+
return findings;
|
|
96
|
+
}
|
|
97
|
+
/** The directory portion of a path, without pulling in node:path (this module stays pure). */
|
|
98
|
+
function dirOf(path) {
|
|
99
|
+
const cut = path.lastIndexOf('/');
|
|
100
|
+
return cut < 0 ? '' : path.slice(0, cut + 1);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Where a preload SOURCE might live, in the order worth trying.
|
|
104
|
+
*
|
|
105
|
+
* Beside `main` first (the unbundled layout), then the usual source directories — a bundled setup
|
|
106
|
+
* points `main` at `out/` or `dist/` while the real preload stays in `src/` or `electron/`.
|
|
107
|
+
*/
|
|
108
|
+
function preloadCandidates(mainDir) {
|
|
109
|
+
const names = ['preload.cjs', 'preload.js', 'preload.mjs', 'preload.ts', 'preload.mts'];
|
|
110
|
+
const dirs = [mainDir, 'electron/', 'src/', 'src/preload/', 'src/main/', ''];
|
|
111
|
+
return dirs.flatMap((dir) => names.map((name) => `${dir}${name}`));
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Where a BUNDLED preload's output lands. electron-vite's default layout mirrors `out/main` with
|
|
115
|
+
* `out/preload`; Forge and hand-rolled setups favour `dist`/`build`.
|
|
116
|
+
*/
|
|
117
|
+
function bundledPreloadCandidates(mainDir) {
|
|
118
|
+
const roots = [mainDir.replace(/main\/?$/, ''), 'out/', 'dist/', 'build/', '.vite/build/'];
|
|
119
|
+
const names = [
|
|
120
|
+
'preload/index.js',
|
|
121
|
+
'preload/index.mjs',
|
|
122
|
+
'preload/index.cjs',
|
|
123
|
+
'preload.js',
|
|
124
|
+
'preload.mjs',
|
|
125
|
+
'preload.cjs',
|
|
126
|
+
];
|
|
127
|
+
return roots.flatMap((root) => names.map((name) => `${root}${name}`));
|
|
128
|
+
}
|
|
129
|
+
/**
|
|
130
|
+
* Is the preload wired, judged from whatever evidence exists?
|
|
131
|
+
*
|
|
132
|
+
* Source first (the require is right there). Failing that, the BUILD OUTPUT: bundling inlines the
|
|
133
|
+
* shim, and the shim carries the contract's own window global — finding that string in the artifact
|
|
134
|
+
* proves the preload is wired even though the require has been compiled away. Undefined means no
|
|
135
|
+
* evidence either way, and an unknown must never be reported as a fault.
|
|
136
|
+
*/
|
|
137
|
+
function preloadWired(read, mainDir) {
|
|
138
|
+
for (const candidate of preloadCandidates(mainDir)) {
|
|
139
|
+
const source = read(candidate);
|
|
140
|
+
if (source !== undefined)
|
|
141
|
+
return { wired: source.includes(PRELOAD_REQUIRE), file: candidate };
|
|
142
|
+
}
|
|
143
|
+
for (const candidate of bundledPreloadCandidates(mainDir)) {
|
|
144
|
+
const built = read(candidate);
|
|
145
|
+
if (built !== undefined) {
|
|
146
|
+
return { wired: built.includes(RETICLE_IPC_GLOBAL), file: candidate };
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return undefined;
|
|
150
|
+
}
|
|
151
|
+
function diagnoseElectron(read, main) {
|
|
152
|
+
const findings = [];
|
|
153
|
+
const dir = dirOf(main);
|
|
154
|
+
// Undefined = no source AND no build output to judge from. An unknown is not a fault.
|
|
155
|
+
const preload = preloadWired(read, dir);
|
|
156
|
+
if (preload !== undefined && !preload.wired) {
|
|
157
|
+
findings.push({
|
|
158
|
+
code: DesktopFinding.ELECTRON_PRELOAD_MISSING,
|
|
159
|
+
file: preload.file,
|
|
160
|
+
problem: 'the preload never installs the Reticle IPC shim, so every ipcRenderer.invoke is invisible — reticle_network will report nothing and read as "this app makes no backend calls"',
|
|
161
|
+
fix: `add as the FIRST line: require('${PRELOAD_REQUIRE}')`,
|
|
162
|
+
});
|
|
163
|
+
}
|
|
164
|
+
const mainSource = read(main);
|
|
165
|
+
if (mainSource !== undefined && !mainSource.includes(CAPTURE_REQUIRE)) {
|
|
166
|
+
findings.push({
|
|
167
|
+
code: DesktopFinding.ELECTRON_CAPTURE_MISSING,
|
|
168
|
+
file: main,
|
|
169
|
+
problem: 'the main process never installs the capture helper, so screenshots are unavailable',
|
|
170
|
+
fix: `add: const { installReticleCapture } = require('${CAPTURE_REQUIRE}') then installReticleCapture(win)`,
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
return findings;
|
|
174
|
+
}
|
|
175
|
+
/** Is this project a desktop shell at all? Used to print a positive result instead of silence. */
|
|
176
|
+
export function isDesktopProject(read) {
|
|
177
|
+
if (read(TAURI_CONF) !== undefined)
|
|
178
|
+
return true;
|
|
179
|
+
const pkg = parseJson(read('package.json'));
|
|
180
|
+
if (pkg === undefined)
|
|
181
|
+
return false;
|
|
182
|
+
const deps = { ...record(pkg['dependencies']), ...record(pkg['devDependencies']) };
|
|
183
|
+
return deps['electron'] !== undefined;
|
|
184
|
+
}
|
|
185
|
+
/** Which desktop shell (if any) this project is, and what is missing from its Reticle wiring. */
|
|
186
|
+
export function diagnoseDesktop(read, port) {
|
|
187
|
+
const tauri = diagnoseTauri(read, port);
|
|
188
|
+
if (tauri.length > 0 || read(TAURI_CONF) !== undefined)
|
|
189
|
+
return tauri;
|
|
190
|
+
const pkg = parseJson(read('package.json'));
|
|
191
|
+
if (pkg === undefined)
|
|
192
|
+
return [];
|
|
193
|
+
const deps = { ...record(pkg['dependencies']), ...record(pkg['devDependencies']) };
|
|
194
|
+
if (deps['electron'] === undefined)
|
|
195
|
+
return [];
|
|
196
|
+
const main = typeof pkg['main'] === 'string' ? pkg['main'] : undefined;
|
|
197
|
+
return main === undefined ? [] : diagnoseElectron(read, main);
|
|
198
|
+
}
|