@remnic/core 9.3.733 → 9.3.734

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.
Files changed (294) hide show
  1. package/dist/access-boundary.d.ts +10 -10
  2. package/dist/access-boundary.js +9 -9
  3. package/dist/access-cli.js +25 -23
  4. package/dist/access-cli.js.map +1 -1
  5. package/dist/access-http.d.ts +10 -10
  6. package/dist/access-http.js +14 -14
  7. package/dist/access-mcp.d.ts +10 -10
  8. package/dist/access-mcp.js +13 -13
  9. package/dist/access-operations-batch.js +11 -11
  10. package/dist/access-operations.d.ts +10 -10
  11. package/dist/access-operations.js +12 -12
  12. package/dist/{access-service-Byoe3HsT.d.ts → access-service-rjFfmfKB.d.ts} +4 -4
  13. package/dist/access-service.d.ts +10 -10
  14. package/dist/access-service.js +8 -8
  15. package/dist/access-surface-catalog.d.ts +10 -10
  16. package/dist/action-confidence.d.ts +1 -1
  17. package/dist/active-memory-bridge.d.ts +1 -1
  18. package/dist/active-memory-bridge.js +3 -2
  19. package/dist/active-recall.d.ts +1 -1
  20. package/dist/behavior-learner.d.ts +1 -1
  21. package/dist/behavior-signals.d.ts +1 -1
  22. package/dist/bootstrap.d.ts +9 -9
  23. package/dist/briefing.d.ts +1 -1
  24. package/dist/buffer-surprise-report.d.ts +1 -1
  25. package/dist/buffer.d.ts +1 -1
  26. package/dist/calibration.d.ts +1 -1
  27. package/dist/capabilities.d.ts +97 -2
  28. package/dist/capabilities.js +11 -3
  29. package/dist/{catalog-DM1nk7cM.d.ts → catalog-DHYXzM4-.d.ts} +2 -2
  30. package/dist/causal-behavior.d.ts +1 -1
  31. package/dist/causal-consolidation.d.ts +1 -1
  32. package/dist/causal-trajectory-graph.d.ts +1 -1
  33. package/dist/{chunk-24D66MMN.js → chunk-2L5RTVMO.js} +7 -4
  34. package/dist/chunk-2L5RTVMO.js.map +1 -0
  35. package/dist/{chunk-KQYGNGON.js → chunk-3QETM5NG.js} +6 -3
  36. package/dist/chunk-3QETM5NG.js.map +1 -0
  37. package/dist/{chunk-ZQUAVZNG.js → chunk-54RCE5Z3.js} +7 -4
  38. package/dist/chunk-54RCE5Z3.js.map +1 -0
  39. package/dist/{chunk-NOU77OHX.js → chunk-5DIKZKOD.js} +2 -2
  40. package/dist/{chunk-CGPHMNL4.js → chunk-5OYHJIJN.js} +10 -6
  41. package/dist/chunk-5OYHJIJN.js.map +1 -0
  42. package/dist/{chunk-LUCARK4W.js → chunk-6U7TES2M.js} +29 -28
  43. package/dist/chunk-6U7TES2M.js.map +1 -0
  44. package/dist/{chunk-FFUCCKPN.js → chunk-7FPJFCXL.js} +10 -7
  45. package/dist/chunk-7FPJFCXL.js.map +1 -0
  46. package/dist/{chunk-PMAQRUN4.js → chunk-CILX2XW7.js} +5 -2
  47. package/dist/chunk-CILX2XW7.js.map +1 -0
  48. package/dist/{chunk-ZVHRSR2R.js → chunk-ET5HXSQL.js} +6 -3
  49. package/dist/chunk-ET5HXSQL.js.map +1 -0
  50. package/dist/{chunk-KSJCXXOU.js → chunk-FAGERSH2.js} +6 -3
  51. package/dist/chunk-FAGERSH2.js.map +1 -0
  52. package/dist/{chunk-FYWUNVFZ.js → chunk-IDIXGGDN.js} +6 -6
  53. package/dist/{chunk-CX77GNMB.js → chunk-IWMGBNXY.js} +6 -3
  54. package/dist/chunk-IWMGBNXY.js.map +1 -0
  55. package/dist/{chunk-GGL34GCW.js → chunk-IZLTOS5L.js} +7 -4
  56. package/dist/chunk-IZLTOS5L.js.map +1 -0
  57. package/dist/{chunk-HHNSLPX7.js → chunk-K7PAILHO.js} +10 -9
  58. package/dist/chunk-K7PAILHO.js.map +1 -0
  59. package/dist/{chunk-UZYLX7M6.js → chunk-LV32K4OP.js} +9 -6
  60. package/dist/chunk-LV32K4OP.js.map +1 -0
  61. package/dist/{chunk-HJWQJUKQ.js → chunk-NDYQIN6C.js} +3 -3
  62. package/dist/{chunk-DKT3X5C3.js → chunk-PEF2XOIV.js} +7 -4
  63. package/dist/chunk-PEF2XOIV.js.map +1 -0
  64. package/dist/{chunk-646B5ERJ.js → chunk-PKO5NJ65.js} +51 -48
  65. package/dist/chunk-PKO5NJ65.js.map +1 -0
  66. package/dist/{chunk-QZHF4BWN.js → chunk-Q5LGXWNG.js} +6 -6
  67. package/dist/{chunk-ESF7TRYJ.js → chunk-SHJGBAIW.js} +37 -2
  68. package/dist/{chunk-ESF7TRYJ.js.map → chunk-SHJGBAIW.js.map} +1 -1
  69. package/dist/{chunk-O4ZIBPIW.js → chunk-T7CGPTFU.js} +3 -3
  70. package/dist/{chunk-PLBIPT6I.js → chunk-TJSQHO4Q.js} +7 -4
  71. package/dist/chunk-TJSQHO4Q.js.map +1 -0
  72. package/dist/{chunk-6TUWSUUD.js → chunk-UF3N7IRP.js} +26 -24
  73. package/dist/chunk-UF3N7IRP.js.map +1 -0
  74. package/dist/{chunk-P3VJCTVE.js → chunk-UH3NYOHN.js} +4 -3
  75. package/dist/chunk-UH3NYOHN.js.map +1 -0
  76. package/dist/{chunk-J6BH2OBA.js → chunk-UK6U5C3N.js} +8 -5
  77. package/dist/chunk-UK6U5C3N.js.map +1 -0
  78. package/dist/{chunk-OTQE66IX.js → chunk-V5OVSGB6.js} +6 -3
  79. package/dist/chunk-V5OVSGB6.js.map +1 -0
  80. package/dist/{chunk-H3MB3F62.js → chunk-WHQ2JB35.js} +4 -3
  81. package/dist/chunk-WHQ2JB35.js.map +1 -0
  82. package/dist/{chunk-NIZQH6AU.js → chunk-WTTVFSCO.js} +8 -7
  83. package/dist/chunk-WTTVFSCO.js.map +1 -0
  84. package/dist/{chunk-OUITHS6V.js → chunk-Z7J3OAPR.js} +357 -325
  85. package/dist/chunk-Z7J3OAPR.js.map +1 -0
  86. package/dist/{cli-Dt-tuiYH.d.ts → cli-XVpmSoQs.d.ts} +3 -3
  87. package/dist/cli.d.ts +11 -11
  88. package/dist/cli.js +20 -20
  89. package/dist/compounding/engine.d.ts +3 -2
  90. package/dist/compounding/engine.js +2 -1
  91. package/dist/compounding/preference-consolidator.d.ts +1 -1
  92. package/dist/compression-optimizer.d.ts +1 -1
  93. package/dist/config.d.ts +1 -1
  94. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  95. package/dist/connectors/codex-materialize.d.ts +1 -1
  96. package/dist/connectors/index.d.ts +1 -1
  97. package/dist/consolidation-provenance-check.d.ts +1 -1
  98. package/dist/consolidation-undo.d.ts +1 -1
  99. package/dist/contradiction/index.d.ts +2 -2
  100. package/dist/contradiction/index.js +2 -1
  101. package/dist/{contradiction-scan-HWGEOUDS.js → contradiction-scan-OUHMCUBT.js} +3 -2
  102. package/dist/conversation-index/backend.d.ts +1 -1
  103. package/dist/conversation-index/chunker.d.ts +1 -1
  104. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  105. package/dist/conversation-index/indexer.d.ts +1 -1
  106. package/dist/conversation-index/search.d.ts +1 -1
  107. package/dist/day-summary.d.ts +1 -1
  108. package/dist/delinearize.d.ts +1 -1
  109. package/dist/direct-answer-wiring.d.ts +1 -1
  110. package/dist/direct-answer.d.ts +1 -1
  111. package/dist/embedding-fallback.d.ts +1 -1
  112. package/dist/embedding-fallback.js +2 -2
  113. package/dist/enrichment/index.d.ts +1 -1
  114. package/dist/entity-retrieval.d.ts +1 -1
  115. package/dist/entity-retrieval.js +2 -1
  116. package/dist/entity-schema.d.ts +1 -1
  117. package/dist/explicit-capture.d.ts +9 -9
  118. package/dist/explicit-capture.js +2 -1
  119. package/dist/extraction-faithfulness.d.ts +1 -1
  120. package/dist/extraction-judge-telemetry.d.ts +1 -1
  121. package/dist/extraction-judge-training.d.ts +1 -1
  122. package/dist/extraction-judge.d.ts +1 -1
  123. package/dist/extraction.d.ts +1 -1
  124. package/dist/extraction.js +3 -3
  125. package/dist/fallback-llm.d.ts +1 -1
  126. package/dist/{first-start-migration-OOR57AYR.js → first-start-migration-W4U6XDKI.js} +7 -6
  127. package/dist/first-start-migration-W4U6XDKI.js.map +1 -0
  128. package/dist/graph-dashboard-diff.d.ts +1 -1
  129. package/dist/graph-dashboard-key.d.ts +1 -1
  130. package/dist/graph-dashboard-parser.d.ts +1 -1
  131. package/dist/graph-edge-reinforcement.d.ts +1 -1
  132. package/dist/graph-snapshot.d.ts +1 -1
  133. package/dist/graph.d.ts +1 -1
  134. package/dist/identity-continuity.d.ts +1 -1
  135. package/dist/importance.d.ts +1 -1
  136. package/dist/index.d.ts +12 -12
  137. package/dist/index.js +43 -43
  138. package/dist/intent.d.ts +1 -1
  139. package/dist/lcm/engine.d.ts +1 -1
  140. package/dist/lcm/index.d.ts +1 -1
  141. package/dist/lcm/tools.d.ts +1 -1
  142. package/dist/lifecycle.d.ts +1 -1
  143. package/dist/live-connectors-runner.d.ts +1 -1
  144. package/dist/local-llm.d.ts +1 -1
  145. package/dist/local-llm.js +2 -1
  146. package/dist/local-model-endpoint.d.ts +1 -1
  147. package/dist/maintenance/memory-governance.d.ts +1 -1
  148. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  149. package/dist/memory-action-policy.d.ts +1 -1
  150. package/dist/memory-cache.d.ts +1 -1
  151. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  152. package/dist/memory-projection-store.d.ts +1 -1
  153. package/dist/memory-provenance.d.ts +1 -1
  154. package/dist/memory-worth-outcomes.d.ts +1 -1
  155. package/dist/models-json.d.ts +1 -1
  156. package/dist/namespaces/migrate.d.ts +2 -2
  157. package/dist/namespaces/migrate.js +6 -6
  158. package/dist/namespaces/principal.d.ts +1 -1
  159. package/dist/namespaces/principal.js +2 -1
  160. package/dist/namespaces/search.d.ts +1 -1
  161. package/dist/namespaces/search.js +4 -4
  162. package/dist/namespaces/storage.d.ts +2 -2
  163. package/dist/namespaces/storage.js +2 -1
  164. package/dist/native-knowledge.d.ts +1 -1
  165. package/dist/operator-toolkit.d.ts +1 -1
  166. package/dist/operator-toolkit.js +11 -11
  167. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  168. package/dist/orchestration/maintenance.d.ts +2 -2
  169. package/dist/orchestration/maintenance.js +6 -5
  170. package/dist/{orchestrator-B4KjaOtY.d.ts → orchestrator-BXi-gadS.d.ts} +66 -5
  171. package/dist/orchestrator.d.ts +5 -5
  172. package/dist/orchestrator.js +20 -18
  173. package/dist/patterns-cli.d.ts +1 -1
  174. package/dist/policy-runtime.d.ts +1 -1
  175. package/dist/provenance.d.ts +1 -1
  176. package/dist/qmd-recall-cache.d.ts +1 -1
  177. package/dist/qmd.d.ts +1 -1
  178. package/dist/recall-disclosure-escalation.d.ts +1 -1
  179. package/dist/recall-explain-renderer.d.ts +1 -1
  180. package/dist/recall-planner-llm.d.ts +1 -1
  181. package/dist/recall-state.d.ts +1 -1
  182. package/dist/recall-tag-filter.d.ts +1 -1
  183. package/dist/recall-xray-cli.d.ts +1 -1
  184. package/dist/recall-xray-renderer.d.ts +1 -1
  185. package/dist/recall-xray.d.ts +1 -1
  186. package/dist/resolve-auth-token.d.ts +1 -1
  187. package/dist/retrieval-agents.d.ts +1 -1
  188. package/dist/retrieval-tiers.d.ts +1 -1
  189. package/dist/routing/engine.d.ts +1 -1
  190. package/dist/routing/store.d.ts +1 -1
  191. package/dist/schemas.d.ts +22 -22
  192. package/dist/search/embed-helper.d.ts +1 -1
  193. package/dist/search/embed-helper.js +2 -2
  194. package/dist/search/factory.d.ts +1 -1
  195. package/dist/search/factory.js +3 -3
  196. package/dist/search/index.d.ts +1 -1
  197. package/dist/search/index.js +3 -3
  198. package/dist/search/lancedb-backend.d.ts +1 -1
  199. package/dist/search/meilisearch-backend.d.ts +1 -1
  200. package/dist/search/noop-backend.d.ts +1 -1
  201. package/dist/search/orama-backend.d.ts +1 -1
  202. package/dist/search/port.d.ts +1 -1
  203. package/dist/search/remote-backend.d.ts +1 -1
  204. package/dist/{semantic-SLAa_prH.d.ts → semantic-DJR8_DMQ.d.ts} +1 -1
  205. package/dist/{semantic-consolidation-CstTvHPo.d.ts → semantic-consolidation-DeL5grLx.d.ts} +1 -1
  206. package/dist/semantic-consolidation.d.ts +2 -2
  207. package/dist/semantic-rule-verifier.d.ts +1 -1
  208. package/dist/session-observer-bands.d.ts +1 -1
  209. package/dist/session-observer-state.d.ts +1 -1
  210. package/dist/shared-context/manager.d.ts +1 -1
  211. package/dist/signal.d.ts +1 -1
  212. package/dist/storage.d.ts +1 -1
  213. package/dist/summarizer.d.ts +1 -1
  214. package/dist/summarizer.js +3 -2
  215. package/dist/summary-snapshot.d.ts +1 -1
  216. package/dist/temporal-supersession.d.ts +1 -1
  217. package/dist/temporal-validity.d.ts +1 -1
  218. package/dist/threading.d.ts +1 -1
  219. package/dist/tier-migration.d.ts +1 -1
  220. package/dist/tier-routing.d.ts +1 -1
  221. package/dist/{tier-stats-3LYQ3VV5.js → tier-stats-LSM35HZY.js} +5 -2
  222. package/dist/tier-stats-LSM35HZY.js.map +1 -0
  223. package/dist/topics.d.ts +1 -1
  224. package/dist/transcript.d.ts +1 -1
  225. package/dist/transfer/types.d.ts +12 -12
  226. package/dist/trust-score-stage.d.ts +1 -1
  227. package/dist/trust-score.d.ts +1 -1
  228. package/dist/{types-VkxElCHR.d.ts → types-CpFz51Pv.d.ts} +1 -1
  229. package/dist/types.d.ts +1 -1
  230. package/dist/utility-runtime.d.ts +1 -1
  231. package/package.json +2 -2
  232. package/src/access-service.ts +42 -37
  233. package/src/active-memory-bridge.ts +2 -1
  234. package/src/admin/admin-surfaces.ts +2 -1
  235. package/src/capabilities.test.ts +178 -0
  236. package/src/capabilities.ts +197 -0
  237. package/src/cli.ts +13 -9
  238. package/src/compounding/engine.ts +4 -3
  239. package/src/contradiction/contradiction-scan.ts +4 -3
  240. package/src/embedding-fallback.ts +5 -2
  241. package/src/entity-retrieval.ts +3 -2
  242. package/src/explicit-capture.ts +2 -1
  243. package/src/extraction.ts +6 -3
  244. package/src/local-llm.ts +4 -3
  245. package/src/maintenance/first-start-migration.ts +6 -3
  246. package/src/maintenance/namespace-maintenance-fanout.ts +2 -1
  247. package/src/maintenance/namespace-planner.ts +4 -3
  248. package/src/maintenance/tier-stats.ts +2 -1
  249. package/src/namespaces/catalog.ts +2 -1
  250. package/src/namespaces/migrate.ts +2 -1
  251. package/src/namespaces/principal.ts +6 -5
  252. package/src/namespaces/scope-profiles.ts +2 -1
  253. package/src/namespaces/search.ts +2 -1
  254. package/src/namespaces/storage.ts +4 -3
  255. package/src/operator-toolkit.ts +19 -18
  256. package/src/orchestration/maintenance.ts +8 -4
  257. package/src/orchestration/semantic-consolidation-coordinator.ts +454 -0
  258. package/src/orchestration/tier-migration-coordinator.ts +5 -4
  259. package/src/orchestrator.ts +78 -417
  260. package/src/scopes/scope-plan.ts +3 -2
  261. package/src/search/embed-helper.ts +5 -2
  262. package/src/search/factory.ts +9 -6
  263. package/src/summarizer.ts +3 -2
  264. package/dist/chunk-24D66MMN.js.map +0 -1
  265. package/dist/chunk-646B5ERJ.js.map +0 -1
  266. package/dist/chunk-6TUWSUUD.js.map +0 -1
  267. package/dist/chunk-CGPHMNL4.js.map +0 -1
  268. package/dist/chunk-CX77GNMB.js.map +0 -1
  269. package/dist/chunk-DKT3X5C3.js.map +0 -1
  270. package/dist/chunk-FFUCCKPN.js.map +0 -1
  271. package/dist/chunk-GGL34GCW.js.map +0 -1
  272. package/dist/chunk-H3MB3F62.js.map +0 -1
  273. package/dist/chunk-HHNSLPX7.js.map +0 -1
  274. package/dist/chunk-J6BH2OBA.js.map +0 -1
  275. package/dist/chunk-KQYGNGON.js.map +0 -1
  276. package/dist/chunk-KSJCXXOU.js.map +0 -1
  277. package/dist/chunk-LUCARK4W.js.map +0 -1
  278. package/dist/chunk-NIZQH6AU.js.map +0 -1
  279. package/dist/chunk-OTQE66IX.js.map +0 -1
  280. package/dist/chunk-OUITHS6V.js.map +0 -1
  281. package/dist/chunk-P3VJCTVE.js.map +0 -1
  282. package/dist/chunk-PLBIPT6I.js.map +0 -1
  283. package/dist/chunk-PMAQRUN4.js.map +0 -1
  284. package/dist/chunk-UZYLX7M6.js.map +0 -1
  285. package/dist/chunk-ZQUAVZNG.js.map +0 -1
  286. package/dist/chunk-ZVHRSR2R.js.map +0 -1
  287. package/dist/first-start-migration-OOR57AYR.js.map +0 -1
  288. package/dist/tier-stats-3LYQ3VV5.js.map +0 -1
  289. /package/dist/{chunk-NOU77OHX.js.map → chunk-5DIKZKOD.js.map} +0 -0
  290. /package/dist/{chunk-FYWUNVFZ.js.map → chunk-IDIXGGDN.js.map} +0 -0
  291. /package/dist/{chunk-HJWQJUKQ.js.map → chunk-NDYQIN6C.js.map} +0 -0
  292. /package/dist/{chunk-QZHF4BWN.js.map → chunk-Q5LGXWNG.js.map} +0 -0
  293. /package/dist/{chunk-O4ZIBPIW.js.map → chunk-T7CGPTFU.js.map} +0 -0
  294. /package/dist/{contradiction-scan-HWGEOUDS.js.map → contradiction-scan-OUHMCUBT.js.map} +0 -0
