nlm-memory 0.20.0 → 0.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +19 -10
- package/dist/cli/digest.js +60 -1
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/init.d.ts +12 -0
- package/dist/cli/init.js +49 -0
- package/dist/cli/init.js.map +1 -0
- package/dist/cli/nlm.d.ts +13 -1
- package/dist/cli/nlm.js +872 -61
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/scope-backfill.d.ts +34 -0
- package/dist/cli/scope-backfill.js +237 -0
- package/dist/cli/scope-backfill.js.map +1 -0
- package/dist/cli/scope-coverage.d.ts +44 -0
- package/dist/cli/scope-coverage.js +205 -0
- package/dist/cli/scope-coverage.js.map +1 -0
- package/dist/core/actions/overlay.d.ts +20 -6
- package/dist/core/actions/overlay.js +32 -18
- package/dist/core/actions/overlay.js.map +1 -1
- package/dist/core/adapters/claude-code.d.ts +14 -0
- package/dist/core/adapters/claude-code.js +36 -0
- package/dist/core/adapters/claude-code.js.map +1 -1
- package/dist/core/classifier/prompt.js +3 -3
- package/dist/core/dataset/build-dataset.js +1 -0
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +13 -3
- package/dist/core/digest/compose.js +23 -18
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +43 -0
- package/dist/core/digest/hook-injection.js +79 -0
- package/dist/core/digest/hook-injection.js.map +1 -0
- package/dist/core/embedding/embed-backfill.d.ts +13 -2
- package/dist/core/embedding/embed-backfill.js +181 -43
- package/dist/core/embedding/embed-backfill.js.map +1 -1
- package/dist/core/embedding/embedding-config.d.ts +17 -0
- package/dist/core/embedding/embedding-config.js +12 -0
- package/dist/core/embedding/embedding-config.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.d.ts +31 -0
- package/dist/core/embedding/pg-embed-backfill.js +264 -0
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -0
- package/dist/core/entities/dedup-suggest.d.ts +25 -0
- package/dist/core/entities/dedup-suggest.js +107 -0
- package/dist/core/entities/dedup-suggest.js.map +1 -0
- package/dist/core/eval/classifier-fixture-eval.d.ts +29 -0
- package/dist/core/eval/classifier-fixture-eval.js +217 -0
- package/dist/core/eval/classifier-fixture-eval.js.map +1 -0
- package/dist/core/eval/extraction-scoring.d.ts +63 -0
- package/dist/core/eval/extraction-scoring.js +79 -0
- package/dist/core/eval/extraction-scoring.js.map +1 -0
- package/dist/core/eval/run-eval.d.ts +40 -0
- package/dist/core/eval/run-eval.js +34 -0
- package/dist/core/eval/run-eval.js.map +1 -0
- package/dist/core/exemplars/capture-from-session.d.ts +2 -0
- package/dist/core/exemplars/capture-from-session.js +7 -3
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/diff-parse.d.ts +23 -0
- package/dist/core/exemplars/diff-parse.js +73 -0
- package/dist/core/exemplars/diff-parse.js.map +1 -0
- package/dist/core/exemplars/embed-backfill.d.ts +36 -0
- package/dist/core/exemplars/embed-backfill.js +85 -0
- package/dist/core/exemplars/embed-backfill.js.map +1 -0
- package/dist/core/exemplars/embed-text.d.ts +15 -0
- package/dist/core/exemplars/embed-text.js +18 -0
- package/dist/core/exemplars/embed-text.js.map +1 -0
- package/dist/core/exemplars/extract-exemplar.d.ts +2 -0
- package/dist/core/exemplars/extract-exemplar.js +9 -66
- package/dist/core/exemplars/extract-exemplar.js.map +1 -1
- package/dist/core/exemplars/ingest-exemplar.d.ts +1 -0
- package/dist/core/exemplars/ingest-exemplar.js +1 -0
- package/dist/core/exemplars/ingest-exemplar.js.map +1 -1
- package/dist/core/exemplars/recall-code.js +4 -0
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/exemplars/warm-embedder.d.ts +14 -0
- package/dist/core/exemplars/warm-embedder.js +18 -0
- package/dist/core/exemplars/warm-embedder.js.map +1 -0
- package/dist/core/health/corpus-state.d.ts +8 -0
- package/dist/core/health/corpus-state.js +11 -0
- package/dist/core/health/corpus-state.js.map +1 -0
- package/dist/core/health/embed-inflight.d.ts +9 -0
- package/dist/core/health/embed-inflight.js +30 -0
- package/dist/core/health/embed-inflight.js.map +1 -0
- package/dist/core/health/embedding-lane-state.d.ts +6 -0
- package/dist/core/health/embedding-lane-state.js +18 -0
- package/dist/core/health/embedding-lane-state.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +12 -0
- package/dist/core/health/warmup-state.js +12 -0
- package/dist/core/health/warmup-state.js.map +1 -0
- package/dist/core/hook/claude-settings.d.ts +1 -1
- package/dist/core/hook/claude-settings.js +0 -1
- package/dist/core/hook/claude-settings.js.map +1 -1
- package/dist/core/hook/gate.d.ts +13 -6
- package/dist/core/hook/gate.js +47 -6
- package/dist/core/hook/gate.js.map +1 -1
- package/dist/core/hook/hook-log.d.ts +5 -0
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +12 -0
- package/dist/core/hook/memo.js +41 -1
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +1 -0
- package/dist/core/hook/pointer-block.js +23 -2
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/query-extract.d.ts +2 -1
- package/dist/core/hook/query-extract.js +10 -1
- package/dist/core/hook/query-extract.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +28 -0
- package/dist/core/hook/resolve-conversation-by-query.js +98 -0
- package/dist/core/hook/resolve-conversation-by-query.js.map +1 -0
- package/dist/core/hook/select.d.ts +8 -0
- package/dist/core/hook/select.js +9 -2
- package/dist/core/hook/select.js.map +1 -1
- package/dist/core/hook/transcript.js +16 -2
- package/dist/core/hook/transcript.js.map +1 -1
- package/dist/core/ingest/backfill-derivables.d.ts +92 -0
- package/dist/core/ingest/backfill-derivables.js +175 -0
- package/dist/core/ingest/backfill-derivables.js.map +1 -0
- package/dist/core/ingest/ingest-session.d.ts +5 -0
- package/dist/core/ingest/ingest-session.js +23 -0
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +5 -0
- package/dist/core/ingest/reclassify-oversized.js +9 -0
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +96 -0
- package/dist/core/ingest/reprocess.js +280 -0
- package/dist/core/ingest/reprocess.js.map +1 -0
- package/dist/core/ingest/transcript-derivables.d.ts +27 -0
- package/dist/core/ingest/transcript-derivables.js +138 -0
- package/dist/core/ingest/transcript-derivables.js.map +1 -0
- package/dist/core/integrity/check-invariants.d.ts +6 -1
- package/dist/core/integrity/check-invariants.js +209 -3
- package/dist/core/integrity/check-invariants.js.map +1 -1
- package/dist/core/metrics/corpus-stats.d.ts +49 -0
- package/dist/core/metrics/corpus-stats.js +111 -0
- package/dist/core/metrics/corpus-stats.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +48 -0
- package/dist/core/metrics/re-derivation.js +87 -0
- package/dist/core/metrics/re-derivation.js.map +1 -0
- package/dist/core/outcome/coverage.d.ts +33 -0
- package/dist/core/outcome/coverage.js +46 -0
- package/dist/core/outcome/coverage.js.map +1 -0
- package/dist/core/outcome/rollup.d.ts +33 -0
- package/dist/core/outcome/rollup.js +113 -0
- package/dist/core/outcome/rollup.js.map +1 -0
- package/dist/core/recall/citation-log.d.ts +8 -0
- package/dist/core/recall/citation-log.js +17 -0
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +2 -2
- package/dist/core/recall/hook-recall-log.js +2 -2
- package/dist/core/recall/query-intent.d.ts +7 -0
- package/dist/core/recall/query-intent.js +25 -0
- package/dist/core/recall/query-intent.js.map +1 -0
- package/dist/core/recall/query-log.d.ts +4 -0
- package/dist/core/recall/query-log.js +4 -0
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +37 -1
- package/dist/core/recall/recall-service.js +106 -63
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/related-exemplars.d.ts +1 -0
- package/dist/core/recall/related-exemplars.js +4 -1
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.js +2 -2
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall/reranker.d.ts +2 -1
- package/dist/core/recall/reranker.js +3 -3
- package/dist/core/recall/reranker.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +7 -0
- package/dist/core/recall-facts/fact-query-log.js +2 -0
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +9 -1
- package/dist/core/recall-facts/fact-recall-service.js +22 -8
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.d.ts +6 -6
- package/dist/core/scheduler/scan-once.js +15 -49
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +10 -0
- package/dist/core/scheduler/scheduler.js +109 -13
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/scope/alias-map.d.ts +10 -0
- package/dist/core/scope/alias-map.js +41 -0
- package/dist/core/scope/alias-map.js.map +1 -0
- package/dist/core/scope/derive-scope.d.ts +8 -0
- package/dist/core/scope/derive-scope.js +54 -0
- package/dist/core/scope/derive-scope.js.map +1 -0
- package/dist/core/scope/scope-clause.d.ts +16 -0
- package/dist/core/scope/scope-clause.js +21 -0
- package/dist/core/scope/scope-clause.js.map +1 -0
- package/dist/core/scope/stamp-flag.d.ts +1 -0
- package/dist/core/scope/stamp-flag.js +4 -0
- package/dist/core/scope/stamp-flag.js.map +1 -0
- package/dist/core/signals/code-signal.d.ts +50 -0
- package/dist/core/signals/code-signal.js +54 -0
- package/dist/core/signals/code-signal.js.map +1 -0
- package/dist/core/signals/ingest-signal.d.ts +1 -1
- package/dist/core/signals/ingest-signal.js +3 -1
- package/dist/core/signals/ingest-signal.js.map +1 -1
- package/dist/core/signals/stamp-scope.d.ts +18 -0
- package/dist/core/signals/stamp-scope.js +28 -0
- package/dist/core/signals/stamp-scope.js.map +1 -0
- package/dist/core/storage/db-restore.js +3 -1
- package/dist/core/storage/db-restore.js.map +1 -1
- package/dist/core/storage/fact-batch.d.ts +9 -0
- package/dist/core/storage/fact-batch.js +14 -0
- package/dist/core/storage/fact-batch.js.map +1 -0
- package/dist/core/storage/pg-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/pg-code-exemplar-store.js +13 -2
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-embedding-config.d.ts +29 -0
- package/dist/core/storage/pg-embedding-config.js +53 -0
- package/dist/core/storage/pg-embedding-config.js.map +1 -0
- package/dist/core/storage/pg-entity-store.d.ts +12 -0
- package/dist/core/storage/pg-entity-store.js +79 -0
- package/dist/core/storage/pg-entity-store.js.map +1 -0
- package/dist/core/storage/pg-fact-ingest.d.ts +15 -0
- package/dist/core/storage/pg-fact-ingest.js +34 -0
- package/dist/core/storage/pg-fact-ingest.js.map +1 -0
- package/dist/core/storage/pg-fact-store.d.ts +3 -0
- package/dist/core/storage/pg-fact-store.js +26 -30
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-migrate.d.ts +18 -0
- package/dist/core/storage/pg-migrate.js +73 -0
- package/dist/core/storage/pg-migrate.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +11 -2
- package/dist/core/storage/pg-session-store.js +224 -96
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.js +4 -3
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +9 -7
- package/dist/core/storage/pg-storage.js +20 -50
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +25 -0
- package/dist/core/storage/pg-workstream-store.js +97 -0
- package/dist/core/storage/pg-workstream-store.js.map +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +1 -0
- package/dist/core/storage/sqlite-code-exemplar-store.js +15 -2
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-embedding-config.d.ts +10 -0
- package/dist/core/storage/sqlite-embedding-config.js +27 -0
- package/dist/core/storage/sqlite-embedding-config.js.map +1 -0
- package/dist/core/storage/sqlite-entity-store.d.ts +13 -0
- package/dist/core/storage/sqlite-entity-store.js +96 -0
- package/dist/core/storage/sqlite-entity-store.js.map +1 -0
- package/dist/core/storage/sqlite-fact-store.d.ts +15 -7
- package/dist/core/storage/sqlite-fact-store.js +81 -27
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-outcome-store.d.ts +89 -0
- package/dist/core/storage/sqlite-outcome-store.js +158 -0
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -0
- package/dist/core/storage/sqlite-session-store.d.ts +42 -7
- package/dist/core/storage/sqlite-session-store.js +208 -95
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.js +4 -2
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +8 -8
- package/dist/core/storage/sqlite-storage.js +21 -32
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +25 -0
- package/dist/core/storage/sqlite-workstream-store.js +99 -0
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -0
- package/dist/core/storage/supersedence-log.js +2 -0
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/core/telemetry/probe-filter.d.ts +35 -0
- package/dist/core/telemetry/probe-filter.js +56 -0
- package/dist/core/telemetry/probe-filter.js.map +1 -0
- package/dist/core/update-check/check.d.ts +6 -0
- package/dist/core/update-check/check.js +35 -0
- package/dist/core/update-check/check.js.map +1 -1
- package/dist/core/work-digest/active-spans.d.ts +8 -0
- package/dist/core/work-digest/active-spans.js +29 -0
- package/dist/core/work-digest/active-spans.js.map +1 -0
- package/dist/core/work-digest/attribute.d.ts +15 -0
- package/dist/core/work-digest/attribute.js +76 -0
- package/dist/core/work-digest/attribute.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +12 -0
- package/dist/core/work-digest/build-work-digest.js +69 -0
- package/dist/core/work-digest/build-work-digest.js.map +1 -0
- package/dist/core/work-digest/compose-work-digest.d.ts +3 -0
- package/dist/core/work-digest/compose-work-digest.js +52 -0
- package/dist/core/work-digest/compose-work-digest.js.map +1 -0
- package/dist/core/work-digest/merge-active.d.ts +10 -0
- package/dist/core/work-digest/merge-active.js +22 -0
- package/dist/core/work-digest/merge-active.js.map +1 -0
- package/dist/core/work-digest/read-transcript-timestamps.d.ts +7 -0
- package/dist/core/work-digest/read-transcript-timestamps.js +40 -0
- package/dist/core/work-digest/read-transcript-timestamps.js.map +1 -0
- package/dist/core/work-digest/topics.d.ts +18 -0
- package/dist/core/work-digest/topics.js +26 -0
- package/dist/core/work-digest/topics.js.map +1 -0
- package/dist/core/work-digest/types.d.ts +45 -0
- package/dist/core/work-digest/types.js +2 -0
- package/dist/core/work-digest/types.js.map +1 -0
- package/dist/core/workstream/bind.d.ts +26 -0
- package/dist/core/workstream/bind.js +42 -0
- package/dist/core/workstream/bind.js.map +1 -0
- package/dist/core/workstream/compose-recall.d.ts +2 -0
- package/dist/core/workstream/compose-recall.js +39 -0
- package/dist/core/workstream/compose-recall.js.map +1 -0
- package/dist/core/workstream/merge-suggest.d.ts +19 -0
- package/dist/core/workstream/merge-suggest.js +61 -0
- package/dist/core/workstream/merge-suggest.js.map +1 -0
- package/dist/core/workstream/model.d.ts +21 -0
- package/dist/core/workstream/model.js +9 -0
- package/dist/core/workstream/model.js.map +1 -0
- package/dist/core/workstream/name-match.d.ts +8 -0
- package/dist/core/workstream/name-match.js +18 -0
- package/dist/core/workstream/name-match.js.map +1 -0
- package/dist/core/workstream/resolve.d.ts +10 -0
- package/dist/core/workstream/resolve.js +21 -0
- package/dist/core/workstream/resolve.js.map +1 -0
- package/dist/core/workstream/rollup.d.ts +12 -0
- package/dist/core/workstream/rollup.js +17 -0
- package/dist/core/workstream/rollup.js.map +1 -0
- package/dist/core/workstream/work-topics.d.ts +10 -0
- package/dist/core/workstream/work-topics.js +55 -0
- package/dist/core/workstream/work-topics.js.map +1 -0
- package/dist/hook/hook-helpers.d.ts +4 -0
- package/dist/hook/hook-helpers.js +36 -0
- package/dist/hook/hook-helpers.js.map +1 -0
- package/dist/hook/pre-compact-hook.d.ts +23 -0
- package/dist/hook/pre-compact-hook.js +67 -0
- package/dist/hook/pre-compact-hook.js.map +1 -0
- package/dist/hook/prompt-recall-hook.d.ts +38 -0
- package/dist/hook/prompt-recall-hook.js +124 -20
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-gate.d.ts +29 -0
- package/dist/hook/recall-gate.js +50 -0
- package/dist/hook/recall-gate.js.map +1 -0
- package/dist/hook/recall-over-http.d.ts +3 -2
- package/dist/hook/recall-over-http.js +26 -13
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/recent-context.d.ts +25 -0
- package/dist/hook/recent-context.js +104 -0
- package/dist/hook/recent-context.js.map +1 -0
- package/dist/hook/score-floor.d.ts +27 -0
- package/dist/hook/score-floor.js +42 -0
- package/dist/hook/score-floor.js.map +1 -0
- package/dist/hook/session-end-hook.js +8 -29
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.js +26 -60
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +24 -60
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +6 -0
- package/dist/http/app.js +52 -44
- package/dist/http/app.js.map +1 -1
- package/dist/install/setup.js +2 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/llm/build-classifier.d.ts +22 -0
- package/dist/llm/build-classifier.js +42 -0
- package/dist/llm/build-classifier.js.map +1 -0
- package/dist/llm/build-embedder.d.ts +11 -0
- package/dist/llm/build-embedder.js +42 -0
- package/dist/llm/build-embedder.js.map +1 -0
- package/dist/llm/bundled-embedder-client.d.ts +37 -0
- package/dist/llm/bundled-embedder-client.js +90 -0
- package/dist/llm/bundled-embedder-client.js.map +1 -0
- package/dist/llm/classifier-box.d.ts +13 -5
- package/dist/llm/classifier-box.js +28 -6
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/llm/classifier-egress.d.ts +18 -0
- package/dist/llm/classifier-egress.js +59 -0
- package/dist/llm/classifier-egress.js.map +1 -0
- package/dist/llm/client-shared.d.ts +4 -0
- package/dist/llm/client-shared.js +39 -0
- package/dist/llm/client-shared.js.map +1 -0
- package/dist/llm/deepseek-client.d.ts +20 -0
- package/dist/llm/deepseek-client.js +59 -45
- package/dist/llm/deepseek-client.js.map +1 -1
- package/dist/llm/embedder-info.d.ts +15 -0
- package/dist/llm/embedder-info.js +27 -0
- package/dist/llm/embedder-info.js.map +1 -0
- package/dist/llm/model-quirks.d.ts +4 -0
- package/dist/llm/model-quirks.js +7 -0
- package/dist/llm/model-quirks.js.map +1 -0
- package/dist/llm/naming.d.ts +5 -0
- package/dist/llm/naming.js +20 -0
- package/dist/llm/naming.js.map +1 -0
- package/dist/llm/ollama-client.d.ts +7 -8
- package/dist/llm/ollama-client.js +59 -51
- package/dist/llm/ollama-client.js.map +1 -1
- package/dist/llm/ollama-code-embedder.d.ts +8 -3
- package/dist/llm/ollama-code-embedder.js +14 -24
- package/dist/llm/ollama-code-embedder.js.map +1 -1
- package/dist/llm/openai-code-embedder-client.d.ts +25 -0
- package/dist/llm/openai-code-embedder-client.js +52 -0
- package/dist/llm/openai-code-embedder-client.js.map +1 -0
- package/dist/llm/openai-embedder-client.d.ts +41 -0
- package/dist/llm/openai-embedder-client.js +83 -0
- package/dist/llm/openai-embedder-client.js.map +1 -0
- package/dist/mcp/server.d.ts +69 -2
- package/dist/mcp/server.js +404 -19
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/code-embedder.d.ts +6 -1
- package/dist/ports/code-exemplar-store.d.ts +5 -0
- package/dist/ports/entity-store.d.ts +35 -0
- package/dist/ports/entity-store.js +7 -0
- package/dist/ports/entity-store.js.map +1 -0
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/llm-client.d.ts +9 -1
- package/dist/ports/outcome.d.ts +85 -0
- package/dist/ports/outcome.js +11 -0
- package/dist/ports/outcome.js.map +1 -0
- package/dist/ports/session-store.d.ts +12 -6
- package/dist/ports/storage.d.ts +7 -30
- package/dist/ports/storage.js +3 -7
- package/dist/ports/storage.js.map +1 -1
- package/dist/ports/transcript-adapter.d.ts +2 -0
- package/dist/ports/workstream-store.d.ts +22 -0
- package/dist/ports/workstream-store.js +2 -0
- package/dist/ports/workstream-store.js.map +1 -0
- package/dist/shared/net.d.ts +3 -0
- package/dist/shared/net.js +4 -0
- package/dist/shared/net.js.map +1 -0
- package/dist/shared/types.d.ts +56 -2
- package/dist/shared/types.js +4 -1
- package/dist/shared/types.js.map +1 -1
- package/dist/ui/assets/{index-CMpQkbQy.js → index-CSaBtgXD.js} +1 -1
- package/dist/ui/index.html +1 -1
- package/fixtures/classifier-gold/README.md +94 -0
- package/fixtures/classifier-gold/reference.json +318 -0
- package/fixtures/classifier-gold/transcripts/01-bug-fix-null-pointer-api.txt +75 -0
- package/fixtures/classifier-gold/transcripts/02-bug-fix-race-condition-queue.txt +77 -0
- package/fixtures/classifier-gold/transcripts/03-bug-fix-jwt-clock-skew.txt +86 -0
- package/fixtures/classifier-gold/transcripts/04-feature-webhook-retry.txt +95 -0
- package/fixtures/classifier-gold/transcripts/05-feature-csv-export.txt +86 -0
- package/fixtures/classifier-gold/transcripts/06-feature-rate-limiting.txt +61 -0
- package/fixtures/classifier-gold/transcripts/07-refactor-db-abstraction.txt +72 -0
- package/fixtures/classifier-gold/transcripts/08-refactor-config-loading.txt +89 -0
- package/fixtures/classifier-gold/transcripts/09-ops-docker-staging.txt +94 -0
- package/fixtures/classifier-gold/transcripts/10-ops-nginx-ssl.txt +121 -0
- package/fixtures/classifier-gold/transcripts/11-ops-postgres-migration.txt +74 -0
- package/fixtures/classifier-gold/transcripts/12-ops-cron-debugging.txt +73 -0
- package/fixtures/classifier-gold/transcripts/13-research-vector-db-comparison.txt +59 -0
- package/fixtures/classifier-gold/transcripts/14-research-oauth-provider.txt +74 -0
- package/fixtures/classifier-gold/transcripts/15-writing-api-docs.txt +154 -0
- package/fixtures/classifier-gold/transcripts/16-meeting-sprint-planning.txt +69 -0
- package/fixtures/classifier-gold/transcripts/17-trivial-list-files.txt +14 -0
- package/fixtures/classifier-gold/transcripts/18-trivial-version-check.txt +21 -0
- package/fixtures/classifier-gold/transcripts/19-trivial-syntax-help.txt +29 -0
- package/fixtures/classifier-gold/transcripts/20-trivial-read-package-json.txt +41 -0
- package/migrations/000_initial_schema.sql +1 -1
- package/migrations/024_backfill_exemplar_repo_basename.sql +32 -0
- package/migrations/025_workstreams.sql +30 -0
- package/migrations/026_embedding_config.sql +12 -0
- package/migrations/027_drop_legacy_session_embeddings.sql +7 -0
- package/migrations/028_classifier_provenance.sql +5 -0
- package/migrations/029_project_scope.sql +21 -0
- package/migrations/032_session_derivables.sql +11 -0
- package/migrations/pg/001_initial.sql +34 -0
- package/migrations/pg/019_split_replaces.sql +16 -7
- package/migrations/pg/025_workstreams.sql +34 -0
- package/migrations/pg/026_embedding_config.sql +12 -0
- package/migrations/pg/028_classifier_provenance.sql +5 -0
- package/migrations/pg/029_entity_variants.sql +9 -0
- package/migrations/pg/030_project_scope.sql +23 -0
- package/migrations/pg/031_widen_session_edges_kind.sql +11 -0
- package/migrations/pg/032_session_derivables.sql +17 -0
- package/nlm/index.js +405 -39
- package/package.json +12 -2
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/scripts/prompt-recall-hook.mjs +413 -43
- package/plugin/scripts/session-start-hook.mjs +295 -61
- package/plugin/scripts/stop-hook.mjs +89 -66
- package/plugin-hermes-agent/__init__.py +2 -1
- package/templates/agent-contract/README.md +24 -0
- package/templates/agent-contract/claude-code.md +40 -0
- package/templates/agent-contract/generic.md +38 -0
- package/dist/core/embedding/embed-normalize.d.ts +0 -28
- package/dist/core/embedding/embed-normalize.js +0 -98
- package/dist/core/embedding/embed-normalize.js.map +0 -1
- package/dist/core/storage/pg-tx-context.d.ts +0 -52
- package/dist/core/storage/pg-tx-context.js +0 -149
- package/dist/core/storage/pg-tx-context.js.map +0 -1
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
User: I need to add indexes to the sessions table in our Postgres database. The table has 8 million rows and I can't afford a full table lock. The migration is in alembic/versions/0042_session_indexes.py.
|
|
2
|
+
|
|
3
|
+
Agent: [Read: alembic/versions/0042_session_indexes.py]
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
def upgrade() -> None:
|
|
7
|
+
op.create_index("idx_sessions_created_at", "sessions", ["created_at"])
|
|
8
|
+
op.create_index("idx_sessions_workspace_id", "sessions", ["workspace_id"])
|
|
9
|
+
op.create_index("idx_sessions_workspace_created", "sessions", ["workspace_id", "created_at"])
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
These use standard CREATE INDEX, which takes an AccessShareExclusive lock for the full duration on an 8M-row table. That will block reads and writes for minutes.
|
|
13
|
+
|
|
14
|
+
The fix is to use CREATE INDEX CONCURRENTLY, which only takes a brief lock at the start and end. Alembic supports this via `postgresql_concurrently=True`.
|
|
15
|
+
|
|
16
|
+
User: Switch them all to concurrent.
|
|
17
|
+
|
|
18
|
+
Agent: [Edit: alembic/versions/0042_session_indexes.py]
|
|
19
|
+
|
|
20
|
+
```python
|
|
21
|
+
def upgrade() -> None:
|
|
22
|
+
with op.get_context().autocommit_block():
|
|
23
|
+
op.create_index(
|
|
24
|
+
"idx_sessions_created_at", "sessions", ["created_at"],
|
|
25
|
+
postgresql_concurrently=True,
|
|
26
|
+
)
|
|
27
|
+
op.create_index(
|
|
28
|
+
"idx_sessions_workspace_id", "sessions", ["workspace_id"],
|
|
29
|
+
postgresql_concurrently=True,
|
|
30
|
+
)
|
|
31
|
+
op.create_index(
|
|
32
|
+
"idx_sessions_workspace_created", "sessions",
|
|
33
|
+
["workspace_id", "created_at"],
|
|
34
|
+
postgresql_concurrently=True,
|
|
35
|
+
)
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
The `autocommit_block()` is required because CREATE INDEX CONCURRENTLY cannot run inside a transaction.
|
|
39
|
+
|
|
40
|
+
User: What about statement_timeout? Our default is 30 seconds which would kill a concurrent index build.
|
|
41
|
+
|
|
42
|
+
Agent: Good catch. Concurrent index builds on large tables can take several minutes. You should set `statement_timeout = 0` for the migration connection only, not globally. In psql:
|
|
43
|
+
|
|
44
|
+
```sql
|
|
45
|
+
SET statement_timeout = 0;
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
Or in the Alembic migration, before the index creates:
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
op.execute("SET statement_timeout = 0")
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
I'll add that at the top of the upgrade function.
|
|
55
|
+
|
|
56
|
+
[Edit: alembic/versions/0042_session_indexes.py]
|
|
57
|
+
|
|
58
|
+
Added `op.execute("SET statement_timeout = 0")` as the first statement inside `autocommit_block()`.
|
|
59
|
+
|
|
60
|
+
User: Can we run the migration now, or should we wait for off-peak?
|
|
61
|
+
|
|
62
|
+
Agent: CONCURRENTLY is safe to run any time without locking, but the index build will consume IO and CPU proportional to table size. On an 8M-row table expect 2-5 minutes. Running during peak hours won't cause downtime, but it will increase query latency while the build is in progress. Off-peak is safer for user experience.
|
|
63
|
+
|
|
64
|
+
User: We'll run it tonight. Anything else?
|
|
65
|
+
|
|
66
|
+
Agent: One thing to verify before running: check there are no long-running transactions open, as CONCURRENTLY waits for them to complete before starting. Run:
|
|
67
|
+
|
|
68
|
+
```sql
|
|
69
|
+
SELECT pid, now() - pg_stat_activity.query_start AS duration, query
|
|
70
|
+
FROM pg_stat_activity
|
|
71
|
+
WHERE state = 'active' AND now() - pg_stat_activity.query_start > interval '1 minute';
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
If any show up, investigate before starting the migration.
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
User: A nightly report cron job on the flarepath server stopped running three days ago. No errors in the app logs. It was set up in the user crontab. Can you help debug?
|
|
2
|
+
|
|
3
|
+
Agent: [Bash: crontab -l]
|
|
4
|
+
|
|
5
|
+
```
|
|
6
|
+
0 2 * * * /opt/flarepath/scripts/nightly-report.sh >> /var/log/flarepath/nightly.log 2>&1
|
|
7
|
+
```
|
|
8
|
+
|
|
9
|
+
The crontab entry looks correct syntactically. Let me check if cron itself is running and whether it logged anything.
|
|
10
|
+
|
|
11
|
+
[Bash: systemctl status cron]
|
|
12
|
+
|
|
13
|
+
```
|
|
14
|
+
Active: active (running) since Mon 2026-06-15 09:12:44 UTC; 3 days ago
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Cron is running. Check its log:
|
|
18
|
+
|
|
19
|
+
[Bash: grep nightly-report /var/log/syslog | tail -20]
|
|
20
|
+
|
|
21
|
+
```
|
|
22
|
+
Jun 15 02:00:01 flarepath CRON[84231]: (ubuntu) CMD (/opt/flarepath/scripts/nightly-report.sh >> /var/log/flarepath/nightly.log 2>&1)
|
|
23
|
+
Jun 15 02:00:01 flarepath CRON[84232]: (CRON) error (grandchild #84231 failed with exit status 126)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Exit code 126 means "permission denied" or "not executable". The script exists but is not executable.
|
|
27
|
+
|
|
28
|
+
[Bash: ls -la /opt/flarepath/scripts/nightly-report.sh]
|
|
29
|
+
|
|
30
|
+
```
|
|
31
|
+
-rw-r--r-- 1 ubuntu ubuntu 1842 Jun 14 18:32 /opt/flarepath/scripts/nightly-report.sh
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
No execute bit. The script was edited on June 14 and the execute permission was lost, likely from a git checkout that replaced the file.
|
|
35
|
+
|
|
36
|
+
User: Fix it.
|
|
37
|
+
|
|
38
|
+
Agent: [Bash: chmod +x /opt/flarepath/scripts/nightly-report.sh]
|
|
39
|
+
|
|
40
|
+
[Bash: ls -la /opt/flarepath/scripts/nightly-report.sh]
|
|
41
|
+
|
|
42
|
+
```
|
|
43
|
+
-rwxr-xr-x 1 ubuntu ubuntu 1842 Jun 14 18:32 /opt/flarepath/scripts/nightly-report.sh
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
Fixed. Run a manual test now to confirm it executes cleanly:
|
|
47
|
+
|
|
48
|
+
[Bash: /opt/flarepath/scripts/nightly-report.sh]
|
|
49
|
+
|
|
50
|
+
```
|
|
51
|
+
[2026-06-18 14:23:01] Generating nightly report...
|
|
52
|
+
[2026-06-18 14:23:04] Fetched 2341 records
|
|
53
|
+
[2026-06-18 14:23:05] Report written to /var/log/flarepath/reports/2026-06-18.json
|
|
54
|
+
[2026-06-18 14:23:05] Done.
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
Runs cleanly.
|
|
58
|
+
|
|
59
|
+
User: Should we track this in git so it doesn't happen again?
|
|
60
|
+
|
|
61
|
+
Agent: Yes. The issue is that git does not preserve execute bits by default on some checkout configurations. Two options: set `core.fileMode = true` in the repo's git config (the default on Linux, but can be overridden), or add an explicit `chmod` call to the deploy script so the script is always made executable after checkout.
|
|
62
|
+
|
|
63
|
+
The deploy script approach is more robust since it works regardless of git config.
|
|
64
|
+
|
|
65
|
+
User: Let's add it to the deploy script.
|
|
66
|
+
|
|
67
|
+
Agent: [Read: scripts/deploy.sh]
|
|
68
|
+
|
|
69
|
+
[Edit: scripts/deploy.sh]
|
|
70
|
+
|
|
71
|
+
Added `chmod +x /opt/flarepath/scripts/nightly-report.sh` after the git pull step.
|
|
72
|
+
|
|
73
|
+
The cron job will run correctly from 2am tonight. The root cause was a git checkout stripping the execute bit; the deploy script now re-applies it on every deploy.
|
|
@@ -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');
|