nlm-memory 0.20.0 → 0.21.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 +19 -10
- package/dist/cli/digest.js +60 -1
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.js +49 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/nlm.d.ts +13 -1
- package/dist/cli/nlm.js +872 -61
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/scope-backfill.d.ts +34 -0
- package/dist/cli/scope-backfill.js +237 -0
- package/dist/cli/scope-backfill.js.map +1 -0
- package/dist/cli/scope-coverage.d.ts +44 -0
- package/dist/cli/scope-coverage.js +205 -0
- package/dist/cli/scope-coverage.js.map +1 -0
- package/dist/core/actions/overlay.d.ts +20 -6
- package/dist/core/actions/overlay.js +32 -18
- package/dist/core/actions/overlay.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts +14 -0
- package/dist/core/adapters/claude-code.js +36 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/classifier/prompt.js +3 -3
- package/dist/core/dataset/build-dataset.js +1 -0
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +13 -3
- package/dist/core/digest/compose.js +23 -18
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +43 -0
- package/dist/core/digest/hook-injection.js +79 -0
- package/dist/core/digest/hook-injection.js.map +1 -0
- package/dist/core/embedding/embed-backfill.d.ts +13 -2
- package/dist/core/embedding/embed-backfill.js +181 -43
- package/dist/core/embedding/embed-backfill.js.map +1 -1
- package/dist/core/embedding/embedding-config.d.ts +17 -0
- package/dist/core/embedding/embedding-config.js +12 -0
- package/dist/core/embedding/embedding-config.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.d.ts +31 -0
- package/dist/core/embedding/pg-embed-backfill.js +264 -0
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -0
- package/dist/core/entities/dedup-suggest.d.ts +25 -0
- package/dist/core/entities/dedup-suggest.js +107 -0
- package/dist/core/entities/dedup-suggest.js.map +1 -0
- package/dist/core/eval/classifier-fixture-eval.d.ts +29 -0
- package/dist/core/eval/classifier-fixture-eval.js +217 -0
- package/dist/core/eval/classifier-fixture-eval.js.map +1 -0
- package/dist/core/eval/extraction-scoring.d.ts +63 -0
- package/dist/core/eval/extraction-scoring.js +79 -0
- package/dist/core/eval/extraction-scoring.js.map +1 -0
- package/dist/core/eval/run-eval.d.ts +40 -0
- package/dist/core/eval/run-eval.js +34 -0
- package/dist/core/eval/run-eval.js.map +1 -0
- package/dist/core/exemplars/capture-from-session.d.ts +2 -0
- package/dist/core/exemplars/capture-from-session.js +7 -3
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/diff-parse.d.ts +23 -0
- package/dist/core/exemplars/diff-parse.js +73 -0
- package/dist/core/exemplars/diff-parse.js.map +1 -0
- package/dist/core/exemplars/embed-backfill.d.ts +36 -0
- package/dist/core/exemplars/embed-backfill.js +85 -0
- package/dist/core/exemplars/embed-backfill.js.map +1 -0
- package/dist/core/exemplars/embed-text.d.ts +15 -0
- package/dist/core/exemplars/embed-text.js +18 -0
- package/dist/core/exemplars/embed-text.js.map +1 -0
- package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
- package/dist/core/exemplars/extract-exemplar.js +9 -66
- package/dist/core/exemplars/extract-exemplar.js.map +1 -1
- package/dist/core/exemplars/ingest-exemplar.d.ts +1 -0
- package/dist/core/exemplars/ingest-exemplar.js +1 -0
- package/dist/core/exemplars/ingest-exemplar.js.map +1 -1
- package/dist/core/exemplars/recall-code.js +4 -0
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/exemplars/warm-embedder.d.ts +14 -0
- package/dist/core/exemplars/warm-embedder.js +18 -0
- package/dist/core/exemplars/warm-embedder.js.map +1 -0
- package/dist/core/health/corpus-state.d.ts +8 -0
- package/dist/core/health/corpus-state.js +11 -0
- package/dist/core/health/corpus-state.js.map +1 -0
- package/dist/core/health/embed-inflight.d.ts +9 -0
- package/dist/core/health/embed-inflight.js +30 -0
- package/dist/core/health/embed-inflight.js.map +1 -0
- package/dist/core/health/embedding-lane-state.d.ts +6 -0
- package/dist/core/health/embedding-lane-state.js +18 -0
- package/dist/core/health/embedding-lane-state.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +12 -0
- package/dist/core/health/warmup-state.js +12 -0
- package/dist/core/health/warmup-state.js.map +1 -0
- package/dist/core/hook/claude-settings.d.ts +1 -1
- package/dist/core/hook/claude-settings.js +0 -1
- package/dist/core/hook/claude-settings.js.map +1 -1
- package/dist/core/hook/gate.d.ts +13 -6
- package/dist/core/hook/gate.js +47 -6
- package/dist/core/hook/gate.js.map +1 -1
- package/dist/core/hook/hook-log.d.ts +5 -0
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +12 -0
- package/dist/core/hook/memo.js +41 -1
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +1 -0
- package/dist/core/hook/pointer-block.js +23 -2
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/query-extract.d.ts +2 -1
- package/dist/core/hook/query-extract.js +10 -1
- package/dist/core/hook/query-extract.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +28 -0
- package/dist/core/hook/resolve-conversation-by-query.js +98 -0
- package/dist/core/hook/resolve-conversation-by-query.js.map +1 -0
- package/dist/core/hook/select.d.ts +8 -0
- package/dist/core/hook/select.js +9 -2
- package/dist/core/hook/select.js.map +1 -1
- package/dist/core/hook/transcript.js +16 -2
- package/dist/core/hook/transcript.js.map +1 -1
- package/dist/core/ingest/backfill-derivables.d.ts +92 -0
- package/dist/core/ingest/backfill-derivables.js +175 -0
- package/dist/core/ingest/backfill-derivables.js.map +1 -0
- package/dist/core/ingest/ingest-session.d.ts +5 -0
- package/dist/core/ingest/ingest-session.js +23 -0
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +5 -0
- package/dist/core/ingest/reclassify-oversized.js +9 -0
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +96 -0
- package/dist/core/ingest/reprocess.js +280 -0
- package/dist/core/ingest/reprocess.js.map +1 -0
- package/dist/core/ingest/transcript-derivables.d.ts +27 -0
- package/dist/core/ingest/transcript-derivables.js +138 -0
- package/dist/core/ingest/transcript-derivables.js.map +1 -0
- package/dist/core/integrity/check-invariants.d.ts +6 -1
- package/dist/core/integrity/check-invariants.js +209 -3
- package/dist/core/integrity/check-invariants.js.map +1 -1
- package/dist/core/metrics/corpus-stats.d.ts +49 -0
- package/dist/core/metrics/corpus-stats.js +111 -0
- package/dist/core/metrics/corpus-stats.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +48 -0
- package/dist/core/metrics/re-derivation.js +87 -0
- package/dist/core/metrics/re-derivation.js.map +1 -0
- package/dist/core/outcome/coverage.d.ts +33 -0
- package/dist/core/outcome/coverage.js +46 -0
- package/dist/core/outcome/coverage.js.map +1 -0
- package/dist/core/outcome/rollup.d.ts +33 -0
- package/dist/core/outcome/rollup.js +113 -0
- package/dist/core/outcome/rollup.js.map +1 -0
- package/dist/core/recall/citation-log.d.ts +8 -0
- package/dist/core/recall/citation-log.js +17 -0
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +2 -2
- package/dist/core/recall/hook-recall-log.js +2 -2
- package/dist/core/recall/query-intent.d.ts +7 -0
- package/dist/core/recall/query-intent.js +25 -0
- package/dist/core/recall/query-intent.js.map +1 -0
- package/dist/core/recall/query-log.d.ts +4 -0
- package/dist/core/recall/query-log.js +4 -0
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +37 -1
- package/dist/core/recall/recall-service.js +106 -63
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/related-exemplars.d.ts +1 -0
- package/dist/core/recall/related-exemplars.js +4 -1
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.js +2 -2
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall/reranker.d.ts +2 -1
- package/dist/core/recall/reranker.js +3 -3
- package/dist/core/recall/reranker.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +7 -0
- package/dist/core/recall-facts/fact-query-log.js +2 -0
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +9 -1
- package/dist/core/recall-facts/fact-recall-service.js +22 -8
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.d.ts +6 -6
- package/dist/core/scheduler/scan-once.js +15 -49
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +10 -0
- package/dist/core/scheduler/scheduler.js +109 -13
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/scope/alias-map.d.ts +10 -0
- package/dist/core/scope/alias-map.js +41 -0
- package/dist/core/scope/alias-map.js.map +1 -0
- package/dist/core/scope/derive-scope.d.ts +8 -0
- package/dist/core/scope/derive-scope.js +54 -0
- package/dist/core/scope/derive-scope.js.map +1 -0
- package/dist/core/scope/scope-clause.d.ts +16 -0
- package/dist/core/scope/scope-clause.js +21 -0
- package/dist/core/scope/scope-clause.js.map +1 -0
- package/dist/core/scope/stamp-flag.d.ts +1 -0
- package/dist/core/scope/stamp-flag.js +4 -0
- package/dist/core/scope/stamp-flag.js.map +1 -0
- package/dist/core/signals/code-signal.d.ts +50 -0
- package/dist/core/signals/code-signal.js +54 -0
- package/dist/core/signals/code-signal.js.map +1 -0
- package/dist/core/signals/ingest-signal.d.ts +1 -1
- package/dist/core/signals/ingest-signal.js +3 -1
- package/dist/core/signals/ingest-signal.js.map +1 -1
- package/dist/core/signals/stamp-scope.d.ts +18 -0
- package/dist/core/signals/stamp-scope.js +28 -0
- package/dist/core/signals/stamp-scope.js.map +1 -0
- package/dist/core/storage/db-restore.js +3 -1
- package/dist/core/storage/db-restore.js.map +1 -1
- package/dist/core/storage/fact-batch.d.ts +9 -0
- package/dist/core/storage/fact-batch.js +14 -0
- package/dist/core/storage/fact-batch.js.map +1 -0
- package/dist/core/storage/pg-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/pg-code-exemplar-store.js +13 -2
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-embedding-config.d.ts +29 -0
- package/dist/core/storage/pg-embedding-config.js +53 -0
- package/dist/core/storage/pg-embedding-config.js.map +1 -0
- package/dist/core/storage/pg-entity-store.d.ts +12 -0
- package/dist/core/storage/pg-entity-store.js +79 -0
- package/dist/core/storage/pg-entity-store.js.map +1 -0
- package/dist/core/storage/pg-fact-ingest.d.ts +15 -0
- package/dist/core/storage/pg-fact-ingest.js +34 -0
- package/dist/core/storage/pg-fact-ingest.js.map +1 -0
- package/dist/core/storage/pg-fact-store.d.ts +3 -0
- package/dist/core/storage/pg-fact-store.js +26 -30
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-migrate.d.ts +18 -0
- package/dist/core/storage/pg-migrate.js +73 -0
- package/dist/core/storage/pg-migrate.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +11 -2
- package/dist/core/storage/pg-session-store.js +224 -96
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.js +4 -3
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +9 -7
- package/dist/core/storage/pg-storage.js +20 -50
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +25 -0
- package/dist/core/storage/pg-workstream-store.js +97 -0
- package/dist/core/storage/pg-workstream-store.js.map +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.js +15 -2
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-embedding-config.d.ts +10 -0
- package/dist/core/storage/sqlite-embedding-config.js +27 -0
- package/dist/core/storage/sqlite-embedding-config.js.map +1 -0
- package/dist/core/storage/sqlite-entity-store.d.ts +13 -0
- package/dist/core/storage/sqlite-entity-store.js +96 -0
- package/dist/core/storage/sqlite-entity-store.js.map +1 -0
- package/dist/core/storage/sqlite-fact-store.d.ts +15 -7
- package/dist/core/storage/sqlite-fact-store.js +81 -27
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-outcome-store.d.ts +89 -0
- package/dist/core/storage/sqlite-outcome-store.js +158 -0
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
- package/dist/core/storage/sqlite-session-store.d.ts +42 -7
- package/dist/core/storage/sqlite-session-store.js +208 -95
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.js +4 -2
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +8 -8
- package/dist/core/storage/sqlite-storage.js +21 -32
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +25 -0
- package/dist/core/storage/sqlite-workstream-store.js +99 -0
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -0
- package/dist/core/storage/supersedence-log.js +2 -0
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/core/telemetry/probe-filter.d.ts +35 -0
- package/dist/core/telemetry/probe-filter.js +56 -0
- package/dist/core/telemetry/probe-filter.js.map +1 -0
- package/dist/core/update-check/check.d.ts +6 -0
- package/dist/core/update-check/check.js +35 -0
- package/dist/core/update-check/check.js.map +1 -1
- package/dist/core/work-digest/active-spans.d.ts +8 -0
- package/dist/core/work-digest/active-spans.js +29 -0
- package/dist/core/work-digest/active-spans.js.map +1 -0
- package/dist/core/work-digest/attribute.d.ts +15 -0
- package/dist/core/work-digest/attribute.js +76 -0
- package/dist/core/work-digest/attribute.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +12 -0
- package/dist/core/work-digest/build-work-digest.js +69 -0
- package/dist/core/work-digest/build-work-digest.js.map +1 -0
- package/dist/core/work-digest/compose-work-digest.d.ts +3 -0
- package/dist/core/work-digest/compose-work-digest.js +52 -0
- package/dist/core/work-digest/compose-work-digest.js.map +1 -0
- package/dist/core/work-digest/merge-active.d.ts +10 -0
- package/dist/core/work-digest/merge-active.js +22 -0
- package/dist/core/work-digest/merge-active.js.map +1 -0
- package/dist/core/work-digest/read-transcript-timestamps.d.ts +7 -0
- package/dist/core/work-digest/read-transcript-timestamps.js +40 -0
- package/dist/core/work-digest/read-transcript-timestamps.js.map +1 -0
- package/dist/core/work-digest/topics.d.ts +18 -0
- package/dist/core/work-digest/topics.js +26 -0
- package/dist/core/work-digest/topics.js.map +1 -0
- package/dist/core/work-digest/types.d.ts +45 -0
- package/dist/core/work-digest/types.js +2 -0
- package/dist/core/work-digest/types.js.map +1 -0
- package/dist/core/workstream/bind.d.ts +26 -0
- package/dist/core/workstream/bind.js +42 -0
- package/dist/core/workstream/bind.js.map +1 -0
- package/dist/core/workstream/compose-recall.d.ts +2 -0
- package/dist/core/workstream/compose-recall.js +39 -0
- package/dist/core/workstream/compose-recall.js.map +1 -0
- package/dist/core/workstream/merge-suggest.d.ts +19 -0
- package/dist/core/workstream/merge-suggest.js +61 -0
- package/dist/core/workstream/merge-suggest.js.map +1 -0
- package/dist/core/workstream/model.d.ts +21 -0
- package/dist/core/workstream/model.js +9 -0
- package/dist/core/workstream/model.js.map +1 -0
- package/dist/core/workstream/name-match.d.ts +8 -0
- package/dist/core/workstream/name-match.js +18 -0
- package/dist/core/workstream/name-match.js.map +1 -0
- package/dist/core/workstream/resolve.d.ts +10 -0
- package/dist/core/workstream/resolve.js +21 -0
- package/dist/core/workstream/resolve.js.map +1 -0
- package/dist/core/workstream/rollup.d.ts +12 -0
- package/dist/core/workstream/rollup.js +17 -0
- package/dist/core/workstream/rollup.js.map +1 -0
- package/dist/core/workstream/work-topics.d.ts +10 -0
- package/dist/core/workstream/work-topics.js +55 -0
- package/dist/core/workstream/work-topics.js.map +1 -0
- package/dist/hook/hook-helpers.d.ts +4 -0
- package/dist/hook/hook-helpers.js +36 -0
- package/dist/hook/hook-helpers.js.map +1 -0
- package/dist/hook/pre-compact-hook.d.ts +23 -0
- package/dist/hook/pre-compact-hook.js +67 -0
- package/dist/hook/pre-compact-hook.js.map +1 -0
- package/dist/hook/prompt-recall-hook.d.ts +38 -0
- package/dist/hook/prompt-recall-hook.js +124 -20
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-gate.d.ts +29 -0
- package/dist/hook/recall-gate.js +50 -0
- package/dist/hook/recall-gate.js.map +1 -0
- package/dist/hook/recall-over-http.d.ts +3 -2
- package/dist/hook/recall-over-http.js +26 -13
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/recent-context.d.ts +25 -0
- package/dist/hook/recent-context.js +104 -0
- package/dist/hook/recent-context.js.map +1 -0
- package/dist/hook/score-floor.d.ts +27 -0
- package/dist/hook/score-floor.js +42 -0
- package/dist/hook/score-floor.js.map +1 -0
- package/dist/hook/session-end-hook.js +8 -29
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.js +26 -60
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +24 -60
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +6 -0
- package/dist/http/app.js +52 -44
- package/dist/http/app.js.map +1 -1
- package/dist/install/setup.js +2 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/llm/build-classifier.d.ts +22 -0
- package/dist/llm/build-classifier.js +42 -0
- package/dist/llm/build-classifier.js.map +1 -0
- package/dist/llm/build-embedder.d.ts +11 -0
- package/dist/llm/build-embedder.js +42 -0
- package/dist/llm/build-embedder.js.map +1 -0
- package/dist/llm/bundled-embedder-client.d.ts +37 -0
- package/dist/llm/bundled-embedder-client.js +90 -0
- package/dist/llm/bundled-embedder-client.js.map +1 -0
- package/dist/llm/classifier-box.d.ts +13 -5
- package/dist/llm/classifier-box.js +28 -6
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/llm/classifier-egress.d.ts +18 -0
- package/dist/llm/classifier-egress.js +59 -0
- package/dist/llm/classifier-egress.js.map +1 -0
- package/dist/llm/client-shared.d.ts +4 -0
- package/dist/llm/client-shared.js +39 -0
- package/dist/llm/client-shared.js.map +1 -0
- package/dist/llm/deepseek-client.d.ts +20 -0
- package/dist/llm/deepseek-client.js +59 -45
- package/dist/llm/deepseek-client.js.map +1 -1
- package/dist/llm/embedder-info.d.ts +15 -0
- package/dist/llm/embedder-info.js +27 -0
- package/dist/llm/embedder-info.js.map +1 -0
- package/dist/llm/model-quirks.d.ts +4 -0
- package/dist/llm/model-quirks.js +7 -0
- package/dist/llm/model-quirks.js.map +1 -0
- package/dist/llm/naming.d.ts +5 -0
- package/dist/llm/naming.js +20 -0
- package/dist/llm/naming.js.map +1 -0
- package/dist/llm/ollama-client.d.ts +7 -8
- package/dist/llm/ollama-client.js +59 -51
- package/dist/llm/ollama-client.js.map +1 -1
- package/dist/llm/ollama-code-embedder.d.ts +8 -3
- package/dist/llm/ollama-code-embedder.js +14 -24
- package/dist/llm/ollama-code-embedder.js.map +1 -1
- package/dist/llm/openai-code-embedder-client.d.ts +25 -0
- package/dist/llm/openai-code-embedder-client.js +52 -0
- package/dist/llm/openai-code-embedder-client.js.map +1 -0
- package/dist/llm/openai-embedder-client.d.ts +41 -0
- package/dist/llm/openai-embedder-client.js +83 -0
- package/dist/llm/openai-embedder-client.js.map +1 -0
- package/dist/mcp/server.d.ts +69 -2
- package/dist/mcp/server.js +404 -19
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/code-embedder.d.ts +6 -1
- package/dist/ports/code-exemplar-store.d.ts +5 -0
- package/dist/ports/entity-store.d.ts +35 -0
- package/dist/ports/entity-store.js +7 -0
- package/dist/ports/entity-store.js.map +1 -0
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/llm-client.d.ts +9 -1
- package/dist/ports/outcome.d.ts +85 -0
- package/dist/ports/outcome.js +11 -0
- package/dist/ports/outcome.js.map +1 -0
- package/dist/ports/session-store.d.ts +12 -6
- package/dist/ports/storage.d.ts +7 -30
- package/dist/ports/storage.js +3 -7
- package/dist/ports/storage.js.map +1 -1
- package/dist/ports/transcript-adapter.d.ts +2 -0
- package/dist/ports/workstream-store.d.ts +22 -0
- package/dist/ports/workstream-store.js +2 -0
- package/dist/ports/workstream-store.js.map +1 -0
- package/dist/shared/net.d.ts +3 -0
- package/dist/shared/net.js +4 -0
- package/dist/shared/net.js.map +1 -0
- package/dist/shared/types.d.ts +56 -2
- package/dist/shared/types.js +4 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/ui/assets/{index-CMpQkbQy.js → index-CSaBtgXD.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/fixtures/classifier-gold/README.md +94 -0
- package/fixtures/classifier-gold/reference.json +318 -0
- package/fixtures/classifier-gold/transcripts/01-bug-fix-null-pointer-api.txt +75 -0
- package/fixtures/classifier-gold/transcripts/02-bug-fix-race-condition-queue.txt +77 -0
- package/fixtures/classifier-gold/transcripts/03-bug-fix-jwt-clock-skew.txt +86 -0
- package/fixtures/classifier-gold/transcripts/04-feature-webhook-retry.txt +95 -0
- package/fixtures/classifier-gold/transcripts/05-feature-csv-export.txt +86 -0
- package/fixtures/classifier-gold/transcripts/06-feature-rate-limiting.txt +61 -0
- package/fixtures/classifier-gold/transcripts/07-refactor-db-abstraction.txt +72 -0
- package/fixtures/classifier-gold/transcripts/08-refactor-config-loading.txt +89 -0
- package/fixtures/classifier-gold/transcripts/09-ops-docker-staging.txt +94 -0
- package/fixtures/classifier-gold/transcripts/10-ops-nginx-ssl.txt +121 -0
- package/fixtures/classifier-gold/transcripts/11-ops-postgres-migration.txt +74 -0
- package/fixtures/classifier-gold/transcripts/12-ops-cron-debugging.txt +73 -0
- package/fixtures/classifier-gold/transcripts/13-research-vector-db-comparison.txt +59 -0
- package/fixtures/classifier-gold/transcripts/14-research-oauth-provider.txt +74 -0
- package/fixtures/classifier-gold/transcripts/15-writing-api-docs.txt +154 -0
- package/fixtures/classifier-gold/transcripts/16-meeting-sprint-planning.txt +69 -0
- package/fixtures/classifier-gold/transcripts/17-trivial-list-files.txt +14 -0
- package/fixtures/classifier-gold/transcripts/18-trivial-version-check.txt +21 -0
- package/fixtures/classifier-gold/transcripts/19-trivial-syntax-help.txt +29 -0
- package/fixtures/classifier-gold/transcripts/20-trivial-read-package-json.txt +41 -0
- package/migrations/000_initial_schema.sql +1 -1
- package/migrations/024_backfill_exemplar_repo_basename.sql +32 -0
- package/migrations/025_workstreams.sql +30 -0
- package/migrations/026_embedding_config.sql +12 -0
- package/migrations/027_drop_legacy_session_embeddings.sql +7 -0
- package/migrations/028_classifier_provenance.sql +5 -0
- package/migrations/029_project_scope.sql +21 -0
- package/migrations/032_session_derivables.sql +11 -0
- package/migrations/pg/001_initial.sql +34 -0
- package/migrations/pg/019_split_replaces.sql +16 -7
- package/migrations/pg/025_workstreams.sql +34 -0
- package/migrations/pg/026_embedding_config.sql +12 -0
- package/migrations/pg/028_classifier_provenance.sql +5 -0
- package/migrations/pg/029_entity_variants.sql +9 -0
- package/migrations/pg/030_project_scope.sql +23 -0
- package/migrations/pg/031_widen_session_edges_kind.sql +11 -0
- package/migrations/pg/032_session_derivables.sql +17 -0
- package/nlm/index.js +405 -39
- package/package.json +12 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/scripts/prompt-recall-hook.mjs +413 -43
- package/plugin/scripts/session-start-hook.mjs +295 -61
- package/plugin/scripts/stop-hook.mjs +89 -66
- package/plugin-hermes-agent/__init__.py +2 -1
- package/templates/agent-contract/README.md +24 -0
- package/templates/agent-contract/claude-code.md +40 -0
- package/templates/agent-contract/generic.md +38 -0
- package/dist/core/embedding/embed-normalize.d.ts +0 -28
- package/dist/core/embedding/embed-normalize.js +0 -98
- package/dist/core/embedding/embed-normalize.js.map +0 -1
- package/dist/core/storage/pg-tx-context.d.ts +0 -52
- package/dist/core/storage/pg-tx-context.js +0 -149
- package/dist/core/storage/pg-tx-context.js.map +0 -1
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nlm scope backfill`: derive and stamp scope on legacy corpus rows.
|
|
3
|
+
*
|
|
4
|
+
* Cascade order: sessions -> facts -> exemplars -> signals -> workstreams.
|
|
5
|
+
* --dry-run (default): computes would-change counts and writes nothing.
|
|
6
|
+
* --apply: writes; only fills scope IS NULL rows; idempotent.
|
|
7
|
+
*/
|
|
8
|
+
import { open } from "node:fs/promises";
|
|
9
|
+
import Database from "better-sqlite3";
|
|
10
|
+
import { deriveScope } from "../core/scope/derive-scope.js";
|
|
11
|
+
/** Read at most this many bytes from the head of a transcript to find cwd. */
|
|
12
|
+
const HEAD_BYTES = 8_192;
|
|
13
|
+
/**
|
|
14
|
+
* Bounded head-read that matches the claude-code adapter's cwd extraction
|
|
15
|
+
* exactly (src/core/adapters/claude-code.ts:144):
|
|
16
|
+
* if (!projectDir && typeof evt["cwd"] === "string") projectDir = evt["cwd"];
|
|
17
|
+
*
|
|
18
|
+
* Also covers pi-runtime JSONL: the pi adapter reads cwd from the
|
|
19
|
+
* `type: "session"` event on line 1 (src/core/adapters/pi.ts:124-126);
|
|
20
|
+
* taking the first `cwd` field on any line subsumes that shape.
|
|
21
|
+
*
|
|
22
|
+
* Reads at most HEAD_BYTES from the file start, splits into lines, parses
|
|
23
|
+
* each as JSON, and returns the value of the first "cwd" string field found.
|
|
24
|
+
* A first line longer than HEAD_BYTES arrives truncated, fails JSON.parse,
|
|
25
|
+
* and is skipped: fail-closed to NULL, never a mis-parse.
|
|
26
|
+
*/
|
|
27
|
+
async function readCwdFromTranscript(transcriptPath) {
|
|
28
|
+
let fd;
|
|
29
|
+
try {
|
|
30
|
+
fd = await open(transcriptPath, "r");
|
|
31
|
+
const buf = Buffer.alloc(HEAD_BYTES);
|
|
32
|
+
const { bytesRead } = await fd.read(buf, 0, HEAD_BYTES, 0);
|
|
33
|
+
const head = buf.toString("utf8", 0, bytesRead);
|
|
34
|
+
for (const line of head.split("\n")) {
|
|
35
|
+
const trimmed = line.trim();
|
|
36
|
+
if (!trimmed)
|
|
37
|
+
continue;
|
|
38
|
+
let evt;
|
|
39
|
+
try {
|
|
40
|
+
evt = JSON.parse(trimmed);
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
continue;
|
|
44
|
+
}
|
|
45
|
+
if (typeof evt["cwd"] === "string" && evt["cwd"]) {
|
|
46
|
+
return { cwd: evt["cwd"] };
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return { cwd: null };
|
|
50
|
+
}
|
|
51
|
+
catch (err) {
|
|
52
|
+
const code = err.code;
|
|
53
|
+
const skipReason = code === "ENOENT" || code === "EACCES" || code === "EPERM"
|
|
54
|
+
? "missing"
|
|
55
|
+
: "malformed";
|
|
56
|
+
return { cwd: null, skipReason };
|
|
57
|
+
}
|
|
58
|
+
finally {
|
|
59
|
+
await fd?.close().catch(() => { });
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
function inc(counter, scope) {
|
|
63
|
+
counter[scope] = (counter[scope] ?? 0) + 1;
|
|
64
|
+
}
|
|
65
|
+
function emptyTable() {
|
|
66
|
+
return { total: 0, byScope: {} };
|
|
67
|
+
}
|
|
68
|
+
export async function runScopeBackfill(opts) {
|
|
69
|
+
const { db, apply, aliasMap } = opts;
|
|
70
|
+
const sessionRows = db
|
|
71
|
+
.prepare("SELECT id, transcript_path FROM sessions WHERE scope IS NULL AND transcript_path IS NOT NULL")
|
|
72
|
+
.all();
|
|
73
|
+
const derivedScopes = new Map();
|
|
74
|
+
let missingCount = 0;
|
|
75
|
+
let malformedCount = 0;
|
|
76
|
+
let noCwdCount = 0;
|
|
77
|
+
for (const row of sessionRows) {
|
|
78
|
+
const { cwd, skipReason } = await readCwdFromTranscript(row.transcript_path);
|
|
79
|
+
if (skipReason === "missing") {
|
|
80
|
+
missingCount++;
|
|
81
|
+
continue;
|
|
82
|
+
}
|
|
83
|
+
if (skipReason === "malformed") {
|
|
84
|
+
malformedCount++;
|
|
85
|
+
continue;
|
|
86
|
+
}
|
|
87
|
+
if (!cwd) {
|
|
88
|
+
noCwdCount++;
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
const scope = deriveScope(cwd, aliasMap);
|
|
92
|
+
if (scope === null)
|
|
93
|
+
continue;
|
|
94
|
+
derivedScopes.set(row.id, scope);
|
|
95
|
+
}
|
|
96
|
+
const result = {
|
|
97
|
+
dryRun: !apply,
|
|
98
|
+
sessions: emptyTable(),
|
|
99
|
+
facts: emptyTable(),
|
|
100
|
+
exemplars: emptyTable(),
|
|
101
|
+
signals: emptyTable(),
|
|
102
|
+
workstreams: emptyTable(),
|
|
103
|
+
skipped: { missingTranscript: missingCount, malformed: malformedCount, noCwdFound: noCwdCount },
|
|
104
|
+
};
|
|
105
|
+
for (const scope of derivedScopes.values()) {
|
|
106
|
+
result.sessions.total++;
|
|
107
|
+
inc(result.sessions.byScope, scope);
|
|
108
|
+
}
|
|
109
|
+
const performUpdates = () => {
|
|
110
|
+
const updateSession = db.prepare("UPDATE sessions SET scope = ? WHERE id = ? AND scope IS NULL");
|
|
111
|
+
for (const [id, scope] of derivedScopes) {
|
|
112
|
+
updateSession.run(scope, id);
|
|
113
|
+
}
|
|
114
|
+
const factRows = db
|
|
115
|
+
.prepare(`
|
|
116
|
+
SELECT s.scope, COUNT(f.id) AS n
|
|
117
|
+
FROM facts f
|
|
118
|
+
JOIN sessions s ON f.source_session_id = s.id
|
|
119
|
+
WHERE f.scope IS NULL AND s.scope IS NOT NULL
|
|
120
|
+
GROUP BY s.scope
|
|
121
|
+
`)
|
|
122
|
+
.all();
|
|
123
|
+
for (const { scope, n } of factRows) {
|
|
124
|
+
result.facts.total += n;
|
|
125
|
+
inc(result.facts.byScope, scope);
|
|
126
|
+
}
|
|
127
|
+
db.prepare(`
|
|
128
|
+
UPDATE facts
|
|
129
|
+
SET scope = (SELECT s.scope FROM sessions s WHERE s.id = facts.source_session_id)
|
|
130
|
+
WHERE scope IS NULL
|
|
131
|
+
AND source_session_id IN (SELECT id FROM sessions WHERE scope IS NOT NULL)
|
|
132
|
+
`).run();
|
|
133
|
+
const exemplarRows = db
|
|
134
|
+
.prepare(`
|
|
135
|
+
SELECT s.scope, COUNT(e.id) AS n
|
|
136
|
+
FROM code_exemplars e
|
|
137
|
+
JOIN sessions s ON e.session_id = s.id
|
|
138
|
+
WHERE e.scope IS NULL AND s.scope IS NOT NULL
|
|
139
|
+
GROUP BY s.scope
|
|
140
|
+
`)
|
|
141
|
+
.all();
|
|
142
|
+
for (const { scope, n } of exemplarRows) {
|
|
143
|
+
result.exemplars.total += n;
|
|
144
|
+
inc(result.exemplars.byScope, scope);
|
|
145
|
+
}
|
|
146
|
+
db.prepare(`
|
|
147
|
+
UPDATE code_exemplars
|
|
148
|
+
SET scope = (SELECT s.scope FROM sessions s WHERE s.id = code_exemplars.session_id)
|
|
149
|
+
WHERE scope IS NULL
|
|
150
|
+
AND session_id IN (SELECT id FROM sessions WHERE scope IS NOT NULL)
|
|
151
|
+
`).run();
|
|
152
|
+
const signalRows = db
|
|
153
|
+
.prepare(`
|
|
154
|
+
SELECT s.scope, COUNT(sig.id) AS n
|
|
155
|
+
FROM signals sig
|
|
156
|
+
JOIN sessions s ON sig.session_id = s.id
|
|
157
|
+
WHERE sig.scope IS NULL AND s.scope IS NOT NULL AND s.scope != 'global'
|
|
158
|
+
GROUP BY s.scope
|
|
159
|
+
`)
|
|
160
|
+
.all();
|
|
161
|
+
for (const { scope, n } of signalRows) {
|
|
162
|
+
result.signals.total += n;
|
|
163
|
+
inc(result.signals.byScope, scope);
|
|
164
|
+
}
|
|
165
|
+
db.prepare(`
|
|
166
|
+
UPDATE signals
|
|
167
|
+
SET scope = (SELECT s.scope FROM sessions s WHERE s.id = signals.session_id)
|
|
168
|
+
WHERE scope IS NULL
|
|
169
|
+
AND session_id IS NOT NULL
|
|
170
|
+
AND session_id IN (
|
|
171
|
+
SELECT id FROM sessions WHERE scope IS NOT NULL AND scope != 'global'
|
|
172
|
+
)
|
|
173
|
+
`).run();
|
|
174
|
+
const pendingWorkstreams = db
|
|
175
|
+
.prepare("SELECT id FROM workstreams WHERE scope IS NULL")
|
|
176
|
+
.all();
|
|
177
|
+
const getMemberScopes = db.prepare("SELECT scope FROM sessions WHERE workstream_id = ?");
|
|
178
|
+
const updateWs = db.prepare("UPDATE workstreams SET scope = ? WHERE id = ? AND scope IS NULL");
|
|
179
|
+
for (const ws of pendingWorkstreams) {
|
|
180
|
+
const members = getMemberScopes.all(ws.id);
|
|
181
|
+
if (members.length === 0)
|
|
182
|
+
continue;
|
|
183
|
+
if (members.some((m) => m.scope === null))
|
|
184
|
+
continue;
|
|
185
|
+
const unique = new Set(members.map((m) => m.scope));
|
|
186
|
+
if (unique.size !== 1)
|
|
187
|
+
continue;
|
|
188
|
+
const wsScope = [...unique][0];
|
|
189
|
+
result.workstreams.total++;
|
|
190
|
+
inc(result.workstreams.byScope, wsScope);
|
|
191
|
+
updateWs.run(wsScope, ws.id);
|
|
192
|
+
}
|
|
193
|
+
};
|
|
194
|
+
if (apply) {
|
|
195
|
+
db.transaction(performUpdates)();
|
|
196
|
+
}
|
|
197
|
+
else {
|
|
198
|
+
db.exec("BEGIN");
|
|
199
|
+
try {
|
|
200
|
+
performUpdates();
|
|
201
|
+
}
|
|
202
|
+
finally {
|
|
203
|
+
db.exec("ROLLBACK");
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
return result;
|
|
207
|
+
}
|
|
208
|
+
export function formatBackfillResult(result, write) {
|
|
209
|
+
const heading = result.dryRun
|
|
210
|
+
? "scope backfill (dry run -- no writes):"
|
|
211
|
+
: "scope backfill applied:";
|
|
212
|
+
write(`${heading}\n`);
|
|
213
|
+
const rows = [
|
|
214
|
+
["sessions", result.dryRun ? "would change" : "stamped", result.sessions],
|
|
215
|
+
["facts", result.dryRun ? "would cascade" : "cascaded", result.facts],
|
|
216
|
+
["exemplars", result.dryRun ? "would cascade" : "cascaded", result.exemplars],
|
|
217
|
+
["signals", result.dryRun ? "would cascade" : "cascaded", result.signals],
|
|
218
|
+
["workstreams", result.dryRun ? "would cascade" : "cascaded", result.workstreams],
|
|
219
|
+
];
|
|
220
|
+
for (const [table, verb, data] of rows) {
|
|
221
|
+
const entries = Object.entries(data.byScope);
|
|
222
|
+
const breakdown = entries.length > 0
|
|
223
|
+
? ` [${entries.map(([s, c]) => `${s}: ${c}`).join(", ")}]`
|
|
224
|
+
: "";
|
|
225
|
+
write(` ${table.padEnd(12)}${String(data.total).padStart(4)} ${verb}${breakdown}\n`);
|
|
226
|
+
}
|
|
227
|
+
const { missingTranscript, malformed, noCwdFound } = result.skipped;
|
|
228
|
+
const skipTotal = missingTranscript + malformed + noCwdFound;
|
|
229
|
+
if (skipTotal > 0) {
|
|
230
|
+
write(` skipped: ${skipTotal}` +
|
|
231
|
+
` (missing transcript: ${missingTranscript}, malformed: ${malformed}, no cwd found: ${noCwdFound})\n`);
|
|
232
|
+
}
|
|
233
|
+
else {
|
|
234
|
+
write(` skipped: 0\n`);
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
//# sourceMappingURL=scope-backfill.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-backfill.js","sourceRoot":"","sources":["../../src/cli/scope-backfill.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nlm scope coverage`: per-table and recall-weighted scope coverage fractions.
|
|
3
|
+
*
|
|
4
|
+
* READ-ONLY: opens the DB with { readonly: true }; never writes.
|
|
5
|
+
* No env flags consulted. No recall behavior change.
|
|
6
|
+
*/
|
|
7
|
+
export interface TableCoverage {
|
|
8
|
+
total: number;
|
|
9
|
+
stamped: number;
|
|
10
|
+
unstamped: number;
|
|
11
|
+
stamped_fraction: number;
|
|
12
|
+
byScope: Record<string, number>;
|
|
13
|
+
}
|
|
14
|
+
export interface OverallCoverage {
|
|
15
|
+
total: number;
|
|
16
|
+
stamped: number;
|
|
17
|
+
unstamped: number;
|
|
18
|
+
stamped_fraction: number;
|
|
19
|
+
}
|
|
20
|
+
export interface RecallWeightedStats {
|
|
21
|
+
distinctReturnedIds: number;
|
|
22
|
+
foundInDb: number;
|
|
23
|
+
scoped: number;
|
|
24
|
+
fraction: number;
|
|
25
|
+
}
|
|
26
|
+
export interface RecallWeightedCoverage extends RecallWeightedStats {
|
|
27
|
+
bySurface: Record<string, RecallWeightedStats>;
|
|
28
|
+
}
|
|
29
|
+
export interface CoverageResult {
|
|
30
|
+
sessions: TableCoverage;
|
|
31
|
+
facts: TableCoverage;
|
|
32
|
+
code_exemplars: TableCoverage;
|
|
33
|
+
signals: TableCoverage;
|
|
34
|
+
workstreams: TableCoverage;
|
|
35
|
+
overall: OverallCoverage;
|
|
36
|
+
recallWeighted: RecallWeightedCoverage | null;
|
|
37
|
+
queryLogNote: string | null;
|
|
38
|
+
}
|
|
39
|
+
export declare function runScopeCoverage(opts: {
|
|
40
|
+
dbPath: string;
|
|
41
|
+
queryLogPath?: string;
|
|
42
|
+
window?: number;
|
|
43
|
+
}): Promise<CoverageResult>;
|
|
44
|
+
export declare function formatCoverageResult(result: CoverageResult, write: (s: string) => void): void;
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `nlm scope coverage`: per-table and recall-weighted scope coverage fractions.
|
|
3
|
+
*
|
|
4
|
+
* READ-ONLY: opens the DB with { readonly: true }; never writes.
|
|
5
|
+
* No env flags consulted. No recall behavior change.
|
|
6
|
+
*/
|
|
7
|
+
import Database from "better-sqlite3";
|
|
8
|
+
import { existsSync } from "node:fs";
|
|
9
|
+
import { homedir } from "node:os";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { recentQueryLog } from "../core/recall/recent-log.js";
|
|
12
|
+
function overallOf(tables) {
|
|
13
|
+
let total = 0;
|
|
14
|
+
let stamped = 0;
|
|
15
|
+
for (const t of tables) {
|
|
16
|
+
total += t.total;
|
|
17
|
+
stamped += t.stamped;
|
|
18
|
+
}
|
|
19
|
+
return {
|
|
20
|
+
total,
|
|
21
|
+
stamped,
|
|
22
|
+
unstamped: total - stamped,
|
|
23
|
+
stamped_fraction: total === 0 ? 0 : stamped / total,
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
function tableStats(db, table) {
|
|
27
|
+
const agg = db
|
|
28
|
+
.prepare(`SELECT COUNT(*) AS total, SUM(CASE WHEN scope IS NOT NULL THEN 1 ELSE 0 END) AS scoped FROM "${table}"`)
|
|
29
|
+
.get();
|
|
30
|
+
const total = agg.total;
|
|
31
|
+
const scoped = agg.scoped ?? 0;
|
|
32
|
+
const rows = db
|
|
33
|
+
.prepare(`SELECT scope, COUNT(*) AS n FROM "${table}" WHERE scope IS NOT NULL GROUP BY scope`)
|
|
34
|
+
.all();
|
|
35
|
+
const byScope = {};
|
|
36
|
+
for (const { scope, n } of rows) {
|
|
37
|
+
byScope[scope] = n;
|
|
38
|
+
}
|
|
39
|
+
return {
|
|
40
|
+
total,
|
|
41
|
+
stamped: scoped,
|
|
42
|
+
unstamped: total - scoped,
|
|
43
|
+
stamped_fraction: total === 0 ? 0 : scoped / total,
|
|
44
|
+
byScope,
|
|
45
|
+
};
|
|
46
|
+
}
|
|
47
|
+
function defaultQueryLogPath() {
|
|
48
|
+
return process.env["NLM_QUERY_LOG"] ?? join(homedir(), ".nlm", "query_log.jsonl");
|
|
49
|
+
}
|
|
50
|
+
const CHUNK_SIZE = 999;
|
|
51
|
+
export async function runScopeCoverage(opts) {
|
|
52
|
+
const entryWindow = opts.window ?? 200;
|
|
53
|
+
if (!Number.isFinite(entryWindow) || entryWindow <= 0) {
|
|
54
|
+
throw new Error(`invalid --window: ${String(opts.window)} (expected a positive integer)`);
|
|
55
|
+
}
|
|
56
|
+
const db = new Database(opts.dbPath, { readonly: true });
|
|
57
|
+
try {
|
|
58
|
+
const sessions = tableStats(db, "sessions");
|
|
59
|
+
const facts = tableStats(db, "facts");
|
|
60
|
+
const code_exemplars = tableStats(db, "code_exemplars");
|
|
61
|
+
const signals = tableStats(db, "signals");
|
|
62
|
+
const workstreams = tableStats(db, "workstreams");
|
|
63
|
+
const overall = overallOf([sessions, facts, code_exemplars, signals, workstreams]);
|
|
64
|
+
const logPath = opts.queryLogPath ?? defaultQueryLogPath();
|
|
65
|
+
if (!existsSync(logPath)) {
|
|
66
|
+
return {
|
|
67
|
+
sessions,
|
|
68
|
+
facts,
|
|
69
|
+
code_exemplars,
|
|
70
|
+
signals,
|
|
71
|
+
workstreams,
|
|
72
|
+
overall,
|
|
73
|
+
recallWeighted: null,
|
|
74
|
+
queryLogNote: `query log not found at ${logPath}`,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
const entries = recentQueryLog(entryWindow, logPath);
|
|
78
|
+
const idSet = new Set();
|
|
79
|
+
const idsBySurface = new Map();
|
|
80
|
+
for (const entry of entries) {
|
|
81
|
+
let surfaceIds = idsBySurface.get(entry.source);
|
|
82
|
+
if (!surfaceIds) {
|
|
83
|
+
surfaceIds = new Set();
|
|
84
|
+
idsBySurface.set(entry.source, surfaceIds);
|
|
85
|
+
}
|
|
86
|
+
for (const id of entry.returnedIds) {
|
|
87
|
+
idSet.add(id);
|
|
88
|
+
surfaceIds.add(id);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (idSet.size === 0) {
|
|
92
|
+
return {
|
|
93
|
+
sessions,
|
|
94
|
+
facts,
|
|
95
|
+
code_exemplars,
|
|
96
|
+
signals,
|
|
97
|
+
workstreams,
|
|
98
|
+
overall,
|
|
99
|
+
recallWeighted: { distinctReturnedIds: 0, foundInDb: 0, scoped: 0, fraction: 0, bySurface: {} },
|
|
100
|
+
queryLogNote: null,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
// Recalled ids span the corpus tables (session recall returns session
|
|
104
|
+
// ids, fact recall fact ids, code recall exemplar ids); resolve each id
|
|
105
|
+
// to its scope across all three, first match wins.
|
|
106
|
+
const scopeById = new Map();
|
|
107
|
+
const ids = [...idSet];
|
|
108
|
+
for (const table of ["sessions", "facts", "code_exemplars"]) {
|
|
109
|
+
for (let i = 0; i < ids.length; i += CHUNK_SIZE) {
|
|
110
|
+
const chunk = ids.slice(i, i + CHUNK_SIZE).filter((id) => !scopeById.has(id));
|
|
111
|
+
if (chunk.length === 0)
|
|
112
|
+
continue;
|
|
113
|
+
const placeholders = chunk.map(() => "?").join(", ");
|
|
114
|
+
const rows = db
|
|
115
|
+
.prepare(`SELECT id, scope FROM "${table}" WHERE id IN (${placeholders})`)
|
|
116
|
+
.all(...chunk);
|
|
117
|
+
for (const row of rows) {
|
|
118
|
+
if (!scopeById.has(row.id))
|
|
119
|
+
scopeById.set(row.id, row.scope);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
const statsFor = (set) => {
|
|
124
|
+
let foundInDb = 0;
|
|
125
|
+
let scoped = 0;
|
|
126
|
+
for (const id of set) {
|
|
127
|
+
const scope = scopeById.get(id);
|
|
128
|
+
if (scope === undefined)
|
|
129
|
+
continue;
|
|
130
|
+
foundInDb++;
|
|
131
|
+
if (scope !== null)
|
|
132
|
+
scoped++;
|
|
133
|
+
}
|
|
134
|
+
return {
|
|
135
|
+
distinctReturnedIds: set.size,
|
|
136
|
+
foundInDb,
|
|
137
|
+
scoped,
|
|
138
|
+
fraction: foundInDb === 0 ? 0 : scoped / foundInDb,
|
|
139
|
+
};
|
|
140
|
+
};
|
|
141
|
+
const bySurface = {};
|
|
142
|
+
for (const [source, surfaceIds] of idsBySurface) {
|
|
143
|
+
if (surfaceIds.size > 0)
|
|
144
|
+
bySurface[source] = statsFor(surfaceIds);
|
|
145
|
+
}
|
|
146
|
+
return {
|
|
147
|
+
sessions,
|
|
148
|
+
facts,
|
|
149
|
+
code_exemplars,
|
|
150
|
+
signals,
|
|
151
|
+
workstreams,
|
|
152
|
+
overall,
|
|
153
|
+
recallWeighted: { ...statsFor(idSet), bySurface },
|
|
154
|
+
queryLogNote: null,
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
finally {
|
|
158
|
+
db.close();
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
export function formatCoverageResult(result, write) {
|
|
162
|
+
write("scope coverage:\n\n");
|
|
163
|
+
write(" per-table:\n");
|
|
164
|
+
const tables = [
|
|
165
|
+
["sessions", result.sessions],
|
|
166
|
+
["facts", result.facts],
|
|
167
|
+
["code_exemplars", result.code_exemplars],
|
|
168
|
+
["signals", result.signals],
|
|
169
|
+
["workstreams", result.workstreams],
|
|
170
|
+
];
|
|
171
|
+
for (const [name, cov] of tables) {
|
|
172
|
+
const pct = `${(cov.stamped_fraction * 100).toFixed(1)}%`;
|
|
173
|
+
const counts = `${cov.stamped}/${cov.total} stamped (${pct})`;
|
|
174
|
+
const entries = Object.entries(cov.byScope);
|
|
175
|
+
const breakdown = entries.length > 0
|
|
176
|
+
? ` [${entries.map(([s, c]) => `${s}: ${c}`).join(", ")}]`
|
|
177
|
+
: "";
|
|
178
|
+
write(` ${name.padEnd(15)} ${counts}${breakdown}\n`);
|
|
179
|
+
}
|
|
180
|
+
const o = result.overall;
|
|
181
|
+
const overallPct = `${(o.stamped_fraction * 100).toFixed(1)}%`;
|
|
182
|
+
write(` ${"overall".padEnd(15)} ${o.stamped}/${o.total} stamped (${overallPct})\n`);
|
|
183
|
+
write("\n");
|
|
184
|
+
if (result.queryLogNote !== null) {
|
|
185
|
+
write(` recall-weighted: skipped -- ${result.queryLogNote}\n`);
|
|
186
|
+
}
|
|
187
|
+
else if (result.recallWeighted !== null) {
|
|
188
|
+
const rw = result.recallWeighted;
|
|
189
|
+
const pct = `${(rw.fraction * 100).toFixed(1)}%`;
|
|
190
|
+
write(` recall-weighted (recalled ids from last window):\n`);
|
|
191
|
+
write(` distinct ids: ${rw.distinctReturnedIds}\n`);
|
|
192
|
+
write(` found in db: ${rw.foundInDb}\n`);
|
|
193
|
+
write(` scoped: ${rw.scoped}\n`);
|
|
194
|
+
write(` fraction: ${pct}\n`);
|
|
195
|
+
const surfaces = Object.entries(rw.bySurface);
|
|
196
|
+
if (surfaces.length > 0) {
|
|
197
|
+
write(` per-surface:\n`);
|
|
198
|
+
for (const [source, s] of surfaces) {
|
|
199
|
+
const sPct = `${(s.fraction * 100).toFixed(1)}%`;
|
|
200
|
+
write(` ${source.padEnd(15)} ${s.scoped}/${s.foundInDb} scoped (${sPct}, ${s.distinctReturnedIds} ids)\n`);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
//# sourceMappingURL=scope-coverage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scope-coverage.js","sourceRoot":"","sources":["../../src/cli/scope-coverage.ts"],"names":[],"mappings":"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"}
|
|
@@ -5,38 +5,52 @@
|
|
|
5
5
|
* at read time without mutating the underlying store.
|
|
6
6
|
*
|
|
7
7
|
* Shared by buildDataset (UI projection) and SqliteSessionStore (recall
|
|
8
|
-
* path), so the same overlay drives both surfaces. Append-only
|
|
8
|
+
* path), so the same overlay drives both surfaces. Append-only; every
|
|
9
9
|
* mutation lives as a row in `actions`.
|
|
10
10
|
*/
|
|
11
11
|
import type Database from "better-sqlite3";
|
|
12
|
+
import type { Pool } from "pg";
|
|
12
13
|
export interface ActionOverlay {
|
|
13
14
|
readonly dismissedAlerts: Set<string>;
|
|
14
15
|
readonly snoozedAlerts: Map<string, string>;
|
|
15
16
|
readonly retiredEntities: Set<string>;
|
|
16
17
|
readonly snoozedEntities: Map<string, string>;
|
|
17
18
|
readonly labeledEntities: Map<string, string>;
|
|
18
|
-
/** entity canonical
|
|
19
|
+
/** entity canonical -> new display label. Storage canonical is untouched;
|
|
19
20
|
* legacy-name recall still resolves because sessions stay tagged with
|
|
20
21
|
* the original canonical. Last non-reverted rename per subject wins. */
|
|
21
22
|
readonly renamedEntities: Map<string, string>;
|
|
22
23
|
/** open-question ids resolved without becoming decisions */
|
|
23
24
|
readonly resolvedOpens: Set<string>;
|
|
24
|
-
/** open-question id
|
|
25
|
+
/** open-question id -> resolution text (becomes a decision at projection time) */
|
|
25
26
|
readonly promotedOpens: Map<string, string>;
|
|
26
27
|
/** decision ids hidden from the projection (the underlying session body keeps the original line). */
|
|
27
28
|
readonly dismissedDecisions: Set<string>;
|
|
28
|
-
/** decision id
|
|
29
|
+
/** decision id -> corrected text shown in place of the original. */
|
|
29
30
|
readonly revisedDecisions: Map<string, string>;
|
|
30
|
-
/** entity canonical
|
|
31
|
+
/** entity canonical -> user-asserted coherence bucket. Overrides the
|
|
31
32
|
* computed (session_count + age) classification at projection time;
|
|
32
33
|
* last non-reverted write wins. */
|
|
33
34
|
readonly coherenceOverrides: Map<string, "active" | "sparse" | "stale">;
|
|
34
|
-
/** source canonical
|
|
35
|
+
/** source canonical -> target canonical. Source is hidden at projection
|
|
35
36
|
* time (treated as retired); target absorbs the source's session count. */
|
|
36
37
|
readonly mergedEntities: Map<string, string>;
|
|
37
38
|
}
|
|
39
|
+
export interface ActionRow {
|
|
40
|
+
kind: string;
|
|
41
|
+
subject_type: string;
|
|
42
|
+
subject_id: string;
|
|
43
|
+
payload: string | null;
|
|
44
|
+
}
|
|
38
45
|
export declare const EMPTY_OVERLAY: ActionOverlay;
|
|
46
|
+
/**
|
|
47
|
+
* Pure reducer: folds a sequence of action rows (ordered by id, reverted rows
|
|
48
|
+
* excluded by caller) into an ActionOverlay. Used by both the SQLite and PG
|
|
49
|
+
* loaders so the projection logic is shared and not duplicated per backend.
|
|
50
|
+
*/
|
|
51
|
+
export declare function reduceActionRows(rows: ReadonlyArray<ActionRow>): ActionOverlay;
|
|
39
52
|
export declare function loadActionOverlay(db: Database.Database): ActionOverlay;
|
|
53
|
+
export declare function loadActionOverlayPg(pool: Pool): Promise<ActionOverlay>;
|
|
40
54
|
/**
|
|
41
55
|
* Stable id for an open question: `${sessionId}::${hash12(text)}`. Both
|
|
42
56
|
* sides (overlay creators and consumers) compute it the same way so action
|
|
@@ -5,7 +5,7 @@
|
|
|
5
5
|
* at read time without mutating the underlying store.
|
|
6
6
|
*
|
|
7
7
|
* Shared by buildDataset (UI projection) and SqliteSessionStore (recall
|
|
8
|
-
* path), so the same overlay drives both surfaces. Append-only
|
|
8
|
+
* path), so the same overlay drives both surfaces. Append-only; every
|
|
9
9
|
* mutation lives as a row in `actions`.
|
|
10
10
|
*/
|
|
11
11
|
export const EMPTY_OVERLAY = {
|
|
@@ -22,12 +22,12 @@ export const EMPTY_OVERLAY = {
|
|
|
22
22
|
coherenceOverrides: new Map(),
|
|
23
23
|
mergedEntities: new Map(),
|
|
24
24
|
};
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
25
|
+
/**
|
|
26
|
+
* Pure reducer: folds a sequence of action rows (ordered by id, reverted rows
|
|
27
|
+
* excluded by caller) into an ActionOverlay. Used by both the SQLite and PG
|
|
28
|
+
* loaders so the projection logic is shared and not duplicated per backend.
|
|
29
|
+
*/
|
|
30
|
+
export function reduceActionRows(rows) {
|
|
31
31
|
const overlay = {
|
|
32
32
|
dismissedAlerts: new Set(),
|
|
33
33
|
snoozedAlerts: new Map(),
|
|
@@ -42,16 +42,6 @@ export function loadActionOverlay(db) {
|
|
|
42
42
|
coherenceOverrides: new Map(),
|
|
43
43
|
mergedEntities: new Map(),
|
|
44
44
|
};
|
|
45
|
-
// ORDER BY id keeps reducer deterministic: later writes overwrite earlier
|
|
46
|
-
// ones, so the latest non-reverted rename per subject wins.
|
|
47
|
-
const rows = db
|
|
48
|
-
.prepare(`
|
|
49
|
-
SELECT kind, subject_type, subject_id, payload
|
|
50
|
-
FROM actions
|
|
51
|
-
WHERE reverted_by IS NULL
|
|
52
|
-
ORDER BY id
|
|
53
|
-
`)
|
|
54
|
-
.all();
|
|
55
45
|
const now = new Date().toISOString();
|
|
56
46
|
for (const r of rows) {
|
|
57
47
|
const payload = r.payload ? safeParse(r.payload) : null;
|
|
@@ -114,13 +104,37 @@ export function loadActionOverlay(db) {
|
|
|
114
104
|
overlay.coherenceOverrides.set(r.subject_id, state);
|
|
115
105
|
}
|
|
116
106
|
else {
|
|
117
|
-
// Empty payload reverts to the computed bucket.
|
|
118
107
|
overlay.coherenceOverrides.delete(r.subject_id);
|
|
119
108
|
}
|
|
120
109
|
}
|
|
121
110
|
}
|
|
122
111
|
return overlay;
|
|
123
112
|
}
|
|
113
|
+
export function loadActionOverlay(db) {
|
|
114
|
+
const hasActions = db
|
|
115
|
+
.prepare("SELECT name FROM sqlite_master WHERE type='table' AND name='actions'")
|
|
116
|
+
.get();
|
|
117
|
+
if (!hasActions)
|
|
118
|
+
return EMPTY_OVERLAY;
|
|
119
|
+
// ORDER BY id keeps reducer deterministic: later writes overwrite earlier
|
|
120
|
+
// ones, so the latest non-reverted rename per subject wins.
|
|
121
|
+
const rows = db
|
|
122
|
+
.prepare(`
|
|
123
|
+
SELECT kind, subject_type, subject_id, payload
|
|
124
|
+
FROM actions
|
|
125
|
+
WHERE reverted_by IS NULL
|
|
126
|
+
ORDER BY id
|
|
127
|
+
`)
|
|
128
|
+
.all();
|
|
129
|
+
return reduceActionRows(rows);
|
|
130
|
+
}
|
|
131
|
+
export async function loadActionOverlayPg(pool) {
|
|
132
|
+
const result = await pool.query(`SELECT kind, subject_type, subject_id, payload
|
|
133
|
+
FROM actions
|
|
134
|
+
WHERE reverted_by IS NULL
|
|
135
|
+
ORDER BY id`);
|
|
136
|
+
return reduceActionRows(result.rows);
|
|
137
|
+
}
|
|
124
138
|
/**
|
|
125
139
|
* Stable id for an open question: `${sessionId}::${hash12(text)}`. Both
|
|
126
140
|
* sides (overlay creators and consumers) compute it the same way so action
|