nlm-memory 0.20.1 → 0.21.12
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 +69 -12
- package/assets/replay-eval-dark.svg +26 -0
- package/assets/replay-eval-light.svg +26 -0
- package/dist/cli/digest.js +69 -4
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/nlm.d.ts +14 -0
- package/dist/cli/nlm.js +556 -71
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/reprocess-job-adapters.d.ts +35 -0
- package/dist/cli/reprocess-job-adapters.js +80 -0
- package/dist/cli/reprocess-job-adapters.js.map +1 -0
- 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 +208 -0
- package/dist/cli/scope-coverage.js.map +1 -0
- package/dist/cli/supersede.js +8 -7
- package/dist/cli/supersede.js.map +1 -1
- package/dist/core/actions/actions-log.d.ts +65 -8
- package/dist/core/actions/actions-log.js +134 -17
- package/dist/core/actions/actions-log.js.map +1 -1
- package/dist/core/actions/overlay.d.ts +11 -2
- package/dist/core/actions/overlay.js +18 -6
- 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 +30 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/adapters/from-source.js +11 -3
- package/dist/core/adapters/from-source.js.map +1 -1
- package/dist/core/adapters/fs-wiki-writer.d.ts +44 -0
- package/dist/core/adapters/fs-wiki-writer.js +132 -0
- package/dist/core/adapters/fs-wiki-writer.js.map +1 -0
- package/dist/core/adapters/hermes-agent.d.ts +15 -2
- package/dist/core/adapters/hermes-agent.js +57 -11
- package/dist/core/adapters/hermes-agent.js.map +1 -1
- package/dist/core/adapters/memory-wiki-writer.d.ts +8 -0
- package/dist/core/adapters/memory-wiki-writer.js +16 -0
- package/dist/core/adapters/memory-wiki-writer.js.map +1 -0
- package/dist/core/adapters/muse.d.ts +51 -0
- package/dist/core/adapters/muse.js +271 -0
- package/dist/core/adapters/muse.js.map +1 -0
- package/dist/core/adapters/opencode.d.ts +11 -4
- package/dist/core/adapters/opencode.js +41 -7
- package/dist/core/adapters/opencode.js.map +1 -1
- package/dist/core/alerts/alert-state.d.ts +17 -0
- package/dist/core/alerts/alert-state.js +45 -0
- package/dist/core/alerts/alert-state.js.map +1 -0
- package/dist/core/alerts/check-and-alert.d.ts +28 -0
- package/dist/core/alerts/check-and-alert.js +53 -0
- package/dist/core/alerts/check-and-alert.js.map +1 -0
- package/dist/core/alerts/drift-transition.d.ts +27 -0
- package/dist/core/alerts/drift-transition.js +56 -0
- package/dist/core/alerts/drift-transition.js.map +1 -0
- package/dist/core/alerts/embedder-transition.d.ts +23 -0
- package/dist/core/alerts/embedder-transition.js +40 -0
- package/dist/core/alerts/embedder-transition.js.map +1 -0
- package/dist/core/alerts/fire-alert.d.ts +24 -0
- package/dist/core/alerts/fire-alert.js +72 -0
- package/dist/core/alerts/fire-alert.js.map +1 -0
- package/dist/core/alerts/job-alert.d.ts +12 -0
- package/dist/core/alerts/job-alert.js +37 -0
- package/dist/core/alerts/job-alert.js.map +1 -0
- package/dist/core/alerts/types.d.ts +104 -0
- package/dist/core/alerts/types.js +11 -0
- package/dist/core/alerts/types.js.map +1 -0
- package/dist/core/alerts/wiki-alert.d.ts +15 -0
- package/dist/core/alerts/wiki-alert.js +31 -0
- package/dist/core/alerts/wiki-alert.js.map +1 -0
- package/dist/core/classifier/prompt.d.ts +13 -0
- package/dist/core/classifier/prompt.js +52 -2
- package/dist/core/classifier/prompt.js.map +1 -1
- package/dist/core/dataset/build-dataset.d.ts +16 -1
- package/dist/core/dataset/build-dataset.js +46 -13
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +11 -3
- package/dist/core/digest/compose.js +70 -17
- 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 +87 -0
- package/dist/core/digest/hook-injection.js.map +1 -0
- package/dist/core/digest/hook-version-parity.d.ts +31 -0
- package/dist/core/digest/hook-version-parity.js +56 -0
- package/dist/core/digest/hook-version-parity.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.js +1 -1
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -1
- package/dist/core/exemplars/capture-from-session.d.ts +2 -1
- package/dist/core/exemplars/capture-from-session.js +4 -4
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/embed-backfill.d.ts +9 -0
- package/dist/core/exemplars/embed-backfill.js +9 -1
- package/dist/core/exemplars/embed-backfill.js.map +1 -1
- package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
- package/dist/core/exemplars/extract-exemplar.js +7 -1
- 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.d.ts +1 -1
- package/dist/core/exemplars/recall-code.js +2 -2
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/facts/backfill-facts.d.ts +1 -1
- package/dist/core/facts/backfill-facts.js +4 -4
- package/dist/core/facts/backfill-facts.js.map +1 -1
- package/dist/core/facts/embed-backfill.d.ts +54 -0
- package/dist/core/facts/embed-backfill.js +109 -0
- package/dist/core/facts/embed-backfill.js.map +1 -0
- package/dist/core/facts/reconcile-facts.d.ts +42 -0
- package/dist/core/facts/reconcile-facts.js +133 -0
- package/dist/core/facts/reconcile-facts.js.map +1 -0
- package/dist/core/health/embed-failure-state.d.ts +4 -0
- package/dist/core/health/embed-failure-state.js +12 -0
- package/dist/core/health/embed-failure-state.js.map +1 -0
- package/dist/core/health/warmup-retry.d.ts +27 -0
- package/dist/core/health/warmup-retry.js +53 -0
- package/dist/core/health/warmup-retry.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +15 -0
- package/dist/core/health/warmup-state.js +15 -1
- package/dist/core/health/warmup-state.js.map +1 -1
- package/dist/core/hook/cite-memo.d.ts +11 -7
- package/dist/core/hook/cite-memo.js +25 -17
- package/dist/core/hook/cite-memo.js.map +1 -1
- 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/hook-log.d.ts +13 -2
- package/dist/core/hook/hook-log.js +16 -8
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +10 -6
- package/dist/core/hook/memo.js +25 -17
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +8 -1
- package/dist/core/hook/pointer-block.js +17 -4
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +6 -5
- package/dist/core/hook/resolve-conversation-by-query.js +24 -12
- package/dist/core/hook/resolve-conversation-by-query.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 +1 -1
- package/dist/core/ingest/ingest-session.js +23 -3
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +1 -1
- package/dist/core/ingest/reclassify-oversized.js +8 -2
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +1 -1
- package/dist/core/ingest/reprocess.js +7 -2
- package/dist/core/ingest/reprocess.js.map +1 -1
- 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/jobs/job-supervisor.d.ts +168 -0
- package/dist/core/jobs/job-supervisor.js +335 -0
- package/dist/core/jobs/job-supervisor.js.map +1 -0
- package/dist/core/learner/model.d.ts +63 -0
- package/dist/core/learner/model.js +30 -0
- package/dist/core/learner/model.js.map +1 -0
- package/dist/core/learner/service.d.ts +42 -0
- package/dist/core/learner/service.js +74 -0
- package/dist/core/learner/service.js.map +1 -0
- package/dist/core/learner/summary.d.ts +28 -0
- package/dist/core/learner/summary.js +70 -0
- package/dist/core/learner/summary.js.map +1 -0
- package/dist/core/learner/validate.d.ts +18 -0
- package/dist/core/learner/validate.js +95 -0
- package/dist/core/learner/validate.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +31 -2
- package/dist/core/metrics/re-derivation.js +36 -4
- package/dist/core/metrics/re-derivation.js.map +1 -1
- 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/providers/provider-registry.d.ts +40 -23
- package/dist/core/providers/provider-registry.js +99 -81
- package/dist/core/providers/provider-registry.js.map +1 -1
- package/dist/core/recall/citation-log.d.ts +10 -5
- package/dist/core/recall/citation-log.js +21 -10
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +7 -4
- package/dist/core/recall/hook-recall-log.js +14 -8
- package/dist/core/recall/hook-recall-log.js.map +1 -1
- package/dist/core/recall/miss-log.d.ts +7 -4
- package/dist/core/recall/miss-log.js +18 -11
- package/dist/core/recall/miss-log.js.map +1 -1
- package/dist/core/recall/query-log.d.ts +8 -5
- package/dist/core/recall/query-log.js +16 -9
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +10 -1
- package/dist/core/recall/recall-service.js +31 -12
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/recent-log.d.ts +6 -1
- package/dist/core/recall/recent-log.js +13 -5
- package/dist/core/recall/recent-log.js.map +1 -1
- package/dist/core/recall/related-concepts.d.ts +29 -0
- package/dist/core/recall/related-concepts.js +67 -0
- package/dist/core/recall/related-concepts.js.map +1 -0
- package/dist/core/recall/related-exemplars.d.ts +1 -1
- package/dist/core/recall/related-exemplars.js +2 -2
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.d.ts +1 -1
- package/dist/core/recall/related-facts.js +3 -3
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +8 -4
- package/dist/core/recall-facts/fact-query-log.js +16 -8
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +2 -2
- package/dist/core/recall-facts/fact-recall-service.js +13 -12
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.js +15 -12
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +3 -0
- package/dist/core/scheduler/scheduler.js +45 -10
- 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 +1 -0
- package/dist/core/signals/code-signal.js +1 -0
- package/dist/core/signals/code-signal.js.map +1 -1
- package/dist/core/signals/failure-mode-recall.d.ts +1 -1
- package/dist/core/signals/failure-mode-recall.js +2 -2
- package/dist/core/signals/failure-mode-recall.js.map +1 -1
- 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/sources/source-registry.d.ts +49 -28
- package/dist/core/sources/source-registry.js +113 -70
- package/dist/core/sources/source-registry.js.map +1 -1
- package/dist/core/storage/pg-code-exemplar-store.d.ts +19 -10
- package/dist/core/storage/pg-code-exemplar-store.js +62 -27
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-entity-store.d.ts +6 -1
- package/dist/core/storage/pg-entity-store.js +33 -18
- package/dist/core/storage/pg-entity-store.js.map +1 -1
- package/dist/core/storage/pg-fact-ingest.d.ts +1 -1
- package/dist/core/storage/pg-fact-ingest.js +10 -7
- package/dist/core/storage/pg-fact-ingest.js.map +1 -1
- package/dist/core/storage/pg-fact-store.d.ts +29 -17
- package/dist/core/storage/pg-fact-store.js +99 -46
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-learner-store.d.ts +27 -0
- package/dist/core/storage/pg-learner-store.js +174 -0
- package/dist/core/storage/pg-learner-store.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +25 -21
- package/dist/core/storage/pg-session-store.js +186 -114
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.d.ts +10 -5
- package/dist/core/storage/pg-signal-store.js +26 -13
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +4 -0
- package/dist/core/storage/pg-storage.js +6 -0
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +17 -11
- package/dist/core/storage/pg-workstream-store.js +47 -29
- package/dist/core/storage/pg-workstream-store.js.map +1 -1
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +24 -10
- package/dist/core/storage/sqlite-code-exemplar-store.js +86 -40
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-entity-store.d.ts +8 -1
- package/dist/core/storage/sqlite-entity-store.js +46 -27
- package/dist/core/storage/sqlite-entity-store.js.map +1 -1
- package/dist/core/storage/sqlite-fact-store.d.ts +45 -19
- package/dist/core/storage/sqlite-fact-store.js +175 -64
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-learner-store.d.ts +33 -0
- package/dist/core/storage/sqlite-learner-store.js +178 -0
- package/dist/core/storage/sqlite-learner-store.js.map +1 -0
- package/dist/core/storage/sqlite-outcome-store.d.ts +104 -0
- package/dist/core/storage/sqlite-outcome-store.js +211 -0
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
- package/dist/core/storage/sqlite-session-store.d.ts +50 -21
- package/dist/core/storage/sqlite-session-store.js +233 -149
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.d.ts +12 -5
- package/dist/core/storage/sqlite-signal-store.js +29 -15
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +4 -0
- package/dist/core/storage/sqlite-storage.js +10 -2
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +17 -11
- package/dist/core/storage/sqlite-workstream-store.js +53 -31
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -1
- package/dist/core/storage/supersedence-log.d.ts +10 -7
- package/dist/core/storage/supersedence-log.js +21 -14
- 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/tenancy/default-team.d.ts +6 -0
- package/dist/core/tenancy/default-team.js +7 -0
- package/dist/core/tenancy/default-team.js.map +1 -0
- package/dist/core/tenancy/hosted-mode.d.ts +9 -0
- package/dist/core/tenancy/hosted-mode.js +12 -0
- package/dist/core/tenancy/hosted-mode.js.map +1 -0
- package/dist/core/tenancy/team-auth.d.ts +16 -0
- package/dist/core/tenancy/team-auth.js +22 -0
- package/dist/core/tenancy/team-auth.js.map +1 -0
- package/dist/core/tenancy/team-token-store.d.ts +45 -0
- package/dist/core/tenancy/team-token-store.js +52 -0
- package/dist/core/tenancy/team-token-store.js.map +1 -0
- package/dist/core/tenancy/tenant-clause.d.ts +37 -0
- package/dist/core/tenancy/tenant-clause.js +11 -0
- package/dist/core/tenancy/tenant-clause.js.map +1 -0
- package/dist/core/tenancy/tenant-state-path.d.ts +28 -0
- package/dist/core/tenancy/tenant-state-path.js +49 -0
- package/dist/core/tenancy/tenant-state-path.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/wiki/project.d.ts +17 -0
- package/dist/core/wiki/project.js +37 -0
- package/dist/core/wiki/project.js.map +1 -0
- package/dist/core/wiki/reconcile.d.ts +15 -0
- package/dist/core/wiki/reconcile.js +14 -0
- package/dist/core/wiki/reconcile.js.map +1 -0
- package/dist/core/wiki/render.d.ts +5 -0
- package/dist/core/wiki/render.js +84 -0
- package/dist/core/wiki/render.js.map +1 -0
- package/dist/core/wiki/rollup.d.ts +28 -0
- package/dist/core/wiki/rollup.js +91 -0
- package/dist/core/wiki/rollup.js.map +1 -0
- package/dist/core/wiki/select.d.ts +8 -0
- package/dist/core/wiki/select.js +7 -0
- package/dist/core/wiki/select.js.map +1 -0
- package/dist/core/wiki/slug.d.ts +36 -0
- package/dist/core/wiki/slug.js +71 -0
- package/dist/core/wiki/slug.js.map +1 -0
- package/dist/core/wiki/types.d.ts +37 -0
- package/dist/core/wiki/types.js +2 -0
- package/dist/core/wiki/types.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +1 -1
- package/dist/core/work-digest/build-work-digest.js +3 -3
- package/dist/core/work-digest/build-work-digest.js.map +1 -1
- package/dist/core/workstream/bind.d.ts +3 -2
- package/dist/core/workstream/bind.js +29 -10
- package/dist/core/workstream/bind.js.map +1 -1
- package/dist/core/workstream/model.d.ts +1 -0
- package/dist/core/workstream/model.js.map +1 -1
- package/dist/core/workstream/rollup.d.ts +1 -1
- package/dist/core/workstream/rollup.js +6 -6
- package/dist/core/workstream/rollup.js.map +1 -1
- package/dist/hook/hook-helpers.d.ts +14 -0
- package/dist/hook/hook-helpers.js +29 -2
- package/dist/hook/hook-helpers.js.map +1 -1
- package/dist/hook/pre-compact-hook.js +8 -5
- package/dist/hook/pre-compact-hook.js.map +1 -1
- package/dist/hook/prompt-recall-hook.d.ts +7 -3
- package/dist/hook/prompt-recall-hook.js +35 -20
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-over-http.d.ts +28 -3
- package/dist/hook/recall-over-http.js +58 -12
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/session-end-hook.js +7 -5
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.d.ts +14 -1
- package/dist/hook/session-start-hook.js +57 -16
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +11 -8
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +47 -3
- package/dist/http/app.js +379 -132
- package/dist/http/app.js.map +1 -1
- package/dist/install/claude-code.d.ts +17 -0
- package/dist/install/claude-code.js +44 -5
- package/dist/install/claude-code.js.map +1 -1
- package/dist/install/codex.d.ts +23 -2
- package/dist/install/codex.js +111 -14
- package/dist/install/codex.js.map +1 -1
- package/dist/install/cursor.d.ts +2 -2
- package/dist/install/cursor.js +7 -7
- package/dist/install/cursor.js.map +1 -1
- package/dist/install/hermes.d.ts +8 -0
- package/dist/install/hermes.js +28 -5
- package/dist/install/hermes.js.map +1 -1
- package/dist/install/local-source.d.ts +20 -0
- package/dist/install/local-source.js +28 -0
- package/dist/install/local-source.js.map +1 -0
- package/dist/install/mcp-block.d.ts +77 -0
- package/dist/install/mcp-block.js +99 -0
- package/dist/install/mcp-block.js.map +1 -0
- package/dist/install/pi.d.ts +26 -0
- package/dist/install/pi.js +43 -0
- package/dist/install/pi.js.map +1 -1
- package/dist/install/setup.js +6 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/install/windsurf.d.ts +2 -2
- package/dist/install/windsurf.js +7 -7
- package/dist/install/windsurf.js.map +1 -1
- package/dist/llm/classifier-box.d.ts +5 -0
- package/dist/llm/classifier-box.js +5 -0
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/mcp/server.d.ts +94 -15
- package/dist/mcp/server.js +402 -79
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/clock.d.ts +12 -0
- package/dist/ports/clock.js +10 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/code-exemplar-store.d.ts +13 -13
- package/dist/ports/entity-store.d.ts +5 -1
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/learner-store.d.ts +80 -0
- package/dist/ports/learner-store.js +19 -0
- package/dist/ports/learner-store.js.map +1 -0
- 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 +20 -20
- package/dist/ports/session-store.js +5 -0
- package/dist/ports/session-store.js.map +1 -1
- package/dist/ports/signal-store.d.ts +12 -8
- package/dist/ports/spawn-child.d.ts +14 -0
- package/dist/ports/spawn-child.js +10 -0
- package/dist/ports/spawn-child.js.map +1 -0
- package/dist/ports/storage.d.ts +6 -0
- package/dist/ports/transcript-adapter.d.ts +11 -0
- package/dist/ports/wiki-writer.d.ts +19 -0
- package/dist/ports/wiki-writer.js +12 -0
- package/dist/ports/wiki-writer.js.map +1 -0
- package/dist/ports/workstream-store.d.ts +20 -12
- 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 +55 -0
- package/dist/shared/types.js +4 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/shared/version.d.ts +9 -0
- package/dist/shared/version.js +11 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/ui/assets/index-D6F3xAis.js +11 -0
- package/dist/ui/index.html +1 -1
- package/migrations/029_project_scope.sql +21 -0
- package/migrations/032_session_derivables.sql +11 -0
- package/migrations/033_actions_kind_check.sql +58 -0
- package/migrations/034_tenancy_teams_and_stamps.sql +40 -0
- package/migrations/035_tenancy_entity_rekey.sql +75 -0
- package/migrations/036_tenant_name_uniqueness.sql +59 -0
- package/migrations/037_sessions_covering_index.sql +25 -0
- package/migrations/038_sources_muse.sql +33 -0
- package/migrations/039_learner_evidence.sql +51 -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/migrations/pg/033_actions_kind_check.sql +17 -0
- package/migrations/pg/034_tenancy.sql +77 -0
- package/migrations/pg/035_tenant_name_uniqueness.sql +15 -0
- package/migrations/pg/036_sources_muse.sql +12 -0
- package/migrations/pg/037_learner_evidence.sql +55 -0
- package/nlm/index.js +258 -59
- package/package.json +10 -5
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/scripts/prompt-recall-hook.mjs +256 -58
- package/plugin/scripts/session-start-hook.mjs +283 -55
- package/plugin/scripts/stop-hook.mjs +199 -38
- package/dist/hook/subagent-start-hook.d.ts +0 -28
- package/dist/hook/subagent-start-hook.js +0 -81
- package/dist/hook/subagent-start-hook.js.map +0 -1
- package/dist/ui/assets/index-CMpQkbQy.js +0 -11
|
@@ -9,13 +9,21 @@
|
|
|
9
9
|
* Embeddings live in code_exemplar_embeddings with ON DELETE CASCADE, so the
|
|
10
10
|
* prune/cap deletes here don't need separate vec bookkeeping (unlike the
|
|
11
11
|
* SQLite store, which deletes from code_exemplars_vec explicitly).
|
|
12
|
+
*
|
|
13
|
+
* Tenancy: mirrors SqliteCodeExemplarStore — every method takes `tenantId`
|
|
14
|
+
* as its non-optional first parameter and routes STAMP-table WHERE
|
|
15
|
+
* fragments through `tenantClausePg`. See that file's header comment for
|
|
16
|
+
* the vector-path rationale.
|
|
12
17
|
*/
|
|
13
18
|
import { exemplarId } from "./sqlite-code-exemplar-store.js";
|
|
19
|
+
import { tenantClausePg } from "../tenancy/tenant-clause.js";
|
|
14
20
|
const VEC_DIM = 768;
|
|
21
|
+
// Read column list stays scope-free while stamping is write-only (#348
|
|
22
|
+
// Stage A); reads gain scope in the enforcement task.
|
|
15
23
|
const COLUMNS = "id, install_scope, signal_id, session_id, repo, model, lang, " +
|
|
16
24
|
"task_context, code, code_hash, outcome, git_sha, survived, ts, created_at, " +
|
|
17
25
|
"retired_at, label_source";
|
|
18
|
-
function insertParams(input) {
|
|
26
|
+
function insertParams(input, tenantId) {
|
|
19
27
|
const id = exemplarId({
|
|
20
28
|
installScope: input.installScope,
|
|
21
29
|
repo: input.repo,
|
|
@@ -36,14 +44,16 @@ function insertParams(input) {
|
|
|
36
44
|
input.outcome,
|
|
37
45
|
input.gitSha,
|
|
38
46
|
input.survived,
|
|
47
|
+
input.scope,
|
|
39
48
|
input.ts,
|
|
49
|
+
tenantId,
|
|
40
50
|
];
|
|
41
51
|
}
|
|
42
52
|
const INSERT_SQL = `
|
|
43
53
|
INSERT INTO code_exemplars
|
|
44
54
|
(id, install_scope, signal_id, session_id, repo, model, lang,
|
|
45
|
-
task_context, code, code_hash, outcome, git_sha, survived, ts)
|
|
46
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14)
|
|
55
|
+
task_context, code, code_hash, outcome, git_sha, survived, scope, ts, tenant_id)
|
|
56
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16)
|
|
47
57
|
ON CONFLICT (id) DO NOTHING
|
|
48
58
|
`;
|
|
49
59
|
export class PgCodeExemplarStore {
|
|
@@ -51,12 +61,12 @@ export class PgCodeExemplarStore {
|
|
|
51
61
|
constructor(pool) {
|
|
52
62
|
this.pool = pool;
|
|
53
63
|
}
|
|
54
|
-
async insert(input) {
|
|
55
|
-
const params = insertParams(input);
|
|
64
|
+
async insert(tenantId, input) {
|
|
65
|
+
const params = insertParams(input, tenantId);
|
|
56
66
|
const res = await this.pool.query(INSERT_SQL, params);
|
|
57
67
|
return { id: params[0], skipped: res.rowCount === 0 };
|
|
58
68
|
}
|
|
59
|
-
async insertMany(inputs) {
|
|
69
|
+
async insertMany(tenantId, inputs) {
|
|
60
70
|
if (inputs.length === 0)
|
|
61
71
|
return 0;
|
|
62
72
|
const client = await this.pool.connect();
|
|
@@ -64,7 +74,7 @@ export class PgCodeExemplarStore {
|
|
|
64
74
|
try {
|
|
65
75
|
await client.query("BEGIN");
|
|
66
76
|
for (const input of inputs) {
|
|
67
|
-
const res = await client.query(INSERT_SQL, insertParams(input));
|
|
77
|
+
const res = await client.query(INSERT_SQL, insertParams(input, tenantId));
|
|
68
78
|
if (res.rowCount && res.rowCount > 0)
|
|
69
79
|
inserted++;
|
|
70
80
|
}
|
|
@@ -79,30 +89,46 @@ export class PgCodeExemplarStore {
|
|
|
79
89
|
}
|
|
80
90
|
return inserted;
|
|
81
91
|
}
|
|
82
|
-
|
|
92
|
+
/**
|
|
93
|
+
* No-op if exemplarId isn't owned by tenantId — writing an embedding for
|
|
94
|
+
* another tenant's exemplar must never fall through to a write.
|
|
95
|
+
*/
|
|
96
|
+
async upsertEmbedding(tenantId, exemplarId, vector) {
|
|
83
97
|
if (vector.length !== VEC_DIM) {
|
|
84
98
|
throw new Error(`code exemplar embeddings must be ${VEC_DIM}-dim (got ${vector.length})`);
|
|
85
99
|
}
|
|
100
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
101
|
+
const owned = await this.pool.query(`SELECT id FROM code_exemplars WHERE id = $1 AND ${tc.sql}`, [exemplarId, tc.param]);
|
|
102
|
+
if (owned.rows.length === 0)
|
|
103
|
+
return;
|
|
86
104
|
const vecStr = `[${Array.from(vector).join(",")}]`;
|
|
87
105
|
await this.pool.query(`INSERT INTO code_exemplar_embeddings (exemplar_id, embedding)
|
|
88
106
|
VALUES ($1, $2::vector)
|
|
89
107
|
ON CONFLICT (exemplar_id) DO UPDATE SET embedding = EXCLUDED.embedding`, [exemplarId, vecStr]);
|
|
90
108
|
}
|
|
91
|
-
async searchByVector(queryVector, filter) {
|
|
109
|
+
async searchByVector(tenantId, queryVector, filter) {
|
|
92
110
|
const k = Math.max(1, Math.min(50, filter.k ?? 5));
|
|
93
111
|
const includeNegatives = filter.includeNegatives ?? true;
|
|
94
112
|
const overFetch = k * 4;
|
|
95
113
|
const vecStr = `[${Array.from(queryVector).join(",")}]`;
|
|
96
114
|
// pgvector <-> is L2 distance; OllamaCodeEmbedder L2-normalises vectors,
|
|
97
115
|
// so this orders identically to cosine and matches the SQLite vec0 lane.
|
|
98
|
-
|
|
116
|
+
// Tenant filter applied in the id-resolution join against code_exemplars
|
|
117
|
+
// (program spec §4.3 vector-path rule) — code_exemplar_embeddings
|
|
118
|
+
// carries no tenant_id of its own.
|
|
119
|
+
const tc = tenantClausePg(tenantId, 3);
|
|
120
|
+
const res = await this.pool.query(`SELECT ${COLUMNS.split(", ").map((c) => `ce.${c}`).join(", ")}, ce.tenant_id,
|
|
99
121
|
e.embedding <-> $1::vector AS distance
|
|
100
122
|
FROM code_exemplar_embeddings e
|
|
101
123
|
JOIN code_exemplars ce ON ce.id = e.exemplar_id
|
|
102
|
-
WHERE ce.install_scope = $2 AND ce.retired_at IS NULL
|
|
124
|
+
WHERE ce.install_scope = $2 AND ce.retired_at IS NULL AND ${tc.sql}
|
|
103
125
|
ORDER BY e.embedding <-> $1::vector
|
|
104
|
-
LIMIT $
|
|
105
|
-
|
|
126
|
+
LIMIT $4`, [vecStr, filter.installScope, tc.param, overFetch]);
|
|
127
|
+
// Defense in depth (never a substitute for the SQL filter above): re-check
|
|
128
|
+
// each resolved row's own tenant, read into a local first so this JS
|
|
129
|
+
// comparison can never be mistaken by the tenant-guard scan for an
|
|
130
|
+
// inlined SQL WHERE fragment (that literal is reserved for tenant-clause.ts).
|
|
131
|
+
let hits = res.rows.filter((r) => { const rowTenant = r["tenant_id"]; return rowTenant === tenantId; }).map((r) => ({
|
|
106
132
|
id: r.id,
|
|
107
133
|
code: r.code,
|
|
108
134
|
taskContext: r.task_context,
|
|
@@ -132,21 +158,24 @@ export class PgCodeExemplarStore {
|
|
|
132
158
|
});
|
|
133
159
|
return hits.slice(0, k);
|
|
134
160
|
}
|
|
135
|
-
async getById(id) {
|
|
136
|
-
const
|
|
161
|
+
async getById(tenantId, id) {
|
|
162
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
163
|
+
const res = await this.pool.query(`SELECT ${COLUMNS} FROM code_exemplars WHERE id = $1 AND ${tc.sql}`, [id, tc.param]);
|
|
137
164
|
const row = res.rows[0];
|
|
138
165
|
return row ? this.rowToExemplar(row) : null;
|
|
139
166
|
}
|
|
140
|
-
async listBySessions(sessionIds) {
|
|
167
|
+
async listBySessions(tenantId, sessionIds) {
|
|
141
168
|
if (sessionIds.length === 0)
|
|
142
169
|
return [];
|
|
143
170
|
const ph = sessionIds.map((_, i) => `$${i + 1}`).join(",");
|
|
144
|
-
const
|
|
171
|
+
const tc = tenantClausePg(tenantId, sessionIds.length + 1);
|
|
172
|
+
const res = await this.pool.query(`SELECT ${COLUMNS} FROM code_exemplars WHERE session_id IN (${ph}) AND retired_at IS NULL AND ${tc.sql} ORDER BY ts ASC`, [...sessionIds, tc.param]);
|
|
145
173
|
return res.rows.map((r) => this.rowToExemplar(r));
|
|
146
174
|
}
|
|
147
|
-
async applyBucketCap(installScope, maxPerBucket) {
|
|
175
|
+
async applyBucketCap(tenantId, installScope, maxPerBucket) {
|
|
148
176
|
// Window-rank within each (repo, lang, outcome-class) bucket newest-first,
|
|
149
177
|
// delete everything past the cap. Cascade clears the embeddings.
|
|
178
|
+
const tc = tenantClausePg(tenantId, 3);
|
|
150
179
|
const res = await this.pool.query(`WITH ranked AS (
|
|
151
180
|
SELECT id, ROW_NUMBER() OVER (
|
|
152
181
|
PARTITION BY repo, lang,
|
|
@@ -154,18 +183,20 @@ export class PgCodeExemplarStore {
|
|
|
154
183
|
ORDER BY ts DESC
|
|
155
184
|
) AS rn
|
|
156
185
|
FROM code_exemplars
|
|
157
|
-
WHERE install_scope = $1
|
|
186
|
+
WHERE install_scope = $1 AND ${tc.sql}
|
|
158
187
|
)
|
|
159
188
|
DELETE FROM code_exemplars
|
|
160
|
-
WHERE id IN (SELECT id FROM ranked WHERE rn > $2)`, [installScope, maxPerBucket]);
|
|
189
|
+
WHERE id IN (SELECT id FROM ranked WHERE rn > $2)`, [installScope, maxPerBucket, tc.param]);
|
|
161
190
|
return res.rowCount ?? 0;
|
|
162
191
|
}
|
|
163
|
-
async pruneReverted(installScope) {
|
|
164
|
-
const
|
|
192
|
+
async pruneReverted(tenantId, installScope) {
|
|
193
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
194
|
+
const res = await this.pool.query(`DELETE FROM code_exemplars WHERE install_scope = $1 AND survived = 0 AND ${tc.sql}`, [installScope, tc.param]);
|
|
165
195
|
return res.rowCount ?? 0;
|
|
166
196
|
}
|
|
167
|
-
async setVerdict(id, patch, source) {
|
|
168
|
-
const
|
|
197
|
+
async setVerdict(tenantId, id, patch, source) {
|
|
198
|
+
const curTc = tenantClausePg(tenantId, 2);
|
|
199
|
+
const cur = await this.pool.query(`SELECT label_source FROM code_exemplars WHERE id = $1 AND ${curTc.sql}`, [id, curTc.param]);
|
|
169
200
|
if (cur.rows.length === 0)
|
|
170
201
|
return { status: "not_found" };
|
|
171
202
|
if (source === "llm" && cur.rows[0].label_source === "human")
|
|
@@ -184,11 +215,14 @@ export class PgCodeExemplarStore {
|
|
|
184
215
|
values.push(patch.outcome);
|
|
185
216
|
}
|
|
186
217
|
values.push(id);
|
|
187
|
-
|
|
218
|
+
const updateTc = tenantClausePg(tenantId, n + 1);
|
|
219
|
+
values.push(updateTc.param);
|
|
220
|
+
await this.pool.query(`UPDATE code_exemplars SET ${sets.join(", ")} WHERE id = $${n} AND ${updateTc.sql}`, values);
|
|
188
221
|
return { status: "applied" };
|
|
189
222
|
}
|
|
190
|
-
async pruneOlderThan(olderThanTs) {
|
|
191
|
-
const
|
|
223
|
+
async pruneOlderThan(tenantId, olderThanTs) {
|
|
224
|
+
const tc = tenantClausePg(tenantId, 2);
|
|
225
|
+
const res = await this.pool.query(`DELETE FROM code_exemplars WHERE ts < $1 AND ${tc.sql}`, [olderThanTs, tc.param]);
|
|
192
226
|
return res.rowCount ?? 0;
|
|
193
227
|
}
|
|
194
228
|
rowToExemplar(row) {
|
|
@@ -206,6 +240,7 @@ export class PgCodeExemplarStore {
|
|
|
206
240
|
outcome: row.outcome,
|
|
207
241
|
gitSha: row.git_sha,
|
|
208
242
|
survived: row.survived,
|
|
243
|
+
scope: row.scope ?? null,
|
|
209
244
|
ts: row.ts,
|
|
210
245
|
createdAt: row.created_at,
|
|
211
246
|
retiredAt: row.retired_at,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-code-exemplar-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-code-exemplar-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pg-code-exemplar-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-code-exemplar-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -2,11 +2,16 @@
|
|
|
2
2
|
* PgEntityStore -- EntityStore implementation over pg.Pool.
|
|
3
3
|
*
|
|
4
4
|
* All merge operations run inside a single pg transaction.
|
|
5
|
+
*
|
|
6
|
+
* Tenancy: mirrors SqliteEntityStore — merge takes tenantId as its
|
|
7
|
+
* non-optional first parameter and routes every STAMP-table WHERE fragment
|
|
8
|
+
* through tenantClausePg. entities/entity_variants carry a composite PK
|
|
9
|
+
* (tenant_id, canonical/variant).
|
|
5
10
|
*/
|
|
6
11
|
import type { Pool } from "pg";
|
|
7
12
|
import type { EntityStore } from "../../ports/entity-store.js";
|
|
8
13
|
export declare class PgEntityStore implements EntityStore {
|
|
9
14
|
private readonly pool;
|
|
10
15
|
constructor(pool: Pool);
|
|
11
|
-
merge(source: string, target: string): Promise<void>;
|
|
16
|
+
merge(tenantId: string, source: string, target: string): Promise<void>;
|
|
12
17
|
}
|
|
@@ -2,69 +2,84 @@
|
|
|
2
2
|
* PgEntityStore -- EntityStore implementation over pg.Pool.
|
|
3
3
|
*
|
|
4
4
|
* All merge operations run inside a single pg transaction.
|
|
5
|
+
*
|
|
6
|
+
* Tenancy: mirrors SqliteEntityStore — merge takes tenantId as its
|
|
7
|
+
* non-optional first parameter and routes every STAMP-table WHERE fragment
|
|
8
|
+
* through tenantClausePg. entities/entity_variants carry a composite PK
|
|
9
|
+
* (tenant_id, canonical/variant).
|
|
5
10
|
*/
|
|
11
|
+
import { tenantClausePg } from "../tenancy/tenant-clause.js";
|
|
6
12
|
export class PgEntityStore {
|
|
7
13
|
pool;
|
|
8
14
|
constructor(pool) {
|
|
9
15
|
this.pool = pool;
|
|
10
16
|
}
|
|
11
|
-
async merge(source, target) {
|
|
17
|
+
async merge(tenantId, source, target) {
|
|
12
18
|
const client = await this.pool.connect();
|
|
13
19
|
try {
|
|
14
20
|
await client.query("BEGIN");
|
|
15
|
-
const
|
|
21
|
+
const targetTc = tenantClausePg(tenantId, 2);
|
|
22
|
+
const targetRes = await client.query(`SELECT status FROM entities WHERE canonical = $1 AND ${targetTc.sql}`, [target, targetTc.param]);
|
|
16
23
|
if (targetRes.rowCount === 0) {
|
|
17
24
|
throw new Error(`merge: target entity not found: ${target}`);
|
|
18
25
|
}
|
|
19
26
|
if (targetRes.rows[0].status === "retired") {
|
|
20
27
|
throw new Error(`merge: target entity is retired: ${target}`);
|
|
21
28
|
}
|
|
22
|
-
const
|
|
29
|
+
const sourceTc = tenantClausePg(tenantId, 2);
|
|
30
|
+
const sourceRes = await client.query(`SELECT status FROM entities WHERE canonical = $1 AND ${sourceTc.sql}`, [source, sourceTc.param]);
|
|
23
31
|
if (sourceRes.rowCount === 0) {
|
|
24
32
|
throw new Error(`merge: source entity not found: ${source}`);
|
|
25
33
|
}
|
|
26
34
|
// Step 1: copy source session_entities to target, dedup on composite PK.
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
35
|
+
const copyTc = tenantClausePg(tenantId, 3);
|
|
36
|
+
await client.query(`INSERT INTO session_entities (tenant_id, session_id, entity_canonical)
|
|
37
|
+
SELECT $3, session_id, $1 FROM session_entities WHERE entity_canonical = $2 AND ${copyTc.sql}
|
|
38
|
+
ON CONFLICT DO NOTHING`, [target, source, copyTc.param]);
|
|
30
39
|
// Step 2: delete source's session_entities rows.
|
|
31
|
-
|
|
40
|
+
const deleteEntTc = tenantClausePg(tenantId, 2);
|
|
41
|
+
await client.query(`DELETE FROM session_entities WHERE entity_canonical = $1 AND ${deleteEntTc.sql}`, [source, deleteEntTc.param]);
|
|
32
42
|
// Step 3: recompute target.session_count exactly from session_entities.
|
|
43
|
+
const countTc = tenantClausePg(tenantId, 2);
|
|
33
44
|
await client.query(`UPDATE entities
|
|
34
|
-
SET session_count = (SELECT COUNT(*) FROM session_entities WHERE entity_canonical = $1),
|
|
45
|
+
SET session_count = (SELECT COUNT(*) FROM session_entities WHERE entity_canonical = $1 AND ${countTc.sql}),
|
|
35
46
|
updated_at = NOW()
|
|
36
|
-
WHERE canonical = $1`, [target]);
|
|
47
|
+
WHERE canonical = $1 AND ${countTc.sql}`, [target, countTc.param]);
|
|
37
48
|
// Step 4: widen first_seen_session / last_seen_session.
|
|
38
49
|
// first_seen and last_seen are session IDs (text FK to sessions.id).
|
|
39
50
|
// Join to sessions to order by started_at and pick earliest / latest.
|
|
51
|
+
const seenTc = tenantClausePg(tenantId, 2);
|
|
40
52
|
const seenRes = await client.query(`SELECT id, started_at FROM sessions
|
|
41
53
|
WHERE id IN (
|
|
42
|
-
SELECT first_seen_session FROM entities WHERE canonical = ANY($1)
|
|
54
|
+
SELECT first_seen_session FROM entities WHERE canonical = ANY($1) AND ${seenTc.sql}
|
|
43
55
|
UNION
|
|
44
|
-
SELECT last_seen_session FROM entities WHERE canonical = ANY($1)
|
|
45
|
-
)`, [[source, target]]);
|
|
56
|
+
SELECT last_seen_session FROM entities WHERE canonical = ANY($1) AND ${seenTc.sql}
|
|
57
|
+
)`, [[source, target], seenTc.param]);
|
|
46
58
|
if (seenRes.rows.length > 0) {
|
|
47
59
|
const sorted = seenRes.rows.slice().sort((a, b) => a.started_at.localeCompare(b.started_at));
|
|
48
60
|
const earliest = sorted[0].id;
|
|
49
61
|
const latest = sorted[sorted.length - 1].id;
|
|
62
|
+
const widenTc = tenantClausePg(tenantId, 4);
|
|
50
63
|
await client.query(`UPDATE entities
|
|
51
64
|
SET first_seen_session = $1,
|
|
52
65
|
last_seen_session = $2,
|
|
53
66
|
updated_at = NOW()
|
|
54
|
-
WHERE canonical = $3`, [earliest, latest, target]);
|
|
67
|
+
WHERE canonical = $3 AND ${widenTc.sql}`, [earliest, latest, target, widenTc.param]);
|
|
55
68
|
}
|
|
56
69
|
// Step 5: insert the variant record so future ingest resolves source -> target.
|
|
57
|
-
await client.query(`INSERT INTO entity_variants (variant, canonical, source_session_id)
|
|
58
|
-
VALUES ($1, $2, NULL)
|
|
59
|
-
ON CONFLICT DO NOTHING`, [source, target]);
|
|
70
|
+
await client.query(`INSERT INTO entity_variants (tenant_id, variant, canonical, source_session_id)
|
|
71
|
+
VALUES ($1, $2, $3, NULL)
|
|
72
|
+
ON CONFLICT DO NOTHING`, [tenantId, source, target]);
|
|
60
73
|
// Step 6: re-point existing variants of source to target.
|
|
61
|
-
|
|
74
|
+
const repointTc = tenantClausePg(tenantId, 3);
|
|
75
|
+
await client.query(`UPDATE entity_variants SET canonical = $1 WHERE canonical = $2 AND variant != $2 AND ${repointTc.sql}`, [target, source, repointTc.param]);
|
|
62
76
|
// Step 7: retire the source entity row in place.
|
|
77
|
+
const retireTc = tenantClausePg(tenantId, 2);
|
|
63
78
|
await client.query(`UPDATE entities
|
|
64
79
|
SET status = 'retired',
|
|
65
80
|
session_count = 0,
|
|
66
81
|
updated_at = NOW()
|
|
67
|
-
WHERE canonical = $1`, [source]);
|
|
82
|
+
WHERE canonical = $1 AND ${retireTc.sql}`, [source, retireTc.param]);
|
|
68
83
|
await client.query("COMMIT");
|
|
69
84
|
}
|
|
70
85
|
catch (err) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-entity-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-entity-store.ts"],"names":[],"mappings":"AAAA
|
|
1
|
+
{"version":3,"file":"pg-entity-store.js","sourceRoot":"","sources":["../../../src/core/storage/pg-entity-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -12,4 +12,4 @@
|
|
|
12
12
|
*/
|
|
13
13
|
import type { PoolClient } from "pg";
|
|
14
14
|
import type { Fact } from "../../shared/types.js";
|
|
15
|
-
export declare function ingestSessionFactsOnClient(client: PoolClient, sessionId: string, facts: ReadonlyArray<Fact
|
|
15
|
+
export declare function ingestSessionFactsOnClient(client: PoolClient, tenantId: string, sessionId: string, facts: ReadonlyArray<Fact>, scope?: string | null): Promise<void>;
|
|
@@ -11,20 +11,23 @@
|
|
|
11
11
|
* - every fact the collapse supersedes leaves the ANN index immediately
|
|
12
12
|
*/
|
|
13
13
|
import { batchWinners } from "./fact-batch.js";
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
import { tenantClausePg } from "../tenancy/tenant-clause.js";
|
|
15
|
+
export async function ingestSessionFactsOnClient(client, tenantId, sessionId, facts, scope = null) {
|
|
16
|
+
const deleteTc = tenantClausePg(tenantId, 2);
|
|
17
|
+
await client.query(`DELETE FROM facts WHERE source_session_id = $1 AND ${deleteTc.sql}`, [sessionId, deleteTc.param]);
|
|
16
18
|
if (facts.length === 0)
|
|
17
19
|
return;
|
|
18
20
|
for (const f of facts) {
|
|
19
21
|
await client.query(`INSERT INTO facts (id, kind, subject, predicate, value, source_session_id,
|
|
20
|
-
source_quote, created_at, superseded_by, confidence, retired_at)
|
|
21
|
-
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11)`, [f.id, f.kind, f.subject, f.predicate, f.value, f.sourceSessionId,
|
|
22
|
-
f.sourceQuote, f.createdAt, f.supersededBy, f.confidence, f.retiredAt]);
|
|
22
|
+
source_quote, created_at, superseded_by, confidence, retired_at, scope, tenant_id)
|
|
23
|
+
VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13)`, [f.id, f.kind, f.subject, f.predicate, f.value, f.sourceSessionId,
|
|
24
|
+
f.sourceQuote, f.createdAt, f.supersededBy, f.confidence, f.retiredAt, scope, tenantId]);
|
|
23
25
|
}
|
|
24
26
|
for (const f of batchWinners(facts)) {
|
|
27
|
+
const collapseTc = tenantClausePg(tenantId, 4);
|
|
25
28
|
const collapsed = await client.query(`UPDATE facts SET superseded_by = $1
|
|
26
|
-
WHERE subject = $2 AND predicate = $3 AND superseded_by IS NULL AND id != $1
|
|
27
|
-
RETURNING id`, [f.id, f.subject, f.predicate]);
|
|
29
|
+
WHERE subject = $2 AND predicate = $3 AND superseded_by IS NULL AND id != $1 AND ${collapseTc.sql}
|
|
30
|
+
RETURNING id`, [f.id, f.subject, f.predicate, collapseTc.param]);
|
|
28
31
|
const ids = collapsed.rows.map((r) => r.id);
|
|
29
32
|
if (ids.length > 0) {
|
|
30
33
|
await client.query("DELETE FROM fact_embeddings WHERE fact_id = ANY($1)", [ids]);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pg-fact-ingest.js","sourceRoot":"","sources":["../../../src/core/storage/pg-fact-ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;
|
|
1
|
+
{"version":3,"file":"pg-fact-ingest.js","sourceRoot":"","sources":["../../../src/core/storage/pg-fact-ingest.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAIH,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EAAE,cAAc,EAAE,MAAM,gCAAgC,CAAC;AAEhE,MAAM,CAAC,KAAK,UAAU,0BAA0B,CAC9C,MAAkB,EAClB,QAAgB,EAChB,SAAiB,EACjB,KAA0B,EAC1B,QAAuB,IAAI;IAE3B,MAAM,QAAQ,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;IAC7C,MAAM,MAAM,CAAC,KAAK,CAAC,sDAAsD,QAAQ,CAAC,GAAG,EAAE,EAAE,CAAC,SAAS,EAAE,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC;IACtH,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,OAAO;IAE/B,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,MAAM,MAAM,CAAC,KAAK,CAChB;;uEAEiE,EACjE,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,eAAe;YAChE,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC,SAAS,EAAE,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,SAAS,EAAE,KAAK,EAAE,QAAQ,CAAC,CACzF,CAAC;IACJ,CAAC;IAED,KAAK,MAAM,CAAC,IAAI,YAAY,CAAC,KAAK,CAAC,EAAE,CAAC;QACpC,MAAM,UAAU,GAAG,cAAc,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC;QAC/C,MAAM,SAAS,GAAG,MAAM,MAAM,CAAC,KAAK,CAClC;0FACoF,UAAU,CAAC,GAAG;oBACpF,EACd,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC,SAAS,EAAE,UAAU,CAAC,KAAK,CAAC,CACjD,CAAC;QACF,MAAM,GAAG,GAAG,SAAS,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC5C,IAAI,GAAG,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACnB,MAAM,MAAM,CAAC,KAAK,CAAC,qDAAqD,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;QACnF,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -2,33 +2,45 @@
|
|
|
2
2
|
* PgFactStore — FactStore implementation over pg.Pool + pgvector.
|
|
3
3
|
*
|
|
4
4
|
* Receives its Pool from PgStorage. Never opens its own connection.
|
|
5
|
+
*
|
|
6
|
+
* Tenancy: mirrors SqliteFactStore — every method takes `tenantId` as its
|
|
7
|
+
* non-optional first parameter and routes STAMP-table WHERE fragments
|
|
8
|
+
* through `tenantClausePg`. See that file's header comment for the full
|
|
9
|
+
* per-table rationale, including the vector-path re-resolution in
|
|
10
|
+
* semanticSearch.
|
|
5
11
|
*/
|
|
6
12
|
import type { Pool } from "pg";
|
|
7
|
-
import type { FactListFilter, FactQuery, FactSemanticNeighbor, FactStore } from "../../ports/fact-store.js";
|
|
13
|
+
import type { FactListFilter, FactQuery, FactSemanticNeighbor, FactStore, SubjectStat } from "../../ports/fact-store.js";
|
|
8
14
|
import type { Fact, FactHistoryChain } from "../../shared/types.js";
|
|
9
15
|
export declare class PgFactStore implements FactStore {
|
|
10
16
|
private readonly pool;
|
|
11
17
|
constructor(pool: Pool);
|
|
12
|
-
insert(fact: Fact): Promise<void>;
|
|
13
|
-
insertMany(facts: ReadonlyArray<Fact>): Promise<void>;
|
|
14
|
-
getById(id: string): Promise<Fact | null>;
|
|
15
|
-
getByIds(ids: ReadonlyArray<string>): Promise<ReadonlyArray<Fact>>;
|
|
16
|
-
findCurrent(subject: string, predicate: string): Promise<Fact | null>;
|
|
17
|
-
list(query: FactQuery): Promise<ReadonlyArray<Fact>>;
|
|
18
|
-
listBySession(sessionId: string): Promise<ReadonlyArray<Fact>>;
|
|
19
|
-
listBySessions(sessionIds: ReadonlyArray<string>, opts?: {
|
|
18
|
+
insert(tenantId: string, fact: Fact): Promise<void>;
|
|
19
|
+
insertMany(tenantId: string, facts: ReadonlyArray<Fact>): Promise<void>;
|
|
20
|
+
getById(tenantId: string, id: string): Promise<Fact | null>;
|
|
21
|
+
getByIds(tenantId: string, ids: ReadonlyArray<string>): Promise<ReadonlyArray<Fact>>;
|
|
22
|
+
findCurrent(tenantId: string, subject: string, predicate: string): Promise<Fact | null>;
|
|
23
|
+
list(tenantId: string, query: FactQuery): Promise<ReadonlyArray<Fact>>;
|
|
24
|
+
listBySession(tenantId: string, sessionId: string): Promise<ReadonlyArray<Fact>>;
|
|
25
|
+
listBySessions(tenantId: string, sessionIds: ReadonlyArray<string>, opts?: {
|
|
20
26
|
includeSuperseded?: boolean;
|
|
21
27
|
}): Promise<ReadonlyArray<Fact>>;
|
|
22
|
-
listForRecall(filter: FactListFilter): Promise<ReadonlyArray<Fact>>;
|
|
23
|
-
markSuperseded(oldId: string, newId: string | null): Promise<void>;
|
|
24
|
-
retire(factId: string): Promise<void>;
|
|
25
|
-
ingestSessionFacts(sessionId: string, facts: ReadonlyArray<Fact>): Promise<void>;
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
28
|
+
listForRecall(tenantId: string, filter: FactListFilter): Promise<ReadonlyArray<Fact>>;
|
|
29
|
+
markSuperseded(tenantId: string, oldId: string, newId: string | null): Promise<void>;
|
|
30
|
+
retire(tenantId: string, factId: string): Promise<void>;
|
|
31
|
+
ingestSessionFacts(tenantId: string, sessionId: string, facts: ReadonlyArray<Fact>): Promise<void>;
|
|
32
|
+
/**
|
|
33
|
+
* Guarded by a tenant-scoped existence check — writing an embedding for a
|
|
34
|
+
* fact outside the caller's tenant is a no-op, not a fallthrough write.
|
|
35
|
+
*/
|
|
36
|
+
upsertEmbedding(tenantId: string, factId: string, vector: Float32Array): Promise<void>;
|
|
37
|
+
semanticSearch(tenantId: string, queryVector: Float32Array, limit: number): Promise<ReadonlyArray<FactSemanticNeighbor>>;
|
|
38
|
+
getHistory(tenantId: string, subject: string, predicate?: string): Promise<ReadonlyArray<FactHistoryChain>>;
|
|
39
|
+
corroborationCounts(tenantId: string, triples: ReadonlyArray<{
|
|
30
40
|
readonly subject: string;
|
|
31
41
|
readonly predicate: string;
|
|
32
42
|
readonly value: string;
|
|
33
43
|
}>): Promise<Map<string, number>>;
|
|
44
|
+
listSubjectStats(_tenantId: string): Promise<ReadonlyArray<SubjectStat>>;
|
|
45
|
+
listBySubjects(_tenantId: string, _subjects: ReadonlyArray<string>): Promise<ReadonlyArray<Fact>>;
|
|
34
46
|
}
|