@remnic/core 9.3.741 → 9.3.743

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 (286) hide show
  1. package/dist/access-boundary.d.ts +5 -5
  2. package/dist/access-boundary.js +10 -10
  3. package/dist/access-cli.js +32 -32
  4. package/dist/access-http.d.ts +5 -5
  5. package/dist/access-http.js +15 -15
  6. package/dist/access-mcp.d.ts +5 -5
  7. package/dist/access-mcp.js +14 -14
  8. package/dist/access-operations-batch.js +12 -12
  9. package/dist/access-operations.d.ts +5 -5
  10. package/dist/access-operations.js +13 -13
  11. package/dist/{access-service-Cbk-Kv_A.d.ts → access-service-BeW5GOg1.d.ts} +3 -3
  12. package/dist/access-service.d.ts +5 -5
  13. package/dist/access-service.js +9 -9
  14. package/dist/access-surface-catalog.d.ts +5 -5
  15. package/dist/action-confidence.d.ts +1 -1
  16. package/dist/active-memory-bridge.d.ts +1 -1
  17. package/dist/active-memory-bridge.js +3 -3
  18. package/dist/active-recall.d.ts +1 -1
  19. package/dist/{auto-sync-G3V5AN4C.js → auto-sync-XHSKKQAH.js} +2 -2
  20. package/dist/behavior-learner.d.ts +1 -1
  21. package/dist/behavior-signals.d.ts +1 -1
  22. package/dist/bootstrap.d.ts +4 -4
  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/buffer.js +2 -2
  27. package/dist/calibration.d.ts +1 -1
  28. package/dist/capabilities.d.ts +10 -5
  29. package/dist/capabilities.js +1 -1
  30. package/dist/{catalog-_Bap6vfD.d.ts → catalog-CX0CjOaf.d.ts} +1 -1
  31. package/dist/causal-behavior.d.ts +1 -1
  32. package/dist/causal-consolidation.d.ts +1 -1
  33. package/dist/causal-consolidation.js +2 -2
  34. package/dist/causal-trajectory-graph.d.ts +1 -1
  35. package/dist/{chunk-X5PMDVY4.js → chunk-3EA5LIFJ.js} +4 -4
  36. package/dist/{chunk-YNHRWFAP.js → chunk-4DLFJJOQ.js} +2 -2
  37. package/dist/{chunk-WIMKOTNY.js → chunk-5QANTTY2.js} +2 -2
  38. package/dist/{chunk-QCO2QFLZ.js → chunk-5UNSGRCR.js} +7 -6
  39. package/dist/{chunk-QCO2QFLZ.js.map → chunk-5UNSGRCR.js.map} +1 -1
  40. package/dist/{chunk-Y6PNYJVO.js → chunk-A2KKLCOS.js} +2 -2
  41. package/dist/{chunk-O4IWVWSW.js → chunk-AVBT5WEW.js} +3 -3
  42. package/dist/{chunk-M5KLYHHI.js → chunk-BYLC4DKI.js} +2 -2
  43. package/dist/{chunk-OZECYVGI.js → chunk-C7LDPZJJ.js} +6 -4
  44. package/dist/{chunk-OZECYVGI.js.map → chunk-C7LDPZJJ.js.map} +1 -1
  45. package/dist/{chunk-UOVDO6TC.js → chunk-CHELXDTO.js} +3 -3
  46. package/dist/{chunk-TQQN64J2.js → chunk-DBSMLRTO.js} +2 -2
  47. package/dist/{chunk-4J53ZVPQ.js → chunk-DYK27X7V.js} +3 -3
  48. package/dist/{chunk-K2N6WIZM.js → chunk-E7RGJQWP.js} +2 -2
  49. package/dist/{chunk-M4WI23X3.js → chunk-EEKDRAWX.js} +2 -2
  50. package/dist/{chunk-H3WSZWHK.js → chunk-G5FP7VSQ.js} +13 -12
  51. package/dist/chunk-G5FP7VSQ.js.map +1 -0
  52. package/dist/{chunk-BE6NEQLF.js → chunk-HAZVVOYT.js} +3 -3
  53. package/dist/{chunk-OT5K26NG.js → chunk-HM6UJPPO.js} +2 -2
  54. package/dist/{chunk-PI4JHLDD.js → chunk-IP5SANO2.js} +2 -2
  55. package/dist/{chunk-WHEF76BQ.js → chunk-JRZV3767.js} +2 -2
  56. package/dist/{chunk-OS5RKJOH.js → chunk-JZ7P26GF.js} +2 -2
  57. package/dist/{chunk-Y62QPRKV.js → chunk-K5LLP4CY.js} +2 -2
  58. package/dist/{chunk-C3Z5YJSM.js → chunk-LOPZ2DWR.js} +2 -2
  59. package/dist/{chunk-BJPL5WAL.js → chunk-MXDG6SRH.js} +3 -3
  60. package/dist/{chunk-UYYSOMS2.js → chunk-NBP3YHHS.js} +4 -4
  61. package/dist/{chunk-USHVHI6J.js → chunk-NNL4LJAD.js} +3 -3
  62. package/dist/{chunk-GPX5E36D.js → chunk-OSMBC3JU.js} +2 -2
  63. package/dist/{chunk-OUSOMUFV.js → chunk-PE6XR4GG.js} +2 -2
  64. package/dist/{chunk-DGVM5SFL.js → chunk-PHRLJFWZ.js} +3 -2
  65. package/dist/{chunk-DGVM5SFL.js.map → chunk-PHRLJFWZ.js.map} +1 -1
  66. package/dist/{chunk-CMPXLMC3.js → chunk-PI23H7FV.js} +3 -3
  67. package/dist/{chunk-WGDE2TJP.js → chunk-QOGXUNWL.js} +4 -4
  68. package/dist/{chunk-ELL5VYXC.js → chunk-RNWWAS5V.js} +3 -3
  69. package/dist/{chunk-LD6A7XG5.js → chunk-TQPSOTC7.js} +7 -7
  70. package/dist/{chunk-AX4TRSRE.js → chunk-U5WVRMCA.js} +2 -2
  71. package/dist/{chunk-773DPI6T.js → chunk-V5RVMULT.js} +11 -8
  72. package/dist/chunk-V5RVMULT.js.map +1 -0
  73. package/dist/{chunk-DBVBV2RF.js → chunk-VE54E6RP.js} +4 -4
  74. package/dist/{chunk-VC7QELR6.js → chunk-VO4VARZL.js} +1054 -869
  75. package/dist/chunk-VO4VARZL.js.map +1 -0
  76. package/dist/{chunk-G7Q4D2G3.js → chunk-VSF7AAGE.js} +1 -3
  77. package/dist/chunk-VSF7AAGE.js.map +1 -0
  78. package/dist/{chunk-OVYBENIJ.js → chunk-W3M34XT4.js} +3 -3
  79. package/dist/{chunk-XPOOY35N.js → chunk-W4H5A3TJ.js} +3 -2
  80. package/dist/chunk-W4H5A3TJ.js.map +1 -0
  81. package/dist/{chunk-7Y5KKMIP.js → chunk-WPLRJ4XM.js} +9 -8
  82. package/dist/{chunk-7Y5KKMIP.js.map → chunk-WPLRJ4XM.js.map} +1 -1
  83. package/dist/{chunk-3TUDKDTQ.js → chunk-XEADGIAA.js} +6 -6
  84. package/dist/{cli-BQW2xKdb.d.ts → cli-BYad9YYY.d.ts} +3 -3
  85. package/dist/cli.d.ts +6 -6
  86. package/dist/cli.js +21 -21
  87. package/dist/compounding/engine.d.ts +1 -1
  88. package/dist/compounding/engine.js +3 -3
  89. package/dist/compounding/preference-consolidator.d.ts +1 -1
  90. package/dist/compression-optimizer.d.ts +1 -1
  91. package/dist/config.d.ts +1 -1
  92. package/dist/connectors/codex-materialize-runner.d.ts +1 -1
  93. package/dist/connectors/codex-materialize.d.ts +1 -1
  94. package/dist/connectors/index.d.ts +1 -1
  95. package/dist/connectors/index.js +2 -2
  96. package/dist/consolidation-provenance-check.d.ts +1 -1
  97. package/dist/consolidation-undo.d.ts +1 -1
  98. package/dist/contradiction/index.d.ts +1 -1
  99. package/dist/contradiction/index.js +2 -2
  100. package/dist/{contradiction-scan-UERKJESC.js → contradiction-scan-3FJYWS3G.js} +3 -3
  101. package/dist/conversation-index/backend.d.ts +1 -1
  102. package/dist/conversation-index/chunker.d.ts +1 -1
  103. package/dist/conversation-index/faiss-adapter.d.ts +1 -1
  104. package/dist/conversation-index/indexer.d.ts +1 -1
  105. package/dist/conversation-index/search.d.ts +1 -1
  106. package/dist/day-summary.d.ts +1 -1
  107. package/dist/day-summary.js +2 -2
  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 -2
  116. package/dist/entity-schema.d.ts +1 -1
  117. package/dist/explicit-capture.d.ts +4 -4
  118. package/dist/explicit-capture.js +2 -2
  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 +4 -4
  125. package/dist/fallback-llm.d.ts +1 -1
  126. package/dist/{first-start-migration-GQ3UQNIL.js → first-start-migration-4I3VDSYS.js} +2 -2
  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-recall.js +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 +9 -9
  137. package/dist/index.js +40 -40
  138. package/dist/intent.d.ts +1 -1
  139. package/dist/lcm/engine.d.ts +1 -1
  140. package/dist/lcm/engine.js +2 -2
  141. package/dist/lcm/index.d.ts +1 -1
  142. package/dist/lcm/index.js +2 -2
  143. package/dist/lcm/summarizer.js +1 -1
  144. package/dist/lcm/tools.d.ts +1 -1
  145. package/dist/lifecycle.d.ts +1 -1
  146. package/dist/live-connectors-runner.d.ts +1 -1
  147. package/dist/local-llm.d.ts +1 -1
  148. package/dist/local-llm.js +2 -2
  149. package/dist/local-model-endpoint.d.ts +1 -1
  150. package/dist/maintenance/memory-governance.d.ts +1 -1
  151. package/dist/mcp-memory-inspector-app.d.ts +5 -5
  152. package/dist/memory-action-policy.d.ts +1 -1
  153. package/dist/memory-cache.d.ts +1 -1
  154. package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
  155. package/dist/memory-projection-store.d.ts +1 -1
  156. package/dist/memory-provenance.d.ts +1 -1
  157. package/dist/memory-worth-outcomes.d.ts +1 -1
  158. package/dist/models-json.d.ts +1 -1
  159. package/dist/namespaces/migrate.d.ts +2 -2
  160. package/dist/namespaces/migrate.js +6 -6
  161. package/dist/namespaces/principal.d.ts +1 -1
  162. package/dist/namespaces/principal.js +2 -2
  163. package/dist/namespaces/search.d.ts +1 -1
  164. package/dist/namespaces/search.js +4 -4
  165. package/dist/namespaces/storage.d.ts +2 -2
  166. package/dist/namespaces/storage.js +2 -2
  167. package/dist/native-knowledge.d.ts +1 -1
  168. package/dist/operator-toolkit.d.ts +1 -1
  169. package/dist/operator-toolkit.js +11 -11
  170. package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
  171. package/dist/orchestration/compression-guideline-coordinator.js +2 -2
  172. package/dist/orchestration/maintenance.d.ts +2 -2
  173. package/dist/orchestration/maintenance.js +6 -6
  174. package/dist/{orchestrator-BOAFN_Yr.d.ts → orchestrator-CupigmWu.d.ts} +221 -7
  175. package/dist/orchestrator.d.ts +4 -4
  176. package/dist/orchestrator.js +27 -27
  177. package/dist/patterns-cli.d.ts +1 -1
  178. package/dist/policy-runtime.d.ts +1 -1
  179. package/dist/provenance.d.ts +1 -1
  180. package/dist/qmd-recall-cache.d.ts +1 -1
  181. package/dist/qmd.d.ts +1 -1
  182. package/dist/recall-disclosure-escalation.d.ts +1 -1
  183. package/dist/recall-explain-renderer.d.ts +1 -1
  184. package/dist/recall-planner-llm.d.ts +1 -1
  185. package/dist/recall-state.d.ts +1 -1
  186. package/dist/recall-tag-filter.d.ts +1 -1
  187. package/dist/recall-xray-cli.d.ts +1 -1
  188. package/dist/recall-xray-renderer.d.ts +1 -1
  189. package/dist/recall-xray.d.ts +1 -1
  190. package/dist/resolve-auth-token.d.ts +1 -1
  191. package/dist/retrieval-agents.d.ts +1 -1
  192. package/dist/retrieval-tiers.d.ts +1 -1
  193. package/dist/routing/engine.d.ts +1 -1
  194. package/dist/routing/store.d.ts +1 -1
  195. package/dist/search/embed-helper.d.ts +1 -1
  196. package/dist/search/embed-helper.js +2 -2
  197. package/dist/search/factory.d.ts +1 -1
  198. package/dist/search/factory.js +3 -3
  199. package/dist/search/index.d.ts +1 -1
  200. package/dist/search/index.js +3 -3
  201. package/dist/search/lancedb-backend.d.ts +1 -1
  202. package/dist/search/meilisearch-backend.d.ts +1 -1
  203. package/dist/search/noop-backend.d.ts +1 -1
  204. package/dist/search/orama-backend.d.ts +1 -1
  205. package/dist/search/port.d.ts +1 -1
  206. package/dist/search/remote-backend.d.ts +1 -1
  207. package/dist/{semantic-consolidation-DsIEiCka.d.ts → semantic-consolidation-ByzGwC9c.d.ts} +1 -1
  208. package/dist/semantic-consolidation.d.ts +2 -2
  209. package/dist/semantic-consolidation.js +2 -2
  210. package/dist/semantic-rule-verifier.d.ts +1 -1
  211. package/dist/session-observer-bands.d.ts +1 -1
  212. package/dist/session-observer-state.d.ts +1 -1
  213. package/dist/shared-context/manager.d.ts +1 -1
  214. package/dist/shared-context/manager.js +2 -2
  215. package/dist/signal.d.ts +1 -1
  216. package/dist/storage.d.ts +1 -1
  217. package/dist/summarizer.d.ts +1 -1
  218. package/dist/summarizer.js +3 -3
  219. package/dist/summary-snapshot.d.ts +1 -1
  220. package/dist/temporal-supersession.d.ts +1 -1
  221. package/dist/temporal-validity.d.ts +1 -1
  222. package/dist/threading.d.ts +1 -1
  223. package/dist/tier-migration.d.ts +1 -1
  224. package/dist/tier-routing.d.ts +1 -1
  225. package/dist/{tier-stats-CSKL7BDG.js → tier-stats-5XF4UBRQ.js} +2 -2
  226. package/dist/topics.d.ts +1 -1
  227. package/dist/transcript.d.ts +1 -1
  228. package/dist/trust-score-stage.d.ts +1 -1
  229. package/dist/trust-score.d.ts +1 -1
  230. package/dist/{types-CglNn2V-.d.ts → types-5Jik3r4G.d.ts} +1 -1
  231. package/dist/types.d.ts +1 -1
  232. package/dist/utility-runtime.d.ts +1 -1
  233. package/package.json +2 -2
  234. package/src/capabilities.test.ts +0 -2
  235. package/src/capabilities.ts +7 -6
  236. package/src/cli.ts +2 -1
  237. package/src/graph-recall.ts +2 -1
  238. package/src/lcm/engine.ts +9 -6
  239. package/src/lcm/summarizer.ts +2 -1
  240. package/src/operator-toolkit.ts +2 -1
  241. package/src/orchestration/contradiction-linking-coordinator.ts +336 -0
  242. package/src/orchestration/qmd-result-resolver.ts +377 -0
  243. package/src/orchestration/recall-section-coordinator.ts +349 -0
  244. package/src/orchestrator.ts +81 -679
  245. package/src/procedural/procedure-stats.ts +2 -1
  246. package/src/wearables/pipeline.ts +5 -3
  247. package/dist/chunk-773DPI6T.js.map +0 -1
  248. package/dist/chunk-G7Q4D2G3.js.map +0 -1
  249. package/dist/chunk-H3WSZWHK.js.map +0 -1
  250. package/dist/chunk-VC7QELR6.js.map +0 -1
  251. package/dist/chunk-XPOOY35N.js.map +0 -1
  252. /package/dist/{auto-sync-G3V5AN4C.js.map → auto-sync-XHSKKQAH.js.map} +0 -0
  253. /package/dist/{chunk-X5PMDVY4.js.map → chunk-3EA5LIFJ.js.map} +0 -0
  254. /package/dist/{chunk-YNHRWFAP.js.map → chunk-4DLFJJOQ.js.map} +0 -0
  255. /package/dist/{chunk-WIMKOTNY.js.map → chunk-5QANTTY2.js.map} +0 -0
  256. /package/dist/{chunk-Y6PNYJVO.js.map → chunk-A2KKLCOS.js.map} +0 -0
  257. /package/dist/{chunk-O4IWVWSW.js.map → chunk-AVBT5WEW.js.map} +0 -0
  258. /package/dist/{chunk-M5KLYHHI.js.map → chunk-BYLC4DKI.js.map} +0 -0
  259. /package/dist/{chunk-UOVDO6TC.js.map → chunk-CHELXDTO.js.map} +0 -0
  260. /package/dist/{chunk-TQQN64J2.js.map → chunk-DBSMLRTO.js.map} +0 -0
  261. /package/dist/{chunk-4J53ZVPQ.js.map → chunk-DYK27X7V.js.map} +0 -0
  262. /package/dist/{chunk-K2N6WIZM.js.map → chunk-E7RGJQWP.js.map} +0 -0
  263. /package/dist/{chunk-M4WI23X3.js.map → chunk-EEKDRAWX.js.map} +0 -0
  264. /package/dist/{chunk-BE6NEQLF.js.map → chunk-HAZVVOYT.js.map} +0 -0
  265. /package/dist/{chunk-OT5K26NG.js.map → chunk-HM6UJPPO.js.map} +0 -0
  266. /package/dist/{chunk-PI4JHLDD.js.map → chunk-IP5SANO2.js.map} +0 -0
  267. /package/dist/{chunk-WHEF76BQ.js.map → chunk-JRZV3767.js.map} +0 -0
  268. /package/dist/{chunk-OS5RKJOH.js.map → chunk-JZ7P26GF.js.map} +0 -0
  269. /package/dist/{chunk-Y62QPRKV.js.map → chunk-K5LLP4CY.js.map} +0 -0
  270. /package/dist/{chunk-C3Z5YJSM.js.map → chunk-LOPZ2DWR.js.map} +0 -0
  271. /package/dist/{chunk-BJPL5WAL.js.map → chunk-MXDG6SRH.js.map} +0 -0
  272. /package/dist/{chunk-UYYSOMS2.js.map → chunk-NBP3YHHS.js.map} +0 -0
  273. /package/dist/{chunk-USHVHI6J.js.map → chunk-NNL4LJAD.js.map} +0 -0
  274. /package/dist/{chunk-GPX5E36D.js.map → chunk-OSMBC3JU.js.map} +0 -0
  275. /package/dist/{chunk-OUSOMUFV.js.map → chunk-PE6XR4GG.js.map} +0 -0
  276. /package/dist/{chunk-CMPXLMC3.js.map → chunk-PI23H7FV.js.map} +0 -0
  277. /package/dist/{chunk-WGDE2TJP.js.map → chunk-QOGXUNWL.js.map} +0 -0
  278. /package/dist/{chunk-ELL5VYXC.js.map → chunk-RNWWAS5V.js.map} +0 -0
  279. /package/dist/{chunk-LD6A7XG5.js.map → chunk-TQPSOTC7.js.map} +0 -0
  280. /package/dist/{chunk-AX4TRSRE.js.map → chunk-U5WVRMCA.js.map} +0 -0
  281. /package/dist/{chunk-DBVBV2RF.js.map → chunk-VE54E6RP.js.map} +0 -0
  282. /package/dist/{chunk-OVYBENIJ.js.map → chunk-W3M34XT4.js.map} +0 -0
  283. /package/dist/{chunk-3TUDKDTQ.js.map → chunk-XEADGIAA.js.map} +0 -0
  284. /package/dist/{contradiction-scan-UERKJESC.js.map → contradiction-scan-3FJYWS3G.js.map} +0 -0
  285. /package/dist/{first-start-migration-GQ3UQNIL.js.map → first-start-migration-4I3VDSYS.js.map} +0 -0
  286. /package/dist/{tier-stats-CSKL7BDG.js.map → tier-stats-5XF4UBRQ.js.map} +0 -0
