nlm-memory 0.21.0 → 0.21.13
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 +67 -12
- package/assets/replay-eval-dark.svg +26 -0
- package/assets/replay-eval-light.svg +26 -0
- package/dist/cli/digest.js +34 -7
- package/dist/cli/digest.js.map +1 -1
- package/dist/cli/nlm.d.ts +14 -0
- package/dist/cli/nlm.js +450 -65
- package/dist/cli/nlm.js.map +1 -1
- package/dist/cli/reprocess-job-adapters.d.ts +35 -0
- package/dist/cli/reprocess-job-adapters.js +80 -0
- package/dist/cli/reprocess-job-adapters.js.map +1 -0
- package/dist/cli/scope-coverage.js +4 -1
- package/dist/cli/scope-coverage.js.map +1 -1
- package/dist/cli/supersede.js +8 -7
- package/dist/cli/supersede.js.map +1 -1
- package/dist/core/actions/actions-log.d.ts +65 -8
- package/dist/core/actions/actions-log.js +134 -17
- package/dist/core/actions/actions-log.js.map +1 -1
- package/dist/core/actions/overlay.d.ts +11 -2
- package/dist/core/actions/overlay.js +18 -6
- package/dist/core/actions/overlay.js.map +1 -1
- package/dist/core/adapters/from-source.js +11 -3
- package/dist/core/adapters/from-source.js.map +1 -1
- package/dist/core/adapters/fs-wiki-writer.d.ts +44 -0
- package/dist/core/adapters/fs-wiki-writer.js +132 -0
- package/dist/core/adapters/fs-wiki-writer.js.map +1 -0
- package/dist/core/adapters/hermes-agent.d.ts +15 -2
- package/dist/core/adapters/hermes-agent.js +57 -11
- package/dist/core/adapters/hermes-agent.js.map +1 -1
- package/dist/core/adapters/memory-wiki-writer.d.ts +8 -0
- package/dist/core/adapters/memory-wiki-writer.js +16 -0
- package/dist/core/adapters/memory-wiki-writer.js.map +1 -0
- package/dist/core/adapters/muse.d.ts +51 -0
- package/dist/core/adapters/muse.js +271 -0
- package/dist/core/adapters/muse.js.map +1 -0
- package/dist/core/adapters/opencode.d.ts +11 -4
- package/dist/core/adapters/opencode.js +41 -7
- package/dist/core/adapters/opencode.js.map +1 -1
- package/dist/core/alerts/alert-state.d.ts +17 -0
- package/dist/core/alerts/alert-state.js +45 -0
- package/dist/core/alerts/alert-state.js.map +1 -0
- package/dist/core/alerts/check-and-alert.d.ts +28 -0
- package/dist/core/alerts/check-and-alert.js +53 -0
- package/dist/core/alerts/check-and-alert.js.map +1 -0
- package/dist/core/alerts/drift-transition.d.ts +27 -0
- package/dist/core/alerts/drift-transition.js +56 -0
- package/dist/core/alerts/drift-transition.js.map +1 -0
- package/dist/core/alerts/embedder-transition.d.ts +23 -0
- package/dist/core/alerts/embedder-transition.js +40 -0
- package/dist/core/alerts/embedder-transition.js.map +1 -0
- package/dist/core/alerts/fire-alert.d.ts +24 -0
- package/dist/core/alerts/fire-alert.js +72 -0
- package/dist/core/alerts/fire-alert.js.map +1 -0
- package/dist/core/alerts/job-alert.d.ts +12 -0
- package/dist/core/alerts/job-alert.js +37 -0
- package/dist/core/alerts/job-alert.js.map +1 -0
- package/dist/core/alerts/types.d.ts +104 -0
- package/dist/core/alerts/types.js +11 -0
- package/dist/core/alerts/types.js.map +1 -0
- package/dist/core/alerts/wiki-alert.d.ts +15 -0
- package/dist/core/alerts/wiki-alert.js +31 -0
- package/dist/core/alerts/wiki-alert.js.map +1 -0
- package/dist/core/classifier/prompt.d.ts +13 -0
- package/dist/core/classifier/prompt.js +52 -2
- package/dist/core/classifier/prompt.js.map +1 -1
- package/dist/core/dataset/build-dataset.d.ts +16 -1
- package/dist/core/dataset/build-dataset.js +105 -45
- package/dist/core/dataset/build-dataset.js.map +1 -1
- package/dist/core/digest/compose.d.ts +8 -0
- package/dist/core/digest/compose.js +54 -0
- package/dist/core/digest/compose.js.map +1 -1
- package/dist/core/digest/hook-injection.d.ts +1 -1
- package/dist/core/digest/hook-injection.js +9 -1
- package/dist/core/digest/hook-injection.js.map +1 -1
- package/dist/core/digest/hook-version-parity.d.ts +31 -0
- package/dist/core/digest/hook-version-parity.js +56 -0
- package/dist/core/digest/hook-version-parity.js.map +1 -0
- package/dist/core/embedding/pg-embed-backfill.js +1 -1
- package/dist/core/embedding/pg-embed-backfill.js.map +1 -1
- package/dist/core/exemplars/capture-from-session.d.ts +1 -1
- package/dist/core/exemplars/capture-from-session.js +3 -3
- package/dist/core/exemplars/capture-from-session.js.map +1 -1
- package/dist/core/exemplars/embed-backfill.d.ts +9 -0
- package/dist/core/exemplars/embed-backfill.js +9 -1
- package/dist/core/exemplars/embed-backfill.js.map +1 -1
- package/dist/core/exemplars/recall-code.d.ts +1 -1
- package/dist/core/exemplars/recall-code.js +2 -2
- package/dist/core/exemplars/recall-code.js.map +1 -1
- package/dist/core/facts/backfill-facts.d.ts +1 -1
- package/dist/core/facts/backfill-facts.js +4 -4
- package/dist/core/facts/backfill-facts.js.map +1 -1
- package/dist/core/facts/embed-backfill.d.ts +54 -0
- package/dist/core/facts/embed-backfill.js +109 -0
- package/dist/core/facts/embed-backfill.js.map +1 -0
- package/dist/core/facts/reconcile-facts.d.ts +42 -0
- package/dist/core/facts/reconcile-facts.js +133 -0
- package/dist/core/facts/reconcile-facts.js.map +1 -0
- package/dist/core/health/embed-failure-state.d.ts +4 -0
- package/dist/core/health/embed-failure-state.js +12 -0
- package/dist/core/health/embed-failure-state.js.map +1 -0
- package/dist/core/health/warmup-retry.d.ts +27 -0
- package/dist/core/health/warmup-retry.js +53 -0
- package/dist/core/health/warmup-retry.js.map +1 -0
- package/dist/core/health/warmup-state.d.ts +15 -0
- package/dist/core/health/warmup-state.js +15 -1
- package/dist/core/health/warmup-state.js.map +1 -1
- package/dist/core/hook/cite-memo.d.ts +11 -7
- package/dist/core/hook/cite-memo.js +25 -17
- package/dist/core/hook/cite-memo.js.map +1 -1
- package/dist/core/hook/hook-log.d.ts +13 -2
- package/dist/core/hook/hook-log.js +16 -8
- package/dist/core/hook/hook-log.js.map +1 -1
- package/dist/core/hook/memo.d.ts +10 -6
- package/dist/core/hook/memo.js +25 -17
- package/dist/core/hook/memo.js.map +1 -1
- package/dist/core/hook/pointer-block.d.ts +8 -1
- package/dist/core/hook/pointer-block.js +17 -4
- package/dist/core/hook/pointer-block.js.map +1 -1
- package/dist/core/hook/resolve-conversation-by-query.d.ts +6 -5
- package/dist/core/hook/resolve-conversation-by-query.js +24 -12
- package/dist/core/hook/resolve-conversation-by-query.js.map +1 -1
- package/dist/core/ingest/ingest-session.d.ts +1 -1
- package/dist/core/ingest/ingest-session.js +3 -3
- package/dist/core/ingest/ingest-session.js.map +1 -1
- package/dist/core/ingest/reclassify-oversized.d.ts +1 -1
- package/dist/core/ingest/reclassify-oversized.js +2 -2
- package/dist/core/ingest/reclassify-oversized.js.map +1 -1
- package/dist/core/ingest/reprocess.d.ts +1 -1
- package/dist/core/ingest/reprocess.js +2 -2
- package/dist/core/ingest/reprocess.js.map +1 -1
- package/dist/core/jobs/job-supervisor.d.ts +168 -0
- package/dist/core/jobs/job-supervisor.js +335 -0
- package/dist/core/jobs/job-supervisor.js.map +1 -0
- package/dist/core/learner/model.d.ts +63 -0
- package/dist/core/learner/model.js +30 -0
- package/dist/core/learner/model.js.map +1 -0
- package/dist/core/learner/service.d.ts +42 -0
- package/dist/core/learner/service.js +74 -0
- package/dist/core/learner/service.js.map +1 -0
- package/dist/core/learner/summary.d.ts +28 -0
- package/dist/core/learner/summary.js +70 -0
- package/dist/core/learner/summary.js.map +1 -0
- package/dist/core/learner/validate.d.ts +18 -0
- package/dist/core/learner/validate.js +95 -0
- package/dist/core/learner/validate.js.map +1 -0
- package/dist/core/metrics/re-derivation.d.ts +31 -2
- package/dist/core/metrics/re-derivation.js +36 -4
- package/dist/core/metrics/re-derivation.js.map +1 -1
- package/dist/core/outcome/coverage.d.ts +1 -1
- package/dist/core/outcome/coverage.js +2 -2
- package/dist/core/outcome/coverage.js.map +1 -1
- package/dist/core/outcome/rollup.d.ts +1 -1
- package/dist/core/outcome/rollup.js +4 -4
- package/dist/core/outcome/rollup.js.map +1 -1
- package/dist/core/providers/provider-registry.d.ts +40 -23
- package/dist/core/providers/provider-registry.js +99 -81
- package/dist/core/providers/provider-registry.js.map +1 -1
- package/dist/core/recall/citation-log.d.ts +10 -5
- package/dist/core/recall/citation-log.js +21 -10
- package/dist/core/recall/citation-log.js.map +1 -1
- package/dist/core/recall/hook-recall-log.d.ts +5 -2
- package/dist/core/recall/hook-recall-log.js +12 -6
- package/dist/core/recall/hook-recall-log.js.map +1 -1
- package/dist/core/recall/miss-log.d.ts +7 -4
- package/dist/core/recall/miss-log.js +18 -11
- package/dist/core/recall/miss-log.js.map +1 -1
- package/dist/core/recall/query-log.d.ts +8 -5
- package/dist/core/recall/query-log.js +16 -9
- package/dist/core/recall/query-log.js.map +1 -1
- package/dist/core/recall/recall-service.d.ts +10 -1
- package/dist/core/recall/recall-service.js +31 -12
- package/dist/core/recall/recall-service.js.map +1 -1
- package/dist/core/recall/recent-log.d.ts +6 -1
- package/dist/core/recall/recent-log.js +13 -5
- package/dist/core/recall/recent-log.js.map +1 -1
- package/dist/core/recall/related-concepts.d.ts +29 -0
- package/dist/core/recall/related-concepts.js +67 -0
- package/dist/core/recall/related-concepts.js.map +1 -0
- package/dist/core/recall/related-exemplars.d.ts +1 -1
- package/dist/core/recall/related-exemplars.js +2 -2
- package/dist/core/recall/related-exemplars.js.map +1 -1
- package/dist/core/recall/related-facts.d.ts +1 -1
- package/dist/core/recall/related-facts.js +3 -3
- package/dist/core/recall/related-facts.js.map +1 -1
- package/dist/core/recall-facts/fact-query-log.d.ts +8 -4
- package/dist/core/recall-facts/fact-query-log.js +16 -8
- package/dist/core/recall-facts/fact-query-log.js.map +1 -1
- package/dist/core/recall-facts/fact-recall-service.d.ts +2 -2
- package/dist/core/recall-facts/fact-recall-service.js +12 -12
- package/dist/core/recall-facts/fact-recall-service.js.map +1 -1
- package/dist/core/scheduler/scan-once.js +15 -14
- package/dist/core/scheduler/scan-once.js.map +1 -1
- package/dist/core/scheduler/scheduler.d.ts +3 -0
- package/dist/core/scheduler/scheduler.js +15 -11
- package/dist/core/scheduler/scheduler.js.map +1 -1
- package/dist/core/signals/failure-mode-recall.d.ts +1 -1
- package/dist/core/signals/failure-mode-recall.js +2 -2
- package/dist/core/signals/failure-mode-recall.js.map +1 -1
- package/dist/core/signals/stamp-scope.d.ts +2 -2
- package/dist/core/signals/stamp-scope.js +2 -2
- package/dist/core/signals/stamp-scope.js.map +1 -1
- package/dist/core/sources/source-registry.d.ts +49 -28
- package/dist/core/sources/source-registry.js +113 -70
- package/dist/core/sources/source-registry.js.map +1 -1
- package/dist/core/storage/pg-code-exemplar-store.d.ts +19 -10
- package/dist/core/storage/pg-code-exemplar-store.js +58 -27
- package/dist/core/storage/pg-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/pg-entity-store.d.ts +6 -1
- package/dist/core/storage/pg-entity-store.js +33 -18
- package/dist/core/storage/pg-entity-store.js.map +1 -1
- package/dist/core/storage/pg-fact-ingest.d.ts +1 -1
- package/dist/core/storage/pg-fact-ingest.js +10 -7
- package/dist/core/storage/pg-fact-ingest.js.map +1 -1
- package/dist/core/storage/pg-fact-store.d.ts +29 -17
- package/dist/core/storage/pg-fact-store.js +99 -46
- package/dist/core/storage/pg-fact-store.js.map +1 -1
- package/dist/core/storage/pg-learner-store.d.ts +27 -0
- package/dist/core/storage/pg-learner-store.js +174 -0
- package/dist/core/storage/pg-learner-store.js.map +1 -0
- package/dist/core/storage/pg-session-store.d.ts +24 -20
- package/dist/core/storage/pg-session-store.js +162 -90
- package/dist/core/storage/pg-session-store.js.map +1 -1
- package/dist/core/storage/pg-signal-store.d.ts +10 -5
- package/dist/core/storage/pg-signal-store.js +24 -12
- package/dist/core/storage/pg-signal-store.js.map +1 -1
- package/dist/core/storage/pg-storage.d.ts +4 -0
- package/dist/core/storage/pg-storage.js +6 -0
- package/dist/core/storage/pg-storage.js.map +1 -1
- package/dist/core/storage/pg-workstream-store.d.ts +16 -11
- package/dist/core/storage/pg-workstream-store.js +46 -29
- package/dist/core/storage/pg-workstream-store.js.map +1 -1
- package/dist/core/storage/sqlite-code-exemplar-store.d.ts +24 -10
- package/dist/core/storage/sqlite-code-exemplar-store.js +84 -40
- package/dist/core/storage/sqlite-code-exemplar-store.js.map +1 -1
- package/dist/core/storage/sqlite-entity-store.d.ts +8 -1
- package/dist/core/storage/sqlite-entity-store.js +46 -27
- package/dist/core/storage/sqlite-entity-store.js.map +1 -1
- package/dist/core/storage/sqlite-fact-store.d.ts +45 -19
- package/dist/core/storage/sqlite-fact-store.js +172 -64
- package/dist/core/storage/sqlite-fact-store.js.map +1 -1
- package/dist/core/storage/sqlite-learner-store.d.ts +33 -0
- package/dist/core/storage/sqlite-learner-store.js +178 -0
- package/dist/core/storage/sqlite-learner-store.js.map +1 -0
- package/dist/core/storage/sqlite-outcome-store.d.ts +37 -22
- package/dist/core/storage/sqlite-outcome-store.js +90 -37
- package/dist/core/storage/sqlite-outcome-store.js.map +1 -1
- package/dist/core/storage/sqlite-session-store.d.ts +29 -20
- package/dist/core/storage/sqlite-session-store.js +207 -121
- package/dist/core/storage/sqlite-session-store.js.map +1 -1
- package/dist/core/storage/sqlite-signal-store.d.ts +12 -5
- package/dist/core/storage/sqlite-signal-store.js +27 -15
- package/dist/core/storage/sqlite-signal-store.js.map +1 -1
- package/dist/core/storage/sqlite-storage.d.ts +4 -0
- package/dist/core/storage/sqlite-storage.js +10 -2
- package/dist/core/storage/sqlite-storage.js.map +1 -1
- package/dist/core/storage/sqlite-workstream-store.d.ts +16 -11
- package/dist/core/storage/sqlite-workstream-store.js +52 -31
- package/dist/core/storage/sqlite-workstream-store.js.map +1 -1
- package/dist/core/storage/supersedence-log.d.ts +10 -7
- package/dist/core/storage/supersedence-log.js +19 -14
- package/dist/core/storage/supersedence-log.js.map +1 -1
- package/dist/core/tenancy/default-team.d.ts +6 -0
- package/dist/core/tenancy/default-team.js +7 -0
- package/dist/core/tenancy/default-team.js.map +1 -0
- package/dist/core/tenancy/hosted-mode.d.ts +9 -0
- package/dist/core/tenancy/hosted-mode.js +12 -0
- package/dist/core/tenancy/hosted-mode.js.map +1 -0
- package/dist/core/tenancy/team-auth.d.ts +16 -0
- package/dist/core/tenancy/team-auth.js +22 -0
- package/dist/core/tenancy/team-auth.js.map +1 -0
- package/dist/core/tenancy/team-token-store.d.ts +45 -0
- package/dist/core/tenancy/team-token-store.js +52 -0
- package/dist/core/tenancy/team-token-store.js.map +1 -0
- package/dist/core/tenancy/tenant-clause.d.ts +37 -0
- package/dist/core/tenancy/tenant-clause.js +11 -0
- package/dist/core/tenancy/tenant-clause.js.map +1 -0
- package/dist/core/tenancy/tenant-state-path.d.ts +28 -0
- package/dist/core/tenancy/tenant-state-path.js +49 -0
- package/dist/core/tenancy/tenant-state-path.js.map +1 -0
- package/dist/core/wiki/project.d.ts +17 -0
- package/dist/core/wiki/project.js +37 -0
- package/dist/core/wiki/project.js.map +1 -0
- package/dist/core/wiki/reconcile.d.ts +15 -0
- package/dist/core/wiki/reconcile.js +14 -0
- package/dist/core/wiki/reconcile.js.map +1 -0
- package/dist/core/wiki/render.d.ts +5 -0
- package/dist/core/wiki/render.js +84 -0
- package/dist/core/wiki/render.js.map +1 -0
- package/dist/core/wiki/rollup.d.ts +28 -0
- package/dist/core/wiki/rollup.js +91 -0
- package/dist/core/wiki/rollup.js.map +1 -0
- package/dist/core/wiki/select.d.ts +8 -0
- package/dist/core/wiki/select.js +7 -0
- package/dist/core/wiki/select.js.map +1 -0
- package/dist/core/wiki/slug.d.ts +36 -0
- package/dist/core/wiki/slug.js +71 -0
- package/dist/core/wiki/slug.js.map +1 -0
- package/dist/core/wiki/types.d.ts +37 -0
- package/dist/core/wiki/types.js +2 -0
- package/dist/core/wiki/types.js.map +1 -0
- package/dist/core/work-digest/build-work-digest.d.ts +1 -1
- package/dist/core/work-digest/build-work-digest.js +3 -3
- package/dist/core/work-digest/build-work-digest.js.map +1 -1
- package/dist/core/workstream/bind.d.ts +1 -1
- package/dist/core/workstream/bind.js +10 -10
- package/dist/core/workstream/bind.js.map +1 -1
- package/dist/core/workstream/rollup.d.ts +1 -1
- package/dist/core/workstream/rollup.js +6 -6
- package/dist/core/workstream/rollup.js.map +1 -1
- package/dist/hook/hook-helpers.d.ts +14 -0
- package/dist/hook/hook-helpers.js +29 -2
- package/dist/hook/hook-helpers.js.map +1 -1
- package/dist/hook/pre-compact-hook.js +6 -4
- package/dist/hook/pre-compact-hook.js.map +1 -1
- package/dist/hook/prompt-recall-hook.d.ts +5 -2
- package/dist/hook/prompt-recall-hook.js +28 -17
- package/dist/hook/prompt-recall-hook.js.map +1 -1
- package/dist/hook/recall-over-http.d.ts +27 -3
- package/dist/hook/recall-over-http.js +44 -11
- package/dist/hook/recall-over-http.js.map +1 -1
- package/dist/hook/session-end-hook.js +7 -5
- package/dist/hook/session-end-hook.js.map +1 -1
- package/dist/hook/session-start-hook.d.ts +14 -1
- package/dist/hook/session-start-hook.js +55 -15
- package/dist/hook/session-start-hook.js.map +1 -1
- package/dist/hook/stop-hook.js +9 -7
- package/dist/hook/stop-hook.js.map +1 -1
- package/dist/http/app.d.ts +41 -3
- package/dist/http/app.js +355 -96
- package/dist/http/app.js.map +1 -1
- package/dist/install/claude-code.d.ts +17 -0
- package/dist/install/claude-code.js +44 -5
- package/dist/install/claude-code.js.map +1 -1
- package/dist/install/codex.d.ts +23 -2
- package/dist/install/codex.js +111 -14
- package/dist/install/codex.js.map +1 -1
- package/dist/install/cursor.d.ts +2 -2
- package/dist/install/cursor.js +7 -7
- package/dist/install/cursor.js.map +1 -1
- package/dist/install/hermes.d.ts +8 -0
- package/dist/install/hermes.js +28 -5
- package/dist/install/hermes.js.map +1 -1
- package/dist/install/local-source.d.ts +20 -0
- package/dist/install/local-source.js +28 -0
- package/dist/install/local-source.js.map +1 -0
- package/dist/install/mcp-block.d.ts +77 -0
- package/dist/install/mcp-block.js +99 -0
- package/dist/install/mcp-block.js.map +1 -0
- package/dist/install/pi.d.ts +26 -0
- package/dist/install/pi.js +43 -0
- package/dist/install/pi.js.map +1 -1
- package/dist/install/setup.js +6 -0
- package/dist/install/setup.js.map +1 -1
- package/dist/install/windsurf.d.ts +2 -2
- package/dist/install/windsurf.js +7 -7
- package/dist/install/windsurf.js.map +1 -1
- package/dist/llm/classifier-box.d.ts +5 -0
- package/dist/llm/classifier-box.js +5 -0
- package/dist/llm/classifier-box.js.map +1 -1
- package/dist/mcp/server.d.ts +73 -16
- package/dist/mcp/server.js +306 -83
- package/dist/mcp/server.js.map +1 -1
- package/dist/ports/clock.d.ts +12 -0
- package/dist/ports/clock.js +10 -0
- package/dist/ports/clock.js.map +1 -0
- package/dist/ports/code-exemplar-store.d.ts +13 -13
- package/dist/ports/entity-store.d.ts +5 -1
- package/dist/ports/fact-store.d.ts +0 -0
- package/dist/ports/fact-store.js +0 -0
- package/dist/ports/fact-store.js.map +1 -1
- package/dist/ports/learner-store.d.ts +80 -0
- package/dist/ports/learner-store.js +19 -0
- package/dist/ports/learner-store.js.map +1 -0
- package/dist/ports/outcome.d.ts +3 -3
- package/dist/ports/session-store.d.ts +20 -14
- package/dist/ports/session-store.js +5 -0
- package/dist/ports/session-store.js.map +1 -1
- package/dist/ports/signal-store.d.ts +12 -8
- package/dist/ports/spawn-child.d.ts +14 -0
- package/dist/ports/spawn-child.js +10 -0
- package/dist/ports/spawn-child.js.map +1 -0
- package/dist/ports/storage.d.ts +6 -0
- package/dist/ports/transcript-adapter.d.ts +11 -0
- package/dist/ports/wiki-writer.d.ts +19 -0
- package/dist/ports/wiki-writer.js +12 -0
- package/dist/ports/wiki-writer.js.map +1 -0
- package/dist/ports/workstream-store.d.ts +19 -12
- package/dist/shared/types.d.ts +22 -0
- package/dist/shared/types.js.map +1 -1
- package/dist/shared/version.d.ts +9 -0
- package/dist/shared/version.js +11 -0
- package/dist/shared/version.js.map +1 -0
- package/dist/ui/assets/index-D6F3xAis.js +11 -0
- package/dist/ui/index.html +1 -1
- package/migrations/033_actions_kind_check.sql +58 -0
- package/migrations/034_tenancy_teams_and_stamps.sql +40 -0
- package/migrations/035_tenancy_entity_rekey.sql +75 -0
- package/migrations/036_tenant_name_uniqueness.sql +59 -0
- package/migrations/037_sessions_covering_index.sql +25 -0
- package/migrations/038_sources_muse.sql +33 -0
- package/migrations/039_learner_evidence.sql +51 -0
- package/migrations/pg/033_actions_kind_check.sql +17 -0
- package/migrations/pg/034_tenancy.sql +77 -0
- package/migrations/pg/035_tenant_name_uniqueness.sql +15 -0
- package/migrations/pg/036_sources_muse.sql +12 -0
- package/migrations/pg/037_learner_evidence.sql +55 -0
- package/nlm/index.js +246 -55
- package/package.json +10 -5
- package/plugin/.codex-plugin/plugin.json +2 -2
- package/plugin/scripts/prompt-recall-hook.mjs +244 -55
- package/plugin/scripts/session-start-hook.mjs +273 -53
- package/plugin/scripts/stop-hook.mjs +195 -37
- package/dist/ui/assets/index-CSaBtgXD.js +0 -11
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
import { slugify } from "./slug.js";
|
|
2
|
+
const LOG_LIMIT = 100;
|
|
3
|
+
export function renderPage(page, config) {
|
|
4
|
+
const lines = [
|
|
5
|
+
"---",
|
|
6
|
+
`title: ${JSON.stringify(page.subject)}`,
|
|
7
|
+
"nlm_generated: true",
|
|
8
|
+
`fact_count: ${page.current.length}`,
|
|
9
|
+
`session_count: ${page.sessionIds.length}`,
|
|
10
|
+
`superseded_count: ${page.superseded.length}`,
|
|
11
|
+
...(page.aliases.length > 0
|
|
12
|
+
? [`aliases: [${page.aliases.map((a) => JSON.stringify(a)).join(", ")}]`]
|
|
13
|
+
: []),
|
|
14
|
+
"---",
|
|
15
|
+
"",
|
|
16
|
+
`> Generated by NLM from ${page.sessionIds.length} session${page.sessionIds.length === 1 ? "" : "s"}.`,
|
|
17
|
+
"> Edits are overwritten. To keep something here, promote it.",
|
|
18
|
+
"",
|
|
19
|
+
"## Current",
|
|
20
|
+
"",
|
|
21
|
+
];
|
|
22
|
+
for (const f of page.current) {
|
|
23
|
+
lines.push(`- ${f.predicate}: ${f.value} ^${f.id}`);
|
|
24
|
+
lines.push(` <sup>[session](${config.linkBase}/thread/${f.sourceSessionId}) · confidence ${f.confidence}</sup>`);
|
|
25
|
+
}
|
|
26
|
+
lines.push("");
|
|
27
|
+
if (page.superseded.length > 0) {
|
|
28
|
+
lines.push("## History", "");
|
|
29
|
+
for (const f of page.superseded) {
|
|
30
|
+
lines.push(`- ~~${f.predicate}: ${f.value}~~ <sup>superseded, from [session](${config.linkBase}/thread/${f.sourceSessionId})</sup>`);
|
|
31
|
+
}
|
|
32
|
+
lines.push("");
|
|
33
|
+
}
|
|
34
|
+
if (page.related.length > 0) {
|
|
35
|
+
lines.push("## Related", "");
|
|
36
|
+
lines.push(page.related.map((s) => `[[${slugify(s)}]]`).join(" · "));
|
|
37
|
+
lines.push("");
|
|
38
|
+
}
|
|
39
|
+
return { relPath: `${page.slug}.md`, content: lines.join("\n") };
|
|
40
|
+
}
|
|
41
|
+
export function renderIndex(pages, today) {
|
|
42
|
+
const lines = [
|
|
43
|
+
"---",
|
|
44
|
+
"title: Index",
|
|
45
|
+
"nlm_generated: true",
|
|
46
|
+
`last_projected: ${today}`,
|
|
47
|
+
"---",
|
|
48
|
+
"",
|
|
49
|
+
`> Generated by NLM. ${pages.length} page${pages.length === 1 ? "" : "s"}.`,
|
|
50
|
+
"",
|
|
51
|
+
];
|
|
52
|
+
const sorted = pages.slice().sort((a, b) => a.subject.localeCompare(b.subject));
|
|
53
|
+
for (const p of sorted) {
|
|
54
|
+
lines.push(`- [[${p.slug}]] <sup>${p.current.length} facts · ${p.sessionIds.length} sessions</sup>`);
|
|
55
|
+
}
|
|
56
|
+
lines.push("");
|
|
57
|
+
return { relPath: "index.md", content: lines.join("\n") };
|
|
58
|
+
}
|
|
59
|
+
export function renderLog(pages, today) {
|
|
60
|
+
const entries = [];
|
|
61
|
+
for (const p of pages)
|
|
62
|
+
for (const f of p.current)
|
|
63
|
+
entries.push({ fact: f, page: p });
|
|
64
|
+
entries.sort((a, b) => b.fact.createdAt.localeCompare(a.fact.createdAt) || a.fact.id.localeCompare(b.fact.id));
|
|
65
|
+
const lines = [
|
|
66
|
+
"---",
|
|
67
|
+
"title: Log",
|
|
68
|
+
"nlm_generated: true",
|
|
69
|
+
`last_projected: ${today}`,
|
|
70
|
+
"---",
|
|
71
|
+
"",
|
|
72
|
+
"> Generated by NLM, most recent knowledge at the top.",
|
|
73
|
+
"",
|
|
74
|
+
];
|
|
75
|
+
for (const { fact, page } of entries.slice(0, LOG_LIMIT)) {
|
|
76
|
+
lines.push(`- ${fact.createdAt.slice(0, 10)} [[${page.slug}]] ${fact.predicate}: ${fact.value}`);
|
|
77
|
+
}
|
|
78
|
+
lines.push("");
|
|
79
|
+
return { relPath: "log.md", content: lines.join("\n") };
|
|
80
|
+
}
|
|
81
|
+
export function renderAll(pages, config, today) {
|
|
82
|
+
return [...pages.map((p) => renderPage(p, config)), renderIndex(pages, today), renderLog(pages, today)];
|
|
83
|
+
}
|
|
84
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../../../src/core/wiki/render.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Assemble one PageRollup per slug group.
|
|
3
|
+
*
|
|
4
|
+
* A group with more than one member is a merge: colliding spellings of one
|
|
5
|
+
* concept, already resolved by buildSlugGroups. This stage picks a canonical
|
|
6
|
+
* spelling, unions the group's facts (deduplicated by id, since the same
|
|
7
|
+
* fact must never render twice), and lists the rest as aliases.
|
|
8
|
+
*
|
|
9
|
+
* `related` links co-occurring subjects rather than entities. Entity pages do
|
|
10
|
+
* not exist until P4, so entity wikilinks would render broken on every page;
|
|
11
|
+
* a subject link points at a page this same run produces, and always names
|
|
12
|
+
* the canonical spelling so the link never points at an alias.
|
|
13
|
+
*
|
|
14
|
+
* All selected subjects' facts are loaded in a single listBySubjects call
|
|
15
|
+
* rather than one listForRecall call per subject: better-sqlite3 is
|
|
16
|
+
* synchronous, so a Promise.all over per-subject queries serializes into one
|
|
17
|
+
* blocking chain instead of parallelizing, and listForRecall's default
|
|
18
|
+
* limit + includeSuperseded flag disqualify its partial indexes. See #wiki
|
|
19
|
+
* rollup perf writeup. listBySubjects also excludes retired facts outright
|
|
20
|
+
* (listForRecall's includeSuperseded does not), so a retired fact can never
|
|
21
|
+
* render under Current again.
|
|
22
|
+
*/
|
|
23
|
+
import type { FactStore, SubjectStat } from "../../ports/fact-store.js";
|
|
24
|
+
import type { PageRollup } from "./types.js";
|
|
25
|
+
export interface RollupDeps {
|
|
26
|
+
readonly facts: Pick<FactStore, "listBySubjects">;
|
|
27
|
+
}
|
|
28
|
+
export declare function rollupPages(deps: RollupDeps, tenantId: string, selected: ReadonlyArray<SubjectStat>, groups: ReadonlyMap<string, ReadonlyArray<string>>): Promise<ReadonlyArray<PageRollup>>;
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
export async function rollupPages(deps, tenantId, selected, groups) {
|
|
2
|
+
const currentFactCountBySubject = new Map(selected.map((s) => [s.subject, s.factCount]));
|
|
3
|
+
const sortedGroups = [...groups.entries()].sort(([a], [b]) => a.localeCompare(b));
|
|
4
|
+
const allSubjects = sortedGroups.flatMap(([, members]) => members);
|
|
5
|
+
const allFacts = await deps.facts.listBySubjects(tenantId, allSubjects);
|
|
6
|
+
const factsBySubject = new Map();
|
|
7
|
+
for (const f of allFacts) {
|
|
8
|
+
const bucket = factsBySubject.get(f.subject);
|
|
9
|
+
if (bucket)
|
|
10
|
+
bucket.push(f);
|
|
11
|
+
else
|
|
12
|
+
factsBySubject.set(f.subject, [f]);
|
|
13
|
+
}
|
|
14
|
+
const loaded = sortedGroups.map(([slug, members]) => {
|
|
15
|
+
const perMember = members.map((subject) => factsBySubject.get(subject) ?? []);
|
|
16
|
+
const deduped = dedupeById(perMember.flat());
|
|
17
|
+
const current = deduped.filter((f) => f.supersededBy === null);
|
|
18
|
+
const superseded = deduped.filter((f) => f.supersededBy !== null);
|
|
19
|
+
const orderedMembers = members
|
|
20
|
+
.slice()
|
|
21
|
+
.sort((a, b) => compareCanonical(a, b, slug, currentFactCountBySubject));
|
|
22
|
+
const subject = orderedMembers[0];
|
|
23
|
+
const aliases = orderedMembers.slice(1).sort((a, b) => a.localeCompare(b));
|
|
24
|
+
return { slug, subject, aliases, current, superseded };
|
|
25
|
+
});
|
|
26
|
+
const subjectsBySession = new Map();
|
|
27
|
+
for (const { subject, current } of loaded) {
|
|
28
|
+
for (const f of current) {
|
|
29
|
+
let set = subjectsBySession.get(f.sourceSessionId);
|
|
30
|
+
if (!set) {
|
|
31
|
+
set = new Set();
|
|
32
|
+
subjectsBySession.set(f.sourceSessionId, set);
|
|
33
|
+
}
|
|
34
|
+
set.add(subject);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
return loaded.map(({ slug, subject, aliases, current, superseded }) => {
|
|
38
|
+
const sessionIds = [...new Set(current.map((f) => f.sourceSessionId))].sort();
|
|
39
|
+
const related = new Set();
|
|
40
|
+
for (const sid of sessionIds) {
|
|
41
|
+
for (const other of subjectsBySession.get(sid) ?? []) {
|
|
42
|
+
if (other !== subject)
|
|
43
|
+
related.add(other);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
subject,
|
|
48
|
+
slug,
|
|
49
|
+
aliases,
|
|
50
|
+
current: sortFacts(current),
|
|
51
|
+
superseded: sortFacts(superseded),
|
|
52
|
+
sessionIds,
|
|
53
|
+
related: [...related].sort(),
|
|
54
|
+
};
|
|
55
|
+
});
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Canonical spelling within a group: most current facts wins; a tie where
|
|
59
|
+
* exactly one spelling equals the slug is broken in its favor; any remaining
|
|
60
|
+
* tie falls to localeCompare. A strict total order, so sorting members with
|
|
61
|
+
* it and taking the first element is deterministic regardless of input
|
|
62
|
+
* order.
|
|
63
|
+
*
|
|
64
|
+
* `a` and `b` are always group members, and every group member is drawn
|
|
65
|
+
* from `selected` (buildSlugGroups is only ever called on
|
|
66
|
+
* `selected.map(s => s.subject)`), which is exactly what populates
|
|
67
|
+
* `currentFactCountBySubject`. The lookup can't miss, so a non-null
|
|
68
|
+
* assertion documents that instead of a `?? 0` fallback masking a case that
|
|
69
|
+
* never occurs.
|
|
70
|
+
*/
|
|
71
|
+
function compareCanonical(a, b, slug, currentFactCountBySubject) {
|
|
72
|
+
const countA = currentFactCountBySubject.get(a);
|
|
73
|
+
const countB = currentFactCountBySubject.get(b);
|
|
74
|
+
if (countA !== countB)
|
|
75
|
+
return countB - countA;
|
|
76
|
+
const aIsSlug = a === slug;
|
|
77
|
+
const bIsSlug = b === slug;
|
|
78
|
+
if (aIsSlug !== bIsSlug)
|
|
79
|
+
return aIsSlug ? -1 : 1;
|
|
80
|
+
return a.localeCompare(b);
|
|
81
|
+
}
|
|
82
|
+
function dedupeById(facts) {
|
|
83
|
+
const byId = new Map();
|
|
84
|
+
for (const f of facts)
|
|
85
|
+
byId.set(f.id, f);
|
|
86
|
+
return [...byId.values()];
|
|
87
|
+
}
|
|
88
|
+
function sortFacts(facts) {
|
|
89
|
+
return facts.slice().sort((a, b) => a.createdAt.localeCompare(b.createdAt) || a.id.localeCompare(b.id));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=rollup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rollup.js","sourceRoot":"","sources":["../../../src/core/wiki/rollup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Threshold selection. Both bounds must hold: fact count alone lets one
|
|
3
|
+
* chatty session mint a page, and session count alone lets a subject
|
|
4
|
+
* mentioned once in each of three sessions mint a page with nothing on it.
|
|
5
|
+
*/
|
|
6
|
+
import type { SubjectStat } from "../../ports/fact-store.js";
|
|
7
|
+
import type { WikiConfig } from "./types.js";
|
|
8
|
+
export declare function selectSubjects(stats: ReadonlyArray<SubjectStat>, config: WikiConfig): ReadonlyArray<SubjectStat>;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
export function selectSubjects(stats, config) {
|
|
2
|
+
return stats
|
|
3
|
+
.filter((s) => s.factCount >= config.minFacts && s.sessionCount >= config.minSessions)
|
|
4
|
+
.slice()
|
|
5
|
+
.sort((a, b) => b.factCount - a.factCount || a.subject.localeCompare(b.subject));
|
|
6
|
+
}
|
|
7
|
+
//# sourceMappingURL=select.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"select.js","sourceRoot":"","sources":["../../../src/core/wiki/select.ts"],"names":[],"mappings":"AAQA,MAAM,UAAU,cAAc,CAC5B,KAAiC,EACjC,MAAkB;IAElB,OAAO,KAAK;SACT,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,IAAI,MAAM,CAAC,QAAQ,IAAI,CAAC,CAAC,YAAY,IAAI,MAAM,CAAC,WAAW,CAAC;SACrF,KAAK,EAAE;SACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,GAAG,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;AACrF,CAAC"}
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subject to filename. Subjects come from the classifier already lowercased
|
|
3
|
+
* and trimmed by prompt contract, but that contract is not enforced at the
|
|
4
|
+
* storage layer: a minority carry spaces, path separators, and colons. A raw
|
|
5
|
+
* write of `scripts/release.sh` would create a subdirectory rather than a
|
|
6
|
+
* page, so slugging is required, not cosmetic.
|
|
7
|
+
*
|
|
8
|
+
* Slugging is lossy, so two distinct subjects can land on one filename.
|
|
9
|
+
* Empirically every such collision on the real corpus is one concept spelled
|
|
10
|
+
* two ways, so buildSlugGroups merges them into a single page rather than
|
|
11
|
+
* throwing; rollup.ts picks a canonical spelling and lists the rest as
|
|
12
|
+
* aliases. A slug that matches a reserved filename is different in kind (it
|
|
13
|
+
* would collide with a generated file, not another subject) and still
|
|
14
|
+
* throws.
|
|
15
|
+
*/
|
|
16
|
+
/**
|
|
17
|
+
* Slugs `renderAll` always emits (`index.md`, `log.md`) regardless of the
|
|
18
|
+
* corpus. A subject that slugs to one of these would silently overwrite the
|
|
19
|
+
* generated file (or be overwritten by it), so buildSlugGroups still throws
|
|
20
|
+
* on a match here rather than merging a subject's facts into the index.
|
|
21
|
+
*/
|
|
22
|
+
export declare const RESERVED_SLUGS: readonly ["index", "log"];
|
|
23
|
+
export declare function slugify(subject: string): string;
|
|
24
|
+
export declare class SlugCollisionError extends Error {
|
|
25
|
+
readonly slug: string;
|
|
26
|
+
readonly subjects: ReadonlyArray<string>;
|
|
27
|
+
constructor(slug: string, subjects: ReadonlyArray<string>);
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Group selected subjects by slug. A slug with more than one member is a
|
|
31
|
+
* merge candidate for rollup.ts, not an error: only a match against a
|
|
32
|
+
* reserved filename still throws. Members of each group are deduplicated and
|
|
33
|
+
* sorted with localeCompare so the group's contents are deterministic
|
|
34
|
+
* regardless of input order.
|
|
35
|
+
*/
|
|
36
|
+
export declare function buildSlugGroups(subjects: ReadonlyArray<string>): ReadonlyMap<string, ReadonlyArray<string>>;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Subject to filename. Subjects come from the classifier already lowercased
|
|
3
|
+
* and trimmed by prompt contract, but that contract is not enforced at the
|
|
4
|
+
* storage layer: a minority carry spaces, path separators, and colons. A raw
|
|
5
|
+
* write of `scripts/release.sh` would create a subdirectory rather than a
|
|
6
|
+
* page, so slugging is required, not cosmetic.
|
|
7
|
+
*
|
|
8
|
+
* Slugging is lossy, so two distinct subjects can land on one filename.
|
|
9
|
+
* Empirically every such collision on the real corpus is one concept spelled
|
|
10
|
+
* two ways, so buildSlugGroups merges them into a single page rather than
|
|
11
|
+
* throwing; rollup.ts picks a canonical spelling and lists the rest as
|
|
12
|
+
* aliases. A slug that matches a reserved filename is different in kind (it
|
|
13
|
+
* would collide with a generated file, not another subject) and still
|
|
14
|
+
* throws.
|
|
15
|
+
*/
|
|
16
|
+
const UNSAFE = /[^a-z0-9.-]+/g;
|
|
17
|
+
const RUNS = /-{2,}/g;
|
|
18
|
+
const EDGES = /^-+|-+$/g;
|
|
19
|
+
/**
|
|
20
|
+
* Slugs `renderAll` always emits (`index.md`, `log.md`) regardless of the
|
|
21
|
+
* corpus. A subject that slugs to one of these would silently overwrite the
|
|
22
|
+
* generated file (or be overwritten by it), so buildSlugGroups still throws
|
|
23
|
+
* on a match here rather than merging a subject's facts into the index.
|
|
24
|
+
*/
|
|
25
|
+
export const RESERVED_SLUGS = ["index", "log"];
|
|
26
|
+
export function slugify(subject) {
|
|
27
|
+
return subject
|
|
28
|
+
.toLowerCase()
|
|
29
|
+
.replace(UNSAFE, "-")
|
|
30
|
+
.replace(RUNS, "-")
|
|
31
|
+
.replace(EDGES, "");
|
|
32
|
+
}
|
|
33
|
+
export class SlugCollisionError extends Error {
|
|
34
|
+
slug;
|
|
35
|
+
subjects;
|
|
36
|
+
constructor(slug, subjects) {
|
|
37
|
+
super(`wiki slug collision: ${subjects.map((s) => JSON.stringify(s)).join(" and ")} ` +
|
|
38
|
+
`both slug to ${JSON.stringify(slug)}`);
|
|
39
|
+
this.name = "SlugCollisionError";
|
|
40
|
+
this.slug = slug;
|
|
41
|
+
this.subjects = subjects;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Group selected subjects by slug. A slug with more than one member is a
|
|
46
|
+
* merge candidate for rollup.ts, not an error: only a match against a
|
|
47
|
+
* reserved filename still throws. Members of each group are deduplicated and
|
|
48
|
+
* sorted with localeCompare so the group's contents are deterministic
|
|
49
|
+
* regardless of input order.
|
|
50
|
+
*/
|
|
51
|
+
export function buildSlugGroups(subjects) {
|
|
52
|
+
const bySlug = new Map();
|
|
53
|
+
for (const subject of subjects) {
|
|
54
|
+
const slug = slugify(subject);
|
|
55
|
+
if (RESERVED_SLUGS.includes(slug)) {
|
|
56
|
+
throw new SlugCollisionError(slug, [subject, `generated file ${slug}.md`]);
|
|
57
|
+
}
|
|
58
|
+
let members = bySlug.get(slug);
|
|
59
|
+
if (!members) {
|
|
60
|
+
members = new Set();
|
|
61
|
+
bySlug.set(slug, members);
|
|
62
|
+
}
|
|
63
|
+
members.add(subject);
|
|
64
|
+
}
|
|
65
|
+
const out = new Map();
|
|
66
|
+
for (const slug of [...bySlug.keys()].sort((a, b) => a.localeCompare(b))) {
|
|
67
|
+
out.set(slug, [...bySlug.get(slug)].sort((a, b) => a.localeCompare(b)));
|
|
68
|
+
}
|
|
69
|
+
return out;
|
|
70
|
+
}
|
|
71
|
+
//# sourceMappingURL=slug.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"slug.js","sourceRoot":"","sources":["../../../src/core/wiki/slug.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAEH,MAAM,MAAM,GAAG,eAAe,CAAC;AAC/B,MAAM,IAAI,GAAG,QAAQ,CAAC;AACtB,MAAM,KAAK,GAAG,UAAU,CAAC;AAEzB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,OAAO,EAAE,KAAK,CAAU,CAAC;AAExD,MAAM,UAAU,OAAO,CAAC,OAAe;IACrC,OAAO,OAAO;SACX,WAAW,EAAE;SACb,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC;SACpB,OAAO,CAAC,IAAI,EAAE,GAAG,CAAC;SAClB,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;AACxB,CAAC;AAED,MAAM,OAAO,kBAAmB,SAAQ,KAAK;IAClC,IAAI,CAAS;IACb,QAAQ,CAAwB;IAEzC,YAAY,IAAY,EAAE,QAA+B;QACvD,KAAK,CACH,wBAAwB,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG;YAC7E,gBAAgB,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,EAAE,CACzC,CAAC;QACF,IAAI,CAAC,IAAI,GAAG,oBAAoB,CAAC;QACjC,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAC7B,QAA+B;IAE/B,MAAM,MAAM,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC9C,KAAK,MAAM,OAAO,IAAI,QAAQ,EAAE,CAAC;QAC/B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9B,IAAK,cAAwC,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC;YAC7D,MAAM,IAAI,kBAAkB,CAAC,IAAI,EAAE,CAAC,OAAO,EAAE,kBAAkB,IAAI,KAAK,CAAC,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,OAAO,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAC/B,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;YAC5B,MAAM,CAAC,GAAG,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;QAC5B,CAAC;QACD,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;IACvB,CAAC;IACD,MAAM,GAAG,GAAG,IAAI,GAAG,EAAiC,CAAC;IACrD,KAAK,MAAM,IAAI,IAAI,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,GAAG,CAAC,GAAG,CACL,IAAI,EACJ,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,IAAI,CAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,CAC1D,CAAC;IACJ,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { Fact } from "../../shared/types.js";
|
|
2
|
+
export interface WikiConfig {
|
|
3
|
+
readonly minFacts: number;
|
|
4
|
+
readonly minSessions: number;
|
|
5
|
+
/** Base URL a page's session links point at. Config because a page outlives
|
|
6
|
+
* the process that wrote it and a synced vault must not carry dead
|
|
7
|
+
* loopback links. */
|
|
8
|
+
readonly linkBase: string;
|
|
9
|
+
}
|
|
10
|
+
export interface PageRollup {
|
|
11
|
+
/** Canonical spelling, chosen deterministically when a page merges more
|
|
12
|
+
* than one colliding spelling. See rollup.ts for the selection rule. */
|
|
13
|
+
readonly subject: string;
|
|
14
|
+
readonly slug: string;
|
|
15
|
+
readonly current: ReadonlyArray<Fact>;
|
|
16
|
+
readonly superseded: ReadonlyArray<Fact>;
|
|
17
|
+
readonly sessionIds: ReadonlyArray<string>;
|
|
18
|
+
/** Other subjects that earned a page and share a session with this one. */
|
|
19
|
+
readonly related: ReadonlyArray<string>;
|
|
20
|
+
/** Other spellings that merged into this page. Empty when nothing merged. */
|
|
21
|
+
readonly aliases: ReadonlyArray<string>;
|
|
22
|
+
}
|
|
23
|
+
export interface RenderedPage {
|
|
24
|
+
readonly relPath: string;
|
|
25
|
+
readonly content: string;
|
|
26
|
+
}
|
|
27
|
+
export interface ProjectionResult {
|
|
28
|
+
readonly written: number;
|
|
29
|
+
readonly unchanged: number;
|
|
30
|
+
readonly removed: number;
|
|
31
|
+
/** Number of pages selection produced, i.e. distinct slug groups — not the
|
|
32
|
+
* number of selected subjects, since a merge makes those diverge. */
|
|
33
|
+
readonly qualifying: number;
|
|
34
|
+
readonly onDisk: number;
|
|
35
|
+
/** qualifying minus onDisk after the run. Nonzero means a run failed. */
|
|
36
|
+
readonly coverageDrift: number;
|
|
37
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/wiki/types.ts"],"names":[],"mappings":""}
|
|
@@ -9,4 +9,4 @@ export interface BuildWorkDigestDeps {
|
|
|
9
9
|
readonly readTimestamps?: (path: string, fromMs: number, toMs: number) => number[];
|
|
10
10
|
readonly workstreams?: Pick<import("../../ports/workstream-store.js").WorkstreamStore, "listAll">;
|
|
11
11
|
}
|
|
12
|
-
export declare function buildWorkDigest(deps: BuildWorkDigestDeps, date: string): Promise<WorkDigest>;
|
|
12
|
+
export declare function buildWorkDigest(deps: BuildWorkDigestDeps, tenantId: string, date: string): Promise<WorkDigest>;
|
|
@@ -12,13 +12,13 @@ function dayWindow(date) {
|
|
|
12
12
|
to.setDate(to.getDate() + 1);
|
|
13
13
|
return { fromMs: from.getTime(), toMs: to.getTime(), fromIso: from.toISOString(), toIso: to.toISOString() };
|
|
14
14
|
}
|
|
15
|
-
export async function buildWorkDigest(deps, date) {
|
|
15
|
+
export async function buildWorkDigest(deps, tenantId, date) {
|
|
16
16
|
const idleThresholdMin = deps.idleThresholdMin ?? 5;
|
|
17
17
|
const deepBlockMin = deps.deepBlockMin ?? 25;
|
|
18
18
|
const topicProvider = deps.topicProvider ?? defaultTopicProvider;
|
|
19
19
|
const readTs = deps.readTimestamps ?? readTranscriptTimestamps;
|
|
20
20
|
const provider = deps.workstreams ? workstreamTopicProvider(topicProvider) : topicProvider;
|
|
21
|
-
const wsList = deps.workstreams ? await deps.workstreams.listAll() : [];
|
|
21
|
+
const wsList = deps.workstreams ? await deps.workstreams.listAll(tenantId) : [];
|
|
22
22
|
const wsById = new Map(wsList.map((w) => [w.id, { id: w.id, mergedInto: w.mergedInto }]));
|
|
23
23
|
const wsLabel = new Map(wsList.map((w) => [w.id, w.label]));
|
|
24
24
|
function resolveWs(id) {
|
|
@@ -29,7 +29,7 @@ export async function buildWorkDigest(deps, date) {
|
|
|
29
29
|
return label ? { id: live, label } : null;
|
|
30
30
|
}
|
|
31
31
|
const { fromMs, toMs, fromIso, toIso } = dayWindow(date);
|
|
32
|
-
const sessions = await deps.store.listByDateRange(fromIso, toIso);
|
|
32
|
+
const sessions = await deps.store.listByDateRange(tenantId, fromIso, toIso);
|
|
33
33
|
const activities = [];
|
|
34
34
|
const allSpans = [];
|
|
35
35
|
const decisions = new Set();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"build-work-digest.js","sourceRoot":"","sources":["../../../src/core/work-digest/build-work-digest.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,OAAO,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3E,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAsB,MAAM,aAAa,CAAC;AAChG,OAAO,EAAE,mBAAmB,EAAE,MAAM,6BAA6B,CAAC;AAGlE,MAAM,UAAU,GAAG,0EAA0E,CAAC;AAW9F,6EAA6E;AAC7E,SAAS,SAAS,CAAC,IAAY;IAC7B,MAAM,IAAI,GAAG,IAAI,IAAI,CAAC,GAAG,IAAI,WAAW,CAAC,CAAC;IAC1C,MAAM,EAAE,GAAG,IAAI,IAAI,CAAC,IAAI,CAAC,CAAC;IAC1B,EAAE,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC;IAC7B,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,EAAE,EAAE,OAAO,EAAE,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,EAAE,CAAC,WAAW,EAAE,EAAE,CAAC;AAC9G,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,eAAe,CAAC,IAAyB,EAAE,IAAY;
|
|
1
|
+
{"version":3,"file":"build-work-digest.js","sourceRoot":"","sources":["../../../src/core/work-digest/build-work-digest.ts"],"names":[],"mappings":"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"}
|
|
@@ -23,4 +23,4 @@ export interface BindInput {
|
|
|
23
23
|
export interface BindResult {
|
|
24
24
|
readonly workstreamId: string;
|
|
25
25
|
}
|
|
26
|
-
export declare function bindSessionToWorkstream(deps: BindDeps, input: BindInput): Promise<BindResult | null>;
|
|
26
|
+
export declare function bindSessionToWorkstream(deps: BindDeps, tenantId: string, input: BindInput): Promise<BindResult | null>;
|
|
@@ -5,26 +5,26 @@ export const NAMING_CONTENT_CHARS = 8000;
|
|
|
5
5
|
function scopeMatches(wsScope, sessionScope) {
|
|
6
6
|
return wsScope === sessionScope;
|
|
7
7
|
}
|
|
8
|
-
async function applyBinding(deps, input, workstreamId) {
|
|
9
|
-
await deps.sessions.setWorkstreamBinding(input.sessionId, workstreamId, deps.source ?? "classifier", null);
|
|
10
|
-
await deps.workstreams.upsertEntities(workstreamId, input.entities);
|
|
11
|
-
await deps.workstreams.touchLastSession(workstreamId, input.startedAt);
|
|
8
|
+
async function applyBinding(deps, tenantId, input, workstreamId) {
|
|
9
|
+
await deps.sessions.setWorkstreamBinding(tenantId, input.sessionId, workstreamId, deps.source ?? "classifier", null);
|
|
10
|
+
await deps.workstreams.upsertEntities(tenantId, workstreamId, input.entities);
|
|
11
|
+
await deps.workstreams.touchLastSession(tenantId, workstreamId, input.startedAt);
|
|
12
12
|
return { workstreamId };
|
|
13
13
|
}
|
|
14
|
-
export async function bindSessionToWorkstream(deps, input) {
|
|
14
|
+
export async function bindSessionToWorkstream(deps, tenantId, input) {
|
|
15
15
|
try {
|
|
16
|
-
const all = await deps.workstreams.listAll();
|
|
16
|
+
const all = await deps.workstreams.listAll(tenantId);
|
|
17
17
|
const content = `${input.label}\n${(input.body || input.summary).slice(0, NAMING_CONTENT_CHARS)}`;
|
|
18
18
|
if (scopeStampEnabled()) {
|
|
19
19
|
const scoped = all.filter((w) => scopeMatches(w.scope, input.scope));
|
|
20
20
|
const named = await deps.namer.nameWorkstream(content, scoped.map((w) => ({ label: w.label })));
|
|
21
21
|
const decision = decideWorkstreamByName(named, scoped, deps.aliasToLabel);
|
|
22
22
|
if (decision.kind === "bind") {
|
|
23
|
-
return applyBinding(deps, input, decision.workstreamId);
|
|
23
|
+
return applyBinding(deps, tenantId, input, decision.workstreamId);
|
|
24
24
|
}
|
|
25
25
|
if (named && named.trim()) {
|
|
26
|
-
const ws = await deps.workstreams.create({ id: makeWorkstreamId(), label: named.trim(), scope: input.scope });
|
|
27
|
-
return applyBinding(deps, input, ws.id);
|
|
26
|
+
const ws = await deps.workstreams.create(tenantId, { id: makeWorkstreamId(), label: named.trim(), scope: input.scope });
|
|
27
|
+
return applyBinding(deps, tenantId, input, ws.id);
|
|
28
28
|
}
|
|
29
29
|
return null;
|
|
30
30
|
}
|
|
@@ -32,7 +32,7 @@ export async function bindSessionToWorkstream(deps, input) {
|
|
|
32
32
|
const decision = decideWorkstreamByName(named, all, deps.aliasToLabel);
|
|
33
33
|
if (decision.kind === "abstain")
|
|
34
34
|
return null;
|
|
35
|
-
return applyBinding(deps, input, decision.workstreamId);
|
|
35
|
+
return applyBinding(deps, tenantId, input, decision.workstreamId);
|
|
36
36
|
}
|
|
37
37
|
catch (e) {
|
|
38
38
|
deps.log?.(`[workstream] bind failed for ${input.sessionId}: ${e instanceof Error ? e.message : String(e)}`);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../../src/core/workstream/bind.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAyBzC,SAAS,YAAY,CAAC,OAAsB,EAAE,YAA2B;IACvE,OAAO,OAAO,KAAK,YAAY,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAc,EAAE,KAAgB,EAAE,YAAoB;
|
|
1
|
+
{"version":3,"file":"bind.js","sourceRoot":"","sources":["../../../src/core/workstream/bind.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,MAAM,YAAY,CAAC;AAC9C,OAAO,EAAE,sBAAsB,EAAE,MAAM,iBAAiB,CAAC;AACzD,OAAO,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAE9D,MAAM,CAAC,MAAM,oBAAoB,GAAG,IAAI,CAAC;AAyBzC,SAAS,YAAY,CAAC,OAAsB,EAAE,YAA2B;IACvE,OAAO,OAAO,KAAK,YAAY,CAAC;AAClC,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,IAAc,EAAE,QAAgB,EAAE,KAAgB,EAAE,YAAoB;IAClG,MAAM,IAAI,CAAC,QAAQ,CAAC,oBAAoB,CAAC,QAAQ,EAAE,KAAK,CAAC,SAAS,EAAE,YAAY,EAAE,IAAI,CAAC,MAAM,IAAI,YAAY,EAAE,IAAI,CAAC,CAAC;IACrH,MAAM,IAAI,CAAC,WAAW,CAAC,cAAc,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,QAAQ,CAAC,CAAC;IAC9E,MAAM,IAAI,CAAC,WAAW,CAAC,gBAAgB,CAAC,QAAQ,EAAE,YAAY,EAAE,KAAK,CAAC,SAAS,CAAC,CAAC;IACjF,OAAO,EAAE,YAAY,EAAE,CAAC;AAC1B,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,uBAAuB,CAAC,IAAc,EAAE,QAAgB,EAAE,KAAgB;IAC9F,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACrD,MAAM,OAAO,GAAG,GAAG,KAAK,CAAC,KAAK,KAAK,CAAC,KAAK,CAAC,IAAI,IAAI,KAAK,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,oBAAoB,CAAC,EAAE,CAAC;QAElG,IAAI,iBAAiB,EAAE,EAAE,CAAC;YACxB,MAAM,MAAM,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,YAAY,CAAC,CAAC,CAAC,KAAK,EAAE,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC;YACrE,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;YAChG,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;YAE1E,IAAI,QAAQ,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gBAC7B,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;YACpE,CAAC;YAED,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;gBAC1B,MAAM,EAAE,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,QAAQ,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,IAAI,EAAE,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,CAAC,CAAC;gBACxH,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,CAAC,EAAE,CAAC,CAAC;YACpD,CAAC;YACD,OAAO,IAAI,CAAC;QACd,CAAC;QAED,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,OAAO,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC;QAC7F,MAAM,QAAQ,GAAG,sBAAsB,CAAC,KAAK,EAAE,GAAG,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACvE,IAAI,QAAQ,CAAC,IAAI,KAAK,SAAS;YAAE,OAAO,IAAI,CAAC;QAC7C,OAAO,YAAY,CAAC,IAAI,EAAE,QAAQ,EAAE,KAAK,EAAE,QAAQ,CAAC,YAAY,CAAC,CAAC;IACpE,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,CAAC,GAAG,EAAE,CAAC,gCAAgC,KAAK,CAAC,SAAS,KAAK,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;QAC7G,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC"}
|
|
@@ -9,4 +9,4 @@ export interface RollupDeps {
|
|
|
9
9
|
readonly facts: Pick<FactStore, "listBySessions">;
|
|
10
10
|
readonly exemplars: Pick<CodeExemplarStore, "listBySessions">;
|
|
11
11
|
}
|
|
12
|
-
export declare function rollupWorkstream(deps: RollupDeps, workstreamId: string): Promise<WorkstreamRollup | null>;
|
|
12
|
+
export declare function rollupWorkstream(deps: RollupDeps, tenantId: string, workstreamId: string): Promise<WorkstreamRollup | null>;
|
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
import { resolveWorkstreamId } from "./resolve.js";
|
|
2
|
-
export async function rollupWorkstream(deps, workstreamId) {
|
|
3
|
-
const all = await deps.workstreams.listAll();
|
|
2
|
+
export async function rollupWorkstream(deps, tenantId, workstreamId) {
|
|
3
|
+
const all = await deps.workstreams.listAll(tenantId);
|
|
4
4
|
const byId = new Map(all.map((w) => [w.id, { id: w.id, mergedInto: w.mergedInto }]));
|
|
5
5
|
const survivorId = resolveWorkstreamId(workstreamId, byId);
|
|
6
|
-
const workstream = await deps.workstreams.getById(survivorId);
|
|
6
|
+
const workstream = await deps.workstreams.getById(tenantId, survivorId);
|
|
7
7
|
if (!workstream)
|
|
8
8
|
return null;
|
|
9
9
|
const memberIds = all.filter((w) => resolveWorkstreamId(w.id, byId) === survivorId).map((w) => w.id);
|
|
10
|
-
const sessionIds = await deps.sessions.listSessionIdsByWorkstreams(memberIds);
|
|
10
|
+
const sessionIds = await deps.sessions.listSessionIdsByWorkstreams(tenantId, memberIds);
|
|
11
11
|
const [facts, exemplars] = await Promise.all([
|
|
12
|
-
deps.facts.listBySessions(sessionIds),
|
|
13
|
-
deps.exemplars.listBySessions(sessionIds),
|
|
12
|
+
deps.facts.listBySessions(tenantId, sessionIds),
|
|
13
|
+
deps.exemplars.listBySessions(tenantId, sessionIds),
|
|
14
14
|
]);
|
|
15
15
|
return { workstream, sessionIds, facts, exemplars };
|
|
16
16
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollup.js","sourceRoot":"","sources":["../../../src/core/workstream/rollup.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AASnD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAgB,EAAE,YAAoB;
|
|
1
|
+
{"version":3,"file":"rollup.js","sourceRoot":"","sources":["../../../src/core/workstream/rollup.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,mBAAmB,EAAE,MAAM,cAAc,CAAC;AASnD,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,IAAgB,EAAE,QAAgB,EAAE,YAAoB;IAC7F,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;IACrD,MAAM,IAAI,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,UAAU,EAAE,CAAC,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC,CAAC;IACrF,MAAM,UAAU,GAAG,mBAAmB,CAAC,YAAY,EAAE,IAAI,CAAC,CAAC;IAC3D,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,WAAW,CAAC,OAAO,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;IACxE,IAAI,CAAC,UAAU;QAAE,OAAO,IAAI,CAAC;IAE7B,MAAM,SAAS,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,CAAC,KAAK,UAAU,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACrG,MAAM,UAAU,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,2BAA2B,CAAC,QAAQ,EAAE,SAAS,CAAC,CAAC;IACxF,MAAM,CAAC,KAAK,EAAE,SAAS,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QAC3C,IAAI,CAAC,KAAK,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;QAC/C,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,QAAQ,EAAE,UAAU,CAAC;KACpD,CAAC,CAAC;IACH,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -1,3 +1,17 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* "Am I the entry point?" for a hook module, tolerant of symlinked installs.
|
|
3
|
+
*
|
|
4
|
+
* Node realpath-resolves `import.meta.url` but leaves `process.argv[1]` as the
|
|
5
|
+
* literal string the caller passed. Comparing them directly means any
|
|
6
|
+
* symlinked path fails the check, main() never runs, and the hook exits 0
|
|
7
|
+
* having silently done nothing. A versioned install with a `current` ->
|
|
8
|
+
* versions/X pointer invokes hooks through exactly such a symlink, so the
|
|
9
|
+
* naive comparison disables session capture while still reporting success.
|
|
10
|
+
*
|
|
11
|
+
* Resolving argv[1] before comparing makes the two agree in both layouts.
|
|
12
|
+
* A nonexistent argv[1] is not an error here — it just isn't us.
|
|
13
|
+
*/
|
|
14
|
+
export declare function isMainModule(metaUrl: string, argv1: string | undefined): boolean;
|
|
1
15
|
export declare function readStdin(): Promise<string>;
|
|
2
16
|
export declare function fetchWithTimeout(url: string, init: RequestInit, ms: number): Promise<Response>;
|
|
3
17
|
export declare function hookModeFromEnv(): "shadow" | "live";
|
|
@@ -1,6 +1,33 @@
|
|
|
1
|
-
import { appendFileSync, mkdirSync } from "node:fs";
|
|
1
|
+
import { appendFileSync, mkdirSync, realpathSync } from "node:fs";
|
|
2
2
|
import { homedir } from "node:os";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
|
+
import { pathToFileURL } from "node:url";
|
|
5
|
+
import { NLM_VERSION } from "../shared/version.js";
|
|
6
|
+
/**
|
|
7
|
+
* "Am I the entry point?" for a hook module, tolerant of symlinked installs.
|
|
8
|
+
*
|
|
9
|
+
* Node realpath-resolves `import.meta.url` but leaves `process.argv[1]` as the
|
|
10
|
+
* literal string the caller passed. Comparing them directly means any
|
|
11
|
+
* symlinked path fails the check, main() never runs, and the hook exits 0
|
|
12
|
+
* having silently done nothing. A versioned install with a `current` ->
|
|
13
|
+
* versions/X pointer invokes hooks through exactly such a symlink, so the
|
|
14
|
+
* naive comparison disables session capture while still reporting success.
|
|
15
|
+
*
|
|
16
|
+
* Resolving argv[1] before comparing makes the two agree in both layouts.
|
|
17
|
+
* A nonexistent argv[1] is not an error here — it just isn't us.
|
|
18
|
+
*/
|
|
19
|
+
export function isMainModule(metaUrl, argv1) {
|
|
20
|
+
if (!argv1)
|
|
21
|
+
return false;
|
|
22
|
+
let resolved;
|
|
23
|
+
try {
|
|
24
|
+
resolved = realpathSync(argv1);
|
|
25
|
+
}
|
|
26
|
+
catch {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return metaUrl === pathToFileURL(resolved).href;
|
|
30
|
+
}
|
|
4
31
|
export function readStdin() {
|
|
5
32
|
return new Promise((resolve) => {
|
|
6
33
|
let data = "";
|
|
@@ -27,7 +54,7 @@ export function appendHookEvent(data) {
|
|
|
27
54
|
try {
|
|
28
55
|
const path = process.env["NLM_HOOK_LOG"] ?? join(homedir(), ".nlm", "hook-log.jsonl");
|
|
29
56
|
mkdirSync(dirname(path), { recursive: true });
|
|
30
|
-
appendFileSync(path, `${JSON.stringify(data)}\n`, "utf8");
|
|
57
|
+
appendFileSync(path, `${JSON.stringify({ ...data, v: NLM_VERSION })}\n`, "utf8");
|
|
31
58
|
}
|
|
32
59
|
catch {
|
|
33
60
|
// Telemetry failure must never break the hook.
|