@reticlehq/server 2.2.1 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/bridge-security.d.ts +0 -1
- package/dist/bridge-security.js +0 -1
- package/dist/bridge.d.ts +0 -1
- package/dist/bridge.js +102 -12
- package/dist/bridge.test-harness.d.ts +5 -1
- package/dist/bridge.test-harness.js +12 -1
- package/dist/capsule/capsule-store.d.ts +2 -3
- package/dist/capsule/capsule-store.js +0 -1
- package/dist/capsule/capsule.d.ts +0 -1
- package/dist/capsule/capsule.js +0 -1
- package/dist/capsule/causal-summary.d.ts +21 -1
- package/dist/capsule/causal-summary.js +20 -2
- package/dist/capsule/divergence.d.ts +0 -1
- package/dist/capsule/divergence.js +0 -1
- package/dist/capsule/minimize.d.ts +0 -1
- package/dist/capsule/minimize.js +0 -1
- package/dist/capsule/predicate-to-links.d.ts +0 -1
- package/dist/capsule/predicate-to-links.js +0 -1
- package/dist/cli-doctor.d.ts +6 -0
- package/dist/cli-doctor.js +60 -0
- package/dist/cli-flow-commands.d.ts +0 -1
- package/dist/cli-flow-commands.js +0 -1
- package/dist/cli-launch.d.ts +0 -1
- package/dist/cli-launch.js +7 -3
- package/dist/cli-parse.d.ts +47 -3
- package/dist/cli-parse.js +147 -13
- package/dist/cli-port.d.ts +3 -1
- package/dist/cli-port.js +21 -1
- package/dist/cli-verify.d.ts +0 -1
- package/dist/cli-verify.js +1 -2
- package/dist/cli.d.ts +0 -1
- package/dist/cli.js +88 -69
- package/dist/cloud/cloud-config.d.ts +0 -1
- package/dist/cloud/cloud-config.js +0 -1
- package/dist/cloud/cloud-sync.d.ts +4 -5
- package/dist/cloud/cloud-sync.js +0 -1
- package/dist/cloud-cli.d.ts +0 -1
- package/dist/cloud-cli.js +9 -2
- package/dist/crawl/crawl-tools.d.ts +0 -1
- package/dist/crawl/crawl-tools.js +1 -2
- package/dist/crawl/crawl.d.ts +17 -3
- package/dist/crawl/crawl.js +43 -4
- package/dist/daemon-resilience.d.ts +6 -1
- package/dist/daemon-resilience.js +63 -1
- package/dist/daemon.d.ts +23 -3
- package/dist/daemon.js +36 -24
- package/dist/domain/domain-model.d.ts +0 -1
- package/dist/domain/domain-model.js +1 -2
- package/dist/domain/domain-tools.d.ts +0 -7
- package/dist/domain/domain-tools.js +21 -4
- package/dist/domain/flow-risk.d.ts +0 -1
- package/dist/domain/flow-risk.js +0 -1
- package/dist/ee/audit-log.d.ts +0 -1
- package/dist/ee/audit-log.js +0 -1
- package/dist/events/body-failures.d.ts +4 -0
- package/dist/events/body-failures.js +113 -0
- package/dist/events/contradictions.d.ts +53 -0
- package/dist/events/contradictions.js +282 -0
- package/dist/events/echo-mismatch.d.ts +4 -0
- package/dist/events/echo-mismatch.js +138 -0
- package/dist/events/event-filters.d.ts +17 -3
- package/dist/events/event-filters.js +13 -3
- package/dist/events/json-salvage.d.ts +32 -0
- package/dist/events/json-salvage.js +96 -0
- package/dist/events/predicate-eval.d.ts +2 -1
- package/dist/events/predicate-eval.js +56 -9
- package/dist/events/predicate.d.ts +0 -1
- package/dist/events/predicate.js +56 -2
- package/dist/events/reaction.d.ts +0 -1
- package/dist/events/reaction.js +0 -1
- package/dist/events/reconcile.d.ts +39 -0
- package/dist/events/reconcile.js +211 -0
- package/dist/events/ring-buffer.d.ts +0 -1
- package/dist/events/ring-buffer.js +0 -1
- package/dist/events/stale-response.d.ts +4 -0
- package/dist/events/stale-response.js +139 -0
- package/dist/events/unit-mismatch.d.ts +16 -0
- package/dist/events/unit-mismatch.js +167 -0
- package/dist/flows/affected-tools.d.ts +18 -0
- package/dist/flows/affected-tools.js +52 -0
- package/dist/flows/affected.d.ts +0 -1
- package/dist/flows/affected.js +0 -1
- package/dist/flows/annotate-tools.d.ts +0 -1
- package/dist/flows/annotate-tools.js +21 -3
- package/dist/flows/annotate.d.ts +0 -1
- package/dist/flows/annotate.js +0 -1
- package/dist/flows/annotation-store.d.ts +0 -1
- package/dist/flows/annotation-store.js +0 -1
- package/dist/flows/assertion-integrity.d.ts +0 -1
- package/dist/flows/assertion-integrity.js +0 -1
- package/dist/flows/assertion-tiers-store.d.ts +0 -1
- package/dist/flows/assertion-tiers-store.js +0 -1
- package/dist/flows/buddy-status.d.ts +0 -1
- package/dist/flows/buddy-status.js +0 -1
- package/dist/flows/coverage.d.ts +0 -1
- package/dist/flows/coverage.js +0 -1
- package/dist/flows/decision.d.ts +0 -7
- package/dist/flows/decision.js +47 -7
- package/dist/flows/flake-store.d.ts +0 -1
- package/dist/flows/flake-store.js +0 -1
- package/dist/flows/flake.d.ts +0 -1
- package/dist/flows/flake.js +0 -1
- package/dist/flows/flow-classify.d.ts +0 -1
- package/dist/flows/flow-classify.js +0 -1
- package/dist/flows/flow-replay-run.d.ts +0 -1
- package/dist/flows/flow-replay-run.js +2 -3
- package/dist/flows/flow-replay.d.ts +20 -4
- package/dist/flows/flow-replay.js +9 -43
- package/dist/flows/flow-report.d.ts +0 -1
- package/dist/flows/flow-report.js +0 -1
- package/dist/flows/flow-scope.d.ts +0 -1
- package/dist/flows/flow-scope.js +0 -1
- package/dist/flows/flow-sources.d.ts +0 -1
- package/dist/flows/flow-sources.js +0 -1
- package/dist/flows/flow-step-runners.d.ts +23 -0
- package/dist/flows/flow-step-runners.js +102 -0
- package/dist/flows/flow-success.d.ts +0 -1
- package/dist/flows/flow-success.js +0 -1
- package/dist/flows/flow-tools.d.ts +0 -1
- package/dist/flows/flow-tools.js +44 -14
- package/dist/flows/flows.d.ts +6 -2
- package/dist/flows/flows.js +15 -2
- package/dist/flows/gate.d.ts +0 -1
- package/dist/flows/gate.js +0 -1
- package/dist/flows/git-changed.d.ts +0 -1
- package/dist/flows/git-changed.js +0 -1
- package/dist/flows/heal-run.d.ts +0 -1
- package/dist/flows/heal-run.js +0 -1
- package/dist/flows/heal.d.ts +0 -1
- package/dist/flows/heal.js +0 -1
- package/dist/flows/parallel-suite.d.ts +0 -1
- package/dist/flows/parallel-suite.js +0 -1
- package/dist/flows/recordings.d.ts +0 -1
- package/dist/flows/recordings.js +0 -1
- package/dist/flows/replay.d.ts +0 -1
- package/dist/flows/replay.js +71 -4
- package/dist/flows/server-verify.d.ts +0 -1
- package/dist/flows/server-verify.js +0 -1
- package/dist/flows/verify-change-tools.d.ts +2 -0
- package/dist/flows/verify-change-tools.js +187 -0
- package/dist/flows/watch-batcher.d.ts +0 -1
- package/dist/flows/watch-batcher.js +0 -1
- package/dist/honesty/accepted-write.d.ts +14 -0
- package/dist/honesty/accepted-write.js +17 -0
- package/dist/honesty/blind-spots.d.ts +18 -1
- package/dist/honesty/blind-spots.js +47 -5
- package/dist/honesty/honesty.d.ts +0 -1
- package/dist/honesty/honesty.js +0 -1
- package/dist/honesty/uncaptured-bodies.d.ts +19 -0
- package/dist/honesty/uncaptured-bodies.js +30 -0
- package/dist/honesty/unread-outcome.d.ts +2 -0
- package/dist/honesty/unread-outcome.js +50 -0
- package/dist/honesty/verified.d.ts +40 -0
- package/dist/honesty/verified.js +86 -0
- package/dist/http-server.d.ts +0 -1
- package/dist/http-server.js +5 -1
- package/dist/hunt/hunt-report.d.ts +50 -0
- package/dist/hunt/hunt-report.js +84 -0
- package/dist/idle-shutdown.d.ts +0 -1
- package/dist/idle-shutdown.js +0 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.js +0 -1
- package/dist/init/agent-rules.d.ts +0 -1
- package/dist/init/agent-rules.js +4 -2
- package/dist/init/capabilities.d.ts +17 -0
- package/dist/init/capabilities.js +51 -0
- package/dist/init/cursor.d.ts +0 -1
- package/dist/init/cursor.js +0 -1
- package/dist/init/desktop-doctor.d.ts +40 -0
- package/dist/init/desktop-doctor.js +198 -0
- package/dist/init/detect.d.ts +25 -1
- package/dist/init/detect.js +65 -4
- package/dist/init/mcp.d.ts +0 -1
- package/dist/init/mcp.js +0 -1
- package/dist/init/next-patch.d.ts +41 -0
- package/dist/init/next-patch.js +106 -0
- package/dist/init/node-io.d.ts +0 -1
- package/dist/init/node-io.js +25 -1
- package/dist/init/patch-kind.d.ts +20 -0
- package/dist/init/patch-kind.js +10 -0
- package/dist/init/plan-framework.d.ts +35 -0
- package/dist/init/plan-framework.js +217 -0
- package/dist/init/plan.d.ts +55 -4
- package/dist/init/plan.js +130 -112
- package/dist/init/project-id.d.ts +0 -1
- package/dist/init/project-id.js +0 -1
- package/dist/init/run.d.ts +17 -1
- package/dist/init/run.js +237 -18
- package/dist/init/slash-command.d.ts +18 -0
- package/dist/init/slash-command.js +52 -0
- package/dist/init/snippets.d.ts +48 -3
- package/dist/init/snippets.js +156 -6
- package/dist/init/vite-config.d.ts +4 -11
- package/dist/init/vite-config.js +15 -8
- package/dist/input/driven-redaction.d.ts +15 -0
- package/dist/input/driven-redaction.js +76 -0
- package/dist/input/network-detail.d.ts +9 -4
- package/dist/input/network-detail.js +35 -16
- package/dist/input/network-mock-tools.d.ts +0 -1
- package/dist/input/network-mock-tools.js +3 -4
- package/dist/input/network-mock.d.ts +0 -1
- package/dist/input/network-mock.js +0 -1
- package/dist/input/real-input.d.ts +14 -1
- package/dist/input/real-input.js +45 -3
- package/dist/input/scroll-find.d.ts +0 -1
- package/dist/input/scroll-find.js +0 -1
- package/dist/input/scroll-tools.d.ts +0 -1
- package/dist/input/scroll-tools.js +0 -1
- package/dist/input/viewport-tools.d.ts +0 -1
- package/dist/input/viewport-tools.js +3 -4
- package/dist/journal/ambient-store.d.ts +0 -1
- package/dist/journal/ambient-store.js +0 -1
- package/dist/journal/ambient.d.ts +0 -1
- package/dist/journal/ambient.js +0 -1
- package/dist/journal/attach-journal.d.ts +0 -1
- package/dist/journal/attach-journal.js +0 -1
- package/dist/journal/deviation-report.d.ts +0 -1
- package/dist/journal/deviation-report.js +0 -1
- package/dist/journal/deviation-service.d.ts +0 -1
- package/dist/journal/deviation-service.js +0 -1
- package/dist/journal/envelope-store.d.ts +0 -1
- package/dist/journal/envelope-store.js +0 -1
- package/dist/journal/envelope.d.ts +8 -9
- package/dist/journal/envelope.js +0 -1
- package/dist/journal/journal-query.d.ts +0 -1
- package/dist/journal/journal-query.js +0 -1
- package/dist/journal/journal-recorder.d.ts +0 -1
- package/dist/journal/journal-recorder.js +0 -1
- package/dist/journal/retention.d.ts +0 -1
- package/dist/journal/retention.js +0 -1
- package/dist/journal/rollups.d.ts +0 -1
- package/dist/journal/rollups.js +0 -1
- package/dist/journal/session-end.d.ts +0 -1
- package/dist/journal/session-end.js +0 -1
- package/dist/journal/session-journal.d.ts +0 -1
- package/dist/journal/session-journal.js +0 -1
- package/dist/license/license.d.ts +0 -1
- package/dist/license/license.js +0 -1
- package/dist/log.d.ts +0 -1
- package/dist/log.js +0 -1
- package/dist/mcp-proxy.d.ts +35 -4
- package/dist/mcp-proxy.js +174 -28
- package/dist/mcp.d.ts +15 -1
- package/dist/mcp.js +145 -17
- package/dist/oracles/flow-instrument-gaps.d.ts +0 -1
- package/dist/oracles/flow-instrument-gaps.js +0 -1
- package/dist/oracles/propose-consequences.d.ts +0 -1
- package/dist/oracles/propose-consequences.js +0 -1
- package/dist/oracles/self-instrument.d.ts +0 -1
- package/dist/oracles/self-instrument.js +0 -1
- package/dist/pairing-token.d.ts +0 -1
- package/dist/pairing-token.js +0 -1
- package/dist/phenomena/phenomena.d.ts +0 -1
- package/dist/phenomena/phenomena.js +0 -1
- package/dist/pool/browser-pool.d.ts +0 -1
- package/dist/pool/browser-pool.js +0 -1
- package/dist/pool/lease-reaper.d.ts +0 -1
- package/dist/pool/lease-reaper.js +0 -1
- package/dist/pool/playwright-launcher.d.ts +0 -1
- package/dist/pool/playwright-launcher.js +10 -2
- package/dist/project/baselines.d.ts +0 -1
- package/dist/project/baselines.js +0 -1
- package/dist/project/file-lock.d.ts +2 -1
- package/dist/project/file-lock.js +12 -2
- package/dist/project/fs-port.d.ts +0 -1
- package/dist/project/fs-port.js +0 -1
- package/dist/project/project-store.d.ts +0 -1
- package/dist/project/project-store.js +0 -1
- package/dist/project/project-tools.d.ts +0 -1
- package/dist/project/project-tools.js +29 -4
- package/dist/project/reticle-dir.d.ts +0 -1
- package/dist/project/reticle-dir.js +0 -1
- package/dist/runs/build-verification-run.d.ts +0 -1
- package/dist/runs/build-verification-run.js +0 -1
- package/dist/runs/profile-redact.d.ts +0 -1
- package/dist/runs/profile-redact.js +0 -1
- package/dist/runs/render-report.d.ts +0 -1
- package/dist/runs/render-report.js +0 -1
- package/dist/runs/repair-prompt.d.ts +0 -1
- package/dist/runs/repair-prompt.js +0 -1
- package/dist/runs/replay-mapping.d.ts +0 -1
- package/dist/runs/replay-mapping.js +0 -1
- package/dist/runs/reticle-runner.d.ts +0 -1
- package/dist/runs/reticle-runner.js +4 -2
- package/dist/runs/risk-classify.d.ts +0 -1
- package/dist/runs/risk-classify.js +0 -1
- package/dist/runs/run-diff.d.ts +0 -1
- package/dist/runs/run-diff.js +0 -1
- package/dist/runs/run-store.d.ts +0 -1
- package/dist/runs/run-store.js +0 -1
- package/dist/runs/run-tools.d.ts +0 -1
- package/dist/runs/run-tools.js +0 -1
- package/dist/runs/runner-port.d.ts +0 -1
- package/dist/runs/runner-port.js +0 -1
- package/dist/runs/verification-sync.d.ts +0 -1
- package/dist/runs/verification-sync.js +0 -1
- package/dist/runs/verify-http.d.ts +0 -1
- package/dist/runs/verify-http.js +0 -1
- package/dist/runs/verify-server.d.ts +0 -1
- package/dist/runs/verify-server.js +0 -1
- package/dist/server-version.d.ts +0 -1
- package/dist/server-version.js +0 -1
- package/dist/session/command-timeout.d.ts +35 -0
- package/dist/session/command-timeout.js +41 -0
- package/dist/session/control-envelope.d.ts +2 -3
- package/dist/session/control-envelope.js +2 -3
- package/dist/session/last-act.d.ts +31 -0
- package/dist/session/last-act.js +24 -0
- package/dist/session/live-control-tools.d.ts +0 -1
- package/dist/session/live-control-tools.js +3 -4
- package/dist/session/live-control.d.ts +0 -1
- package/dist/session/live-control.js +0 -1
- package/dist/session/observed-state.d.ts +12 -2
- package/dist/session/observed-state.js +29 -2
- package/dist/session/output-budget.d.ts +0 -1
- package/dist/session/output-budget.js +0 -1
- package/dist/session/pending-commands.d.ts +12 -0
- package/dist/session/pending-commands.js +36 -0
- package/dist/session/presenter-args.d.ts +0 -1
- package/dist/session/presenter-args.js +0 -1
- package/dist/session/review-store.d.ts +0 -1
- package/dist/session/review-store.js +0 -1
- package/dist/session/session-health.d.ts +26 -2
- package/dist/session/session-health.js +13 -1
- package/dist/session/session-info.d.ts +29 -0
- package/dist/session/session-info.js +1 -0
- package/dist/session/session-lease.d.ts +25 -0
- package/dist/session/session-lease.js +14 -0
- package/dist/session/session-manager.d.ts +7 -19
- package/dist/session/session-manager.js +35 -2
- package/dist/session/session-readiness.d.ts +0 -1
- package/dist/session/session-readiness.js +3 -4
- package/dist/session/session-reaper.d.ts +0 -1
- package/dist/session/session-reaper.js +0 -1
- package/dist/session/session-recommendation.d.ts +0 -1
- package/dist/session/session-recommendation.js +0 -1
- package/dist/session/session-tools.d.ts +0 -1
- package/dist/session/session-tools.js +2 -3
- package/dist/session/session.d.ts +33 -53
- package/dist/session/session.js +102 -66
- package/dist/session/state-select.d.ts +0 -1
- package/dist/session/state-select.js +0 -1
- package/dist/telemetry/argument-shape.d.ts +41 -0
- package/dist/telemetry/argument-shape.js +87 -0
- package/dist/telemetry/bug-found.d.ts +33 -0
- package/dist/telemetry/bug-found.js +95 -0
- package/dist/telemetry/cli-telemetry.d.ts +13 -0
- package/dist/telemetry/cli-telemetry.js +43 -0
- package/dist/telemetry/connect-failure.d.ts +16 -0
- package/dist/telemetry/connect-failure.js +44 -0
- package/dist/telemetry/daemon-telemetry.d.ts +19 -0
- package/dist/telemetry/daemon-telemetry.js +76 -0
- package/dist/telemetry/dev-repo.d.ts +10 -0
- package/dist/telemetry/dev-repo.js +80 -0
- package/dist/telemetry/error-fingerprint.d.ts +24 -0
- package/dist/telemetry/error-fingerprint.js +88 -0
- package/dist/telemetry/feedback-cli.d.ts +31 -0
- package/dist/telemetry/feedback-cli.js +102 -0
- package/dist/telemetry/feedback-context.d.ts +32 -0
- package/dist/telemetry/feedback-context.js +143 -0
- package/dist/telemetry/feedback.d.ts +66 -0
- package/dist/telemetry/feedback.js +175 -0
- package/dist/telemetry/git-facts.d.ts +21 -0
- package/dist/telemetry/git-facts.js +109 -0
- package/dist/telemetry/identify.d.ts +22 -0
- package/dist/telemetry/identify.js +73 -0
- package/dist/telemetry/init-telemetry.d.ts +26 -0
- package/dist/telemetry/init-telemetry.js +33 -0
- package/dist/telemetry/machine-snapshot.d.ts +6 -0
- package/dist/telemetry/machine-snapshot.js +39 -0
- package/dist/telemetry/mcp-connection.d.ts +5 -0
- package/dist/telemetry/mcp-connection.js +44 -0
- package/dist/telemetry/project-profile.d.ts +44 -0
- package/dist/telemetry/project-profile.js +205 -0
- package/dist/telemetry/run-telemetry.d.ts +21 -0
- package/dist/telemetry/run-telemetry.js +62 -0
- package/dist/telemetry/session-metrics.d.ts +103 -0
- package/dist/telemetry/session-metrics.js +329 -0
- package/dist/telemetry/telemetry.d.ts +35 -8
- package/dist/telemetry/telemetry.js +105 -12
- package/dist/token-auth.d.ts +0 -1
- package/dist/token-auth.js +0 -1
- package/dist/tools/act-capsule.d.ts +23 -0
- package/dist/tools/act-capsule.js +47 -0
- package/dist/tools/act-danger.d.ts +7 -0
- package/dist/tools/act-danger.js +44 -0
- package/dist/tools/act-helpers.d.ts +17 -0
- package/dist/tools/act-helpers.js +40 -0
- package/dist/tools/act-tools.d.ts +8 -1
- package/dist/tools/act-tools.js +96 -98
- package/dist/tools/act-view.d.ts +7 -1
- package/dist/tools/act-view.js +13 -1
- package/dist/tools/assert-grade.d.ts +22 -1
- package/dist/tools/assert-grade.js +46 -1
- package/dist/tools/assert-verdict.d.ts +21 -0
- package/dist/tools/assert-verdict.js +62 -0
- package/dist/tools/browser-tools.d.ts +0 -1
- package/dist/tools/browser-tools.js +2 -2
- package/dist/tools/contract-tools.d.ts +0 -1
- package/dist/tools/contract-tools.js +0 -1
- package/dist/tools/coverage-tools.d.ts +9 -0
- package/dist/tools/coverage-tools.js +92 -0
- package/dist/tools/dynamic-tools.d.ts +0 -1
- package/dist/tools/dynamic-tools.js +21 -2
- package/dist/tools/error-recovery.d.ts +18 -2
- package/dist/tools/error-recovery.js +42 -7
- package/dist/tools/feedback-tools.d.ts +24 -0
- package/dist/tools/feedback-tools.js +180 -0
- package/dist/tools/invoke-tool.d.ts +0 -1
- package/dist/tools/invoke-tool.js +115 -5
- package/dist/tools/lease-tools.d.ts +0 -1
- package/dist/tools/lease-tools.js +6 -5
- package/dist/tools/merge-tools.d.ts +0 -1
- package/dist/tools/merge-tools.js +0 -1
- package/dist/tools/observe-tools.d.ts +0 -1
- package/dist/tools/observe-tools.js +91 -39
- package/dist/tools/profiles.d.ts +1 -2
- package/dist/tools/profiles.js +43 -16
- package/dist/tools/query-paginate.d.ts +0 -1
- package/dist/tools/query-paginate.js +0 -1
- package/dist/tools/read-tools.d.ts +0 -1
- package/dist/tools/read-tools.js +14 -8
- package/dist/tools/reconcile-tools.d.ts +2 -0
- package/dist/tools/reconcile-tools.js +111 -0
- package/dist/tools/snapshot-delta.d.ts +0 -1
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/tool-invoker.d.ts +0 -1
- package/dist/tools/tool-invoker.js +0 -1
- package/dist/tools/tool-kit.d.ts +16 -1
- package/dist/tools/tool-kit.js +8 -2
- package/dist/tools/tool-names.d.ts +6 -1
- package/dist/tools/tool-names.js +6 -1
- package/dist/tools/tools-helpers.d.ts +0 -1
- package/dist/tools/tools-helpers.js +0 -1
- package/dist/tools/tools.d.ts +0 -1
- package/dist/tools/tools.js +24 -4
- package/dist/update/update-checker.d.ts +0 -1
- package/dist/update/update-checker.js +0 -1
- package/dist/update/update-nudge.d.ts +20 -0
- package/dist/update/update-nudge.js +72 -0
- package/dist/update/updater.d.ts +14 -1
- package/dist/update/updater.js +33 -2
- package/dist/visual/visual-diff.d.ts +0 -1
- package/dist/visual/visual-diff.js +0 -1
- package/dist/visual/visual-store.d.ts +0 -1
- package/dist/visual/visual-store.js +0 -1
- package/dist/visual/visual-tools.d.ts +0 -1
- package/dist/visual/visual-tools.js +103 -16
- package/package.json +2 -2
- package/dist/bridge-security.d.ts.map +0 -1
- package/dist/bridge-security.js.map +0 -1
- package/dist/bridge.d.ts.map +0 -1
- package/dist/bridge.js.map +0 -1
- package/dist/bridge.test-harness.d.ts.map +0 -1
- package/dist/bridge.test-harness.js.map +0 -1
- package/dist/capsule/capsule-store.d.ts.map +0 -1
- package/dist/capsule/capsule-store.js.map +0 -1
- package/dist/capsule/capsule.d.ts.map +0 -1
- package/dist/capsule/capsule.js.map +0 -1
- package/dist/capsule/causal-summary.d.ts.map +0 -1
- package/dist/capsule/causal-summary.js.map +0 -1
- package/dist/capsule/divergence.d.ts.map +0 -1
- package/dist/capsule/divergence.js.map +0 -1
- package/dist/capsule/minimize.d.ts.map +0 -1
- package/dist/capsule/minimize.js.map +0 -1
- package/dist/capsule/predicate-to-links.d.ts.map +0 -1
- package/dist/capsule/predicate-to-links.js.map +0 -1
- package/dist/cli-flow-commands.d.ts.map +0 -1
- package/dist/cli-flow-commands.js.map +0 -1
- package/dist/cli-launch.d.ts.map +0 -1
- package/dist/cli-launch.js.map +0 -1
- package/dist/cli-parse.d.ts.map +0 -1
- package/dist/cli-parse.js.map +0 -1
- package/dist/cli-port.d.ts.map +0 -1
- package/dist/cli-port.js.map +0 -1
- package/dist/cli-verify.d.ts.map +0 -1
- package/dist/cli-verify.js.map +0 -1
- package/dist/cli.d.ts.map +0 -1
- package/dist/cli.js.map +0 -1
- package/dist/cloud/cloud-config.d.ts.map +0 -1
- package/dist/cloud/cloud-config.js.map +0 -1
- package/dist/cloud/cloud-sync.d.ts.map +0 -1
- package/dist/cloud/cloud-sync.js.map +0 -1
- package/dist/cloud-cli.d.ts.map +0 -1
- package/dist/cloud-cli.js.map +0 -1
- package/dist/crawl/crawl-tools.d.ts.map +0 -1
- package/dist/crawl/crawl-tools.js.map +0 -1
- package/dist/crawl/crawl.d.ts.map +0 -1
- package/dist/crawl/crawl.js.map +0 -1
- package/dist/daemon-resilience.d.ts.map +0 -1
- package/dist/daemon-resilience.js.map +0 -1
- package/dist/daemon.d.ts.map +0 -1
- package/dist/daemon.js.map +0 -1
- package/dist/domain/domain-model.d.ts.map +0 -1
- package/dist/domain/domain-model.js.map +0 -1
- package/dist/domain/domain-tools.d.ts.map +0 -1
- package/dist/domain/domain-tools.js.map +0 -1
- package/dist/domain/flow-risk.d.ts.map +0 -1
- package/dist/domain/flow-risk.js.map +0 -1
- package/dist/ee/audit-log.d.ts.map +0 -1
- package/dist/ee/audit-log.js.map +0 -1
- package/dist/events/event-filters.d.ts.map +0 -1
- package/dist/events/event-filters.js.map +0 -1
- package/dist/events/predicate-eval.d.ts.map +0 -1
- package/dist/events/predicate-eval.js.map +0 -1
- package/dist/events/predicate.d.ts.map +0 -1
- package/dist/events/predicate.js.map +0 -1
- package/dist/events/reaction.d.ts.map +0 -1
- package/dist/events/reaction.js.map +0 -1
- package/dist/events/ring-buffer.d.ts.map +0 -1
- package/dist/events/ring-buffer.js.map +0 -1
- package/dist/flows/affected.d.ts.map +0 -1
- package/dist/flows/affected.js.map +0 -1
- package/dist/flows/annotate-tools.d.ts.map +0 -1
- package/dist/flows/annotate-tools.js.map +0 -1
- package/dist/flows/annotate.d.ts.map +0 -1
- package/dist/flows/annotate.js.map +0 -1
- package/dist/flows/annotation-store.d.ts.map +0 -1
- package/dist/flows/annotation-store.js.map +0 -1
- package/dist/flows/assertion-integrity.d.ts.map +0 -1
- package/dist/flows/assertion-integrity.js.map +0 -1
- package/dist/flows/assertion-tiers-store.d.ts.map +0 -1
- package/dist/flows/assertion-tiers-store.js.map +0 -1
- package/dist/flows/buddy-status.d.ts.map +0 -1
- package/dist/flows/buddy-status.js.map +0 -1
- package/dist/flows/coverage.d.ts.map +0 -1
- package/dist/flows/coverage.js.map +0 -1
- package/dist/flows/decision.d.ts.map +0 -1
- package/dist/flows/decision.js.map +0 -1
- package/dist/flows/flake-store.d.ts.map +0 -1
- package/dist/flows/flake-store.js.map +0 -1
- package/dist/flows/flake.d.ts.map +0 -1
- package/dist/flows/flake.js.map +0 -1
- package/dist/flows/flow-classify.d.ts.map +0 -1
- package/dist/flows/flow-classify.js.map +0 -1
- package/dist/flows/flow-replay-run.d.ts.map +0 -1
- package/dist/flows/flow-replay-run.js.map +0 -1
- package/dist/flows/flow-replay.d.ts.map +0 -1
- package/dist/flows/flow-replay.js.map +0 -1
- package/dist/flows/flow-report.d.ts.map +0 -1
- package/dist/flows/flow-report.js.map +0 -1
- package/dist/flows/flow-scope.d.ts.map +0 -1
- package/dist/flows/flow-scope.js.map +0 -1
- package/dist/flows/flow-sources.d.ts.map +0 -1
- package/dist/flows/flow-sources.js.map +0 -1
- package/dist/flows/flow-success.d.ts.map +0 -1
- package/dist/flows/flow-success.js.map +0 -1
- package/dist/flows/flow-tools.d.ts.map +0 -1
- package/dist/flows/flow-tools.js.map +0 -1
- package/dist/flows/flows.d.ts.map +0 -1
- package/dist/flows/flows.js.map +0 -1
- package/dist/flows/gate.d.ts.map +0 -1
- package/dist/flows/gate.js.map +0 -1
- package/dist/flows/git-changed.d.ts.map +0 -1
- package/dist/flows/git-changed.js.map +0 -1
- package/dist/flows/heal-run.d.ts.map +0 -1
- package/dist/flows/heal-run.js.map +0 -1
- package/dist/flows/heal.d.ts.map +0 -1
- package/dist/flows/heal.js.map +0 -1
- package/dist/flows/parallel-suite.d.ts.map +0 -1
- package/dist/flows/parallel-suite.js.map +0 -1
- package/dist/flows/recordings.d.ts.map +0 -1
- package/dist/flows/recordings.js.map +0 -1
- package/dist/flows/replay.d.ts.map +0 -1
- package/dist/flows/replay.js.map +0 -1
- package/dist/flows/server-verify.d.ts.map +0 -1
- package/dist/flows/server-verify.js.map +0 -1
- package/dist/flows/watch-batcher.d.ts.map +0 -1
- package/dist/flows/watch-batcher.js.map +0 -1
- package/dist/honesty/blind-spots.d.ts.map +0 -1
- package/dist/honesty/blind-spots.js.map +0 -1
- package/dist/honesty/honesty.d.ts.map +0 -1
- package/dist/honesty/honesty.js.map +0 -1
- package/dist/http-server.d.ts.map +0 -1
- package/dist/http-server.js.map +0 -1
- package/dist/idle-shutdown.d.ts.map +0 -1
- package/dist/idle-shutdown.js.map +0 -1
- package/dist/index.d.ts.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/init/agent-rules.d.ts.map +0 -1
- package/dist/init/agent-rules.js.map +0 -1
- package/dist/init/cursor.d.ts.map +0 -1
- package/dist/init/cursor.js.map +0 -1
- package/dist/init/detect.d.ts.map +0 -1
- package/dist/init/detect.js.map +0 -1
- package/dist/init/mcp.d.ts.map +0 -1
- package/dist/init/mcp.js.map +0 -1
- package/dist/init/node-io.d.ts.map +0 -1
- package/dist/init/node-io.js.map +0 -1
- package/dist/init/plan.d.ts.map +0 -1
- package/dist/init/plan.js.map +0 -1
- package/dist/init/project-id.d.ts.map +0 -1
- package/dist/init/project-id.js.map +0 -1
- package/dist/init/run.d.ts.map +0 -1
- package/dist/init/run.js.map +0 -1
- package/dist/init/snippets.d.ts.map +0 -1
- package/dist/init/snippets.js.map +0 -1
- package/dist/init/vite-config.d.ts.map +0 -1
- package/dist/init/vite-config.js.map +0 -1
- package/dist/input/network-detail.d.ts.map +0 -1
- package/dist/input/network-detail.js.map +0 -1
- package/dist/input/network-mock-tools.d.ts.map +0 -1
- package/dist/input/network-mock-tools.js.map +0 -1
- package/dist/input/network-mock.d.ts.map +0 -1
- package/dist/input/network-mock.js.map +0 -1
- package/dist/input/real-input.d.ts.map +0 -1
- package/dist/input/real-input.js.map +0 -1
- package/dist/input/scroll-find.d.ts.map +0 -1
- package/dist/input/scroll-find.js.map +0 -1
- package/dist/input/scroll-tools.d.ts.map +0 -1
- package/dist/input/scroll-tools.js.map +0 -1
- package/dist/input/viewport-tools.d.ts.map +0 -1
- package/dist/input/viewport-tools.js.map +0 -1
- package/dist/journal/ambient-store.d.ts.map +0 -1
- package/dist/journal/ambient-store.js.map +0 -1
- package/dist/journal/ambient.d.ts.map +0 -1
- package/dist/journal/ambient.js.map +0 -1
- package/dist/journal/attach-journal.d.ts.map +0 -1
- package/dist/journal/attach-journal.js.map +0 -1
- package/dist/journal/deviation-report.d.ts.map +0 -1
- package/dist/journal/deviation-report.js.map +0 -1
- package/dist/journal/deviation-service.d.ts.map +0 -1
- package/dist/journal/deviation-service.js.map +0 -1
- package/dist/journal/envelope-store.d.ts.map +0 -1
- package/dist/journal/envelope-store.js.map +0 -1
- package/dist/journal/envelope.d.ts.map +0 -1
- package/dist/journal/envelope.js.map +0 -1
- package/dist/journal/journal-query.d.ts.map +0 -1
- package/dist/journal/journal-query.js.map +0 -1
- package/dist/journal/journal-recorder.d.ts.map +0 -1
- package/dist/journal/journal-recorder.js.map +0 -1
- package/dist/journal/retention.d.ts.map +0 -1
- package/dist/journal/retention.js.map +0 -1
- package/dist/journal/rollups.d.ts.map +0 -1
- package/dist/journal/rollups.js.map +0 -1
- package/dist/journal/session-end.d.ts.map +0 -1
- package/dist/journal/session-end.js.map +0 -1
- package/dist/journal/session-journal.d.ts.map +0 -1
- package/dist/journal/session-journal.js.map +0 -1
- package/dist/license/license.d.ts.map +0 -1
- package/dist/license/license.js.map +0 -1
- package/dist/log.d.ts.map +0 -1
- package/dist/log.js.map +0 -1
- package/dist/mcp-proxy.d.ts.map +0 -1
- package/dist/mcp-proxy.js.map +0 -1
- package/dist/mcp.d.ts.map +0 -1
- package/dist/mcp.js.map +0 -1
- package/dist/oracles/flow-instrument-gaps.d.ts.map +0 -1
- package/dist/oracles/flow-instrument-gaps.js.map +0 -1
- package/dist/oracles/propose-consequences.d.ts.map +0 -1
- package/dist/oracles/propose-consequences.js.map +0 -1
- package/dist/oracles/self-instrument.d.ts.map +0 -1
- package/dist/oracles/self-instrument.js.map +0 -1
- package/dist/pairing-token.d.ts.map +0 -1
- package/dist/pairing-token.js.map +0 -1
- package/dist/phenomena/phenomena.d.ts.map +0 -1
- package/dist/phenomena/phenomena.js.map +0 -1
- package/dist/pool/browser-pool.d.ts.map +0 -1
- package/dist/pool/browser-pool.js.map +0 -1
- package/dist/pool/lease-reaper.d.ts.map +0 -1
- package/dist/pool/lease-reaper.js.map +0 -1
- package/dist/pool/playwright-launcher.d.ts.map +0 -1
- package/dist/pool/playwright-launcher.js.map +0 -1
- package/dist/project/baselines.d.ts.map +0 -1
- package/dist/project/baselines.js.map +0 -1
- package/dist/project/file-lock.d.ts.map +0 -1
- package/dist/project/file-lock.js.map +0 -1
- package/dist/project/fs-port.d.ts.map +0 -1
- package/dist/project/fs-port.js.map +0 -1
- package/dist/project/project-store.d.ts.map +0 -1
- package/dist/project/project-store.js.map +0 -1
- package/dist/project/project-tools.d.ts.map +0 -1
- package/dist/project/project-tools.js.map +0 -1
- package/dist/project/reticle-dir.d.ts.map +0 -1
- package/dist/project/reticle-dir.js.map +0 -1
- package/dist/runs/build-verification-run.d.ts.map +0 -1
- package/dist/runs/build-verification-run.js.map +0 -1
- package/dist/runs/profile-redact.d.ts.map +0 -1
- package/dist/runs/profile-redact.js.map +0 -1
- package/dist/runs/render-report.d.ts.map +0 -1
- package/dist/runs/render-report.js.map +0 -1
- package/dist/runs/repair-prompt.d.ts.map +0 -1
- package/dist/runs/repair-prompt.js.map +0 -1
- package/dist/runs/replay-mapping.d.ts.map +0 -1
- package/dist/runs/replay-mapping.js.map +0 -1
- package/dist/runs/reticle-runner.d.ts.map +0 -1
- package/dist/runs/reticle-runner.js.map +0 -1
- package/dist/runs/risk-classify.d.ts.map +0 -1
- package/dist/runs/risk-classify.js.map +0 -1
- package/dist/runs/run-diff.d.ts.map +0 -1
- package/dist/runs/run-diff.js.map +0 -1
- package/dist/runs/run-store.d.ts.map +0 -1
- package/dist/runs/run-store.js.map +0 -1
- package/dist/runs/run-tools.d.ts.map +0 -1
- package/dist/runs/run-tools.js.map +0 -1
- package/dist/runs/runner-port.d.ts.map +0 -1
- package/dist/runs/runner-port.js.map +0 -1
- package/dist/runs/verification-sync.d.ts.map +0 -1
- package/dist/runs/verification-sync.js.map +0 -1
- package/dist/runs/verify-http.d.ts.map +0 -1
- package/dist/runs/verify-http.js.map +0 -1
- package/dist/runs/verify-server.d.ts.map +0 -1
- package/dist/runs/verify-server.js.map +0 -1
- package/dist/server-version.d.ts.map +0 -1
- package/dist/server-version.js.map +0 -1
- package/dist/session/control-envelope.d.ts.map +0 -1
- package/dist/session/control-envelope.js.map +0 -1
- package/dist/session/live-control-tools.d.ts.map +0 -1
- package/dist/session/live-control-tools.js.map +0 -1
- package/dist/session/live-control.d.ts.map +0 -1
- package/dist/session/live-control.js.map +0 -1
- package/dist/session/observed-state.d.ts.map +0 -1
- package/dist/session/observed-state.js.map +0 -1
- package/dist/session/output-budget.d.ts.map +0 -1
- package/dist/session/output-budget.js.map +0 -1
- package/dist/session/presenter-args.d.ts.map +0 -1
- package/dist/session/presenter-args.js.map +0 -1
- package/dist/session/review-store.d.ts.map +0 -1
- package/dist/session/review-store.js.map +0 -1
- package/dist/session/session-health.d.ts.map +0 -1
- package/dist/session/session-health.js.map +0 -1
- package/dist/session/session-manager.d.ts.map +0 -1
- package/dist/session/session-manager.js.map +0 -1
- package/dist/session/session-readiness.d.ts.map +0 -1
- package/dist/session/session-readiness.js.map +0 -1
- package/dist/session/session-reaper.d.ts.map +0 -1
- package/dist/session/session-reaper.js.map +0 -1
- package/dist/session/session-recommendation.d.ts.map +0 -1
- package/dist/session/session-recommendation.js.map +0 -1
- package/dist/session/session-tools.d.ts.map +0 -1
- package/dist/session/session-tools.js.map +0 -1
- package/dist/session/session.d.ts.map +0 -1
- package/dist/session/session.js.map +0 -1
- package/dist/session/state-select.d.ts.map +0 -1
- package/dist/session/state-select.js.map +0 -1
- package/dist/telemetry/telemetry.d.ts.map +0 -1
- package/dist/telemetry/telemetry.js.map +0 -1
- package/dist/token-auth.d.ts.map +0 -1
- package/dist/token-auth.js.map +0 -1
- package/dist/tools/act-tools.d.ts.map +0 -1
- package/dist/tools/act-tools.js.map +0 -1
- package/dist/tools/act-view.d.ts.map +0 -1
- package/dist/tools/act-view.js.map +0 -1
- package/dist/tools/assert-grade.d.ts.map +0 -1
- package/dist/tools/assert-grade.js.map +0 -1
- package/dist/tools/browser-tools.d.ts.map +0 -1
- package/dist/tools/browser-tools.js.map +0 -1
- package/dist/tools/contract-tools.d.ts.map +0 -1
- package/dist/tools/contract-tools.js.map +0 -1
- package/dist/tools/dynamic-tools.d.ts.map +0 -1
- package/dist/tools/dynamic-tools.js.map +0 -1
- package/dist/tools/error-recovery.d.ts.map +0 -1
- package/dist/tools/error-recovery.js.map +0 -1
- package/dist/tools/invoke-tool.d.ts.map +0 -1
- package/dist/tools/invoke-tool.js.map +0 -1
- package/dist/tools/lease-tools.d.ts.map +0 -1
- package/dist/tools/lease-tools.js.map +0 -1
- package/dist/tools/merge-tools.d.ts.map +0 -1
- package/dist/tools/merge-tools.js.map +0 -1
- package/dist/tools/observe-tools.d.ts.map +0 -1
- package/dist/tools/observe-tools.js.map +0 -1
- package/dist/tools/profiles.d.ts.map +0 -1
- package/dist/tools/profiles.js.map +0 -1
- package/dist/tools/query-paginate.d.ts.map +0 -1
- package/dist/tools/query-paginate.js.map +0 -1
- package/dist/tools/read-tools.d.ts.map +0 -1
- package/dist/tools/read-tools.js.map +0 -1
- package/dist/tools/snapshot-delta.d.ts.map +0 -1
- package/dist/tools/snapshot-delta.js.map +0 -1
- package/dist/tools/tool-invoker.d.ts.map +0 -1
- package/dist/tools/tool-invoker.js.map +0 -1
- package/dist/tools/tool-kit.d.ts.map +0 -1
- package/dist/tools/tool-kit.js.map +0 -1
- package/dist/tools/tool-names.d.ts.map +0 -1
- package/dist/tools/tool-names.js.map +0 -1
- package/dist/tools/tools-helpers.d.ts.map +0 -1
- package/dist/tools/tools-helpers.js.map +0 -1
- package/dist/tools/tools.d.ts.map +0 -1
- package/dist/tools/tools.js.map +0 -1
- package/dist/update/update-checker.d.ts.map +0 -1
- package/dist/update/update-checker.js.map +0 -1
- package/dist/update/updater.d.ts.map +0 -1
- package/dist/update/updater.js.map +0 -1
- package/dist/visual/visual-diff.d.ts.map +0 -1
- package/dist/visual/visual-diff.js.map +0 -1
- package/dist/visual/visual-store.d.ts.map +0 -1
- package/dist/visual/visual-store.js.map +0 -1
- package/dist/visual/visual-tools.d.ts.map +0 -1
- package/dist/visual/visual-tools.js.map +0 -1
|
@@ -0,0 +1,329 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The in-process session accumulator — the reason Reticle's telemetry bill does not scale with how
|
|
3
|
+
* hard people use it.
|
|
4
|
+
*
|
|
5
|
+
* The old design emitted one event per MCP tool call. That reads as harmless until you multiply it
|
|
6
|
+
* out: a single agent verification loop is 50–200 tool calls, so a thousand daily users would push
|
|
7
|
+
* millions of events a day, and PostHog bills per ingested event. Worse, it was millions of events
|
|
8
|
+
* answering a question that ONE property answers better — `{reticle_act: 40, reticle_assert: 12}`
|
|
9
|
+
* tells you the session was a real verification loop, where 52 separate rows tell you only that 52
|
|
10
|
+
* things happened, with the shape scattered across them.
|
|
11
|
+
*
|
|
12
|
+
* So counts live here, in memory, and leave as a single `daemon_stopped` event.
|
|
13
|
+
*
|
|
14
|
+
* Everything recorded is a COUNT or a fingerprint. No tool arguments, no results, no selectors, no
|
|
15
|
+
* URLs, no error messages — the accumulator has no way to hold them, which is a stronger guarantee
|
|
16
|
+
* than a rule saying it shouldn't.
|
|
17
|
+
*/
|
|
18
|
+
import { BrowserLaunchKind, } from '@reticlehq/core';
|
|
19
|
+
import { errorSkeleton, fingerprintError } from './error-fingerprint.js';
|
|
20
|
+
import { describeToolParams } from './argument-shape.js';
|
|
21
|
+
import { machineSnapshot } from './machine-snapshot.js';
|
|
22
|
+
/** Cap the distinct error shapes held in memory — a pathological loop must not grow unbounded. */
|
|
23
|
+
const MAX_ERROR_KINDS = 40;
|
|
24
|
+
/** Cap distinct MCP clients recorded; more than a handful on one daemon is already the story. */
|
|
25
|
+
const MAX_CLIENTS = 8;
|
|
26
|
+
/** Bounds on the parameter map. Our own schemas are already finite; these are a belt-and-braces cap. */
|
|
27
|
+
const MAX_PARAM_TOOLS = 60;
|
|
28
|
+
const MAX_PARAMS_PER_TOOL = 24;
|
|
29
|
+
/**
|
|
30
|
+
* How many recent tool calls to remember for the crash breadcrumb.
|
|
31
|
+
*
|
|
32
|
+
* Twelve is roughly one verification loop — enough to see the APPROACH (`snapshot → act → act →
|
|
33
|
+
* assert`) rather than just the last step, which is what turns "it crashed in act-tools" into "it
|
|
34
|
+
* crashed acting on a page it had just navigated away from". Names only, so this is a dozen short
|
|
35
|
+
* strings and costs nothing to hold.
|
|
36
|
+
*/
|
|
37
|
+
const BREADCRUMB_LENGTH = 12;
|
|
38
|
+
/**
|
|
39
|
+
* Mutable counters for one daemon lifetime. A plain class, not a store: it is process-local, it never
|
|
40
|
+
* persists, and it dies with the daemon.
|
|
41
|
+
*/
|
|
42
|
+
export class SessionMetrics {
|
|
43
|
+
#toolCalls = 0;
|
|
44
|
+
#toolErrors = 0;
|
|
45
|
+
#verifications = 0;
|
|
46
|
+
#toolCounts = new Map();
|
|
47
|
+
#toolParams = new Map();
|
|
48
|
+
/** Ring of the most recent tool NAMES — the agent's approach run, for a crash report. */
|
|
49
|
+
#breadcrumb = [];
|
|
50
|
+
/** The tool currently in flight, so a crash can name its trigger point. */
|
|
51
|
+
#inFlight;
|
|
52
|
+
#sdkFailures = 0;
|
|
53
|
+
#sdkFailureKinds = new Map();
|
|
54
|
+
#errorKinds = new Map();
|
|
55
|
+
#connections = new Map();
|
|
56
|
+
#toolTiming = new Map();
|
|
57
|
+
#busyMs = 0;
|
|
58
|
+
#concurrent = 0;
|
|
59
|
+
#peakConcurrent = 0;
|
|
60
|
+
#unknownToolCalls = 0;
|
|
61
|
+
#bugsFound = 0;
|
|
62
|
+
#browserMs = 0;
|
|
63
|
+
#browserCommands = 0;
|
|
64
|
+
#bugKinds = new Map();
|
|
65
|
+
/**
|
|
66
|
+
* Kinds already reported this session — the dedup key, deliberately SEPARATE from `#bugKinds`.
|
|
67
|
+
*
|
|
68
|
+
* `#bugKinds` is capped at MAX_ERROR_KINDS, and once full a genuinely new kind is never inserted,
|
|
69
|
+
* so asking it "have I seen this?" answers no forever and marks every later occurrence as first —
|
|
70
|
+
* inflating the distinct-defect count precisely where a session got interesting. This set is not
|
|
71
|
+
* capped: the kind vocabulary is a bounded enum plus oracle names, not user data.
|
|
72
|
+
*/
|
|
73
|
+
#seenBugKinds = new Set();
|
|
74
|
+
#clients = new Set();
|
|
75
|
+
#startedAt;
|
|
76
|
+
#now;
|
|
77
|
+
/** Clock injected — this file must stay testable without a real one, per the repo's clock rule. */
|
|
78
|
+
constructor(now) {
|
|
79
|
+
this.#now = now;
|
|
80
|
+
this.#startedAt = now();
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Record a call starting. Returns a function to call when it finishes — that closure is what makes
|
|
84
|
+
* timing correct under CONCURRENCY: several agents can be inside `runTool` at once, so a single
|
|
85
|
+
* "last start time" field would attribute one tool's duration to another. Each call carries its own.
|
|
86
|
+
*/
|
|
87
|
+
startToolCall(tool, args) {
|
|
88
|
+
this.recordToolCall(tool, args);
|
|
89
|
+
this.#concurrent += 1;
|
|
90
|
+
if (this.#concurrent > this.#peakConcurrent)
|
|
91
|
+
this.#peakConcurrent = this.#concurrent;
|
|
92
|
+
let settled = false;
|
|
93
|
+
return (durationMs) => {
|
|
94
|
+
if (settled)
|
|
95
|
+
return; // a double-settle would corrupt the concurrency count
|
|
96
|
+
settled = true;
|
|
97
|
+
this.#concurrent = Math.max(0, this.#concurrent - 1);
|
|
98
|
+
this.#busyMs += durationMs;
|
|
99
|
+
const timing = this.#toolTiming.get(tool) ?? { totalMs: 0, maxMs: 0 };
|
|
100
|
+
timing.totalMs += durationMs;
|
|
101
|
+
timing.maxMs = Math.max(timing.maxMs, durationMs);
|
|
102
|
+
this.#toolTiming.set(tool, timing);
|
|
103
|
+
};
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Time spent waiting on the BROWSER, across all commands.
|
|
107
|
+
*
|
|
108
|
+
* Compared against `busyMs` this answers the question a single total cannot: of the time an agent
|
|
109
|
+
* spends inside Reticle, how much is us and how much is the app under test? Without the split a
|
|
110
|
+
* 4-second `reticle_act` is unattributable — it could be our overhead or the app taking 4 seconds
|
|
111
|
+
* to settle, and those have opposite fixes. A high ratio here is a finding about their app; a low
|
|
112
|
+
* one alongside a high `busyMs` is a performance bug of ours.
|
|
113
|
+
*/
|
|
114
|
+
recordBrowserLatency(ms) {
|
|
115
|
+
this.#browserMs += ms;
|
|
116
|
+
this.#browserCommands += 1;
|
|
117
|
+
}
|
|
118
|
+
/** A call for a tool that does not exist. Non-zero means our surface is confusing the agent. */
|
|
119
|
+
recordUnknownTool() {
|
|
120
|
+
this.#unknownToolCalls += 1;
|
|
121
|
+
}
|
|
122
|
+
recordToolCall(tool, args) {
|
|
123
|
+
this.#toolCalls += 1;
|
|
124
|
+
bump(this.#toolCounts, tool);
|
|
125
|
+
this.#inFlight = tool;
|
|
126
|
+
this.#breadcrumb.push(tool);
|
|
127
|
+
if (this.#breadcrumb.length > BREADCRUMB_LENGTH)
|
|
128
|
+
this.#breadcrumb.shift();
|
|
129
|
+
if (args === undefined)
|
|
130
|
+
return;
|
|
131
|
+
// Which PARAMETERS get used, per tool — names only (plus a short allowlist of our own enums).
|
|
132
|
+
// Bounded by our own schemas: a tool has a fixed handful of declared parameters, so this map
|
|
133
|
+
// cannot grow with traffic the way a value-carrying one would.
|
|
134
|
+
let perTool = this.#toolParams.get(tool);
|
|
135
|
+
if (perTool === undefined) {
|
|
136
|
+
if (this.#toolParams.size >= MAX_PARAM_TOOLS)
|
|
137
|
+
return;
|
|
138
|
+
perTool = new Map();
|
|
139
|
+
this.#toolParams.set(tool, perTool);
|
|
140
|
+
}
|
|
141
|
+
for (const param of describeToolParams(args)) {
|
|
142
|
+
if (perTool.size < MAX_PARAMS_PER_TOOL || perTool.has(param))
|
|
143
|
+
bump(perTool, param);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* One failed tool call. Grouped by fingerprint, but stored WITH its skeleton message and the tool
|
|
148
|
+
* that produced it — a bare fingerprint could be ranked and never diagnosed, which made the top
|
|
149
|
+
* error in the dashboard a number nobody could act on.
|
|
150
|
+
*/
|
|
151
|
+
recordToolError(message, tool) {
|
|
152
|
+
this.#toolErrors += 1;
|
|
153
|
+
const fingerprint = fingerprintError(message);
|
|
154
|
+
const existing = this.#errorKinds.get(fingerprint);
|
|
155
|
+
if (existing !== undefined) {
|
|
156
|
+
existing.count += 1;
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
// Stop growing once the cap is hit; the tail is noise and the head is what gets fixed.
|
|
160
|
+
if (this.#errorKinds.size >= MAX_ERROR_KINDS)
|
|
161
|
+
return;
|
|
162
|
+
this.#errorKinds.set(fingerprint, {
|
|
163
|
+
fingerprint,
|
|
164
|
+
count: 1,
|
|
165
|
+
message: errorSkeleton(message),
|
|
166
|
+
...(tool !== undefined ? { tool } : {}),
|
|
167
|
+
});
|
|
168
|
+
}
|
|
169
|
+
/**
|
|
170
|
+
* A failure reported by the IN-PAGE half of Reticle, over the bridge.
|
|
171
|
+
*
|
|
172
|
+
* Kept in its own bucket rather than mixed into tool errors: a broken observer and a failing tool
|
|
173
|
+
* call are different defects with different owners, and merging them would hide the browser-side
|
|
174
|
+
* one inside a much larger pile. Same treatment otherwise — fingerprinted, variables stripped.
|
|
175
|
+
*/
|
|
176
|
+
recordSdkFailure(site, message) {
|
|
177
|
+
this.#sdkFailures += 1;
|
|
178
|
+
const fingerprint = fingerprintError(`${site}|${message}`);
|
|
179
|
+
const existing = this.#sdkFailureKinds.get(fingerprint);
|
|
180
|
+
if (existing !== undefined) {
|
|
181
|
+
existing.count += 1;
|
|
182
|
+
return;
|
|
183
|
+
}
|
|
184
|
+
if (this.#sdkFailureKinds.size >= MAX_ERROR_KINDS)
|
|
185
|
+
return;
|
|
186
|
+
this.#sdkFailureKinds.set(fingerprint, {
|
|
187
|
+
fingerprint,
|
|
188
|
+
count: 1,
|
|
189
|
+
message: errorSkeleton(message),
|
|
190
|
+
tool: site,
|
|
191
|
+
});
|
|
192
|
+
}
|
|
193
|
+
/** The agent's recent approach run + the call in flight — context for a crash report. */
|
|
194
|
+
get trail() {
|
|
195
|
+
return { breadcrumb: [...this.#breadcrumb], inFlight: this.#inFlight };
|
|
196
|
+
}
|
|
197
|
+
recordVerification() {
|
|
198
|
+
this.#verifications += 1;
|
|
199
|
+
}
|
|
200
|
+
/**
|
|
201
|
+
* One defect found in the app under test — the outcome number, kept broken down by kind.
|
|
202
|
+
*
|
|
203
|
+
* Returns TRUE when this kind is new to the session. Every occurrence is still counted; the flag
|
|
204
|
+
* only lets a reader separate "how many distinct defects" from "how often they were hit", which
|
|
205
|
+
* are different claims and were previously indistinguishable in the data.
|
|
206
|
+
*/
|
|
207
|
+
recordBug(kind) {
|
|
208
|
+
this.#bugsFound += 1;
|
|
209
|
+
if (this.#bugKinds.size < MAX_ERROR_KINDS || this.#bugKinds.has(kind))
|
|
210
|
+
bump(this.#bugKinds, kind);
|
|
211
|
+
const first = !this.#seenBugKinds.has(kind);
|
|
212
|
+
this.#seenBugKinds.add(kind);
|
|
213
|
+
return first;
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* One connection ATTEMPT. Call before the attempt; settle it with the outcome.
|
|
217
|
+
*
|
|
218
|
+
* The previous version counted only successes, and counted them inconsistently — incrementing
|
|
219
|
+
* before the await on the CDP path and after it on the launch path — so one number meant attempts,
|
|
220
|
+
* the others meant successes, and nothing in the data said which. A connection metric that cannot
|
|
221
|
+
* express failure misses the only question worth asking: how often can people not get a browser?
|
|
222
|
+
*/
|
|
223
|
+
recordConnectAttempt(kind) {
|
|
224
|
+
const stats = this.#connections.get(kind) ?? { attempts: 0, successes: 0 };
|
|
225
|
+
stats.attempts += 1;
|
|
226
|
+
this.#connections.set(kind, stats);
|
|
227
|
+
let settled = false;
|
|
228
|
+
return (failure) => {
|
|
229
|
+
if (settled)
|
|
230
|
+
return;
|
|
231
|
+
settled = true;
|
|
232
|
+
if (failure === undefined) {
|
|
233
|
+
stats.successes += 1;
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
stats.failures ??= {};
|
|
237
|
+
stats.failures[failure] = (stats.failures[failure] ?? 0) + 1;
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
recordClient(name) {
|
|
241
|
+
if (this.#clients.size < MAX_CLIENTS)
|
|
242
|
+
this.#clients.add(name.slice(0, 64));
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
245
|
+
* Roll the counters into the event payload. `final` marks a clean shutdown; a periodic flush passes
|
|
246
|
+
* false so a session killed before it can exit is not lost entirely (see the flush note in cli.ts).
|
|
247
|
+
*/
|
|
248
|
+
summarize(final) {
|
|
249
|
+
const machine = machineSnapshot();
|
|
250
|
+
return {
|
|
251
|
+
durationMs: Math.max(0, this.#now() - this.#startedAt),
|
|
252
|
+
toolCalls: this.#toolCalls,
|
|
253
|
+
toolCounts: Object.fromEntries(this.#toolCounts),
|
|
254
|
+
toolErrors: this.#toolErrors,
|
|
255
|
+
...(this.#errorKinds.size > 0 ? { errors: [...this.#errorKinds.values()] } : {}),
|
|
256
|
+
sdkFailures: this.#sdkFailures,
|
|
257
|
+
...(this.#sdkFailureKinds.size > 0 ? { sdkErrors: [...this.#sdkFailureKinds.values()] } : {}),
|
|
258
|
+
verifications: this.#verifications,
|
|
259
|
+
bugsFound: this.#bugsFound,
|
|
260
|
+
...(this.#bugKinds.size > 0 ? { bugKinds: Object.fromEntries(this.#bugKinds) } : {}),
|
|
261
|
+
...(this.#toolParams.size > 0
|
|
262
|
+
? {
|
|
263
|
+
toolParams: Object.fromEntries([...this.#toolParams].map(([tool, params]) => [tool, Object.fromEntries(params)])),
|
|
264
|
+
}
|
|
265
|
+
: {}),
|
|
266
|
+
...(this.#connections.size > 0 ? { connections: Object.fromEntries(this.#connections) } : {}),
|
|
267
|
+
...(this.#toolTiming.size > 0 ? { toolTiming: Object.fromEntries(this.#toolTiming) } : {}),
|
|
268
|
+
busyMs: this.#busyMs,
|
|
269
|
+
browserMs: this.#browserMs,
|
|
270
|
+
browserCommands: this.#browserCommands,
|
|
271
|
+
peakConcurrentTools: this.#peakConcurrent,
|
|
272
|
+
unknownToolCalls: this.#unknownToolCalls,
|
|
273
|
+
...(machine !== undefined ? { machine } : {}),
|
|
274
|
+
...(this.#clients.size > 0 ? { clients: [...this.#clients] } : {}),
|
|
275
|
+
final,
|
|
276
|
+
};
|
|
277
|
+
}
|
|
278
|
+
/** True when nothing at all happened — a flush of an idle daemon is not worth an event. */
|
|
279
|
+
get empty() {
|
|
280
|
+
return (this.#toolCalls === 0 &&
|
|
281
|
+
this.#verifications === 0 &&
|
|
282
|
+
this.#toolErrors === 0 &&
|
|
283
|
+
this.#bugsFound === 0 &&
|
|
284
|
+
this.#sdkFailures === 0);
|
|
285
|
+
}
|
|
286
|
+
/** Zero the counters after a non-final flush so the next flush reports the NEXT window, not a total. */
|
|
287
|
+
reset() {
|
|
288
|
+
this.#toolCalls = 0;
|
|
289
|
+
this.#toolErrors = 0;
|
|
290
|
+
this.#verifications = 0;
|
|
291
|
+
this.#toolCounts.clear();
|
|
292
|
+
this.#toolParams.clear();
|
|
293
|
+
this.#errorKinds.clear();
|
|
294
|
+
this.#sdkFailures = 0;
|
|
295
|
+
this.#sdkFailureKinds.clear();
|
|
296
|
+
this.#connections.clear();
|
|
297
|
+
this.#toolTiming.clear();
|
|
298
|
+
this.#busyMs = 0;
|
|
299
|
+
this.#browserMs = 0;
|
|
300
|
+
this.#browserCommands = 0;
|
|
301
|
+
this.#peakConcurrent = 0;
|
|
302
|
+
this.#unknownToolCalls = 0;
|
|
303
|
+
this.#bugsFound = 0;
|
|
304
|
+
this.#bugKinds.clear();
|
|
305
|
+
this.#seenBugKinds.clear();
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
function bump(map, key) {
|
|
309
|
+
map.set(key, (map.get(key) ?? 0) + 1);
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* The process-wide accumulator. A module singleton because the two call sites that feed it — the tool
|
|
313
|
+
* chokepoint and the MCP error boundary — are far apart in the graph and threading a metrics object
|
|
314
|
+
* through every ToolDeps would be a large, purely mechanical change for no added safety.
|
|
315
|
+
*/
|
|
316
|
+
let current;
|
|
317
|
+
export const getSessionMetrics = (now = () => Date.now()) => (current ??= new SessionMetrics(now));
|
|
318
|
+
/** Record one browser round-trip. Free-function form so the session hot path is a single call. */
|
|
319
|
+
export const recordBrowserLatency = (ms) => {
|
|
320
|
+
getSessionMetrics().recordBrowserLatency(ms);
|
|
321
|
+
};
|
|
322
|
+
/** Narrow-and-record one in-page failure. Keeps the session hot path to a single call. */
|
|
323
|
+
export const recordSdkFailure = (failure) => {
|
|
324
|
+
getSessionMetrics().recordSdkFailure(failure.site, failure.message);
|
|
325
|
+
};
|
|
326
|
+
/** Tests only — drop the singleton so each case starts from zero. */
|
|
327
|
+
export const resetSessionMetrics = () => {
|
|
328
|
+
current = undefined;
|
|
329
|
+
};
|
|
@@ -1,23 +1,51 @@
|
|
|
1
|
-
import { TelemetryEventKind } from '@reticlehq/core';
|
|
1
|
+
import { TelemetryEventKind, type Crash, type Feedback, type Identity, type BugFound, type InitOutcome, type McpConnection, type ProjectProfile, type SessionSummary, type TelemetryActor, type Verification, type VersionChange } from '@reticlehq/core';
|
|
2
2
|
/** The current telemetry state and which control set it — what `reticle telemetry status` prints. */
|
|
3
|
-
export declare const describeTelemetry: (env?: NodeJS.ProcessEnv, dir?: string) => {
|
|
3
|
+
export declare const describeTelemetry: (env?: NodeJS.ProcessEnv, dir?: string, cwd?: string) => {
|
|
4
4
|
enabled: boolean;
|
|
5
5
|
reason: string;
|
|
6
6
|
policyUrl: string;
|
|
7
7
|
};
|
|
8
8
|
/** Persist (or lift) the machine-wide opt-out — `reticle telemetry disable` / `enable`. */
|
|
9
9
|
export declare const setTelemetryEnabled: (enabled: boolean, dir?: string) => void;
|
|
10
|
+
/**
|
|
11
|
+
* The per-event extras — one optional block per event kind, so a payload can only ever be attached
|
|
12
|
+
* to the event it belongs to. `feedback` is the only one carrying author-written text, and it only
|
|
13
|
+
* ever arrives from `submitFeedback`, which redacts and validates it first. Nothing else may set it.
|
|
14
|
+
*/
|
|
15
|
+
export interface TelemetryExtra {
|
|
16
|
+
detach?: boolean;
|
|
17
|
+
actor?: TelemetryActor;
|
|
18
|
+
/** `cli_command_run`: which subcommand a human ran. */
|
|
19
|
+
command?: string;
|
|
20
|
+
/** `cli_command_run`: flag NAMES present on the invocation. Never values. */
|
|
21
|
+
flags?: string[];
|
|
22
|
+
/** `daemon_stopped`: the whole session rolled up. Replaces the old per-tool-call event. */
|
|
23
|
+
session?: SessionSummary;
|
|
24
|
+
/** `project_profiled`: the project's shape and depth-of-use. */
|
|
25
|
+
project?: ProjectProfile;
|
|
26
|
+
/** `verification_completed`: one verdict. */
|
|
27
|
+
verification?: Verification;
|
|
28
|
+
/** `version_changed`: update or rollback. */
|
|
29
|
+
versionChange?: VersionChange;
|
|
30
|
+
/** `runtime_crashed`: a fingerprinted crash. */
|
|
31
|
+
crash?: Crash;
|
|
32
|
+
feedback?: Feedback;
|
|
33
|
+
/** `identified`: a self-declared identity. Opt-in, typed by a human, never inferred. */
|
|
34
|
+
identity?: Identity;
|
|
35
|
+
/** `mcp_client_connected`: a client attached, and whether it had attached before. */
|
|
36
|
+
connection?: McpConnection;
|
|
37
|
+
/** `init_completed`: how `reticle init` went. */
|
|
38
|
+
init?: InitOutcome;
|
|
39
|
+
/** `bug_found`: one defect Reticle found in the app under test. */
|
|
40
|
+
bug?: BugFound;
|
|
41
|
+
}
|
|
10
42
|
export interface Telemetry {
|
|
11
43
|
/**
|
|
12
44
|
* Fire one event, non-blocking. `detach: true` hands the send to a disowned child so a short-lived
|
|
13
45
|
* CLI process can exit immediately instead of waiting out the POST (use it from command entry
|
|
14
46
|
* points; daemon-side events send in-process).
|
|
15
47
|
*/
|
|
16
|
-
emit(kind: TelemetryEventKind, extra?:
|
|
17
|
-
sessionMs?: number;
|
|
18
|
-
tool?: string;
|
|
19
|
-
detach?: boolean;
|
|
20
|
-
}): Promise<void>;
|
|
48
|
+
emit(kind: TelemetryEventKind, extra?: TelemetryExtra): Promise<void>;
|
|
21
49
|
readonly enabled: boolean;
|
|
22
50
|
/** True the very first run on this machine — the CLI emits INSTALL alongside the first INVOKE. */
|
|
23
51
|
readonly firstRun: boolean;
|
|
@@ -38,4 +66,3 @@ export declare const createTelemetry: (opts: {
|
|
|
38
66
|
}) => Telemetry;
|
|
39
67
|
export declare const getTelemetry: () => Telemetry;
|
|
40
68
|
export { TelemetryEventKind };
|
|
41
|
-
//# sourceMappingURL=telemetry.d.ts.map
|
|
@@ -19,7 +19,7 @@ import { randomUUID, createHash } from 'node:crypto';
|
|
|
19
19
|
import { readFileSync, writeFileSync, mkdirSync, existsSync, rmSync } from 'node:fs';
|
|
20
20
|
import { homedir, platform } from 'node:os';
|
|
21
21
|
import { join } from 'node:path';
|
|
22
|
-
import { TelemetryEventKind, TELEMETRY_EVENT_VERSION } from '@reticlehq/core';
|
|
22
|
+
import { TelemetryEventKind, TELEMETRY_EVENT_VERSION, ProjectIdSource, } from '@reticlehq/core';
|
|
23
23
|
import { SERVER_VERSION } from '../server-version.js';
|
|
24
24
|
const RETICLE_DIR = join(homedir(), '.reticle');
|
|
25
25
|
const ID_FILE = join(RETICLE_DIR, 'telemetry-id');
|
|
@@ -53,6 +53,8 @@ const DETACHED_SEND_SCRIPT = "fetch(process.argv[1],{method:'POST',headers:{'con
|
|
|
53
53
|
`body:process.argv[2],signal:AbortSignal.timeout(${SEND_TIMEOUT_MS})})` +
|
|
54
54
|
'.catch(()=>{}).finally(()=>process.exit(0))';
|
|
55
55
|
/** Env var names — mirror cloud-sync's `RETICLE_*` convention. */
|
|
56
|
+
import { isReticleSourceCheckout } from './dev-repo.js';
|
|
57
|
+
import { gitFacts } from './git-facts.js';
|
|
56
58
|
const Env = {
|
|
57
59
|
DISABLE: 'RETICLE_TELEMETRY', // "0" / "false" / "off" → disabled
|
|
58
60
|
DO_NOT_TRACK: 'DO_NOT_TRACK', // the cross-tool opt-out convention (any truthy value)
|
|
@@ -61,12 +63,17 @@ const Env = {
|
|
|
61
63
|
CI: 'CI', // presence marks a CI environment
|
|
62
64
|
VITEST: 'VITEST', // set by vitest — unit tests must never phone home
|
|
63
65
|
};
|
|
64
|
-
const isDisabled = (env) => {
|
|
66
|
+
const isDisabled = (env, cwd = process.cwd()) => {
|
|
65
67
|
const off = new Set(['0', 'false', 'off', 'no']);
|
|
66
68
|
if (off.has((env[Env.DISABLE] ?? '').toLowerCase()))
|
|
67
69
|
return true;
|
|
68
70
|
if (env[Env.VITEST] !== undefined)
|
|
69
71
|
return true; // a test run is not a user
|
|
72
|
+
// Developing Reticle is not using Reticle. The `.env` carrying RETICLE_TELEMETRY=0 is gitignored,
|
|
73
|
+
// so it only exists on the machine that made it — a fresh clone would phone home on a
|
|
74
|
+
// contributor's first `reticle serve`. The repo marker is committed, so this guarantee travels.
|
|
75
|
+
if (isReticleSourceCheckout(cwd))
|
|
76
|
+
return true;
|
|
70
77
|
const dnt = env[Env.DO_NOT_TRACK];
|
|
71
78
|
return typeof dnt === 'string' && dnt !== '' && dnt !== '0';
|
|
72
79
|
};
|
|
@@ -88,8 +95,31 @@ const resolveIdentity = () => {
|
|
|
88
95
|
return { anonymousId: randomUUID(), firstRun: false };
|
|
89
96
|
}
|
|
90
97
|
};
|
|
91
|
-
/**
|
|
92
|
-
|
|
98
|
+
/**
|
|
99
|
+
* One-way project fingerprint: distinct-count of this = "projects Reticle is used in", reveals nothing.
|
|
100
|
+
*
|
|
101
|
+
* Prefers a hash of the git ORIGIN over a hash of the cwd. The contract in `@reticlehq/core` always
|
|
102
|
+
* said "one-way hash of the git remote (or cwd)", but the implementation only ever hashed the path —
|
|
103
|
+
* which meant the same repo cloned by four teammates, or checked out twice on one machine, counted as
|
|
104
|
+
* four separate projects. That inflates the project count and, worse, makes team adoption look like
|
|
105
|
+
* unrelated individuals. Hashing the origin dedupes a real project down to one id across every clone.
|
|
106
|
+
*
|
|
107
|
+
* Still one-way, still non-reversible, and still exactly what the published policy describes: the
|
|
108
|
+
* remote URL itself never leaves the machine, only its SHA-256. The URL is normalized first (scheme,
|
|
109
|
+
* credentials, `.git` suffix and case removed) so `git@github.com:acme/web.git` and
|
|
110
|
+
* `https://github.com/Acme/web` are recognized as the same project rather than two.
|
|
111
|
+
*/
|
|
112
|
+
const projectFingerprint = (cwd) => {
|
|
113
|
+
const { origin } = gitFacts(cwd);
|
|
114
|
+
return {
|
|
115
|
+
projectId: createHash('sha256')
|
|
116
|
+
.update(origin ?? cwd)
|
|
117
|
+
.digest('hex')
|
|
118
|
+
.slice(0, 32),
|
|
119
|
+
// Reported alongside so the analytics knows whether this id is comparable to another machine's.
|
|
120
|
+
source: origin !== undefined ? ProjectIdSource.GIT_ORIGIN : ProjectIdSource.CWD,
|
|
121
|
+
};
|
|
122
|
+
};
|
|
93
123
|
/** Print the opt-out notice exactly once per machine (honest disclosure, the OSS-trust bar). */
|
|
94
124
|
const showNoticeOnce = () => {
|
|
95
125
|
try {
|
|
@@ -106,8 +136,17 @@ const showNoticeOnce = () => {
|
|
|
106
136
|
}
|
|
107
137
|
};
|
|
108
138
|
/** The current telemetry state and which control set it — what `reticle telemetry status` prints. */
|
|
109
|
-
export const describeTelemetry = (env = process.env, dir = RETICLE_DIR) => {
|
|
110
|
-
|
|
139
|
+
export const describeTelemetry = (env = process.env, dir = RETICLE_DIR, cwd = process.cwd()) => {
|
|
140
|
+
// Report the reason that ACTUALLY applies. Saying "environment variable" when the real cause is
|
|
141
|
+
// the source-checkout guard would send a contributor hunting for a variable that is not set.
|
|
142
|
+
if (isReticleSourceCheckout(cwd)) {
|
|
143
|
+
return {
|
|
144
|
+
enabled: false,
|
|
145
|
+
reason: 'this is a Reticle source checkout — developing it is not using it',
|
|
146
|
+
policyUrl: POLICY_URL,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
if (isDisabled(env, cwd)) {
|
|
111
150
|
return { enabled: false, reason: 'disabled by environment variable', policyUrl: POLICY_URL };
|
|
112
151
|
}
|
|
113
152
|
if (existsSync(join(dir, 'telemetry-opt-out'))) {
|
|
@@ -142,7 +181,8 @@ const NOOP = { emit: async () => { }, enabled: false, firstRun: false };
|
|
|
142
181
|
*/
|
|
143
182
|
export const createTelemetry = (opts) => {
|
|
144
183
|
const env = opts.env ?? process.env;
|
|
145
|
-
|
|
184
|
+
const cwd = opts.cwd ?? process.cwd();
|
|
185
|
+
if (isDisabled(env, cwd))
|
|
146
186
|
return NOOP;
|
|
147
187
|
try {
|
|
148
188
|
if (existsSync(OPT_OUT_FILE))
|
|
@@ -160,7 +200,13 @@ export const createTelemetry = (opts) => {
|
|
|
160
200
|
const ci = env[Env.CI] !== undefined && env[Env.CI] !== '';
|
|
161
201
|
const os = platform();
|
|
162
202
|
const { anonymousId, firstRun } = resolveIdentity();
|
|
163
|
-
|
|
203
|
+
/**
|
|
204
|
+
* One id per PROCESS, minted in memory and never persisted — which is exactly right: a daemon run
|
|
205
|
+
* IS the session, and a restarted daemon is genuinely a new one. Ephemeral by construction, so it
|
|
206
|
+
* adds no durable identifier to the machine.
|
|
207
|
+
*/
|
|
208
|
+
const sessionId = randomUUID();
|
|
209
|
+
const { projectId, source: projectIdSource } = projectFingerprint(opts.cwd ?? process.cwd());
|
|
164
210
|
showNoticeOnce();
|
|
165
211
|
const spawnDetached = opts.spawnImpl ??
|
|
166
212
|
((command, args) => {
|
|
@@ -170,17 +216,65 @@ export const createTelemetry = (opts) => {
|
|
|
170
216
|
const event = {
|
|
171
217
|
v: TELEMETRY_EVENT_VERSION,
|
|
172
218
|
anonymousId,
|
|
219
|
+
sessionId,
|
|
173
220
|
projectId,
|
|
174
221
|
event: kind,
|
|
175
222
|
ts: now(),
|
|
176
223
|
version: opts.version,
|
|
177
224
|
ci,
|
|
178
225
|
os,
|
|
179
|
-
|
|
180
|
-
...(extra?.
|
|
226
|
+
projectIdSource,
|
|
227
|
+
...(extra?.actor !== undefined ? { actor: extra.actor } : {}),
|
|
228
|
+
...(extra?.command !== undefined ? { command: extra.command } : {}),
|
|
229
|
+
...(extra?.flags !== undefined ? { flags: extra.flags } : {}),
|
|
230
|
+
...(extra?.session !== undefined ? { session: extra.session } : {}),
|
|
231
|
+
...(extra?.project !== undefined ? { project: extra.project } : {}),
|
|
232
|
+
...(extra?.verification !== undefined ? { verification: extra.verification } : {}),
|
|
233
|
+
...(extra?.versionChange !== undefined ? { versionChange: extra.versionChange } : {}),
|
|
234
|
+
...(extra?.crash !== undefined ? { crash: extra.crash } : {}),
|
|
235
|
+
...(extra?.feedback !== undefined ? { feedback: extra.feedback } : {}),
|
|
236
|
+
...(extra?.identity !== undefined ? { identity: extra.identity } : {}),
|
|
237
|
+
...(extra?.connection !== undefined ? { connection: extra.connection } : {}),
|
|
238
|
+
...(extra?.init !== undefined ? { init: extra.init } : {}),
|
|
239
|
+
...(extra?.bug !== undefined ? { bug: extra.bug } : {}),
|
|
181
240
|
};
|
|
182
241
|
// Map the core contract onto PostHog's capture shape: id/name/time move up, the rest are properties.
|
|
183
|
-
|
|
242
|
+
// The feedback body is FLATTENED into `feedback_*` properties rather than sent as a nested object:
|
|
243
|
+
// PostHog filters and breakdowns operate on top-level properties, so a nested `feedback.stack`
|
|
244
|
+
// would be invisible to the exact "which stacks report the most bugs" question this exists to
|
|
245
|
+
// answer. One prefix keeps them grouped in the UI without a nested path.
|
|
246
|
+
const { anonymousId: distinctId, event: name, ts, sessionId: eventSessionId, feedback, session, project, verification, versionChange, crash, identity, connection, init, bug, ...rest } = event;
|
|
247
|
+
// `$session_id` is PostHog's OWN session property, so sending ours under that name lights up
|
|
248
|
+
// its built-in session views and funnels for free rather than requiring custom HogQL everywhere.
|
|
249
|
+
const properties = {
|
|
250
|
+
...rest,
|
|
251
|
+
sessionId: eventSessionId,
|
|
252
|
+
$session_id: eventSessionId,
|
|
253
|
+
};
|
|
254
|
+
// Each block is flattened under its own prefix rather than nested. PostHog filters, breakdowns and
|
|
255
|
+
// insight builders all operate on TOP-LEVEL properties, so a nested `project.stack` is invisible to
|
|
256
|
+
// the exact "which stacks retain best" question these exist to answer — you would have to drop to
|
|
257
|
+
// raw HogQL for every chart. One prefix per block keeps them grouped in the property list without
|
|
258
|
+
// paying that cost. The two genuine maps (`toolCounts`, `errorKinds`) stay objects: their keys are
|
|
259
|
+
// open-ended, so flattening them would mint an unbounded number of property names, which is the one
|
|
260
|
+
// thing that actually degrades a PostHog project.
|
|
261
|
+
const blocks = {
|
|
262
|
+
feedback,
|
|
263
|
+
session,
|
|
264
|
+
project,
|
|
265
|
+
verification,
|
|
266
|
+
version: versionChange,
|
|
267
|
+
crash,
|
|
268
|
+
identity,
|
|
269
|
+
connection,
|
|
270
|
+
init,
|
|
271
|
+
bug,
|
|
272
|
+
};
|
|
273
|
+
for (const [prefix, block] of Object.entries(blocks)) {
|
|
274
|
+
for (const [key, value] of Object.entries(block ?? {})) {
|
|
275
|
+
properties[`${prefix}_${key}`] = value;
|
|
276
|
+
}
|
|
277
|
+
}
|
|
184
278
|
const body = JSON.stringify({
|
|
185
279
|
api_key: apiKey,
|
|
186
280
|
batch: [
|
|
@@ -217,4 +311,3 @@ export const createTelemetry = (opts) => {
|
|
|
217
311
|
let singleton;
|
|
218
312
|
export const getTelemetry = () => (singleton ??= createTelemetry({ version: SERVER_VERSION }));
|
|
219
313
|
export { TelemetryEventKind };
|
|
220
|
-
//# sourceMappingURL=telemetry.js.map
|
package/dist/token-auth.d.ts
CHANGED
|
@@ -21,4 +21,3 @@ export declare function isLoopbackHost(hostHeader: string | undefined): boolean;
|
|
|
21
21
|
* non-loopback value fails, which is what kills a rebound `http://evil.com` page reading the plane.
|
|
22
22
|
*/
|
|
23
23
|
export declare function isLocalWebOrigin(origin: string | undefined, referer: string | undefined): boolean;
|
|
24
|
-
//# sourceMappingURL=token-auth.d.ts.map
|
package/dist/token-auth.js
CHANGED
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ExpectedLink } from '../capsule/divergence.js';
|
|
2
|
+
import type { DivergenceCapsule } from '../capsule/capsule.js';
|
|
3
|
+
import type { ToolDeps } from './tool-kit.js';
|
|
4
|
+
interface CapsuleSaveInputs {
|
|
5
|
+
deps: ToolDeps;
|
|
6
|
+
verdict: {
|
|
7
|
+
pass: boolean;
|
|
8
|
+
failureReason?: string;
|
|
9
|
+
};
|
|
10
|
+
capsule?: DivergenceCapsule | undefined;
|
|
11
|
+
links: readonly ExpectedLink[];
|
|
12
|
+
args: Record<string, unknown>;
|
|
13
|
+
actResult: {
|
|
14
|
+
result?: unknown;
|
|
15
|
+
};
|
|
16
|
+
actedSource?: {
|
|
17
|
+
file: string;
|
|
18
|
+
line: number;
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/** Returns the capsule id when one was written, or undefined when there was nothing to save. */
|
|
22
|
+
export declare function saveFailedAssertCapsule(inputs: CapsuleSaveInputs): Promise<string | undefined>;
|
|
23
|
+
export {};
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Persist a failed assertion as a replayable fail-to-pass capsule.
|
|
3
|
+
*
|
|
4
|
+
* : a red assertion is the ONE moment the evidence explaining it is in hand. Persist it as a
|
|
5
|
+
// replayable fail-to-pass capsule so the bug survives the turn — and becomes a regression flow
|
|
6
|
+
// the moment it goes green. Best-effort: capturing evidence must never fail the run that found it.
|
|
7
|
+
*
|
|
8
|
+
* Split out of act-tools.ts when it crossed the 600-line cap. The seam is real: this is the only
|
|
9
|
+
* part of the act path that writes to disk, and it is best-effort by design — capturing evidence
|
|
10
|
+
* must never fail the run that found it.
|
|
11
|
+
*/
|
|
12
|
+
import { ActionType, AnchorKind } from '@reticlehq/core';
|
|
13
|
+
import { CapsuleStore, capsuleId } from '../capsule/capsule-store.js';
|
|
14
|
+
import { ReticleTool } from './tool-names.js';
|
|
15
|
+
import { asRecord, asString } from './tools-helpers.js';
|
|
16
|
+
/** Returns the capsule id when one was written, or undefined when there was nothing to save. */
|
|
17
|
+
export async function saveFailedAssertCapsule(inputs) {
|
|
18
|
+
const { deps, verdict, capsule, links, args, actResult, actedSource } = inputs;
|
|
19
|
+
if (verdict.pass || capsule === undefined)
|
|
20
|
+
return undefined;
|
|
21
|
+
const id = capsuleId(deps.now(), asString(args['ref']) ?? 'assert');
|
|
22
|
+
const expectedText = links
|
|
23
|
+
.map((l) => ('name' in l ? `${l.kind} ${String(l.name)}` : l.kind))
|
|
24
|
+
.join(' AND ');
|
|
25
|
+
const saved = await new CapsuleStore(deps.fs, deps.reticleRoot).save({
|
|
26
|
+
version: 1,
|
|
27
|
+
id,
|
|
28
|
+
createdAt: deps.now(),
|
|
29
|
+
origin: 'failed-assert',
|
|
30
|
+
expected: expectedText.length > 0 ? expectedText : 'declared consequence',
|
|
31
|
+
observed: capsule.firstDivergence?.observed ?? verdict.failureReason ?? 'not observed',
|
|
32
|
+
steps: [
|
|
33
|
+
{
|
|
34
|
+
tool: ReticleTool.ACT,
|
|
35
|
+
anchor: {
|
|
36
|
+
kind: AnchorKind.TESTID,
|
|
37
|
+
value: asString(asRecord(actResult.result)['testid']) ?? asString(args['ref']) ?? '',
|
|
38
|
+
// Carried so the saved capsule — which outlives this turn and becomes a regression flow
|
|
39
|
+
// when it goes green — still knows which file the failure came from.
|
|
40
|
+
...(actedSource === undefined ? {} : { source: actedSource }),
|
|
41
|
+
},
|
|
42
|
+
action: (asString(args['action']) ?? ActionType.CLICK),
|
|
43
|
+
},
|
|
44
|
+
],
|
|
45
|
+
});
|
|
46
|
+
return saved ? id : undefined;
|
|
47
|
+
}
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import { ActionType } from '@reticlehq/core';
|
|
2
|
+
export declare function assertNotDestructive(action: ActionType, innerArgs: Record<string, unknown>, inspected: unknown): void;
|
|
3
|
+
/**
|
|
4
|
+
* A drag is judged on BOTH ends. Dropping a harmless row onto "Delete" is destructive, and the
|
|
5
|
+
* source alone never says so.
|
|
6
|
+
*/
|
|
7
|
+
export declare function assertDragNotDestructive(innerArgs: Record<string, unknown>, from: unknown, to: unknown): void;
|