@@ -0,0 +1,349 @@
1
+ /**
2
+ * Recall section coordinator — extracted from the orchestrator (issue #1526).
3
+ *
4
+ * Owns the recall-output section-budgeting subsystem: section enablement
5
+ * lookups, per-section maxChars/number resolution, section bucket appends,
6
+ * budget-aware section truncation, and final ordered assembly of recall
7
+ * sections within the configured character budget. Also builds the
8
+ * LastRecallBudgetSummary and collects the sources used for X-ray tracing.
9
+ *
10
+ * Behavior-preserving move from orchestrator.ts — no logic changes; the
11
+ * orchestrator constructs one instance and keeps thin delegating methods so
12
+ * existing call sites (recallInternal, consolidation) continue to work.
13
+ *
14
+ * Config is accessed through a getter callback (not captured at construction)
15
+ * so that post-construction reassignment of the orchestrator's live
16
+ * `config` field is honored. This mirrors the ConversationIndexCoordinator /
17
+ * TierMigrationCoordinator accessor pattern.
18
+ */
19
+
20
+ import type { PluginConfig, RecallSectionConfig } from "../types.js";
21
+ import type { LastRecallBudgetSummary } from "../recall-state.js";
22
+
23
+ /**
24
+ * Coordinator for the recall section budgeting + assembly subsystem.
25
+ *
26
+ * All methods are pure with respect to the coordinator's own state — they
27
+ * read config via the getter and operate on the caller-provided section
28
+ * buckets. No caches are held because the config-derived values are cheap
29
+ * to recompute and the buckets are transient (per-recall-call).
30
+ */
31
+ export class RecallSectionCoordinator {
32
+ private readonly getConfig: () => PluginConfig;
33
+ private readonly resolveSectionEnabled: (
34
+ sectionId: string,
35
+ defaultEnabled: boolean,
36
+ ) => boolean;
37
+
38
+ constructor(options: {
39
+ getConfig: () => PluginConfig;
40
+ resolveSectionEnabled?: (
41
+ sectionId: string,
42
+ defaultEnabled: boolean,
43
+ ) => boolean;
44
+ }) {
45
+ this.getConfig = options.getConfig;
46
+ // Default to the coordinator's own config-based check so standalone usage
47
+ // (e.g. config-recall-pipeline tests) keeps self-gating. The orchestrator
48
+ // injects its own resolver so appendRecallSection flows through the same
49
+ // overridable isRecallSectionEnabled that the recallInternal computation
50
+ // gates use — keeping compute-side and append-side enablement coherent
51
+ // (seam 13). This preserves the recall-hardening test seam where tests
52
+ // override orchestrator.isRecallSectionEnabled to isolate sections.
53
+ this.resolveSectionEnabled =
54
+ options.resolveSectionEnabled ??
55
+ ((id, def) => this.isRecallSectionEnabled(id, def));
56
+ }
57
+
58
+ getRecallSectionEntry(
59
+ sectionId: string,
60
+ ): RecallSectionConfig | undefined {
61
+ const pipeline = Array.isArray(this.getConfig().recallPipeline)
62
+ ? this.getConfig().recallPipeline
63
+ : [];
64
+ return pipeline.find((entry) => entry.id === sectionId);
65
+ }
66
+
67
+ isRecallSectionEnabled(
68
+ sectionId: string,
69
+ defaultEnabled: boolean = true,
70
+ ): boolean {
71
+ const entry = this.getRecallSectionEntry(sectionId);
72
+ if (!entry) return defaultEnabled;
73
+ return entry.enabled !== false;
74
+ }
75
+
76
+ isSpecializedRecallSectionEnabled(
77
+ sectionId: string,
78
+ topLevelEnabled: boolean,
79
+ ): boolean {
80
+ const entry = this.getRecallSectionEntry(sectionId);
81
+ if (!entry) return topLevelEnabled;
82
+ return entry.enabled === true || (topLevelEnabled && entry.enabled !== false);
83
+ }
84
+
85
+ getRecallSectionMaxChars(
86
+ sectionId: string,
87
+ ): number | null | undefined {
88
+ const entry = this.getRecallSectionEntry(sectionId);
89
+ if (!entry) return undefined;
90
+ if (entry.maxChars === null) return null;
91
+ if (typeof entry.maxChars !== "number") return undefined;
92
+ return Math.max(0, Math.floor(entry.maxChars));
93
+ }
94
+
95
+ getRecallSectionNumber(
96
+ sectionId: string,
97
+ key: keyof RecallSectionConfig,
98
+ ): number | undefined {
99
+ const entry = this.getRecallSectionEntry(sectionId);
100
+ if (!entry) return undefined;
101
+ const value = entry[key];
102
+ if (typeof value !== "number" || !Number.isFinite(value)) return undefined;
103
+ return Math.max(0, Math.floor(value));
104
+ }
105
+
106
+ appendRecallSection(
107
+ sectionBuckets: Map<string, string[]>,
108
+ sectionId: string,
109
+ content: string,
110
+ ): boolean {
111
+ // Returns true when the section was actually appended to sectionBuckets,
112
+ // false when it was dropped (disabled, empty, or maxChars===0). Callers
113
+ // that need to know whether injection occurred (e.g. xray annotation for
114
+ // peer-profile) must gate on this return value rather than on whether the
115
+ // section text was computed (Codex P2 finding, PR #764).
116
+ if (!this.resolveSectionEnabled(sectionId, true)) return false;
117
+ const trimmed = content.trim();
118
+ if (trimmed.length === 0) return false;
119
+
120
+ const maxChars = this.getRecallSectionMaxChars(sectionId);
121
+ let finalContent = trimmed;
122
+ if (maxChars === 0) return false;
123
+ if (typeof maxChars === "number" && finalContent.length > maxChars) {
124
+ finalContent = `${finalContent.slice(0, maxChars)}\n\n...(trimmed)\n`;
125
+ }
126
+
127
+ const existing = sectionBuckets.get(sectionId) ?? [];
128
+ existing.push(finalContent);
129
+ sectionBuckets.set(sectionId, existing);
130
+ return true;
131
+ }
132
+
133
+ truncateRecallSectionToBudget(
134
+ content: string,
135
+ maxChars: number,
136
+ ): string {
137
+ if (maxChars <= 0) return "";
138
+ if (content.length <= maxChars) return content;
139
+ const suffix = "\n\n...(memory context trimmed)";
140
+ if (maxChars <= suffix.length) {
141
+ return content.slice(0, maxChars);
142
+ }
143
+ return `${content.slice(0, maxChars - suffix.length)}${suffix}`;
144
+ }
145
+
146
+ protectedRecallSectionIds(
147
+ sectionBuckets: Map<string, string[]>,
148
+ ): Set<string> {
149
+ const protectedIds = new Set<string>();
150
+ if ((sectionBuckets.get("memories")?.length ?? 0) > 0) {
151
+ protectedIds.add("memories");
152
+ }
153
+ return protectedIds;
154
+ }
155
+
156
+ protectedRecallReservationChars(content: string): number {
157
+ const headingBoundary = content.indexOf("\n\n");
158
+ const headingChars =
159
+ headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);
160
+ return Math.min(content.length, Math.max(headingChars, 24));
161
+ }
162
+
163
+ estimateReservedRecallBudget(
164
+ entries: Array<{ id: string; content: string }>,
165
+ startIndex: number,
166
+ protectedIds: Set<string>,
167
+ alreadyIncludedCount: number,
168
+ ): number {
169
+ const separatorLength = "\n\n---\n\n".length;
170
+ let reserved = 0;
171
+ let simulatedIncluded = alreadyIncludedCount;
172
+ for (let i = startIndex; i < entries.length; i += 1) {
173
+ const entry = entries[i];
174
+ if (!entry || !protectedIds.has(entry.id)) continue;
175
+ if (simulatedIncluded > 0) {
176
+ reserved += separatorLength;
177
+ }
178
+ reserved += this.protectedRecallReservationChars(entry.content);
179
+ simulatedIncluded += 1;
180
+ }
181
+ return reserved;
182
+ }
183
+
184
+ getRecallBudgetChars(override?: number): number {
185
+ if (
186
+ typeof override === "number" &&
187
+ Number.isFinite(override) &&
188
+ override >= 0
189
+ ) {
190
+ return Math.floor(override);
191
+ }
192
+ const configuredBudget = this.getConfig().recallBudgetChars;
193
+ if (
194
+ typeof configuredBudget === "number" &&
195
+ Number.isFinite(configuredBudget) &&
196
+ configuredBudget >= 0
197
+ ) {
198
+ return Math.floor(configuredBudget);
199
+ }
200
+ const tokenBudget = this.getConfig().maxMemoryTokens;
201
+ if (
202
+ typeof tokenBudget === "number" &&
203
+ Number.isFinite(tokenBudget) &&
204
+ tokenBudget >= 0
205
+ ) {
206
+ return Math.floor(tokenBudget * 4);
207
+ }
208
+ return 0;
209
+ }
210
+
211
+ assembleRecallSections(
212
+ sectionBuckets: Map<string, string[]>,
213
+ budgetOverride?: number,
214
+ ): {
215
+ sections: string[];
216
+ includedIds: string[];
217
+ omittedIds: string[];
218
+ truncated: boolean;
219
+ finalChars: number;
220
+ } {
221
+ const orderedEntries: Array<{ id: string; content: string }> = [];
222
+ const pipeline = Array.isArray(this.getConfig().recallPipeline)
223
+ ? this.getConfig().recallPipeline
224
+ : [];
225
+ const orderedIds = pipeline
226
+ .filter((entry) => entry.enabled !== false)
227
+ .map((entry) => entry.id);
228
+ const seen = new Set<string>();
229
+
230
+ for (const id of orderedIds) {
231
+ const chunks = sectionBuckets.get(id);
232
+ if (!chunks || chunks.length === 0) continue;
233
+ orderedEntries.push({ id, content: chunks.join("\n\n") });
234
+ seen.add(id);
235
+ }
236
+
237
+ for (const [id, chunks] of sectionBuckets.entries()) {
238
+ if (seen.has(id)) continue;
239
+ if (chunks.length === 0) continue;
240
+ orderedEntries.push({ id, content: chunks.join("\n\n") });
241
+ }
242
+
243
+ const budget = this.getRecallBudgetChars(budgetOverride);
244
+ if (budget === 0) {
245
+ return {
246
+ sections: [],
247
+ includedIds: [],
248
+ omittedIds: orderedEntries.map((entry) => entry.id),
249
+ truncated: orderedEntries.length > 0,
250
+ finalChars: 0,
251
+ };
252
+ }
253
+
254
+ const separator = "\n\n---\n\n";
255
+ const protectedIds = this.protectedRecallSectionIds(sectionBuckets);
256
+ const sections: string[] = [];
257
+ const includedIds: string[] = [];
258
+ const omittedIds: string[] = [];
259
+ let usedChars = 0;
260
+ let truncated = false;
261
+
262
+ for (let index = 0; index < orderedEntries.length; index += 1) {
263
+ const entry = orderedEntries[index]!;
264
+ const separatorChars = sections.length > 0 ? separator.length : 0;
265
+ const reserve = protectedIds.has(entry.id)
266
+ ? 0
267
+ : this.estimateReservedRecallBudget(
268
+ orderedEntries,
269
+ index + 1,
270
+ protectedIds,
271
+ sections.length + 1,
272
+ );
273
+ const availableForEntry = budget - usedChars - separatorChars - reserve;
274
+ if (availableForEntry <= 0) {
275
+ omittedIds.push(entry.id);
276
+ truncated = true;
277
+ continue;
278
+ }
279
+ const finalContent = this.truncateRecallSectionToBudget(
280
+ entry.content,
281
+ availableForEntry,
282
+ );
283
+ if (!finalContent) {
284
+ omittedIds.push(entry.id);
285
+ truncated = true;
286
+ continue;
287
+ }
288
+ if (finalContent.length < entry.content.length) {
289
+ truncated = true;
290
+ }
291
+ sections.push(finalContent);
292
+ includedIds.push(entry.id);
293
+ usedChars += separatorChars + finalContent.length;
294
+ }
295
+
296
+ return {
297
+ sections,
298
+ includedIds,
299
+ omittedIds,
300
+ truncated,
301
+ finalChars: usedChars,
302
+ };
303
+ }
304
+
305
+ buildLastRecallBudgetSummary(options: {
306
+ requestedTopK?: number;
307
+ recallResultLimit: number;
308
+ qmdFetchLimit: number;
309
+ qmdHybridFetchLimit: number;
310
+ finalContextChars?: number;
311
+ truncated?: boolean;
312
+ includedSections?: string[];
313
+ omittedSections?: string[];
314
+ }): LastRecallBudgetSummary {
315
+ return {
316
+ requestedTopK: options.requestedTopK,
317
+ appliedTopK: options.recallResultLimit,
318
+ recallBudgetChars: this.getRecallBudgetChars(),
319
+ maxMemoryTokens: this.getConfig().maxMemoryTokens,
320
+ qmdFetchLimit: options.qmdFetchLimit,
321
+ qmdHybridFetchLimit: options.qmdHybridFetchLimit,
322
+ finalContextChars: options.finalContextChars,
323
+ truncated: options.truncated,
324
+ includedSections: [...(options.includedSections ?? [])],
325
+ omittedSections: [...(options.omittedSections ?? [])],
326
+ };
327
+ }
328
+
329
+ collectLastRecallSources(
330
+ sectionBuckets: Map<string, string[]>,
331
+ recallSource:
332
+ | "none"
333
+ | "hot_qmd"
334
+ | "hot_embedding"
335
+ | "cold_fallback"
336
+ | "recent_scan",
337
+ ): string[] {
338
+ const used = new Set<string>();
339
+ if (recallSource !== "none") {
340
+ used.add(recallSource);
341
+ }
342
+ for (const [sectionId, chunks] of sectionBuckets.entries()) {
343
+ if (chunks.length > 0) {
344
+ used.add(sectionId);
345
+ }
346
+ }
347
+ return [...used];
348
+ }
349
+ }