@@ -404,3 +404,200 @@ export function resolveCreationMemoryCapabilities(
404
404
  commitmentLifecycle: config.commitmentLifecycleEnabled,
405
405
  });
406
406
  }
407
+
408
+ // ---------------------------------------------------------------------------
409
+ // Namespace capability set (issue #1523 batch 5).
410
+ //
411
+ // `namespacesEnabled` is the single most-scattered config flag in the codebase
412
+ // (101 read sites outside config.ts across 18 files — orchestrator, access-service,
413
+ // namespace modules, maintenance, CLI, admin). It gates whether the multi-namespace
414
+ // system is active at all: every namespace resolution, storage path, recall budget,
415
+ // and maintenance fanout checks it. Like the other projections above it gets its own
416
+ // resolver invoked ONCE per operation entry rather than re-derived at each site.
417
+ //
418
+ // The field is a non-optional boolean in PluginConfig, so no coercion is needed.
419
+ // ---------------------------------------------------------------------------
420
+
421
+ /**
422
+ * Frozen projection of namespace feature gates (issue #1523 batch 5).
423
+ *
424
+ * Every field is `readonly boolean`. Composition lives ONLY in
425
+ * {@link resolveNamespaceCapabilities}.
426
+ */
427
+ export interface NamespaceCapabilitySet {
428
+ /** `namespacesEnabled` — multi-namespace system master switch. */
429
+ readonly namespaces: boolean;
430
+ }
431
+
432
+ /**
433
+ * Config projection consumed by {@link resolveNamespaceCapabilities}.
434
+ */
435
+ export type NamespaceConfigProjection = Pick<PluginConfig, "namespacesEnabled">;
436
+
437
+ /**
438
+ * Resolve the {@link NamespaceCapabilitySet} from parsed config.
439
+ *
440
+ * Call this ONCE at operation entry and thread the result down. The flag is a
441
+ * non-optional boolean so the projection is a pure pass-through.
442
+ */
443
+ export function resolveNamespaceCapabilities(
444
+ config: NamespaceConfigProjection,
445
+ ): NamespaceCapabilitySet {
446
+ return Object.freeze({
447
+ namespaces: config.namespacesEnabled,
448
+ });
449
+ }
450
+
451
+ // ---------------------------------------------------------------------------
452
+ // QMD capability set (issue #1523 batch 6).
453
+ //
454
+ // The twelve QMD (query-managed database) flags are the largest remaining
455
+ // scattered cluster after batch 5. They gate every aspect of the tiered
456
+ // memory system: master switch, tier migration, cold tier, daemon, auto-embed,
457
+ // maintenance, query rerank, intent hints, explain, auto-upgrade, and parity
458
+ // graph. Read sites span orchestrator, operator-toolkit, access-service, and
459
+ // search/factory. All flags are non-optional booleans on PluginConfig (defaults
460
+ // resolved at the parse boundary), so the projection is pure pass-through.
461
+ // ---------------------------------------------------------------------------
462
+
463
+ /**
464
+ * Frozen projection of QMD feature gates (issue #1523 batch 6).
465
+ *
466
+ * Every field is `readonly boolean`. Composition lives ONLY in
467
+ * {@link resolveQmdCapabilities}.
468
+ */
469
+ export interface QmdCapabilitySet {
470
+ /** `qmdEnabled` — QMD tiered-memory master switch. */
471
+ readonly qmd: boolean;
472
+ /** `qmdTierMigrationEnabled` — automatic tier promotion/demotion. */
473
+ readonly qmdTierMigration: boolean;
474
+ /** `qmdTierAutoBackfillEnabled` — backfill stale tier entries. */
475
+ readonly qmdTierAutoBackfill: boolean;
476
+ /** `qmdAutoEmbedEnabled` — auto-embed documents on write. */
477
+ readonly qmdAutoEmbed: boolean;
478
+ /** `qmdMaintenanceEnabled` — QMD maintenance pass runner. */
479
+ readonly qmdMaintenance: boolean;
480
+ /** `qmdColdTierEnabled` — cold-tier storage. */
481
+ readonly qmdColdTier: boolean;
482
+ /** `qmdDaemonEnabled` — background QMD daemon. */
483
+ readonly qmdDaemon: boolean;
484
+ /** `qmdTierParityGraphEnabled` — tier parity graph. */
485
+ readonly qmdTierParityGraph: boolean;
486
+ /** `qmdQueryRerankEnabled` — QMD query reranking. */
487
+ readonly qmdQueryRerank: boolean;
488
+ /** `qmdIntentHintsEnabled` — QMD intent hint extraction. */
489
+ readonly qmdIntentHints: boolean;
490
+ /** `qmdExplainEnabled` — QMD explain output. */
491
+ readonly qmdExplain: boolean;
492
+ /** `qmdAutoUpgradeEnabled` — QMD auto-upgrade tiers. */
493
+ readonly qmdAutoUpgrade: boolean;
494
+ }
495
+
496
+ /**
497
+ * Config projection consumed by {@link resolveQmdCapabilities}.
498
+ */
499
+ export type QmdConfigProjection = Pick<
500
+ PluginConfig,
501
+ | "qmdEnabled"
502
+ | "qmdTierMigrationEnabled"
503
+ | "qmdTierAutoBackfillEnabled"
504
+ | "qmdAutoEmbedEnabled"
505
+ | "qmdMaintenanceEnabled"
506
+ | "qmdColdTierEnabled"
507
+ | "qmdDaemonEnabled"
508
+ | "qmdTierParityGraphEnabled"
509
+ | "qmdQueryRerankEnabled"
510
+ | "qmdIntentHintsEnabled"
511
+ | "qmdExplainEnabled"
512
+ | "qmdAutoUpgradeEnabled"
513
+ >;
514
+
515
+ /**
516
+ * Resolve the {@link QmdCapabilitySet} from parsed config.
517
+ *
518
+ * Call this ONCE at operation entry and thread the result down. Eleven flags
519
+ * are non-optional booleans (pure pass-through); `qmdColdTierEnabled` is
520
+ * optional and coerced with `=== true` (matching the pre-migration call sites).
521
+ */
522
+ export function resolveQmdCapabilities(config: QmdConfigProjection): QmdCapabilitySet {
523
+ return Object.freeze({
524
+ qmd: config.qmdEnabled,
525
+ qmdTierMigration: config.qmdTierMigrationEnabled,
526
+ qmdTierAutoBackfill: config.qmdTierAutoBackfillEnabled,
527
+ qmdAutoEmbed: config.qmdAutoEmbedEnabled,
528
+ qmdMaintenance: config.qmdMaintenanceEnabled,
529
+ qmdColdTier: config.qmdColdTierEnabled === true,
530
+ qmdDaemon: config.qmdDaemonEnabled,
531
+ qmdTierParityGraph: config.qmdTierParityGraphEnabled,
532
+ qmdQueryRerank: config.qmdQueryRerankEnabled,
533
+ qmdIntentHints: config.qmdIntentHintsEnabled,
534
+ qmdExplain: config.qmdExplainEnabled,
535
+ qmdAutoUpgrade: config.qmdAutoUpgradeEnabled,
536
+ });
537
+ }
538
+
539
+ // ---------------------------------------------------------------------------
540
+ // Identity-continuity capability set (issue #1523 batch 6).
541
+ //
542
+ // `identityContinuityEnabled` gates the identity/continuity system (agent
543
+ // identity tracking, continuity incident logging). Its 13 read sites span
544
+ // orchestrator, access-service, and CLI. The flag is a non-optional boolean
545
+ // on PluginConfig, so the projection is a pure pass-through.
546
+ // ---------------------------------------------------------------------------
547
+
548
+ /**
549
+ * Frozen projection of identity-continuity feature gates (issue #1523 batch 6).
550
+ */
551
+ export interface IdentityContinuityCapabilitySet {
552
+ /** `identityContinuityEnabled` — identity-continuity master switch. */
553
+ readonly identityContinuity: boolean;
554
+ }
555
+
556
+ /**
557
+ * Config projection consumed by {@link resolveIdentityContinuityCapabilities}.
558
+ */
559
+ export type IdentityContinuityConfigProjection = Pick<PluginConfig, "identityContinuityEnabled">;
560
+
561
+ /**
562
+ * Resolve the {@link IdentityContinuityCapabilitySet} from parsed config.
563
+ */
564
+ export function resolveIdentityContinuityCapabilities(
565
+ config: IdentityContinuityConfigProjection,
566
+ ): IdentityContinuityCapabilitySet {
567
+ return Object.freeze({
568
+ identityContinuity: config.identityContinuityEnabled,
569
+ });
570
+ }
571
+
572
+ // ---------------------------------------------------------------------------
573
+ // Local-LLM capability set (issue #1523 batch 6).
574
+ //
575
+ // `localLlmEnabled` gates whether a local (on-device) LLM is used for
576
+ // summarization, embedding fallback, extraction, and search. Its 11 read
577
+ // sites span orchestrator, extraction, embedding-fallback, local-llm,
578
+ // search/embed-helper, and summarizer. The flag is a non-optional boolean.
579
+ // ---------------------------------------------------------------------------
580
+
581
+ /**
582
+ * Frozen projection of local-LLM feature gates (issue #1523 batch 6).
583
+ */
584
+ export interface LocalLlmCapabilitySet {
585
+ /** `localLlmEnabled` — local (on-device) LLM master switch. */
586
+ readonly localLlm: boolean;
587
+ }
588
+
589
+ /**
590
+ * Config projection consumed by {@link resolveLocalLlmCapabilities}.
591
+ */
592
+ export type LocalLlmConfigProjection = Pick<PluginConfig, "localLlmEnabled">;
593
+
594
+ /**
595
+ * Resolve the {@link LocalLlmCapabilitySet} from parsed config.
596
+ */
597
+ export function resolveLocalLlmCapabilities(
598
+ config: LocalLlmConfigProjection,
599
+ ): LocalLlmCapabilitySet {
600
+ return Object.freeze({
601
+ localLlm: config.localLlmEnabled,
602
+ });
603
+ }
package/src/cli.ts CHANGED
@@ -4,7 +4,11 @@ import { access, lstat, readFile, readdir, realpath, unlink } from "node:fs/prom
4
4
  import { createHash } from "node:crypto";
