@reticlehq/server 2.1.0 → 2.2.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/LICENSE-ENTERPRISE +37 -0
- package/README.md +5 -1
- package/dist/bridge-security.d.ts +1 -1
- package/dist/bridge-security.js +1 -1
- package/dist/bridge.d.ts +7 -0
- package/dist/bridge.d.ts.map +1 -1
- package/dist/bridge.js +22 -3
- package/dist/bridge.js.map +1 -1
- package/dist/bridge.test-harness.d.ts +5 -0
- package/dist/bridge.test-harness.d.ts.map +1 -1
- package/dist/bridge.test-harness.js +4 -0
- package/dist/bridge.test-harness.js.map +1 -1
- package/dist/capsule/capsule-store.d.ts +66 -0
- package/dist/capsule/capsule-store.d.ts.map +1 -0
- package/dist/capsule/capsule-store.js +110 -0
- package/dist/capsule/capsule-store.js.map +1 -0
- package/dist/capsule/capsule.d.ts +19 -0
- package/dist/capsule/capsule.d.ts.map +1 -0
- package/dist/capsule/capsule.js +36 -0
- package/dist/capsule/capsule.js.map +1 -0
- package/dist/capsule/causal-summary.d.ts +36 -0
- package/dist/capsule/causal-summary.d.ts.map +1 -0
- package/dist/capsule/causal-summary.js +111 -0
- package/dist/capsule/causal-summary.js.map +1 -0
- package/dist/capsule/divergence.d.ts +31 -0
- package/dist/capsule/divergence.d.ts.map +1 -0
- package/dist/capsule/divergence.js +41 -0
- package/dist/capsule/divergence.js.map +1 -0
- package/dist/capsule/minimize.d.ts +13 -0
- package/dist/capsule/minimize.d.ts.map +1 -0
- package/dist/capsule/minimize.js +23 -0
- package/dist/capsule/minimize.js.map +1 -0
- package/dist/capsule/predicate-to-links.d.ts +9 -0
- package/dist/capsule/predicate-to-links.d.ts.map +1 -0
- package/dist/capsule/predicate-to-links.js +31 -0
- package/dist/capsule/predicate-to-links.js.map +1 -0
- package/dist/cli-flow-commands.d.ts +31 -0
- package/dist/cli-flow-commands.d.ts.map +1 -0
- package/dist/cli-flow-commands.js +207 -0
- package/dist/cli-flow-commands.js.map +1 -0
- package/dist/cli-parse.d.ts +18 -2
- package/dist/cli-parse.d.ts.map +1 -1
- package/dist/cli-parse.js +57 -0
- package/dist/cli-parse.js.map +1 -1
- package/dist/cli-port.d.ts +10 -4
- package/dist/cli-port.d.ts.map +1 -1
- package/dist/cli-port.js +32 -6
- package/dist/cli-port.js.map +1 -1
- package/dist/cli-verify.d.ts.map +1 -1
- package/dist/cli-verify.js +29 -10
- package/dist/cli-verify.js.map +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +81 -2
- package/dist/cli.js.map +1 -1
- package/dist/crawl/crawl-tools.d.ts.map +1 -1
- package/dist/crawl/crawl-tools.js +12 -0
- package/dist/crawl/crawl-tools.js.map +1 -1
- package/dist/crawl/crawl.d.ts +23 -1
- package/dist/crawl/crawl.d.ts.map +1 -1
- package/dist/crawl/crawl.js +36 -9
- package/dist/crawl/crawl.js.map +1 -1
- package/dist/daemon-resilience.d.ts +5 -5
- package/dist/daemon-resilience.js +5 -5
- package/dist/daemon.d.ts +1 -1
- package/dist/daemon.js +1 -1
- package/dist/domain/domain-tools.d.ts.map +1 -1
- package/dist/domain/domain-tools.js +11 -1
- package/dist/domain/domain-tools.js.map +1 -1
- package/dist/domain/flow-risk.d.ts +4 -4
- package/dist/domain/flow-risk.js +4 -4
- package/dist/ee/audit-log.d.ts +2 -2
- package/dist/ee/audit-log.js +2 -2
- package/dist/events/event-filters.d.ts +29 -1
- package/dist/events/event-filters.d.ts.map +1 -1
- package/dist/events/event-filters.js +75 -1
- package/dist/events/event-filters.js.map +1 -1
- package/dist/events/predicate-eval.d.ts +15 -0
- package/dist/events/predicate-eval.d.ts.map +1 -1
- package/dist/events/predicate-eval.js +97 -18
- package/dist/events/predicate-eval.js.map +1 -1
- package/dist/events/predicate.d.ts +22 -1
- package/dist/events/predicate.d.ts.map +1 -1
- package/dist/events/predicate.js +154 -20
- package/dist/events/predicate.js.map +1 -1
- package/dist/events/ring-buffer.d.ts +3 -3
- package/dist/events/ring-buffer.d.ts.map +1 -1
- package/dist/events/ring-buffer.js +54 -8
- package/dist/events/ring-buffer.js.map +1 -1
- package/dist/flows/affected.d.ts +25 -0
- package/dist/flows/affected.d.ts.map +1 -0
- package/dist/flows/affected.js +36 -0
- package/dist/flows/affected.js.map +1 -0
- package/dist/flows/annotate.d.ts +4 -4
- package/dist/flows/annotate.js +4 -4
- package/dist/flows/assertion-integrity.d.ts +24 -0
- package/dist/flows/assertion-integrity.d.ts.map +1 -0
- package/dist/flows/assertion-integrity.js +27 -0
- package/dist/flows/assertion-integrity.js.map +1 -0
- package/dist/flows/assertion-tiers-store.d.ts +80 -0
- package/dist/flows/assertion-tiers-store.d.ts.map +1 -0
- package/dist/flows/assertion-tiers-store.js +99 -0
- package/dist/flows/assertion-tiers-store.js.map +1 -0
- package/dist/flows/buddy-status.d.ts +25 -0
- package/dist/flows/buddy-status.d.ts.map +1 -0
- package/dist/flows/buddy-status.js +33 -0
- package/dist/flows/buddy-status.js.map +1 -0
- package/dist/flows/coverage.d.ts +28 -0
- package/dist/flows/coverage.d.ts.map +1 -0
- package/dist/flows/coverage.js +22 -0
- package/dist/flows/coverage.js.map +1 -0
- package/dist/flows/decision.d.ts.map +1 -1
- package/dist/flows/decision.js +16 -8
- package/dist/flows/decision.js.map +1 -1
- package/dist/flows/flake-store.d.ts +20 -0
- package/dist/flows/flake-store.d.ts.map +1 -0
- package/dist/flows/flake-store.js +59 -0
- package/dist/flows/flake-store.js.map +1 -0
- package/dist/flows/flake.d.ts +58 -0
- package/dist/flows/flake.d.ts.map +1 -0
- package/dist/flows/flake.js +36 -0
- package/dist/flows/flake.js.map +1 -0
- package/dist/flows/flow-classify.d.ts +8 -8
- package/dist/flows/flow-classify.js +8 -8
- package/dist/flows/flow-replay-run.d.ts.map +1 -1
- package/dist/flows/flow-replay-run.js +36 -0
- package/dist/flows/flow-replay-run.js.map +1 -1
- package/dist/flows/flow-replay.d.ts +9 -0
- package/dist/flows/flow-replay.d.ts.map +1 -1
- package/dist/flows/flow-replay.js +48 -13
- package/dist/flows/flow-replay.js.map +1 -1
- package/dist/flows/flow-report.d.ts +4 -4
- package/dist/flows/flow-sources.d.ts +20 -0
- package/dist/flows/flow-sources.d.ts.map +1 -0
- package/dist/flows/flow-sources.js +33 -0
- package/dist/flows/flow-sources.js.map +1 -0
- package/dist/flows/flow-tools.d.ts +13 -1
- package/dist/flows/flow-tools.d.ts.map +1 -1
- package/dist/flows/flow-tools.js +92 -5
- package/dist/flows/flow-tools.js.map +1 -1
- package/dist/flows/flows.d.ts +9 -4
- package/dist/flows/flows.d.ts.map +1 -1
- package/dist/flows/flows.js +38 -21
- package/dist/flows/flows.js.map +1 -1
- package/dist/flows/gate.d.ts +39 -0
- package/dist/flows/gate.d.ts.map +1 -0
- package/dist/flows/gate.js +34 -0
- package/dist/flows/gate.js.map +1 -0
- package/dist/flows/git-changed.d.ts +9 -0
- package/dist/flows/git-changed.d.ts.map +1 -0
- package/dist/flows/git-changed.js +25 -0
- package/dist/flows/git-changed.js.map +1 -0
- package/dist/flows/heal-run.d.ts +1 -1
- package/dist/flows/heal-run.js +1 -1
- package/dist/flows/parallel-suite.d.ts +27 -0
- package/dist/flows/parallel-suite.d.ts.map +1 -0
- package/dist/flows/parallel-suite.js +51 -0
- package/dist/flows/parallel-suite.js.map +1 -0
- package/dist/flows/replay.d.ts.map +1 -1
- package/dist/flows/replay.js +33 -11
- package/dist/flows/replay.js.map +1 -1
- package/dist/flows/watch-batcher.d.ts +18 -0
- package/dist/flows/watch-batcher.d.ts.map +1 -0
- package/dist/flows/watch-batcher.js +20 -0
- package/dist/flows/watch-batcher.js.map +1 -0
- package/dist/honesty/blind-spots.d.ts +37 -0
- package/dist/honesty/blind-spots.d.ts.map +1 -0
- package/dist/honesty/blind-spots.js +57 -0
- package/dist/honesty/blind-spots.js.map +1 -0
- package/dist/honesty/honesty.d.ts +57 -0
- package/dist/honesty/honesty.d.ts.map +1 -0
- package/dist/honesty/honesty.js +63 -0
- package/dist/honesty/honesty.js.map +1 -0
- package/dist/http-server.d.ts +5 -5
- package/dist/http-server.js +4 -4
- package/dist/idle-shutdown.d.ts +2 -2
- package/dist/idle-shutdown.js +2 -2
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +98 -13
- package/dist/index.js.map +1 -1
- package/dist/init/agent-rules.d.ts +38 -0
- package/dist/init/agent-rules.d.ts.map +1 -0
- package/dist/init/agent-rules.js +65 -0
- package/dist/init/agent-rules.js.map +1 -0
- package/dist/init/plan.d.ts +6 -0
- package/dist/init/plan.d.ts.map +1 -1
- package/dist/init/plan.js +79 -3
- package/dist/init/plan.js.map +1 -1
- package/dist/init/run.d.ts.map +1 -1
- package/dist/init/run.js +4 -0
- package/dist/init/run.js.map +1 -1
- package/dist/init/snippets.js +1 -1
- package/dist/init/vite-config.d.ts +1 -1
- package/dist/init/vite-config.js +2 -2
- package/dist/init/vite-config.js.map +1 -1
- package/dist/input/network-detail.d.ts +74 -0
- package/dist/input/network-detail.d.ts.map +1 -0
- package/dist/input/network-detail.js +160 -0
- package/dist/input/network-detail.js.map +1 -0
- package/dist/input/network-mock.d.ts +4 -4
- package/dist/input/real-input.d.ts +44 -11
- package/dist/input/real-input.d.ts.map +1 -1
- package/dist/input/real-input.js +57 -9
- package/dist/input/real-input.js.map +1 -1
- package/dist/journal/ambient-store.d.ts +16 -0
- package/dist/journal/ambient-store.d.ts.map +1 -0
- package/dist/journal/ambient-store.js +46 -0
- package/dist/journal/ambient-store.js.map +1 -0
- package/dist/journal/ambient.d.ts +48 -0
- package/dist/journal/ambient.d.ts.map +1 -0
- package/dist/journal/ambient.js +48 -0
- package/dist/journal/ambient.js.map +1 -0
- package/dist/journal/attach-journal.d.ts +22 -0
- package/dist/journal/attach-journal.d.ts.map +1 -0
- package/dist/journal/attach-journal.js +20 -0
- package/dist/journal/attach-journal.js.map +1 -0
- package/dist/journal/deviation-report.d.ts +28 -0
- package/dist/journal/deviation-report.d.ts.map +1 -0
- package/dist/journal/deviation-report.js +54 -0
- package/dist/journal/deviation-report.js.map +1 -0
- package/dist/journal/deviation-service.d.ts +12 -0
- package/dist/journal/deviation-service.d.ts.map +1 -0
- package/dist/journal/deviation-service.js +32 -0
- package/dist/journal/deviation-service.js.map +1 -0
- package/dist/journal/envelope-store.d.ts +19 -0
- package/dist/journal/envelope-store.d.ts.map +1 -0
- package/dist/journal/envelope-store.js +62 -0
- package/dist/journal/envelope-store.js.map +1 -0
- package/dist/journal/envelope.d.ts +232 -0
- package/dist/journal/envelope.d.ts.map +1 -0
- package/dist/journal/envelope.js +94 -0
- package/dist/journal/envelope.js.map +1 -0
- package/dist/journal/journal-query.d.ts +20 -0
- package/dist/journal/journal-query.d.ts.map +1 -0
- package/dist/journal/journal-query.js +28 -0
- package/dist/journal/journal-query.js.map +1 -0
- package/dist/journal/journal-recorder.d.ts +38 -0
- package/dist/journal/journal-recorder.d.ts.map +1 -0
- package/dist/journal/journal-recorder.js +81 -0
- package/dist/journal/journal-recorder.js.map +1 -0
- package/dist/journal/retention.d.ts +21 -0
- package/dist/journal/retention.d.ts.map +1 -0
- package/dist/journal/retention.js +50 -0
- package/dist/journal/retention.js.map +1 -0
- package/dist/journal/rollups.d.ts +49 -0
- package/dist/journal/rollups.d.ts.map +1 -0
- package/dist/journal/rollups.js +83 -0
- package/dist/journal/rollups.js.map +1 -0
- package/dist/journal/session-end.d.ts +32 -0
- package/dist/journal/session-end.d.ts.map +1 -0
- package/dist/journal/session-end.js +52 -0
- package/dist/journal/session-end.js.map +1 -0
- package/dist/journal/session-journal.d.ts +25 -0
- package/dist/journal/session-journal.d.ts.map +1 -0
- package/dist/journal/session-journal.js +168 -0
- package/dist/journal/session-journal.js.map +1 -0
- package/dist/license/license.d.ts +8 -3
- package/dist/license/license.d.ts.map +1 -1
- package/dist/license/license.js +34 -11
- package/dist/license/license.js.map +1 -1
- package/dist/mcp-proxy.d.ts +20 -0
- package/dist/mcp-proxy.d.ts.map +1 -1
- package/dist/mcp-proxy.js +45 -27
- package/dist/mcp-proxy.js.map +1 -1
- package/dist/mcp.d.ts +14 -0
- package/dist/mcp.d.ts.map +1 -1
- package/dist/mcp.js +79 -9
- package/dist/mcp.js.map +1 -1
- package/dist/oracles/flow-instrument-gaps.d.ts +19 -0
- package/dist/oracles/flow-instrument-gaps.d.ts.map +1 -0
- package/dist/oracles/flow-instrument-gaps.js +45 -0
- package/dist/oracles/flow-instrument-gaps.js.map +1 -0
- package/dist/oracles/propose-consequences.d.ts +22 -0
- package/dist/oracles/propose-consequences.d.ts.map +1 -0
- package/dist/oracles/propose-consequences.js +93 -0
- package/dist/oracles/propose-consequences.js.map +1 -0
- package/dist/oracles/self-instrument.d.ts +32 -0
- package/dist/oracles/self-instrument.d.ts.map +1 -0
- package/dist/oracles/self-instrument.js +44 -0
- package/dist/oracles/self-instrument.js.map +1 -0
- package/dist/pairing-token.d.ts +1 -1
- package/dist/phenomena/phenomena.d.ts +27 -0
- package/dist/phenomena/phenomena.d.ts.map +1 -0
- package/dist/phenomena/phenomena.js +102 -0
- package/dist/phenomena/phenomena.js.map +1 -0
- package/dist/pool/browser-pool.d.ts +5 -3
- package/dist/pool/browser-pool.d.ts.map +1 -1
- package/dist/pool/browser-pool.js +21 -3
- package/dist/pool/browser-pool.js.map +1 -1
- package/dist/pool/playwright-launcher.d.ts.map +1 -1
- package/dist/pool/playwright-launcher.js +9 -2
- package/dist/pool/playwright-launcher.js.map +1 -1
- package/dist/project/file-lock.d.ts +2 -0
- package/dist/project/file-lock.d.ts.map +1 -0
- package/dist/project/file-lock.js +24 -0
- package/dist/project/file-lock.js.map +1 -0
- package/dist/project/fs-port.d.ts +18 -0
- package/dist/project/fs-port.d.ts.map +1 -1
- package/dist/project/fs-port.js +24 -2
- package/dist/project/fs-port.js.map +1 -1
- package/dist/project/project-store.d.ts.map +1 -1
- package/dist/project/project-store.js +13 -7
- package/dist/project/project-store.js.map +1 -1
- package/dist/project/project-tools.d.ts +0 -6
- package/dist/project/project-tools.d.ts.map +1 -1
- package/dist/project/project-tools.js +24 -1
- package/dist/project/project-tools.js.map +1 -1
- package/dist/project/reticle-dir.d.ts +39 -14
- package/dist/project/reticle-dir.d.ts.map +1 -1
- package/dist/project/reticle-dir.js +30 -4
- package/dist/project/reticle-dir.js.map +1 -1
- package/dist/runs/build-verification-run.d.ts +1 -1
- package/dist/runs/build-verification-run.js +1 -1
- package/dist/runs/repair-prompt.d.ts +2 -0
- package/dist/runs/repair-prompt.d.ts.map +1 -1
- package/dist/runs/repair-prompt.js +14 -1
- package/dist/runs/repair-prompt.js.map +1 -1
- package/dist/runs/reticle-runner.d.ts +1 -1
- package/dist/runs/reticle-runner.d.ts.map +1 -1
- package/dist/runs/run-diff.d.ts +34 -0
- package/dist/runs/run-diff.d.ts.map +1 -0
- package/dist/runs/run-diff.js +71 -0
- package/dist/runs/run-diff.js.map +1 -0
- package/dist/runs/run-store.d.ts +6 -1
- package/dist/runs/run-store.d.ts.map +1 -1
- package/dist/runs/run-store.js +22 -2
- package/dist/runs/run-store.js.map +1 -1
- package/dist/runs/run-tools.d.ts.map +1 -1
- package/dist/runs/run-tools.js +16 -3
- package/dist/runs/run-tools.js.map +1 -1
- package/dist/runs/verify-server.js +1 -1
- package/dist/runs/verify-server.js.map +1 -1
- package/dist/session/control-envelope.d.ts +9 -1
- package/dist/session/control-envelope.d.ts.map +1 -1
- package/dist/session/control-envelope.js +13 -1
- package/dist/session/control-envelope.js.map +1 -1
- package/dist/session/live-control-tools.d.ts +1 -1
- package/dist/session/live-control-tools.js +1 -1
- package/dist/session/live-control.d.ts +38 -0
- package/dist/session/live-control.d.ts.map +1 -0
- package/dist/session/live-control.js +64 -0
- package/dist/session/live-control.js.map +1 -0
- package/dist/session/observed-state.d.ts +46 -0
- package/dist/session/observed-state.d.ts.map +1 -0
- package/dist/session/observed-state.js +76 -0
- package/dist/session/observed-state.js.map +1 -0
- package/dist/session/output-budget.d.ts +9 -0
- package/dist/session/output-budget.d.ts.map +1 -1
- package/dist/session/output-budget.js +9 -0
- package/dist/session/output-budget.js.map +1 -1
- package/dist/session/review-store.d.ts +1 -1
- package/dist/session/review-store.d.ts.map +1 -1
- package/dist/session/review-store.js +2 -2
- package/dist/session/review-store.js.map +1 -1
- package/dist/session/session-manager.d.ts +9 -7
- package/dist/session/session-manager.d.ts.map +1 -1
- package/dist/session/session-manager.js +8 -8
- package/dist/session/session-manager.js.map +1 -1
- package/dist/session/session-readiness.js +1 -1
- package/dist/session/session-readiness.js.map +1 -1
- package/dist/session/session-reaper.d.ts +1 -1
- package/dist/session/session-reaper.js +1 -1
- package/dist/session/session-recommendation.d.ts +1 -1
- package/dist/session/session-recommendation.js +1 -1
- package/dist/session/session-tools.js +1 -1
- package/dist/session/session-tools.js.map +1 -1
- package/dist/session/session.d.ts +43 -11
- package/dist/session/session.d.ts.map +1 -1
- package/dist/session/session.js +115 -46
- package/dist/session/session.js.map +1 -1
- package/dist/tools/act-tools.d.ts.map +1 -1
- package/dist/tools/act-tools.js +252 -70
- package/dist/tools/act-tools.js.map +1 -1
- package/dist/tools/act-view.d.ts +4 -4
- package/dist/tools/act-view.js +4 -4
- package/dist/tools/browser-tools.d.ts.map +1 -1
- package/dist/tools/browser-tools.js +32 -8
- package/dist/tools/browser-tools.js.map +1 -1
- package/dist/tools/contract-tools.d.ts.map +1 -1
- package/dist/tools/contract-tools.js +5 -0
- package/dist/tools/contract-tools.js.map +1 -1
- package/dist/tools/dynamic-tools.d.ts.map +1 -1
- package/dist/tools/dynamic-tools.js +7 -6
- package/dist/tools/dynamic-tools.js.map +1 -1
- package/dist/tools/invoke-tool.d.ts.map +1 -1
- package/dist/tools/invoke-tool.js +32 -29
- package/dist/tools/invoke-tool.js.map +1 -1
- package/dist/tools/lease-tools.d.ts +16 -0
- package/dist/tools/lease-tools.d.ts.map +1 -1
- package/dist/tools/lease-tools.js +11 -0
- package/dist/tools/lease-tools.js.map +1 -1
- package/dist/tools/merge-tools.d.ts +43 -0
- package/dist/tools/merge-tools.d.ts.map +1 -0
- package/dist/tools/merge-tools.js +66 -0
- package/dist/tools/merge-tools.js.map +1 -0
- package/dist/tools/observe-tools.d.ts.map +1 -1
- package/dist/tools/observe-tools.js +172 -29
- package/dist/tools/observe-tools.js.map +1 -1
- package/dist/tools/profiles.d.ts +18 -13
- package/dist/tools/profiles.d.ts.map +1 -1
- package/dist/tools/profiles.js +39 -33
- package/dist/tools/profiles.js.map +1 -1
- package/dist/tools/query-paginate.d.ts +9 -2
- package/dist/tools/query-paginate.d.ts.map +1 -1
- package/dist/tools/query-paginate.js +21 -4
- package/dist/tools/query-paginate.js.map +1 -1
- package/dist/tools/read-tools.d.ts.map +1 -1
- package/dist/tools/read-tools.js +30 -1
- package/dist/tools/read-tools.js.map +1 -1
- package/dist/tools/snapshot-delta.d.ts +2 -0
- package/dist/tools/snapshot-delta.d.ts.map +1 -1
- package/dist/tools/snapshot-delta.js +0 -0
- package/dist/tools/snapshot-delta.js.map +1 -1
- package/dist/tools/tool-kit.d.ts +3 -2
- package/dist/tools/tool-kit.d.ts.map +1 -1
- package/dist/tools/tool-kit.js +11 -1
- package/dist/tools/tool-kit.js.map +1 -1
- package/dist/tools/tool-names.d.ts +18 -10
- package/dist/tools/tool-names.d.ts.map +1 -1
- package/dist/tools/tool-names.js +22 -13
- package/dist/tools/tool-names.js.map +1 -1
- package/dist/tools/tools-helpers.d.ts +12 -0
- package/dist/tools/tools-helpers.d.ts.map +1 -1
- package/dist/tools/tools-helpers.js +20 -0
- package/dist/tools/tools-helpers.js.map +1 -1
- package/dist/tools/tools.d.ts.map +1 -1
- package/dist/tools/tools.js +162 -12
- package/dist/tools/tools.js.map +1 -1
- package/dist/update/updater.d.ts +1 -1
- package/dist/update/updater.js +2 -2
- package/dist/update/updater.js.map +1 -1
- package/package.json +8 -3
- package/dist/update/update-tools.d.ts +0 -3
- package/dist/update/update-tools.d.ts.map +0 -1
- package/dist/update/update-tools.js +0 -94
- package/dist/update/update-tools.js.map +0 -1
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { compareSegment, MIN_ENVELOPE_SAMPLES, } from './envelope.js';
|
|
2
|
+
function headlineFor(report) {
|
|
3
|
+
const truncNote = report.truncatedSegments > 0
|
|
4
|
+
? ` (${String(report.truncatedSegments)} truncated — counts partial)`
|
|
5
|
+
: '';
|
|
6
|
+
if (report.insufficientSamples) {
|
|
7
|
+
return `envelope too new (need ${String(MIN_ENVELOPE_SAMPLES)} runs) — see causal summary${truncNote}`;
|
|
8
|
+
}
|
|
9
|
+
if (report.deviations.length === 0) {
|
|
10
|
+
const s = report.nominalSegments === 1 ? '' : 's';
|
|
11
|
+
return `${String(report.nominalSegments)} segment${s} nominal${truncNote}`;
|
|
12
|
+
}
|
|
13
|
+
const routes = [...new Set(report.deviations.map((d) => d.route))].join(', ');
|
|
14
|
+
const n = report.deviations.length;
|
|
15
|
+
return `${String(n)} deviation${n === 1 ? '' : 's'}: ${routes}${truncNote}`;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Judge observed segments against their per-route envelopes. Segments without a route, or whose
|
|
19
|
+
* envelope is too green, are counted as unjudged rather than silently passed.
|
|
20
|
+
*/
|
|
21
|
+
export function buildDeviationReport(envelopes, segments, zThreshold) {
|
|
22
|
+
const deviations = [];
|
|
23
|
+
let judged = 0;
|
|
24
|
+
let nominal = 0;
|
|
25
|
+
let truncated = 0;
|
|
26
|
+
for (const segment of segments) {
|
|
27
|
+
if (segment.route === undefined)
|
|
28
|
+
continue;
|
|
29
|
+
// A truncated segment's counts understate reality — judging it could read a false "nominal".
|
|
30
|
+
if (segment.truncated === true) {
|
|
31
|
+
truncated += 1;
|
|
32
|
+
continue;
|
|
33
|
+
}
|
|
34
|
+
const envelope = envelopes.get(segment.route);
|
|
35
|
+
if (envelope === undefined || envelope.samples < MIN_ENVELOPE_SAMPLES)
|
|
36
|
+
continue;
|
|
37
|
+
judged += 1;
|
|
38
|
+
const segDeviations = compareSegment(envelope, segment, zThreshold);
|
|
39
|
+
if (segDeviations.length === 0)
|
|
40
|
+
nominal += 1;
|
|
41
|
+
else
|
|
42
|
+
deviations.push(...segDeviations);
|
|
43
|
+
}
|
|
44
|
+
deviations.sort((a, b) => b.z - a.z);
|
|
45
|
+
const base = {
|
|
46
|
+
deviations,
|
|
47
|
+
nominalSegments: nominal,
|
|
48
|
+
judgedSegments: judged,
|
|
49
|
+
truncatedSegments: truncated,
|
|
50
|
+
insufficientSamples: judged === 0,
|
|
51
|
+
};
|
|
52
|
+
return { ...base, headline: headlineFor(base) };
|
|
53
|
+
}
|
|
54
|
+
//# sourceMappingURL=deviation-report.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviation-report.js","sourceRoot":"","sources":["../../src/journal/deviation-report.ts"],"names":[],"mappings":"AACA,OAAO,EACL,cAAc,EAGd,oBAAoB,GACrB,MAAM,eAAe,CAAC;AAuBvB,SAAS,WAAW,CAAC,MAAyC;IAC5D,MAAM,SAAS,GACb,MAAM,CAAC,iBAAiB,GAAG,CAAC;QAC1B,CAAC,CAAC,KAAK,MAAM,CAAC,MAAM,CAAC,iBAAiB,CAAC,8BAA8B;QACrE,CAAC,CAAC,EAAE,CAAC;IACT,IAAI,MAAM,CAAC,mBAAmB,EAAE,CAAC;QAC/B,OAAO,0BAA0B,MAAM,CAAC,oBAAoB,CAAC,8BAA8B,SAAS,EAAE,CAAC;IACzG,CAAC;IACD,IAAI,MAAM,CAAC,UAAU,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACnC,MAAM,CAAC,GAAG,MAAM,CAAC,eAAe,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC;QAClD,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,eAAe,CAAC,WAAW,CAAC,WAAW,SAAS,EAAE,CAAC;IAC7E,CAAC;IACD,MAAM,MAAM,GAAG,CAAC,GAAG,IAAI,GAAG,CAAC,MAAM,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC9E,MAAM,CAAC,GAAG,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC;IACnC,OAAO,GAAG,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,MAAM,GAAG,SAAS,EAAE,CAAC;AAC9E,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,oBAAoB,CAClC,SAA6C,EAC7C,QAAkC,EAClC,UAAmB;IAEnB,MAAM,UAAU,GAAgB,EAAE,CAAC;IACnC,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;YAAE,SAAS;QAC1C,6FAA6F;QAC7F,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YAC/B,SAAS,IAAI,CAAC,CAAC;YACf,SAAS;QACX,CAAC;QACD,MAAM,QAAQ,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;QAC9C,IAAI,QAAQ,KAAK,SAAS,IAAI,QAAQ,CAAC,OAAO,GAAG,oBAAoB;YAAE,SAAS;QAChF,MAAM,IAAI,CAAC,CAAC;QACZ,MAAM,aAAa,GAAG,cAAc,CAAC,QAAQ,EAAE,OAAO,EAAE,UAAU,CAAC,CAAC;QACpE,IAAI,aAAa,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO,IAAI,CAAC,CAAC;;YACxC,UAAU,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,CAAC;IACzC,CAAC;IACD,UAAU,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC;IACrC,MAAM,IAAI,GAAG;QACX,UAAU;QACV,eAAe,EAAE,OAAO;QACxB,cAAc,EAAE,MAAM;QACtB,iBAAiB,EAAE,SAAS;QAC5B,mBAAmB,EAAE,MAAM,KAAK,CAAC;KAClC,CAAC;IACF,OAAO,EAAE,GAAG,IAAI,EAAE,QAAQ,EAAE,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;AAClD,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { EnvelopeStore } from './envelope-store.js';
|
|
2
|
+
import { type DeviationReport } from './deviation-report.js';
|
|
3
|
+
import type { SegmentRollup } from './rollups.js';
|
|
4
|
+
/**
|
|
5
|
+
* The accumulate-and-compare loop behind the push default. Given the segments a drive/replay produced:
|
|
6
|
+
* judge them against the envelopes learned from PAST runs, then fold them in so the baseline sharpens
|
|
7
|
+
* over time. Order matters — compare first, learn second — so a run never grades itself against a
|
|
8
|
+
* baseline it just polluted. Below MIN_ENVELOPE_SAMPLES the report says insufficientSamples and the
|
|
9
|
+
* caller shows the causal summary instead.
|
|
10
|
+
*/
|
|
11
|
+
export declare function reportAndAccumulate(store: EnvelopeStore, segments: readonly SegmentRollup[], zThreshold?: number): Promise<DeviationReport>;
|
|
12
|
+
//# sourceMappingURL=deviation-service.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviation-service.d.ts","sourceRoot":"","sources":["../../src/journal/deviation-service.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,EAAwB,KAAK,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACnF,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAGlD;;;;;;GAMG;AACH,wBAAsB,mBAAmB,CACvC,KAAK,EAAE,aAAa,EACpB,QAAQ,EAAE,SAAS,aAAa,EAAE,EAClC,UAAU,CAAC,EAAE,MAAM,GAClB,OAAO,CAAC,eAAe,CAAC,CAkB1B"}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { addSegmentToEnvelope, emptyEnvelope } from './envelope.js';
|
|
2
|
+
import { buildDeviationReport } from './deviation-report.js';
|
|
3
|
+
import { withFileLock } from '../project/file-lock.js';
|
|
4
|
+
/**
|
|
5
|
+
* The accumulate-and-compare loop behind the push default. Given the segments a drive/replay produced:
|
|
6
|
+
* judge them against the envelopes learned from PAST runs, then fold them in so the baseline sharpens
|
|
7
|
+
* over time. Order matters — compare first, learn second — so a run never grades itself against a
|
|
8
|
+
* baseline it just polluted. Below MIN_ENVELOPE_SAMPLES the report says insufficientSamples and the
|
|
9
|
+
* caller shows the causal summary instead.
|
|
10
|
+
*/
|
|
11
|
+
export async function reportAndAccumulate(store, segments, zThreshold) {
|
|
12
|
+
// Serialized per file: the compare-then-learn read-modify-write runs concurrently under parallel
|
|
13
|
+
// flow_verify. Without the lock, two runs load the same baseline and the later save drops the other's
|
|
14
|
+
// learned segments (and could grade against a half-updated baseline). "Compare first, learn second"
|
|
15
|
+
// only holds within one holder of the lock.
|
|
16
|
+
return withFileLock(store.path, async () => {
|
|
17
|
+
const envelopes = await store.load();
|
|
18
|
+
const report = buildDeviationReport(envelopes, segments, zThreshold);
|
|
19
|
+
for (const segment of segments) {
|
|
20
|
+
if (segment.route === undefined)
|
|
21
|
+
continue;
|
|
22
|
+
// Never learn from a truncated sample — its understated counts would poison the baseline.
|
|
23
|
+
if (segment.truncated === true)
|
|
24
|
+
continue;
|
|
25
|
+
const current = envelopes.get(segment.route) ?? emptyEnvelope(segment.route);
|
|
26
|
+
envelopes.set(segment.route, addSegmentToEnvelope(current, segment));
|
|
27
|
+
}
|
|
28
|
+
await store.save(envelopes);
|
|
29
|
+
return report;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
//# sourceMappingURL=deviation-service.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"deviation-service.js","sourceRoot":"","sources":["../../src/journal/deviation-service.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,oBAAoB,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACpE,OAAO,EAAE,oBAAoB,EAAwB,MAAM,uBAAuB,CAAC;AAEnF,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAEvD;;;;;;GAMG;AACH,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAoB,EACpB,QAAkC,EAClC,UAAmB;IAEnB,iGAAiG;IACjG,sGAAsG;IACtG,oGAAoG;IACpG,4CAA4C;IAC5C,OAAO,YAAY,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE;QACzC,MAAM,SAAS,GAAG,MAAM,KAAK,CAAC,IAAI,EAAE,CAAC;QACrC,MAAM,MAAM,GAAG,oBAAoB,CAAC,SAAS,EAAE,QAAQ,EAAE,UAAU,CAAC,CAAC;QACrE,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;YAC/B,IAAI,OAAO,CAAC,KAAK,KAAK,SAAS;gBAAE,SAAS;YAC1C,0FAA0F;YAC1F,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI;gBAAE,SAAS;YACzC,MAAM,OAAO,GAAG,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,aAAa,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC;YAC7E,SAAS,CAAC,GAAG,CAAC,OAAO,CAAC,KAAK,EAAE,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC;QACvE,CAAC;QACD,MAAM,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QAC5B,OAAO,MAAM,CAAC;IAChB,CAAC,CAAC,CAAC;AACL,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import type { FileSystemPort } from '../project/fs-port.js';
|
|
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
|
+
/**
|
|
6
|
+
* Persists the learned per-route envelopes at `.reticle/envelopes.json`. Local, single-project statistics
|
|
7
|
+
* (single-player memory stays OSS — OSS-VS-SERVER). Loads never throw: a missing, malformed, or
|
|
8
|
+
* wrong-version file degrades to no envelopes, so a bad baseline can never crash a drive; the deviation
|
|
9
|
+
* report just falls back to the causal summary until the envelope rebuilds.
|
|
10
|
+
*/
|
|
11
|
+
export declare class EnvelopeStore {
|
|
12
|
+
#private;
|
|
13
|
+
constructor(fs: FileSystemPort, root: string);
|
|
14
|
+
/** Absolute path of the backing file — the key a caller uses to serialize its read-modify-write. */
|
|
15
|
+
get path(): string;
|
|
16
|
+
load(): Promise<Map<string, RouteEnvelope>>;
|
|
17
|
+
save(envelopes: ReadonlyMap<string, RouteEnvelope>): Promise<void>;
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=envelope-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-store.d.ts","sourceRoot":"","sources":["../../src/journal/envelope-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAE5D,OAAO,EAAuB,KAAK,aAAa,EAAE,MAAM,eAAe,CAAC;AAExE,4GAA4G;AAC5G,eAAO,MAAM,qBAAqB,IAAI,CAAC;AAOvC;;;;;GAKG;AACH,qBAAa,aAAa;;gBAIZ,EAAE,EAAE,cAAc,EAAE,IAAI,EAAE,MAAM;IAK5C,oGAAoG;IACpG,IAAI,IAAI,IAAI,MAAM,CAEjB;IAEK,IAAI,IAAI,OAAO,CAAC,GAAG,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;IAmB3C,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,MAAM,EAAE,aAAa,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC;CAUzE"}
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import { dirname } from 'node:path';
|
|
3
|
+
import { reticleDirPaths } from '../project/reticle-dir.js';
|
|
4
|
+
import { RouteEnvelopeSchema } from './envelope.js';
|
|
5
|
+
/** Bumped on any breaking change to the persisted envelope shape (matches the runs/contract convention). */
|
|
6
|
+
export const ENVELOPE_FILE_VERSION = 1;
|
|
7
|
+
const EnvelopeFileSchema = z.object({
|
|
8
|
+
version: z.literal(ENVELOPE_FILE_VERSION),
|
|
9
|
+
routes: z.record(RouteEnvelopeSchema),
|
|
10
|
+
});
|
|
11
|
+
/**
|
|
12
|
+
* Persists the learned per-route envelopes at `.reticle/envelopes.json`. Local, single-project statistics
|
|
13
|
+
* (single-player memory stays OSS — OSS-VS-SERVER). Loads never throw: a missing, malformed, or
|
|
14
|
+
* wrong-version file degrades to no envelopes, so a bad baseline can never crash a drive; the deviation
|
|
15
|
+
* report just falls back to the causal summary until the envelope rebuilds.
|
|
16
|
+
*/
|
|
17
|
+
export class EnvelopeStore {
|
|
18
|
+
#fs;
|
|
19
|
+
#path;
|
|
20
|
+
constructor(fs, root) {
|
|
21
|
+
this.#fs = fs;
|
|
22
|
+
this.#path = reticleDirPaths(root).envelopes;
|
|
23
|
+
}
|
|
24
|
+
/** Absolute path of the backing file — the key a caller uses to serialize its read-modify-write. */
|
|
25
|
+
get path() {
|
|
26
|
+
return this.#path;
|
|
27
|
+
}
|
|
28
|
+
async load() {
|
|
29
|
+
let text;
|
|
30
|
+
try {
|
|
31
|
+
text = await this.#fs.readFile(this.#path);
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
if (this.#fs.isNotFound(error))
|
|
35
|
+
return new Map();
|
|
36
|
+
throw error;
|
|
37
|
+
}
|
|
38
|
+
let parsed;
|
|
39
|
+
try {
|
|
40
|
+
parsed = JSON.parse(text);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
return new Map();
|
|
44
|
+
}
|
|
45
|
+
const result = EnvelopeFileSchema.safeParse(parsed);
|
|
46
|
+
if (!result.success)
|
|
47
|
+
return new Map();
|
|
48
|
+
return new Map(Object.entries(result.data.routes));
|
|
49
|
+
}
|
|
50
|
+
async save(envelopes) {
|
|
51
|
+
await this.#fs.mkdir(dirname(this.#path));
|
|
52
|
+
const routes = {};
|
|
53
|
+
for (const [route, envelope] of envelopes)
|
|
54
|
+
routes[route] = envelope;
|
|
55
|
+
const body = `${JSON.stringify({ version: ENVELOPE_FILE_VERSION, routes }, null, 2)}\n`;
|
|
56
|
+
// Atomic publish: write a temp sibling then rename, so a crash never leaves a half-written baseline.
|
|
57
|
+
const tmp = `${this.#path}.tmp`;
|
|
58
|
+
await this.#fs.writeFile(tmp, body);
|
|
59
|
+
await this.#fs.rename(tmp, this.#path);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
//# sourceMappingURL=envelope-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope-store.js","sourceRoot":"","sources":["../../src/journal/envelope-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAC5D,OAAO,EAAE,mBAAmB,EAAsB,MAAM,eAAe,CAAC;AAExE,4GAA4G;AAC5G,MAAM,CAAC,MAAM,qBAAqB,GAAG,CAAC,CAAC;AAEvC,MAAM,kBAAkB,GAAG,CAAC,CAAC,MAAM,CAAC;IAClC,OAAO,EAAE,CAAC,CAAC,OAAO,CAAC,qBAAqB,CAAC;IACzC,MAAM,EAAE,CAAC,CAAC,MAAM,CAAC,mBAAmB,CAAC;CACtC,CAAC,CAAC;AAEH;;;;;GAKG;AACH,MAAM,OAAO,aAAa;IACf,GAAG,CAAiB;IACpB,KAAK,CAAS;IAEvB,YAAY,EAAkB,EAAE,IAAY;QAC1C,IAAI,CAAC,GAAG,GAAG,EAAE,CAAC;QACd,IAAI,CAAC,KAAK,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC;IAC/C,CAAC;IAED,oGAAoG;IACpG,IAAI,IAAI;QACN,OAAO,IAAI,CAAC,KAAK,CAAC;IACpB,CAAC;IAED,KAAK,CAAC,IAAI;QACR,IAAI,IAAY,CAAC;QACjB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAC7C,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,IAAI,IAAI,CAAC,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC;gBAAE,OAAO,IAAI,GAAG,EAAE,CAAC;YACjD,MAAM,KAAK,CAAC;QACd,CAAC;QACD,IAAI,MAAe,CAAC;QACpB,IAAI,CAAC;YACH,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,GAAG,EAAE,CAAC;QACnB,CAAC;QACD,MAAM,MAAM,GAAG,kBAAkB,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACpD,IAAI,CAAC,MAAM,CAAC,OAAO;YAAE,OAAO,IAAI,GAAG,EAAE,CAAC;QACtC,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC;IACrD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,SAA6C;QACtD,MAAM,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC;QAC1C,MAAM,MAAM,GAAkC,EAAE,CAAC;QACjD,KAAK,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,IAAI,SAAS;YAAE,MAAM,CAAC,KAAK,CAAC,GAAG,QAAQ,CAAC;QACpE,MAAM,IAAI,GAAG,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,OAAO,EAAE,qBAAqB,EAAE,MAAM,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC;QACxF,qGAAqG;QACrG,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,KAAK,MAAM,CAAC;QAChC,MAAM,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACpC,MAAM,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,GAAG,EAAE,IAAI,CAAC,KAAK,CAAC,CAAC;IACzC,CAAC;CACF"}
|
|
@@ -0,0 +1,232 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
import type { SegmentRollup } from './rollups.js';
|
|
3
|
+
/**
|
|
4
|
+
* The expected-envelope model — the OSS statistical engine behind the deviation report. Per-metric
|
|
5
|
+
* running stats (Welford, so we never store every sample) accumulate across runs of the same route;
|
|
6
|
+
* a new segment is compared against them and flagged when a metric runs high. The *math* is open; the
|
|
7
|
+
* fleet-calibrated thresholds are the paid layer (see OSS-VS-SERVER). We only flag INCREASES
|
|
8
|
+
* (slower, more errors, more requests) — a segment doing less than expected is not a regression.
|
|
9
|
+
*/
|
|
10
|
+
/** Online mean/variance/max for one metric (Welford's algorithm). Immutable: addStat returns a copy. */
|
|
11
|
+
export interface MetricStats {
|
|
12
|
+
count: number;
|
|
13
|
+
mean: number;
|
|
14
|
+
/** Sum of squared deviations (Welford M2); variance = m2/(count-1). */
|
|
15
|
+
m2: number;
|
|
16
|
+
max: number;
|
|
17
|
+
}
|
|
18
|
+
export declare function emptyStats(): MetricStats;
|
|
19
|
+
export declare function addStat(stats: MetricStats, x: number): MetricStats;
|
|
20
|
+
export declare function stddev(stats: MetricStats): number;
|
|
21
|
+
/** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
|
|
22
|
+
export declare function zScore(stats: MetricStats, x: number): number;
|
|
23
|
+
/** The metrics an envelope tracks per route. */
|
|
24
|
+
export declare const ENVELOPE_METRICS: readonly ["durationMs", "net", "netErrors", "consoleErrors"];
|
|
25
|
+
export type EnvelopeMetric = (typeof ENVELOPE_METRICS)[number];
|
|
26
|
+
export interface RouteEnvelope {
|
|
27
|
+
route: string;
|
|
28
|
+
/** Runs that contributed a sample — below MIN_ENVELOPE_SAMPLES the envelope is too green to judge. */
|
|
29
|
+
samples: number;
|
|
30
|
+
stats: Record<EnvelopeMetric, MetricStats>;
|
|
31
|
+
}
|
|
32
|
+
/** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
|
|
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
|
+
/** Persisted shape of a route envelope. Validated on load; a bad file degrades to no envelope. */
|
|
37
|
+
export declare const RouteEnvelopeSchema: z.ZodObject<{
|
|
38
|
+
route: z.ZodString;
|
|
39
|
+
samples: z.ZodNumber;
|
|
40
|
+
stats: z.ZodObject<{
|
|
41
|
+
durationMs: z.ZodObject<{
|
|
42
|
+
count: z.ZodNumber;
|
|
43
|
+
mean: z.ZodNumber;
|
|
44
|
+
m2: z.ZodNumber;
|
|
45
|
+
max: z.ZodNumber;
|
|
46
|
+
}, "strip", z.ZodTypeAny, {
|
|
47
|
+
count: number;
|
|
48
|
+
mean: number;
|
|
49
|
+
m2: number;
|
|
50
|
+
max: number;
|
|
51
|
+
}, {
|
|
52
|
+
count: number;
|
|
53
|
+
mean: number;
|
|
54
|
+
m2: number;
|
|
55
|
+
max: number;
|
|
56
|
+
}>;
|
|
57
|
+
net: z.ZodObject<{
|
|
58
|
+
count: z.ZodNumber;
|
|
59
|
+
mean: z.ZodNumber;
|
|
60
|
+
m2: z.ZodNumber;
|
|
61
|
+
max: z.ZodNumber;
|
|
62
|
+
}, "strip", z.ZodTypeAny, {
|
|
63
|
+
count: number;
|
|
64
|
+
mean: number;
|
|
65
|
+
m2: number;
|
|
66
|
+
max: number;
|
|
67
|
+
}, {
|
|
68
|
+
count: number;
|
|
69
|
+
mean: number;
|
|
70
|
+
m2: number;
|
|
71
|
+
max: number;
|
|
72
|
+
}>;
|
|
73
|
+
netErrors: z.ZodObject<{
|
|
74
|
+
count: z.ZodNumber;
|
|
75
|
+
mean: z.ZodNumber;
|
|
76
|
+
m2: z.ZodNumber;
|
|
77
|
+
max: z.ZodNumber;
|
|
78
|
+
}, "strip", z.ZodTypeAny, {
|
|
79
|
+
count: number;
|
|
80
|
+
mean: number;
|
|
81
|
+
m2: number;
|
|
82
|
+
max: number;
|
|
83
|
+
}, {
|
|
84
|
+
count: number;
|
|
85
|
+
mean: number;
|
|
86
|
+
m2: number;
|
|
87
|
+
max: number;
|
|
88
|
+
}>;
|
|
89
|
+
consoleErrors: z.ZodObject<{
|
|
90
|
+
count: z.ZodNumber;
|
|
91
|
+
mean: z.ZodNumber;
|
|
92
|
+
m2: z.ZodNumber;
|
|
93
|
+
max: z.ZodNumber;
|
|
94
|
+
}, "strip", z.ZodTypeAny, {
|
|
95
|
+
count: number;
|
|
96
|
+
mean: number;
|
|
97
|
+
m2: number;
|
|
98
|
+
max: number;
|
|
99
|
+
}, {
|
|
100
|
+
count: number;
|
|
101
|
+
mean: number;
|
|
102
|
+
m2: number;
|
|
103
|
+
max: number;
|
|
104
|
+
}>;
|
|
105
|
+
}, "strip", z.ZodTypeAny, {
|
|
106
|
+
net: {
|
|
107
|
+
count: number;
|
|
108
|
+
mean: number;
|
|
109
|
+
m2: number;
|
|
110
|
+
max: number;
|
|
111
|
+
};
|
|
112
|
+
durationMs: {
|
|
113
|
+
count: number;
|
|
114
|
+
mean: number;
|
|
115
|
+
m2: number;
|
|
116
|
+
max: number;
|
|
117
|
+
};
|
|
118
|
+
consoleErrors: {
|
|
119
|
+
count: number;
|
|
120
|
+
mean: number;
|
|
121
|
+
m2: number;
|
|
122
|
+
max: number;
|
|
123
|
+
};
|
|
124
|
+
netErrors: {
|
|
125
|
+
count: number;
|
|
126
|
+
mean: number;
|
|
127
|
+
m2: number;
|
|
128
|
+
max: number;
|
|
129
|
+
};
|
|
130
|
+
}, {
|
|
131
|
+
net: {
|
|
132
|
+
count: number;
|
|
133
|
+
mean: number;
|
|
134
|
+
m2: number;
|
|
135
|
+
max: number;
|
|
136
|
+
};
|
|
137
|
+
durationMs: {
|
|
138
|
+
count: number;
|
|
139
|
+
mean: number;
|
|
140
|
+
m2: number;
|
|
141
|
+
max: number;
|
|
142
|
+
};
|
|
143
|
+
consoleErrors: {
|
|
144
|
+
count: number;
|
|
145
|
+
mean: number;
|
|
146
|
+
m2: number;
|
|
147
|
+
max: number;
|
|
148
|
+
};
|
|
149
|
+
netErrors: {
|
|
150
|
+
count: number;
|
|
151
|
+
mean: number;
|
|
152
|
+
m2: number;
|
|
153
|
+
max: number;
|
|
154
|
+
};
|
|
155
|
+
}>;
|
|
156
|
+
}, "strip", z.ZodTypeAny, {
|
|
157
|
+
route: string;
|
|
158
|
+
samples: number;
|
|
159
|
+
stats: {
|
|
160
|
+
net: {
|
|
161
|
+
count: number;
|
|
162
|
+
mean: number;
|
|
163
|
+
m2: number;
|
|
164
|
+
max: number;
|
|
165
|
+
};
|
|
166
|
+
durationMs: {
|
|
167
|
+
count: number;
|
|
168
|
+
mean: number;
|
|
169
|
+
m2: number;
|
|
170
|
+
max: number;
|
|
171
|
+
};
|
|
172
|
+
consoleErrors: {
|
|
173
|
+
count: number;
|
|
174
|
+
mean: number;
|
|
175
|
+
m2: number;
|
|
176
|
+
max: number;
|
|
177
|
+
};
|
|
178
|
+
netErrors: {
|
|
179
|
+
count: number;
|
|
180
|
+
mean: number;
|
|
181
|
+
m2: number;
|
|
182
|
+
max: number;
|
|
183
|
+
};
|
|
184
|
+
};
|
|
185
|
+
}, {
|
|
186
|
+
route: string;
|
|
187
|
+
samples: number;
|
|
188
|
+
stats: {
|
|
189
|
+
net: {
|
|
190
|
+
count: number;
|
|
191
|
+
mean: number;
|
|
192
|
+
m2: number;
|
|
193
|
+
max: number;
|
|
194
|
+
};
|
|
195
|
+
durationMs: {
|
|
196
|
+
count: number;
|
|
197
|
+
mean: number;
|
|
198
|
+
m2: number;
|
|
199
|
+
max: number;
|
|
200
|
+
};
|
|
201
|
+
consoleErrors: {
|
|
202
|
+
count: number;
|
|
203
|
+
mean: number;
|
|
204
|
+
m2: number;
|
|
205
|
+
max: number;
|
|
206
|
+
};
|
|
207
|
+
netErrors: {
|
|
208
|
+
count: number;
|
|
209
|
+
mean: number;
|
|
210
|
+
m2: number;
|
|
211
|
+
max: number;
|
|
212
|
+
};
|
|
213
|
+
};
|
|
214
|
+
}>;
|
|
215
|
+
export declare function emptyEnvelope(route: string): RouteEnvelope;
|
|
216
|
+
/** Fold one observed segment into the envelope as a new sample. */
|
|
217
|
+
export declare function addSegmentToEnvelope(envelope: RouteEnvelope, segment: SegmentRollup): RouteEnvelope;
|
|
218
|
+
/** One metric of one segment running abnormally high against its envelope. */
|
|
219
|
+
export interface Deviation {
|
|
220
|
+
route: string;
|
|
221
|
+
metric: EnvelopeMetric;
|
|
222
|
+
observed: number;
|
|
223
|
+
expectedMean: number;
|
|
224
|
+
z: number;
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Compare a segment against its envelope. Returns the metrics running high (z above threshold),
|
|
228
|
+
* ranked most-severe first. Empty when the envelope is too green (< MIN_ENVELOPE_SAMPLES) — the caller
|
|
229
|
+
* falls back to the causal summary in that case.
|
|
230
|
+
*/
|
|
231
|
+
export declare function compareSegment(envelope: RouteEnvelope, segment: SegmentRollup, zThreshold?: number): Deviation[];
|
|
232
|
+
//# sourceMappingURL=envelope.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.d.ts","sourceRoot":"","sources":["../../src/journal/envelope.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,CAAC,EAAE,MAAM,KAAK,CAAC;AACxB,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD;;;;;;GAMG;AAEH,wGAAwG;AACxG,MAAM,WAAW,WAAW;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;IACb,uEAAuE;IACvE,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;CACb;AAED,wBAAgB,UAAU,IAAI,WAAW,CAExC;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,WAAW,CAMlE;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,CAEjD;AAED,+EAA+E;AAC/E,wBAAgB,MAAM,CAAC,KAAK,EAAE,WAAW,EAAE,CAAC,EAAE,MAAM,GAAG,MAAM,CAG5D;AAED,gDAAgD;AAChD,eAAO,MAAM,gBAAgB,8DAA+D,CAAC;AAC7F,MAAM,MAAM,cAAc,GAAG,CAAC,OAAO,gBAAgB,CAAC,CAAC,MAAM,CAAC,CAAC;AAE/D,MAAM,WAAW,aAAa;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,sGAAsG;IACtG,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;CAC5C;AAED,gGAAgG;AAChG,eAAO,MAAM,oBAAoB,IAAI,CAAC;AAEtC,kGAAkG;AAClG,eAAO,MAAM,mBAAmB,IAAI,CAAC;AASrC,kGAAkG;AAClG,eAAO,MAAM,mBAAmB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;EAS9B,CAAC;AAEH,wBAAgB,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,aAAa,CAW1D;AAeD,mEAAmE;AACnE,wBAAgB,oBAAoB,CAClC,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,aAAa,GACrB,aAAa,CAMf;AAED,8EAA8E;AAC9E,MAAM,WAAW,SAAS;IACxB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,cAAc,CAAC;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,CAAC,EAAE,MAAM,CAAC;CACX;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAC5B,QAAQ,EAAE,aAAa,EACvB,OAAO,EAAE,aAAa,EACtB,UAAU,GAAE,MAA4B,GACvC,SAAS,EAAE,CAYb"}
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
import { z } from 'zod';
|
|
2
|
+
export function emptyStats() {
|
|
3
|
+
return { count: 0, mean: 0, m2: 0, max: 0 };
|
|
4
|
+
}
|
|
5
|
+
export function addStat(stats, x) {
|
|
6
|
+
const count = stats.count + 1;
|
|
7
|
+
const delta = x - stats.mean;
|
|
8
|
+
const mean = stats.mean + delta / count;
|
|
9
|
+
const m2 = stats.m2 + delta * (x - mean);
|
|
10
|
+
return { count, mean, m2, max: Math.max(stats.max, x) };
|
|
11
|
+
}
|
|
12
|
+
export function stddev(stats) {
|
|
13
|
+
return stats.count < 2 ? 0 : Math.sqrt(stats.m2 / (stats.count - 1));
|
|
14
|
+
}
|
|
15
|
+
/** How many stddevs above the mean `x` sits (0 when there's no spread yet). */
|
|
16
|
+
export function zScore(stats, x) {
|
|
17
|
+
const sd = stddev(stats);
|
|
18
|
+
return sd === 0 ? 0 : (x - stats.mean) / sd;
|
|
19
|
+
}
|
|
20
|
+
/** The metrics an envelope tracks per route. */
|
|
21
|
+
export const ENVELOPE_METRICS = ['durationMs', 'net', 'netErrors', 'consoleErrors'];
|
|
22
|
+
/** Below this, an envelope is noise — the deviation report falls back to the causal summary. */
|
|
23
|
+
export const MIN_ENVELOPE_SAMPLES = 3;
|
|
24
|
+
/** Default flag threshold in stddevs. The number is a placeholder for fleet-calibrated priors. */
|
|
25
|
+
export const DEFAULT_Z_THRESHOLD = 3;
|
|
26
|
+
const MetricStatsSchema = z.object({
|
|
27
|
+
count: z.number(),
|
|
28
|
+
mean: z.number(),
|
|
29
|
+
m2: z.number(),
|
|
30
|
+
max: z.number(),
|
|
31
|
+
});
|
|
32
|
+
/** Persisted shape of a route envelope. Validated on load; a bad file degrades to no envelope. */
|
|
33
|
+
export const RouteEnvelopeSchema = z.object({
|
|
34
|
+
route: z.string(),
|
|
35
|
+
samples: z.number().int().min(0),
|
|
36
|
+
stats: z.object({
|
|
37
|
+
durationMs: MetricStatsSchema,
|
|
38
|
+
net: MetricStatsSchema,
|
|
39
|
+
netErrors: MetricStatsSchema,
|
|
40
|
+
consoleErrors: MetricStatsSchema,
|
|
41
|
+
}),
|
|
42
|
+
});
|
|
43
|
+
export function emptyEnvelope(route) {
|
|
44
|
+
return {
|
|
45
|
+
route,
|
|
46
|
+
samples: 0,
|
|
47
|
+
stats: {
|
|
48
|
+
durationMs: emptyStats(),
|
|
49
|
+
net: emptyStats(),
|
|
50
|
+
netErrors: emptyStats(),
|
|
51
|
+
consoleErrors: emptyStats(),
|
|
52
|
+
},
|
|
53
|
+
};
|
|
54
|
+
}
|
|
55
|
+
function metricValue(segment, metric) {
|
|
56
|
+
switch (metric) {
|
|
57
|
+
case 'durationMs':
|
|
58
|
+
return segment.durationMs;
|
|
59
|
+
case 'net':
|
|
60
|
+
return segment.net.total;
|
|
61
|
+
case 'netErrors':
|
|
62
|
+
return segment.net.errors;
|
|
63
|
+
case 'consoleErrors':
|
|
64
|
+
return segment.consoleErrors;
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
/** Fold one observed segment into the envelope as a new sample. */
|
|
68
|
+
export function addSegmentToEnvelope(envelope, segment) {
|
|
69
|
+
const stats = { ...envelope.stats };
|
|
70
|
+
for (const metric of ENVELOPE_METRICS) {
|
|
71
|
+
stats[metric] = addStat(stats[metric], metricValue(segment, metric));
|
|
72
|
+
}
|
|
73
|
+
return { route: envelope.route, samples: envelope.samples + 1, stats };
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* Compare a segment against its envelope. Returns the metrics running high (z above threshold),
|
|
77
|
+
* ranked most-severe first. Empty when the envelope is too green (< MIN_ENVELOPE_SAMPLES) — the caller
|
|
78
|
+
* falls back to the causal summary in that case.
|
|
79
|
+
*/
|
|
80
|
+
export function compareSegment(envelope, segment, zThreshold = DEFAULT_Z_THRESHOLD) {
|
|
81
|
+
if (envelope.samples < MIN_ENVELOPE_SAMPLES)
|
|
82
|
+
return [];
|
|
83
|
+
const deviations = [];
|
|
84
|
+
for (const metric of ENVELOPE_METRICS) {
|
|
85
|
+
const stats = envelope.stats[metric];
|
|
86
|
+
const observed = metricValue(segment, metric);
|
|
87
|
+
const z = zScore(stats, observed);
|
|
88
|
+
if (z > zThreshold) {
|
|
89
|
+
deviations.push({ route: envelope.route, metric, observed, expectedMean: stats.mean, z });
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return deviations.sort((a, b) => b.z - a.z);
|
|
93
|
+
}
|
|
94
|
+
//# sourceMappingURL=envelope.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"envelope.js","sourceRoot":"","sources":["../../src/journal/envelope.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { ReticleEvent } from '@reticlehq/core';
|
|
2
|
+
/** Filter bounds for a journal-backed event query. All optional; omitted = unbounded on that axis. */
|
|
3
|
+
export interface EventQueryOptions {
|
|
4
|
+
/** Lower time bound (inclusive), elapsed ms — the act cursor semantics of `eventsSince`. */
|
|
5
|
+
since?: number | undefined;
|
|
6
|
+
/** Upper time bound (inclusive), elapsed ms — the new `until` param. */
|
|
7
|
+
until?: number | undefined;
|
|
8
|
+
/** Keep only events attributed to this action id — answers "what did action N cause". */
|
|
9
|
+
actionId?: string | undefined;
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Merge the durable journal's events with the ring buffer's, de-duplicated by `seq` (unique per
|
|
13
|
+
* session), ordered by `seq` (falling back to `t` for any pre-2.2 event without one). Neither source is
|
|
14
|
+
* a strict superset — the journal holds everything already flushed (incl. evicted), the buffer holds the
|
|
15
|
+
* most-recent tail that may not be flushed yet — so the union is the complete picture.
|
|
16
|
+
*/
|
|
17
|
+
export declare function mergeEventsBySeq(journal: readonly ReticleEvent[], buffer: readonly ReticleEvent[]): ReticleEvent[];
|
|
18
|
+
/** Apply since/until/actionId bounds to an event list. */
|
|
19
|
+
export declare function filterEvents(events: readonly ReticleEvent[], options: EventQueryOptions): ReticleEvent[];
|
|
20
|
+
//# sourceMappingURL=journal-query.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-query.d.ts","sourceRoot":"","sources":["../../src/journal/journal-query.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAEpD,sGAAsG;AACtG,MAAM,WAAW,iBAAiB;IAChC,4FAA4F;IAC5F,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,wEAAwE;IACxE,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,yFAAyF;IACzF,QAAQ,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC/B;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,OAAO,EAAE,SAAS,YAAY,EAAE,EAChC,MAAM,EAAE,SAAS,YAAY,EAAE,GAC9B,YAAY,EAAE,CAWhB;AAED,0DAA0D;AAC1D,wBAAgB,YAAY,CAC1B,MAAM,EAAE,SAAS,YAAY,EAAE,EAC/B,OAAO,EAAE,iBAAiB,GACzB,YAAY,EAAE,CAOhB"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Merge the durable journal's events with the ring buffer's, de-duplicated by `seq` (unique per
|
|
3
|
+
* session), ordered by `seq` (falling back to `t` for any pre-2.2 event without one). Neither source is
|
|
4
|
+
* a strict superset — the journal holds everything already flushed (incl. evicted), the buffer holds the
|
|
5
|
+
* most-recent tail that may not be flushed yet — so the union is the complete picture.
|
|
6
|
+
*/
|
|
7
|
+
export function mergeEventsBySeq(journal, buffer) {
|
|
8
|
+
const bySeq = new Map();
|
|
9
|
+
const noSeq = [];
|
|
10
|
+
for (const event of [...journal, ...buffer]) {
|
|
11
|
+
if (typeof event.seq === 'number')
|
|
12
|
+
bySeq.set(event.seq, event);
|
|
13
|
+
else
|
|
14
|
+
noSeq.push(event);
|
|
15
|
+
}
|
|
16
|
+
return [...bySeq.values(), ...noSeq].sort((a, b) => {
|
|
17
|
+
if (a.seq !== undefined && b.seq !== undefined)
|
|
18
|
+
return a.seq - b.seq;
|
|
19
|
+
return a.t - b.t;
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/** Apply since/until/actionId bounds to an event list. */
|
|
23
|
+
export function filterEvents(events, options) {
|
|
24
|
+
return events.filter((event) => (options.since === undefined || event.t >= options.since) &&
|
|
25
|
+
(options.until === undefined || event.t <= options.until) &&
|
|
26
|
+
(options.actionId === undefined || event.actionId === options.actionId));
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=journal-query.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-query.js","sourceRoot":"","sources":["../../src/journal/journal-query.ts"],"names":[],"mappings":"AAYA;;;;;GAKG;AACH,MAAM,UAAU,gBAAgB,CAC9B,OAAgC,EAChC,MAA+B;IAE/B,MAAM,KAAK,GAAG,IAAI,GAAG,EAAwB,CAAC;IAC9C,MAAM,KAAK,GAAmB,EAAE,CAAC;IACjC,KAAK,MAAM,KAAK,IAAI,CAAC,GAAG,OAAO,EAAE,GAAG,MAAM,CAAC,EAAE,CAAC;QAC5C,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ;YAAE,KAAK,CAAC,GAAG,CAAC,KAAK,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;;YAC1D,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACzB,CAAC;IACD,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,EAAE,GAAG,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACjD,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS,IAAI,CAAC,CAAC,GAAG,KAAK,SAAS;YAAE,OAAO,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QACrE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;IACnB,CAAC,CAAC,CAAC;AACL,CAAC;AAED,0DAA0D;AAC1D,MAAM,UAAU,YAAY,CAC1B,MAA+B,EAC/B,OAA0B;IAE1B,OAAO,MAAM,CAAC,MAAM,CAClB,CAAC,KAAK,EAAE,EAAE,CACR,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC;QACzD,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,IAAI,KAAK,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,CAAC;QACzD,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,IAAI,KAAK,CAAC,QAAQ,KAAK,OAAO,CAAC,QAAQ,CAAC,CAC1E,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { type JournalAction, type ReticleEvent } from '@reticlehq/core';
|
|
2
|
+
/** Where a recorder persists. `SessionJournal` satisfies this structurally. */
|
|
3
|
+
export interface JournalSink {
|
|
4
|
+
appendEvents(events: readonly ReticleEvent[]): Promise<void>;
|
|
5
|
+
appendAction(action: JournalAction): Promise<void>;
|
|
6
|
+
}
|
|
7
|
+
/** Read side of the durable journal — the fall-through source when the ring buffer has evicted. */
|
|
8
|
+
export interface JournalReader {
|
|
9
|
+
readEvents(): Promise<ReticleEvent[]>;
|
|
10
|
+
}
|
|
11
|
+
export interface JournalRecorderOptions {
|
|
12
|
+
/** Injected elapsed-ms clock (never read from Date here — the clock-injection rule). */
|
|
13
|
+
now: () => number;
|
|
14
|
+
/** Flush the pending-event batch once this many accumulate. */
|
|
15
|
+
flushAt?: number;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Owns action-window attribution and batched, order-preserving journaling — the durable half of the
|
|
19
|
+
* causal spine, kept out of Session so neither file bloats. Every stamped event is `observe`d: if an
|
|
20
|
+
* action is active (dispatch→settle), the event is attributed to it (`attribution:"window"` — a time
|
|
21
|
+
* heuristic, never presented as dataflow truth) and its seq folds into the action's range. Writes are
|
|
22
|
+
* serialized on one chain so `events.jsonl` never interleaves and an action is always persisted after
|
|
23
|
+
* the events it closed. Sink writes are best-effort: a failed local journal write must never break the
|
|
24
|
+
* live session, so errors are swallowed.
|
|
25
|
+
*/
|
|
26
|
+
export declare class JournalRecorder {
|
|
27
|
+
#private;
|
|
28
|
+
constructor(sink: JournalSink, options: JournalRecorderOptions);
|
|
29
|
+
/** Attribute (if an action is active), enqueue for journaling, and return the possibly-stamped event. */
|
|
30
|
+
observe(event: ReticleEvent): ReticleEvent;
|
|
31
|
+
/** Open an attribution window. One action is active at a time (the agent drives sequentially). */
|
|
32
|
+
beginAction(actionId: string, tool: string, args: Record<string, unknown>): void;
|
|
33
|
+
/** Close the active window: persist its buffered events, then the action record. No-op if none active. */
|
|
34
|
+
finishAction(effect?: unknown, settled?: boolean, settledInMs?: number): void;
|
|
35
|
+
/** Persist any buffered events now (call on session end). Awaits the write chain to settle. */
|
|
36
|
+
flush(): Promise<void>;
|
|
37
|
+
}
|
|
38
|
+
//# sourceMappingURL=journal-recorder.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"journal-recorder.d.ts","sourceRoot":"","sources":["../../src/journal/journal-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,EAGL,KAAK,aAAa,EAClB,KAAK,YAAY,EAClB,MAAM,iBAAiB,CAAC;AAEzB,+EAA+E;AAC/E,MAAM,WAAW,WAAW;IAC1B,YAAY,CAAC,MAAM,EAAE,SAAS,YAAY,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC7D,YAAY,CAAC,MAAM,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpD;AAED,mGAAmG;AACnG,MAAM,WAAW,aAAa;IAC5B,UAAU,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;CACvC;AAED,MAAM,WAAW,sBAAsB;IACrC,wFAAwF;IACxF,GAAG,EAAE,MAAM,MAAM,CAAC;IAClB,+DAA+D;IAC/D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAaD;;;;;;;;GAQG;AACH,qBAAa,eAAe;;gBAQd,IAAI,EAAE,WAAW,EAAE,OAAO,EAAE,sBAAsB;IAM9D,yGAAyG;IACzG,OAAO,CAAC,KAAK,EAAE,YAAY,GAAG,YAAY;IAgB1C,kGAAkG;IAClG,WAAW,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAIhF,0GAA0G;IAC1G,YAAY,CAAC,MAAM,CAAC,EAAE,OAAO,EAAE,OAAO,CAAC,EAAE,OAAO,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI;IAuB7E,+FAA+F;IACzF,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;CAW7B"}
|