@reticlehq/server 2.4.0 → 2.6.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 +719 -0
- package/dist/bridge/auth-failure-reason.d.ts +19 -0
- package/dist/bridge/auth-failure-reason.js +29 -0
- package/dist/{bridge-security.d.ts → bridge/bridge-security.d.ts} +1 -1
- package/dist/{bridge-security.js → bridge/bridge-security.js} +1 -1
- package/dist/{bridge.d.ts → bridge/bridge.d.ts} +13 -1
- package/dist/{bridge.js → bridge/bridge.js} +95 -15
- package/dist/{bridge.test-harness.d.ts → bridge/bridge.test-harness.d.ts} +9 -11
- package/dist/{bridge.test-harness.js → bridge/bridge.test-harness.js} +18 -10
- package/dist/{pairing-token.js → bridge/pairing-token.js} +1 -1
- package/dist/capsule/capsule-store.d.ts +8 -3
- package/dist/capsule/capsule-store.js +7 -2
- package/dist/capsule/capsule.js +3 -3
- package/dist/capsule/causal-summary.d.ts +8 -0
- package/dist/capsule/causal-summary.js +22 -12
- package/dist/capsule/divergence.d.ts +9 -4
- package/dist/capsule/divergence.js +8 -8
- package/dist/capsule/predicate-to-links.js +11 -8
- package/dist/cli/cli-doctor.d.ts +1 -0
- package/dist/cli/cli-doctor.js +135 -0
- package/dist/{cli-flow-commands.d.ts → cli/cli-flow-commands.d.ts} +2 -2
- package/dist/{cli-flow-commands.js → cli/cli-flow-commands.js} +15 -15
- package/dist/{cli-launch.d.ts → cli/cli-launch.d.ts} +32 -3
- package/dist/cli/cli-launch.js +171 -0
- package/dist/cli/cli-parse-feedback.d.ts +31 -0
- package/dist/cli/cli-parse-feedback.js +56 -0
- package/dist/{cli-parse.d.ts → cli/cli-parse.d.ts} +6 -19
- package/dist/{cli-parse.js → cli/cli-parse.js} +118 -81
- package/dist/{cli-port.d.ts → cli/cli-port.d.ts} +12 -0
- package/dist/{cli-port.js → cli/cli-port.js} +9 -9
- package/dist/cli/cli-update-commands.d.ts +4 -0
- package/dist/cli/cli-update-commands.js +93 -0
- package/dist/{cli-verify.js → cli/cli-verify.js} +14 -14
- package/dist/{cloud-cli.js → cli/cloud-cli.js} +29 -24
- package/dist/cli/doctor-daemon-line.d.ts +37 -0
- package/dist/cli/doctor-daemon-line.js +35 -0
- package/dist/cli/port-holder.d.ts +43 -0
- package/dist/cli/port-holder.js +99 -0
- package/dist/cli.d.ts +2 -2
- package/dist/cli.js +302 -100
- package/dist/cloud/cloud-config.d.ts +0 -1
- package/dist/cloud/cloud-config.js +9 -9
- package/dist/cloud/cloud-sync.d.ts +1 -7
- package/dist/cloud/cloud-sync.js +12 -12
- package/dist/crawl/crawl-empty.d.ts +16 -0
- package/dist/crawl/crawl-empty.js +24 -0
- package/dist/crawl/crawl-tools.js +4 -1
- package/dist/crawl/crawl.js +26 -7
- package/dist/daemon/daemon-resilience.d.ts +73 -0
- package/dist/daemon/daemon-resilience.js +279 -0
- package/dist/daemon/daemon-usefulness.d.ts +61 -0
- package/dist/daemon/daemon-usefulness.js +62 -0
- package/dist/{daemon.d.ts → daemon/daemon.d.ts} +33 -8
- package/dist/{daemon.js → daemon/daemon.js} +105 -48
- package/dist/daemon/heartbeat.d.ts +115 -0
- package/dist/daemon/heartbeat.js +141 -0
- package/dist/daemon/idle-grace.d.ts +32 -0
- package/dist/daemon/idle-grace.js +41 -0
- package/dist/{idle-shutdown.d.ts → daemon/idle-shutdown.d.ts} +23 -2
- package/dist/{idle-shutdown.js → daemon/idle-shutdown.js} +37 -6
- package/dist/daemon/port-presence.d.ts +76 -0
- package/dist/daemon/port-presence.js +93 -0
- package/dist/daemon/state-dir.d.ts +7 -0
- package/dist/daemon/state-dir.js +59 -0
- package/dist/daemon/unclean-predecessor.d.ts +23 -0
- package/dist/daemon/unclean-predecessor.js +27 -0
- package/dist/domain/domain-model.js +2 -2
- package/dist/events/body-failures.js +8 -8
- package/dist/events/contradictions.d.ts +1 -1
- package/dist/events/contradictions.js +60 -10
- package/dist/events/echo-mismatch.js +10 -10
- package/dist/events/event-filters.js +6 -6
- package/dist/events/json-salvage.d.ts +2 -1
- package/dist/events/json-salvage.js +6 -6
- package/dist/events/observed-in-window.d.ts +12 -0
- package/dist/events/observed-in-window.js +21 -0
- package/dist/events/predicate-eval.d.ts +53 -20
- package/dist/events/predicate-eval.js +179 -55
- package/dist/events/predicate-parse.d.ts +23 -0
- package/dist/events/predicate-parse.js +54 -0
- package/dist/events/predicate.d.ts +7 -2
- package/dist/events/predicate.js +126 -35
- package/dist/events/reconcile.js +5 -5
- package/dist/events/ring-buffer.js +2 -17
- package/dist/events/stale-response.js +6 -6
- package/dist/events/testid-near-miss.d.ts +22 -0
- package/dist/events/testid-near-miss.js +33 -0
- package/dist/events/unit-mismatch.js +8 -8
- package/dist/flows/affected-tools.js +19 -4
- package/dist/flows/affected.js +1 -1
- package/dist/flows/annotate-target.d.ts +1 -0
- package/dist/flows/annotate-target.js +20 -0
- package/dist/flows/annotate-tools.js +25 -3
- package/dist/flows/annotate.js +17 -4
- package/dist/flows/assertion-integrity.d.ts +2 -1
- package/dist/flows/assertion-tiers-store.d.ts +3 -66
- package/dist/flows/assertion-tiers-store.js +2 -2
- package/dist/flows/attributed-failure.d.ts +17 -0
- package/dist/flows/attributed-failure.js +20 -0
- package/dist/flows/buddy-status.d.ts +2 -1
- package/dist/flows/buddy-status.js +2 -2
- package/dist/flows/coverage.d.ts +3 -2
- package/dist/flows/coverage.js +2 -2
- package/dist/flows/decision.js +24 -9
- package/dist/flows/empty-flow.d.ts +6 -0
- package/dist/flows/empty-flow.js +24 -0
- package/dist/flows/flake-store.d.ts +0 -1
- package/dist/flows/flake-store.js +1 -1
- package/dist/flows/flake.d.ts +2 -1
- package/dist/flows/flake.js +2 -2
- package/dist/flows/flow-classify.js +12 -0
- package/dist/flows/flow-replay-run.js +4 -4
- package/dist/flows/flow-replay.d.ts +6 -8
- package/dist/flows/flow-replay.js +132 -48
- package/dist/flows/flow-report.js +1 -1
- package/dist/flows/flow-scope.d.ts +1 -6
- package/dist/flows/flow-step-runners.d.ts +26 -6
- package/dist/flows/flow-step-runners.js +156 -6
- package/dist/flows/flow-success.js +20 -15
- package/dist/flows/flow-tools.js +63 -21
- package/dist/flows/flows.js +15 -11
- package/dist/flows/gate.d.ts +4 -3
- package/dist/flows/gate.js +1 -1
- package/dist/flows/heal-run.d.ts +0 -8
- package/dist/flows/heal-run.js +5 -5
- package/dist/flows/heal.js +3 -3
- package/dist/flows/predicate-to-expect.d.ts +38 -0
- package/dist/flows/predicate-to-expect.js +95 -0
- package/dist/flows/replay.d.ts +16 -1
- package/dist/flows/replay.js +58 -22
- package/dist/flows/role-anchor-nearest.d.ts +6 -0
- package/dist/flows/role-anchor-nearest.js +45 -0
- package/dist/flows/role-drift-reason.d.ts +20 -0
- package/dist/flows/role-drift-reason.js +39 -0
- package/dist/flows/server-verify.d.ts +1 -1
- package/dist/flows/server-verify.js +5 -5
- package/dist/flows/suite-flakes.d.ts +33 -0
- package/dist/flows/suite-flakes.js +32 -0
- package/dist/flows/verify-change-tools.js +32 -10
- package/dist/flows/verify-change-verdict.d.ts +15 -0
- package/dist/flows/verify-change-verdict.js +25 -0
- package/dist/flows/watch-batcher.d.ts +3 -2
- package/dist/honesty/already-true.d.ts +2 -0
- package/dist/honesty/already-true.js +31 -0
- package/dist/honesty/blind-spots.d.ts +35 -3
- package/dist/honesty/blind-spots.js +57 -12
- package/dist/honesty/honesty.d.ts +3 -2
- package/dist/honesty/honesty.js +4 -4
- package/dist/honesty/uncaptured-bodies.js +1 -1
- package/dist/honesty/unread-outcome.js +2 -2
- package/dist/honesty/verified.d.ts +31 -3
- package/dist/honesty/verified.js +64 -8
- package/dist/http-server.js +23 -7
- package/dist/hunt/hunt-report.d.ts +2 -1
- package/dist/hunt/hunt-report.js +2 -2
- package/dist/index.d.ts +9 -6
- package/dist/index.js +41 -25
- package/dist/init/agent-rules.d.ts +20 -1
- package/dist/init/agent-rules.js +64 -8
- package/dist/init/app-choice.d.ts +20 -0
- package/dist/init/app-choice.js +25 -0
- package/dist/init/astro-host.d.ts +21 -0
- package/dist/init/astro-host.js +27 -0
- package/dist/init/astro-patch.d.ts +16 -0
- package/dist/init/astro-patch.js +240 -0
- package/dist/init/capabilities.js +4 -1
- package/dist/init/cra.d.ts +50 -0
- package/dist/init/cra.js +106 -0
- package/dist/init/cursor.js +39 -4
- package/dist/init/desktop-doctor.d.ts +3 -2
- package/dist/init/desktop-doctor.js +4 -4
- package/dist/init/detect.d.ts +9 -2
- package/dist/init/detect.js +24 -5
- package/dist/init/mcp-clients.d.ts +81 -0
- package/dist/init/mcp-clients.js +248 -0
- package/dist/init/mcp-registered.d.ts +12 -0
- package/dist/init/mcp-registered.js +14 -0
- package/dist/init/mcp.d.ts +27 -2
- package/dist/init/mcp.js +40 -4
- package/dist/init/next-patch.d.ts +2 -4
- package/dist/init/next-patch.js +109 -19
- package/dist/init/node-io.js +29 -6
- package/dist/init/plan-framework.d.ts +16 -1
- package/dist/init/plan-framework.js +166 -8
- package/dist/init/plan.d.ts +85 -6
- package/dist/init/plan.js +196 -33
- package/dist/init/project-id.d.ts +5 -9
- package/dist/init/project-id.js +10 -22
- package/dist/init/run.d.ts +23 -1
- package/dist/init/run.js +338 -47
- package/dist/init/slash-command.d.ts +9 -0
- package/dist/init/slash-command.js +10 -1
- package/dist/init/snippets.d.ts +7 -10
- package/dist/init/snippets.js +44 -15
- package/dist/init/vite-config.js +1 -1
- package/dist/init/windows-quote.d.ts +38 -0
- package/dist/init/windows-quote.js +70 -0
- package/dist/init/workspace-apps.d.ts +23 -0
- package/dist/init/workspace-apps.js +68 -0
- package/dist/input/driven-redaction.js +1 -1
- package/dist/input/network-detail.js +8 -8
- package/dist/input/network-mock-tools.js +2 -2
- package/dist/input/network-mock.js +4 -4
- package/dist/input/real-input.js +8 -3
- package/dist/input/scroll-find.js +2 -2
- package/dist/input/scroll-tools.d.ts +0 -5
- package/dist/input/scroll-tools.js +11 -4
- package/dist/input/viewport-tools.js +2 -2
- package/dist/journal/ambient-store.d.ts +0 -2
- package/dist/journal/ambient-store.js +1 -1
- package/dist/journal/ambient.js +1 -1
- package/dist/journal/attach-journal.d.ts +2 -1
- package/dist/journal/deviation-report.js +6 -6
- package/dist/journal/deviation-service.js +1 -1
- package/dist/journal/envelope-store.d.ts +0 -2
- package/dist/journal/envelope-store.js +1 -1
- package/dist/journal/envelope.d.ts +2 -3
- package/dist/journal/envelope.js +3 -3
- package/dist/journal/journal-query.js +1 -1
- package/dist/journal/journal-recorder.d.ts +2 -1
- package/dist/journal/journal-recorder.js +2 -2
- package/dist/journal/rollups.js +9 -9
- package/dist/journal/session-end.d.ts +2 -1
- package/dist/journal/session-journal.js +4 -4
- package/dist/license/license.d.ts +0 -14
- package/dist/license/license.js +8 -8
- package/dist/log.d.ts +10 -0
- package/dist/log.js +11 -1
- package/dist/mcp/mcp-is-error.d.ts +13 -0
- package/dist/mcp/mcp-is-error.js +18 -0
- package/dist/mcp/mcp-outage.d.ts +32 -0
- package/dist/mcp/mcp-outage.js +55 -0
- package/dist/mcp/mcp-proxy.d.ts +134 -0
- package/dist/mcp/mcp-proxy.js +720 -0
- package/dist/{mcp.d.ts → mcp/mcp.d.ts} +13 -10
- package/dist/{mcp.js → mcp/mcp.js} +139 -37
- package/dist/mcp/proxy-handshake.d.ts +3 -0
- package/dist/mcp/proxy-handshake.js +54 -0
- package/dist/mcp/proxy-lifecycle.d.ts +64 -0
- package/dist/mcp/proxy-lifecycle.js +70 -0
- package/dist/mcp/tool-catalog-cache.d.ts +29 -0
- package/dist/mcp/tool-catalog-cache.js +55 -0
- package/dist/oracles/propose-consequences.d.ts +2 -1
- package/dist/oracles/propose-consequences.js +16 -11
- package/dist/oracles/self-instrument.d.ts +2 -1
- package/dist/oracles/self-instrument.js +1 -1
- package/dist/phenomena/phenomena.js +3 -3
- package/dist/platform.d.ts +16 -0
- package/dist/platform.js +16 -0
- package/dist/pool/browser-pool.d.ts +9 -0
- package/dist/pool/browser-pool.js +38 -9
- package/dist/pool/playwright-launcher.d.ts +15 -2
- package/dist/pool/playwright-launcher.js +21 -2
- package/dist/project/fs-port.js +1 -1
- package/dist/project/project-tools.js +2 -2
- package/dist/runs/build-verification-run.js +1 -1
- package/dist/runs/repair-prompt.d.ts +0 -6
- package/dist/runs/repair-prompt.js +3 -3
- package/dist/runs/risk-classify.js +1 -1
- package/dist/runs/run-diff.d.ts +0 -2
- package/dist/runs/run-diff.js +3 -3
- package/dist/runs/run-tools.js +2 -2
- package/dist/runs/verification-sync.js +2 -2
- package/dist/runs/verify-http.js +1 -1
- package/dist/runs/verify-server.js +1 -1
- package/dist/session/attachment-history.d.ts +46 -0
- package/dist/session/attachment-history.js +65 -0
- package/dist/session/command-timeout.d.ts +11 -3
- package/dist/session/command-timeout.js +2 -2
- package/dist/session/control-envelope.d.ts +6 -0
- package/dist/session/control-envelope.js +7 -1
- package/dist/session/dev-server-probe.d.ts +13 -0
- package/dist/session/dev-server-probe.js +52 -0
- package/dist/session/last-act.d.ts +17 -3
- package/dist/session/last-act.js +16 -4
- package/dist/session/live-control-tools.js +7 -2
- package/dist/session/live-control.js +1 -1
- package/dist/session/looks-like-dev-server.d.ts +14 -0
- package/dist/session/looks-like-dev-server.js +25 -0
- package/dist/session/no-session-diagnosis.d.ts +45 -0
- package/dist/session/no-session-diagnosis.js +120 -0
- package/dist/session/no-session-watch.d.ts +21 -0
- package/dist/session/no-session-watch.js +69 -0
- package/dist/session/observed-state.d.ts +4 -0
- package/dist/session/observed-state.js +19 -1
- package/dist/session/output-budget.js +1 -1
- package/dist/session/pending-commands.js +1 -0
- package/dist/session/session-health.d.ts +8 -1
- package/dist/session/session-health.js +8 -7
- package/dist/session/session-info.d.ts +43 -8
- package/dist/session/session-info.js +46 -1
- package/dist/session/session-lease.d.ts +0 -11
- package/dist/session/session-lease.js +1 -1
- package/dist/session/session-manager.d.ts +6 -0
- package/dist/session/session-manager.js +124 -12
- package/dist/session/session-readiness.d.ts +1 -1
- package/dist/session/session-readiness.js +6 -1
- package/dist/session/session-reaper.js +1 -1
- package/dist/session/session-reconnect.d.ts +32 -0
- package/dist/session/session-reconnect.js +42 -0
- package/dist/session/session.d.ts +15 -2
- package/dist/session/session.js +77 -26
- package/dist/session/state-select.d.ts +1 -1
- package/dist/session/state-select.js +1 -1
- package/dist/status-payload.d.ts +19 -0
- package/dist/status-payload.js +11 -0
- package/dist/telemetry/argument-shape.js +10 -1
- package/dist/telemetry/browser-mode.d.ts +27 -0
- package/dist/telemetry/browser-mode.js +33 -0
- package/dist/telemetry/bug-found.d.ts +17 -21
- package/dist/telemetry/bug-found.js +120 -8
- package/dist/telemetry/cli-telemetry.d.ts +2 -12
- package/dist/telemetry/cli-telemetry.js +27 -4
- package/dist/telemetry/crash-cause.d.ts +47 -0
- package/dist/telemetry/crash-cause.js +104 -0
- package/dist/telemetry/daemon-telemetry.d.ts +38 -1
- package/dist/telemetry/daemon-telemetry.js +37 -12
- package/dist/telemetry/dev-repo.js +4 -4
- package/dist/telemetry/error-class.d.ts +26 -0
- package/dist/telemetry/error-class.js +52 -0
- package/dist/telemetry/error-fingerprint.js +21 -2
- package/dist/telemetry/feedback-cli.d.ts +8 -3
- package/dist/telemetry/feedback-cli.js +52 -8
- package/dist/telemetry/feedback-context.d.ts +23 -6
- package/dist/telemetry/feedback-context.js +105 -5
- package/dist/telemetry/feedback-delivery.d.ts +20 -0
- package/dist/telemetry/feedback-delivery.js +30 -0
- package/dist/telemetry/feedback-outbox.d.ts +22 -0
- package/dist/telemetry/feedback-outbox.js +87 -0
- package/dist/telemetry/feedback.d.ts +22 -1
- package/dist/telemetry/feedback.js +67 -8
- package/dist/telemetry/git-facts.d.ts +7 -0
- package/dist/telemetry/git-facts.js +5 -5
- package/dist/telemetry/project-profile.js +2 -1
- package/dist/telemetry/session-metrics.d.ts +47 -3
- package/dist/telemetry/session-metrics.js +315 -15
- package/dist/telemetry/telemetry.d.ts +45 -2
- package/dist/telemetry/telemetry.js +150 -37
- package/dist/telemetry/verification-of.d.ts +22 -0
- package/dist/telemetry/verification-of.js +84 -0
- package/dist/tools/act-capsule.js +2 -2
- package/dist/tools/act-danger.d.ts +12 -0
- package/dist/tools/act-danger.js +20 -3
- package/dist/tools/act-helpers.js +4 -4
- package/dist/tools/act-tools.d.ts +0 -8
- package/dist/tools/act-tools.js +114 -118
- package/dist/tools/act-view.js +7 -7
- package/dist/tools/alias-args.d.ts +17 -0
- package/dist/tools/alias-args.js +25 -0
- package/dist/tools/assert-grade.js +9 -9
- package/dist/tools/assert-verdict.d.ts +9 -1
- package/dist/tools/assert-verdict.js +21 -6
- package/dist/tools/browser-tools.js +36 -11
- package/dist/tools/contract-tools.d.ts +0 -5
- package/dist/tools/contract-tools.js +27 -1
- package/dist/tools/coverage-identity.d.ts +34 -0
- package/dist/tools/coverage-identity.js +46 -0
- package/dist/tools/coverage-tools.js +10 -14
- package/dist/tools/dynamic-tools.d.ts +2 -1
- package/dist/tools/dynamic-tools.js +96 -19
- package/dist/tools/error-recovery.d.ts +34 -2
- package/dist/tools/error-recovery.js +255 -4
- package/dist/tools/feedback-invite.d.ts +48 -0
- package/dist/tools/feedback-invite.js +71 -0
- package/dist/tools/feedback-tools.d.ts +12 -1
- package/dist/tools/feedback-tools.js +28 -5
- package/dist/tools/invoke-tool.d.ts +0 -12
- package/dist/tools/invoke-tool.js +126 -33
- package/dist/tools/lease-hint.d.ts +17 -0
- package/dist/tools/lease-hint.js +24 -0
- package/dist/tools/lease-tools.js +6 -5
- package/dist/tools/merge-tools.d.ts +10 -1
- package/dist/tools/merge-tools.js +9 -3
- package/dist/tools/merged-name-redirect.d.ts +13 -0
- package/dist/tools/merged-name-redirect.js +55 -0
- package/dist/tools/navigate-arrival.d.ts +26 -0
- package/dist/tools/navigate-arrival.js +60 -0
- package/dist/tools/navigate-result.d.ts +31 -0
- package/dist/tools/navigate-result.js +38 -0
- package/dist/tools/observe-tools.js +72 -20
- package/dist/tools/observed-nothing.d.ts +25 -0
- package/dist/tools/observed-nothing.js +33 -0
- package/dist/tools/query-paginate.js +2 -2
- package/dist/tools/query-shape.d.ts +18 -0
- package/dist/tools/query-shape.js +39 -0
- package/dist/tools/read-tools.js +81 -20
- package/dist/tools/real-input-attempt.d.ts +28 -0
- package/dist/tools/real-input-attempt.js +93 -0
- package/dist/tools/reconcile-tools.js +7 -7
- package/dist/tools/reload-result.d.ts +14 -0
- package/dist/tools/reload-result.js +29 -0
- package/dist/tools/snapshot-delta.d.ts +4 -5
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/tool-kit.d.ts +16 -0
- package/dist/tools/tool-surface.d.ts +83 -0
- package/dist/tools/tool-surface.js +217 -0
- package/dist/tools/tools-helpers.js +6 -6
- package/dist/tools/tools.d.ts +15 -0
- package/dist/tools/tools.js +53 -17
- package/dist/tools/unadvertised-help.d.ts +5 -0
- package/dist/tools/unadvertised-help.js +39 -0
- package/dist/trace.d.ts +69 -0
- package/dist/trace.js +150 -0
- package/dist/update/nudge-credit.d.ts +4 -0
- package/dist/update/nudge-credit.js +53 -0
- package/dist/update/sdk-sync.d.ts +21 -0
- package/dist/update/sdk-sync.js +42 -0
- package/dist/update/update-checker.js +3 -3
- package/dist/update/update-nudge.d.ts +63 -6
- package/dist/update/update-nudge.js +128 -15
- package/dist/update/updater.d.ts +1 -9
- package/dist/update/updater.js +13 -8
- package/dist/version/peer-announce.d.ts +4 -0
- package/dist/version/peer-announce.js +30 -0
- package/dist/{server-version.js → version/server-version.js} +5 -1
- package/dist/version/version-nudge.d.ts +28 -0
- package/dist/version/version-nudge.js +40 -0
- package/dist/version/version-skew.d.ts +66 -0
- package/dist/version/version-skew.js +71 -0
- package/dist/visual/visual-diff.js +2 -2
- package/dist/visual/visual-tools.js +4 -4
- package/docs/README.md +55 -0
- package/docs/agent-cheatsheet.md +85 -0
- package/docs/architecture.md +113 -0
- package/docs/benchmarks.md +255 -0
- package/docs/debugging.md +102 -0
- package/docs/deploy-checks.md +69 -0
- package/docs/desktop-apps.md +256 -0
- package/docs/enterprise.md +62 -0
- package/docs/fixtures-dispatch-receiver.yml +76 -0
- package/docs/fixtures.md +45 -0
- package/docs/flows.md +166 -0
- package/docs/gate-plan.md +98 -0
- package/docs/gates.md +117 -0
- package/docs/getting-started.md +469 -0
- package/docs/human-control.md +63 -0
- package/docs/integration-patterns.md +171 -0
- package/docs/local-registry.md +126 -0
- package/docs/matrix/2.5.0/claude-code-machine.json +19 -0
- package/docs/matrix/2.5.0/codex-machine.json +20 -0
- package/docs/matrix/2.5.0/cursor-machine.json +22 -0
- package/docs/matrix/2.5.0/gemini-machine.json +22 -0
- package/docs/matrix/2.5.0/opencode-machine.json +22 -0
- package/docs/matrix/2.5.0/vscode-machine.json +22 -0
- package/docs/matrix/2.5.0/windsurf-machine.json +22 -0
- package/docs/matrix/MATRIX.md +26 -0
- package/docs/matrix/README.md +59 -0
- package/docs/mint.json +61 -0
- package/docs/multi-agent-testing.md +55 -0
- package/docs/platform-integration.md +122 -0
- package/docs/system-map.md +152 -0
- package/docs/telemetry-contract.md +214 -0
- package/docs/telemetry.md +191 -0
- package/docs/testing.md +82 -0
- package/docs/token-efficiency.md +80 -0
- package/docs/usage.md +1046 -0
- package/package.json +8 -5
- package/dist/cli-doctor.d.ts +0 -6
- package/dist/cli-doctor.js +0 -60
- package/dist/cli-launch.js +0 -112
- package/dist/daemon-resilience.d.ts +0 -22
- package/dist/daemon-resilience.js +0 -85
- package/dist/mcp-proxy.d.ts +0 -67
- package/dist/mcp-proxy.js +0 -337
- package/dist/tools/profiles.d.ts +0 -37
- package/dist/tools/profiles.js +0 -139
- /package/dist/{pairing-token.d.ts → bridge/pairing-token.d.ts} +0 -0
- /package/dist/{token-auth.d.ts → bridge/token-auth.d.ts} +0 -0
- /package/dist/{token-auth.js → bridge/token-auth.js} +0 -0
- /package/dist/{cli-verify.d.ts → cli/cli-verify.d.ts} +0 -0
- /package/dist/{cloud-cli.d.ts → cli/cloud-cli.d.ts} +0 -0
- /package/dist/{server-version.d.ts → version/server-version.d.ts} +0 -0
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType } from '@reticlehq/core';
|
|
1
|
+
import { EventType, PredicateKind } from '@reticlehq/core';
|
|
2
2
|
const TIER = { SIGNAL: 0, CONSEQUENCE: 1, PRESENCE: 2 };
|
|
3
3
|
function pathname(url) {
|
|
4
4
|
if (typeof url !== 'string')
|
|
@@ -25,9 +25,9 @@ export function proposeConsequences(events) {
|
|
|
25
25
|
switch (event.type) {
|
|
26
26
|
case EventType.SIGNAL: {
|
|
27
27
|
const name = data['name'];
|
|
28
|
-
if (typeof name
|
|
28
|
+
if ('string' === typeof name) {
|
|
29
29
|
add(`signal:${name}`, {
|
|
30
|
-
predicate: { kind:
|
|
30
|
+
predicate: { kind: PredicateKind.SIGNAL, name },
|
|
31
31
|
tier: TIER.SIGNAL,
|
|
32
32
|
label: `signal "${name}" fires`,
|
|
33
33
|
weak: false,
|
|
@@ -37,10 +37,15 @@ export function proposeConsequences(events) {
|
|
|
37
37
|
}
|
|
38
38
|
case EventType.NET_REQUEST: {
|
|
39
39
|
const path = pathname(data['url']);
|
|
40
|
-
const method = typeof data['method']
|
|
40
|
+
const method = 'string' === typeof data['method'] ? data['method'] : 'GET';
|
|
41
41
|
if (path !== undefined) {
|
|
42
42
|
add(`net:${method} ${path}`, {
|
|
43
|
-
predicate: {
|
|
43
|
+
predicate: {
|
|
44
|
+
kind: PredicateKind.NET,
|
|
45
|
+
method,
|
|
46
|
+
urlContains: path,
|
|
47
|
+
status: data['status'],
|
|
48
|
+
},
|
|
44
49
|
tier: TIER.CONSEQUENCE,
|
|
45
50
|
label: `${method} ${path} responds`,
|
|
46
51
|
weak: false,
|
|
@@ -50,9 +55,9 @@ export function proposeConsequences(events) {
|
|
|
50
55
|
}
|
|
51
56
|
case EventType.STATE_CHANGE: {
|
|
52
57
|
const name = data['name'];
|
|
53
|
-
if (typeof name
|
|
58
|
+
if ('string' === typeof name) {
|
|
54
59
|
add(`state:${name}`, {
|
|
55
|
-
predicate: { kind:
|
|
60
|
+
predicate: { kind: PredicateKind.STATE, store: name, path: data['path'] },
|
|
56
61
|
tier: TIER.CONSEQUENCE,
|
|
57
62
|
label: `state "${name}" changes`,
|
|
58
63
|
weak: false,
|
|
@@ -62,9 +67,9 @@ export function proposeConsequences(events) {
|
|
|
62
67
|
}
|
|
63
68
|
case EventType.ROUTE_CHANGE: {
|
|
64
69
|
const to = data['pathname'];
|
|
65
|
-
if (typeof to
|
|
70
|
+
if ('string' === typeof to) {
|
|
66
71
|
add(`route:${to}`, {
|
|
67
|
-
predicate: { kind:
|
|
72
|
+
predicate: { kind: PredicateKind.ROUTE, to },
|
|
68
73
|
tier: TIER.CONSEQUENCE,
|
|
69
74
|
label: `route changes to ${to}`,
|
|
70
75
|
weak: false,
|
|
@@ -74,9 +79,9 @@ export function proposeConsequences(events) {
|
|
|
74
79
|
}
|
|
75
80
|
case EventType.DOM_ADDED: {
|
|
76
81
|
const name = data['name'];
|
|
77
|
-
if (typeof name
|
|
82
|
+
if ('string' === typeof name && name.length > 0) {
|
|
78
83
|
add(`presence:${name}`, {
|
|
79
|
-
predicate: { kind:
|
|
84
|
+
predicate: { kind: PredicateKind.ELEMENT, name },
|
|
80
85
|
tier: TIER.PRESENCE,
|
|
81
86
|
label: `"${name}" appears (presence only — prefer a consequence)`,
|
|
82
87
|
weak: true,
|
|
@@ -20,7 +20,7 @@ export interface InstrumentationGap {
|
|
|
20
20
|
/** Why this gap matters (e.g. "checkout flow asserts presence only"). */
|
|
21
21
|
context?: string;
|
|
22
22
|
}
|
|
23
|
-
|
|
23
|
+
interface InstrumentationProposal {
|
|
24
24
|
file: string;
|
|
25
25
|
line: number;
|
|
26
26
|
/** The code to insert. */
|
|
@@ -29,3 +29,4 @@ export interface InstrumentationProposal {
|
|
|
29
29
|
}
|
|
30
30
|
/** Turn located capability gaps into ready-to-apply instrumentation proposals. Deterministic. */
|
|
31
31
|
export declare function proposeInstrumentation(gaps: readonly InstrumentationGap[]): InstrumentationProposal[];
|
|
32
|
+
export {};
|
|
@@ -12,7 +12,7 @@ export const InstrumentationGapKind = {
|
|
|
12
12
|
};
|
|
13
13
|
/** PascalCase a store name for a `useX.getState` hint (cart → Cart). */
|
|
14
14
|
function pascal(name) {
|
|
15
|
-
return name.length
|
|
15
|
+
return 0 === name.length ? name : name[0]?.toUpperCase() + name.slice(1);
|
|
16
16
|
}
|
|
17
17
|
function insertFor(gap) {
|
|
18
18
|
switch (gap.kind) {
|
|
@@ -28,14 +28,14 @@ export function detectHidden500(events) {
|
|
|
28
28
|
for (const event of events) {
|
|
29
29
|
if (event.type === EventType.PAGE_HEALTH) {
|
|
30
30
|
const h = event.data['hidden'];
|
|
31
|
-
if (typeof h
|
|
31
|
+
if ('boolean' === typeof h)
|
|
32
32
|
hidden = h;
|
|
33
33
|
continue;
|
|
34
34
|
}
|
|
35
35
|
if (event.type !== EventType.NET_REQUEST)
|
|
36
36
|
continue;
|
|
37
37
|
const status = event.data['status'];
|
|
38
|
-
if (hidden && typeof status
|
|
38
|
+
if (hidden && 'number' === typeof status && status >= 500) {
|
|
39
39
|
findings.push({
|
|
40
40
|
phenomenon: PhenomenonType.HIDDEN_500,
|
|
41
41
|
evidence: { url: event.data['url'], status, method: event.data['method'] },
|
|
@@ -83,7 +83,7 @@ export function detectSwallowedErrors(events) {
|
|
|
83
83
|
const detail = event.data['data'];
|
|
84
84
|
findings.push({
|
|
85
85
|
phenomenon: PhenomenonType.SWALLOWED_ERROR,
|
|
86
|
-
evidence: typeof detail
|
|
86
|
+
evidence: 'object' === typeof detail && detail !== null ? detail : {},
|
|
87
87
|
});
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `process.platform` values this daemon actually branches on, named once.
|
|
3
|
+
*
|
|
4
|
+
* They were spelled inline in five files — `cli-launch`, `cloud-cli`, `init/node-io`, `update/updater`
|
|
5
|
+
* — and every one of them gates real behaviour rather than cosmetics: whether a spawn needs a shell,
|
|
6
|
+
* whether the npm binary is `npm.cmd`, which command opens a browser. A typo in any of those reads as
|
|
7
|
+
* "Windows is broken" and is invisible on the machine of whoever wrote it, because the wrong branch
|
|
8
|
+
* simply never runs there.
|
|
9
|
+
*
|
|
10
|
+
* Node-side only, so deliberately NOT in `@reticlehq/core` — core is the wire contract, and a
|
|
11
|
+
* platform name never crosses the wire.
|
|
12
|
+
*/
|
|
13
|
+
export declare const NodePlatform: {
|
|
14
|
+
readonly WINDOWS: "win32";
|
|
15
|
+
readonly MACOS: "darwin";
|
|
16
|
+
};
|
package/dist/platform.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The `process.platform` values this daemon actually branches on, named once.
|
|
3
|
+
*
|
|
4
|
+
* They were spelled inline in five files — `cli-launch`, `cloud-cli`, `init/node-io`, `update/updater`
|
|
5
|
+
* — and every one of them gates real behaviour rather than cosmetics: whether a spawn needs a shell,
|
|
6
|
+
* whether the npm binary is `npm.cmd`, which command opens a browser. A typo in any of those reads as
|
|
7
|
+
* "Windows is broken" and is invisible on the machine of whoever wrote it, because the wrong branch
|
|
8
|
+
* simply never runs there.
|
|
9
|
+
*
|
|
10
|
+
* Node-side only, so deliberately NOT in `@reticlehq/core` — core is the wire contract, and a
|
|
11
|
+
* platform name never crosses the wire.
|
|
12
|
+
*/
|
|
13
|
+
export const NodePlatform = {
|
|
14
|
+
WINDOWS: 'win32',
|
|
15
|
+
MACOS: 'darwin',
|
|
16
|
+
};
|
|
@@ -77,6 +77,15 @@ export declare class BrowserPool {
|
|
|
77
77
|
* forever. Returns the released sessionIds. This is the fault-tolerance backstop for the pool.
|
|
78
78
|
*/
|
|
79
79
|
sweepExpired(): Promise<string[]>;
|
|
80
|
+
/**
|
|
81
|
+
* How many leases this pool has reclaimed for going stale.
|
|
82
|
+
*
|
|
83
|
+
* Read by the no-session diagnosis: an aged-out lease used to be reported as "the tab was closed
|
|
84
|
+
* … ask the human to reopen the app", which is wrong on every clause and sent one reporter looking
|
|
85
|
+
* for a port mismatch (#157). A count is enough — the message says "likeliest", not "certainly",
|
|
86
|
+
* because nothing here knows WHICH session the caller just lost.
|
|
87
|
+
*/
|
|
88
|
+
reapedLeaseCount(): number;
|
|
80
89
|
/**
|
|
81
90
|
* Lease an isolated context, navigate it to `url`, and return a handle. If the pool is at capacity,
|
|
82
91
|
* waits FIFO until a slot frees (or until `signal` aborts, if provided).
|
|
@@ -27,6 +27,8 @@ export class BrowserPool {
|
|
|
27
27
|
#browser;
|
|
28
28
|
#launching;
|
|
29
29
|
#closed = false;
|
|
30
|
+
/** Leases reclaimed for going stale — see reapedLeaseCount(). */
|
|
31
|
+
#reapedLeases = 0;
|
|
30
32
|
#active = new Map();
|
|
31
33
|
/**
|
|
32
34
|
* Slots claimed-or-active — the real concurrency gate. Incremented SYNCHRONOUSLY the instant an
|
|
@@ -85,8 +87,20 @@ export class BrowserPool {
|
|
|
85
87
|
.map(([sessionId]) => sessionId);
|
|
86
88
|
for (const sessionId of expired)
|
|
87
89
|
await this.#release(sessionId);
|
|
90
|
+
this.#reapedLeases += expired.length;
|
|
88
91
|
return expired;
|
|
89
92
|
}
|
|
93
|
+
/**
|
|
94
|
+
* How many leases this pool has reclaimed for going stale.
|
|
95
|
+
*
|
|
96
|
+
* Read by the no-session diagnosis: an aged-out lease used to be reported as "the tab was closed
|
|
97
|
+
* … ask the human to reopen the app", which is wrong on every clause and sent one reporter looking
|
|
98
|
+
* for a port mismatch (#157). A count is enough — the message says "likeliest", not "certainly",
|
|
99
|
+
* because nothing here knows WHICH session the caller just lost.
|
|
100
|
+
*/
|
|
101
|
+
reapedLeaseCount() {
|
|
102
|
+
return this.#reapedLeases;
|
|
103
|
+
}
|
|
90
104
|
/**
|
|
91
105
|
* Lease an isolated context, navigate it to `url`, and return a handle. If the pool is at capacity,
|
|
92
106
|
* waits FIFO until a slot frees (or until `signal` aborts, if provided).
|
|
@@ -138,6 +152,15 @@ export class BrowserPool {
|
|
|
138
152
|
this.#active.clear();
|
|
139
153
|
this.#occupied = 0;
|
|
140
154
|
await Promise.all(contexts.map((c) => c.close().catch(() => undefined)));
|
|
155
|
+
// If a launch is in flight, await it so we can close the resulting browser — otherwise it
|
|
156
|
+
// resolves after shutdown returns and the Chromium process is orphaned (hundreds of MB leaked).
|
|
157
|
+
const inflight = this.#launching;
|
|
158
|
+
if (inflight !== undefined) {
|
|
159
|
+
const launched = await inflight.catch(() => undefined);
|
|
160
|
+
if (launched !== undefined && launched !== this.#browser) {
|
|
161
|
+
await launched.close().catch(() => undefined);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
141
164
|
const browser = this.#browser;
|
|
142
165
|
this.#browser = undefined;
|
|
143
166
|
if (browser !== undefined)
|
|
@@ -168,27 +191,33 @@ export class BrowserPool {
|
|
|
168
191
|
const onFree = () => {
|
|
169
192
|
// The pool shut down while we waited → reject rather than relaunch a browser.
|
|
170
193
|
if (this.#closed) {
|
|
194
|
+
if (signal !== undefined)
|
|
195
|
+
signal.removeEventListener('abort', onAbort);
|
|
171
196
|
reject(new Error('browser pool is shut down'));
|
|
172
197
|
return;
|
|
173
198
|
}
|
|
174
199
|
// Claim the freed slot; if another woken waiter beat us to it, re-queue.
|
|
175
|
-
if (this.#tryClaim())
|
|
200
|
+
if (this.#tryClaim()) {
|
|
201
|
+
if (signal !== undefined)
|
|
202
|
+
signal.removeEventListener('abort', onAbort);
|
|
176
203
|
resolve();
|
|
177
|
-
|
|
204
|
+
}
|
|
205
|
+
else {
|
|
178
206
|
this.#waiters.push(onFree);
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
const onAbort = () => {
|
|
210
|
+
const i = this.#waiters.indexOf(onFree);
|
|
211
|
+
if (i >= 0)
|
|
212
|
+
this.#waiters.splice(i, 1);
|
|
213
|
+
reject(new Error('acquire aborted'));
|
|
179
214
|
};
|
|
180
215
|
if (signal !== undefined) {
|
|
181
216
|
if (signal.aborted) {
|
|
182
217
|
reject(new Error('acquire aborted'));
|
|
183
218
|
return;
|
|
184
219
|
}
|
|
185
|
-
signal.addEventListener('abort',
|
|
186
|
-
// Remove ourselves from the queue so a later wake doesn't claim a slot we'll never use.
|
|
187
|
-
const i = this.#waiters.indexOf(onFree);
|
|
188
|
-
if (i >= 0)
|
|
189
|
-
this.#waiters.splice(i, 1);
|
|
190
|
-
reject(new Error('acquire aborted'));
|
|
191
|
-
}, { once: true });
|
|
220
|
+
signal.addEventListener('abort', onAbort, { once: true });
|
|
192
221
|
}
|
|
193
222
|
this.#waiters.push(onFree);
|
|
194
223
|
});
|
|
@@ -6,8 +6,21 @@
|
|
|
6
6
|
* Headless by default — the pool exists for fault-tolerant headless multi-agent testing.
|
|
7
7
|
*/
|
|
8
8
|
import type { Launcher } from './browser-pool.js';
|
|
9
|
-
/**
|
|
10
|
-
|
|
9
|
+
/**
|
|
10
|
+
* How a leased tab navigates. Pure, and exported, because the decision in it is worth a test while
|
|
11
|
+
* the rest of this file needs a real Chromium.
|
|
12
|
+
*
|
|
13
|
+
* `waitUntil: 'domcontentloaded'` — NOT Playwright's default of `load`. `load` waits for every
|
|
14
|
+
* subresource, so an app with one that never finishes burns the whole nav budget and the lease then
|
|
15
|
+
* reports "is the app running?" about an app that is running. Measured on the sveltekit fixture:
|
|
16
|
+
* 30,501ms and a false diagnosis. The SDK connect is a module script and runs before
|
|
17
|
+
* DOMContentLoaded, and the pool separately waits for the session to register, so the load event was
|
|
18
|
+
* never what proved the page was usable.
|
|
19
|
+
*/
|
|
20
|
+
export declare function gotoOptions(timeoutMs: number | undefined): {
|
|
21
|
+
waitUntil: 'domcontentloaded';
|
|
22
|
+
timeout?: number;
|
|
23
|
+
};
|
|
11
24
|
/** A Launcher that boots a real headless Chromium and adapts it to the pool's interface. */
|
|
12
25
|
export declare function playwrightLauncher(opts?: {
|
|
13
26
|
headless?: boolean;
|
|
@@ -8,6 +8,25 @@
|
|
|
8
8
|
import { BrowserLaunchKind } from '@reticlehq/core';
|
|
9
9
|
import { getSessionMetrics } from '../telemetry/session-metrics.js';
|
|
10
10
|
import { classifyConnectFailure } from '../telemetry/connect-failure.js';
|
|
11
|
+
/**
|
|
12
|
+
* How a leased tab navigates. Pure, and exported, because the decision in it is worth a test while
|
|
13
|
+
* the rest of this file needs a real Chromium.
|
|
14
|
+
*
|
|
15
|
+
* `waitUntil: 'domcontentloaded'` — NOT Playwright's default of `load`. `load` waits for every
|
|
16
|
+
* subresource, so an app with one that never finishes burns the whole nav budget and the lease then
|
|
17
|
+
* reports "is the app running?" about an app that is running. Measured on the sveltekit fixture:
|
|
18
|
+
* 30,501ms and a false diagnosis. The SDK connect is a module script and runs before
|
|
19
|
+
* DOMContentLoaded, and the pool separately waits for the session to register, so the load event was
|
|
20
|
+
* never what proved the page was usable.
|
|
21
|
+
*/
|
|
22
|
+
export function gotoOptions(timeoutMs) {
|
|
23
|
+
return {
|
|
24
|
+
waitUntil: 'domcontentloaded',
|
|
25
|
+
// Absent, not zero: zero means "no timeout" to Playwright, which would turn a slow page into a
|
|
26
|
+
// lease that never returns.
|
|
27
|
+
...(timeoutMs === undefined ? {} : { timeout: timeoutMs }),
|
|
28
|
+
};
|
|
29
|
+
}
|
|
11
30
|
function wrapBrowser(browser) {
|
|
12
31
|
return {
|
|
13
32
|
isConnected: () => browser.isConnected(),
|
|
@@ -17,7 +36,7 @@ function wrapBrowser(browser) {
|
|
|
17
36
|
newPage: async () => {
|
|
18
37
|
const page = await context.newPage();
|
|
19
38
|
return {
|
|
20
|
-
goto: (url, opts) => page.goto(url, opts?.timeoutMs
|
|
39
|
+
goto: (url, opts) => page.goto(url, gotoOptions(opts?.timeoutMs)),
|
|
21
40
|
close: () => page.close(),
|
|
22
41
|
onCrash: (handler) => page.on('crash', handler),
|
|
23
42
|
};
|
|
@@ -30,7 +49,7 @@ function wrapBrowser(browser) {
|
|
|
30
49
|
};
|
|
31
50
|
}
|
|
32
51
|
/** The fix for the most common first-run failure: Chromium isn't installed for Playwright. */
|
|
33
|
-
|
|
52
|
+
const CHROMIUM_MISSING_HINT = 'Chromium is not installed for Playwright. Run: npx playwright install chromium';
|
|
34
53
|
/** A Launcher that boots a real headless Chromium and adapts it to the pool's interface. */
|
|
35
54
|
export function playwrightLauncher(opts = {}) {
|
|
36
55
|
const headless = opts.headless ?? true;
|
package/dist/project/fs-port.js
CHANGED
|
@@ -36,7 +36,7 @@ function numericDelta(before, after) {
|
|
|
36
36
|
*/
|
|
37
37
|
async function cloudRegression(deps, sessionId) {
|
|
38
38
|
const config = resolveCloudConfig(process.env);
|
|
39
|
-
if (
|
|
39
|
+
if (null === config)
|
|
40
40
|
return undefined;
|
|
41
41
|
let projectId;
|
|
42
42
|
try {
|
|
@@ -173,7 +173,7 @@ export const PROJECT_TOOLS = [
|
|
|
173
173
|
const kindArg = args['kind'];
|
|
174
174
|
const summary = asString(args['summary']);
|
|
175
175
|
await deps.project.recordRun({
|
|
176
|
-
kind: typeof kindArg
|
|
176
|
+
kind: 'string' === typeof kindArg ? kindArg : RunKind.MANUAL,
|
|
177
177
|
name,
|
|
178
178
|
status,
|
|
179
179
|
...(summary !== undefined ? { summary } : {}),
|
|
@@ -46,7 +46,7 @@ export function computeVerdict(input) {
|
|
|
46
46
|
status = VerdictStatus.PASS;
|
|
47
47
|
const ran = input.flows.length + input.checks.length;
|
|
48
48
|
let confidence;
|
|
49
|
-
if (
|
|
49
|
+
if (0 === ran)
|
|
50
50
|
confidence = RunConfidence.LOW;
|
|
51
51
|
else if (input.flows.some((f) => f.oracle !== undefined) || input.checks.length > 0)
|
|
52
52
|
confidence = RunConfidence.HIGH;
|
|
@@ -5,12 +5,6 @@
|
|
|
5
5
|
* RepairPacket shape. This is the OEM self-heal value — a verdict that also says how to fix.
|
|
6
6
|
*/
|
|
7
7
|
import { type FlowReplayResult, type RepairPacket } from '@reticlehq/core';
|
|
8
|
-
/**
|
|
9
|
-
* Build a repair packet for a failed replay, or undefined when the flow passed. The actual cause is
|
|
10
|
-
* the decision's whatChanged, falling back to the replay error or a generic message.
|
|
11
|
-
*/
|
|
12
|
-
/** The deviation report's headline when it flagged something — narrows the replay's `unknown` deviation. */
|
|
13
|
-
export declare function deviationHeadline(deviation: unknown): string | undefined;
|
|
14
8
|
export declare function buildRepairPacket(replay: FlowReplayResult): RepairPacket | undefined;
|
|
15
9
|
/** Build the repair packets for a set of replays (failed ones only). */
|
|
16
10
|
export declare function buildRepairPackets(replays: ReadonlyArray<FlowReplayResult>): RepairPacket[];
|
|
@@ -36,11 +36,11 @@ function suggestedPrompt(name, actual, where, nextAction) {
|
|
|
36
36
|
* the decision's whatChanged, falling back to the replay error or a generic message.
|
|
37
37
|
*/
|
|
38
38
|
/** The deviation report's headline when it flagged something — narrows the replay's `unknown` deviation. */
|
|
39
|
-
|
|
40
|
-
if (typeof deviation !== 'object' ||
|
|
39
|
+
function deviationHeadline(deviation) {
|
|
40
|
+
if (typeof deviation !== 'object' || null === deviation)
|
|
41
41
|
return undefined;
|
|
42
42
|
const d = deviation;
|
|
43
|
-
if (Array.isArray(d.deviations) && d.deviations.length > 0 && typeof d.headline
|
|
43
|
+
if (Array.isArray(d.deviations) && d.deviations.length > 0 && 'string' === typeof d.headline) {
|
|
44
44
|
return d.headline;
|
|
45
45
|
}
|
|
46
46
|
return undefined;
|
|
@@ -62,7 +62,7 @@ export function buildRisks(changedFiles, policy = {}) {
|
|
|
62
62
|
const risks = [];
|
|
63
63
|
for (const { surface } of RISK_PATTERNS) {
|
|
64
64
|
const files = filesBySurface.get(surface);
|
|
65
|
-
if (files === undefined || files.length
|
|
65
|
+
if (files === undefined || 0 === files.length)
|
|
66
66
|
continue;
|
|
67
67
|
risks.push({
|
|
68
68
|
surface,
|
package/dist/runs/run-diff.d.ts
CHANGED
|
@@ -22,8 +22,6 @@ export interface RunDiff {
|
|
|
22
22
|
};
|
|
23
23
|
headline: string;
|
|
24
24
|
}
|
|
25
|
-
/** Below this percent, a duration change is noise (machine jitter), not a regression. */
|
|
26
|
-
export declare const DEFAULT_NOISE_FLOOR_PCT = 10;
|
|
27
25
|
/**
|
|
28
26
|
* Compare two verification runs — the concrete answer to "what changed between run A and B". Flow
|
|
29
27
|
* durations are diffed with a noise floor (jitter below it is ignored); status changes and new/removed
|
package/dist/runs/run-diff.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
/** Below this percent, a duration change is noise (machine jitter), not a regression. */
|
|
2
|
-
|
|
2
|
+
const DEFAULT_NOISE_FLOOR_PCT = 10;
|
|
3
3
|
function pct(before, delta) {
|
|
4
4
|
return before > 0 ? Math.round((delta / before) * 100) : 0;
|
|
5
5
|
}
|
|
@@ -11,7 +11,7 @@ function headlineFor(diff) {
|
|
|
11
11
|
const regressions = diff.flows.filter((f) => f.regressed);
|
|
12
12
|
if (regressions.length > 0) {
|
|
13
13
|
const worst = regressions[0];
|
|
14
|
-
parts.push(`${String(regressions.length)} regression${regressions.length
|
|
14
|
+
parts.push(`${String(regressions.length)} regression${1 === regressions.length ? '' : 's'} (worst: ${worst?.name ?? ''} ${String(worst?.durationDeltaPct ?? 0)}%)`);
|
|
15
15
|
}
|
|
16
16
|
if (diff.newFlows.length > 0)
|
|
17
17
|
parts.push(`+${String(diff.newFlows.length)} flow`);
|
|
@@ -20,7 +20,7 @@ function headlineFor(diff) {
|
|
|
20
20
|
if (diff.verdictChange !== undefined) {
|
|
21
21
|
parts.push(`verdict ${diff.verdictChange.from}→${diff.verdictChange.to}`);
|
|
22
22
|
}
|
|
23
|
-
return parts.length
|
|
23
|
+
return 0 === parts.length ? 'no significant change between runs' : parts.join(', ');
|
|
24
24
|
}
|
|
25
25
|
/**
|
|
26
26
|
* Compare two verification runs — the concrete answer to "what changed between run A and B". Flow
|
package/dist/runs/run-tools.js
CHANGED
|
@@ -38,7 +38,7 @@ export const RUN_TOOLS = [
|
|
|
38
38
|
handler: async (deps, args) => {
|
|
39
39
|
const store = new RunStore(deps.fs, deps.reticleRoot);
|
|
40
40
|
// format:"diff" is a whole-history operation (two most-recent runs), not a single-run read.
|
|
41
|
-
if (asString(args['format'])
|
|
41
|
+
if ('diff' === asString(args['format'])) {
|
|
42
42
|
const pair = await store.latestTwo();
|
|
43
43
|
if (pair === undefined) {
|
|
44
44
|
return {
|
|
@@ -75,7 +75,7 @@ export const RUN_TOOLS = [
|
|
|
75
75
|
}
|
|
76
76
|
run = latest;
|
|
77
77
|
}
|
|
78
|
-
return asString(args['format'])
|
|
78
|
+
return 'report' === asString(args['format']) ? { report: renderRunReport(run) } : { run };
|
|
79
79
|
},
|
|
80
80
|
},
|
|
81
81
|
];
|
|
@@ -41,7 +41,7 @@ function assembleRun(deps, timed, projectId) {
|
|
|
41
41
|
* unaffected. Returns the runId (for logging/tests); undefined if nothing was produced (empty suite).
|
|
42
42
|
*/
|
|
43
43
|
export async function persistAndSyncVerificationRun(deps, timed, projectId) {
|
|
44
|
-
if (timed.length
|
|
44
|
+
if (0 === timed.length)
|
|
45
45
|
return undefined;
|
|
46
46
|
let run;
|
|
47
47
|
try {
|
|
@@ -56,7 +56,7 @@ export async function persistAndSyncVerificationRun(deps, timed, projectId) {
|
|
|
56
56
|
}
|
|
57
57
|
// Per-project cloud: only push when THIS project has cloud attached AND its policy allows runs.
|
|
58
58
|
const cloud = await resolveProjectCloud(deps.fs, deps.reticleRoot, homedir(), process.env);
|
|
59
|
-
if (cloud.config
|
|
59
|
+
if (null === cloud.config || !cloud.policy.runs)
|
|
60
60
|
return run.runId; // not attached / runs disabled → local only
|
|
61
61
|
const result = await syncRunToCloud(run, cloud.config, (url, init) => fetch(url, init));
|
|
62
62
|
if (result.outcome !== SyncOutcome.SYNCED) {
|
package/dist/runs/verify-http.js
CHANGED
|
@@ -67,7 +67,7 @@ function toVerifyOptions(body) {
|
|
|
67
67
|
}
|
|
68
68
|
/** Constant-time token check. Empty expected token ⇒ open (localhost-only deployments). */
|
|
69
69
|
export function tokenOk(provided, expected) {
|
|
70
|
-
if (expected.length
|
|
70
|
+
if (0 === expected.length)
|
|
71
71
|
return true;
|
|
72
72
|
if (provided === undefined)
|
|
73
73
|
return false;
|
|
@@ -91,7 +91,7 @@ export function startVerifyServer(opts, port) {
|
|
|
91
91
|
return new Promise((resolve) => {
|
|
92
92
|
server.listen(port, LOCALHOST, () => {
|
|
93
93
|
const address = server.address();
|
|
94
|
-
const boundPort = typeof address
|
|
94
|
+
const boundPort = 'object' === typeof address && address !== null ? address.port : port;
|
|
95
95
|
resolve({ server, port: boundPort });
|
|
96
96
|
});
|
|
97
97
|
});
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a session was attached for the whole window an agent is about to reason about.
|
|
3
|
+
*
|
|
4
|
+
* `reticle_sessions` answers "which tabs are connected RIGHT NOW", and **a tab that dropped for four
|
|
5
|
+
* seconds and came back looks identical to one that never dropped** (#117). That is the difference
|
|
6
|
+
* between a verdict you can trust and one that describes what you happened to see — the same problem
|
|
7
|
+
* `honesty.integrity` solves for a single action, applied to the session.
|
|
8
|
+
*
|
|
9
|
+
* Measured HERE rather than reported by the SDK. The browser transport does track
|
|
10
|
+
* `#disconnectedSince` (`transport.ts:95`), and reading it would need a wire change and a new thing
|
|
11
|
+
* for every SDK version to remember to send. The daemon already sees both halves — `remove()` when
|
|
12
|
+
* the socket drops, `add()` when it returns — so the gap is computable with no protocol change at
|
|
13
|
+
* all, and it cannot drift out of sync with what the daemon actually observed.
|
|
14
|
+
*
|
|
15
|
+
* The clock is injected, per the repo rule: this is arithmetic over timestamps, and a test that
|
|
16
|
+
* needs to wait four seconds to check a four-second gap is a test nobody runs.
|
|
17
|
+
*/
|
|
18
|
+
/** What an agent needs to know about the continuity of one session. */
|
|
19
|
+
export interface Attachment {
|
|
20
|
+
/** How long THIS attachment has lasted. Resets on reconnect — it is not the session's lifetime. */
|
|
21
|
+
connectedSinceMs: number;
|
|
22
|
+
/** How many times this session dropped and came back. Zero means it never left. */
|
|
23
|
+
outages: number;
|
|
24
|
+
/** The most recent gap, when there has been one. */
|
|
25
|
+
lastOutage?: {
|
|
26
|
+
startedMs: number;
|
|
27
|
+
durationMs: number;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
export declare class AttachmentHistory {
|
|
31
|
+
#private;
|
|
32
|
+
constructor(now?: () => number);
|
|
33
|
+
/** A session connected, or reconnected. A reconnect closes the open gap and counts an outage. */
|
|
34
|
+
attached(sessionId: string): void;
|
|
35
|
+
/** A session dropped. The gap stays open until it comes back, or the record is forgotten. */
|
|
36
|
+
detached(sessionId: string): void;
|
|
37
|
+
/** Drop a session's history. A long-lived daemon must not accumulate one record per tab forever. */
|
|
38
|
+
forget(sessionId: string): void;
|
|
39
|
+
/**
|
|
40
|
+
* The continuity of one session, or `undefined` when it has never been seen.
|
|
41
|
+
*
|
|
42
|
+
* Undefined rather than a zeroed record on purpose: `outages: 0` reads as "it never dropped", which
|
|
43
|
+
* is a confident claim about a session this has no knowledge of.
|
|
44
|
+
*/
|
|
45
|
+
of(sessionId: string): Attachment | undefined;
|
|
46
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Whether a session was attached for the whole window an agent is about to reason about.
|
|
3
|
+
*
|
|
4
|
+
* `reticle_sessions` answers "which tabs are connected RIGHT NOW", and **a tab that dropped for four
|
|
5
|
+
* seconds and came back looks identical to one that never dropped** (#117). That is the difference
|
|
6
|
+
* between a verdict you can trust and one that describes what you happened to see — the same problem
|
|
7
|
+
* `honesty.integrity` solves for a single action, applied to the session.
|
|
8
|
+
*
|
|
9
|
+
* Measured HERE rather than reported by the SDK. The browser transport does track
|
|
10
|
+
* `#disconnectedSince` (`transport.ts:95`), and reading it would need a wire change and a new thing
|
|
11
|
+
* for every SDK version to remember to send. The daemon already sees both halves — `remove()` when
|
|
12
|
+
* the socket drops, `add()` when it returns — so the gap is computable with no protocol change at
|
|
13
|
+
* all, and it cannot drift out of sync with what the daemon actually observed.
|
|
14
|
+
*
|
|
15
|
+
* The clock is injected, per the repo rule: this is arithmetic over timestamps, and a test that
|
|
16
|
+
* needs to wait four seconds to check a four-second gap is a test nobody runs.
|
|
17
|
+
*/
|
|
18
|
+
export class AttachmentHistory {
|
|
19
|
+
#now;
|
|
20
|
+
#records = new Map();
|
|
21
|
+
constructor(now = Date.now) {
|
|
22
|
+
this.#now = now;
|
|
23
|
+
}
|
|
24
|
+
/** A session connected, or reconnected. A reconnect closes the open gap and counts an outage. */
|
|
25
|
+
attached(sessionId) {
|
|
26
|
+
const at = this.#now();
|
|
27
|
+
const prior = this.#records.get(sessionId);
|
|
28
|
+
if (prior?.detachedAt === undefined) {
|
|
29
|
+
this.#records.set(sessionId, { attachedAt: at, outages: prior?.outages ?? 0 });
|
|
30
|
+
return;
|
|
31
|
+
}
|
|
32
|
+
this.#records.set(sessionId, {
|
|
33
|
+
attachedAt: at,
|
|
34
|
+
outages: prior.outages + 1,
|
|
35
|
+
lastOutage: { startedMs: prior.detachedAt, durationMs: at - prior.detachedAt },
|
|
36
|
+
});
|
|
37
|
+
}
|
|
38
|
+
/** A session dropped. The gap stays open until it comes back, or the record is forgotten. */
|
|
39
|
+
detached(sessionId) {
|
|
40
|
+
const prior = this.#records.get(sessionId);
|
|
41
|
+
if (prior === undefined)
|
|
42
|
+
return;
|
|
43
|
+
this.#records.set(sessionId, { ...prior, detachedAt: this.#now() });
|
|
44
|
+
}
|
|
45
|
+
/** Drop a session's history. A long-lived daemon must not accumulate one record per tab forever. */
|
|
46
|
+
forget(sessionId) {
|
|
47
|
+
this.#records.delete(sessionId);
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* The continuity of one session, or `undefined` when it has never been seen.
|
|
51
|
+
*
|
|
52
|
+
* Undefined rather than a zeroed record on purpose: `outages: 0` reads as "it never dropped", which
|
|
53
|
+
* is a confident claim about a session this has no knowledge of.
|
|
54
|
+
*/
|
|
55
|
+
of(sessionId) {
|
|
56
|
+
const record = this.#records.get(sessionId);
|
|
57
|
+
if (record === undefined)
|
|
58
|
+
return undefined;
|
|
59
|
+
return {
|
|
60
|
+
connectedSinceMs: this.#now() - record.attachedAt,
|
|
61
|
+
outages: record.outages,
|
|
62
|
+
...(record.lastOutage === undefined ? {} : { lastOutage: record.lastOutage }),
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { AppRuntime } from '@reticlehq/core';
|
|
1
2
|
/**
|
|
2
3
|
* Turn a bare command timeout into something the reader can act on.
|
|
3
4
|
*
|
|
@@ -21,9 +22,15 @@
|
|
|
21
22
|
* The advice is ADDED, never substituted — the original fact still leads — and only for a runtime
|
|
22
23
|
* that can actually suffer it, since misdirecting an Electron user costs them the same hour.
|
|
23
24
|
*/
|
|
24
|
-
/**
|
|
25
|
-
|
|
26
|
-
|
|
25
|
+
/**
|
|
26
|
+
* What the page told us about its shell, via PAGE_HEALTH. Undefined before the first report.
|
|
27
|
+
*
|
|
28
|
+
* An alias of core's AppRuntime rather than a second list of the same three strings: the SDK reports
|
|
29
|
+
* this value, so it is a wire value, and two independent spellings of it is how one side gains a
|
|
30
|
+
* runtime the other silently refuses to recognise.
|
|
31
|
+
*/
|
|
32
|
+
export type PageRuntime = AppRuntime;
|
|
33
|
+
interface TimeoutContext {
|
|
27
34
|
url: string;
|
|
28
35
|
/** The page's own last visibility report. */
|
|
29
36
|
hidden: boolean;
|
|
@@ -33,3 +40,4 @@ export interface TimeoutContext {
|
|
|
33
40
|
lastSeenMs?: number;
|
|
34
41
|
}
|
|
35
42
|
export declare function commandTimeoutMessage(name: string, timeoutMs: number, context: TimeoutContext): string;
|
|
43
|
+
export {};
|