5
5
  import type { Readable, Writable } from "node:stream";
6
6
  import type { Orchestrator } from "./orchestrator.js";
7
- import { resolveMemoryLifecycleCapabilities } from "./capabilities.js";
7
+ import {
8
+ resolveNamespaceCapabilities,
9
+ resolveMemoryLifecycleCapabilities,
10
+ resolveIdentityContinuityCapabilities,
11
+ } from "./capabilities.js";
8
12
  import { ThreadingManager } from "./threading.js";
9
13
  import { utcDayRange } from "./transcript.js";
10
14
  import { runWearablesCliCommand } from "./wearables/cli.js";
@@ -2361,7 +2365,7 @@ export function hasDestructivePurgeFailures(
2361
2365
 
2362
2366
  function resolvePolicySignalNamespaces(orchestrator: PolicyTuningCliOrchestrator): string[] {
2363
2367
  const names = new Set<string>([orchestrator.config.defaultNamespace]);
2364
- if (orchestrator.config.namespacesEnabled) {
2368
+ if (resolveNamespaceCapabilities(orchestrator.config).namespaces) {
2365
2369
  names.add(orchestrator.config.sharedNamespace);
2366
2370
  for (const policy of orchestrator.config.namespacePolicies) {
2367
2371
  if (policy?.name) names.add(policy.name);
@@ -2520,7 +2524,7 @@ function resolveAuditNamespaces(
2520
2524
  }
2521
2525
 
2522
2526
  const names = new Set<string>([orchestrator.config.defaultNamespace]);
2523
- if (orchestrator.config.namespacesEnabled) {
2527
+ if (resolveNamespaceCapabilities(orchestrator.config).namespaces) {
2524
2528
  names.add(orchestrator.config.sharedNamespace);
2525
2529
  for (const policy of orchestrator.config.namespacePolicies) {
2526
2530
  if (policy?.name) names.add(policy.name);
@@ -3319,7 +3323,7 @@ export async function resolveMemoryDirForNamespace(
3319
3323
  const ns = (namespace ?? "").trim();
3320
3324
  if (!ns) return orchestrator.config.memoryDir;
3321
3325
  assertSafeNamespaceSegment(ns);
3322
- if (!orchestrator.config.namespacesEnabled) {
3326
+ if (!resolveNamespaceCapabilities(orchestrator.config).namespaces) {
3323
3327
  if (options?.rejectUnsupportedOverride && ns !== orchestrator.config.defaultNamespace) {
3324
3328
  throw new Error(`namespaces are disabled; cannot target namespace: ${ns}`);
3325
3329
  }
@@ -7858,7 +7862,7 @@ export function registerCli(
7858
7862
  .option("--state <state>", "Filter by state: open|closed|all", "open")
7859
7863
  .option("--limit <number>", "Maximum incidents to list", "25")
7860
7864
  .action(async (...args: unknown[]) => {
7861
- if (!orchestrator.config.identityContinuityEnabled) {
7865
+ if (!resolveIdentityContinuityCapabilities(orchestrator.config).identityContinuity) {
7862
7866
  console.log("Identity continuity is disabled.");
7863
7867
  return;
7864
7868
  }
@@ -7886,7 +7890,7 @@ export function registerCli(
7886
7890
  .option("--trigger-window <window>", "Optional incident trigger window")
7887
7891
  .option("--suspected-cause <text>", "Optional suspected cause")
7888
7892
  .action(async (...args: unknown[]) => {
7889
- if (!orchestrator.config.identityContinuityEnabled) {
7893
+ if (!resolveIdentityContinuityCapabilities(orchestrator.config).identityContinuity) {
7890
7894
  console.log("Identity continuity is disabled.");
7891
7895
  return;
7892
7896
  }
@@ -7917,7 +7921,7 @@ export function registerCli(
7917
7921
  .option("--verification-result <text>", "Required verification result")
7918
7922
  .option("--preventive-rule <text>", "Optional preventive rule")
7919
7923
  .action(async (...args: unknown[]) => {
7920
- if (!orchestrator.config.identityContinuityEnabled) {
7924
+ if (!resolveIdentityContinuityCapabilities(orchestrator.config).identityContinuity) {
7921
7925
  console.log("Identity continuity is disabled.");
7922
7926
  return;
7923
7927
  }
@@ -8507,7 +8511,7 @@ export function registerCli(
8507
8511
  mergedContent: cmdOpts.mergedContent,
8508
8512
  storageForNamespace: (namespace) => {
8509
8513
  const requested = namespace?.trim();
8510
- if (!orchestrator.config.namespacesEnabled) {
8514
+ if (!resolveNamespaceCapabilities(orchestrator.config).namespaces) {
8511
8515
  if (requested && requested !== orchestrator.config.defaultNamespace) {
8512
8516
  throw new Error(`unsupported namespace: ${requested}`);
8513
8517
  }
@@ -8554,7 +8558,7 @@ export function registerCli(
8554
8558
  storageForNamespace: async (namespace) => {
8555
8559
  const resolvedNamespace =
8556
8560
  namespace?.trim() ||
8557
- (orchestrator.config.namespacesEnabled ? orchestrator.config.defaultNamespace : undefined);
8561
+ (resolveNamespaceCapabilities(orchestrator.config).namespaces ? orchestrator.config.defaultNamespace : undefined);
8558
8562
  const storage = await orchestrator.getStorageForNamespace(resolvedNamespace);
8559
8563
  return { storage, namespace: resolvedNamespace };
8560
8564
  },
@@ -7,6 +7,7 @@ import { StorageManager } from "../storage.js";
7
7
  import type { ContinuityIncidentRecord, PluginConfig } from "../types.js";
8
8
  import { resolveSharedContextDir, SharedFeedbackEntrySchema, type SharedFeedbackEntry } from "../shared-context/manager.js";
9
9
  import { parseContinuityImprovementLoops } from "../identity-continuity.js";
10
+ import { resolveQmdCapabilities, type QmdConfigProjection } from "../capabilities.js";
10
11
 
11
12
  type MistakesFile = {
12
13
  version?: number;
@@ -369,7 +370,7 @@ export interface TierMigrationCycleBudget {
369
370
  }
370
371
 
371
372
  export function defaultTierMigrationCycleBudget(
372
- config: Pick<PluginConfig, "qmdTierAutoBackfillEnabled">,
373
+ config: QmdConfigProjection,
373
374
  trigger: TierMigrationCycleTrigger,
374
375
  ): TierMigrationCycleBudget {
375
376
  if (trigger === "extraction") {
@@ -380,11 +381,11 @@ export function defaultTierMigrationCycleBudget(
380
381
  minIntervalMs: 60_000,
381
382
  };
382
383
  }
383
- const limit = config.qmdTierAutoBackfillEnabled ? 200 : 50;
384
+ const limit = resolveQmdCapabilities(config).qmdTierAutoBackfill ? 200 : 50;
384
385
  return {
385
386
  limit,
386
387
  scanLimit: limit * 4,
387
- minIntervalMs: config.qmdTierAutoBackfillEnabled ? 120_000 : 300_000,
388
+ minIntervalMs: resolveQmdCapabilities(config).qmdTierAutoBackfill ? 120_000 : 300_000,
388
389
  };
389
390
  }
390
391
 
@@ -14,6 +14,7 @@
14
14
  * 4. Cap per-run work at maxPairsPerRun.
15
15
  */
16
16
 
17
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
17
18
  import type { StorageManager } from "../storage.js";
18
19
  import type { PluginConfig, MemoryFile, MemoryStatus } from "../types.js";
19
20
  import type { SemanticDedupLookup } from "../dedup/semantic.js";
@@ -107,7 +108,7 @@ export async function runContradictionScan(deps: ScanDependencies): Promise<Scan
107
108
  }
108
109
 
109
110
  const { storage: scanStorage, namespace } = await resolveScanStorage(deps, requestedNamespace);
110
- if (config.namespacesEnabled && namespace !== undefined && isDefaultNamespaceScan(config, requestedNamespace, namespace)) {
111
+ if (resolveNamespaceCapabilities(config).namespaces && namespace !== undefined && isDefaultNamespaceScan(config, requestedNamespace, namespace)) {
111
112
  const migrated = migrateUnscopedPairsToNamespace(memoryDir, namespace, { cooldownDays: scanConfig.cooldownDays });
112
113
  if (migrated > 0) {
113
114
  log.info("[contradiction-scan] migrated %d legacy unscoped review pairs to namespace %s", migrated, namespace);
@@ -382,7 +383,7 @@ async function resolveScanStorage(
382
383
  deps: ScanDependencies,
383
384
  namespace: string | undefined,
384
385
  ): Promise<ScanStorageResolution> {
385
- if (!deps.config.namespacesEnabled) {
386
+ if (!resolveNamespaceCapabilities(deps.config).namespaces) {
386
387
  const defaultNamespace = normalizeScanNamespace(deps.config.defaultNamespace);
387
388
  if (namespace && namespace !== defaultNamespace) {
388
389
  throw new Error(`unsupported namespace: ${namespace}`);
@@ -427,7 +428,7 @@ function isStorageManagerLike(value: unknown): value is StorageManager {
427
428
 
428
429
  function fallbackResolvedNamespace(deps: ScanDependencies, namespace: string | undefined): string | undefined {
429
430
  if (namespace) return namespace;
430
- return deps.config.namespacesEnabled ? deps.config.defaultNamespace : undefined;
431
+ return resolveNamespaceCapabilities(deps.config).namespaces ? deps.config.defaultNamespace : undefined;
431
432
  }
432
433
 
433
434
  function isDefaultNamespaceScan(
@@ -1,7 +1,10 @@
1
1
  import path from "node:path";
2
2
  import { mkdir, readFile, rename, rm, writeFile } from "node:fs/promises";
3
3
  import { log } from "./logger.js";
4
- import { resolveMemoryLifecycleCapabilities } from "./capabilities.js";
4
+ import {
5
+ resolveMemoryLifecycleCapabilities,
6
+ resolveLocalLlmCapabilities,
7
+ } from "./capabilities.js";
5
8
  import { readEnvVar } from "./runtime/env.js";
6
9
  import type { PluginConfig } from "./types.js";
7
10
  import {
@@ -461,7 +464,7 @@ export class EmbeddingFallback {
461
464
  }
462
465
 
463
466
  private createLocalProvider(): ProviderConfig | null {
464
- if (!this.config.localLlmEnabled || !this.config.localLlmUrl) return null;
467
+ if (!resolveLocalLlmCapabilities(this.config).localLlm || !this.config.localLlmUrl) return null;
465
468
  const base = this.config.localLlmUrl.replace(/\/$/, "");
466
469
  const endpoint = /\/v1$/i.test(base) ? `${base}/embeddings` : `${base}/v1/embeddings`;
467
470
  const headers: Record<string, string> = {
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "./capabilities.js";
1
2
  import { createHash } from "node:crypto";
2
3
  import { sanitizeMemoryContent } from "./sanitize.js";
3
4
  import { mkdir, readFile, writeFile } from "node:fs/promises";
@@ -329,7 +330,7 @@ async function readNativeChunks(
329
330
  workspaceDir: config.workspaceDir,
330
331
  memoryDir: config.memoryDir,
331
332
  config: config.nativeKnowledge,
332
- recallNamespaces: config.namespacesEnabled ? recallNamespaces : undefined,
333
+ recallNamespaces: resolveNamespaceCapabilities(config).namespaces ? recallNamespaces : undefined,
333
334
  defaultNamespace: config.defaultNamespace,
334
335
  }).catch(() => []);
335
336
  }
@@ -341,7 +342,7 @@ async function resolveEntityIndexStorages(
341
342
  namespaceStorage?: (namespace: string) => Promise<StorageManager>,
342
343
  ): Promise<StorageManager[]> {
343
344
  if (
344
- !config.namespacesEnabled ||
345
+ !resolveNamespaceCapabilities(config).namespaces ||
345
346
  !namespaceStorage ||
346
347
  !recallNamespaces ||
347
348
  recallNamespaces.length === 0
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "./capabilities.js";
1
2
  import { randomUUID } from "node:crypto";
2
3
  import type { Orchestrator } from "./orchestrator.js";
3
4
  import { isSafeRouteNamespace } from "./routing/engine.js";
@@ -175,7 +176,7 @@ function resolveExplicitCaptureNamespace(
175
176
  ): string | undefined {
176
177
  const normalized = asTrimmed(namespace);
177
178
  if (!normalized) return undefined;
178
- if (!orchestrator.config.namespacesEnabled) {
179
+ if (!resolveNamespaceCapabilities(orchestrator.config).namespaces) {
179
180
  if (normalized !== orchestrator.config.defaultNamespace) {
180
181
  throw new Error(`unsupported namespace: ${normalized}`);
181
182
  }
package/src/extraction.ts CHANGED
@@ -38,7 +38,10 @@ import { normalizeProcedureSteps } from "./procedural/procedure-types.js";
38
38
  import { normalizeReasoningTrace } from "./reasoning-trace-types.js";
39
39
  import { looksLikeMechanicalTelemetryTranscript } from "./telemetry-transcript.js";
40
40
  import { buildFactProvenance, type ProvenanceTurnInput } from "./provenance.js";
41
- import { resolveMemoryLifecycleCapabilities } from "./capabilities.js";
41
+ import {
42
+ resolveMemoryLifecycleCapabilities,
43
+ resolveLocalLlmCapabilities,
44
+ } from "./capabilities.js";
42
45
 
43
46
  type ExtractionQuestion = ExtractionResult["questions"][number];
44
47
  type ExtractedFactResult = ExtractionResult["facts"][number];
@@ -152,7 +155,7 @@ export class ExtractionEngine {
152
155
  * Disabled when gateway model source is active (gateway chain replaces local).
153
156
  */
154
157
  private get shouldUseLocalLlm(): boolean {
155
- return this.config.localLlmEnabled && !this.useGatewayModelSource;
158
+ return resolveLocalLlmCapabilities(this.config).localLlm && !this.useGatewayModelSource;
156
159
  }
157
160
 
158
161
  /**
@@ -1114,7 +1117,7 @@ export class ExtractionEngine {
1114
1117
  // --- profiling instrumentation ---
1115
1118
  const extractionTraceId = this.profiler.startTrace("extraction", undefined, {
1116
1119
  model: this.config.model,
1117
- localLlm: this.config.localLlmEnabled,
1120
+ localLlm: resolveLocalLlmCapabilities(this.config).localLlm,
1118
1121
  });
1119
1122
  this.profiler.startSpan("total", extractionTraceId);
1120
1123
 
package/src/local-llm.ts CHANGED
@@ -5,6 +5,7 @@ import os from "node:os";
5
5
  import type { ModelRegistry } from "./model-registry.js";
6
6
  import { launchProcessSync } from "./runtime/child-process.js";
7
7
  import { mergeEnv, readEnvVar } from "./runtime/env.js";
8
+ import { resolveLocalLlmCapabilities } from "./capabilities.js";
8
9
 
9
10
  /** Trim trailing slash characters without backtracking regex. */
10
11
  function trimTrailingSlashes(s: string): string {
@@ -934,7 +935,7 @@ export class LocalLlmClient {
934
935
  queueMeta?: { priority: LocalLlmRequestPriority; enqueuedAtMs: number },
935
936
  ): Promise<LocalLlmChatCompletionResult | null> {
936
937
  log.debug(
937
- `local LLM chatCompletion: localLlmEnabled=${this.config.localLlmEnabled}, model=${this.config.localLlmModel}`,
938
+ `local LLM chatCompletion: localLlmEnabled=${resolveLocalLlmCapabilities(this.config).localLlm}, model=${this.config.localLlmModel}`,
938
939
  );
939
940
 
940
941
  const operation = options.operation ?? "unspecified";
@@ -1389,7 +1390,7 @@ export class LocalLlmClient {
1389
1390
  messages: Array<{ role: string; content: string }>,
1390
1391
  options: LocalLlmChatCompletionOptions = {},
1391
1392
  ): Promise<LocalLlmChatCompletionResult | null> {
1392
- if (!this.config.localLlmEnabled) {
1393
+ if (!resolveLocalLlmCapabilities(this.config).localLlm) {
1393
1394
  log.debug("local LLM: disabled, returning null");
1394
1395
  return null;
1395
1396
  }
@@ -1444,7 +1445,7 @@ export class LocalLlmClient {
1444
1445
  operationName: string
1445
1446
  ): Promise<T> {
1446
1447
  // Try local LLM first if enabled
1447
- if (this.config.localLlmEnabled) {
1448
+ if (resolveLocalLlmCapabilities(this.config).localLlm) {
1448
1449
  const localResult = await localOperation();
1449
1450
  if (localResult !== null) {
1450
1451
  log.debug(`${operationName}: used local LLM`);
@@ -18,7 +18,10 @@
18
18
 
19
19
  import path from "node:path";
20
20
  import { access, mkdir, readFile, unlink, writeFile } from "node:fs/promises";
21
- import { resolveMemoryLifecycleCapabilities } from "../capabilities.js";
21
+ import {
22
+ resolveMemoryLifecycleCapabilities,
23
+ resolveQmdCapabilities,
24
+ } from "../capabilities.js";
22
25
  import type { StorageManager } from "../storage.js";
23
26
  import type { PluginConfig } from "../types.js";
24
27
  import {
@@ -135,7 +138,7 @@ async function clearQmdRefreshPending(memoryDir: string): Promise<void> {
135
138
 
136
139
  async function buildTierRoutingPolicy(config: PluginConfig): Promise<TierRoutingPolicy> {
137
140
  const basePolicy: TierRoutingPolicy = {
138
- enabled: config.qmdTierMigrationEnabled,
141
+ enabled: resolveQmdCapabilities(config).qmdTierMigration,
139
142
  demotionMinAgeDays: config.qmdTierDemotionMinAgeDays,
140
143
  demotionValueThreshold: config.qmdTierDemotionValueThreshold,
141
144
  promotionValueThreshold: config.qmdTierPromotionValueThreshold,
@@ -207,7 +210,7 @@ export async function runFirstStartMigration(
207
210
  };
208
211
  }
209
212
 
210
- if (!config.qmdTierMigrationEnabled) {
213
+ if (!resolveQmdCapabilities(config).qmdTierMigration) {
211
214
  return {
212
215
  skipped: true,
213
216
  skipReason: "qmdTierMigrationEnabled is false",
@@ -24,6 +24,7 @@
24
24
  * - Per-namespace locks prevent duplicate concurrent runs (planner-provided).
25
25
  */
26
26
 
27
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
27
28
  import type { NamespaceCatalog } from "../namespaces/catalog.js";
28
29
  import type { PluginConfig } from "../types.js";
29
30
  import {
@@ -262,7 +263,7 @@ export async function summarizeNamespaceMaintenanceHealth(
262
263
  return {
263
264
  generatedAt,
264
265
  fanoutEnabled: config.maintenanceNamespaceFanoutEnabled !== false,
265
- namespacesEnabled: config.namespacesEnabled,
266
+ namespacesEnabled: resolveNamespaceCapabilities(config).namespaces,
266
267
  maxNamespacesPerCycle: config.maintenanceMaxNamespacesPerCycle,
267
268
  jobs,
268
269
  totalRan,
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
1
2
  import { createHash, randomUUID } from "node:crypto";
2
3
  import type { Dirent } from "node:fs";
3
4
  import { lstat, mkdir, open, readFile, readdir, rename, rm, rmdir, stat, utimes, writeFile } from "node:fs/promises";
@@ -211,7 +212,7 @@ export async function planNamespaceMaintenance(
211
212
  // policies) would make a mutating maintenance job process the SAME corpus
212
213
  // once per configured name. The #1500 contract is "namespaces disabled:
213
214
  // maintain the current default storage only," so collapse to the default.
214
- const configured = config.namespacesEnabled
215
+ const configured = resolveNamespaceCapabilities(config).namespaces
215
216
  ? getConfiguredNamespaces(config)
216
217
  : [config.defaultNamespace.trim()].filter(Boolean);
217
218
  const byNamespace = new Map<string, NamespaceMaintenanceCandidate>();
@@ -226,7 +227,7 @@ export async function planNamespaceMaintenance(
226
227
  });
227
228
  }
228
229
 
229
- if (config.namespacesEnabled && config.maintenanceNamespaceFanoutEnabled !== false) {
230
+ if (resolveNamespaceCapabilities(config).namespaces && config.maintenanceNamespaceFanoutEnabled !== false) {
230
231
  const configuredSet = new Set(configured);
231
232
  try {
232
233
  const records = options.catalog?.enabled ? await options.catalog.listNamespaces() : [];
@@ -267,7 +268,7 @@ export async function planNamespaceMaintenance(
267
268
  detail: error instanceof Error ? error.message : String(error),
268
269
  });
269
270
  }
270
- } else if (config.namespacesEnabled) {
271
+ } else if (resolveNamespaceCapabilities(config).namespaces) {
271
272
  skipped.push({
272
273
  namespace: "*",
273
274
  reason: "fanout_disabled",
@@ -25,6 +25,7 @@ import {
25
25
  type TierRoutingPolicy,
26
26
  type TierTransitionDecision,
27
27
  } from "../tier-routing.js";
28
+ import { resolveQmdCapabilities } from "../capabilities.js";
28
29
  import {
29
30
  applyUtilityPromotionRuntimePolicy,
30
31
  loadUtilityRuntimeValues,
@@ -82,7 +83,7 @@ async function tierRoutingPolicyFromConfig(
82
83
  config: PluginConfig,
83
84
  ): Promise<TierRoutingPolicy> {
84
85
  const basePolicy: TierRoutingPolicy = {
85
- enabled: config.qmdTierMigrationEnabled,
86
+ enabled: resolveQmdCapabilities(config).qmdTierMigration,
86
87
  demotionMinAgeDays: config.qmdTierDemotionMinAgeDays,
87
88
  demotionValueThreshold: config.qmdTierDemotionValueThreshold,
88
89
  promotionValueThreshold: config.qmdTierPromotionValueThreshold,
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
1
2
  import path from "node:path";
2
3
  import type { Dirent } from "node:fs";
3
4
  import {
@@ -181,7 +182,7 @@ const MEMORY_DATA_CHILDREN = [
181
182
  function isCatalogEnabled(config: PluginConfig): boolean {
182
183
  // Inert unless namespaces are enabled. namespaceCatalogEnabled defaults to
183
184
  // true (undefined => enabled) but is only honored when namespacesEnabled.
184
- if (config.namespacesEnabled !== true) return false;
185
+ if (resolveNamespaceCapabilities(config).namespaces !== true) return false;
185
186
  return (config as { namespaceCatalogEnabled?: boolean }).namespaceCatalogEnabled !== false;
186
187
  }
187
188
 
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
1
2
  import path from "node:path";
2
3
  import { access, lstat, mkdir, readdir, realpath, rename, rmdir } from "node:fs/promises";
3
4
  import type { PluginConfig } from "../types.js";
@@ -146,7 +147,7 @@ export async function runNamespaceMigration(options: {
146
147
  dryRun?: boolean;
147
148
  renameFn?: typeof rename;
148
149
  }): Promise<NamespaceMigrationReport> {
149
- if (!options.config.namespacesEnabled) {
150
+ if (!resolveNamespaceCapabilities(options.config).namespaces) {
150
151
  throw new Error("Namespaces are disabled.");
151
152
  }
152
153
 
@@ -1,3 +1,4 @@
1
+ import { resolveNamespaceCapabilities } from "../capabilities.js";
1
2
  import type { PluginConfig } from "../types.js";
2
3
  import { isLikelyUnsafeRegex } from "../routing/engine.js";
3
4
 
@@ -13,7 +14,7 @@ function compileSafePrincipalRegex(pattern: string): RegExp | null {
13
14
  }
14
15
 
15
16
  export function resolvePrincipal(sessionKey: string | undefined, config: PluginConfig): string | undefined {
16
- if (!config.namespacesEnabled) return "default";
17
+ if (!resolveNamespaceCapabilities(config).namespaces) return "default";
17
18
  const sk = typeof sessionKey === "string" && sessionKey.trim().length > 0
18
19
  ? sessionKey
19
20
  : "";
@@ -51,7 +52,7 @@ export function resolvePrincipal(sessionKey: string | undefined, config: PluginC
51
52
  }
52
53
 
53
54
  export function canReadNamespace(principal: string | undefined, namespace: string, config: PluginConfig): boolean {
54
- if (!config.namespacesEnabled) return true;
55
+ if (!resolveNamespaceCapabilities(config).namespaces) return true;
55
56
  if (!principal) return false;
56
57
  const policy = config.namespacePolicies.find((p) => p.name === namespace);
57
58
  if (!policy) return namespace === config.defaultNamespace || namespace === config.sharedNamespace;
@@ -59,7 +60,7 @@ export function canReadNamespace(principal: string | undefined, namespace: strin
59
60
  }
60
61
 
61
62
  export function canWriteNamespace(principal: string | undefined, namespace: string, config: PluginConfig): boolean {
62
- if (!config.namespacesEnabled) return true;
63
+ if (!resolveNamespaceCapabilities(config).namespaces) return true;
63
64
  if (!principal) return false;
64
65
  const policy = config.namespacePolicies.find((p) => p.name === namespace);
65
66
  if (!policy) return namespace === config.defaultNamespace;
@@ -74,7 +75,7 @@ export function canWriteNamespace(principal: string | undefined, namespace: stri
74
75
  * - Otherwise use config.defaultNamespace.
75
76
  */
76
77
  export function defaultNamespaceForPrincipal(principal: string | undefined, config: PluginConfig): string {
77
- if (!config.namespacesEnabled) return config.defaultNamespace;
78
+ if (!resolveNamespaceCapabilities(config).namespaces) return config.defaultNamespace;
78
79
  if (!principal) return config.defaultNamespace;
79
80
  const exists = config.namespacePolicies.some((p) => p.name === principal);
80
81
  return exists ? principal : config.defaultNamespace;
@@ -82,7 +83,7 @@ export function defaultNamespaceForPrincipal(principal: string | undefined, conf
82
83
 
83
84
  export function recallNamespacesForPrincipal(principal: string | undefined, config: PluginConfig): string[] {
84
85
  const out: string[] = [];
85
- if (!config.namespacesEnabled) return [config.defaultNamespace];
86
+ if (!resolveNamespaceCapabilities(config).namespaces) return [config.defaultNamespace];
86
87
  if (!principal) return out;
87
88
 
88
89
  const selfNs = defaultNamespaceForPrincipal(principal, config);