nlm-memory 0.19.0 → 0.20.1
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 +17 -10
- package/dist/cli/digest.js +21 -0
- 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 +766 -55
- package/dist/cli/nlm.js.map +1 -1
- 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.js +6 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/classifier/hierarchical-classify.d.ts +6 -2
- package/dist/core/classifier/hierarchical-classify.js +10 -6
- package/dist/core/classifier/hierarchical-classify.js.map +1 -1
- package/dist/core/classifier/prompt.js +3 -3
- package/dist/core/digest/compose.d.ts +10 -0
- package/dist/core/digest/compose.js +7 -1
- package/dist/core/digest/compose.js.map +1 -1
- 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 +1 -0
- package/dist/core/exemplars/capture-from-session.js +6 -2
- 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.js +2 -65
- package/dist/core/exemplars/extract-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/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/ingest-session.d.ts +5 -0
- package/dist/core/ingest/ingest-session.js +3 -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 +3 -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 +275 -0
- package/dist/core/ingest/reprocess.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/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/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 +21 -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 +13 -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 +80 -28
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/signals/code-signal.d.ts +49 -0
- package/dist/core/signals/code-signal.js +53 -0
- package/dist/core/signals/code-signal.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 +7 -0
- 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 +9 -0
- package/dist/core/storage/pg-session-store.js +204 -76
- package/dist/core/storage/pg-session-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 +24 -0
- package/dist/core/storage/pg-workstream-store.js +96 -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 +11 -0
- 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 +76 -25
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.d.ts +20 -5
- package/dist/core/storage/sqlite-session-store.js +183 -68
- package/dist/core/storage/sqlite-session-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 +24 -0
- package/dist/core/storage/sqlite-workstream-store.js +98 -0
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -0
- package/dist/core/util/with-timeout.d.ts +5 -0
- package/dist/core/util/with-timeout.js +20 -0
- package/dist/core/util/with-timeout.js.map +1 -0
- 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 +25 -0
- package/dist/core/workstream/bind.js +23 -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 +20 -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 +66 -0
- package/dist/hook/pre-compact-hook.js.map +1 -0
- package/dist/hook/prompt-recall-hook.d.ts +37 -0
- package/dist/hook/prompt-recall-hook.js +120 -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 +1 -1
- package/dist/hook/recall-over-http.js +11 -11
- 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 +24 -59
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +22 -59
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/hook/subagent-start-hook.d.ts +28 -0
- package/dist/hook/subagent-start-hook.js +81 -0
- package/dist/hook/subagent-start-hook.js.map +1 -0
- package/dist/http/app.js +28 -8
- 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 +47 -2
- package/dist/mcp/server.js +303 -18
- 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/session-store.d.ts +12 -0
- 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 +21 -0
- package/dist/ports/workstream-store.js +2 -0
- package/dist/ports/workstream-store.js.map +1 -0
- package/dist/shared/types.d.ts +23 -2
- 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/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/nlm/index.js +395 -37
- package/package.json +12 -2
- package/plugin/.codex-plugin/plugin.json +1 -1
- package/plugin/scripts/prompt-recall-hook.mjs +402 -41
- package/plugin/scripts/session-start-hook.mjs +286 -60
- package/plugin/scripts/stop-hook.mjs +85 -65
- 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,59 @@
|
|
|
1
|
+
User: For pulsearch I need to pick a vector database. The candidates are pgvector, Qdrant, and Weaviate. We're embedding 2-3 million documents, need sub-100ms p99 search, and I want to avoid managing a separate service if possible. Can you compare them?
|
|
2
|
+
|
|
3
|
+
Agent: Here's a structured comparison for the pulsearch use case:
|
|
4
|
+
|
|
5
|
+
pgvector
|
|
6
|
+
- Runs as a Postgres extension, so no separate service if you're already on Postgres
|
|
7
|
+
- At 2-3M vectors, IVFFlat and HNSW indexes both work but require tuning (lists parameter for IVFFlat, ef_construction for HNSW)
|
|
8
|
+
- Sub-100ms p99 is achievable at this scale with HNSW and appropriate connection pool sizing
|
|
9
|
+
- Filtering on metadata is native SQL, which is convenient
|
|
10
|
+
- Writes block on the HNSW index during bulk inserts; need to insert then create index, not the other way around
|
|
11
|
+
|
|
12
|
+
Qdrant
|
|
13
|
+
- Dedicated vector database, separate service (Docker or cloud)
|
|
14
|
+
- HNSW index is its primary structure, very well tuned; consistently strong benchmark numbers at 1-10M scale
|
|
15
|
+
- Payload filtering is first-class and done before the ANN step, not post-filter, which matters for selective queries
|
|
16
|
+
- REST and gRPC APIs; client libraries for Python, TypeScript, Go
|
|
17
|
+
- Requires running and operating another service
|
|
18
|
+
|
|
19
|
+
Weaviate
|
|
20
|
+
- Dedicated vector database with a built-in GraphQL query layer
|
|
21
|
+
- More opinionated about data modeling (schemas with classes)
|
|
22
|
+
- Larger operational footprint than Qdrant
|
|
23
|
+
- Better fit when you need hybrid BM25+vector search out of the box
|
|
24
|
+
|
|
25
|
+
For pulsearch specifically:
|
|
26
|
+
- If Postgres is already in your stack and ops simplicity is the priority, pgvector with HNSW is reasonable at 2-3M documents
|
|
27
|
+
- If you want best-in-class ANN performance and are comfortable running another service, Qdrant is the stronger choice at this scale
|
|
28
|
+
- Weaviate adds complexity without clear benefit unless you need its GraphQL layer
|
|
29
|
+
|
|
30
|
+
User: We're already running Postgres, but search quality is the top priority. What do you recommend?
|
|
31
|
+
|
|
32
|
+
Agent: Go with Qdrant. At 2-3M documents with sub-100ms p99 as a hard requirement, Qdrant's HNSW implementation is more predictable than pgvector's, and payload filtering before the ANN step means selective filters don't degrade recall. The operational overhead of one additional Docker container is low.
|
|
33
|
+
|
|
34
|
+
You can keep Postgres for everything else and run Qdrant alongside it. The pulsearch embedding pipeline writes to both: Postgres for the source record, Qdrant for the vector.
|
|
35
|
+
|
|
36
|
+
User: Agreed. What collection configuration would you recommend for pulsearch?
|
|
37
|
+
|
|
38
|
+
Agent: For 2-3M documents with 1536-dim embeddings (if using text-embedding-3-small) or 768-dim (if using a local model):
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
client.create_collection(
|
|
42
|
+
collection_name="pulsearch-docs",
|
|
43
|
+
vectors_config=VectorParams(
|
|
44
|
+
size=1536, # adjust to your embedding dim
|
|
45
|
+
distance=Distance.COSINE,
|
|
46
|
+
),
|
|
47
|
+
hnsw_config=HnswConfigDiff(
|
|
48
|
+
m=16,
|
|
49
|
+
ef_construct=100,
|
|
50
|
+
),
|
|
51
|
+
optimizers_config=OptimizersConfigDiff(
|
|
52
|
+
indexing_threshold=10_000, # don't index small batches
|
|
53
|
+
),
|
|
54
|
+
)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
HNSW m=16 and ef_construct=100 are conservative defaults that hit sub-100ms comfortably at this scale. You can increase ef_construct for higher recall at the cost of slower indexing.
|
|
58
|
+
|
|
59
|
+
User: Perfect. Let's go with Qdrant.
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
User: irongate needs customer-facing OAuth 2.0. I'm evaluating Keycloak self-hosted versus Auth0 versus SuperTokens. The main requirements are: LDAP integration for our enterprise customers, self-hosted option, OIDC compliance. What do you think?
|
|
2
|
+
|
|
3
|
+
Agent: All three support OIDC. The differentiating factor for your requirements is the LDAP integration:
|
|
4
|
+
|
|
5
|
+
Keycloak
|
|
6
|
+
- Full LDAP and Active Directory federation, built-in and well-documented
|
|
7
|
+
- Self-hosted; runs as a Java service (Quarkus distribution, Docker-friendly)
|
|
8
|
+
- Enterprise-grade: major deployments at scale, active community
|
|
9
|
+
- Admin UI is functional but has a learning curve
|
|
10
|
+
- Free and open source (Apache 2.0)
|
|
11
|
+
|
|
12
|
+
Auth0
|
|
13
|
+
- LDAP integration via Enterprise Connections, which requires the Business tier ($800+/month for even modest user counts)
|
|
14
|
+
- Managed SaaS; a self-hosted option exists via Auth0 Private Cloud but is expensive and not truly self-hosted
|
|
15
|
+
- Developer experience is excellent; SDKs are polished
|
|
16
|
+
- Cost scales with monthly active users, which gets expensive fast
|
|
17
|
+
|
|
18
|
+
SuperTokens
|
|
19
|
+
- Self-hosted option available (open source core)
|
|
20
|
+
- No native LDAP integration; enterprise SSO via their Enterprise tier which supports SAML but LDAP is not supported as a user federation source
|
|
21
|
+
- Better for consumer apps; gaps in enterprise identity features
|
|
22
|
+
|
|
23
|
+
For irongate with the LDAP requirement, Keycloak is the clear choice. It is the only option that covers all three requirements (LDAP federation, self-hosted, OIDC) without additional cost.
|
|
24
|
+
|
|
25
|
+
User: What's the operational complexity of running Keycloak?
|
|
26
|
+
|
|
27
|
+
Agent: Moderate. Key considerations:
|
|
28
|
+
|
|
29
|
+
- Runs as a stateless application backed by Postgres (recommended) or H2 for dev
|
|
30
|
+
- Horizontal scaling works but requires a shared Postgres backend and sticky sessions for the admin console
|
|
31
|
+
- Startup time is 15-30 seconds cold; plan for that in your container orchestration health checks
|
|
32
|
+
- The default Keycloak Docker image needs a few environment variables: KEYCLOAK_ADMIN, KEYCLOAK_ADMIN_PASSWORD, KC_DB_URL, KC_DB_USERNAME, KC_DB_PASSWORD
|
|
33
|
+
- Realm export/import is the standard backup mechanism; automate this
|
|
34
|
+
|
|
35
|
+
For irongate at this stage (pre-scale), a single Keycloak instance behind your nginx proxy on a dedicated small VM is sufficient. You can add a replica later.
|
|
36
|
+
|
|
37
|
+
User: Let's go with Keycloak self-hosted backed by Postgres.
|
|
38
|
+
|
|
39
|
+
Agent: Good choice. I'll draft the Docker Compose configuration for the irongate auth stack.
|
|
40
|
+
|
|
41
|
+
[Write: docker-compose.auth.yml]
|
|
42
|
+
|
|
43
|
+
```yaml
|
|
44
|
+
services:
|
|
45
|
+
keycloak:
|
|
46
|
+
image: quay.io/keycloak/keycloak:24.0
|
|
47
|
+
command: start
|
|
48
|
+
environment:
|
|
49
|
+
KC_DB: postgres
|
|
50
|
+
KC_DB_URL: jdbc:postgresql://auth-db:5432/keycloak
|
|
51
|
+
KC_DB_USERNAME: keycloak
|
|
52
|
+
KC_DB_PASSWORD: ${KC_DB_PASSWORD}
|
|
53
|
+
KC_HOSTNAME: auth.irongate.example.com
|
|
54
|
+
KEYCLOAK_ADMIN: admin
|
|
55
|
+
KEYCLOAK_ADMIN_PASSWORD: ${KEYCLOAK_ADMIN_PASSWORD}
|
|
56
|
+
depends_on:
|
|
57
|
+
- auth-db
|
|
58
|
+
ports:
|
|
59
|
+
- "8180:8080"
|
|
60
|
+
|
|
61
|
+
auth-db:
|
|
62
|
+
image: postgres:16
|
|
63
|
+
environment:
|
|
64
|
+
POSTGRES_DB: keycloak
|
|
65
|
+
POSTGRES_USER: keycloak
|
|
66
|
+
POSTGRES_PASSWORD: ${KC_DB_PASSWORD}
|
|
67
|
+
volumes:
|
|
68
|
+
- keycloak-pgdata:/var/lib/postgresql/data
|
|
69
|
+
|
|
70
|
+
volumes:
|
|
71
|
+
keycloak-pgdata:
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
User: Perfect. We'll proceed with Keycloak.
|
|
@@ -0,0 +1,154 @@
|
|
|
1
|
+
User: I need to write API documentation for cobalt-api. The API has about 12 endpoints. I want to use OpenAPI 3.0 format and host the docs at /api-docs. Can you help me set this up and draft the first few endpoints?
|
|
2
|
+
|
|
3
|
+
Agent: [Read: src/routes/index.ts]
|
|
4
|
+
|
|
5
|
+
I can see the route structure. Let me read the auth and resources endpoints to understand the request/response shapes.
|
|
6
|
+
|
|
7
|
+
[Read: src/routes/auth.ts]
|
|
8
|
+
[Read: src/routes/resources.ts]
|
|
9
|
+
|
|
10
|
+
Good. I'll draft the OpenAPI 3.0 spec for the auth and resources sections. For hosting at /api-docs, Swagger UI is the standard choice and integrates cleanly with Express.
|
|
11
|
+
|
|
12
|
+
User: Use Swagger UI. Let's document the auth endpoints first: POST /auth/token and POST /auth/refresh.
|
|
13
|
+
|
|
14
|
+
Agent: [Write: docs/openapi.yaml]
|
|
15
|
+
|
|
16
|
+
```yaml
|
|
17
|
+
openapi: "3.0.3"
|
|
18
|
+
info:
|
|
19
|
+
title: cobalt-api
|
|
20
|
+
version: "1.0.0"
|
|
21
|
+
description: REST API for the Cobalt platform
|
|
22
|
+
|
|
23
|
+
servers:
|
|
24
|
+
- url: https://api.cobalt.example.com/v1
|
|
25
|
+
description: Production
|
|
26
|
+
- url: http://localhost:3000/v1
|
|
27
|
+
description: Local development
|
|
28
|
+
|
|
29
|
+
components:
|
|
30
|
+
securitySchemes:
|
|
31
|
+
BearerAuth:
|
|
32
|
+
type: http
|
|
33
|
+
scheme: bearer
|
|
34
|
+
bearerFormat: JWT
|
|
35
|
+
|
|
36
|
+
schemas:
|
|
37
|
+
TokenResponse:
|
|
38
|
+
type: object
|
|
39
|
+
required: [access_token, refresh_token, expires_in]
|
|
40
|
+
properties:
|
|
41
|
+
access_token:
|
|
42
|
+
type: string
|
|
43
|
+
refresh_token:
|
|
44
|
+
type: string
|
|
45
|
+
expires_in:
|
|
46
|
+
type: integer
|
|
47
|
+
description: Seconds until access_token expires
|
|
48
|
+
|
|
49
|
+
Error:
|
|
50
|
+
type: object
|
|
51
|
+
required: [error, message]
|
|
52
|
+
properties:
|
|
53
|
+
error:
|
|
54
|
+
type: string
|
|
55
|
+
message:
|
|
56
|
+
type: string
|
|
57
|
+
|
|
58
|
+
paths:
|
|
59
|
+
/auth/token:
|
|
60
|
+
post:
|
|
61
|
+
summary: Exchange credentials for tokens
|
|
62
|
+
requestBody:
|
|
63
|
+
required: true
|
|
64
|
+
content:
|
|
65
|
+
application/json:
|
|
66
|
+
schema:
|
|
67
|
+
type: object
|
|
68
|
+
required: [email, password]
|
|
69
|
+
properties:
|
|
70
|
+
email:
|
|
71
|
+
type: string
|
|
72
|
+
format: email
|
|
73
|
+
password:
|
|
74
|
+
type: string
|
|
75
|
+
responses:
|
|
76
|
+
"200":
|
|
77
|
+
description: Token pair
|
|
78
|
+
content:
|
|
79
|
+
application/json:
|
|
80
|
+
schema:
|
|
81
|
+
$ref: "#/components/schemas/TokenResponse"
|
|
82
|
+
"401":
|
|
83
|
+
description: Invalid credentials
|
|
84
|
+
content:
|
|
85
|
+
application/json:
|
|
86
|
+
schema:
|
|
87
|
+
$ref: "#/components/schemas/Error"
|
|
88
|
+
|
|
89
|
+
/auth/refresh:
|
|
90
|
+
post:
|
|
91
|
+
summary: Exchange a refresh token for a new access token
|
|
92
|
+
requestBody:
|
|
93
|
+
required: true
|
|
94
|
+
content:
|
|
95
|
+
application/json:
|
|
96
|
+
schema:
|
|
97
|
+
type: object
|
|
98
|
+
required: [refresh_token]
|
|
99
|
+
properties:
|
|
100
|
+
refresh_token:
|
|
101
|
+
type: string
|
|
102
|
+
responses:
|
|
103
|
+
"200":
|
|
104
|
+
description: New token pair
|
|
105
|
+
content:
|
|
106
|
+
application/json:
|
|
107
|
+
schema:
|
|
108
|
+
$ref: "#/components/schemas/TokenResponse"
|
|
109
|
+
"401":
|
|
110
|
+
description: Invalid or expired refresh token
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
User: Good. Now wire up Swagger UI to serve this at /api-docs.
|
|
114
|
+
|
|
115
|
+
Agent: [Bash: npm install swagger-ui-express @types/swagger-ui-express yaml -D]
|
|
116
|
+
|
|
117
|
+
[Read: src/app.ts]
|
|
118
|
+
|
|
119
|
+
[Edit: src/app.ts]
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
import swaggerUi from "swagger-ui-express";
|
|
123
|
+
import { readFileSync } from "node:fs";
|
|
124
|
+
import { parse } from "yaml";
|
|
125
|
+
|
|
126
|
+
const spec = parse(readFileSync("docs/openapi.yaml", "utf-8")) as object;
|
|
127
|
+
app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(spec));
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
User: Does this need to be behind auth?
|
|
131
|
+
|
|
132
|
+
Agent: Typically no; API docs are public. But if cobalt-api exposes internal implementation details (internal error codes, admin endpoints), you might want to gate it. For now I'll leave it public and you can add middleware later if needed.
|
|
133
|
+
|
|
134
|
+
User: Fine as-is. Run the server and confirm /api-docs loads.
|
|
135
|
+
|
|
136
|
+
Agent: [Bash: npm run dev &]
|
|
137
|
+
|
|
138
|
+
```
|
|
139
|
+
Server listening on http://localhost:3000
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
[Bash: curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api-docs/]
|
|
143
|
+
|
|
144
|
+
```
|
|
145
|
+
301
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
[Bash: curl -s -o /dev/null -w "%{http_code}" http://localhost:3000/api-docs]
|
|
149
|
+
|
|
150
|
+
```
|
|
151
|
+
200
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
Redirects to trailing slash, returns 200. Swagger UI is serving the spec at /api-docs.
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
User: I need to capture the notes from our sprint planning meeting for orbitflow. Here's what we covered:
|
|
2
|
+
|
|
3
|
+
Attendees: product, backend, frontend squads
|
|
4
|
+
|
|
5
|
+
Sprint 5 goals we discussed:
|
|
6
|
+
- Webhook retry feature (backend priority, carries over from sprint 4 incomplete)
|
|
7
|
+
- Analytics dashboard (frontend wanted this but product deprioritized it)
|
|
8
|
+
- Rate limiting on the ingest API (security team flagged it last week)
|
|
9
|
+
- Mobile push notifications (new request, everyone agreed too large for this sprint)
|
|
10
|
+
|
|
11
|
+
Capacity: backend has 3 devs, one on PTO mid-sprint. Frontend has 2 devs full capacity.
|
|
12
|
+
|
|
13
|
+
Decisions made:
|
|
14
|
+
- Webhook retry moves to sprint 5 as the top backend priority
|
|
15
|
+
- Analytics dashboard deferred to sprint 6
|
|
16
|
+
- Rate limiting assigned to backend as secondary item
|
|
17
|
+
- Mobile push notifications deferred to sprint 6 backlog
|
|
18
|
+
|
|
19
|
+
Sprint 5 end date: July 18.
|
|
20
|
+
|
|
21
|
+
Can you format these into clean sprint notes?
|
|
22
|
+
|
|
23
|
+
Agent: Here are the sprint 5 planning notes for orbitflow:
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
Sprint 5 Planning Notes
|
|
28
|
+
orbitflow | Sprint 5 | Ends July 18
|
|
29
|
+
|
|
30
|
+
Attendees: Product, Backend squad (3 devs, one PTO mid-sprint), Frontend squad (2 devs)
|
|
31
|
+
|
|
32
|
+
Committed Items
|
|
33
|
+
|
|
34
|
+
Backend (primary)
|
|
35
|
+
- Webhook retry with exponential backoff [carries over from sprint 4]
|
|
36
|
+
|
|
37
|
+
Backend (secondary)
|
|
38
|
+
- Rate limiting on ingest API [security flag from last week]
|
|
39
|
+
|
|
40
|
+
Deferred
|
|
41
|
+
|
|
42
|
+
- Analytics dashboard: pushed to sprint 6 [frontend request, deprioritized by product]
|
|
43
|
+
- Mobile push notifications: pushed to sprint 6 backlog [scope too large for current capacity]
|
|
44
|
+
|
|
45
|
+
Capacity Notes
|
|
46
|
+
|
|
47
|
+
Backend is constrained mid-sprint due to PTO; webhook retry is the single priority. Rate limiting is secondary and may slip if webhook retry runs long.
|
|
48
|
+
|
|
49
|
+
---
|
|
50
|
+
|
|
51
|
+
User: Looks good. Can you also add a risks section?
|
|
52
|
+
|
|
53
|
+
Agent: Updated with risks:
|
|
54
|
+
|
|
55
|
+
---
|
|
56
|
+
|
|
57
|
+
Risks
|
|
58
|
+
|
|
59
|
+
1. Backend PTO mid-sprint reduces capacity by roughly 33% for one week. If webhook retry is not at code review by day 6, rate limiting will slip to sprint 6.
|
|
60
|
+
2. Rate limiting scope is not fully defined. The security team flagged the need but did not specify limits or key type. Backend needs a brief sync with security before starting implementation.
|
|
61
|
+
3. Analytics dashboard deferral may resurface as a blocker if frontend has no other committed work. Confirm frontend squad has sufficient sprint 5 items.
|
|
62
|
+
|
|
63
|
+
---
|
|
64
|
+
|
|
65
|
+
User: Perfect. Save this to docs/sprints/sprint-5-planning.md.
|
|
66
|
+
|
|
67
|
+
Agent: [Write: docs/sprints/sprint-5-planning.md]
|
|
68
|
+
|
|
69
|
+
Saved. The sprint 5 notes are in docs/sprints/sprint-5-planning.md with attendees, committed items, deferrals, capacity notes, and risks.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
User: What version of Node.js is installed?
|
|
2
|
+
|
|
3
|
+
Agent: [Bash: node --version]
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
v22.4.0
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
Node.js v22.4.0.
|
|
10
|
+
|
|
11
|
+
User: And npm?
|
|
12
|
+
|
|
13
|
+
Agent: [Bash: npm --version]
|
|
14
|
+
|
|
15
|
+
```
|
|
16
|
+
10.8.1
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
npm 10.8.1.
|
|
20
|
+
|
|
21
|
+
User: Good, that's what I needed.
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
User: How do I iterate over an array in TypeScript and get both the index and the value?
|
|
2
|
+
|
|
3
|
+
Agent: Use `Array.prototype.entries()` with a `for...of` loop:
|
|
4
|
+
|
|
5
|
+
```typescript
|
|
6
|
+
const items = ["a", "b", "c"];
|
|
7
|
+
for (const [index, value] of items.entries()) {
|
|
8
|
+
console.log(index, value);
|
|
9
|
+
}
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
Output:
|
|
13
|
+
```
|
|
14
|
+
0 a
|
|
15
|
+
1 b
|
|
16
|
+
2 c
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
Alternatively, `forEach` with two parameters:
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
items.forEach((value, index) => {
|
|
23
|
+
console.log(index, value);
|
|
24
|
+
});
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
The `for...of` with `.entries()` is generally preferred in modern TypeScript because it works with `break` and `continue`, which `forEach` does not.
|
|
28
|
+
|
|
29
|
+
User: Got it, thanks.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
User: Read the package.json and tell me what dependencies are listed.
|
|
2
|
+
|
|
3
|
+
Agent: [Read: package.json]
|
|
4
|
+
|
|
5
|
+
```json
|
|
6
|
+
{
|
|
7
|
+
"name": "my-project",
|
|
8
|
+
"version": "1.0.0",
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"express": "^4.18.2",
|
|
11
|
+
"pg": "^8.11.0"
|
|
12
|
+
},
|
|
13
|
+
"devDependencies": {
|
|
14
|
+
"typescript": "^5.3.3",
|
|
15
|
+
"vitest": "^1.2.0"
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
Dependencies:
|
|
21
|
+
- express ^4.18.2
|
|
22
|
+
- pg ^8.11.0
|
|
23
|
+
|
|
24
|
+
Dev dependencies:
|
|
25
|
+
- typescript ^5.3.3
|
|
26
|
+
- vitest ^1.2.0
|
|
27
|
+
|
|
28
|
+
User: Are they installed?
|
|
29
|
+
|
|
30
|
+
Agent: [Bash: ls node_modules | grep -E "^(express|pg|typescript|vitest)$"]
|
|
31
|
+
|
|
32
|
+
```
|
|
33
|
+
express
|
|
34
|
+
pg
|
|
35
|
+
typescript
|
|
36
|
+
vitest
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
All four are installed in node_modules.
|
|
40
|
+
|
|
41
|
+
User: Perfect, thanks.
|
|
@@ -40,7 +40,7 @@ CREATE TABLE IF NOT EXISTS entities (
|
|
|
40
40
|
canonical TEXT PRIMARY KEY, -- preferred spelling — also the primary key
|
|
41
41
|
type TEXT NOT NULL, -- 'candidate' until labeled. Built-in labels: project | tool | contact | service | concept. Custom labels are user-defined via the UI / `nle-daemon action label` and have no CHECK constraint.
|
|
42
42
|
status TEXT NOT NULL CHECK(status IN ('active','dormant','retired','rejected','candidate')),
|
|
43
|
-
source TEXT, -- e.g. 'property:.claude/properties/
|
|
43
|
+
source TEXT, -- e.g. 'property:.claude/properties/beacon.yaml', 'auto-detected', 'user-registered'
|
|
44
44
|
notes TEXT, -- freeform user notes
|
|
45
45
|
first_seen_session TEXT REFERENCES sessions(id),
|
|
46
46
|
last_seen_session TEXT REFERENCES sessions(id),
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
-- Migration 024: backfill code_exemplars.repo to logical basenames.
|
|
2
|
+
--
|
|
3
|
+
-- The pre-#330 session-capture path (captureExemplarsFromSession) stamped the
|
|
4
|
+
-- absolute projectDir into the repo column, leaking a host filesystem path
|
|
5
|
+
-- (/Users/.../<name>) into the local store — meaningless on a client install
|
|
6
|
+
-- and a privacy concern (per-install scoping, synthesis item 4). The #330
|
|
7
|
+
-- producer (nlm code-signal) and the now-fixed session-capture path both
|
|
8
|
+
-- record the logical basename instead.
|
|
9
|
+
--
|
|
10
|
+
-- This strips any directory prefix from existing absolute-path repos in place,
|
|
11
|
+
-- generically (no hardcoded host path), via a recursive CTE that peels off
|
|
12
|
+
-- each segment up to and including the next '/' until none remains. Idempotent:
|
|
13
|
+
-- once every repo is a basename, `repo LIKE '/%'` matches nothing and re-running
|
|
14
|
+
-- is a no-op. Fresh installs have no leaked rows, so this is a no-op there too.
|
|
15
|
+
--
|
|
16
|
+
-- The primary key id (sha256 of install_scope|repo|code_hash|outcome) is NOT
|
|
17
|
+
-- recomputed — SQLite cannot sha256 in pure SQL. The stale id is harmless: it
|
|
18
|
+
-- stays a valid unique key and keeps its embedding link. The only consequence
|
|
19
|
+
-- is that re-capturing the exact same legacy commit via the basename path would
|
|
20
|
+
-- compute a fresh id and insert a duplicate rather than dedup-skip — a rare
|
|
21
|
+
-- edge (requires a full re-ingest of old sessions) and never wrong data.
|
|
22
|
+
|
|
23
|
+
WITH RECURSIVE basename(id, rest) AS (
|
|
24
|
+
SELECT id, repo FROM code_exemplars WHERE repo LIKE '/%'
|
|
25
|
+
UNION ALL
|
|
26
|
+
SELECT id, substr(rest, instr(rest, '/') + 1) FROM basename WHERE instr(rest, '/') > 0
|
|
27
|
+
)
|
|
28
|
+
UPDATE code_exemplars
|
|
29
|
+
SET repo = (SELECT rest FROM basename WHERE basename.id = code_exemplars.id AND instr(basename.rest, '/') = 0)
|
|
30
|
+
WHERE repo LIKE '/%';
|
|
31
|
+
|
|
32
|
+
INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (24, '024_backfill_exemplar_repo_basename');
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
-- migrations/025_workstreams.sql
|
|
2
|
+
-- Workstream abstraction (#367) Plan A: a persistent container a session binds
|
|
3
|
+
-- to at end-of-session. See docs/superpowers/specs/2026-06-24-workstream-abstraction-design.md.
|
|
4
|
+
|
|
5
|
+
CREATE TABLE IF NOT EXISTS workstreams (
|
|
6
|
+
id TEXT PRIMARY KEY, -- ws_<uuid>
|
|
7
|
+
label TEXT NOT NULL,
|
|
8
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK(status IN ('active','merged','retired')),
|
|
9
|
+
merged_into TEXT REFERENCES workstreams(id),
|
|
10
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
11
|
+
updated_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
12
|
+
last_session_at TEXT
|
|
13
|
+
);
|
|
14
|
+
|
|
15
|
+
CREATE TABLE IF NOT EXISTS workstream_entities (
|
|
16
|
+
workstream_id TEXT NOT NULL REFERENCES workstreams(id) ON DELETE CASCADE,
|
|
17
|
+
entity_canonical TEXT NOT NULL REFERENCES entities(canonical),
|
|
18
|
+
session_count INTEGER NOT NULL DEFAULT 0,
|
|
19
|
+
PRIMARY KEY (workstream_id, entity_canonical)
|
|
20
|
+
);
|
|
21
|
+
|
|
22
|
+
CREATE INDEX IF NOT EXISTS idx_workstream_entities_entity ON workstream_entities(entity_canonical);
|
|
23
|
+
|
|
24
|
+
ALTER TABLE sessions ADD COLUMN workstream_id TEXT REFERENCES workstreams(id);
|
|
25
|
+
ALTER TABLE sessions ADD COLUMN binding_source TEXT;
|
|
26
|
+
ALTER TABLE sessions ADD COLUMN binding_confidence REAL;
|
|
27
|
+
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_workstream ON sessions(workstream_id);
|
|
29
|
+
|
|
30
|
+
INSERT OR IGNORE INTO schema_migrations (version, name) VALUES (25, 'workstreams');
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
-- Records which embedder produced the stored vectors, per lane.
|
|
2
|
+
-- lane 'prose' covers session chunks and fact embeddings (same embedder);
|
|
3
|
+
-- lane 'code' covers code exemplar embeddings.
|
|
4
|
+
-- Absence of a row means pre-tracking corpus: reconcile treats the running
|
|
5
|
+
-- embedder as canonical and records it.
|
|
6
|
+
CREATE TABLE IF NOT EXISTS embedding_config (
|
|
7
|
+
lane TEXT PRIMARY KEY CHECK (lane IN ('prose', 'code')),
|
|
8
|
+
provider TEXT NOT NULL,
|
|
9
|
+
model TEXT NOT NULL,
|
|
10
|
+
dim INTEGER NOT NULL,
|
|
11
|
+
updated_at TEXT NOT NULL
|
|
12
|
+
);
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
-- Migration 027: drop the legacy session_embeddings virtual table.
|
|
2
|
+
-- Migration 003 created it; migration 009 superseded it with the chunk + max-pool index.
|
|
3
|
+
|
|
4
|
+
DROP TABLE IF EXISTS session_embeddings;
|
|
5
|
+
|
|
6
|
+
INSERT OR IGNORE INTO schema_migrations (version, name)
|
|
7
|
+
VALUES (27, '027_drop_legacy_session_embeddings');
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
-- Which classifier produced this session's classification. NULL = classified
|
|
2
|
+
-- before provenance tracking; nlm reprocess treats NULL as eligible.
|
|
3
|
+
ALTER TABLE sessions ADD COLUMN classifier_provider TEXT;
|
|
4
|
+
ALTER TABLE sessions ADD COLUMN classifier_model TEXT;
|
|
5
|
+
ALTER TABLE sessions ADD COLUMN classifier_confidence REAL;
|
|
@@ -26,6 +26,9 @@ CREATE TABLE IF NOT EXISTS sessions (
|
|
|
26
26
|
transcript_length BIGINT,
|
|
27
27
|
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
28
28
|
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
29
|
+
workstream_id TEXT,
|
|
30
|
+
binding_source TEXT,
|
|
31
|
+
binding_confidence DOUBLE PRECISION,
|
|
29
32
|
fts_vector TSVECTOR GENERATED ALWAYS AS (
|
|
30
33
|
setweight(to_tsvector('english', coalesce(label, '')), 'A') ||
|
|
31
34
|
setweight(to_tsvector('english', coalesce(summary, '')), 'B') ||
|
|
@@ -255,3 +258,34 @@ CREATE TABLE IF NOT EXISTS code_exemplar_embeddings (
|
|
|
255
258
|
CREATE INDEX IF NOT EXISTS code_exemplar_embeddings_idx
|
|
256
259
|
ON code_exemplar_embeddings USING ivfflat (embedding vector_l2_ops)
|
|
257
260
|
WITH (lists = 100);
|
|
261
|
+
|
|
262
|
+
-- ── Workstreams (mirror of SQLite migration 025) ─────────────────────────────
|
|
263
|
+
CREATE TABLE IF NOT EXISTS workstreams (
|
|
264
|
+
id TEXT PRIMARY KEY,
|
|
265
|
+
label TEXT NOT NULL,
|
|
266
|
+
status TEXT NOT NULL DEFAULT 'active' CHECK (status IN ('active','merged','retired')),
|
|
267
|
+
merged_into TEXT REFERENCES workstreams(id),
|
|
268
|
+
created_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
269
|
+
updated_at TIMESTAMPTZ NOT NULL DEFAULT NOW(),
|
|
270
|
+
last_session_at TIMESTAMPTZ
|
|
271
|
+
);
|
|
272
|
+
|
|
273
|
+
CREATE TABLE IF NOT EXISTS workstream_entities (
|
|
274
|
+
workstream_id TEXT NOT NULL REFERENCES workstreams(id) ON DELETE CASCADE,
|
|
275
|
+
entity_canonical TEXT NOT NULL REFERENCES entities(canonical),
|
|
276
|
+
session_count INTEGER NOT NULL DEFAULT 0,
|
|
277
|
+
PRIMARY KEY (workstream_id, entity_canonical)
|
|
278
|
+
);
|
|
279
|
+
|
|
280
|
+
CREATE INDEX IF NOT EXISTS idx_workstream_entities_entity ON workstream_entities(entity_canonical);
|
|
281
|
+
|
|
282
|
+
-- FK from sessions.workstream_id to workstreams (deferred so workstreams exists first)
|
|
283
|
+
DO $$
|
|
284
|
+
BEGIN
|
|
285
|
+
ALTER TABLE sessions
|
|
286
|
+
ADD CONSTRAINT fk_sessions_workstream
|
|
287
|
+
FOREIGN KEY (workstream_id) REFERENCES workstreams(id);
|
|
288
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
289
|
+
END $$;
|
|
290
|
+
|
|
291
|
+
CREATE INDEX IF NOT EXISTS idx_sessions_workstream ON sessions(workstream_id);
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
-- PG parity for SQLite migration 019: split the mechanical `replaces` relation
|
|
2
2
|
-- out of `supersedes`.
|
|
3
3
|
--
|
|
4
|
-
--
|
|
5
|
-
--
|
|
6
|
-
--
|
|
4
|
+
-- Idempotent: safe to re-apply on a database that already has this shape.
|
|
5
|
+
-- DROP CONSTRAINT IF EXISTS removes any existing named constraint before the
|
|
6
|
+
-- DO-block re-adds it, so duplicate_object is never raised in practice;
|
|
7
|
+
-- the EXCEPTION clause is defensive for parity with the 001 pattern.
|
|
7
8
|
--
|
|
8
9
|
-- Widens the CHECK constraints on sessions.status and session_edges.kind to
|
|
9
10
|
-- admit 'replaced' / 'replaces', then reclassifies existing mechanical edges:
|
|
@@ -13,12 +14,20 @@
|
|
|
13
14
|
BEGIN;
|
|
14
15
|
|
|
15
16
|
ALTER TABLE sessions DROP CONSTRAINT IF EXISTS sessions_status_check;
|
|
16
|
-
|
|
17
|
-
|
|
17
|
+
DO $$
|
|
18
|
+
BEGIN
|
|
19
|
+
ALTER TABLE sessions ADD CONSTRAINT sessions_status_check
|
|
20
|
+
CHECK (status IN ('active', 'closed', 'superseded', 'replaced'));
|
|
21
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
22
|
+
END $$;
|
|
18
23
|
|
|
19
24
|
ALTER TABLE session_edges DROP CONSTRAINT IF EXISTS session_edges_kind_check;
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
DO $$
|
|
26
|
+
BEGIN
|
|
27
|
+
ALTER TABLE session_edges ADD CONSTRAINT session_edges_kind_check
|
|
28
|
+
CHECK (kind IN ('supersedes', 'replaces', 'continues'));
|
|
29
|
+
EXCEPTION WHEN duplicate_object THEN NULL;
|
|
30
|
+
END $$;
|
|
22
31
|
|
|
23
32
|
UPDATE session_edges e SET kind = 'replaces'
|
|
24
33
|
WHERE e.kind = 'supersedes'
|