@remnic/core 9.40.0 → 9.42.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (278) hide show
  1. package/dist/access-admin-ops-surface.d.ts +10 -10
  2. package/dist/access-admin-ops-surface.js +5 -4
  3. package/dist/access-authorization-probe.d.ts +10 -10
  4. package/dist/access-authorization-probe.js +6 -5
  5. package/dist/access-boundary.d.ts +10 -10
  6. package/dist/access-boundary.js +5 -4
  7. package/dist/access-cli.js +16 -15
  8. package/dist/access-cli.js.map +1 -1
  9. package/dist/access-extraction-force-flush.d.ts +10 -10
  10. package/dist/access-extraction-force-flush.js +5 -4
  11. package/dist/access-health-types.d.ts +1 -1
  12. package/dist/access-http-lcm-compaction.d.ts +10 -10
  13. package/dist/access-http-lifecycle-flush.d.ts +10 -10
  14. package/dist/access-http.d.ts +10 -10
  15. package/dist/access-http.js +10 -9
  16. package/dist/access-identity-continuity-surface.d.ts +8 -8
  17. package/dist/access-identity-continuity-surface.js +5 -4
  18. package/dist/access-lcm-surface.d.ts +10 -10
  19. package/dist/access-lcm-surface.js +5 -4
  20. package/dist/access-mcp.d.ts +10 -10
  21. package/dist/access-mcp.js +8 -7
  22. package/dist/access-memory-search-fanout.d.ts +2 -2
  23. package/dist/{access-namespace-preflight-BbDJBq0e.d.ts → access-namespace-preflight-47dOyty9.d.ts} +1 -1
  24. package/dist/access-namespace-preflight.d.ts +3 -3
  25. package/dist/access-namespace-preflight.js +5 -4
  26. package/dist/access-observe-write-surface.d.ts +10 -10
  27. package/dist/access-observe-write-surface.js +5 -4
  28. package/dist/access-operations-batch.js +6 -5
  29. package/dist/access-operations.d.ts +13 -13
  30. package/dist/access-operations.js +7 -6
  31. package/dist/access-recall-concurrency.d.ts +10 -10
  32. package/dist/access-recall-concurrency.js +5 -4
  33. package/dist/access-recall-response.d.ts +10 -10
  34. package/dist/access-recall-response.js +5 -4
  35. package/dist/access-recall-surface.d.ts +10 -10
  36. package/dist/access-recall-surface.js +5 -4
  37. package/dist/access-schema.d.ts +84 -84
  38. package/dist/{access-service-B2h6rITp.d.ts → access-service-D1BkxwSf.d.ts} +7 -7
  39. package/dist/access-service-helpers.d.ts +10 -10
  40. package/dist/access-service.d.ts +10 -10
  41. package/dist/access-service.js +5 -4
  42. package/dist/access-surface-catalog.d.ts +10 -10
  43. package/dist/access-wearables-meetings-surface.d.ts +3 -3
  44. package/dist/action-confidence.d.ts +1 -1
  45. package/dist/active-memory-bridge.d.ts +1 -1
  46. package/dist/active-recall.d.ts +1 -1
  47. package/dist/active-recall.js +2 -2
  48. package/dist/behavior-learner.d.ts +1 -1
  49. package/dist/behavior-signals.d.ts +1 -1
  50. package/dist/bootstrap.d.ts +8 -8
  51. package/dist/briefing.d.ts +2 -2
  52. package/dist/buffer-surprise-report.d.ts +1 -1
  53. package/dist/buffer-turn-helpers.d.ts +1 -1
  54. package/dist/buffer.d.ts +2 -2
  55. package/dist/bulk-import/index.d.ts +3 -3
  56. package/dist/calibration.d.ts +1 -1
  57. package/dist/capabilities.d.ts +1 -1
  58. package/dist/{catalog-Bz2LxGNb.d.ts → catalog-DPQynQZG.d.ts} +1 -1
  59. package/dist/causal-behavior.d.ts +1 -1
  60. package/dist/causal-consolidation.d.ts +1 -1
  61. package/dist/causal-trajectory-graph.d.ts +1 -1
  62. package/dist/{chunk-443XCR34.js → chunk-3SG4FGDV.js} +53 -41
  63. package/dist/chunk-3SG4FGDV.js.map +1 -0
  64. package/dist/{chunk-XPQ5ZTL6.js → chunk-6I2C3EOH.js} +6 -6
  65. package/dist/chunk-7VIB7PAE.js +142 -0
  66. package/dist/chunk-7VIB7PAE.js.map +1 -0
  67. package/dist/{chunk-AYICY7IE.js → chunk-AXUU7SG3.js} +2 -2
  68. package/dist/{chunk-RK6WMGTX.js → chunk-CQ5MR2HQ.js} +13 -9
  69. package/dist/chunk-CQ5MR2HQ.js.map +1 -0
  70. package/dist/{chunk-KW4ZFTUS.js → chunk-CWPDM66T.js} +5 -5
  71. package/dist/{chunk-NEO4QCID.js → chunk-FHEJ22B7.js} +10 -4
  72. package/dist/chunk-FHEJ22B7.js.map +1 -0
  73. package/dist/{chunk-EBWOOJEP.js → chunk-GDC4INBF.js} +2 -2
  74. package/dist/{chunk-UIVRPXRR.js → chunk-KXGN6G2Y.js} +3 -3
  75. package/dist/chunk-KXGN6G2Y.js.map +1 -0
  76. package/dist/{chunk-AXHMCRS3.js → chunk-OYFDEJZB.js} +23 -6
  77. package/dist/chunk-OYFDEJZB.js.map +1 -0
  78. package/dist/{chunk-SD4A6IZY.js → chunk-PWKZV4A3.js} +2 -2
  79. package/dist/{chunk-XYXYEDPL.js → chunk-Q4XL7LJW.js} +26 -5
  80. package/dist/chunk-Q4XL7LJW.js.map +1 -0
  81. package/dist/{chunk-MOHZIKZM.js → chunk-TM72UOX2.js} +2 -2
  82. package/dist/{chunk-GLBK35BT.js → chunk-UGCUVLOL.js} +14 -10
  83. package/dist/chunk-UGCUVLOL.js.map +1 -0
  84. package/dist/{chunk-Q6QYN56R.js → chunk-UQVGDEAJ.js} +2 -2
  85. package/dist/{chunk-KYYRJVE6.js → chunk-XRWVXPEM.js} +2 -2
  86. package/dist/{cli-CO8qKPM5.d.ts → cli-IUhV-lmk.d.ts} +5 -5
  87. package/dist/cli.d.ts +12 -12
  88. package/dist/cli.js +15 -14
  89. package/dist/compounding/engine.d.ts +2 -2
  90. package/dist/compounding/preference-consolidator.d.ts +1 -1
  91. package/dist/compression-optimizer.d.ts +1 -1
  92. package/dist/config.d.ts +1 -1
  93. package/dist/config.js +2 -2
  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 +2 -2
  98. package/dist/consolidation-undo.d.ts +2 -2
  99. package/dist/contradiction/index.d.ts +2 -2
  100. package/dist/conversation-index/backend.d.ts +1 -1
  101. package/dist/conversation-index/chunker.d.ts +1 -1
  102. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  103. package/dist/conversation-index/indexer.d.ts +1 -1
  104. package/dist/conversation-index/search.d.ts +1 -1
  105. package/dist/corpus-watermark.d.ts +7 -1
  106. package/dist/corpus-watermark.js +2 -2
  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/enrichment/index.d.ts +1 -1
  113. package/dist/entity-retrieval.d.ts +2 -2
  114. package/dist/entity-schema.d.ts +1 -1
  115. package/dist/explicit-capture.d.ts +8 -8
  116. package/dist/extraction-error-classification.d.ts +1 -1
  117. package/dist/extraction-faithfulness.d.ts +1 -1
  118. package/dist/extraction-judge-telemetry.d.ts +1 -1
  119. package/dist/extraction-judge-training.d.ts +1 -1
  120. package/dist/extraction-judge.d.ts +1 -1
  121. package/dist/extraction-liveness.d.ts +1 -1
  122. package/dist/extraction-liveness.js +3 -1
  123. package/dist/extraction-source-grounding-rules.d.ts +1 -1
  124. package/dist/extraction-source-grounding.d.ts +1 -1
  125. package/dist/extraction.d.ts +1 -1
  126. package/dist/fallback-llm.d.ts +1 -1
  127. package/dist/graph-dashboard-diff.d.ts +1 -1
  128. package/dist/graph-dashboard-key.d.ts +1 -1
  129. package/dist/graph-dashboard-parser.d.ts +1 -1
  130. package/dist/graph-edge-reinforcement.d.ts +1 -1
  131. package/dist/graph-snapshot.d.ts +1 -1
  132. package/dist/graph.d.ts +1 -1
  133. package/dist/importance.d.ts +1 -1
  134. package/dist/importers/index.d.ts +1 -1
  135. package/dist/in-flight-reads.d.ts +1 -1
  136. package/dist/index.d.ts +407 -407
  137. package/dist/index.js +16 -15
  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-model-endpoint.d.ts +1 -1
  146. package/dist/maintenance/memory-governance.d.ts +1 -1
  147. package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +2 -2
  148. package/dist/maintenance/rebuild-memory-projection.d.ts +2 -2
  149. package/dist/{maintenance-D2jkiT9r.d.ts → maintenance-DVBLXkFw.d.ts} +3 -3
  150. package/dist/mcp-memory-inspector-app.d.ts +10 -10
  151. package/dist/memory-action-policy.d.ts +1 -1
  152. package/dist/memory-cache.d.ts +1 -1
  153. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  154. package/dist/memory-projection-store.d.ts +1 -1
  155. package/dist/memory-provenance.d.ts +1 -1
  156. package/dist/memory-worth-outcomes.d.ts +2 -2
  157. package/dist/models-json.d.ts +1 -1
  158. package/dist/namespaces/migrate.d.ts +4 -3
  159. package/dist/namespaces/migrate.js +1 -1
  160. package/dist/namespaces/principal.d.ts +1 -1
  161. package/dist/namespaces/search.d.ts +1 -1
  162. package/dist/namespaces/storage.d.ts +3 -3
  163. package/dist/native-knowledge.d.ts +1 -1
  164. package/dist/offline-sync-impression-drain.d.ts +1 -1
  165. package/dist/operator-doctor-corpus.d.ts +1 -1
  166. package/dist/operator-doctor-corpus.js +3 -3
  167. package/dist/operator-doctor-replica.d.ts +1 -1
  168. package/dist/operator-toolkit.d.ts +5 -4
  169. package/dist/operator-toolkit.js +7 -6
  170. package/dist/orchestration/compression-guideline-coordinator.d.ts +2 -2
  171. package/dist/orchestration/maintenance.d.ts +4 -4
  172. package/dist/{orchestrator-SHaRXCUF.d.ts → orchestrator-fYTncnLy.d.ts} +7 -7
  173. package/dist/orchestrator.d.ts +8 -8
  174. package/dist/orchestrator.js +16 -15
  175. package/dist/patterns-cli.d.ts +1 -1
  176. package/dist/{pipeline-B5_tS1Yc.d.ts → pipeline-Cs76XC-p.d.ts} +1 -1
  177. package/dist/policy-runtime.d.ts +1 -1
  178. package/dist/proactive-contention.d.ts +1 -1
  179. package/dist/provenance.d.ts +1 -1
  180. package/dist/{qmd-CkEV_SPG.d.ts → qmd-WJwvBgiF.d.ts} +1 -1
  181. package/dist/qmd-preflight.d.ts +2 -2
  182. package/dist/qmd-recall-cache.d.ts +1 -1
  183. package/dist/qmd.d.ts +2 -2
  184. package/dist/recall-concurrency-config.d.ts +1 -1
  185. package/dist/recall-disclosure-escalation.d.ts +1 -1
  186. package/dist/recall-explain-renderer.d.ts +1 -1
  187. package/dist/recall-memory-map.d.ts +1 -1
  188. package/dist/recall-planner-llm.d.ts +1 -1
  189. package/dist/recall-state.d.ts +1 -1
  190. package/dist/recall-tag-filter.d.ts +1 -1
  191. package/dist/recall-timings.d.ts +1 -1
  192. package/dist/recall-xray-cli.d.ts +1 -1
  193. package/dist/recall-xray-renderer.d.ts +1 -1
  194. package/dist/recall-xray.d.ts +1 -1
  195. package/dist/replay/normalizers/chatgpt.d.ts +1 -1
  196. package/dist/replay/normalizers/claude.d.ts +1 -1
  197. package/dist/replay/normalizers/openclaw.d.ts +1 -1
  198. package/dist/replay/normalizers/shared.d.ts +1 -1
  199. package/dist/replay/runner.d.ts +1 -1
  200. package/dist/replay/types.d.ts +1 -1
  201. package/dist/replica-divergence.d.ts +1 -1
  202. package/dist/replica-peers-config.d.ts +1 -1
  203. package/dist/resolve-auth-token.d.ts +1 -1
  204. package/dist/resume-bundles.js +3 -3
  205. package/dist/retrieval-agents.d.ts +2 -2
  206. package/dist/retrieval-tiers.d.ts +1 -1
  207. package/dist/routing/engine.d.ts +1 -1
  208. package/dist/routing/store.d.ts +1 -1
  209. package/dist/salvage-envelope.d.ts +1 -1
  210. package/dist/schemas.d.ts +76 -76
  211. package/dist/{scope-profiles-DeAdnocS.d.ts → scope-profiles-CQ0NAleS.d.ts} +1 -1
  212. package/dist/search/embed-helper.d.ts +1 -1
  213. package/dist/search/factory.d.ts +1 -1
  214. package/dist/search/index.d.ts +1 -1
  215. package/dist/search/lancedb-backend.d.ts +1 -1
  216. package/dist/search/meilisearch-backend.d.ts +1 -1
  217. package/dist/search/noop-backend.d.ts +1 -1
  218. package/dist/search/orama-backend.d.ts +1 -1
  219. package/dist/search/port.d.ts +1 -1
  220. package/dist/search/remote-backend.d.ts +1 -1
  221. package/dist/{semantic-consolidation-DR_h-JUD.d.ts → semantic-consolidation-BWxOBMtz.d.ts} +1 -1
  222. package/dist/semantic-consolidation.d.ts +2 -2
  223. package/dist/semantic-rule-verifier.d.ts +1 -1
  224. package/dist/{service-BTb94UPJ.d.ts → service-CLuMO-pa.d.ts} +2 -2
  225. package/dist/session-observer-bands.d.ts +1 -1
  226. package/dist/session-observer-state.d.ts +1 -1
  227. package/dist/shared-context/manager.d.ts +9 -9
  228. package/dist/signal.d.ts +1 -1
  229. package/dist/source-agent-qualifier.d.ts +1 -1
  230. package/dist/{storage-ax2EIsVS.d.ts → storage-Blr71GpS.d.ts} +1 -1
  231. package/dist/storage.d.ts +2 -2
  232. package/dist/summarizer.d.ts +1 -1
  233. package/dist/summary-snapshot.d.ts +1 -1
  234. package/dist/temporal-supersession.d.ts +2 -2
  235. package/dist/temporal-timeline-recall.d.ts +1 -1
  236. package/dist/temporal-validity.d.ts +1 -1
  237. package/dist/threading.d.ts +1 -1
  238. package/dist/tier-migration.d.ts +2 -2
  239. package/dist/tier-routing.d.ts +1 -1
  240. package/dist/topics.d.ts +1 -1
  241. package/dist/transcript.d.ts +1 -1
  242. package/dist/transfer/types.d.ts +66 -66
  243. package/dist/trust-score-stage.d.ts +1 -1
  244. package/dist/trust-score.d.ts +1 -1
  245. package/dist/{types-CCGL-9NX.d.ts → types-CqWwMPr_.d.ts} +41 -59
  246. package/dist/types.d.ts +1 -1
  247. package/dist/utility-runtime.d.ts +1 -1
  248. package/dist/write-envelope.d.ts +1 -1
  249. package/package.json +2 -2
  250. package/src/access-http.test.ts +2 -2
  251. package/src/access-service-health.test.ts +39 -17
  252. package/src/access-service.ts +25 -3
  253. package/src/cli.ts +3 -3
  254. package/src/corpus-watermark.test.ts +16 -0
  255. package/src/corpus-watermark.ts +28 -5
  256. package/src/extraction-liveness.test.ts +81 -19
  257. package/src/extraction-liveness.ts +96 -98
  258. package/src/extraction-watermark.test.ts +290 -0
  259. package/src/namespaces/migrate.ts +10 -2
  260. package/src/operator-doctor-corpus.test.ts +7 -0
  261. package/src/operator-doctor-corpus.ts +1 -1
  262. package/src/operator-toolkit.ts +8 -8
  263. package/src/orchestration/extraction-watermark.ts +188 -0
  264. package/dist/chunk-443XCR34.js.map +0 -1
  265. package/dist/chunk-AXHMCRS3.js.map +0 -1
  266. package/dist/chunk-GLBK35BT.js.map +0 -1
  267. package/dist/chunk-NEO4QCID.js.map +0 -1
  268. package/dist/chunk-RK6WMGTX.js.map +0 -1
  269. package/dist/chunk-UIVRPXRR.js.map +0 -1
  270. package/dist/chunk-XYXYEDPL.js.map +0 -1
  271. /package/dist/{chunk-XPQ5ZTL6.js.map → chunk-6I2C3EOH.js.map} +0 -0
  272. /package/dist/{chunk-AYICY7IE.js.map → chunk-AXUU7SG3.js.map} +0 -0
  273. /package/dist/{chunk-KW4ZFTUS.js.map → chunk-CWPDM66T.js.map} +0 -0
  274. /package/dist/{chunk-EBWOOJEP.js.map → chunk-GDC4INBF.js.map} +0 -0
  275. /package/dist/{chunk-SD4A6IZY.js.map → chunk-PWKZV4A3.js.map} +0 -0
  276. /package/dist/{chunk-MOHZIKZM.js.map → chunk-TM72UOX2.js.map} +0 -0
  277. /package/dist/{chunk-Q6QYN56R.js.map → chunk-UQVGDEAJ.js.map} +0 -0
  278. /package/dist/{chunk-KYYRJVE6.js.map → chunk-XRWVXPEM.js.map} +0 -0
