@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
|
@@ -7,7 +7,7 @@ export interface JournalTarget {
|
|
|
7
7
|
elapsed(): number;
|
|
8
8
|
setJournal(recorder: JournalRecorder, reader?: JournalReader): void;
|
|
9
9
|
}
|
|
10
|
-
|
|
10
|
+
interface JournalAttachDeps {
|
|
11
11
|
fs: FileSystemPort;
|
|
12
12
|
reticleRoot: string;
|
|
13
13
|
/** Journaling is on by default; the opt-out (`.reticle.json` journal:false / env) sets this false. */
|
|
@@ -19,3 +19,4 @@ export interface JournalAttachDeps {
|
|
|
19
19
|
* journaling concern). The recorder's clock is the session's own elapsed time.
|
|
20
20
|
*/
|
|
21
21
|
export declare function makeJournalAttach(deps: JournalAttachDeps): (session: JournalTarget) => void;
|
|
22
|
+
export {};
|
|
@@ -6,13 +6,13 @@ function headlineFor(report) {
|
|
|
6
6
|
if (report.insufficientSamples) {
|
|
7
7
|
return `envelope too new (need ${String(MIN_ENVELOPE_SAMPLES)} runs) — see causal summary${truncNote}`;
|
|
8
8
|
}
|
|
9
|
-
if (report.deviations.length
|
|
10
|
-
const s = report.nominalSegments
|
|
9
|
+
if (0 === report.deviations.length) {
|
|
10
|
+
const s = 1 === report.nominalSegments ? '' : 's';
|
|
11
11
|
return `${String(report.nominalSegments)} segment${s} nominal${truncNote}`;
|
|
12
12
|
}
|
|
13
13
|
const routes = [...new Set(report.deviations.map((d) => d.route))].join(', ');
|
|
14
14
|
const n = report.deviations.length;
|
|
15
|
-
return `${String(n)} deviation${
|
|
15
|
+
return `${String(n)} deviation${1 === n ? '' : 's'}: ${routes}${truncNote}`;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
18
|
* Judge observed segments against their per-route envelopes. Segments without a route, or whose
|
|
@@ -27,7 +27,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
|
|
|
27
27
|
if (segment.route === undefined)
|
|
28
28
|
continue;
|
|
29
29
|
// A truncated segment's counts understate reality — judging it could read a false "nominal".
|
|
30
|
-
if (segment.truncated
|
|
30
|
+
if (true === segment.truncated) {
|
|
31
31
|
truncated += 1;
|
|
32
32
|
continue;
|
|
33
33
|
}
|
|
@@ -36,7 +36,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
|
|
|
36
36
|
continue;
|
|
37
37
|
judged += 1;
|
|
38
38
|
const segDeviations = compareSegment(envelope, segment, zThreshold);
|
|
39
|
-
if (segDeviations.length
|
|
39
|
+
if (0 === segDeviations.length)
|
|
40
40
|
nominal += 1;
|
|
41
41
|
else
|
|
42
42
|
deviations.push(...segDeviations);
|
|
@@ -47,7 +47,7 @@ export function buildDeviationReport(envelopes, segments, zThreshold) {
|
|
|
47
47
|
nominalSegments: nominal,
|
|
48
48
|
judgedSegments: judged,
|
|
49
49
|
truncatedSegments: truncated,
|
|
50
|
-
insufficientSamples:
|
|
50
|
+
insufficientSamples: 0 === judged,
|
|
51
51
|
};
|
|
52
52
|
return { ...base, headline: headlineFor(base) };
|
|
53
53
|
}
|
|
@@ -20,7 +20,7 @@ export async function reportAndAccumulate(store, segments, zThreshold) {
|
|
|
20
20
|
if (segment.route === undefined)
|
|
21
21
|
continue;
|
|
22
22
|
// Never learn from a truncated sample — its understated counts would poison the baseline.
|
|
23
|
-
if (segment.truncated
|
|
23
|
+
if (true === segment.truncated)
|
|
24
24
|
continue;
|
|
25
25
|
const current = envelopes.get(segment.route) ?? emptyEnvelope(segment.route);
|
|
26
26
|
envelopes.set(segment.route, addSegmentToEnvelope(current, segment));
|
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
import type { FileSystemPort } from '../project/fs-port.js';
|
|
2
2
|
import { type RouteEnvelope } from './envelope.js';
|
|
3
|
-
/** Bumped on any breaking change to the persisted envelope shape (matches the runs/contract convention). */
|
|
4
|
-
export declare const ENVELOPE_FILE_VERSION = 1;
|
|
5
3
|
/**
|
|
6
4
|
* Persists the learned per-route envelopes at `.reticle/envelopes.json`. Local, single-project statistics
|
|
7
5
|
* (single-player memory stays OSS — OSS-VS-SERVER). Loads never throw: a missing, malformed, or
|
|
@@ -3,7 +3,7 @@ import { dirname } from 'node:path';
|
|
|
3
3
|
import { reticleDirPaths } from '../project/reticle-dir.js';
|
|
4
4
|
import { RouteEnvelopeSchema } from './envelope.js';
|
|
5
5
|
/** Bumped on any breaking change to the persisted envelope shape (matches the runs/contract convention). */
|
|
6
|
-
|
|
6
|
+
const ENVELOPE_FILE_VERSION = 1;
|
|
7
7
|
const EnvelopeFileSchema = z.object({
|
|
8
8
|
version: z.literal(ENVELOPE_FILE_VERSION),
|
|
9
9
|
routes: z.record(RouteEnvelopeSchema),
|
|
@@ -21,7 +21,7 @@ export declare function stddev(stats: MetricStats): number;
|
|
|
21
21
|
/** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
|
|
22
22
|
export declare function zScore(stats: MetricStats, x: number): number;
|
|
23
23
|
/** The metrics an envelope tracks per route. */
|
|
24
|
-
|
|
24
|
+
declare const ENVELOPE_METRICS: readonly ["durationMs", "net", "netErrors", "consoleErrors"];
|
|
25
25
|
export type EnvelopeMetric = (typeof ENVELOPE_METRICS)[number];
|
|
26
26
|
export interface RouteEnvelope {
|
|
27
27
|
route: string;
|
|
@@ -31,8 +31,6 @@ export interface RouteEnvelope {
|
|
|
31
31
|
}
|
|
32
32
|
/** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
|
|
33
33
|
export declare const MIN_ENVELOPE_SAMPLES = 3;
|
|
34
|
-
/** Default flag threshold in stddevs. The number is a placeholder for fleet-calibrated priors. */
|
|
35
|
-
export declare const DEFAULT_Z_THRESHOLD = 3;
|
|
36
34
|
/** Persisted shape of a route envelope. Validated on load; a bad file degrades to no envelope. */
|
|
37
35
|
export declare const RouteEnvelopeSchema: z.ZodObject<{
|
|
38
36
|
route: z.ZodString;
|
|
@@ -229,3 +227,4 @@ export interface Deviation {
|
|
|
229
227
|
* falls back to the causal summary in that case.
|
|
230
228
|
*/
|
|
231
229
|
export declare function compareSegment(envelope: RouteEnvelope, segment: SegmentRollup, zThreshold?: number): Deviation[];
|
|
230
|
+
export {};
|
package/dist/journal/envelope.js
CHANGED
|
@@ -15,14 +15,14 @@ export function stddev(stats) {
|
|
|
15
15
|
/** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
|
|
16
16
|
export function zScore(stats, x) {
|
|
17
17
|
const sd = stddev(stats);
|
|
18
|
-
return
|
|
18
|
+
return 0 === sd ? 0 : (x - stats.mean) / sd;
|
|
19
19
|
}
|
|
20
20
|
/** The metrics an envelope tracks per route. */
|
|
21
|
-
|
|
21
|
+
const ENVELOPE_METRICS = ['durationMs', 'net', 'netErrors', 'consoleErrors'];
|
|
22
22
|
/** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
|
|
23
23
|
export const MIN_ENVELOPE_SAMPLES = 3;
|
|
24
24
|
/** Default flag threshold in stddevs. The number is a placeholder for fleet-calibrated priors. */
|
|
25
|
-
|
|
25
|
+
const DEFAULT_Z_THRESHOLD = 3;
|
|
26
26
|
const MetricStatsSchema = z.object({
|
|
27
27
|
count: z.number(),
|
|
28
28
|
mean: z.number(),
|
|
@@ -8,7 +8,7 @@ export function mergeEventsBySeq(journal, buffer) {
|
|
|
8
8
|
const bySeq = new Map();
|
|
9
9
|
const noSeq = [];
|
|
10
10
|
for (const event of [...journal, ...buffer]) {
|
|
11
|
-
if (typeof event.seq
|
|
11
|
+
if ('number' === typeof event.seq)
|
|
12
12
|
bySeq.set(event.seq, event);
|
|
13
13
|
else
|
|
14
14
|
noSeq.push(event);
|
|
@@ -8,7 +8,7 @@ export interface JournalSink {
|
|
|
8
8
|
export interface JournalReader {
|
|
9
9
|
readEvents(): Promise<ReticleEvent[]>;
|
|
10
10
|
}
|
|
11
|
-
|
|
11
|
+
interface JournalRecorderOptions {
|
|
12
12
|
/** Injected elapsed-ms clock (never read from Date here — the clock-injection rule). */
|
|
13
13
|
now: () => number;
|
|
14
14
|
/** Flush the pending-event batch once this many accumulate. */
|
|
@@ -35,3 +35,4 @@ export declare class JournalRecorder {
|
|
|
35
35
|
/** Persist any buffered events now (call on session end). Awaits the write chain to settle. */
|
|
36
36
|
flush(): Promise<void>;
|
|
37
37
|
}
|
|
38
|
+
export {};
|
|
@@ -27,7 +27,7 @@ export class JournalRecorder {
|
|
|
27
27
|
const active = this.#active;
|
|
28
28
|
if (active !== undefined) {
|
|
29
29
|
out = { ...event, actionId: active.actionId, attribution: EventAttribution.WINDOW };
|
|
30
|
-
if (typeof event.seq
|
|
30
|
+
if ('number' === typeof event.seq) {
|
|
31
31
|
active.seqFrom =
|
|
32
32
|
active.seqFrom === undefined ? event.seq : Math.min(active.seqFrom, event.seq);
|
|
33
33
|
active.seqTo = active.seqTo === undefined ? event.seq : Math.max(active.seqTo, event.seq);
|
|
@@ -71,7 +71,7 @@ export class JournalRecorder {
|
|
|
71
71
|
await this.#chain;
|
|
72
72
|
}
|
|
73
73
|
#enqueueFlush() {
|
|
74
|
-
if (this.#pending.length
|
|
74
|
+
if (0 === this.#pending.length)
|
|
75
75
|
return;
|
|
76
76
|
const batch = this.#pending;
|
|
77
77
|
this.#pending = [];
|
package/dist/journal/rollups.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { EventType } from '@reticlehq/core';
|
|
1
|
+
import { EventType, StreamDirection } from '@reticlehq/core';
|
|
2
2
|
function finalize(acc) {
|
|
3
3
|
return {
|
|
4
4
|
...(acc.route === undefined ? {} : { route: acc.route }),
|
|
@@ -9,13 +9,13 @@ function finalize(acc) {
|
|
|
9
9
|
net: { total: acc.netTotal, errors: acc.netErrors },
|
|
10
10
|
consoleErrors: acc.consoleErrors,
|
|
11
11
|
statePathsChanged: acc.statePaths,
|
|
12
|
-
...(acc.streams.frames
|
|
12
|
+
...(0 === acc.streams.frames ? {} : { streams: acc.streams }),
|
|
13
13
|
...(acc.truncated ? { truncated: true } : {}),
|
|
14
14
|
};
|
|
15
15
|
}
|
|
16
16
|
function isNetError(event) {
|
|
17
17
|
const status = event.data['status'];
|
|
18
|
-
return event.data['ok']
|
|
18
|
+
return false === event.data['ok'] || ('number' === typeof status && status >= 400);
|
|
19
19
|
}
|
|
20
20
|
/**
|
|
21
21
|
* Fold an ordered event list into route segments split at each ROUTE_CHANGE. Pure: no clock, no IO —
|
|
@@ -41,13 +41,13 @@ export function computeSegments(events) {
|
|
|
41
41
|
if (acc !== undefined)
|
|
42
42
|
segments.push(finalize(acc));
|
|
43
43
|
const pathname = event.data['pathname'];
|
|
44
|
-
acc = open(typeof pathname
|
|
44
|
+
acc = open('string' === typeof pathname ? pathname : undefined, event.t);
|
|
45
45
|
continue;
|
|
46
46
|
}
|
|
47
47
|
if (acc === undefined)
|
|
48
48
|
acc = open(undefined, event.t);
|
|
49
49
|
acc.to = event.t;
|
|
50
|
-
if (typeof event.actionId
|
|
50
|
+
if ('string' === typeof event.actionId)
|
|
51
51
|
acc.actionIds.add(event.actionId);
|
|
52
52
|
if (event.type === EventType.NET_REQUEST) {
|
|
53
53
|
acc.netTotal += 1;
|
|
@@ -59,17 +59,17 @@ export function computeSegments(events) {
|
|
|
59
59
|
}
|
|
60
60
|
if (event.type === EventType.STATE_CHANGE) {
|
|
61
61
|
const name = event.data['name'];
|
|
62
|
-
if (typeof name
|
|
62
|
+
if ('string' === typeof name && !acc.statePaths.includes(name))
|
|
63
63
|
acc.statePaths.push(name);
|
|
64
64
|
}
|
|
65
65
|
if (event.type === EventType.NET_STREAM) {
|
|
66
66
|
acc.streams.frames += 1;
|
|
67
67
|
const direction = event.data['direction'];
|
|
68
|
-
if (
|
|
68
|
+
if (StreamDirection.OPEN === direction)
|
|
69
69
|
acc.streams.opened += 1;
|
|
70
|
-
else if (
|
|
70
|
+
else if (StreamDirection.IN === direction)
|
|
71
71
|
acc.streams.in += 1;
|
|
72
|
-
else if (
|
|
72
|
+
else if (StreamDirection.OUT === direction)
|
|
73
73
|
acc.streams.out += 1;
|
|
74
74
|
}
|
|
75
75
|
if (event.type === EventType.TRUNCATED || event.type === EventType.TRANSPORT_OVERFLOW) {
|
|
@@ -17,7 +17,7 @@ export interface SessionEndTarget {
|
|
|
17
17
|
ambientCounts(): AmbientCounts;
|
|
18
18
|
ownAmbientCounts(): AmbientCounts;
|
|
19
19
|
}
|
|
20
|
-
|
|
20
|
+
interface SessionEndDeps {
|
|
21
21
|
fs: FileSystemPort;
|
|
22
22
|
reticleRoot: string;
|
|
23
23
|
/** Journaling/persistence off (opt-out) → teardown is a no-op. */
|
|
@@ -29,3 +29,4 @@ export interface SessionEndDeps {
|
|
|
29
29
|
* starts already knowing which regions churn.
|
|
30
30
|
*/
|
|
31
31
|
export declare function makeSessionEnd(deps: SessionEndDeps): (session: SessionEndTarget) => Promise<void>;
|
|
32
|
+
export {};
|
|
@@ -37,7 +37,7 @@ export class SessionJournal {
|
|
|
37
37
|
this.#sessionId = sessionId;
|
|
38
38
|
}
|
|
39
39
|
async appendEvents(events) {
|
|
40
|
-
if (events.length
|
|
40
|
+
if (0 === events.length)
|
|
41
41
|
return;
|
|
42
42
|
await this.#ensureDir();
|
|
43
43
|
const text = `${events.map((e) => JSON.stringify(e)).join('\n')}\n`;
|
|
@@ -108,11 +108,11 @@ export class SessionJournal {
|
|
|
108
108
|
#ingestTail(tail) {
|
|
109
109
|
const cache = this.#eventCache ?? (this.#eventCache = []);
|
|
110
110
|
const end = tail.lastIndexOf('\n') + 1;
|
|
111
|
-
if (
|
|
111
|
+
if (0 === end)
|
|
112
112
|
return 0; // no complete line yet
|
|
113
113
|
const complete = tail.slice(0, end);
|
|
114
114
|
for (const line of complete.split('\n')) {
|
|
115
|
-
if (line.length
|
|
115
|
+
if (0 === line.length)
|
|
116
116
|
continue;
|
|
117
117
|
let parsed;
|
|
118
118
|
try {
|
|
@@ -148,7 +148,7 @@ export class SessionJournal {
|
|
|
148
148
|
}
|
|
149
149
|
const out = [];
|
|
150
150
|
for (const line of text.split('\n')) {
|
|
151
|
-
if (line.length
|
|
151
|
+
if (0 === line.length)
|
|
152
152
|
continue;
|
|
153
153
|
let parsed;
|
|
154
154
|
try {
|
|
@@ -70,20 +70,6 @@ export declare function assertEnterprise(feature: string, ctx: GateContext): voi
|
|
|
70
70
|
/** Env names that carry the activation: the operator's key, and the issuer public key baked at release. */
|
|
71
71
|
export declare const LICENSE_KEY_ENV = "RETICLE_LICENSE_KEY";
|
|
72
72
|
export declare const LICENSE_PUBLIC_KEY_ENV = "RETICLE_LICENSE_PUBLIC_KEY";
|
|
73
|
-
/**
|
|
74
|
-
* Issuer public key COMPILED INTO the build. Empty in the source tree; the release pipeline replaces
|
|
75
|
-
* this literal with the real spki PEM. Baking it (rather than only reading env) is what makes the
|
|
76
|
-
* enterprise gate fail closed: a self-hosted operator can no longer disable enforcement by simply
|
|
77
|
-
* never setting RETICLE_LICENSE_PUBLIC_KEY, because the baked key takes precedence. The public key is
|
|
78
|
-
* safe to ship openly — it can only verify licenses, never mint them (that needs the private key).
|
|
79
|
-
*/
|
|
80
|
-
export declare const BAKED_ISSUER_PUBLIC_KEY_PEM = "";
|
|
81
|
-
/**
|
|
82
|
-
* Resolve the issuer public-key PEM enforcement uses: the baked-in release key wins, so it can't be
|
|
83
|
-
* turned off from the environment. Only when nothing is baked (dev/repo) does the env var apply — that
|
|
84
|
-
* env path is the test/self-eval escape hatch, not the production switch.
|
|
85
|
-
*/
|
|
86
|
-
export declare function resolveIssuerPublicKeyPem(env: NodeJS.ProcessEnv, baked?: string): string | undefined;
|
|
87
73
|
/** The human-facing state of enterprise activation on this machine (what `reticle license status` shows). */
|
|
88
74
|
interface LicenseReport {
|
|
89
75
|
status: 'active' | 'missing' | 'invalid' | 'expired' | 'eval';
|
package/dist/license/license.js
CHANGED
|
@@ -37,13 +37,13 @@ export function signLicenseKey(payload, privateKey) {
|
|
|
37
37
|
}
|
|
38
38
|
/** Verify a key against the issuer public key. Never throws — returns a structured status. */
|
|
39
39
|
export function verifyLicenseKey(key, publicKey, now) {
|
|
40
|
-
if (key === undefined || key.length
|
|
40
|
+
if (key === undefined || 0 === key.length)
|
|
41
41
|
return { status: LicenseStatus.MISSING };
|
|
42
42
|
const parts = key.split(KEY_SEP);
|
|
43
43
|
if (parts.length !== 2 ||
|
|
44
44
|
parts[0] === undefined ||
|
|
45
45
|
parts[1] === undefined ||
|
|
46
|
-
parts[0].length
|
|
46
|
+
0 === parts[0].length) {
|
|
47
47
|
return { status: LicenseStatus.MALFORMED };
|
|
48
48
|
}
|
|
49
49
|
let json;
|
|
@@ -85,7 +85,7 @@ export class EnterpriseLicenseError extends Error {
|
|
|
85
85
|
/** The issuer public key from the environment (set at release / by the operator); undefined if unset. */
|
|
86
86
|
function issuerPublicKey() {
|
|
87
87
|
const pem = process.env[LICENSE_PUBLIC_KEY_ENV];
|
|
88
|
-
if (pem === undefined || pem.length
|
|
88
|
+
if (pem === undefined || 0 === pem.length)
|
|
89
89
|
return undefined;
|
|
90
90
|
try {
|
|
91
91
|
return createPublicKey(pem);
|
|
@@ -122,20 +122,20 @@ export const LICENSE_PUBLIC_KEY_ENV = 'RETICLE_LICENSE_PUBLIC_KEY';
|
|
|
122
122
|
* never setting RETICLE_LICENSE_PUBLIC_KEY, because the baked key takes precedence. The public key is
|
|
123
123
|
* safe to ship openly — it can only verify licenses, never mint them (that needs the private key).
|
|
124
124
|
*/
|
|
125
|
-
|
|
125
|
+
const BAKED_ISSUER_PUBLIC_KEY_PEM = '';
|
|
126
126
|
/**
|
|
127
127
|
* Resolve the issuer public-key PEM enforcement uses: the baked-in release key wins, so it can't be
|
|
128
128
|
* turned off from the environment. Only when nothing is baked (dev/repo) does the env var apply — that
|
|
129
129
|
* env path is the test/self-eval escape hatch, not the production switch.
|
|
130
130
|
*/
|
|
131
|
-
|
|
131
|
+
function resolveIssuerPublicKeyPem(env, baked = BAKED_ISSUER_PUBLIC_KEY_PEM) {
|
|
132
132
|
if (baked.length > 0)
|
|
133
133
|
return baked;
|
|
134
134
|
const envPem = env[LICENSE_PUBLIC_KEY_ENV];
|
|
135
135
|
return envPem !== undefined && envPem.length > 0 ? envPem : undefined;
|
|
136
136
|
}
|
|
137
137
|
function loadPublicKey(pem) {
|
|
138
|
-
if (pem === undefined || pem.length
|
|
138
|
+
if (pem === undefined || 0 === pem.length)
|
|
139
139
|
return undefined;
|
|
140
140
|
try {
|
|
141
141
|
return createPublicKey(pem);
|
|
@@ -151,7 +151,7 @@ function loadPublicKey(pem) {
|
|
|
151
151
|
*/
|
|
152
152
|
export function describeLicense(now, env = process.env, baked = BAKED_ISSUER_PUBLIC_KEY_PEM) {
|
|
153
153
|
const pem = resolveIssuerPublicKeyPem(env, baked);
|
|
154
|
-
if (pem === undefined || pem.length
|
|
154
|
+
if (pem === undefined || 0 === pem.length) {
|
|
155
155
|
// In a production runtime this is NOT a benign eval session — it is a mis-built release whose gate
|
|
156
156
|
// is off, and assertEnterpriseFromEnv now denies rather than unlocking. Say so loudly here too.
|
|
157
157
|
return isProductionEnv(env)
|
|
@@ -196,7 +196,7 @@ export function describeLicense(now, env = process.env, baked = BAKED_ISSUER_PUB
|
|
|
196
196
|
/** True in a production runtime (NODE_ENV=production) — where a missing issuer key is a mis-built
|
|
197
197
|
* release, not an eval session, so the gate must fail CLOSED rather than run features free. */
|
|
198
198
|
function isProductionEnv(env) {
|
|
199
|
-
return
|
|
199
|
+
return 'production' === env['NODE_ENV'];
|
|
200
200
|
}
|
|
201
201
|
/**
|
|
202
202
|
* Gate an enterprise feature using env-resolved activation. Enforcement is ON when the issuer public key
|
package/dist/log.d.ts
CHANGED
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Structured logging to stderr. stdout is reserved for the MCP stdio transport — never
|
|
3
3
|
* write logs there.
|
|
4
|
+
*
|
|
5
|
+
* Every line carries `t`, an ISO-8601 wall clock, FIRST.
|
|
6
|
+
*
|
|
7
|
+
* It did not, and that cost a real investigation its conclusion: `~/.reticle/daemon-4400.log` had
|
|
8
|
+
* grown to 24MB of events and not one of them could be placed in time, so "the daemon vanished right
|
|
9
|
+
* behind the proxy" could only ever be "points at" and never "is". Ordering the key first also means
|
|
10
|
+
* a huge log can be bisected by eye, and by `sort`, without parsing it.
|
|
11
|
+
*
|
|
12
|
+
* The clock is read here rather than injected: this is the I/O boundary, not pure logic, and a
|
|
13
|
+
* logger that needs its caller to supply the time is a logger callers will route around.
|
|
4
14
|
*/
|
|
5
15
|
export declare function log(event: string, fields?: Record<string, unknown>): void;
|
package/dist/log.js
CHANGED
|
@@ -1,8 +1,18 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Structured logging to stderr. stdout is reserved for the MCP stdio transport — never
|
|
3
3
|
* write logs there.
|
|
4
|
+
*
|
|
5
|
+
* Every line carries `t`, an ISO-8601 wall clock, FIRST.
|
|
6
|
+
*
|
|
7
|
+
* It did not, and that cost a real investigation its conclusion: `~/.reticle/daemon-4400.log` had
|
|
8
|
+
* grown to 24MB of events and not one of them could be placed in time, so "the daemon vanished right
|
|
9
|
+
* behind the proxy" could only ever be "points at" and never "is". Ordering the key first also means
|
|
10
|
+
* a huge log can be bisected by eye, and by `sort`, without parsing it.
|
|
11
|
+
*
|
|
12
|
+
* The clock is read here rather than injected: this is the I/O boundary, not pure logic, and a
|
|
13
|
+
* logger that needs its caller to supply the time is a logger callers will route around.
|
|
4
14
|
*/
|
|
5
15
|
export function log(event, fields = {}) {
|
|
6
|
-
const line = JSON.stringify({ event, ...fields });
|
|
16
|
+
const line = JSON.stringify({ t: new Date().toISOString(), event, ...fields });
|
|
7
17
|
process.stderr.write(`${line}\n`);
|
|
8
18
|
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does a SUCCESSFUL tool result actually describe a refusal?
|
|
3
|
+
*
|
|
4
|
+
* `isError` used to be set only when a handler threw. Every tool that returns a well-formed
|
|
5
|
+
* `{ error, recovery }` object instead — and that is half the surface — came back as protocol
|
|
6
|
+
* success with the flag unset, so anything branching on `isError` read a refusal as a result.
|
|
7
|
+
* Reported from a field sweep that had to special-case each tool's shape to score a run at all.
|
|
8
|
+
*
|
|
9
|
+
* A top-level `error` STRING is this codebase's refusal convention (see buildErrorPayload), so that
|
|
10
|
+
* is the whole test. Deliberately top-level only: `error` appears inside console entries and network
|
|
11
|
+
* rows as ordinary data, and flipping the flag for those would make it useless in the other direction.
|
|
12
|
+
*/
|
|
13
|
+
export declare function resultIsError(result: unknown): boolean;
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Does a SUCCESSFUL tool result actually describe a refusal?
|
|
3
|
+
*
|
|
4
|
+
* `isError` used to be set only when a handler threw. Every tool that returns a well-formed
|
|
5
|
+
* `{ error, recovery }` object instead — and that is half the surface — came back as protocol
|
|
6
|
+
* success with the flag unset, so anything branching on `isError` read a refusal as a result.
|
|
7
|
+
* Reported from a field sweep that had to special-case each tool's shape to score a run at all.
|
|
8
|
+
*
|
|
9
|
+
* A top-level `error` STRING is this codebase's refusal convention (see buildErrorPayload), so that
|
|
10
|
+
* is the whole test. Deliberately top-level only: `error` appears inside console entries and network
|
|
11
|
+
* rows as ordinary data, and flipping the flag for those would make it useless in the other direction.
|
|
12
|
+
*/
|
|
13
|
+
export function resultIsError(result) {
|
|
14
|
+
if (typeof result !== 'object' || null === result || Array.isArray(result))
|
|
15
|
+
return false;
|
|
16
|
+
const error = result.error;
|
|
17
|
+
return 'string' === typeof error && error.length > 0;
|
|
18
|
+
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporting that the agent lost its Reticle tools.
|
|
3
|
+
*
|
|
4
|
+
* The proxy already writes a full account of an outage to ~/.reticle/mcp-proxy.log, which is exactly
|
|
5
|
+
* where nobody looks and nothing aggregates. So the one question the transport must answer — how
|
|
6
|
+
* often does a real user's MCP server go down, and does it come back — had no answer outside the
|
|
7
|
+
* machine it happened on.
|
|
8
|
+
*
|
|
9
|
+
* Capped at two events per proxy process, and the cap is the design rather than a limitation. One
|
|
10
|
+
* measured afternoon produced 547 proxy reconnects; an event per reconnect would bill for the
|
|
11
|
+
* pathology instead of measuring it, which is the same mistake the per-call `tool` event made before
|
|
12
|
+
* it was removed. What a dashboard needs is the SHARE OF SESSIONS that lose MCP at all (the first
|
|
13
|
+
* outage) and the share where it never came back on its own (the budget being spent).
|
|
14
|
+
*/
|
|
15
|
+
import { OutageReason, OutageStage } from '@reticlehq/core';
|
|
16
|
+
/**
|
|
17
|
+
* `OutageStage` and `OutageReason` are core's — this re-export only saves the proxy an import. They
|
|
18
|
+
* cross the wire, so the vocabulary lives in the contract package and is never re-listed here.
|
|
19
|
+
*/
|
|
20
|
+
export { OutageReason, OutageStage };
|
|
21
|
+
/** Reset between tests; a real process reports each stage at most once. */
|
|
22
|
+
export declare function resetOutageReporting(): void;
|
|
23
|
+
/**
|
|
24
|
+
* Report one stage of an outage, at most once per process. Fire-and-forget on purpose: this runs on
|
|
25
|
+
* the transport's recovery path, and a telemetry POST must never be the thing that delays — or
|
|
26
|
+
* fails — the reconnect it is describing.
|
|
27
|
+
*/
|
|
28
|
+
export declare function reportMcpOutage(stage: OutageStage, facts: {
|
|
29
|
+
reason: string;
|
|
30
|
+
attempts: number;
|
|
31
|
+
pendingLost?: number;
|
|
32
|
+
}): void;
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Reporting that the agent lost its Reticle tools.
|
|
3
|
+
*
|
|
4
|
+
* The proxy already writes a full account of an outage to ~/.reticle/mcp-proxy.log, which is exactly
|
|
5
|
+
* where nobody looks and nothing aggregates. So the one question the transport must answer — how
|
|
6
|
+
* often does a real user's MCP server go down, and does it come back — had no answer outside the
|
|
7
|
+
* machine it happened on.
|
|
8
|
+
*
|
|
9
|
+
* Capped at two events per proxy process, and the cap is the design rather than a limitation. One
|
|
10
|
+
* measured afternoon produced 547 proxy reconnects; an event per reconnect would bill for the
|
|
11
|
+
* pathology instead of measuring it, which is the same mistake the per-call `tool` event made before
|
|
12
|
+
* it was removed. What a dashboard needs is the SHARE OF SESSIONS that lose MCP at all (the first
|
|
13
|
+
* outage) and the share where it never came back on its own (the budget being spent).
|
|
14
|
+
*/
|
|
15
|
+
import { OutageReason, OutageStage, TelemetryEventKind } from '@reticlehq/core';
|
|
16
|
+
import { getTelemetry } from '../telemetry/telemetry.js';
|
|
17
|
+
/**
|
|
18
|
+
* `OutageStage` and `OutageReason` are core's — this re-export only saves the proxy an import. They
|
|
19
|
+
* cross the wire, so the vocabulary lives in the contract package and is never re-listed here.
|
|
20
|
+
*/
|
|
21
|
+
export { OutageReason, OutageStage };
|
|
22
|
+
/**
|
|
23
|
+
* The proxy's reason strings are free text: they also feed `proxyLog`, where prose is fine, and the
|
|
24
|
+
* wire refuses anything unbounded. Unrecognised reports as `other` rather than being forwarded, so a
|
|
25
|
+
* new drop path can appear in the proxy without an unclassified string leaving the machine.
|
|
26
|
+
*/
|
|
27
|
+
const KNOWN_REASONS = new Set(Object.values(OutageReason));
|
|
28
|
+
function outageReason(raw) {
|
|
29
|
+
return KNOWN_REASONS.has(raw) ? raw : OutageReason.OTHER;
|
|
30
|
+
}
|
|
31
|
+
const reported = new Set();
|
|
32
|
+
/** Reset between tests; a real process reports each stage at most once. */
|
|
33
|
+
export function resetOutageReporting() {
|
|
34
|
+
reported.clear();
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Report one stage of an outage, at most once per process. Fire-and-forget on purpose: this runs on
|
|
38
|
+
* the transport's recovery path, and a telemetry POST must never be the thing that delays — or
|
|
39
|
+
* fails — the reconnect it is describing.
|
|
40
|
+
*/
|
|
41
|
+
export function reportMcpOutage(stage, facts) {
|
|
42
|
+
if (reported.has(stage))
|
|
43
|
+
return;
|
|
44
|
+
reported.add(stage);
|
|
45
|
+
void getTelemetry().emit(TelemetryEventKind.MCP_CONNECTION_LOST, {
|
|
46
|
+
outage: {
|
|
47
|
+
stage,
|
|
48
|
+
reason: outageReason(facts.reason),
|
|
49
|
+
attempts: facts.attempts,
|
|
50
|
+
// Always sent, including zero: zero is the finding — a drop no agent could feel. See
|
|
51
|
+
// McpOutageSchema.pendingLost.
|
|
52
|
+
pendingLost: facts.pendingLost ?? 0,
|
|
53
|
+
},
|
|
54
|
+
});
|
|
55
|
+
}
|