@@ -977,23 +977,31 @@ interface ExtractionBufferSnapshot {
977
977
  interface ExtractionBufferSource {
978
978
  getBufferSnapshot(): Promise<ExtractionBufferSnapshot>;
979
979
  }
980
+ interface ExtractionRootStats {
981
+ extractionCount?: number;
982
+ lastConsolidationAt?: string | null;
983
+ }
984
+ interface ExtractionWatermarkRead {
985
+ lastExtractionAt: string | null;
986
+ readFailed: boolean;
987
+ readError?: string;
988
+ pending?: boolean;
989
+ rootStats?: ExtractionRootStats;
990
+ }
991
+ type ExtractionWatermarkOrStorage = ExtractionWatermarkRead | {
992
+ readMetadata(): Promise<{
993
+ lastExtractionAt?: string | null;
994
+ } | null>;
995
+ } | {
996
+ loadMeta(): Promise<{
997
+ lastExtractionAt?: string | null;
998
+ }>;
999
+ };
1000
+ declare function coerceExtractionWatermark(watermark: ExtractionWatermarkOrStorage): Promise<ExtractionWatermarkRead>;
980
1001
  /**
981
- * The liveness payload surfaced on `/health.extraction` and in the doctor/stats
982
- * details.
983
- *
984
- * DAEMON-SCOPED SIGNAL: a daemon exposes a single extraction verdict; the
985
- * last-extraction watermark is read from the daemon's default/root store, so
986
- * `/health` returns the same `extraction` block for every namespace argument.
987
- *
988
- * KNOWN LIMITATION (issue #2159): extraction stamps `lastExtractionAt` on the
989
- * PER-NAMESPACE store (`storageFor(selfNamespace)`), so this watermark reflects
990
- * only extraction that stamped the root store (default-namespace work). On a
991
- * single-namespace deployment (the common case) the watermark and buffer share
992
- * one scope and the verdict is exact. On a multi-namespace deployment the verdict
993
- * is NOT guaranteed correct for work isolated to a non-default namespace: it can
994
- * over-report `degraded` (the default namespace idle while another is extracting)
995
- * or miss a stall confined to a non-default namespace. Aggregating the watermark
996
- * across namespace stores is tracked in #2159.
1002
+ * The daemon-scoped liveness payload surfaced on `/health.extraction` and in
1003
+ * doctor/stats details. Its watermark is the maximum successful extraction
1004
+ * across every distinct namespace store, matching the daemon-wide buffer scope.
997
1005
  */
998
1006
  interface ExtractionLivenessStatus {
999
1007
  lastExtractionAt: string | null;
@@ -1002,17 +1010,8 @@ interface ExtractionLivenessStatus {
1002
1010
  oldestBufferedTurnAgeMs: number | null;
1003
1011
  degraded: boolean;
1004
1012
  degradedReason: string | null;
1005
- /**
1006
- * Scope of the last-extraction watermark: `root-store` today (read from the
1007
- * daemon's default/root store only), `aggregate` once it is resolved across
1008
- * every namespace store (#2159). A monitor can alert on
1009
- * `watermarkScope !== "aggregate"` while namespaces are enabled instead of
1010
- * trusting a number that may be wrong in either direction.
1011
- */
1012
- watermarkScope: "root-store" | "aggregate";
1013
- }
1014
- interface ExtractionLivenessStorageLike {
1015
- loadMeta(): Promise<Pick<MetaState, "lastExtractionAt">>;
1013
+ watermarkPending?: boolean;
1014
+ watermarkScope: "aggregate";
1016
1015
  }
1017
1016
  interface ExtractionLivenessOrchestratorLike {
1018
1017
  config: Pick<PluginConfig, "extractionLiveness">;
@@ -1048,17 +1047,16 @@ declare function evaluateExtractionLiveness(input: {
1048
1047
  nowMs: number;
1049
1048
  metaReadFailed?: boolean;
1050
1049
  metaReadError?: string;
1051
- watermarkScope?: "root-store" | "aggregate";
1050
+ watermarkPending?: boolean;
1052
1051
  }): ExtractionLivenessStatus;
1053
1052
  /**
1054
- * Gather the liveness status from a meta store (last-extraction watermark) and
1055
- * an optional buffer (backlog). A read failure on EITHER side is captured and
1056
- * surfaced as a DEGRADED status with a distinct reason (§22) rather than being
1057
- * swallowed into a healthy-looking verdict; no failure path throws.
1053
+ * Gather the liveness status from an aggregate watermark read and an optional
1054
+ * buffer. A read failure on either side is surfaced as a degraded status with a
1055
+ * distinct reason rather than swallowed into a healthy-looking verdict.
1058
1056
  */
1059
1057
  declare function gatherExtractionLivenessStatus(input: {
1060
1058
  config: ExtractionLivenessConfig;
1061
- storage: ExtractionLivenessStorageLike;
1059
+ watermark: ExtractionWatermarkOrStorage;
1062
1060
  buffer: ExtractionBufferSource | undefined;
1063
1061
  nowMs: number;
1064
1062
  }): Promise<ExtractionLivenessStatus>;
@@ -1089,38 +1087,22 @@ declare function resolveExtractionLivenessConfig(block: {
1089
1087
  staleWindowMs?: unknown;
1090
1088
  } | undefined): ExtractionLivenessConfig;
1091
1089
  /**
1092
- * Compute the liveness status for the authenticated `/health` payload and emit
1093
- * the throttled aggregated WARN.
1094
- *
1095
- * The watermark is read from the daemon's default/root store (`orchestrator.storage`),
1096
- * which is why `/health` returns the same `extraction` block for any namespace
1097
- * argument. KNOWN LIMITATION (issue #2159): extraction writes `lastExtractionAt`
1098
- * per-namespace, so this watermark reflects only default-namespace extraction and
1099
- * the verdict is exact only for a single-namespace daemon (see
1100
- * `ExtractionLivenessStatus`).
1090
+ * Compute the daemon-wide liveness status for the authenticated `/health`
1091
+ * payload and emit the throttled aggregate warning.
1101
1092
  */
1102
- declare function computeExtractionLivenessStatus(orchestrator: ExtractionLivenessOrchestratorLike & {
1103
- storage: ExtractionLivenessStorageLike;
1104
- }, throttle?: ExtractionLivenessWarnThrottle, nowMs?: number): Promise<ExtractionLivenessStatus>;
1093
+ declare function computeExtractionLivenessStatus(orchestrator: ExtractionLivenessOrchestratorLike, watermark: ExtractionWatermarkOrStorage, throttle?: ExtractionLivenessWarnThrottle, nowMs?: number): Promise<ExtractionLivenessStatus>;
1105
1094
  /**
1106
1095
  * `remnic doctor` check for extraction-pipeline liveness. Status `warn` when
1107
1096
  * degraded (with a remediation hint), `ok` otherwise.
1108
1097
  */
1109
- declare function summarizeExtractionLiveness(config: Pick<PluginConfig, "extractionLiveness">, storage: ExtractionLivenessStorageLike, buffer?: ExtractionBufferSource, nowMs?: number): Promise<OperatorDoctorCheck>;
1110
- /** Meta fields the `remnic stats` view renders directly, beyond the liveness watermark. */
1111
- type ExtractionStatsMeta = Pick<MetaState, "extractionCount" | "lastExtractionAt" | "lastConsolidationAt">;
1098
+ declare function summarizeExtractionLiveness(config: Pick<PluginConfig, "extractionLiveness">, watermark: ExtractionWatermarkOrStorage, buffer?: ExtractionBufferSource, nowMs?: number): Promise<OperatorDoctorCheck>;
1112
1099
  /**
1113
- * Lines for `remnic stats`: extraction watermark, buffer backlog, and the
1114
- * liveness verdict so dashboards can alert on a stalled pipeline. The meta
1115
- * watermark is loaded HERE (not by the caller) so a meta-read failure surfaces
1116
- * as an explicit DEGRADED verdict plus "unavailable" counts (§22) instead of
1117
- * crashing the whole `stats` command.
1100
+ * Lines for `remnic stats`: the aggregate extraction watermark, root metadata
1101
+ * counters, buffer backlog, and liveness verdict. Root counter failures render
1102
+ * those counters unavailable; the injected aggregate read alone determines
1103
+ * watermark liveness so stats cannot diverge from health and doctor.
1118
1104
  */
1119
- declare function renderExtractionLivenessStats(orchestrator: ExtractionLivenessOrchestratorLike & {
1120
- storage: {
1121
- loadMeta(): Promise<ExtractionStatsMeta>;
1122
- };
1123
- }, nowMs?: number): Promise<string[]>;
1105
+ declare function renderExtractionLivenessStats(orchestrator: ExtractionLivenessOrchestratorLike, watermark: ExtractionWatermarkRead, nowMs?: number): Promise<string[]>;
1124
1106
 
1125
1107
  /**
1126
1108
  * `replicaPeers` config surface (issue #2149) — types + parser.
@@ -4690,4 +4672,4 @@ interface HourlySummary {
4690
4672
  generatedAt: string;
4691
4673
  }
4692
4674
 
4693
- export { type ExtractionFailureClass as $, type AgentPersonaModelConfig as A, type BriefingSections as B, type CalendarSource as C, type DreamsPhase as D, type EntityFile as E, type FaithfulnessFrontmatter as F, type GatewayConfig as G, type HourlySummary as H, type IdentityInjectionMode as I, type ExtractionResult as J, type ConsolidationResult as K, type LiveConnectorsConfig as L, type MemoryFile as M, type DaySummaryResult as N, type ProvenanceSource as O, type PluginConfig as P, type QmdSearchResult as Q, type RecallPlanMode as R, type SessionObserverBandConfig as S, type TranscriptEntry as T, type TrustWeights as U, type ConversationThread as V, type LifecycleState as W, type VerificationState as X, type PolicyClass as Y, type ReplicaPeersConfig as Z, type ReplicaPeerConfig as _, type DreamsRunResult as a, type WearableSourceStatus as a$, type ImportanceLevel as a0, type ActiveRecallChatType as a1, type ActiveRecallQueryMode as a2, type ActiveRecallPromptStyle as a3, type ActiveRecallThinking as a4, type ActiveRecallModelFallbackPolicy as a5, type BehaviorSignalEvent as a6, type BufferSurpriseEvent as a7, type ImportTurn as a8, type BulkImportOptions as a9, type QmdSearchExplain as aA, type ActivitySnapshot as aB, type ActivityConfig as aC, type ActivitySourceConfig as aD, type ActivitySourceClient as aE, type FusedWearableConversation as aF, type FusedDayMeta as aG, type FusedDayFile as aH, type MeetingRecord as aI, type MeetingDetectionSource as aJ, type FusedMeeting as aK, type EntityTimelineEntry as aL, type MemoryLink as aM, type BufferState as aN, type MetaState as aO, type FileHygieneConfig as aP, type EntityRelationship as aQ, type EntityActivityEntry as aR, type AccessTrackingEntry as aS, type MemorySummary as aT, type WearableConversation as aU, type WearableSourceSettings as aV, type WearableNativeMemory as aW, type WearableMemoryMode as aX, type WearableSourceConnector as aY, type WearablesConfig as aZ, type WearableSyncSummary as a_, type BulkImportSource as aa, type BulkImportResult as ab, type CompressionGuidelineOptimizerEventCounts as ac, type CompressionGuidelineOptimizerActionSummary as ad, type CompressionGuidelineOptimizerRuleUpdate as ae, type MemoryActionType as af, type MemoryActionEvent as ag, type CompressionGuidelineOptimizerState as ah, type EntityMention as ai, type EntitySchemaDefinition as aj, type EntitySchemaSectionDefinition as ak, type EntityStructuredSection as al, type ProvenanceConfig as am, type ImportanceScore as an, type MemoryIntent as ao, type MemoryActionEligibilityContext as ap, type MemoryActionPolicyResult as aq, type MemoryLifecycleEventType as ar, type MemoryLifecycleStateSummary as as, type ModelProviderConfig as at, type NativeKnowledgeConfig as au, type ExtractionBufferSource as av, summarizeExtractionLiveness as aw, type RetrievalTier as ax, type SignalScanResult as ay, type TopicScore as az, type RecallDisclosure as b, type ExtractionLivenessConfig as b$, type WearableDayTranscript as b0, type WearableCorrectionRule as b1, type MeetingBuildInput as b2, type MeetingsConfig as b3, type MeetingsDetectionInput as b4, type FusionConversationInput as b5, type MeetingActivitySnapshot as b6, type DetectedMeeting as b7, type CodingContext as b8, type DreamsStatusResult as b9, type BulkImportSourceAdapter as bA, type CodexCompatConfig as bB, DEFAULT_RECALL_DISCLOSURE as bC, type DisagreementKind as bD, type ExtractedFact as bE, type FusedContribution as bF, type FusedConversationProvenance as bG, type FusedSegmentProvenance as bH, type FusionSegmentInput as bI, type ImportSourceRole as bJ, type ImportTurnValidationIssue as bK, type MeetingScreenContextEvent as bL, type MeetingSummaryMode as bM, type MemoryActionEligibilitySource as bN, type MemoryObservation as bO, type MemoryScope as bP, RECALL_DISCLOSURE_LEVELS as bQ, type SegmentPickReason as bR, type WearableAuthCheck as bS, type WearableFetchOptions as bT, type WearableFetchPage as bU, type WearableNativeMemoryPage as bV, type WearableTranscriptSegment as bW, isImportRole as bX, isRecallDisclosure as bY, parseIsoTimestamp as bZ, validateImportTurn as b_, type RecallSectionConfig as ba, type BootstrapOptions as bb, type BootstrapResult as bc, type ConsolidationObservation as bd, type CodingModeConfig as be, type FusedSpeaker as bf, type FusedSegment as bg, type FusedDisagreement as bh, type FusionOptions as bi, type FusionDayResult as bj, type CodingKnowledgeConfig as bk, type WearableCleanupSettings as bl, type WearableFusionConfig as bm, type WearableDayTranscriptMeta as bn, type ActivityDayMeta as bo, type ActivityDayDigest as bp, type ActivitySourceCheck as bq, type ActivitySnapshotPage as br, type MeetingsDetectionConfig as bs, type MeetingAudioWindow as bt, type MeetingAppSpan as bu, type ActivityExtractionMode as bv, type BriefingConfig as bw, type BriefingOpenCommitment as bx, type BriefingWindow as by, type BulkImportError as bz, type RecallTierExplain as c, type MemoryActionPolicyDecision as c$, ExtractionLivenessWarnThrottle as c0, computeExtractionLivenessStatus as c1, evaluateExtractionLiveness as c2, formatAgeMs as c3, gatherExtractionLivenessStatus as c4, parseExtractionLivenessConfig as c5, renderExtractionLivenessStats as c6, resolveExtractionLivenessConfig as c7, parseReplicaPeersConfig as c8, resolveReplicaPeersConfig as c9, type ConsolidationAction as cA, type ConsolidationItem as cB, type ContradictionScanConfig as cC, type CronConversationRecallMode as cD, type CronRecallMode as cE, type DreamingConfig as cF, type DreamingNarrativePromptStyle as cG, type DreamsDeepSleepConfig as cH, type DreamsLightSleepConfig as cI, type DreamsPhaseStatus as cJ, type DreamsPhasesConfig as cK, type DreamsRemConfig as cL, type EngramTraceEvent as cM, type ExtractedProcedureStep as cN, type ExtractedQuestion as cO, type ExtractedReasoningTrace as cP, type ExtractedReasoningTraceStep as cQ, type ExtractedRelationship as cR, type ExtractionPassSource as cS, type GitHubLiveConnectorConfig as cT, type GmailLiveConnectorConfig as cU, type GoogleDriveLiveConnectorConfig as cV, type HeartbeatConfig as cW, type HeartbeatDetectionMode as cX, type LlmTraceCallback as cY, type LlmTraceEvent as cZ, type MemoryActionOutcome as c_, type BufferTurnOwner as ca, ProbeTimeoutError as cb, bufferTurnArrayIsSuffixOfSnapshot as cc, bufferTurnArraysEqual as cd, bufferTurnsEqual as ce, copyBufferTurn as cf, describeError as cg, liveTurnsFromExtractionSnapshot as ch, matchingQueuedExtractionPrefixLength as ci, probeWithTimeout as cj, type AgentAccessHttpConfig as ck, type AgentDefaultsConfig as cl, type AgentPersona as cm, type BehaviorLoopAdjustment as cn, type BehaviorSignalDirection as co, type BehaviorSignalType as cp, type BriefingCalendarSourceError as cq, type BufferEntryState as cr, type ChatConfig as cs, type CodexCliReasoningEffort as ct, type CodexCompactionFlushMode as cu, type CodexConnectorConfig as cv, type CodingGraphLspConfig as cw, type CompressionGuidelineActivationState as cx, type CompressionGuidelineOptimizerSourceWindow as cy, type ConfidenceTier as cz, type BriefingFollowup as d, type MemoryActionStatus as d0, type MemoryLinkType as d1, type MemoryOsPresetName as d2, type ModelApi as d3, type ModelDefinitionConfig as d4, type ModelProviderAuthMode as d5, type NamespacePolicy as d6, type NativeKnowledgeFolderRuleConfig as d7, type NativeKnowledgeObsidianVaultConfig as d8, type NativeKnowledgeOpenClawWorkspaceConfig as d9, type NotionLiveConnectorConfig as da, type PrincipalFromSessionKeyMode as db, type PrincipalRule as dc, type ProceduralConfig as dd, type QuestionEntry as de, type ReasoningEffort as df, type RecallPipelineConfig as dg, type RecallTraceEvent as dh, type RelevanceFeedback as di, SPECULATIVE_TTL_DAYS as dj, type ScopeProfileAutoPromoteConfig as dk, type ScopeProfileTeamProjectConfig as dl, type ScopeTeamConfig as dm, type ScoredEntity as dn, type SemanticChunkingConfigShape as dp, type SignalLevel as dq, type SlotBehaviorConfig as dr, type SlotMismatchMode as ds, type TriggerMode as dt, confidenceTier as du, type BriefingFocus as e, type CalendarEvent as f, type BriefingActiveThread as g, type BriefingResult as h, type BriefingRecentEntity as i, type BufferTurn as j, type ExtractionBufferSnapshot as k, type MemoryFrontmatter as l, type Checkpoint as m, type SourceConnectorProvenance as n, type ScopeProfileConfig as o, type ScopeProfileLayerId as p, type ScopeProfilePromotionTarget as q, type BehaviorLoopPolicyState as r, type SecretRef as s, type AgentAccessAuthToken as t, type ExtractionLivenessStatus as u, type MemoryCategory as v, type CaptureMode as w, type MemoryStatus as x, type MemoryProjectionCurrentState as y, type MemoryLifecycleEvent as z };
4675
+ export { type ExtractionFailureClass as $, type AgentPersonaModelConfig as A, type BriefingSections as B, type CalendarSource as C, type DreamsPhase as D, type EntityFile as E, type FaithfulnessFrontmatter as F, type GatewayConfig as G, type HourlySummary as H, type IdentityInjectionMode as I, type ExtractionResult as J, type ConsolidationResult as K, type LiveConnectorsConfig as L, type MemoryFile as M, type DaySummaryResult as N, type ProvenanceSource as O, type PluginConfig as P, type QmdSearchResult as Q, type RecallPlanMode as R, type SessionObserverBandConfig as S, type TranscriptEntry as T, type TrustWeights as U, type ConversationThread as V, type LifecycleState as W, type VerificationState as X, type PolicyClass as Y, type ReplicaPeersConfig as Z, type ReplicaPeerConfig as _, type DreamsRunResult as a, type WearableSourceStatus as a$, type ImportanceLevel as a0, type ActiveRecallChatType as a1, type ActiveRecallQueryMode as a2, type ActiveRecallPromptStyle as a3, type ActiveRecallThinking as a4, type ActiveRecallModelFallbackPolicy as a5, type BehaviorSignalEvent as a6, type BufferSurpriseEvent as a7, type ImportTurn as a8, type BulkImportOptions as a9, type TopicScore as aA, type QmdSearchExplain as aB, type ActivitySnapshot as aC, type ActivityConfig as aD, type ActivitySourceConfig as aE, type ActivitySourceClient as aF, type FusedWearableConversation as aG, type FusedDayMeta as aH, type FusedDayFile as aI, type MeetingRecord as aJ, type MeetingDetectionSource as aK, type FusedMeeting as aL, type EntityTimelineEntry as aM, type MemoryLink as aN, type BufferState as aO, type FileHygieneConfig as aP, type EntityRelationship as aQ, type EntityActivityEntry as aR, type AccessTrackingEntry as aS, type MemorySummary as aT, type WearableConversation as aU, type WearableSourceSettings as aV, type WearableNativeMemory as aW, type WearableMemoryMode as aX, type WearableSourceConnector as aY, type WearablesConfig as aZ, type WearableSyncSummary as a_, type BulkImportSource as aa, type BulkImportResult as ab, type CompressionGuidelineOptimizerEventCounts as ac, type CompressionGuidelineOptimizerActionSummary as ad, type CompressionGuidelineOptimizerRuleUpdate as ae, type MemoryActionType as af, type MemoryActionEvent as ag, type CompressionGuidelineOptimizerState as ah, type EntityMention as ai, type EntitySchemaDefinition as aj, type EntitySchemaSectionDefinition as ak, type EntityStructuredSection as al, type ProvenanceConfig as am, type ImportanceScore as an, type MemoryIntent as ao, type MemoryActionEligibilityContext as ap, type MemoryActionPolicyResult as aq, type MemoryLifecycleEventType as ar, type MemoryLifecycleStateSummary as as, type ModelProviderConfig as at, type NativeKnowledgeConfig as au, type ExtractionBufferSource as av, type MetaState as aw, summarizeExtractionLiveness as ax, type RetrievalTier as ay, type SignalScanResult as az, type RecallDisclosure as b, type ExtractionLivenessConfig as b$, type WearableDayTranscript as b0, type WearableCorrectionRule as b1, type MeetingBuildInput as b2, type MeetingsConfig as b3, type MeetingsDetectionInput as b4, type FusionConversationInput as b5, type MeetingActivitySnapshot as b6, type DetectedMeeting as b7, type CodingContext as b8, type DreamsStatusResult as b9, type BulkImportSourceAdapter as bA, type CodexCompatConfig as bB, DEFAULT_RECALL_DISCLOSURE as bC, type DisagreementKind as bD, type ExtractedFact as bE, type FusedContribution as bF, type FusedConversationProvenance as bG, type FusedSegmentProvenance as bH, type FusionSegmentInput as bI, type ImportSourceRole as bJ, type ImportTurnValidationIssue as bK, type MeetingScreenContextEvent as bL, type MeetingSummaryMode as bM, type MemoryActionEligibilitySource as bN, type MemoryObservation as bO, type MemoryScope as bP, RECALL_DISCLOSURE_LEVELS as bQ, type SegmentPickReason as bR, type WearableAuthCheck as bS, type WearableFetchOptions as bT, type WearableFetchPage as bU, type WearableNativeMemoryPage as bV, type WearableTranscriptSegment as bW, isImportRole as bX, isRecallDisclosure as bY, parseIsoTimestamp as bZ, validateImportTurn as b_, type RecallSectionConfig as ba, type BootstrapOptions as bb, type BootstrapResult as bc, type ConsolidationObservation as bd, type CodingModeConfig as be, type FusedSpeaker as bf, type FusedSegment as bg, type FusedDisagreement as bh, type FusionOptions as bi, type FusionDayResult as bj, type CodingKnowledgeConfig as bk, type WearableCleanupSettings as bl, type WearableFusionConfig as bm, type WearableDayTranscriptMeta as bn, type ActivityDayMeta as bo, type ActivityDayDigest as bp, type ActivitySourceCheck as bq, type ActivitySnapshotPage as br, type MeetingsDetectionConfig as bs, type MeetingAudioWindow as bt, type MeetingAppSpan as bu, type ActivityExtractionMode as bv, type BriefingConfig as bw, type BriefingOpenCommitment as bx, type BriefingWindow as by, type BulkImportError as bz, type RecallTierExplain as c, type HeartbeatDetectionMode as c$, ExtractionLivenessWarnThrottle as c0, type ExtractionRootStats as c1, type ExtractionWatermarkOrStorage as c2, type ExtractionWatermarkRead as c3, coerceExtractionWatermark as c4, computeExtractionLivenessStatus as c5, evaluateExtractionLiveness as c6, formatAgeMs as c7, gatherExtractionLivenessStatus as c8, parseExtractionLivenessConfig as c9, type CodingGraphLspConfig as cA, type CompressionGuidelineActivationState as cB, type CompressionGuidelineOptimizerSourceWindow as cC, type ConfidenceTier as cD, type ConsolidationAction as cE, type ConsolidationItem as cF, type ContradictionScanConfig as cG, type CronConversationRecallMode as cH, type CronRecallMode as cI, type DreamingConfig as cJ, type DreamingNarrativePromptStyle as cK, type DreamsDeepSleepConfig as cL, type DreamsLightSleepConfig as cM, type DreamsPhaseStatus as cN, type DreamsPhasesConfig as cO, type DreamsRemConfig as cP, type EngramTraceEvent as cQ, type ExtractedProcedureStep as cR, type ExtractedQuestion as cS, type ExtractedReasoningTrace as cT, type ExtractedReasoningTraceStep as cU, type ExtractedRelationship as cV, type ExtractionPassSource as cW, type GitHubLiveConnectorConfig as cX, type GmailLiveConnectorConfig as cY, type GoogleDriveLiveConnectorConfig as cZ, type HeartbeatConfig as c_, renderExtractionLivenessStats as ca, resolveExtractionLivenessConfig as cb, parseReplicaPeersConfig as cc, resolveReplicaPeersConfig as cd, type BufferTurnOwner as ce, ProbeTimeoutError as cf, bufferTurnArrayIsSuffixOfSnapshot as cg, bufferTurnArraysEqual as ch, bufferTurnsEqual as ci, copyBufferTurn as cj, describeError as ck, liveTurnsFromExtractionSnapshot as cl, matchingQueuedExtractionPrefixLength as cm, probeWithTimeout as cn, type AgentAccessHttpConfig as co, type AgentDefaultsConfig as cp, type AgentPersona as cq, type BehaviorLoopAdjustment as cr, type BehaviorSignalDirection as cs, type BehaviorSignalType as ct, type BriefingCalendarSourceError as cu, type BufferEntryState as cv, type ChatConfig as cw, type CodexCliReasoningEffort as cx, type CodexCompactionFlushMode as cy, type CodexConnectorConfig as cz, type BriefingFollowup as d, type LlmTraceCallback as d0, type LlmTraceEvent as d1, type MemoryActionOutcome as d2, type MemoryActionPolicyDecision as d3, type MemoryActionStatus as d4, type MemoryLinkType as d5, type MemoryOsPresetName as d6, type ModelApi as d7, type ModelDefinitionConfig as d8, type ModelProviderAuthMode as d9, type NamespacePolicy as da, type NativeKnowledgeFolderRuleConfig as db, type NativeKnowledgeObsidianVaultConfig as dc, type NativeKnowledgeOpenClawWorkspaceConfig as dd, type NotionLiveConnectorConfig as de, type PrincipalFromSessionKeyMode as df, type PrincipalRule as dg, type ProceduralConfig as dh, type QuestionEntry as di, type ReasoningEffort as dj, type RecallPipelineConfig as dk, type RecallTraceEvent as dl, type RelevanceFeedback as dm, SPECULATIVE_TTL_DAYS as dn, type ScopeProfileAutoPromoteConfig as dp, type ScopeProfileTeamProjectConfig as dq, type ScopeTeamConfig as dr, type ScoredEntity as ds, type SemanticChunkingConfigShape as dt, type SignalLevel as du, type SlotBehaviorConfig as dv, type SlotMismatchMode as dw, type TriggerMode as dx, confidenceTier as dy, type BriefingFocus as e, type CalendarEvent as f, type BriefingActiveThread as g, type BriefingResult as h, type BriefingRecentEntity as i, type BufferTurn as j, type ExtractionBufferSnapshot as k, type MemoryFrontmatter as l, type Checkpoint as m, type SourceConnectorProvenance as n, type ScopeProfileConfig as o, type ScopeProfileLayerId as p, type ScopeProfilePromotionTarget as q, type BehaviorLoopPolicyState as r, type SecretRef as s, type AgentAccessAuthToken as t, type ExtractionLivenessStatus as u, type MemoryCategory as v, type CaptureMode as w, type MemoryStatus as x, type MemoryProjectionCurrentState as y, type MemoryLifecycleEvent as z };
package/dist/types.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- export { aS as AccessTrackingEntry, a1 as ActiveRecallChatType, a5 as ActiveRecallModelFallbackPolicy, a3 as ActiveRecallPromptStyle, a2 as ActiveRecallQueryMode, a4 as ActiveRecallThinking, t as AgentAccessAuthToken, ck as AgentAccessHttpConfig, cl as AgentDefaultsConfig, cm as AgentPersona, A as AgentPersonaModelConfig, cn as BehaviorLoopAdjustment, r as BehaviorLoopPolicyState, co as BehaviorSignalDirection, a6 as BehaviorSignalEvent, cp as BehaviorSignalType, bb as BootstrapOptions, bc as BootstrapResult, g as BriefingActiveThread, cq as BriefingCalendarSourceError, bw as BriefingConfig, e as BriefingFocus, d as BriefingFollowup, bx as BriefingOpenCommitment, i as BriefingRecentEntity, h as BriefingResult, B as BriefingSections, by as BriefingWindow, cr as BufferEntryState, aN as BufferState, a7 as BufferSurpriseEvent, j as BufferTurn, f as CalendarEvent, C as CalendarSource, w as CaptureMode, cs as ChatConfig, m as Checkpoint, ct as CodexCliReasoningEffort, cu as CodexCompactionFlushMode, bB as CodexCompatConfig, cv as CodexConnectorConfig, b8 as CodingContext, cw as CodingGraphLspConfig, bk as CodingKnowledgeConfig, be as CodingModeConfig, cx as CompressionGuidelineActivationState, ad as CompressionGuidelineOptimizerActionSummary, ac as CompressionGuidelineOptimizerEventCounts, ae as CompressionGuidelineOptimizerRuleUpdate, cy as CompressionGuidelineOptimizerSourceWindow, ah as CompressionGuidelineOptimizerState, cz as ConfidenceTier, cA as ConsolidationAction, cB as ConsolidationItem, bd as ConsolidationObservation, K as ConsolidationResult, cC as ContradictionScanConfig, V as ConversationThread, cD as CronConversationRecallMode, cE as CronRecallMode, bC as DEFAULT_RECALL_DISCLOSURE, N as DaySummaryResult, cF as DreamingConfig, cG as DreamingNarrativePromptStyle, cH as DreamsDeepSleepConfig, cI as DreamsLightSleepConfig, D as DreamsPhase, cJ as DreamsPhaseStatus, cK as DreamsPhasesConfig, cL as DreamsRemConfig, a as DreamsRunResult, b9 as DreamsStatusResult, cM as EngramTraceEvent, aR as EntityActivityEntry, E as EntityFile, ai as EntityMention, aQ as EntityRelationship, aj as EntitySchemaDefinition, ak as EntitySchemaSectionDefinition, al as EntityStructuredSection, aL as EntityTimelineEntry, bE as ExtractedFact, cN as ExtractedProcedureStep, cO as ExtractedQuestion, cP as ExtractedReasoningTrace, cQ as ExtractedReasoningTraceStep, cR as ExtractedRelationship, $ as ExtractionFailureClass, cS as ExtractionPassSource, J as ExtractionResult, F as FaithfulnessFrontmatter, aP as FileHygieneConfig, G as GatewayConfig, cT as GitHubLiveConnectorConfig, cU as GmailLiveConnectorConfig, cV as GoogleDriveLiveConnectorConfig, cW as HeartbeatConfig, cX as HeartbeatDetectionMode, H as HourlySummary, I as IdentityInjectionMode, a0 as ImportanceLevel, an as ImportanceScore, W as LifecycleState, L as LiveConnectorsConfig, cY as LlmTraceCallback, cZ as LlmTraceEvent, ap as MemoryActionEligibilityContext, bN as MemoryActionEligibilitySource, ag as MemoryActionEvent, c_ as MemoryActionOutcome, c$ as MemoryActionPolicyDecision, aq as MemoryActionPolicyResult, d0 as MemoryActionStatus, af as MemoryActionType, v as MemoryCategory, M as MemoryFile, l as MemoryFrontmatter, ao as MemoryIntent, z as MemoryLifecycleEvent, ar as MemoryLifecycleEventType, as as MemoryLifecycleStateSummary, aM as MemoryLink, d1 as MemoryLinkType, bO as MemoryObservation, d2 as MemoryOsPresetName, y as MemoryProjectionCurrentState, bP as MemoryScope, x as MemoryStatus, aT as MemorySummary, aO as MetaState, d3 as ModelApi, d4 as ModelDefinitionConfig, d5 as ModelProviderAuthMode, at as ModelProviderConfig, d6 as NamespacePolicy, au as NativeKnowledgeConfig, d7 as NativeKnowledgeFolderRuleConfig, d8 as NativeKnowledgeObsidianVaultConfig, d9 as NativeKnowledgeOpenClawWorkspaceConfig, da as NotionLiveConnectorConfig, P as PluginConfig, Y as PolicyClass, db as PrincipalFromSessionKeyMode, dc as PrincipalRule, dd as ProceduralConfig, am as ProvenanceConfig, O as ProvenanceSource, aA as QmdSearchExplain, Q as QmdSearchResult, de as QuestionEntry, bQ as RECALL_DISCLOSURE_LEVELS, df as ReasoningEffort, b as RecallDisclosure, dg as RecallPipelineConfig, R as RecallPlanMode, ba as RecallSectionConfig, c as RecallTierExplain, dh as RecallTraceEvent, di as RelevanceFeedback, ax as RetrievalTier, dj as SPECULATIVE_TTL_DAYS, dk as ScopeProfileAutoPromoteConfig, o as ScopeProfileConfig, p as ScopeProfileLayerId, q as ScopeProfilePromotionTarget, dl as ScopeProfileTeamProjectConfig, dm as ScopeTeamConfig, dn as ScoredEntity, s as SecretRef, dp as SemanticChunkingConfigShape, S as SessionObserverBandConfig, dq as SignalLevel, ay as SignalScanResult, dr as SlotBehaviorConfig, ds as SlotMismatchMode, n as SourceConnectorProvenance, az as TopicScore, T as TranscriptEntry, dt as TriggerMode, U as TrustWeights, X as VerificationState, du as confidenceTier, bY as isRecallDisclosure } from './types-CCGL-9NX.js';
1
+ export { aS as AccessTrackingEntry, a1 as ActiveRecallChatType, a5 as ActiveRecallModelFallbackPolicy, a3 as ActiveRecallPromptStyle, a2 as ActiveRecallQueryMode, a4 as ActiveRecallThinking, t as AgentAccessAuthToken, co as AgentAccessHttpConfig, cp as AgentDefaultsConfig, cq as AgentPersona, A as AgentPersonaModelConfig, cr as BehaviorLoopAdjustment, r as BehaviorLoopPolicyState, cs as BehaviorSignalDirection, a6 as BehaviorSignalEvent, ct as BehaviorSignalType, bb as BootstrapOptions, bc as BootstrapResult, g as BriefingActiveThread, cu as BriefingCalendarSourceError, bw as BriefingConfig, e as BriefingFocus, d as BriefingFollowup, bx as BriefingOpenCommitment, i as BriefingRecentEntity, h as BriefingResult, B as BriefingSections, by as BriefingWindow, cv as BufferEntryState, aO as BufferState, a7 as BufferSurpriseEvent, j as BufferTurn, f as CalendarEvent, C as CalendarSource, w as CaptureMode, cw as ChatConfig, m as Checkpoint, cx as CodexCliReasoningEffort, cy as CodexCompactionFlushMode, bB as CodexCompatConfig, cz as CodexConnectorConfig, b8 as CodingContext, cA as CodingGraphLspConfig, bk as CodingKnowledgeConfig, be as CodingModeConfig, cB as CompressionGuidelineActivationState, ad as CompressionGuidelineOptimizerActionSummary, ac as CompressionGuidelineOptimizerEventCounts, ae as CompressionGuidelineOptimizerRuleUpdate, cC as CompressionGuidelineOptimizerSourceWindow, ah as CompressionGuidelineOptimizerState, cD as ConfidenceTier, cE as ConsolidationAction, cF as ConsolidationItem, bd as ConsolidationObservation, K as ConsolidationResult, cG as ContradictionScanConfig, V as ConversationThread, cH as CronConversationRecallMode, cI as CronRecallMode, bC as DEFAULT_RECALL_DISCLOSURE, N as DaySummaryResult, cJ as DreamingConfig, cK as DreamingNarrativePromptStyle, cL as DreamsDeepSleepConfig, cM as DreamsLightSleepConfig, D as DreamsPhase, cN as DreamsPhaseStatus, cO as DreamsPhasesConfig, cP as DreamsRemConfig, a as DreamsRunResult, b9 as DreamsStatusResult, cQ as EngramTraceEvent, aR as EntityActivityEntry, E as EntityFile, ai as EntityMention, aQ as EntityRelationship, aj as EntitySchemaDefinition, ak as EntitySchemaSectionDefinition, al as EntityStructuredSection, aM as EntityTimelineEntry, bE as ExtractedFact, cR as ExtractedProcedureStep, cS as ExtractedQuestion, cT as ExtractedReasoningTrace, cU as ExtractedReasoningTraceStep, cV as ExtractedRelationship, $ as ExtractionFailureClass, cW as ExtractionPassSource, J as ExtractionResult, F as FaithfulnessFrontmatter, aP as FileHygieneConfig, G as GatewayConfig, cX as GitHubLiveConnectorConfig, cY as GmailLiveConnectorConfig, cZ as GoogleDriveLiveConnectorConfig, c_ as HeartbeatConfig, c$ as HeartbeatDetectionMode, H as HourlySummary, I as IdentityInjectionMode, a0 as ImportanceLevel, an as ImportanceScore, W as LifecycleState, L as LiveConnectorsConfig, d0 as LlmTraceCallback, d1 as LlmTraceEvent, ap as MemoryActionEligibilityContext, bN as MemoryActionEligibilitySource, ag as MemoryActionEvent, d2 as MemoryActionOutcome, d3 as MemoryActionPolicyDecision, aq as MemoryActionPolicyResult, d4 as MemoryActionStatus, af as MemoryActionType, v as MemoryCategory, M as MemoryFile, l as MemoryFrontmatter, ao as MemoryIntent, z as MemoryLifecycleEvent, ar as MemoryLifecycleEventType, as as MemoryLifecycleStateSummary, aN as MemoryLink, d5 as MemoryLinkType, bO as MemoryObservation, d6 as MemoryOsPresetName, y as MemoryProjectionCurrentState, bP as MemoryScope, x as MemoryStatus, aT as MemorySummary, aw as MetaState, d7 as ModelApi, d8 as ModelDefinitionConfig, d9 as ModelProviderAuthMode, at as ModelProviderConfig, da as NamespacePolicy, au as NativeKnowledgeConfig, db as NativeKnowledgeFolderRuleConfig, dc as NativeKnowledgeObsidianVaultConfig, dd as NativeKnowledgeOpenClawWorkspaceConfig, de as NotionLiveConnectorConfig, P as PluginConfig, Y as PolicyClass, df as PrincipalFromSessionKeyMode, dg as PrincipalRule, dh as ProceduralConfig, am as ProvenanceConfig, O as ProvenanceSource, aB as QmdSearchExplain, Q as QmdSearchResult, di as QuestionEntry, bQ as RECALL_DISCLOSURE_LEVELS, dj as ReasoningEffort, b as RecallDisclosure, dk as RecallPipelineConfig, R as RecallPlanMode, ba as RecallSectionConfig, c as RecallTierExplain, dl as RecallTraceEvent, dm as RelevanceFeedback, ay as RetrievalTier, dn as SPECULATIVE_TTL_DAYS, dp as ScopeProfileAutoPromoteConfig, o as ScopeProfileConfig, p as ScopeProfileLayerId, q as ScopeProfilePromotionTarget, dq as ScopeProfileTeamProjectConfig, dr as ScopeTeamConfig, ds as ScoredEntity, s as SecretRef, dt as SemanticChunkingConfigShape, S as SessionObserverBandConfig, du as SignalLevel, az as SignalScanResult, dv as SlotBehaviorConfig, dw as SlotMismatchMode, n as SourceConnectorProvenance, aA as TopicScore, T as TranscriptEntry, dx as TriggerMode, U as TrustWeights, X as VerificationState, dy as confidenceTier, bY as isRecallDisclosure } from './types-CqWwMPr_.js';
2
2
  import './message-parts/index.js';
3
3
  import './bounded-jsonl-state.js';
4
4
  export { ContinuityImprovementLoop, ContinuityIncidentCloseInput, ContinuityIncidentOpenInput, ContinuityIncidentRecord, ContinuityIncidentState, ContinuityLoopCadence, ContinuityLoopReviewInput, ContinuityLoopStatus, ContinuityLoopUpsertInput } from './types-continuity.js';
@@ -1,5 +1,5 @@
1
1
  import { TierRoutingPolicy } from './tier-routing.js';
2
- import './types-CCGL-9NX.js';
2
+ import './types-CqWwMPr_.js';
3
3
  import './message-parts/index.js';
4
4
  import './bounded-jsonl-state.js';
5
5
  import './operator-doctor-types.js';
@@ -1,4 +1,4 @@
1
- import { v as MemoryCategory } from './types-CCGL-9NX.js';
1
+ import { v as MemoryCategory } from './types-CqWwMPr_.js';
2
2
  import './message-parts/index.js';
3
3
  import './bounded-jsonl-state.js';
4
4
  import './operator-doctor-types.js';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@remnic/core",
3
- "version": "9.40.0",
3
+ "version": "9.42.0",
4
4
  "description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
5
5
  "type": "module",
6
6
  "main": "dist/index.js",
@@ -3086,7 +3086,7 @@
3086
3086
  "core"
3087
3087
  ],
3088
3088
  "peerDependencies": {
3089
- "@remnic/coding-graph": "^9.40.0"
3089
+ "@remnic/coding-graph": "^9.42.0"
3090
3090
  },
3091
3091
  "peerDependenciesMeta": {
3092
3092
  "@remnic/coding-graph": {
@@ -1993,7 +1993,7 @@ test("HTTP externalRequestHandler runs pre-auth, can end responses, and falls th
1993
1993
  oldestBufferedTurnAgeMs: null,
1994
1994
  degraded: false,
1995
1995
  degradedReason: null,
1996
- watermarkScope: "root-store",
1996
+ watermarkScope: "aggregate",
1997
1997
  },
1998
1998
  corpus: [],
1999
1999
  corpusComplete: true,
@@ -2120,7 +2120,7 @@ test("HTTP authTokenEntriesGetter is authoritative: scope policy binds connector
2120
2120
  oldestBufferedTurnAgeMs: null,
2121
2121
  degraded: false,
2122
2122
  degradedReason: null,
2123
- watermarkScope: "root-store",
2123
+ watermarkScope: "aggregate",
2124
2124
  },
2125
2125
  corpus: [],
2126
2126
  corpusComplete: true,
@@ -1,11 +1,12 @@
1
1
  import assert from "node:assert/strict";
2
- import { mkdtemp, rm } from "node:fs/promises";
2
+ import { mkdir, mkdtemp, rm } from "node:fs/promises";
3
3
  import os from "node:os";
4
4
  import path from "node:path";
5
5
  import test from "node:test";
6
6
 
7
7
  import { EngramAccessService } from "./access-service.js";
8
8
  import { parseConfig } from "./config.js";
9
+ import { TOKEN_CAPABILITIES_VERSION, tokenCapabilityStore } from "./access-token-capabilities.js";
9
10
  import { namespaceCollectionName } from "./namespaces/search.js";
10
11
  import type { Orchestrator } from "./orchestrator.js";
11
12
  import type { SearchBackend } from "./search/port.js";
@@ -548,16 +549,27 @@ test("health reports extraction liveness ok when the buffer is empty (nothing to
548
549
  assert.equal(health.extraction.degraded, false);
549
550
  assert.equal(health.extraction.bufferedSessionCount, 0);
550
551
  assert.equal(health.extraction.lastExtractionAt, oldTs);
552
+ const scopedHealth = await tokenCapabilityStore.run(
553
+ { version: TOKEN_CAPABILITIES_VERSION, namespaces: ["default"] },
554
+ () => service.health(),
555
+ );
556
+ assert.equal(scopedHealth.extraction.degraded, health.extraction.degraded);
557
+ assert.equal(scopedHealth.extraction.lastExtractionAt, null);
551
558
  } finally {
552
559
  await rm(memoryDir, { recursive: true, force: true });
553
560
  }
554
561
  });
555
562
 
556
- test("health returns the same daemon-global extraction verdict for every namespace (issue #2151)", async () => {
563
+ test("health returns one daemon-global aggregate extraction verdict for every namespace", async () => {
557
564
  const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-health-liveness-ns-"));
558
565
  try {
559
- const rootTs = new Date().toISOString(); // fresh daemon-global watermark
560
- const staleTs = new Date(Date.now() - 7_200_000).toISOString(); // 2h old
566
+ const namespaceDirs: Record<string, string> = {
567
+ fresh: path.join(memoryDir, "namespaces", "fresh"),
568
+ stale: path.join(memoryDir, "namespaces", "stale"),
569
+ };
570
+ await Promise.all(Object.values(namespaceDirs).map((dir) => mkdir(dir, { recursive: true })));
571
+ const freshTs = new Date().toISOString();
572
+ const staleTs = new Date(Date.now() - 7_200_000).toISOString();
561
573
  const config = parseConfig({
562
574
  memoryDir,
563
575
  qmdEnabled: false,
@@ -565,20 +577,25 @@ test("health returns the same daemon-global extraction verdict for every namespa
565
577
  defaultNamespace: "default",
566
578
  extractionLiveness: { staleWindowMs: 3_600_000 },
567
579
  });
568
- // Per-namespace stores return DIVERGING watermarks (fresh vs 2h stale vs
569
- // never), but the global buffer is shared and the watermark must be sourced
570
- // from the root store. Pre-fix, the extraction verdict tracked the
571
- // namespace argument; post-fix it is identical for every namespace.
572
- const perNamespaceMeta: Record<string, string | null> = { fresh: rootTs, stale: staleTs };
580
+ const perNamespaceMeta: Record<string, string | null> = {
581
+ default: staleTs,
582
+ fresh: freshTs,
583
+ stale: staleTs,
584
+ };
573
585
  const service = new EngramAccessService({
574
586
  config,
575
587
  qmd: makeQmd({}),
576
588
  buffer: {
577
- getBufferSnapshot: async () => ({ bufferedSessionCount: 3, pendingTurnCount: 12, oldestTurnTimestamp: staleTs }),
589
+ getBufferSnapshot: async () => ({
590
+ bufferedSessionCount: 3,
591
+ pendingTurnCount: 12,
592
+ oldestTurnTimestamp: staleTs,
593
+ }),
578
594
  },
579
595
  storage: {
596
+ dir: memoryDir,
580
597
  loadMeta: async () => ({
581
- lastExtractionAt: rootTs,
598
+ lastExtractionAt: staleTs,
582
599
  extractionCount: 4,
583
600
  lastConsolidationAt: null,
584
601
  totalMemories: 0,
@@ -586,10 +603,11 @@ test("health returns the same daemon-global extraction verdict for every namespa
586
603
  }),
587
604
  },
588
605
  async getStorage(namespace?: string) {
606
+ const resolved = namespace ?? "default";
589
607
  return {
590
- dir: memoryDir,
608
+ dir: namespaceDirs[resolved] ?? memoryDir,
591
609
  loadMeta: async () => ({
592
- lastExtractionAt: namespace ? perNamespaceMeta[namespace] ?? null : staleTs,
610
+ lastExtractionAt: perNamespaceMeta[resolved] ?? null,
593
611
  extractionCount: 4,
594
612
  lastConsolidationAt: null,
595
613
  totalMemories: 0,
@@ -599,19 +617,23 @@ test("health returns the same daemon-global extraction verdict for every namespa
599
617
  },
600
618
  } as unknown as Orchestrator);
601
619
 
620
+ await service.health();
621
+ const serviceWithCache = service as unknown as {
622
+ corpusWatermarkCache: { whenIdle(): Promise<void> };
623
+ };
624
+ await serviceWithCache.corpusWatermarkCache.whenIdle();
625
+
602
626
  const fresh = (await service.health("fresh")).extraction;
603
627
  const stale = (await service.health("stale")).extraction;
604
628
  const def = (await service.health()).extraction;
605
- // The namespace-governed fields must not vary with the namespace argument
606
- // (oldestBufferedTurnAgeMs is time-derived and intentionally excluded).
607
629
  assert.equal(stale.degraded, fresh.degraded, "degraded must not vary by namespace");
608
630
  assert.equal(def.degraded, fresh.degraded, "default health matches namespaced health");
609
631
  assert.equal(stale.lastExtractionAt, fresh.lastExtractionAt, "watermark must not vary by namespace");
610
632
  assert.equal(def.lastExtractionAt, fresh.lastExtractionAt);
611
633
  assert.equal(stale.degradedReason, fresh.degradedReason);
612
- // Sourced from the fresh root watermark → healthy despite stale per-namespace stores.
613
634
  assert.equal(fresh.degraded, false);
614
- assert.equal(fresh.lastExtractionAt, rootTs);
635
+ assert.equal(fresh.lastExtractionAt, freshTs);
636
+ assert.equal(fresh.watermarkScope, "aggregate");
615
637
  } finally {
616
638
  await rm(memoryDir, { recursive: true, force: true });
617
639
  }
@@ -7,6 +7,7 @@ import { createHash } from "node:crypto";
7
7
  import { ZodError } from "zod";
8
8
  import { AccessIdempotencyStore, hashAccessIdempotencyPayload } from "./access-idempotency.js";
9
9
  import { computeExtractionLivenessStatus, ExtractionLivenessWarnThrottle } from "./extraction-liveness.js";
10
+ import { readAggregateExtractionWatermark } from "./orchestration/extraction-watermark.js";
10
11
  import { enforceNamespaceAllowList, tokenCapabilityStore } from "./access-token-capabilities.js";
11
12
  import {
12
13
  recordCitationUsage as recordCitationUsageForAccess,
@@ -2369,10 +2370,31 @@ export class EngramAccessService {
2369
2370
  const storage = await this.orchestrator.getStorage(resolvedNamespace);
2370
2371
  const searchBackend = this.orchestrator.config.searchBackend ?? "qmd";
2371
2372
  const qmdEnabled = resolveQmdCapabilities(this.orchestrator.config).qmd === true;
2372
- const extraction = await computeExtractionLivenessStatus(this.orchestrator, this.extractionLivenessWarn);
2373
+ const caps = tokenCapabilityStore.getStore();
2374
+ const extractionWatermark = await readAggregateExtractionWatermark({
2375
+ config: this.orchestrator.config,
2376
+ rootStorage: this.orchestrator.storage,
2377
+ storageForNamespace: (candidate) => this.orchestrator.getStorage(candidate),
2378
+ rootsCache: this.corpusWatermarkCache,
2379
+ });
2380
+ const extraction = await computeExtractionLivenessStatus(
2381
+ this.orchestrator,
2382
+ extractionWatermark,
2383
+ caps?.namespaces !== undefined ? undefined : this.extractionLivenessWarn,
2384
+ );
2385
+ const visibleExtraction =
2386
+ caps?.namespaces !== undefined
2387
+ ? {
2388
+ ...extraction,
2389
+ lastExtractionAt: null,
2390
+ bufferedSessionCount: 0,
2391
+ pendingTurnCount: 0,
2392
+ oldestBufferedTurnAgeMs: null,
2393
+ degradedReason: extraction.degraded ? "daemon extraction pipeline degraded" : null,
2394
+ }
2395
+ : extraction;
2373
2396
  // ONE call: the corpus array and the flag describing it must not come from
2374
2397
  // two independently-cached scans (round 8, codex P1).
2375
- const caps = tokenCapabilityStore.getStore();
2376
2398
  const corpusCensus = await computeServiceCorpusCensus(this.orchestrator, {
2377
2399
  cache: this.corpusWatermarkCache, caps });
2378
2400
  let projectionAvailable = false;
@@ -2398,7 +2420,7 @@ export class EngramAccessService {
2398
2420
  ),
2399
2421
  nativeKnowledgeEnabled: this.orchestrator.config.nativeKnowledge?.enabled === true,
2400
2422
  projectionAvailable,
2401
- extraction,
2423
+ extraction: visibleExtraction,
2402
2424
  corpus: corpusCensus.watermarks,
2403
2425
  // Describes THIS response's array (round 8): a separate scan could report
2404
2426
  // complete while the shipped corpus was partial, and peers trust it.
package/src/cli.ts CHANGED
@@ -31,6 +31,7 @@ import { chunkContent } from "./chunking.js";
31
31
  import { rescoreMemoryImportance } from "./importance.js";
32
32
  import { renderQmdBacklogStatus } from "./qmd-status.js";
33
33
  import { renderExtractionLivenessStats } from "./extraction-liveness.js";
34
+ import { readAggregateExtractionWatermark } from "./orchestration/extraction-watermark.js";
34
35
  import { exportJsonBundle } from "./transfer/export-json.js";
35
36
  import { exportMarkdownBundle } from "./transfer/export-md.js";
36
37
  import { backupMemoryDir } from "./transfer/backup.js";
@@ -3653,9 +3654,7 @@ export function registerCli(
3653
3654
  .command("stats")
3654
3655
  .description("Show memory system statistics")
3655
3656
  .action(async () => {
3656
- // Ensure QMD is probed before checking availability
3657
3657
  await orchestrator.qmd.probe();
3658
-
3659
3658
  const memories = await orchestrator.storage.readAllMemories();
3660
3659
  const entities = await orchestrator.storage.readEntities();
3661
3660
  const profile = await orchestrator.storage.readProfile();
@@ -3664,7 +3663,8 @@ export function registerCli(
3664
3663
  console.log(`Total memories: ${memories.length}`);
3665
3664
  console.log(`Total entities: ${entities.length}`);
3666
3665
  console.log(`Profile size: ${profile.length} chars`);
3667
- for (const line of await renderExtractionLivenessStats(orchestrator)) console.log(line);
3666
+ const extractionWatermark = await readAggregateExtractionWatermark({ config: orchestrator.config, rootStorage: orchestrator.storage, storageForNamespace: (ns) => orchestrator.getStorage(ns) });
3667
+ for (const line of await renderExtractionLivenessStats(orchestrator, extractionWatermark)) console.log(line);
3668
3668
  console.log(`QMD: ${orchestrator.qmd.isAvailable() ? "available" : "not available"}`);
3669
3669
  for (const line of await renderQmdBacklogStatus(orchestrator.qmd, orchestrator.config.qmdEmbeddingBacklogThreshold)) console.log(line);
3670
3670
 
@@ -780,6 +780,22 @@ test("finding round-7: namespace enumeration is cached (resolved once per TTL, s
780
780
  assert.equal(resolveCalls, 2, "re-enumerated once the TTL elapsed");
781
781
  });
782
782
 
783
+ test("computeServiceCorpusCensus returns incomplete when roots refresh error is set in cache", async () => {
784
+ const cache = new CorpusWatermarkCache();
785
+ const host = {
786
+ config: parseConfig({ namespacesEnabled: true }),
787
+ getStorage: async () => ({ readAllMemories: async () => [] } as unknown as StorageManager),
788
+ };
789
+ const failingResolve = async (): Promise<CorpusNamespaceRoot[]> => {
790
+ throw new Error("disk unreadable");
791
+ };
792
+ cache.getResolvedRootsStatus(failingResolve);
793
+ await cache.whenIdle();
794
+ const census = await computeServiceCorpusCensus(host, { cache });
795
+ assert.equal(census.complete, false);
796
+ assert.deepEqual(census.watermarks, []);
797
+ });
798
+
783
799
  test("finding round-9: background refresh scans are bounded to maxConcurrentRefreshes", async () => {
784
800
  const cache = new CorpusWatermarkCache({ maxConcurrentRefreshes: 2 });
785
801
  let active = 0;
@@ -312,9 +312,13 @@ export interface CorpusNamespaceRoot {
312
312
  */
313
313
  export async function resolveCorpusNamespaceRoots(options: {
314
314
  config: PluginConfig;
315
+ propagateDiscoveryErrors?: boolean;
315
316
  }): Promise<CorpusNamespaceRoot[]> {
316
317
  const { config } = options;
317
- const configDriven = await listNamespaces({ config });
318
+ const configDriven = await listNamespaces({
319
+ config,
320
+ propagateDiscoveryErrors: options.propagateDiscoveryErrors,
321
+ });
318
322
  // Default namespace first so it wins the representative label when several
319
323
  // configured names collapse onto one root (namespaces disabled → memoryDir).
320
324
  const ordered = [
@@ -376,6 +380,7 @@ export class CorpusWatermarkCache {
376
380
  private readonly clock: () => number;
377
381
  private rootsEntry: { value: CorpusNamespaceRoot[]; expiresAt: number } | undefined;
378
382
  private rootsInFlight: Promise<void> | undefined;
383
+ private rootsRefreshError: unknown;
379
384
  private readonly queued = new Map<string, () => void>();
380
385
  private activeRefreshes = 0;
381
386
  private readonly maxConcurrentRefreshes: number;
@@ -444,9 +449,12 @@ export class CorpusWatermarkCache {
444
449
  this.rootsInFlight = compute()
445
450
  .then((value) => {
446
451
  this.rootsEntry = { value, expiresAt: this.clock() + this.ttlMs };
452
+ this.rootsRefreshError = undefined;
447
453
  })
448
- .catch(() => {
449
- // Enumeration failed: keep serving any stale roots; retry next probe.
454
+ .catch((error: unknown) => {
455
+ this.rootsRefreshError = error;
456
+ // Keep serving any stale roots; callers that require completeness
457
+ // inspect the refresh status before trusting them.
450
458
  })
451
459
  .finally(() => {
452
460
  this.rootsInFlight = undefined;
@@ -454,6 +462,14 @@ export class CorpusWatermarkCache {
454
462
  }
455
463
  return this.rootsEntry?.value;
456
464
  }
465
+
466
+ getResolvedRootsStatus(compute: () => Promise<CorpusNamespaceRoot[]>): {
467
+ roots: CorpusNamespaceRoot[] | undefined;
468
+ refreshError: unknown;
469
+ } {
470
+ const roots = this.getResolvedRoots(compute);
471
+ return { roots, refreshError: this.rootsRefreshError };
472
+ }
457
473
  /** Await every background refresh — in-flight AND queued (issue #2156 round-9) —
458
474
  * plus any roots refresh (shutdown / deterministic tests). */
459
475
  async whenIdle(): Promise<void> {
@@ -518,10 +534,17 @@ export async function computeServiceCorpusCensus(
518
534
  ): Promise<{ watermarks: CorpusWatermark[]; complete: boolean }> {
519
535
  let roots: CorpusNamespaceRoot[] | undefined;
520
536
  if (options.cache) {
521
- roots = options.cache.getResolvedRoots(() => resolveCorpusNamespaceRoots({ config: host.config }));
537
+ const { roots: cachedRoots, refreshError } = options.cache.getResolvedRootsStatus(() =>
538
+ resolveCorpusNamespaceRoots({ config: host.config, propagateDiscoveryErrors: true }),
539
+ );
540
+ if (refreshError !== undefined) return { watermarks: [], complete: false };
541
+ roots = cachedRoots;
522
542
  } else {
523
543
  try {
524
- roots = await resolveCorpusNamespaceRoots({ config: host.config });
544
+ roots = await resolveCorpusNamespaceRoots({
545
+ config: host.config,
546
+ propagateDiscoveryErrors: true,
547
+ });
525
548
  } catch {
526
549
  return { watermarks: [], complete: false }; // never enumerated — not an empty corpus
527
550
  }