@remnic/core 1.1.9 → 1.1.10

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 (204) hide show
  1. package/dist/access-cli.js +35 -32
  2. package/dist/access-cli.js.map +1 -1
  3. package/dist/access-http.d.ts +8 -7
  4. package/dist/access-http.js +17 -14
  5. package/dist/access-mcp.d.ts +8 -7
  6. package/dist/access-mcp.js +16 -13
  7. package/dist/{access-service-BJCIjVRY.d.ts → access-service-BTTNyo1i.d.ts} +5 -3
  8. package/dist/access-service.d.ts +8 -7
  9. package/dist/access-service.js +15 -12
  10. package/dist/active-memory-bridge.d.ts +2 -1
  11. package/dist/active-recall.d.ts +2 -1
  12. package/dist/behavior-learner.d.ts +2 -1
  13. package/dist/behavior-signals.d.ts +2 -1
  14. package/dist/bootstrap.d.ts +7 -6
  15. package/dist/briefing.d.ts +3 -2
  16. package/dist/briefing.js +3 -3
  17. package/dist/buffer-surprise-report.d.ts +2 -1
  18. package/dist/buffer.d.ts +3 -2
  19. package/dist/calibration.d.ts +4 -1
  20. package/dist/calibration.js +10 -5
  21. package/dist/calibration.js.map +1 -1
  22. package/dist/causal-behavior.d.ts +2 -1
  23. package/dist/causal-consolidation.d.ts +5 -2
  24. package/dist/causal-consolidation.js +14 -8
  25. package/dist/causal-consolidation.js.map +1 -1
  26. package/dist/{chunk-ICULSMDG.js → chunk-2YMTO4ZJ.js} +2 -2
  27. package/dist/{chunk-XL3UCAZA.js → chunk-363MWCD3.js} +35 -35
  28. package/dist/{chunk-PHQH2VUO.js → chunk-36CTNQY7.js} +7 -7
  29. package/dist/{chunk-XN4D6Z7X.js → chunk-4DXC6HQQ.js} +5 -3
  30. package/dist/chunk-4DXC6HQQ.js.map +1 -0
  31. package/dist/{chunk-OWGGXPKV.js → chunk-57QNCUEZ.js} +5 -5
  32. package/dist/{chunk-FPWUENQH.js → chunk-5GCNE7CN.js} +90 -486
  33. package/dist/chunk-5GCNE7CN.js.map +1 -0
  34. package/dist/{chunk-LOBRX7VD.js → chunk-5UM2VJ6D.js} +12 -1
  35. package/dist/chunk-5UM2VJ6D.js.map +1 -0
  36. package/dist/{chunk-KMWZXT5T.js → chunk-6XA7UN4Z.js} +2 -2
  37. package/dist/{chunk-G6NX57V2.js → chunk-C5HUWVH2.js} +2 -2
  38. package/dist/{chunk-NN3TS5BM.js → chunk-D54LZC5L.js} +4 -4
  39. package/dist/{chunk-3VRIIII5.js → chunk-ERUDW6DU.js} +65 -5
  40. package/dist/chunk-ERUDW6DU.js.map +1 -0
  41. package/dist/{chunk-U4SZXGEO.js → chunk-EYNQTST2.js} +2 -2
  42. package/dist/chunk-HJYHRE4S.js +647 -0
  43. package/dist/chunk-HJYHRE4S.js.map +1 -0
  44. package/dist/{chunk-M3DK45UM.js → chunk-I6BQZSML.js} +4 -4
  45. package/dist/chunk-IBX3VFOM.js +446 -0
  46. package/dist/chunk-IBX3VFOM.js.map +1 -0
  47. package/dist/{chunk-G3G3LY22.js → chunk-KBYWQWSB.js} +7 -7
  48. package/dist/chunk-KWBPHZUU.js +83 -0
  49. package/dist/chunk-KWBPHZUU.js.map +1 -0
  50. package/dist/{chunk-CTYRIJ5E.js → chunk-LIO5X3CM.js} +2 -2
  51. package/dist/{chunk-MJLUHRSF.js → chunk-MCC6KDQF.js} +2 -2
  52. package/dist/{chunk-J3P6WSFZ.js → chunk-O4XJUPSF.js} +2 -2
  53. package/dist/{chunk-6OAQEOGV.js → chunk-PB5KW5PL.js} +2 -2
  54. package/dist/{chunk-Y3VT6ZCP.js → chunk-PHNGXFQ6.js} +5 -3
  55. package/dist/chunk-PHNGXFQ6.js.map +1 -0
  56. package/dist/{chunk-2MVUXO4H.js → chunk-RXTFCYQF.js} +2 -2
  57. package/dist/{chunk-Q7FJ5ZHM.js → chunk-S3IP6R6K.js} +8 -2
  58. package/dist/{chunk-Q7FJ5ZHM.js.map → chunk-S3IP6R6K.js.map} +1 -1
  59. package/dist/{chunk-ET4BL42V.js → chunk-VQXK37XA.js} +1 -1
  60. package/dist/{chunk-ET4BL42V.js.map → chunk-VQXK37XA.js.map} +1 -1
  61. package/dist/{chunk-FLBYSB2V.js → chunk-VX2IUQFE.js} +94 -8
  62. package/dist/chunk-VX2IUQFE.js.map +1 -0
  63. package/dist/{chunk-QPLYTPYL.js → chunk-WGK4VHGP.js} +77 -15
  64. package/dist/chunk-WGK4VHGP.js.map +1 -0
  65. package/dist/{chunk-7SFAENUZ.js → chunk-WTFWLUSX.js} +2 -2
  66. package/dist/{chunk-A6PGANSE.js → chunk-Y5KDIOKF.js} +3 -3
  67. package/dist/{chunk-KIF7QNKL.js → chunk-Z5S5HNGY.js} +5 -3
  68. package/dist/chunk-Z5S5HNGY.js.map +1 -0
  69. package/dist/{chunk-BIHCWSWA.js → chunk-ZL4S7ARC.js} +3 -3
  70. package/dist/{cli-BojuyOOp.d.ts → cli-BrEwQTnW.d.ts} +4 -4
  71. package/dist/cli.d.ts +9 -8
  72. package/dist/cli.js +27 -25
  73. package/dist/codex-cli-fallback.d.ts +44 -0
  74. package/dist/codex-cli-fallback.js +12 -0
  75. package/dist/{codex-materialize-YVC2wb6n.d.ts → codex-materialize-CQlLTzke.d.ts} +1 -1
  76. package/dist/compression-optimizer.d.ts +2 -1
  77. package/dist/config.d.ts +2 -1
  78. package/dist/consolidation-provenance-check.d.ts +3 -2
  79. package/dist/consolidation-undo.d.ts +3 -2
  80. package/dist/day-summary.d.ts +2 -1
  81. package/dist/delinearize.d.ts +2 -1
  82. package/dist/direct-answer-wiring.d.ts +2 -1
  83. package/dist/direct-answer.d.ts +2 -1
  84. package/dist/embedding-fallback.d.ts +2 -1
  85. package/dist/{engine-EDFFOWDD.js → engine-FOC3IJLA.js} +4 -4
  86. package/dist/entity-retrieval.d.ts +3 -2
  87. package/dist/entity-retrieval.js +3 -3
  88. package/dist/entity-schema.d.ts +2 -1
  89. package/dist/explicit-capture.d.ts +7 -6
  90. package/dist/explicit-cue-recall.js +1 -1
  91. package/dist/extraction-judge-telemetry.d.ts +2 -1
  92. package/dist/extraction-judge-training.d.ts +2 -1
  93. package/dist/extraction-judge.d.ts +2 -1
  94. package/dist/extraction.d.ts +2 -1
  95. package/dist/extraction.js +6 -4
  96. package/dist/fallback-llm.d.ts +8 -1
  97. package/dist/fallback-llm.js +5 -3
  98. package/dist/identity-continuity.d.ts +2 -1
  99. package/dist/importance.d.ts +2 -1
  100. package/dist/index-1qIcnbG1.d.ts +34 -0
  101. package/dist/index.d.ts +15 -13
  102. package/dist/index.js +57 -50
  103. package/dist/index.js.map +1 -1
  104. package/dist/intent.d.ts +2 -1
  105. package/dist/lifecycle.d.ts +2 -1
  106. package/dist/live-connectors-runner.d.ts +2 -1
  107. package/dist/local-llm.d.ts +2 -1
  108. package/dist/memory-action-policy.d.ts +2 -1
  109. package/dist/memory-cache.d.ts +2 -1
  110. package/dist/{memory-governance-AAQPBZEP.js → memory-governance-F3QOJGEY.js} +4 -4
  111. package/dist/memory-governance-F3QOJGEY.js.map +1 -0
  112. package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
  113. package/dist/{memory-projection-store-BW8u5U0u.d.ts → memory-projection-store-CY8TU40w.d.ts} +1 -1
  114. package/dist/memory-projection-store.d.ts +3 -2
  115. package/dist/memory-worth-outcomes.d.ts +3 -2
  116. package/dist/models-json.d.ts +2 -1
  117. package/dist/native-knowledge.d.ts +2 -1
  118. package/dist/objective-state-writers.d.ts +23 -1
  119. package/dist/objective-state-writers.js +10 -306
  120. package/dist/objective-state-writers.js.map +1 -1
  121. package/dist/objective-state.d.ts +7 -1
  122. package/dist/objective-state.js +3 -1
  123. package/dist/operator-toolkit.d.ts +3 -2
  124. package/dist/operator-toolkit.js +6 -6
  125. package/dist/{orchestrator-CYqmqxco.d.ts → orchestrator-6IvQ-Phj.d.ts} +4 -3
  126. package/dist/orchestrator.d.ts +7 -6
  127. package/dist/orchestrator.js +29 -27
  128. package/dist/patterns-cli.d.ts +2 -1
  129. package/dist/policy-runtime.d.ts +2 -1
  130. package/dist/{port-Br27H8dy.d.ts → port-B6VEDIkC.d.ts} +1 -1
  131. package/dist/qmd-recall-cache.d.ts +3 -2
  132. package/dist/qmd.d.ts +3 -2
  133. package/dist/recall-disclosure-escalation.d.ts +2 -1
  134. package/dist/recall-explain-renderer.d.ts +2 -1
  135. package/dist/recall-explain-renderer.js +3 -3
  136. package/dist/recall-state.d.ts +2 -1
  137. package/dist/recall-tag-filter.d.ts +2 -1
  138. package/dist/recall-xray-cli.d.ts +2 -1
  139. package/dist/recall-xray-cli.js +4 -4
  140. package/dist/recall-xray-renderer.d.ts +2 -1
  141. package/dist/recall-xray-renderer.js +3 -3
  142. package/dist/recall-xray.d.ts +2 -1
  143. package/dist/recall-xray.js +2 -2
  144. package/dist/resolve-auth-token.d.ts +2 -1
  145. package/dist/resolve-provider-secret.d.ts +2 -1
  146. package/dist/resolve-provider-secret.js +3 -1
  147. package/dist/resume-bundles.js +3 -3
  148. package/dist/retrieval-agents.d.ts +3 -2
  149. package/dist/retrieval-tiers.d.ts +2 -1
  150. package/dist/{semantic-consolidation-GPcLr9BQ.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +2 -2
  151. package/dist/semantic-consolidation.d.ts +4 -3
  152. package/dist/semantic-consolidation.js +3 -3
  153. package/dist/semantic-rule-promotion.js +3 -3
  154. package/dist/semantic-rule-verifier.d.ts +2 -1
  155. package/dist/semantic-rule-verifier.js +3 -3
  156. package/dist/session-observer-bands.d.ts +2 -1
  157. package/dist/session-observer-state.d.ts +2 -1
  158. package/dist/signal.d.ts +2 -1
  159. package/dist/storage.d.ts +3 -2
  160. package/dist/storage.js +2 -2
  161. package/dist/summarizer.d.ts +2 -1
  162. package/dist/summarizer.js +6 -4
  163. package/dist/summary-snapshot.d.ts +2 -1
  164. package/dist/temporal-supersession.d.ts +3 -2
  165. package/dist/temporal-validity.d.ts +2 -1
  166. package/dist/threading.d.ts +2 -1
  167. package/dist/tier-migration.d.ts +4 -3
  168. package/dist/tier-routing.d.ts +2 -1
  169. package/dist/topics.d.ts +2 -1
  170. package/dist/transcript.d.ts +2 -1
  171. package/dist/types.d.ts +2693 -1
  172. package/dist/types.js +1 -1
  173. package/dist/utility-runtime.d.ts +2 -1
  174. package/dist/verified-recall.js +3 -3
  175. package/package.json +1 -1
  176. package/dist/chunk-3VRIIII5.js.map +0 -1
  177. package/dist/chunk-FLBYSB2V.js.map +0 -1
  178. package/dist/chunk-FPWUENQH.js.map +0 -1
  179. package/dist/chunk-KIF7QNKL.js.map +0 -1
  180. package/dist/chunk-LOBRX7VD.js.map +0 -1
  181. package/dist/chunk-QPLYTPYL.js.map +0 -1
  182. package/dist/chunk-XN4D6Z7X.js.map +0 -1
  183. package/dist/chunk-Y3VT6ZCP.js.map +0 -1
  184. package/dist/types-Bmp9ssU2.d.ts +0 -2714
  185. /package/dist/{chunk-ICULSMDG.js.map → chunk-2YMTO4ZJ.js.map} +0 -0
  186. /package/dist/{chunk-XL3UCAZA.js.map → chunk-363MWCD3.js.map} +0 -0
  187. /package/dist/{chunk-PHQH2VUO.js.map → chunk-36CTNQY7.js.map} +0 -0
  188. /package/dist/{chunk-OWGGXPKV.js.map → chunk-57QNCUEZ.js.map} +0 -0
  189. /package/dist/{chunk-KMWZXT5T.js.map → chunk-6XA7UN4Z.js.map} +0 -0
  190. /package/dist/{chunk-G6NX57V2.js.map → chunk-C5HUWVH2.js.map} +0 -0
  191. /package/dist/{chunk-NN3TS5BM.js.map → chunk-D54LZC5L.js.map} +0 -0
  192. /package/dist/{chunk-U4SZXGEO.js.map → chunk-EYNQTST2.js.map} +0 -0
  193. /package/dist/{chunk-M3DK45UM.js.map → chunk-I6BQZSML.js.map} +0 -0
  194. /package/dist/{chunk-G3G3LY22.js.map → chunk-KBYWQWSB.js.map} +0 -0
  195. /package/dist/{chunk-CTYRIJ5E.js.map → chunk-LIO5X3CM.js.map} +0 -0
  196. /package/dist/{chunk-MJLUHRSF.js.map → chunk-MCC6KDQF.js.map} +0 -0
  197. /package/dist/{chunk-J3P6WSFZ.js.map → chunk-O4XJUPSF.js.map} +0 -0
  198. /package/dist/{chunk-6OAQEOGV.js.map → chunk-PB5KW5PL.js.map} +0 -0
  199. /package/dist/{chunk-2MVUXO4H.js.map → chunk-RXTFCYQF.js.map} +0 -0
  200. /package/dist/{chunk-7SFAENUZ.js.map → chunk-WTFWLUSX.js.map} +0 -0
  201. /package/dist/{chunk-A6PGANSE.js.map → chunk-Y5KDIOKF.js.map} +0 -0
  202. /package/dist/{chunk-BIHCWSWA.js.map → chunk-ZL4S7ARC.js.map} +0 -0
  203. /package/dist/{engine-EDFFOWDD.js.map → codex-cli-fallback.js.map} +0 -0
  204. /package/dist/{memory-governance-AAQPBZEP.js.map → engine-FOC3IJLA.js.map} +0 -0
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/orchestrator.ts","../src/migrate/from-engram.ts","../src/procedural/procedure-recall.ts","../src/maintenance/memory-governance-cron.ts","../src/maintenance/pattern-reinforcement.ts","../src/dedup/semantic.ts","../src/taxonomy/default-taxonomy.ts","../src/taxonomy/resolver-doc-generator.ts","../src/taxonomy/taxonomy-loader.ts","../src/lcm/schema.ts","../src/message-parts/index.ts","../src/lcm/archive.ts","../src/lcm/dag.ts","../src/lcm/summarizer.ts","../src/lcm/recall.ts","../src/lcm/queue.ts","../src/lcm/engine.ts","../src/lcm/tools.ts","../src/conversation-index/chunker.ts","../src/conversation-index/cleanup.ts","../src/coding/coding-namespace.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport {\n mkdir,\n readdir,\n readFile,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { formatDaySummaryMemories } from \"./day-summary.js\";\nimport { resolveHomeDir } from \"./runtime/env.js\";\nimport { migrateFromEngram } from \"./migrate/from-engram.js\";\nimport { SmartBuffer } from \"./buffer.js\";\nimport { chunkContent, type ChunkingConfig } from \"./chunking.js\";\nimport { semanticChunkContent, type SemanticChunkResult } from \"./semantic-chunking.js\";\nimport { ExtractionEngine } from \"./extraction.js\";\nimport { isAboveImportanceThreshold, scoreImportance } from \"./importance.js\";\nimport {\n judgeFactDurability,\n createVerdictCache,\n createDeferCountMap,\n getVerdictKind,\n validateProcedureExtraction,\n type JudgeBatchResult,\n type JudgeCandidate,\n type JudgeVerdict,\n} from \"./extraction-judge.js\";\nimport {\n EXTRACTION_JUDGE_VERDICT_CATEGORY,\n recordJudgeVerdict,\n} from \"./extraction-judge-telemetry.js\";\nimport { recordJudgeTrainingPair } from \"./extraction-judge-training.js\";\nimport { buildProcedurePersistBody } from \"./procedural/procedure-types.js\";\nimport { buildProcedureRecallSection } from \"./procedural/procedure-recall.js\";\nimport {\n attachCitation,\n type CitationContext,\n hasCitationForTemplate,\n stripCitationForTemplate,\n} from \"./source-attribution.js\";\n// stripCitation (default-format only) is intentionally NOT used on the\n// legacy archive path — replaced by skip-with-warning (Finding 2 — Urgw).\n// stripCitationForTemplate IS used for pre-tagged dedup canonicalization.\nimport { findUnresolvedEntityRefs } from \"./reconstruct.js\";\nimport type {\n SearchBackend,\n SearchExecutionOptions,\n SearchQueryOptions,\n} from \"./search/port.js\";\nimport {\n createSearchBackend,\n createConversationIndexRuntime,\n} from \"./search/factory.js\";\nimport { NoopSearchBackend } from \"./search/noop-backend.js\";\nimport {\n compareEntityTimestamps,\n StorageManager,\n ContentHashIndex,\n fingerprintEntityStructuredFacts,\n normalizeEntityName,\n normalizeAttributePairs,\n parseEntityFile,\n} from \"./storage.js\";\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\nimport { ThreadingManager } from \"./threading.js\";\nimport { extractTopics } from \"./topics.js\";\nimport { TranscriptManager } from \"./transcript.js\";\nimport { HourlySummarizer } from \"./summarizer.js\";\nimport { LocalLlmClient } from \"./local-llm.js\";\nimport { FallbackLlmClient } from \"./fallback-llm.js\";\nimport {\n ensureDaySummaryCron,\n ensureNightlyGovernanceCron,\n ensureProceduralMiningCron,\n ensureContradictionScanCron,\n ensurePatternReinforcementCron,\n ensureGraphEdgeDecayCron,\n graphEdgeDecayCadenceToCronExpr,\n} from \"./maintenance/memory-governance-cron.js\";\nimport {\n runLiveConnectorsOnce,\n type LiveConnectorsRunSummary,\n} from \"./live-connectors-runner.js\";\nimport {\n runPatternReinforcement,\n type PatternReinforcementResult,\n} from \"./maintenance/pattern-reinforcement.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { applyRuntimeRetrievalPolicy, expandQuery } from \"./retrieval.js\";\nimport {\n mergeWithAgentResults,\n runDirectAgent,\n runTemporalAgent,\n shouldRunAgent,\n type ParallelSearchResult,\n} from \"./retrieval-agents.js\";\nimport { RerankCache, rerankLocalOrNoop } from \"./rerank.js\";\nimport {\n applyMemoryWorthFilter,\n buildMemoryWorthCounterMap,\n type MemoryWorthCounters,\n} from \"./memory-worth-filter.js\";\nimport { reorderRecallResultsWithMmr } from \"./recall-mmr.js\";\nimport { applyReasoningTraceBoost } from \"./reasoning-trace-recall.js\";\nimport {\n applyTemporalSupersession,\n normalizeSupersessionKey,\n shouldFilterSupersededFromRecall,\n} from \"./temporal-supersession.js\";\nimport { isValidAsOf } from \"./temporal-validity.js\";\nimport { RelevanceStore } from \"./relevance.js\";\nimport { NegativeExampleStore } from \"./negative.js\";\nimport {\n LastRecallStore,\n type LastRecallBudgetSummary,\n TierMigrationStatusStore,\n clampGraphRecallExpandedEntries,\n type GraphRecallExpandedEntry,\n type LastRecallSnapshot,\n type TierMigrationCycleSummary,\n type TierMigrationStatusSnapshot,\n} from \"./recall-state.js\";\nimport {\n buildXraySnapshot,\n type RecallFilterTrace,\n type RecallXrayResult,\n type RecallXrayScoreDecomposition,\n type RecallXraySnapshot,\n type RecallXrayServedBy,\n} from \"./recall-xray.js\";\nimport {\n recordEvalShadowRecall,\n type EvalShadowRecallRecord,\n} from \"./evals.js\";\nimport { SessionObserverState } from \"./session-observer-state.js\";\nimport {\n abortError as sharedAbortError,\n isAbortError,\n throwIfAborted as sharedThrowIfAborted,\n} from \"./abort-error.js\";\nimport { CODEX_THREAD_KEY_PREFIX } from \"./codex-thread-key.js\";\nimport { isDisagreementPrompt } from \"./signal.js\";\nimport { lintWorkspaceFiles, rotateMarkdownFileToArchive } from \"./hygiene.js\";\nimport { EmbeddingFallback } from \"./embedding-fallback.js\";\nimport {\n decideSemanticDedup,\n type SemanticDedupDecision,\n type SemanticDedupHit,\n} from \"./dedup/semantic.js\";\nimport { BootstrapEngine } from \"./bootstrap.js\";\nimport { parseQmdExplain } from \"./qmd.js\";\nimport {\n buildQmdRecallCacheKey,\n getCachedQmdRecall,\n setCachedQmdRecall,\n} from \"./qmd-recall-cache.js\";\nimport {\n buildEntityRecallSection,\n entityRecentTranscriptLookbackHours,\n readRecentEntityTranscriptEntries,\n} from \"./entity-retrieval.js\";\nimport { buildExplicitCueRecallSection } from \"./explicit-cue-recall.js\";\nimport {\n hasBroadGraphIntent,\n inferIntentFromText,\n intentCompatibilityScore,\n planRecallMode,\n} from \"./intent.js\";\nimport { buildRecallQueryPolicy } from \"./recall-query-policy.js\";\nimport { parseMemoryActionEligibilityContext } from \"./schemas.js\";\nimport { evaluateMemoryActionPolicy } from \"./memory-action-policy.js\";\nimport {\n buildCompressionGuidelinesMarkdown as buildCompressionGuidelinesMarkdownV2,\n computeCompressionGuidelineCandidate,\n refineCompressionGuidelineCandidateSemantically,\n renderCompressionGuidelinesMarkdown,\n} from \"./compression-optimizer.js\";\nimport { createRecallSectionMetricRecorder } from \"./recall-qos.js\";\nimport { BoxBuilder, type BoxFrontmatter } from \"./boxes.js\";\nimport { classifyMemoryKind } from \"./himem.js\";\nimport { TmtBuilder } from \"./tmt.js\";\nimport {\n decideLifecycleTransition,\n resolveLifecycleState,\n type LifecycleSignals,\n} from \"./lifecycle.js\";\nimport { isActiveMemoryStatus } from \"./memory-lifecycle-ledger-utils.js\";\nimport {\n indexMemoriesBatch,\n clearIndexes,\n indexesExist,\n deindexMemory,\n queryByDateRangeAsync,\n queryByTagsAsync,\n isTemporalQuery,\n recencyWindowFromPrompt,\n extractTagsFromPrompt,\n resolvePromptTagPrefilterAsync,\n} from \"./temporal-index.js\";\nimport { GraphIndex } from \"./graph.js\";\nimport {\n searchCausalTrajectories,\n type CausalTrajectorySearchResult,\n} from \"./causal-trajectory.js\";\nimport {\n searchObjectiveStateSnapshots,\n type ObjectiveStateSearchResult,\n} from \"./objective-state.js\";\nimport {\n listTrustZoneRecords,\n searchTrustZoneRecords,\n type TrustZoneSearchResult,\n} from \"./trust-zones.js\";\nimport { tryDirectAnswer, type DirectAnswerSources } from \"./direct-answer-wiring.js\";\nimport { DEFAULT_TAXONOMY } from \"./taxonomy/index.js\";\nimport {\n searchHarmonicRetrieval,\n type HarmonicRetrievalResult,\n} from \"./harmonic-retrieval.js\";\nimport {\n searchVerifiedEpisodes,\n type VerifiedEpisodeResult,\n} from \"./verified-recall.js\";\nimport {\n searchVerifiedSemanticRules,\n type VerifiedSemanticRuleResult,\n} from \"./semantic-rule-verifier.js\";\nimport { applyCommitmentLedgerLifecycle } from \"./commitment-ledger.js\";\nimport {\n searchWorkProductLedgerEntries,\n type WorkProductLedgerSearchResult,\n} from \"./work-product-ledger.js\";\nimport {\n collectNativeKnowledgeChunks,\n formatNativeKnowledgeSection,\n searchNativeKnowledge,\n} from \"./native-knowledge.js\";\nimport { normalizeReplaySessionKey, type ReplayTurn } from \"./replay/types.js\";\nimport type { ImportTurn } from \"./bulk-import/types.js\";\nimport {\n confidenceTier,\n type MemoryIntent,\n type MemorySummary,\n} from \"./types.js\";\nimport { LcmEngine } from \"./lcm/index.js\";\nimport { shouldSkipImplicitExtraction } from \"./explicit-capture.js\";\nimport {\n findSimilarClusters,\n buildConsolidationPrompt,\n parseConsolidationResponse,\n buildOperatorAwareConsolidationPrompt,\n parseOperatorAwareConsolidationResponse,\n chooseConsolidationOperator,\n buildExtensionsBlockForConsolidation,\n materializeAfterSemanticConsolidation,\n type SemanticConsolidationLlmOperator,\n type SemanticConsolidationResult,\n} from \"./semantic-consolidation.js\";\nimport { chunkTranscriptEntries } from \"./conversation-index/chunker.js\";\nimport { writeConversationChunks } from \"./conversation-index/indexer.js\";\nimport { cleanupConversationChunks } from \"./conversation-index/cleanup.js\";\nimport {\n type ConversationIndexBackend,\n type ConversationIndexBackendInspection,\n type ConversationQmdRuntime,\n} from \"./conversation-index/backend.js\";\nimport { NamespaceStorageRouter } from \"./namespaces/storage.js\";\nimport {\n canReadNamespace,\n defaultNamespaceForPrincipal,\n recallNamespacesForPrincipal,\n resolvePrincipal,\n} from \"./namespaces/principal.js\";\nimport {\n combineNamespaces,\n resolveCodingNamespaceOverlay,\n} from \"./coding/coding-namespace.js\";\nimport type { CodingContext } from \"./types.js\";\nimport { NamespaceSearchRouter } from \"./namespaces/search.js\";\nimport { SharedContextManager } from \"./shared-context/manager.js\";\nimport {\n CompoundingEngine,\n defaultTierMigrationCycleBudget,\n} from \"./compounding/engine.js\";\n// IRC preference consolidation — used by eval adapter directly;\n// orchestrator integration planned for future PR.\n// import { consolidatePreferences, buildQueryAwarePreferenceSection, synthesizePreferencesFromLcm } from \"./compounding/preference-consolidator.js\";\nimport { TierMigrationExecutor } from \"./tier-migration.js\";\nimport { decideTierTransition, type MemoryTier } from \"./tier-routing.js\";\nimport {\n selectRouteRule,\n type RouteRule,\n type RoutingEngineOptions,\n} from \"./routing/engine.js\";\nimport { RoutingRulesStore } from \"./routing/store.js\";\nimport {\n PolicyRuntimeManager,\n type RuntimePolicyValues,\n} from \"./policy-runtime.js\";\nimport {\n applyUtilityPromotionRuntimePolicy,\n applyUtilityRankingRuntimeDelta,\n loadUtilityRuntimeValues,\n type UtilityRuntimeValues,\n} from \"./utility-runtime.js\";\nimport {\n buildBehaviorSignalsForMemory,\n dedupeBehaviorSignalsByMemoryAndHash,\n} from \"./behavior-signals.js\";\nimport { ProfilingCollector } from \"./profiling.js\";\nimport { keyring, secureStoreDir } from \"./secure-store/index.js\";\nimport type {\n AccessTrackingEntry,\n BehaviorLoopPolicyState,\n BehaviorSignalEvent,\n BootstrapOptions,\n BootstrapResult,\n BufferTurn,\n ContinuityIncidentRecord,\n ConsolidationObservation,\n EngramTraceEvent,\n ExtractionResult,\n IdentityInjectionMode,\n LifecycleState,\n MemoryActionEvent,\n MemoryActionType,\n MemoryLink,\n MemoryFile,\n MemoryFrontmatter,\n DaySummaryResult,\n PluginConfig,\n QmdSearchResult,\n RecallPlanMode,\n RecallSectionConfig,\n RecallTierExplain,\n EntityStructuredSection,\n EntityTimelineEntry,\n} from \"./types.js\";\n\nexport function dedupeEntitySynthesisEvidenceEntries(\n entries: EntityTimelineEntry[],\n): EntityTimelineEntry[] {\n const dedupedEvidenceEntries: EntityTimelineEntry[] = [];\n const evidenceByFact = new Map<string, {\n newest: EntityTimelineEntry;\n oldest: EntityTimelineEntry;\n }>();\n\n for (const entry of entries) {\n const normalizedFact = entry.text.trim();\n if (!normalizedFact) continue;\n const existing = evidenceByFact.get(normalizedFact);\n if (!existing) {\n evidenceByFact.set(normalizedFact, { newest: entry, oldest: entry });\n continue;\n }\n if (compareEntityTimestamps(entry.timestamp, existing.newest.timestamp) > 0) {\n existing.newest = entry;\n }\n if (compareEntityTimestamps(entry.timestamp, existing.oldest.timestamp) < 0) {\n existing.oldest = entry;\n }\n }\n\n for (const { newest, oldest } of evidenceByFact.values()) {\n dedupedEvidenceEntries.push(newest);\n const newestKey = [\n newest.timestamp,\n newest.source ?? \"\",\n newest.sessionKey ?? \"\",\n newest.principal ?? \"\",\n newest.text,\n ].join(\"\\u0000\");\n const oldestKey = [\n oldest.timestamp,\n oldest.source ?? \"\",\n oldest.sessionKey ?? \"\",\n oldest.principal ?? \"\",\n oldest.text,\n ].join(\"\\u0000\");\n if (oldestKey !== newestKey) {\n dedupedEvidenceEntries.push(oldest);\n }\n }\n\n return dedupedEvidenceEntries;\n}\n\nfunction flattenStructuredSectionEvidence(\n sections: EntityStructuredSection[] | undefined,\n): EntityTimelineEntry[] {\n return (sections ?? []).flatMap((section) =>\n section.facts\n .map((fact) => fact.trim())\n .filter((fact) => fact.length > 0)\n .map((fact) => ({\n timestamp: \"\",\n text: fact,\n source: `section:${section.title}`,\n })),\n );\n}\n\nfunction fingerprintEntitySynthesisEvidence(entity: {\n timeline: EntityTimelineEntry[];\n structuredSections?: EntityStructuredSection[];\n}): string {\n const fingerprint = createHash(\"sha256\");\n const timelineEntries = entity.timeline\n .map((entry) => [\n entry.timestamp,\n entry.source ?? \"\",\n entry.sessionKey ?? \"\",\n entry.principal ?? \"\",\n entry.text,\n ].join(\"\\u0000\"))\n .sort();\n const timelineEntrySeparator = String.fromCharCode(1);\n const structuredFactsSeparator = String.fromCharCode(2);\n fingerprint.update(timelineEntries.join(timelineEntrySeparator));\n fingerprint.update(structuredFactsSeparator);\n fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? \"\");\n return fingerprint.digest(\"hex\");\n}\n\nexport interface GraphRecallSnapshot {\n recordedAt: string;\n mode: RecallPlanMode | string;\n queryHash: string;\n queryLength: number;\n namespaces: string[];\n seedCount: number;\n expandedCount: number;\n seeds: string[];\n expanded: GraphRecallExpandedEntry[];\n status?: \"completed\" | \"skipped\" | \"aborted\";\n reason?: string;\n shadowMode?: boolean;\n queryIntent?: MemoryIntent;\n seedResults?: GraphRecallRankedResult[];\n finalResults?: GraphRecallRankedResult[];\n shadowComparison?: GraphRecallShadowComparison;\n}\n\nexport interface GraphRecallRankedResult {\n path: string;\n score: number;\n docid?: string;\n sourceLabels: string[];\n}\n\nexport interface GraphRecallShadowComparison {\n baselineCount: number;\n graphCount: number;\n overlapCount: number;\n overlapRatio: number;\n averageOverlapDelta: number;\n}\n\nexport interface IntentDebugSnapshot {\n recordedAt: string;\n promptHash: string;\n promptLength: number;\n retrievalQueryHash: string;\n retrievalQueryLength: number;\n plannerEnabled: boolean;\n plannedMode: RecallPlanMode;\n effectiveMode: RecallPlanMode;\n recallResultLimit: number;\n queryIntent: MemoryIntent;\n graphExpandedIntentDetected: boolean;\n graphDecision: {\n status: \"not_requested\" | \"skipped\" | \"completed\" | \"aborted\";\n reason?: string;\n shadowMode: boolean;\n qmdAvailable: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n };\n}\n\nexport interface QmdRecallSnapshot {\n recordedAt: string;\n queryHash: string;\n queryLength: number;\n collection?: string;\n namespaces: string[];\n fetchLimit: number;\n primaryResultCount: number;\n hybridResultCount: number;\n queryAwareSeedCount: number;\n resultCount: number;\n intentHint?: string;\n explainEnabled: boolean;\n hybridTopUpUsed: boolean;\n hybridTopUpSkippedReason?: string;\n results: QmdSearchResult[];\n}\n\nexport interface RecallModeDecision {\n plannedMode: RecallPlanMode;\n effectiveMode: RecallPlanMode;\n graphExpandedIntentDetected: boolean;\n graphReason?: string;\n}\n\n/**\n * Map the orchestrator's internal `recallSource` strings to the\n * X-ray `servedBy` vocabulary (issue #570 PR 1). The X-ray tier\n * ladder intentionally flattens QMD / embedding / cold-fallback to\n * the `hybrid` tier because they all materialize through the same\n * hybrid BM25+vector pipeline from the caller's perspective. The\n * `recent_scan` path gets its own dedicated tier because it bypasses\n * the hybrid pipeline entirely. `none` is treated as `hybrid` on the\n * theory that a query that returned nothing still routed through the\n * hybrid pipeline — but callers should normally gate capture on\n * `recalledMemoryIds.length > 0`.\n */\nfunction mapRecallSourceToXrayServedBy(\n source:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\",\n): RecallXrayServedBy {\n // Exhaustive switch: every current union member is explicitly\n // listed so TypeScript surfaces a compile error if a new source is\n // added without a deliberate mapping. The `never`-typed fallthrough\n // keeps the function total at runtime — if the caller passes an\n // unexpected value that slipped past the type system (e.g. a JSON\n // deserialization), we still fall back to `hybrid`.\n switch (source) {\n case \"recent_scan\":\n return \"recent-scan\";\n case \"hot_qmd\":\n case \"hot_embedding\":\n case \"cold_fallback\":\n case \"none\":\n return \"hybrid\";\n }\n const _exhaustive: never = source;\n void _exhaustive;\n return \"hybrid\";\n}\n\nexport interface RecallInvocationOptions {\n namespace?: string;\n topK?: number;\n mode?: RecallPlanMode;\n abortSignal?: AbortSignal;\n /**\n * Capture a `RecallXraySnapshot` for this recall (issue #570). When\n * `true`, the orchestrator builds a snapshot from the data it has\n * already gathered and stashes it in memory, accessible via\n * `getLastXraySnapshot()`. When `false` or absent, nothing is\n * captured and recall behavior is unchanged (schema-only slice).\n */\n xrayCapture?: boolean;\n /**\n * Per-invocation override for `recallBudgetChars` (issue #570 PR 3/4).\n * Flows through `getRecallBudgetChars()` for this recall only — no\n * shared config mutation, so concurrent recalls on the same\n * orchestrator are not affected (CLAUDE.md rule 47: no shared\n * mutable state across async boundaries). Must be a non-negative\n * finite integer; non-conforming values are ignored and the\n * configured budget is used.\n */\n budgetCharsOverride?: number;\n /**\n * Per-invocation principal override (issue #570 PR 4). When set,\n * the orchestrator uses this principal for ACL / namespace checks\n * instead of `resolvePrincipal(sessionKey, config)`. This is the\n * escape hatch for access surfaces (HTTP / MCP) that have already\n * authenticated the caller upstream — threading an unmapped\n * principal through the session-key-based resolver would otherwise\n * collapse it to `\"default\"` and produce false denials in\n * namespace-enabled deployments (CLAUDE.md rule 42).\n */\n principalOverride?: string;\n /**\n * Historical recall point (issue #680). When set, the orchestrator\n * filters out memories whose `valid_at` is after this timestamp OR\n * whose `invalid_at` is at-or-before this timestamp, so callers see\n * the corpus as it existed at `asOf`. ISO 8601 string; comparisons\n * use `Date.parse()` so timezone-aware values round-trip correctly\n * (CLAUDE.md gotcha — never compare ISO strings lexicographically).\n * Invalid values must be rejected at input boundaries (CLAUDE.md\n * rule 51); the orchestrator does NOT silently fall back here.\n */\n asOf?: string;\n /**\n * Issue #681 — when `true`, bypasses `graphTraversalConfidenceFloor`\n * and includes edges below the floor in graph traversal. Useful for\n * diagnostic recall queries that need to surface results that would\n * normally be pruned by confidence decay. Default `false`.\n */\n includeLowConfidence?: boolean;\n}\n\ntype QueryAwarePrefilter = {\n candidatePaths: Set<string> | null;\n temporalFromDate: string | null;\n matchedTags: string[];\n expandedTags: string[];\n combination: \"none\" | \"temporal\" | \"tag\" | \"intersection\" | \"union\";\n filteredToFullSearch: boolean;\n};\n\n// Recall-specific abort helpers. Thin wrappers over the shared\n// `abort-error.ts` module so every abort in the codebase shares the\n// same `name === \"AbortError\"` classification contract (`isAbortError`\n// works uniformly). We keep the \"recall aborted\" default message for\n// back-compat with call-site logs; callers that pass an explicit\n// message (e.g. \"extraction aborted (before_extract)\") are unaffected.\nconst abortRecallError = sharedAbortError;\n\nfunction throwIfRecallAborted(\n signal?: AbortSignal,\n message = \"recall aborted\",\n): void {\n sharedThrowIfAborted(signal, message);\n}\n\nasync function raceRecallAbort<T>(\n promise: Promise<T>,\n signal?: AbortSignal,\n message = \"recall aborted\",\n): Promise<T> {\n throwIfRecallAborted(signal, message);\n if (!signal) return promise;\n\n let onAbort: (() => void) | null = null;\n const abortPromise = new Promise<T>((_resolve, reject) => {\n onAbort = () => reject(abortRecallError(message));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n try {\n return await Promise.race([promise, abortPromise]);\n } finally {\n if (onAbort) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n}\n\n/** Maximum age (ms) before a compaction-reset signal file is considered stale and removed. */\nconst COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour\n\n/** Default workspace directory when no per-agent or config workspace is available. */\nexport function defaultWorkspaceDir(): string {\n return path.join(os.homedir(), \".openclaw\", \"workspace\");\n}\n\n/**\n * Produce a collision-resistant, filesystem-safe identifier from a session key.\n *\n * Session keys follow colon-delimited forms (e.g., `agent:gpucodebot:main`).\n * A naive replace (`:` → `_`) is lossy: different keys like `agent:alpha` and\n * `agent/alpha` would collide. Instead we append a short SHA-256 hash of the\n * original key to the human-readable sanitized prefix, guaranteeing uniqueness\n * while keeping filenames debuggable.\n *\n * Format: `<sanitized>-<12-char-hex-hash>`\n * Example: `agent:gpucodebot:main` → `agent_gpucodebot_main-a1b2c3d4e5f6`\n */\nexport function sanitizeSessionKeyForFilename(sessionKey: string): string {\n const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const hash = createHash(\"sha256\")\n .update(sessionKey)\n .digest(\"hex\")\n .slice(0, 12);\n return `${readable}-${hash}`;\n}\n\nexport function isArtifactMemoryPath(filePath: string): boolean {\n return /(?:^|[\\\\/])artifacts(?:[\\\\/]|$)/i.test(filePath);\n}\n\nexport function deriveTopicsFromExtraction(result: ExtractionResult): string[] {\n const topics = new Set<string>();\n for (const fact of result.facts ?? []) {\n for (const tag of fact.tags ?? []) {\n if (tag && tag.length >= 2) topics.add(tag.toLowerCase());\n }\n if (fact.entityRef) topics.add(fact.entityRef.toLowerCase());\n if (fact.category) topics.add(fact.category);\n }\n for (const entity of (result as any).entities ?? []) {\n if (typeof entity.name === \"string\" && entity.name.length >= 2) {\n topics.add(entity.name.toLowerCase());\n }\n }\n return [...topics].slice(0, 16);\n}\n\nexport function buildCompressionGuidelinesMarkdown(\n events: MemoryActionEvent[],\n generatedAtIso: string = new Date().toISOString(),\n): string {\n return buildCompressionGuidelinesMarkdownV2(events, generatedAtIso);\n}\n\nexport function formatCompressionGuidelinesForRecall(\n raw: string,\n maxLines: number = 5,\n): string | null {\n if (typeof raw !== \"string\" || raw.trim().length === 0) return null;\n const sectionMatch = raw.match(\n /## Suggested Guidelines\\s*\\n([\\s\\S]*?)(?:\\n##\\s+|\\s*$)/i,\n );\n if (!sectionMatch) return null;\n\n const lines = sectionMatch[1]\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"- \"))\n .slice(0, Math.max(1, Math.floor(maxLines)));\n if (lines.length === 0) return null;\n\n return lines.join(\"\\n\");\n}\n\nexport function filterRecallCandidates(\n candidates: QmdSearchResult[],\n options: {\n namespacesEnabled: boolean;\n recallNamespaces: string[];\n resolveNamespace: (path: string) => string;\n limit: number;\n },\n): QmdSearchResult[] {\n const scopedByNamespace = options.namespacesEnabled\n ? candidates.filter((r) =>\n options.recallNamespaces.includes(options.resolveNamespace(r.path)),\n )\n : candidates;\n return scopedByNamespace\n .filter((r) => !isArtifactMemoryPath(r.path))\n .slice(0, Math.max(0, options.limit));\n}\n\nfunction applyQueryAwareCandidateFilter(\n candidates: QmdSearchResult[],\n candidatePaths: Set<string> | null,\n): QmdSearchResult[] {\n if (!candidatePaths || candidatePaths.size === 0) return candidates;\n const filtered = candidates.filter((candidate) =>\n candidatePaths.has(candidate.path),\n );\n return filtered.length > 0 ? filtered : candidates;\n}\n\nfunction tokenizeRecallQuery(prompt: string): string[] {\n return prompt\n .toLowerCase()\n .split(/[^a-z0-9]+/i)\n .map((t) => t.trim())\n .filter((t) => t.length >= 3);\n}\n\nfunction hasLifecycleMetadata(frontmatter: MemoryFrontmatter): boolean {\n return (\n frontmatter.lifecycleState !== undefined ||\n frontmatter.verificationState !== undefined ||\n frontmatter.policyClass !== undefined ||\n frontmatter.lastValidatedAt !== undefined ||\n frontmatter.decayScore !== undefined ||\n frontmatter.heatScore !== undefined\n );\n}\n\nexport function shouldFilterLifecycleRecallCandidate(\n frontmatter: MemoryFrontmatter,\n options: {\n lifecyclePolicyEnabled: boolean;\n lifecycleFilterStaleEnabled: boolean;\n },\n): boolean {\n if (!options.lifecyclePolicyEnabled || !options.lifecycleFilterStaleEnabled)\n return false;\n if (!hasLifecycleMetadata(frontmatter)) return false;\n const lifecycleState = resolveLifecycleState(frontmatter);\n return lifecycleState === \"stale\" || lifecycleState === \"archived\";\n}\n\nexport function lifecycleRecallScoreAdjustment(\n frontmatter: MemoryFrontmatter,\n options: {\n lifecyclePolicyEnabled: boolean;\n },\n): number {\n if (!options.lifecyclePolicyEnabled) return 0;\n if (!hasLifecycleMetadata(frontmatter)) return 0;\n\n let delta = 0;\n const lifecycleState = resolveLifecycleState(frontmatter);\n switch (lifecycleState) {\n case \"active\":\n delta += 0.05;\n break;\n case \"validated\":\n delta += 0.03;\n break;\n case \"candidate\":\n delta -= 0.01;\n break;\n case \"stale\":\n delta -= 0.06;\n break;\n case \"archived\":\n delta -= 0.08;\n break;\n }\n if (frontmatter.verificationState === \"disputed\") {\n delta -= 0.12;\n }\n return delta;\n}\n\nexport function computeArtifactRecallLimit(\n recallMode: RecallPlanMode,\n recallResultLimit: number,\n verbatimArtifactsMaxRecall: number,\n): number {\n if (recallMode === \"no_recall\") return 0;\n if (Math.max(0, recallResultLimit) === 0) return 0;\n const base = Math.max(0, verbatimArtifactsMaxRecall);\n if (recallMode === \"minimal\") {\n return Math.min(base, Math.max(0, recallResultLimit));\n }\n return base;\n}\n\nexport function resolveEffectiveRecallMode(options: {\n plannerEnabled: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n graphExpandedIntentEnabled?: boolean;\n prompt: string;\n}): RecallPlanMode {\n return resolveRecallModeDecision(options).effectiveMode;\n}\n\nexport function resolveRecallModeDecision(options: {\n plannerEnabled: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n graphExpandedIntentEnabled?: boolean;\n prompt: string;\n}): RecallModeDecision {\n let plannedMode: RecallPlanMode = options.plannerEnabled\n ? planRecallMode(options.prompt)\n : \"full\";\n const graphExpandedIntentDetected =\n options.plannerEnabled &&\n options.graphExpandedIntentEnabled === true &&\n hasBroadGraphIntent(options.prompt);\n if (plannedMode !== \"graph_mode\" && graphExpandedIntentDetected) {\n plannedMode = \"graph_mode\";\n }\n if (\n plannedMode === \"graph_mode\" &&\n (!options.graphRecallEnabled || !options.multiGraphMemoryEnabled)\n ) {\n return {\n plannedMode,\n effectiveMode: \"full\",\n graphExpandedIntentDetected,\n graphReason: !options.graphRecallEnabled\n ? \"graph recall disabled by config\"\n : \"multi-graph memory disabled by config\",\n };\n }\n return {\n plannedMode,\n effectiveMode: plannedMode,\n graphExpandedIntentDetected,\n };\n}\n\nexport function hasIdentityRecoveryIntent(prompt: string): boolean {\n const text = typeof prompt === \"string\" ? prompt.toLowerCase() : \"\";\n if (!text) return false;\n return /\\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\\b/i.test(\n text,\n );\n}\n\nexport function resolveEffectiveIdentityInjectionMode(options: {\n configuredMode: IdentityInjectionMode;\n recallMode: RecallPlanMode;\n prompt: string;\n}): { mode: IdentityInjectionMode; shouldInject: boolean } {\n if (\n options.configuredMode === \"recovery_only\" &&\n !hasIdentityRecoveryIntent(options.prompt)\n ) {\n return { mode: \"recovery_only\", shouldInject: false };\n }\n if (options.recallMode === \"minimal\" && options.configuredMode === \"full\") {\n return { mode: \"minimal\", shouldInject: true };\n }\n return { mode: options.configuredMode, shouldInject: true };\n}\n\nexport function computeArtifactCandidateFetchLimit(\n targetCount: number,\n): number {\n const cappedTarget = Math.max(0, targetCount);\n if (cappedTarget === 0) return 0;\n const headroom = Math.max(8, cappedTarget * 4);\n return Math.min(200, cappedTarget + headroom);\n}\n\nexport function computeQmdHybridFetchLimit(\n recallFetchLimit: number,\n artifactsEnabled: boolean,\n maxArtifactRecall: number,\n): number {\n const cappedRecallLimit = Math.max(0, recallFetchLimit);\n if (cappedRecallLimit === 0) return 0;\n if (!artifactsEnabled) return cappedRecallLimit;\n // Overscan when artifacts are enabled, then filter artifact paths before\n // re-applying the recall cap to avoid artifact-dominated top-N starvation.\n const artifactHeadroom = Math.max(20, Math.max(0, maxArtifactRecall) * 8);\n return Math.min(400, cappedRecallLimit + artifactHeadroom);\n}\n\nexport function mergeGraphExpandedResults(\n primary: QmdSearchResult[],\n expanded: QmdSearchResult[],\n): QmdSearchResult[] {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const item of [...primary, ...expanded]) {\n const prev = mergedByPath.get(item.path);\n if (!prev) {\n mergedByPath.set(item.path, item);\n continue;\n }\n const better = item.score > prev.score ? item : prev;\n const snippet = prev.snippet || item.snippet;\n mergedByPath.set(item.path, { ...better, snippet });\n }\n return Array.from(mergedByPath.values());\n}\n\nexport function graphPathRelativeToStorage(\n storageDir: string,\n candidatePath: string,\n): string | null {\n const absolutePath = path.isAbsolute(candidatePath)\n ? candidatePath\n : path.resolve(storageDir, candidatePath);\n const rel = path.relative(storageDir, absolutePath);\n if (!rel || rel === \".\") return null;\n if (rel.startsWith(\"..\")) return null;\n return rel.split(path.sep).join(\"/\");\n}\n\nfunction normalizeGraphActivationScore(score: number): number {\n const bounded = Number.isFinite(score) && score > 0 ? score : 0;\n return bounded / (1 + bounded);\n}\n\nexport function blendGraphExpandedRecallScore(options: {\n graphActivationScore: number;\n seedRecallScore: number;\n activationWeight: number;\n blendMin: number;\n blendMax: number;\n}): number {\n const graphNorm = normalizeGraphActivationScore(options.graphActivationScore);\n const seedScore = Number.isFinite(options.seedRecallScore)\n ? Math.min(1, Math.max(0, options.seedRecallScore))\n : 0;\n const weight = Math.min(1, Math.max(0, options.activationWeight));\n const rawMin = Math.min(1, Math.max(0, options.blendMin));\n const rawMax = Math.min(1, Math.max(0, options.blendMax));\n const minBound = Math.min(rawMin, rawMax);\n const maxBound = Math.max(rawMin, rawMax);\n const blended = graphNorm * weight + seedScore * (1 - weight);\n return Math.max(minBound, Math.min(maxBound, blended));\n}\n\nexport function summarizeGraphShadowComparison(\n baseline: QmdSearchResult[],\n merged: QmdSearchResult[],\n topN: number,\n): {\n baselineCount: number;\n graphCount: number;\n overlapCount: number;\n overlapRatio: number;\n averageOverlapDelta: number;\n} {\n const limit = Math.max(0, Math.floor(topN));\n const baselineTop = limit > 0 ? baseline.slice(0, limit) : [];\n const graphTop = limit > 0 ? merged.slice(0, limit) : [];\n const baselineByPath = new Map(\n baselineTop.map((item) => [item.path, item.score]),\n );\n const graphByPath = new Map(graphTop.map((item) => [item.path, item.score]));\n\n let overlapCount = 0;\n let overlapDeltaSum = 0;\n for (const [p, baselineScore] of baselineByPath.entries()) {\n const graphScore = graphByPath.get(p);\n if (typeof graphScore !== \"number\") continue;\n overlapCount += 1;\n overlapDeltaSum += graphScore - baselineScore;\n }\n\n const baselineCount = baselineTop.length;\n return {\n baselineCount,\n graphCount: graphTop.length,\n overlapCount,\n overlapRatio: baselineCount > 0 ? overlapCount / baselineCount : 0,\n averageOverlapDelta: overlapCount > 0 ? overlapDeltaSum / overlapCount : 0,\n };\n}\n\nfunction parseGraphRecallRankedResults(\n value: unknown,\n): GraphRecallRankedResult[] {\n if (!Array.isArray(value)) return [];\n const parsed: GraphRecallRankedResult[] = [];\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const candidate = entry as Partial<GraphRecallRankedResult>;\n if (\n typeof candidate.path !== \"string\" ||\n typeof candidate.score !== \"number\"\n )\n continue;\n parsed.push({\n path: candidate.path,\n score: candidate.score,\n docid: typeof candidate.docid === \"string\" ? candidate.docid : undefined,\n sourceLabels: Array.isArray(candidate.sourceLabels)\n ? candidate.sourceLabels.filter(\n (item): item is string => typeof item === \"string\",\n )\n : [],\n });\n }\n return parsed.slice(0, 64);\n}\n\nfunction parseMemoryIntentSnapshot(value: unknown): MemoryIntent {\n const candidate =\n value && typeof value === \"object\" ? (value as Partial<MemoryIntent>) : {};\n return {\n goal: typeof candidate.goal === \"string\" ? candidate.goal : \"unknown\",\n actionType:\n typeof candidate.actionType === \"string\"\n ? candidate.actionType\n : \"unknown\",\n entityTypes: Array.isArray(candidate.entityTypes)\n ? candidate.entityTypes.filter(\n (item): item is string => typeof item === \"string\",\n )\n : [],\n taskInitiation: candidate.taskInitiation === true,\n };\n}\n\nfunction buildQmdIntentHint(intent: MemoryIntent): string | undefined {\n const parts: string[] = [];\n if (intent.goal !== \"unknown\") {\n parts.push(`goal:${intent.goal.replace(/_/g, \" \")}`);\n }\n if (intent.actionType !== \"unknown\") {\n parts.push(`action:${intent.actionType.replace(/_/g, \" \")}`);\n }\n if (intent.entityTypes.length > 0) {\n parts.push(`entities:${intent.entityTypes.join(\",\")}`);\n }\n if (intent.taskInitiation === true) {\n parts.push(\"task_initiation\");\n }\n return parts.length > 0 ? parts.join(\" \") : undefined;\n}\n\nfunction parseQmdRecallResults(value: unknown): QmdSearchResult[] {\n if (!Array.isArray(value)) return [];\n const parsed: QmdSearchResult[] = [];\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const candidate = entry as Partial<QmdSearchResult>;\n if (\n typeof candidate.path !== \"string\" ||\n typeof candidate.score !== \"number\"\n )\n continue;\n parsed.push({\n docid: typeof candidate.docid === \"string\" ? candidate.docid : \"\",\n path: candidate.path,\n snippet: typeof candidate.snippet === \"string\" ? candidate.snippet : \"\",\n score: candidate.score,\n explain: parseQmdExplain(candidate.explain),\n transport:\n candidate.transport === \"daemon\" ||\n candidate.transport === \"subprocess\" ||\n candidate.transport === \"hybrid\" ||\n candidate.transport === \"scoped_prefilter\"\n ? candidate.transport\n : undefined,\n });\n }\n return parsed.slice(0, 32);\n}\n\nexport function mergeArtifactRecallCandidates(\n candidatesByNamespace: MemoryFile[][],\n limit: number,\n): MemoryFile[] {\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0) return [];\n\n const out: MemoryFile[] = [];\n const seen = new Set<string>();\n let offset = 0;\n while (out.length < cappedLimit) {\n let hasAnyCandidateAtOffset = false;\n for (const list of candidatesByNamespace) {\n if (offset >= list.length) continue;\n hasAnyCandidateAtOffset = true;\n const item = list[offset];\n const dedupeKey = `${item.frontmatter.id}:${item.frontmatter.sourceMemoryId ?? \"\"}:${item.content}`;\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n out.push(item);\n if (out.length >= cappedLimit) break;\n }\n if (!hasAnyCandidateAtOffset) break;\n offset += 1;\n }\n return out;\n}\n\nexport function resolveRecentThreadMemoryPaths(options: {\n threadEpisodeIds: string[];\n currentMemoryId: string;\n allMemsForGraph: MemoryFile[] | null | undefined;\n pathById?: Map<string, string>;\n storageDir: string;\n maxRecent: number;\n}): string[] {\n const maxRecent = Math.max(0, options.maxRecent);\n if (options.threadEpisodeIds.length === 0 || maxRecent === 0) return [];\n const pathById =\n options.pathById ??\n buildMemoryPathById(options.allMemsForGraph, options.storageDir);\n if (pathById.size === 0) return [];\n\n return options.threadEpisodeIds\n .filter((id) => id !== options.currentMemoryId)\n .slice(-maxRecent)\n .map((id) => pathById.get(id))\n .filter((p): p is string => typeof p === \"string\" && p.length > 0);\n}\n\nexport function buildMemoryPathById(\n allMemsForGraph: MemoryFile[] | null | undefined,\n storageDir: string,\n): Map<string, string> {\n const pathById = new Map<string, string>();\n for (const mem of allMemsForGraph ?? []) {\n const id = mem.frontmatter.id;\n if (!id) continue;\n pathById.set(id, path.relative(storageDir, mem.path));\n }\n return pathById;\n}\n\nexport function appendMemoryToGraphContext(options: {\n allMemsForGraph: MemoryFile[] | null | undefined;\n storageDir: string;\n memoryRelPath: string;\n memoryId: string;\n category: MemoryFile[\"frontmatter\"][\"category\"];\n content: string;\n entityRef: string | undefined;\n}): void {\n if (!Array.isArray(options.allMemsForGraph)) return;\n\n const nowIso = new Date().toISOString();\n options.allMemsForGraph.push({\n path: path.join(options.storageDir, options.memoryRelPath),\n content: options.content,\n frontmatter: {\n id: options.memoryId,\n category: options.category,\n created: nowIso,\n updated: nowIso,\n source: \"extraction\",\n confidence: 0.8,\n confidenceTier: \"implied\",\n tags: [],\n entityRef: options.entityRef,\n status: \"active\",\n },\n });\n}\n\nexport function resolvePersistedMemoryRelativePath(options: {\n memoryId: string;\n pathById: Map<string, string>;\n category: string;\n}): string {\n const persisted = options.pathById.get(options.memoryId);\n if (persisted) return persisted;\n if (options.category === \"correction\") {\n return path.join(\"corrections\", `${options.memoryId}.md`);\n }\n // Pick the subtree that matches the StorageManager.writeMemory routing\n // so fallback paths (used before memoryPathById has seen the fresh\n // write) agree with where the file actually lives. Without this branch,\n // reasoning_trace graph edges point at facts/<date>/, and subsequent\n // graph expansion silently drops those nodes when readMemoryByPath\n // cannot resolve them (issue #564 PR 3 review).\n const subtree =\n options.category === \"procedure\"\n ? \"procedures\"\n : options.category === \"reasoning_trace\"\n ? \"reasoning-traces\"\n : \"facts\";\n const idParts = options.memoryId.split(\"-\");\n const maybeTimestamp = Number(idParts[1]);\n if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {\n const day = new Date(maybeTimestamp).toISOString().slice(0, 10);\n return path.join(subtree, day, `${options.memoryId}.md`);\n }\n return path.join(subtree, `${options.memoryId}.md`);\n}\n\nexport class Orchestrator {\n readonly storage: StorageManager;\n private readonly storageRouter: NamespaceStorageRouter;\n private readonly namespaceSearchRouter: NamespaceSearchRouter;\n qmd: SearchBackend;\n private readonly conversationQmd?: ConversationQmdRuntime;\n private readonly conversationFaiss?: ReturnType<\n typeof createConversationIndexRuntime\n >[\"faiss\"];\n private readonly conversationIndexBackend?: ConversationIndexBackend;\n readonly sharedContext?: SharedContextManager;\n readonly compounding?: CompoundingEngine;\n readonly buffer: SmartBuffer;\n readonly transcript: TranscriptManager;\n readonly sessionObserver: SessionObserverState;\n readonly summarizer: HourlySummarizer;\n readonly localLlm: LocalLlmClient;\n readonly fastLlm: LocalLlmClient;\n private readonly judgeVerdictCache: Map<string, JudgeVerdict>;\n /**\n * Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many\n * times the judge has returned `\"defer\"` for a given candidate content\n * hash so the defer cap can be enforced.\n */\n private readonly judgeDeferCounts: Map<string, number>;\n /**\n * Side-channel: number of facts deferred in the most recent\n * `persistExtraction` call (issue #562, PR 2). The caller reads this after\n * `persistExtraction` returns to decide whether to retain buffer turns for\n * the next extraction pass. Not part of the return signature because many\n * callers already destructure `persistedIds` by position.\n */\n private lastPersistExtractionDeferredCount: number = 0;\n private readonly _fastGatewayLlm: FallbackLlmClient | null;\n\n get fastGatewayLlm(): FallbackLlmClient | null {\n return this._fastGatewayLlm;\n }\n readonly modelRegistry: ModelRegistry;\n readonly relevance: RelevanceStore;\n readonly negatives: NegativeExampleStore;\n readonly lastRecall: LastRecallStore;\n readonly tierMigrationStatus: TierMigrationStatusStore;\n /**\n * In-memory X-ray snapshot from the most recent `recall()` call that\n * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is\n * per-process; later slices add CLI/HTTP/MCP surfaces that consume\n * this via the shared renderer. `null` until the first capture, and\n * NEVER overwritten by a recall that did not request capture —\n * requests without the flag leave prior captures intact so the\n * capturing caller can still read their snapshot back.\n */\n private lastXraySnapshot: RecallXraySnapshot | null = null;\n readonly embeddingFallback: EmbeddingFallback;\n private readonly conversationIndexDir: string;\n private readonly extraction: ExtractionEngine;\n readonly config: PluginConfig;\n readonly profiler: ProfilingCollector;\n private readonly threading: ThreadingManager;\n /** v8.2: Per-namespace multi-graph memory indexes (entity/time/causal edges) */\n private readonly graphIndexes = new Map<string, GraphIndex>();\n /** Per-namespace BoxBuilders, keyed by the namespace root directory path. */\n private readonly boxBuilders = new Map<string, BoxBuilder>();\n /** Temporal Memory Tree builder — builds hour/day/week/persona summary nodes. */\n private readonly tmtBuilder: TmtBuilder;\n /** Lossless Context Management engine — proactive session archive + DAG summarization. */\n readonly lcmEngine: LcmEngine | null = null;\n private readonly rerankCache = new RerankCache();\n\n /**\n * Short-TTL cache for Memory Worth counter lookups so interactive recall\n * doesn't trigger a full `readAllMemories` scan per query. Keyed by\n * namespace; the filter unions across namespaces at query time. The TTL\n * is intentionally short (seconds, not minutes) because counters are\n * mutated by `recordMemoryOutcome` asynchronously and we'd rather serve\n * a 30-second-stale worth score than a stable-but-wrong one.\n */\n private readonly memoryWorthCounterCache = new Map<\n string,\n { at: number; counters: ReadonlyMap<string, MemoryWorthCounters> }\n >();\n private static readonly MEMORY_WORTH_CACHE_TTL_MS = 30_000;\n /**\n * Per-session workspace selections keyed by sessionKey.\n * Set by the before_agent_start hook so recall() uses the correct\n * agent workspace for BOOT.md injection. Cleared after each recall.\n * Using a Map prevents concurrent sessions from overwriting each other.\n */\n private _recallWorkspaceOverrides = new Map<string, string>();\n /**\n * Per-session coding-agent context (issue #569). Populated by connectors at\n * session-start (PRs 5/6/7) via `setCodingContextForSession`. Used by both\n * the recall path and the write path so that memory routing respects the\n * project/branch scope a session is operating in (rule 42 — read + write\n * through the same namespace layer).\n */\n private readonly _codingContextBySession = new Map<string, CodingContext>();\n /**\n * Per-session peer ID registry (issue #679 PR 3/5).\n * Set by connectors / hooks via `setPeerIdForSession` so `recallInternal`\n * can inject the peer's profile into recall context when\n * `peerProfileRecallEnabled` is true. Cleared when the session ends.\n * Keyed by sessionKey so concurrent sessions don't clobber each other\n * (rule 11 — scope globals per plugin ID / session).\n */\n private readonly _peerIdBySession = new Map<string, string>();\n private routingRulesStore: RoutingRulesStore | null = null;\n private contentHashIndex: ContentHashIndex | null = null;\n private readonly artifactSourceStatusCache = new WeakMap<\n StorageManager,\n {\n loadedAtMs: number;\n statusVersion: number;\n statuses: Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">;\n }\n >();\n private static readonly ARTIFACT_STATUS_CACHE_TTL_MS = 60_000;\n\n // Access tracking buffer (Phase 1A)\n // Maps memoryId -> {count, lastAccessed} for batched updates\n private accessTrackingBuffer: Map<\n string,\n { count: number; lastAccessed: string }\n > = new Map();\n\n // Background serial queue for extractions (agent_end optimization)\n // Queue stores promises that resolve when extraction should run\n private extractionQueue: Array<() => Promise<void>> = [];\n private queueProcessing = false;\n private heartbeatObserverChains = new Map<string, Promise<void>>();\n private recentExtractionFingerprints = new Map<string, number>();\n private nonZeroExtractionsSinceConsolidation = 0;\n private lastConsolidationRunAtMs = 0;\n private consolidationInFlight = false;\n private readonly consolidationObservers = new Set<\n (observation: ConsolidationObservation) => Promise<void> | void\n >();\n private qmdMaintenanceTimer: NodeJS.Timeout | null = null;\n private qmdMaintenancePending = false;\n private qmdMaintenanceInFlight = false;\n private lastQmdEmbedAtMs = 0;\n private lastQmdReprobeAtMs = 0;\n private tierMigrationInFlight = false;\n private lastTierMigrationRunAtMs = 0;\n private readonly conversationIndexLastUpdateAtMs = new Map<string, number>();\n private lastFileHygieneRunAtMs = 0;\n // Pattern-reinforcement cadence gate (issue #687 PR 2/4). Tracks the\n // last successful run so `runPatternReinforcement` can short-circuit\n // when the configured cadence has not elapsed. Keyed by namespace\n // so MCP-triggered runs in tenant A don't suppress runs in tenant B\n // (PR #730 review feedback, Codex P2). The default-tenant path\n // uses the empty-string key.\n private lastPatternReinforcementAtByNs = new Map<string, number>();\n private lastRecallFailureLogAtMs = 0;\n private lastRecallFailureAtMs = 0;\n private suppressedRecallFailures = 0;\n private readonly policyRuntime: PolicyRuntimeManager;\n private runtimePolicyValues: RuntimePolicyValues | null = null;\n private utilityRuntimeValues: UtilityRuntimeValues | null = null;\n private evalShadowWriteChain: Promise<void> = Promise.resolve();\n\n // Pending background observation-mode direct-answer annotations (#518).\n // Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,\n // waitForDirectAnswerObservationIdle) can await settlement.\n private directAnswerObservationChain: Promise<void> = Promise.resolve();\n\n // Initialization gate: recall() awaits this before proceeding\n private initPromise: Promise<void> | null = null;\n private resolveInit: (() => void) | null = null;\n\n /**\n * Resolves when deferred initialization (QMD probe, warmup, caches, cron)\n * completes. CLI and http-serve callers that need `qmd.isAvailable()` to\n * reflect reality should `await orchestrator.deferredReady` after\n * `initialize()`. Gateway callers can ignore it — recall() degrades\n * gracefully when QMD isn't ready yet.\n *\n * Also resolves (without error) when `initialize()` throws before reaching\n * the deferred-init phase, so callers never hang on a permanently-pending\n * promise.\n *\n * Host adapters that need to tie deferred init to their stop() lifecycle\n * should `await orchestrator.deferredReady` before proceeding with teardown\n * to prevent background QMD/warmup/cron tasks from racing with shutdown.\n */\n deferredReady: Promise<void> = Promise.resolve();\n private resolveDeferredReady: (() => void) | null = null;\n private deferredInitAbort: AbortController | null = null;\n\n /**\n * Whether the deferred init's QMD startup sync completed successfully.\n * When false after deferredReady resolves, the server retry loop should\n * attempt startupSearchSync() even if `qmd.isAvailable()` is true —\n * availability only means probe succeeded, not that the index is current.\n */\n deferredSyncSucceeded = false;\n\n /**\n * Abort deferred initialization so background QMD sync/warmup stops\n * promptly on shutdown. Safe to call multiple times or before init.\n */\n abortDeferredInit(): void {\n if (this.deferredInitAbort) {\n this.deferredInitAbort.abort();\n this.deferredInitAbort = null;\n }\n }\n\n private async disposeSearchBackendIfNeeded(): Promise<void> {\n await (this.qmd as { dispose?: () => void | Promise<void> }).dispose?.();\n }\n\n /** Set per-session workspace for the next recall() call (compaction reset). @internal */\n setRecallWorkspaceOverride(sessionKey: string, dir: string): void {\n this._recallWorkspaceOverrides.set(sessionKey, dir);\n }\n\n /** Remove a per-session workspace selection (cleanup on error or early return). @internal */\n clearRecallWorkspaceOverride(sessionKey: string): void {\n this._recallWorkspaceOverrides.delete(sessionKey);\n }\n\n resolvePrincipal(sessionKey?: string): string {\n return resolvePrincipal(sessionKey, this.config);\n }\n\n resolveSelfNamespace(sessionKey?: string): string {\n const base = defaultNamespaceForPrincipal(\n this.resolvePrincipal(sessionKey),\n this.config,\n );\n return this.applyCodingNamespaceOverlay(sessionKey, base);\n }\n\n /**\n * Attach a coding-agent context to a session (issue #569). Called by the\n * Claude Code / Codex / Cursor connectors at session start after\n * `resolveGitContext(cwd)`. The context is consulted by the recall path\n * and the write path so that memories route to a project- (and optionally\n * branch-) scoped namespace.\n *\n * Pass `null` to clear.\n */\n setCodingContextForSession(sessionKey: string, codingContext: CodingContext | null): void {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return;\n // Defensive init — `Object.create(Orchestrator.prototype)` stubs in\n // legacy tests skip class-field initializers (rule 16 applies to test\n // teardown; we apply the same defensiveness on construction here so\n // PR 2 doesn't break those tests).\n if (!this._codingContextBySession) {\n (this as unknown as { _codingContextBySession: Map<string, CodingContext> })._codingContextBySession = new Map();\n }\n if (codingContext === null) {\n this._codingContextBySession.delete(sessionKey);\n return;\n }\n this._codingContextBySession.set(sessionKey, codingContext);\n }\n\n /**\n * Read-only accessor for the coding context attached to a session. Returns\n * `null` when none is set. Used by `remnic doctor` and by tests.\n *\n * Defensive `_codingContextBySession` lookup — legacy orchestrator-flush\n * tests use `Object.create(Orchestrator.prototype)` which does not run\n * class-field initializers, so the Map may be undefined on stubs.\n */\n getCodingContextForSession(sessionKey: string | undefined): CodingContext | null {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return null;\n return this._codingContextBySession?.get(sessionKey) ?? null;\n }\n\n /**\n * Shared helper used by both the recall path and the write path (rule 42).\n *\n * Given a base namespace computed from the principal, returns the overlaid\n * coding namespace when the session has a coding context AND\n * `codingMode.projectScope` is true AND `namespacesEnabled` is true.\n * Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.\n *\n * Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with\n * the principal-derived `baseNamespace` rather than replacing it, so two\n * principals working in the same repository do not share memories through\n * a common `project-*` namespace.\n *\n * Namespaces-disabled gate: when `namespacesEnabled` is false, the\n * storage router maps every namespace to the same `memoryDir`. Returning\n * `project-*` in that mode would create apparent route separation with\n * no actual storage isolation — a false-isolation trap. In that mode we\n * return `baseNamespace` unchanged so coding mode degrades to the existing\n * unscoped behavior.\n *\n * @internal\n */\n applyCodingNamespaceOverlay(sessionKey: string | undefined, baseNamespace: string): string {\n if (!this.config.namespacesEnabled) return baseNamespace;\n const codingContext = this.getCodingContextForSession(sessionKey);\n const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode, this.config.defaultNamespace);\n if (!overlay) return baseNamespace;\n return combineNamespaces(baseNamespace, overlay.namespace);\n }\n\n /**\n * Register a peer ID for a session so recall can inject the peer's\n * profile into context (issue #679 PR 3/5). Pass `null` to clear.\n *\n * Connectors and the `before_agent_start` hook call this when the\n * session's counter-party is known. The ID is validated against\n * `PEER_ID_PATTERN` before storing.\n *\n * Fail-closed (Codex P1 review): an invalid peerId clears any\n * previously registered mapping for the session rather than silently\n * keeping stale data. This prevents a malformed metadata update from\n * mixing one peer's profile context into another session.\n *\n * Defensive init (Cursor review + rule 16): `Object.create(\n * Orchestrator.prototype)` stubs in legacy tests skip class-field\n * initializers, so `_peerIdBySession` may be undefined. Mirror the\n * same guard used by `setCodingContextForSession`.\n */\n setPeerIdForSession(sessionKey: string, peerId: string | null): void {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return;\n // Defensive init — mirrors setCodingContextForSession (rule 16).\n if (!this._peerIdBySession) {\n (this as unknown as { _peerIdBySession: Map<string, string> })._peerIdBySession = new Map();\n }\n if (peerId === null) {\n this._peerIdBySession.delete(sessionKey);\n return;\n }\n // Basic pattern guard — full validation lives in peers/storage.ts.\n // Invalid input is fail-closed: clear the existing mapping so stale\n // peer context can't bleed in after a bad metadata update (Codex P1).\n if (\n typeof peerId !== \"string\" ||\n peerId.length === 0 ||\n peerId.length > 64 ||\n !/^[A-Za-z0-9]+(?:[._-][A-Za-z0-9]+)*$/.test(peerId)\n ) {\n log.warn(`setPeerIdForSession: invalid peerId — clearing session mapping`);\n this._peerIdBySession.delete(sessionKey);\n return;\n }\n this._peerIdBySession.set(sessionKey, peerId);\n }\n\n /**\n * Return the peer ID registered for a session, or `null` when none\n * is set. Used by `recallInternal` to inject the peer profile section.\n * Defensive `_peerIdBySession` lookup — legacy orchestrator-flush tests\n * use `Object.create(Orchestrator.prototype)` which skips class-field\n * initializers, so the Map may be undefined on stubs.\n */\n getPeerIdForSession(sessionKey: string | undefined): string | null {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return null;\n return this._peerIdBySession?.get(sessionKey) ?? null;\n }\n\n /**\n * Read-side overlay: returns the list of namespaces a session should read\n * from, including any read fallbacks (branch → project, global root).\n *\n * Returns `null` when:\n * - `namespacesEnabled` is false (overlay would create false isolation)\n * - no context attached to the session\n * - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)\n *\n * The returned `namespace` / `readFallbacks` are RAW overlay fragments\n * (e.g. `project-origin-ab12`). Callers MUST combine them with the\n * principal-derived base through `combineNamespaces()` before passing to\n * storage, so principal isolation is preserved (rule 42).\n *\n * @internal\n */\n applyCodingRecallOverlay(sessionKey: string | undefined): { namespace: string; readFallbacks: string[] } | null {\n if (!this.config.namespacesEnabled) return null;\n const codingContext = this.getCodingContextForSession(sessionKey);\n const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode, this.config.defaultNamespace);\n if (!overlay) return null;\n return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };\n }\n\n async getStorageForNamespace(namespace?: string): Promise<StorageManager> {\n const ns =\n typeof namespace === \"string\" && namespace.trim().length > 0\n ? namespace.trim()\n : this.config.defaultNamespace;\n return this.storageRouter.storageFor(ns);\n }\n\n private configuredNamespaces(): string[] {\n return Array.from(\n new Set(\n [\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((policy) => policy.name),\n ]\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n );\n }\n\n private buildConfiguredQmdSearchOptions(\n queryText: string,\n ): SearchQueryOptions | undefined {\n const intentHint = this.config.qmdIntentHintsEnabled\n ? buildQmdIntentHint(inferIntentFromText(queryText))\n : undefined;\n const explain = this.config.qmdExplainEnabled === true;\n const searchOptions: SearchQueryOptions = {};\n if (intentHint) {\n searchOptions.intent = intentHint;\n }\n if (explain) {\n searchOptions.explain = true;\n }\n return Object.keys(searchOptions).length > 0 ? searchOptions : undefined;\n }\n\n async searchAcrossNamespaces(options: {\n query: string;\n namespaces?: string[];\n maxResults?: number;\n mode?: \"search\" | \"hybrid\" | \"bm25\" | \"vector\";\n searchOptions?: SearchQueryOptions;\n execution?: SearchExecutionOptions;\n }): Promise<QmdSearchResult[]> {\n const namespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set(\n (options.namespaces?.length\n ? options.namespaces\n : this.configuredNamespaces()\n )\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n )\n : [this.config.defaultNamespace];\n\n if (!this.config.namespacesEnabled) {\n switch (options.mode) {\n case \"hybrid\":\n return await this.qmd.hybridSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"bm25\":\n return await this.qmd.bm25Search(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"vector\":\n return await this.qmd.vectorSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n default:\n return await this.qmd.search(\n options.query,\n undefined,\n options.maxResults,\n options.searchOptions,\n options.execution,\n );\n }\n }\n\n return await this.namespaceSearchRouter.searchAcrossNamespaces({\n query: options.query,\n namespaces,\n maxResults: options.maxResults,\n mode: options.mode,\n searchOptions: options.searchOptions,\n execution: options.execution,\n });\n }\n\n private isSearchAvailableForNamespaceRouting(): boolean {\n if (this.config.namespacesEnabled) return true;\n return this.qmd.isAvailable();\n }\n\n invalidateLiveContentHashIndex(): void {\n this.contentHashIndex = null;\n }\n\n constructor(config: PluginConfig) {\n this.config = config;\n this.profiler = new ProfilingCollector({\n enabled: config.profilingEnabled,\n storageDir: config.profilingStorageDir || path.join(config.memoryDir, \"profiling\"),\n maxTraces: config.profilingMaxTraces,\n });\n this.storageRouter = new NamespaceStorageRouter(config);\n this.namespaceSearchRouter = new NamespaceSearchRouter(\n config,\n this.storageRouter,\n );\n this.storage = new StorageManager(config.memoryDir, config.entitySchemas);\n // Propagate the inline-attribution template so the storage layer can strip\n // citations from legacy facts during the hash-index rebuild path.\n this.storage.citationTemplate = config.inlineSourceAttributionFormat;\n // Wire page-level versioning (issue #371)\n this.storage.setVersioningConfig({\n enabled: config.versioningEnabled,\n maxVersionsPerPage: config.versioningMaxPerPage,\n sidecarDir: config.versioningSidecarDir,\n });\n // Wire at-rest encryption (issue #690 PR 3/4).\n // If secureStoreEnabled, check whether the keyring already holds a key\n // for this memory dir (e.g. operator unlocked before daemon restart).\n if (config.secureStoreEnabled) {\n // Mark the store as required so writes throw SecureStoreLockedError\n // instead of silently falling back to plaintext when locked (P1 finding\n // from Cursor review of PR #767).\n this.storage.setSecureStoreRequired(true);\n const storeId = secureStoreDir(config.memoryDir);\n const existingKey = keyring.getKey(storeId);\n if (existingKey) {\n this.storage.setSecureStoreKey(existingKey, config.secureStoreEncryptOnWrite);\n }\n // If no key is present the store remains locked until `remnic secure-store unlock`\n // is run — reads of encrypted files will throw SecureStoreLockedError,\n // and writes will throw SecureStoreLockedError via resolveWriteKey().\n }\n this.qmd = createSearchBackend(config);\n const conversationIndexRuntime = createConversationIndexRuntime(config, {\n getQmd: () => this.conversationQmd,\n getFaiss: () => this.conversationFaiss,\n });\n this.conversationQmd = conversationIndexRuntime.qmd;\n this.conversationFaiss = conversationIndexRuntime.faiss;\n this.conversationIndexBackend = conversationIndexRuntime.backend;\n this.sharedContext = config.sharedContextEnabled\n ? new SharedContextManager(config)\n : undefined;\n this.compounding = config.compoundingEnabled\n ? new CompoundingEngine(config, this.storage)\n : undefined;\n this.buffer = new SmartBuffer(config, this.storage);\n this.transcript = new TranscriptManager(config);\n this.conversationIndexDir = path.join(\n config.memoryDir,\n \"conversation-index\",\n \"chunks\",\n );\n this.modelRegistry = new ModelRegistry(config.memoryDir);\n this.relevance = new RelevanceStore(config.memoryDir);\n this.negatives = new NegativeExampleStore(config.memoryDir);\n this.lastRecall = new LastRecallStore(config.memoryDir);\n this.tierMigrationStatus = new TierMigrationStatusStore(config.memoryDir);\n this.sessionObserver = new SessionObserverState({\n memoryDir: config.memoryDir,\n debounceMs: config.sessionObserverDebounceMs ?? 120_000,\n bands: config.sessionObserverBands ?? [],\n });\n this.embeddingFallback = new EmbeddingFallback(config);\n this.policyRuntime = new PolicyRuntimeManager(config.memoryDir, config);\n this.summarizer = new HourlySummarizer(\n config,\n config.gatewayConfig,\n this.modelRegistry,\n this.transcript,\n );\n this.judgeVerdictCache = createVerdictCache();\n this.judgeDeferCounts = createDeferCountMap();\n this.localLlm = new LocalLlmClient(config, this.modelRegistry);\n // Issue #548: the main local-LLM client is used by extraction,\n // consolidation, and other structured-output tasks that gain\n // nothing from chain-of-thought reasoning. Apply the operator's\n // configured preference (default true) so thinking-capable models\n // skip reasoning tokens and avoid the common 60s extraction\n // timeout. Operators can set `localLlmDisableThinking: false`\n // when they want thinking enabled for narrative paths.\n this.localLlm.disableThinking = config.localLlmDisableThinking;\n this.fastLlm = config.localLlmFastEnabled\n ? (() => {\n const client = new LocalLlmClient(\n {\n ...config,\n localLlmModel: config.localLlmFastModel || config.localLlmModel,\n localLlmUrl: config.localLlmFastUrl,\n localLlmTimeoutMs: config.localLlmFastTimeoutMs,\n },\n this.modelRegistry,\n );\n // Fast-tier always suppresses thinking — the contract of\n // `fastLlm` is \"low latency at all costs\" and that is\n // independent of the main-client config.\n client.disableThinking = true;\n return client;\n })()\n : this.localLlm;\n // Initialize gateway fast LLM for fast-tier ops when modelSource is \"gateway\"\n this._fastGatewayLlm = config.modelSource === \"gateway\"\n ? new FallbackLlmClient(config.gatewayConfig)\n : null;\n if (config.modelSource === \"gateway\") {\n log.debug(\n `orchestrator: gateway model source active` +\n (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : \"\") +\n (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : \"\"),\n );\n }\n this.extraction = new ExtractionEngine(\n config,\n this.profiler,\n this.localLlm,\n config.gatewayConfig,\n this.modelRegistry,\n );\n this.threading = new ThreadingManager(\n path.join(config.memoryDir, \"threads\"),\n config.threadingGapMinutes,\n );\n // BoxBuilders are created per-namespace on first use in runExtraction().\n\n // Temporal Memory Tree (v8.2) — lazy build during consolidation\n this.tmtBuilder = new TmtBuilder(config.memoryDir, {\n temporalMemoryTreeEnabled: config.temporalMemoryTreeEnabled,\n tmtHourlyMinMemories: config.tmtHourlyMinMemories,\n tmtSummaryMaxTokens: config.tmtSummaryMaxTokens,\n });\n\n // Lossless Context Management (LCM) — proactive session archive + DAG summarization\n if (config.lcmEnabled) {\n const summarizeFn = async (\n text: string,\n targetTokens: number,\n aggressive: boolean,\n ) => {\n const instructionText = aggressive\n ? `Compress the following into bullet points. One bullet per distinct fact or decision. Maximum ${targetTokens} tokens total. No prose.`\n : `Compress the following conversation segment into a dense summary. Preserve: decisions made, code artifacts mentioned, errors encountered, open questions, and any commitments or next-steps. Omit: pleasantries, restatements, and anything the agent would not need to recall later. Output a single paragraph, maximum ${targetTokens} tokens.`;\n try {\n const result = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: instructionText },\n { role: \"user\", content: text.slice(0, 12000) },\n ],\n {\n maxTokens: targetTokens * 2,\n operation: \"lcm-summarize\",\n priority: \"background\",\n },\n );\n return result?.content ?? null;\n } catch {\n return null;\n }\n };\n this.lcmEngine = new LcmEngine(config, summarizeFn);\n }\n\n // Create init gate — recall() will await this before proceeding\n this.initPromise = new Promise<void>((resolve) => {\n this.resolveInit = resolve;\n });\n\n // deferredReady is NOT created here — the property initializer provides a\n // safe default (Promise.resolve()), and initialize() recreates it on every\n // call. Creating a pending promise in the constructor would be orphaned\n // since initialize() unconditionally overwrites it.\n }\n\n /** Get or create a BoxBuilder for the given namespace storage root (namespace-isolated). */\n private boxBuilderFor(storage: StorageManager): BoxBuilder {\n const dir = storage.dir;\n if (!this.boxBuilders.has(dir)) {\n this.boxBuilders.set(\n dir,\n new BoxBuilder(dir, {\n memoryBoxesEnabled: this.config.memoryBoxesEnabled,\n traceWeaverEnabled: this.config.traceWeaverEnabled,\n boxTopicShiftThreshold: this.config.boxTopicShiftThreshold,\n boxTimeGapMs: this.config.boxTimeGapMs,\n boxMaxMemories: this.config.boxMaxMemories,\n traceWeaverLookbackDays: this.config.traceWeaverLookbackDays,\n traceWeaverOverlapThreshold: this.config.traceWeaverOverlapThreshold,\n }),\n );\n }\n return this.boxBuilders.get(dir)!;\n }\n\n private effectiveRecencyWeight(): number {\n return applyRuntimeRetrievalPolicy(\n { recencyWeight: this.config.recencyWeight },\n this.runtimePolicyValues,\n ).recencyWeight;\n }\n\n private effectiveCronRecallInstructionHeavyTokenCap(): number {\n return (\n this.runtimePolicyValues?.cronRecallInstructionHeavyTokenCap ??\n this.config.cronRecallInstructionHeavyTokenCap\n );\n }\n\n private currentPolicyVersion(): string {\n const thresholds = this.effectiveLifecycleThresholds();\n const payload = {\n recencyWeight: this.effectiveRecencyWeight(),\n lifecyclePromoteHeatThreshold: thresholds.promoteHeatThreshold,\n lifecycleStaleDecayThreshold: thresholds.staleDecayThreshold,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n utilityRankingBoostMultiplier:\n this.utilityRuntimeValues?.rankingBoostMultiplier ?? 1,\n utilityRankingSuppressMultiplier:\n this.utilityRuntimeValues?.rankingSuppressMultiplier ?? 1,\n utilityPromoteThresholdDelta:\n this.utilityRuntimeValues?.promoteThresholdDelta ?? 0,\n utilityDemoteThresholdDelta:\n this.utilityRuntimeValues?.demoteThresholdDelta ?? 0,\n };\n return createHash(\"sha256\")\n .update(JSON.stringify(payload))\n .digest(\"hex\")\n .slice(0, 12);\n }\n\n private effectiveLifecycleThresholds(): {\n promoteHeatThreshold: number;\n staleDecayThreshold: number;\n archiveDecayThreshold: number;\n } {\n const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;\n const staleDecayThreshold = Math.min(\n this.runtimePolicyValues?.lifecycleStaleDecayThreshold ??\n this.config.lifecycleStaleDecayThreshold,\n archiveDecayThreshold,\n );\n return {\n promoteHeatThreshold:\n this.runtimePolicyValues?.lifecyclePromoteHeatThreshold ??\n this.config.lifecyclePromoteHeatThreshold,\n staleDecayThreshold,\n archiveDecayThreshold,\n };\n }\n\n private routeEngineOptions(): RoutingEngineOptions {\n const allowedNamespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((policy) => policy.name),\n ]),\n )\n : [this.config.defaultNamespace];\n return { allowedNamespaces };\n }\n\n private getRoutingRulesStore(): RoutingRulesStore {\n if (!this.routingRulesStore) {\n this.routingRulesStore = new RoutingRulesStore(\n this.config.memoryDir,\n this.config.routingRulesStateFile,\n );\n }\n return this.routingRulesStore;\n }\n\n private async loadRoutingRules(): Promise<RouteRule[]> {\n if (!this.config.routingRulesEnabled) return [];\n try {\n return await this.getRoutingRulesStore().read(this.routeEngineOptions());\n } catch (err) {\n log.warn(\n `routing rules unavailable; fail-open to default writes: ${err}`,\n );\n return [];\n }\n }\n\n private async resolveArtifactSourceStatuses(\n storage: StorageManager,\n sourceIds: string[],\n ): Promise<Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">> {\n const currentStatusVersion = storage.getMemoryStatusVersion();\n const cached = this.artifactSourceStatusCache.get(storage);\n let snapshot = cached;\n const isFresh =\n snapshot !== undefined &&\n Date.now() - snapshot.loadedAtMs <=\n Orchestrator.ARTIFACT_STATUS_CACHE_TTL_MS &&\n snapshot.statusVersion === currentStatusVersion;\n\n const rebuildSnapshot = async () => {\n const MAX_STABLE_READ_ATTEMPTS = 3;\n let latestStatuses = new Map<\n string,\n \"active\" | \"superseded\" | \"archived\" | \"missing\"\n >();\n let latestVersionAfter = storage.getMemoryStatusVersion();\n\n for (let attempt = 0; attempt < MAX_STABLE_READ_ATTEMPTS; attempt += 1) {\n const versionBefore = storage.getMemoryStatusVersion();\n const allMemories = await storage.readAllMemories();\n const versionAfter = storage.getMemoryStatusVersion();\n latestVersionAfter = versionAfter;\n latestStatuses = new Map(\n allMemories.map((m) => [\n m.frontmatter.id,\n (m.frontmatter.status ?? \"active\") as\n | \"active\"\n | \"superseded\"\n | \"archived\"\n | \"missing\",\n ]),\n );\n\n if (versionAfter === versionBefore) {\n const rebuilt = {\n loadedAtMs: Date.now(),\n statusVersion: versionAfter,\n statuses: latestStatuses,\n };\n this.artifactSourceStatusCache.set(storage, rebuilt);\n return rebuilt;\n }\n }\n\n // Sustained write churn: return latest read without caching a potentially torn snapshot.\n return {\n loadedAtMs: Date.now(),\n statusVersion: latestVersionAfter,\n statuses: latestStatuses,\n };\n };\n\n if (!isFresh) {\n snapshot = await rebuildSnapshot();\n } else {\n // Warm cache may miss brand-new sourceMemoryId values created after snapshot build.\n // Refresh once on-demand when unseen IDs are requested.\n const hasUnknownSourceIds = sourceIds.some(\n (id) => !snapshot?.statuses.has(id),\n );\n if (hasUnknownSourceIds) {\n snapshot = await rebuildSnapshot();\n }\n }\n\n // Persist negative lookups in the cached snapshot so stale source IDs do not\n // trigger repeated full snapshot rebuilds on every matching recall.\n for (const id of sourceIds) {\n if (!snapshot?.statuses.has(id)) {\n snapshot?.statuses.set(id, \"missing\");\n }\n }\n\n const statuses = new Map<\n string,\n \"active\" | \"superseded\" | \"archived\" | \"missing\"\n >();\n for (const id of sourceIds) {\n const status = snapshot?.statuses.get(id);\n if (status) {\n statuses.set(id, status);\n } else {\n statuses.set(id, \"missing\");\n }\n }\n return statuses;\n }\n\n /**\n * Execute a fast-tier LLM chat completion.\n * When gateway model source is active and fastGatewayAgentId is configured,\n * routes through the gateway chain. Otherwise uses the local fast LLM.\n */\n private async fastChatCompletion(\n messages: Array<{ role: string; content: string }>,\n options: { temperature?: number; maxTokens?: number; timeoutMs?: number; operation?: string; priority?: \"background\" | \"recall-critical\" },\n ): Promise<{ content: string } | null> {\n if (this._fastGatewayLlm && this.config.modelSource === \"gateway\") {\n const agentId =\n this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined;\n const result = await this._fastGatewayLlm.chatCompletion(\n messages as Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n { temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId },\n );\n return result ? { content: result.content } : null;\n }\n const result = await this.fastLlm.chatCompletion(messages, options);\n return result ? { content: result.content } : null;\n }\n\n /**\n * Get a fast-tier LLM client compatible with the rerank interface.\n * When gateway model source is active, routes through the gateway fast chain.\n * Otherwise returns the local fast LLM directly.\n */\n get fastLlmForRerank(): {\n chatCompletion: (\n messages: Array<{ role: string; content: string }>,\n options?: { maxTokens?: number; temperature?: number; timeoutMs?: number; operation?: string; priority?: \"recall-critical\" | \"background\" },\n ) => Promise<{ content: string } | null>;\n } {\n if (this._fastGatewayLlm && this.config.modelSource === \"gateway\") {\n return {\n chatCompletion: (messages, options) =>\n this.fastChatCompletion(messages, options ?? {}),\n };\n }\n return this.fastLlm;\n }\n\n async initialize(): Promise<void> {\n // Recreate the deferred-ready gate on every initialize() call.\n // The same Orchestrator instance may be reused across stop/start cycles\n // (src/index.ts does this). Without this reset, the second cycle's\n // `await orchestrator.deferredReady` resolves immediately (already settled\n // from the first cycle) while the new deferredInitialize() is still running.\n this.deferredReady = new Promise<void>((resolve) => {\n this.resolveDeferredReady = resolve;\n });\n\n try {\n await migrateFromEngram({\n quiet: true,\n logger: (message) => log.info(message),\n });\n await this.storage.ensureDirectories();\n await this.storage.loadAliases();\n if (this.config.namespacesEnabled) {\n const namespaces = new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]);\n for (const ns of namespaces) {\n const sm = await this.storageRouter.storageFor(ns);\n await sm.ensureDirectories();\n await sm.loadAliases().catch(() => undefined);\n }\n }\n await this.relevance.load();\n await this.negatives.load();\n await this.lastRecall.load();\n await this.tierMigrationStatus.load();\n await this.sessionObserver.load();\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n this.utilityRuntimeValues = await loadUtilityRuntimeValues({\n memoryDir: this.config.memoryDir,\n memoryUtilityLearningEnabled: this.config.memoryUtilityLearningEnabled,\n promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled,\n });\n\n // Initialize content-hash dedup index\n if (this.config.factDeduplicationEnabled) {\n this.contentHashIndex = this.storage.createContentHashIndex();\n await this.contentHashIndex.load();\n log.info(\n `content-hash dedup: loaded ${this.contentHashIndex.size} hashes`,\n );\n }\n await this.transcript.initialize();\n await this.summarizer.initialize();\n if (this.sharedContext) {\n await this.sharedContext.ensureStructure();\n }\n if (this.compounding) {\n await this.compounding.ensureDirs();\n }\n\n // Buffer and compaction cleanup are fast and needed for basic operation —\n // load them before the init gate so turn buffering works immediately.\n try {\n await this.buffer.load();\n } catch (bufErr) {\n log.error(\n `buffer.load() failed (init gate will still open): ${bufErr}`,\n );\n this.buffer.resetToEmpty();\n }\n if (this.config.compactionResetEnabled) {\n try {\n const wsDir = this.config.workspaceDir || defaultWorkspaceDir();\n const files = await readdir(wsDir).catch(() => [] as string[]);\n for (const f of files) {\n if (!f.startsWith(\".compaction-reset-signal-\")) continue;\n const fp = path.join(wsDir, f);\n const s = await stat(fp).catch(() => null);\n if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {\n await unlink(fp).catch(() => {});\n log.debug(`initialize: removed stale compaction signal ${f}`);\n }\n }\n } catch (err) {\n log.debug(\"initialize: stale signal sweep failed:\", err);\n }\n }\n\n // QMD probe + collection check: determines the final QMD state (real\n // client vs NoopSearchBackend). Must complete BEFORE the init gate opens\n // so that recall() — which awaits initPromise — always observes the final\n // QMD state. Without this ordering, a concurrent recall() could read\n // this.qmd while it's still the real client, then get errors when\n // deferredInitialize() swaps it to NoopSearchBackend mid-query.\n try {\n const available = await this.qmd.probe();\n if (available) {\n log.info(`Search backend: available ${this.qmd.debugStatus()}`);\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n const states = await Promise.all(\n namespaces.map(async (namespace) => ({\n namespace,\n state: this.config.namespacesEnabled\n ? await this.namespaceSearchRouter.ensureNamespaceCollection(\n namespace,\n )\n : await this.qmd.ensureCollection(this.config.memoryDir),\n })),\n );\n const defaultState =\n states.find(\n (entry) => entry.namespace === this.config.defaultNamespace,\n )?.state ?? \"unknown\";\n if (defaultState === \"missing\") {\n await this.disposeSearchBackendIfNeeded();\n this.qmd = new NoopSearchBackend();\n log.warn(\n \"Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)\",\n );\n } else if (defaultState === \"unknown\") {\n log.warn(\n \"Search collection check unavailable; keeping search retrieval enabled for fail-open behavior\",\n );\n } else if (defaultState === \"skipped\") {\n log.debug(\n \"Search collection check skipped (remote or daemon-only mode)\",\n );\n }\n for (const entry of states) {\n if (entry.namespace === this.config.defaultNamespace) continue;\n if (entry.state === \"missing\") {\n log.warn(\n `Search collection missing for namespace '${entry.namespace}'; namespace retrieval will fail open to non-search paths`,\n );\n }\n }\n } else if (this.qmd instanceof NoopSearchBackend) {\n log.debug(`Search backend: noop (search intentionally disabled)`);\n } else {\n log.warn(`Search backend: not available ${this.qmd.debugStatus()}`);\n }\n } catch (err) {\n log.error(`QMD probe/collection check failed (non-fatal): ${err}`);\n }\n\n // Open the init gate — essential state (storage, aliases, relevance,\n // transcript, summarizer, buffer) is loaded AND QMD state is finalized\n // (probe + collection check complete, NoopSearchBackend swap done if\n // needed). Warmup, sync, caches, and remaining heavy operations run in\n // the background after this point via deferredInitialize().\n if (this.resolveInit) {\n this.resolveInit();\n this.resolveInit = null;\n log.info(\"init gate opened (essential state + QMD state loaded)\");\n }\n\n // Deferred init: QMD sync, warmup, conversation index, caches, cron.\n // Runs in background so gateway_start returns fast. On low-power hardware\n // (Umbrel, RPi) QMD warmup/sync alone can take 30-60s and cause gateway\n // restart loops when they block the startup path. See issue #462.\n // Note: QMD probe + collection check (including NoopSearchBackend swap)\n // already ran above before the init gate, so this.qmd is finalized.\n //\n // Capture the resolver by value so a concurrent re-initialize() cannot\n // overwrite this.resolveDeferredReady before .finally() runs — that would\n // cause the first cycle's .finally() to resolve the *second* cycle's\n // promise prematurely while leaving the first cycle's promise pending.\n const resolveDeferred = this.resolveDeferredReady;\n this.resolveDeferredReady = null;\n this.deferredInitAbort = new AbortController();\n this.deferredInitialize(this.deferredInitAbort.signal)\n .catch((err) => {\n log.error(`deferred initialization failed (non-fatal): ${err}`);\n })\n .finally(() => {\n resolveDeferred?.();\n });\n } catch (err) {\n // Resolve both gates so callers never hang on permanently-pending promises\n // after catching the initialize() error:\n //\n // - initPromise: recall(), generateDaySummary(), etc. await this as a\n // readiness gate with a 15s timeout. Leaving it pending means every\n // subsequent call pays that timeout penalty.\n //\n // - deferredReady: CLI callers await this for full QMD readiness. Without\n // resolution it hangs forever since deferredInitialize() never ran.\n if (this.resolveInit) {\n this.resolveInit();\n this.resolveInit = null;\n }\n if (this.resolveDeferredReady) {\n this.resolveDeferredReady();\n this.resolveDeferredReady = null;\n }\n throw err;\n }\n }\n\n private async deferredInitialize(signal: AbortSignal): Promise<void> {\n\n // Sync QMD index with current disk state so recall finds recently-written\n // facts. Without this, the index stays stale from the last extraction-\n // triggered update — which can be days ago if the daemon restarted without\n // new extractions. This is the root cause of \"0 memories\" recall results\n // despite thousands of facts on disk.\n if (this.qmd.isAvailable() && this.config.qmdMaintenanceEnabled) {\n try {\n log.info(\"QMD startup sync: updating index to match current disk state\");\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.updateNamespaces(\n this.configuredNamespaces(),\n { signal },\n );\n } else {\n await this.qmd.update({ signal });\n }\n log.info(\"QMD startup sync: complete\");\n this.deferredSyncSucceeded = true;\n } catch (err) {\n log.warn(`QMD startup sync failed (non-fatal): ${err}`);\n // deferredSyncSucceeded stays false — server retry will attempt sync\n }\n } else if (!(this.qmd.isAvailable())) {\n // QMD not available at deferred init time — server retry will handle it\n } else {\n // QMD available but maintenance disabled — consider sync not needed\n this.deferredSyncSucceeded = true;\n }\n\n if (signal.aborted) return;\n\n // Warmup: run cheap searches to pre-load QMD embedding models and the\n // embedding-fallback JSON index so the first real recall is fast.\n const warmupPromises: Promise<void>[] = [];\n if (this.qmd.isAvailable()) {\n const warmupNs = this.config.defaultNamespace;\n log.info(\"QMD warmup: pre-loading models with a test search\");\n warmupPromises.push(\n this.qmd\n .search(\"warmup\", warmupNs, 1, undefined, { signal })\n .then(() => {\n log.info(\"QMD warmup: complete\");\n })\n .catch((err) => {\n log.debug(`QMD warmup search failed (non-fatal): ${err}`);\n }),\n );\n }\n if (this.config.embeddingFallbackEnabled) {\n warmupPromises.push(\n this.embeddingFallback\n .isAvailable()\n .then((ok) => {\n log.info(\n `Embedding fallback warmup: ${ok ? \"available\" : \"unavailable (no provider)\"}`,\n );\n })\n .catch((err) => {\n log.debug(`Embedding fallback warmup failed (non-fatal): ${err}`);\n }),\n );\n }\n await Promise.all(warmupPromises);\n if (signal.aborted) return;\n\n // Pre-warm knowledge index, memory, and entity caches.\n // Awaited so callers of `deferredReady` can rely on warmups being complete\n // and shutdown sequencing does not race with in-flight cache builds.\n const cacheWarmups: Promise<void>[] = [];\n if (this.config.knowledgeIndexEnabled) {\n cacheWarmups.push(\n (async () => {\n try {\n const t0 = Date.now();\n await this.storage.buildKnowledgeIndex(this.config);\n log.info(`Knowledge Index warmup: complete in ${Date.now() - t0}ms`);\n } catch (err) {\n log.debug(`Knowledge Index warmup failed (non-fatal): ${err}`);\n }\n })(),\n );\n }\n cacheWarmups.push(this.storage.readAllMemories().then(() => {}).catch(() => {}));\n cacheWarmups.push(this.storage.readAllEntityFiles().then(() => {}).catch(() => {}));\n await Promise.all(cacheWarmups);\n if (signal.aborted) return;\n\n if (this.config.conversationIndexEnabled && this.conversationIndexBackend) {\n try {\n const init = await this.conversationIndexBackend.initialize();\n if (!init.enabled) {\n this.config.conversationIndexEnabled = false;\n }\n if (init.logLevel === \"info\") {\n log.info(init.message);\n } else if (init.logLevel === \"warn\") {\n log.warn(init.message);\n } else {\n log.debug(init.message);\n }\n } catch (err) {\n log.error(`Conversation index initialization failed (non-fatal): ${err}`);\n this.config.conversationIndexEnabled = false;\n }\n }\n\n if (signal.aborted) return;\n\n if (this.config.localLlmEnabled) {\n try {\n await this.validateLocalLlmModel();\n } catch (err) {\n log.error(`Local LLM validation failed (non-fatal): ${err}`);\n }\n }\n\n if (signal.aborted) return;\n\n // Await cron auto-registration so callers that `await deferredReady` can\n // rely on cron jobs being registered when it resolves. Without this, the\n // fire-and-forget pattern lets deferredReady settle while cron writes are\n // still in flight. Errors are non-fatal — catch individually.\n if (this.config.daySummaryEnabled) {\n try {\n await this.autoRegisterDaySummaryCron();\n } catch (err) {\n log.debug(`day-summary cron auto-register failed (non-fatal): ${err}`);\n }\n }\n if (this.config.nightlyGovernanceCronAutoRegister) {\n try {\n await this.autoRegisterNightlyGovernanceCron();\n } catch (err) {\n log.debug(`nightly governance cron auto-register failed (non-fatal): ${err}`);\n }\n }\n if (this.config.procedural?.proceduralMiningCronAutoRegister) {\n try {\n await this.autoRegisterProceduralMiningCron();\n } catch (err) {\n log.debug(`procedural mining cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n // Auto-register contradiction scan cron (gated by config)\n if (this.config.contradictionScan?.enabled) {\n try {\n await this.autoRegisterContradictionScanCron();\n } catch (err) {\n log.debug(`contradiction scan cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n // Auto-register pattern-reinforcement cron (issue #687 PR 2/4).\n // Gated on the feature flag so memory-only users without the\n // cron daemon installed never see a stray jobs.json mutation.\n if (this.config.patternReinforcementEnabled) {\n try {\n await this.autoRegisterPatternReinforcementCron();\n } catch (err) {\n log.debug(`pattern reinforcement cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n // Auto-register graph-edge decay cron (gated by config — issue #681 PR 2/3).\n if (this.config.graphEdgeDecayEnabled) {\n try {\n await this.autoRegisterGraphEdgeDecayCron();\n } catch (err) {\n log.debug(`graph edge decay cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n // First-start lifecycle migration (issue #686 retention-completion).\n // When lifecyclePolicyEnabled is true and the memoryDir has never been\n // touched by the lifecycle policy, run a one-time rate-limited demotion\n // sweep (capped at 50 demotions) so the hot tier isn't flooded on the\n // first real cron pass. Non-fatal — a failure here must not break init.\n if (signal.aborted) return;\n if (this.config.lifecyclePolicyEnabled && this.config.qmdTierMigrationEnabled) {\n try {\n const { runFirstStartMigration } = await import(\n \"./maintenance/first-start-migration.js\"\n );\n const result = await runFirstStartMigration({\n storage: this.storage,\n config: this.config,\n qmd: this.qmd,\n hotCollection: this.config.qmdCollection,\n coldCollection: this.config.qmdColdCollection,\n signal,\n });\n if (!result.skipped) {\n log.info(\n `first-start lifecycle migration: demoted ${result.demotedCount} of ${result.candidateCount} candidates (cap=${result.cappedAt})`,\n );\n } else {\n log.debug(`first-start lifecycle migration skipped: ${result.skipReason}`);\n }\n } catch (err) {\n log.warn(`first-start lifecycle migration failed (non-fatal): ${err}`);\n }\n }\n\n log.info(\"orchestrator initialized (full — deferred steps complete)\");\n }\n\n /**\n * Namespace-aware startup search sync. Re-probes QMD, ensures collections\n * (namespace-aware when namespacesEnabled), runs update, and warms up search.\n * Designed for server retry paths that run after the deferred init completes\n * when QMD was not available during initial startup.\n *\n * Accepts an optional AbortSignal so callers can interrupt the sync during\n * shutdown. The signal is checked between phases and forwarded into the QMD\n * update and warmup search calls so a long-running `qmd update` subprocess\n * is killed promptly rather than left in flight after `httpServer.stop()`.\n *\n * Returns true if the sync succeeded (QMD now available), false otherwise.\n */\n async startupSearchSync(signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted) return false;\n\n const available = await this.qmd.probe();\n if (!available) return false;\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after probe\");\n return false;\n }\n\n log.info(`startupSearchSync: backend now available ${this.qmd.debugStatus()}`);\n\n // Clear namespace router cache so re-probe picks up newly available backends\n if (this.config.namespacesEnabled) {\n this.namespaceSearchRouter.clearCache();\n }\n\n // Ensure collections — namespace-aware when enabled\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n\n const states = await Promise.all(\n namespaces.map(async (namespace) => ({\n namespace,\n state: this.config.namespacesEnabled\n ? await this.namespaceSearchRouter.ensureNamespaceCollection(namespace)\n : await this.qmd.ensureCollection(this.config.memoryDir),\n })),\n );\n\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after ensureCollection\");\n return false;\n }\n\n const defaultState =\n states.find((e) => e.namespace === this.config.defaultNamespace)?.state ?? \"unknown\";\n if (defaultState === \"missing\") {\n // Reset the real backend's available flag before replacing it with noop.\n // probe() set available=true earlier in this call; without this reset,\n // any code that captured a reference to the old backend (e.g. a concurrent\n // recall() that read this.qmd before the reassignment) would observe\n // isAvailable()===true against a backend with a missing collection.\n if (\"available\" in this.qmd) {\n (this.qmd as any).available = false;\n }\n await this.disposeSearchBackendIfNeeded();\n this.qmd = new NoopSearchBackend();\n log.warn(\"startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)\");\n return false;\n }\n\n // Run index update — namespace-aware when enabled.\n // qmd.update() swallows errors internally, so we: (1) snapshot fail/run\n // timestamps, (2) reset throttles so the update isn't skipped by stale\n // backoff, and (3) verify timestamps after update to confirm it executed\n // and didn't fail silently.\n // The abort signal is forwarded into the QMD subprocess call so the\n // long-running `qmd update` process is killed promptly on shutdown.\n if (this.config.qmdMaintenanceEnabled) {\n try {\n const failTsBefore = \"lastUpdateFailedAtMs\" in this.qmd\n ? (this.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const hasRunTs = \"lastUpdateRanAtMs\" in this.qmd;\n if (\"resetUpdateThrottles\" in this.qmd) {\n (this.qmd as any).resetUpdateThrottles();\n }\n log.info(\"startupSearchSync: updating index to match current disk state\");\n let namespacesUpdated = 0;\n if (this.config.namespacesEnabled) {\n namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(\n namespaces,\n { signal },\n );\n } else {\n await this.qmd.update({ signal });\n }\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after update\");\n return false;\n }\n const failTsAfter = \"lastUpdateFailedAtMs\" in this.qmd\n ? (this.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const runTsAfter = hasRunTs\n ? (this.qmd as any).lastUpdateRanAtMs as number | null\n : null;\n if (failTsAfter !== null && failTsAfter !== failTsBefore) {\n log.warn(\"startupSearchSync: update silently failed (detected via fail timestamp)\");\n return false;\n }\n if (this.config.namespacesEnabled) {\n if (namespacesUpdated === 0) {\n log.warn(\"startupSearchSync: no namespace backends were eligible for update (all unavailable or collections missing)\");\n return false;\n }\n log.info(`startupSearchSync: namespace updates succeeded (${namespacesUpdated}/${namespaces.length} namespaces updated)`);\n } else if (hasRunTs && runTsAfter === null) {\n log.warn(\"startupSearchSync: update was throttled/skipped (run timestamp is null after reset + update)\");\n return false;\n }\n log.info(\"startupSearchSync: sync complete\");\n } catch (err) {\n log.warn(`startupSearchSync: update failed: ${err}`);\n return false;\n }\n }\n\n // Warmup search to pre-load embedding models\n if (!signal?.aborted) {\n try {\n await this.qmd.search(\"warmup\", this.config.defaultNamespace, 1, undefined, { signal });\n log.info(\"startupSearchSync: warmup complete\");\n } catch (err) {\n log.debug(`startupSearchSync: warmup search failed (non-fatal): ${err}`);\n }\n }\n\n return true;\n }\n\n /**\n * Auto-register the engram-day-summary cron job in OpenClaw if it doesn't exist.\n * Fire-and-forget — never blocks init or crashes on failure.\n */\n private async autoRegisterDaySummaryCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\n \"day-summary cron: jobs.json not found, skipping auto-register\",\n );\n return;\n }\n const created = await ensureDaySummaryCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(\n `day-summary cron auto-registered (${created.jobId}, 23:47 ${Intl.DateTimeFormat().resolvedOptions().timeZone})`,\n );\n } else {\n log.debug(\"day-summary cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`day-summary cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterNightlyGovernanceCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"nightly governance cron: jobs.json not found, skipping auto-register\");\n return;\n }\n\n const created = await ensureNightlyGovernanceCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(\n `nightly governance cron auto-registered (${created.jobId}, 02:23 ${Intl.DateTimeFormat().resolvedOptions().timeZone})`,\n );\n } else {\n log.debug(\"nightly governance cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`nightly governance cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterProceduralMiningCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"procedural mining cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const created = await ensureProceduralMiningCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(`procedural mining cron auto-registered (${created.jobId})`);\n } else {\n log.debug(\"procedural mining cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`procedural mining cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterContradictionScanCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"contradiction scan cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const created = await ensureContradictionScanCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(`contradiction scan cron auto-registered (${created.jobId})`);\n } else {\n log.debug(\"contradiction scan cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`contradiction scan cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterPatternReinforcementCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"pattern reinforcement cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const created = await ensurePatternReinforcementCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(`pattern reinforcement cron auto-registered (${created.jobId})`);\n } else {\n log.debug(\"pattern reinforcement cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`pattern reinforcement cron auto-register error: ${err}`);\n }\n }\n\n /**\n * Run the pattern-reinforcement maintenance job (issue #687 PR 2/4).\n *\n * Cadence-gated on `patternReinforcementCadenceMs` so every caller\n * (orchestrator cron path, MCP tool, CLI) shares a single floor —\n * none can call this on a hot loop and burn the corpus. When the\n * feature is disabled or the cadence has not elapsed, returns a\n * synthetic \"skipped\" result rather than throwing.\n *\n * Cadence tracking is per-namespace so a tenant-scoped MCP run in\n * one namespace does not silence a cron run in another (PR #730\n * review feedback, Codex P2). Pass `force: true` for ad-hoc\n * operator runs that must bypass the cadence floor — mirrors the\n * pattern used by other maintenance MCP tools.\n *\n * `force` deliberately does NOT bypass the master\n * `patternReinforcementEnabled` flag (PR #730 review feedback,\n * Cursor Medium). Operators who have explicitly disabled the\n * feature must not have their corpus mutated by an MCP tool call —\n * the only way to run the job is to enable the feature in config.\n */\n async runPatternReinforcement(options: {\n force?: boolean;\n namespace?: string;\n } = {}): Promise<{\n ran: boolean;\n skippedReason?: \"disabled\" | \"cadence\";\n namespace: string;\n result?: PatternReinforcementResult;\n }> {\n const cadenceKey = options.namespace ?? \"\";\n // Master switch: a disabled feature is never bypassed, even with\n // force=true. `force` only relaxes the cadence floor below.\n if (!this.config.patternReinforcementEnabled) {\n return { ran: false, skippedReason: \"disabled\", namespace: cadenceKey };\n }\n const cadence = this.config.patternReinforcementCadenceMs;\n const lastAt = this.lastPatternReinforcementAtByNs.get(cadenceKey);\n if (\n !options.force &&\n cadence > 0 &&\n lastAt !== undefined &&\n Date.now() - lastAt < cadence\n ) {\n return { ran: false, skippedReason: \"cadence\", namespace: cadenceKey };\n }\n const storage = options.namespace\n ? await this.getStorage(options.namespace)\n : this.storage;\n const result = await runPatternReinforcement(storage, {\n categories: this.config.patternReinforcementCategories,\n minCount: this.config.patternReinforcementMinCount,\n });\n this.lastPatternReinforcementAtByNs.set(cadenceKey, Date.now());\n log.debug(\n `pattern reinforcement [ns=${cadenceKey || \"(default)\"}]: clusters=${result.clustersFound} canonicalsUpdated=${result.canonicalsUpdated} duplicatesSuperseded=${result.duplicatesSuperseded}`,\n );\n return { ran: true, result, namespace: cadenceKey };\n }\n\n private async autoRegisterGraphEdgeDecayCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"graph edge decay cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const scheduleExpr = graphEdgeDecayCadenceToCronExpr(this.config.graphEdgeDecayCadenceMs);\n const created = await ensureGraphEdgeDecayCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n scheduleExpr,\n });\n if (created.created) {\n log.info(`graph edge decay cron auto-registered (${created.jobId}, ${scheduleExpr})`);\n } else {\n log.debug(\"graph edge decay cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`graph edge decay cron auto-register error: ${err}`);\n }\n }\n\n async runLiveConnectors(options: {\n force?: boolean;\n abortSignal?: AbortSignal;\n } = {}): Promise<LiveConnectorsRunSummary> {\n return runLiveConnectorsOnce({\n memoryDir: this.config.memoryDir,\n connectors: this.config.connectors,\n force: options.force === true,\n abortSignal: options.abortSignal,\n ingestDocuments: async (docs) => {\n const fetchedAt = new Date().toISOString();\n const turns = docs.map((doc) => ({\n role: \"assistant\" as const,\n content: doc.title\n ? `# ${doc.title}\\n\\n${doc.content}`\n : doc.content,\n timestamp: fetchedAt,\n }));\n await this.ingestBulkImportBatch(turns);\n },\n });\n }\n\n\n async applyBehaviorRuntimePolicy(\n state: BehaviorLoopPolicyState,\n ): Promise<{\n applied: boolean;\n rolledBack: boolean;\n values: RuntimePolicyValues | null;\n reason: string;\n }> {\n const result = await this.policyRuntime.applyFromBehaviorState(state);\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n return result;\n }\n\n async rollbackBehaviorRuntimePolicy(): Promise<boolean> {\n const rolledBack = await this.policyRuntime.rollback();\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n return rolledBack;\n }\n\n async maybeRunFileHygiene(): Promise<void> {\n const hygiene = this.config.fileHygiene;\n if (!hygiene?.enabled) return;\n\n const now = Date.now();\n if (now - this.lastFileHygieneRunAtMs < hygiene.runMinIntervalMs) return;\n this.lastFileHygieneRunAtMs = now;\n\n // Rotation first (keeps bootstrap files small).\n if (hygiene.rotateEnabled) {\n for (const rel of hygiene.rotatePaths) {\n const abs = path.isAbsolute(rel)\n ? rel\n : path.join(this.config.workspaceDir, rel);\n try {\n const raw = await readFile(abs, \"utf-8\");\n if (raw.length > hygiene.rotateMaxBytes) {\n const archiveDir = path.join(\n this.config.workspaceDir,\n hygiene.archiveDir,\n );\n const base = path.basename(abs);\n const prefix =\n base\n .toUpperCase()\n .replace(/\\.MD$/i, \"\")\n .replace(/[^A-Z0-9]+/g, \"-\") || \"FILE\";\n const { newContent } = await rotateMarkdownFileToArchive({\n filePath: abs,\n archiveDir,\n archivePrefix: prefix,\n keepTailChars: hygiene.rotateKeepTailChars,\n });\n await writeFile(abs, newContent, \"utf-8\");\n }\n } catch {\n // ignore missing/unreadable targets\n }\n }\n }\n\n // Lint (warn before truncation risk).\n if (hygiene.lintEnabled) {\n const warnings = await lintWorkspaceFiles({\n workspaceDir: this.config.workspaceDir,\n paths: hygiene.lintPaths,\n budgetBytes: hygiene.lintBudgetBytes,\n warnRatio: hygiene.lintWarnRatio,\n });\n for (const w of warnings) {\n log.warn(w.message);\n }\n\n if (hygiene.warningsLogEnabled && warnings.length > 0) {\n const fp = path.join(this.config.memoryDir, hygiene.warningsLogPath);\n await mkdir(path.dirname(fp), { recursive: true });\n const stamp = new Date().toISOString();\n const block =\n `\\n\\n## ${stamp}\\n\\n` +\n warnings.map((w) => `- ${w.message}`).join(\"\\n\") +\n \"\\n\";\n let existing = \"\";\n try {\n existing = await readFile(fp, \"utf-8\");\n } catch {\n existing = \"# Engram File Hygiene Warnings\\n\";\n }\n await writeFile(fp, existing + block, \"utf-8\");\n }\n }\n }\n\n async runBootstrap(options: BootstrapOptions): Promise<BootstrapResult> {\n const engine = new BootstrapEngine(this.config, this);\n return engine.run(options);\n }\n\n async runConsolidationNow(): Promise<{\n memoriesProcessed: number;\n merged: number;\n invalidated: number;\n }> {\n return this.runConsolidation();\n }\n\n async reindexMemoryById(\n id: string,\n options?: { storage?: StorageManager },\n ): Promise<void> {\n await this.indexPersistedMemory(options?.storage ?? this.storage, id);\n this.requestQmdMaintenance();\n }\n\n registerConsolidationObserver(\n observer: (observation: ConsolidationObservation) => Promise<void> | void,\n ): () => void {\n this.consolidationObservers.add(observer);\n return () => {\n this.consolidationObservers.delete(observer);\n };\n }\n\n async runSemanticConsolidationNow(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n storage?: StorageManager;\n }): Promise<SemanticConsolidationResult> {\n return this.runSemanticConsolidation({ ...options, force: true });\n }\n\n async runDeepSleepGovernanceNow(options?: {\n dryRun?: boolean;\n storage?: StorageManager;\n }): Promise<{ scannedMemories: number; appliedActionCount: number; notes?: string }> {\n const targetStorage = options?.storage ?? this.storage;\n const { runMemoryGovernance } = await import(\"./maintenance/memory-governance.js\");\n const { summarizeGovernanceResultForDreams } = await import(\"./maintenance/dreams-ledger.js\");\n const govResult = await runMemoryGovernance({\n memoryDir: targetStorage.dir,\n mode: options?.dryRun === true ? \"shadow\" : \"apply\",\n });\n if (options?.dryRun !== true) {\n try {\n await this.processEntitySynthesisQueue(\n this.namespaceFromStorageDir(targetStorage.dir),\n 5,\n );\n } catch (error) {\n log.debug(`deep-sleep governance: entity synthesis refresh failed after apply: ${error}`);\n }\n }\n return summarizeGovernanceResultForDreams(govResult, options?.dryRun === true);\n }\n\n private async runSemanticConsolidation(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n force?: boolean;\n storage?: StorageManager;\n }): Promise<SemanticConsolidationResult> {\n const targetStorage = options?.storage ?? this.storage;\n const result: SemanticConsolidationResult = {\n clustersFound: 0,\n memoriesConsolidated: 0,\n memoriesArchived: 0,\n errors: 0,\n clusters: [],\n };\n\n if (!this.config.semanticConsolidationEnabled && !options?.force) {\n log.debug(\"[semantic-consolidation] disabled in config\");\n return result;\n }\n\n log.info(\"[semantic-consolidation] starting run\");\n\n const allMemories = await targetStorage.readAllMemories();\n if (allMemories.length < 10) {\n log.debug(\"[semantic-consolidation] too few memories, skipping\");\n return result;\n }\n\n const threshold =\n options?.thresholdOverride ?? this.config.semanticConsolidationThreshold;\n const clusters = findSimilarClusters(allMemories, {\n threshold,\n minClusterSize: this.config.semanticConsolidationMinClusterSize,\n excludeCategories: this.config.semanticConsolidationExcludeCategories,\n maxPerRun: this.config.semanticConsolidationMaxPerRun,\n });\n\n result.clustersFound = clusters.length;\n result.clusters = clusters;\n\n if (clusters.length === 0) {\n log.info(\"[semantic-consolidation] no clusters found\");\n return result;\n }\n\n log.info(`[semantic-consolidation] found ${clusters.length} cluster(s)`);\n\n if (options?.dryRun) {\n log.info(\n \"[semantic-consolidation] dry run — skipping LLM synthesis and archival\",\n );\n return result;\n }\n\n // Use FallbackLlmClient for LLM calls (same pattern as causal-consolidation.ts)\n // Honor semanticConsolidationModel: \"auto\" = primary, \"fast\" = local fast, or specific model\n const { FallbackLlmClient } = await import(\"./fallback-llm.js\");\n const useGateway = this.config.modelSource === \"gateway\";\n const modelSetting = this.config.semanticConsolidationModel;\n if (modelSetting === \"fast\" && this.fastLlm && !useGateway) {\n log.info(\"[semantic-consolidation] using fast local LLM for synthesis\");\n }\n const gatewayAgentId = useGateway\n ? (modelSetting === \"fast\" && this.config.fastGatewayAgentId\n ? this.config.fastGatewayAgentId\n : this.config.gatewayAgentId || undefined)\n : undefined;\n const llm = new FallbackLlmClient(this.config.gatewayConfig);\n if (!llm.isAvailable(gatewayAgentId) && !(modelSetting === \"fast\" && this.fastLlm && !useGateway)) {\n log.warn(\n \"[semantic-consolidation] no LLM available — skipping synthesis\",\n );\n return result;\n }\n\n // Discover memory extensions once for all clusters (#382)\n let extensionsBlock = \"\";\n try {\n extensionsBlock = await buildExtensionsBlockForConsolidation(this.config);\n } catch (err) {\n log.warn(`[semantic-consolidation] extension discovery failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);\n }\n\n for (const cluster of clusters) {\n try {\n // Operator-aware prompt (issue #561 PR 3): ask the LLM to pick the\n // SPLIT/MERGE/UPDATE operator alongside the canonical output. Falls\n // back to the legacy plain-blob prompt when operator-aware\n // consolidation is explicitly disabled via config, so rollbacks stay\n // clean.\n // Use the `=== true` idiom for default-false flags (PR #632\n // review, cursor Low): sibling disabled-by-default flags like\n // `semanticConsolidationEnabled` follow the same convention,\n // while `!== false` is reserved for default-on flags.\n const operatorAwareEnabled =\n this.config.operatorAwareConsolidationEnabled === true;\n let prompt = operatorAwareEnabled\n ? buildOperatorAwareConsolidationPrompt(cluster)\n : buildConsolidationPrompt(cluster);\n if (extensionsBlock.length > 0) {\n prompt += \"\\n\\n\" + extensionsBlock;\n }\n const messages = [\n {\n role: \"system\" as const,\n content: operatorAwareEnabled\n ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, \"operator\" and \"output\". The \"operator\" value MUST be one of the exact strings \"merge\", \"update\", or \"split\" — never a pipe-separated placeholder, never prose. The \"output\" value is the canonical memory text.'\n : \"You are a memory consolidation system. Output only the consolidated memory text.\",\n },\n { role: \"user\" as const, content: prompt },\n ];\n const llmOpts = { temperature: 0.2, maxTokens: 2000 };\n\n // Route to the configured model\n let response: { content: string } | null = null;\n if (useGateway) {\n // Gateway model source — use the appropriate agent chain\n response = await llm.chatCompletion(messages, { ...llmOpts, agentId: gatewayAgentId });\n } else if (modelSetting === \"fast\" && this.fastLlm) {\n const fastResult = await this.fastLlm.chatCompletion(messages, {\n operation: \"semantic-consolidation\",\n maxTokens: llmOpts.maxTokens,\n temperature: llmOpts.temperature,\n priority: \"background\",\n });\n response = fastResult ? { content: fastResult.content } : null;\n } else {\n response = await llm.chatCompletion(messages, llmOpts);\n }\n\n if (!response?.content) {\n log.warn(\n `[semantic-consolidation] empty LLM response for cluster in \"${cluster.category}\"`,\n );\n result.errors++;\n continue;\n }\n\n // Operator-aware parse (issue #561 PR 3). In legacy mode we fall\n // back to the plain-text parser and derive the operator from the\n // cluster-shape heuristic so `derived_via` still lands.\n // Restricted to `SemanticConsolidationLlmOperator`\n // (split/merge/update) — `pattern-reinforcement` joined the\n // wider `ConsolidationOperator` type in #687 PR 2/4 but is\n // reserved for the maintenance job and must never be assignable\n // here (Cursor Bugbot review, PR #730).\n let canonicalContent: string;\n let operator: SemanticConsolidationLlmOperator;\n if (operatorAwareEnabled) {\n const parsed = parseOperatorAwareConsolidationResponse(\n response.content,\n cluster,\n );\n canonicalContent = parsed.output;\n operator = parsed.operator;\n } else {\n canonicalContent = parseConsolidationResponse(response.content);\n operator = chooseConsolidationOperator(cluster);\n }\n cluster.canonicalContent = canonicalContent;\n\n // Pick the most recent memory's metadata as the basis for lineage\n const sorted = [...cluster.memories].sort(\n (a, b) =>\n new Date(b.frontmatter.created).getTime() -\n new Date(a.frontmatter.created).getTime(),\n );\n const newest = sorted[0];\n const lineageIds = cluster.memories.map((m) => m.frontmatter.id);\n\n // Consolidation provenance (issue #561 PR 2+3): snapshot each\n // source memory BEFORE archiving it, collecting\n // \"<relpath>:<versionId>\" pointers for the new canonical memory's\n // `derived_from` frontmatter field. Snapshots are best-effort — if\n // page-versioning is disabled (default in `config.ts`) or a single\n // source fails to snapshot we simply omit that entry rather than\n // abort the consolidation. The `derived_via` operator is chosen\n // above (PR 3) from the LLM response or the cluster-shape\n // heuristic fallback and emitted unconditionally so consolidation\n // outputs stay identifiable even when no snapshots are captured\n // (PR #624 review feedback).\n const derivedFromEntries: string[] = [];\n for (const m of cluster.memories) {\n if (!m.path) continue;\n const entry = await targetStorage.snapshotForProvenance(m.path);\n if (entry) derivedFromEntries.push(entry);\n }\n\n // Write the canonical memory\n const canonicalId = await targetStorage.writeMemory(\n newest.frontmatter.category,\n canonicalContent,\n {\n actor: \"semantic-consolidation\",\n confidence: newest.frontmatter.confidence,\n tags: [\n ...new Set(\n cluster.memories.flatMap((m) => m.frontmatter.tags ?? []),\n ),\n ],\n source: \"semantic-consolidation\",\n lineage: lineageIds,\n derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : undefined,\n derivedVia: operator,\n },\n );\n\n result.memoriesConsolidated++;\n\n // Archive originals\n for (const m of cluster.memories) {\n const archiveResult = await targetStorage.archiveMemory(m, {\n actor: \"semantic-consolidation\",\n reasonCode: \"semantic-consolidation\",\n relatedMemoryIds: [canonicalId],\n });\n if (archiveResult) {\n // Remove from content-hash index.\n // Use the raw-content hash stored on the frontmatter at write\n // time (contentHash) — it is format-agnostic and survives any\n // citation template. Legacy memories without contentHash are\n // skipped (see Finding 2 — Urgw).\n if (this.contentHashIndex) {\n if (m.frontmatter.contentHash) {\n // Modern memory: frontmatter.contentHash is already a SHA-256\n // hex string — use removeByHash to avoid double-hashing.\n this.contentHashIndex.removeByHash(m.frontmatter.contentHash);\n } else {\n // Legacy memory written before contentHash was stored on the\n // frontmatter. Pre-#369 facts were stored without inline\n // citations, so m.content is the raw fact text and we can\n // remove the hash directly from the content. This clears\n // stale dedup entries so the fact can be re-extracted.\n log.warn(\n `[semantic-consolidation] removing hash for legacy memory ${m.frontmatter.id ?? \"(unknown)\"} via content fallback — no contentHash in frontmatter`,\n );\n this.contentHashIndex.remove(m.content);\n }\n }\n await this.embeddingFallback.removeFromIndex(m.frontmatter.id);\n if (\n this.config.queryAwareIndexingEnabled &&\n m.path &&\n m.frontmatter?.created\n ) {\n deindexMemory(\n targetStorage.dir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n result.memoriesArchived++;\n }\n }\n\n log.info(\n `[semantic-consolidation] consolidated ${cluster.memories.length} memories → ${canonicalId}`,\n );\n } catch (err) {\n log.warn(\n `[semantic-consolidation] cluster processing failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n result.errors++;\n }\n }\n\n // Save hash index if we modified it\n if (result.memoriesArchived > 0 && this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) =>\n log.warn(\n `[semantic-consolidation] content-hash index save failed: ${err}`,\n ),\n );\n }\n\n log.info(\n `[semantic-consolidation] complete: clusters=${result.clustersFound}, consolidated=${result.memoriesConsolidated}, archived=${result.memoriesArchived}, errors=${result.errors}`,\n );\n\n // #378: fire the Codex materialize post-hook so `codexMaterializeOnConsolidation`\n // actually has a runtime effect. The helper silently no-ops when the\n // feature flag or the per-trigger toggle is off, when the sentinel is\n // missing, or when nothing has changed since the previous run, so it's\n // safe to always call here. Wrapped in a try/catch because a failed\n // materialize must never abort the consolidation result — consolidation\n // is the load-bearing operation; materialization is an optional mirror.\n try {\n await materializeAfterSemanticConsolidation({\n config: this.config,\n memoryDir: targetStorage.dir,\n });\n } catch (err) {\n log.warn(\n `[semantic-consolidation] Codex materialize post-hook failed (non-fatal): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n\n // Issue #679 PR 2/5 — async peer profile reasoner runs as part of\n // the REM phase, immediately after semantic consolidation. Gated\n // on `peerProfileReasonerEnabled` (default false, opt-in). Wrapped\n // in a try/catch because reasoner I/O (LLM call, peer-profile\n // writes) must never abort the consolidation result. The reasoner\n // itself also defends against partial failure — see profile-reasoner.ts.\n if (this.config.peerProfileReasonerEnabled) {\n try {\n const { runPeerProfileReasoner } = await import(\"./peers/index.js\");\n const llm = new FallbackLlmClient(this.config.gatewayConfig);\n const peerResult = await runPeerProfileReasoner({\n memoryDir: targetStorage.dir,\n enabled: true,\n llm,\n model: this.config.peerProfileReasonerModel,\n minInteractions: this.config.peerProfileReasonerMinInteractions,\n maxFieldsPerRun: this.config.peerProfileReasonerMaxFieldsPerRun,\n log: {\n debug: (msg) => log.debug(msg),\n info: (msg) => log.info(msg),\n warn: (msg) => log.warn(msg),\n },\n });\n log.info(\n `[peer-profile-reasoner] complete: peers=${peerResult.peersConsidered}, processed=${peerResult.peersProcessed}, fields=${peerResult.fieldsApplied}`,\n );\n } catch (err) {\n log.warn(\n `[peer-profile-reasoner] post-consolidation hook failed (non-fatal): ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n }\n\n return result;\n }\n\n async waitForExtractionIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.queueProcessing || this.extractionQueue.length > 0) {\n if (Date.now() - started > timeoutMs) {\n log.warn(`waitForExtractionIdle timed out after ${timeoutMs}ms`);\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return true;\n }\n\n async waitForConsolidationIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.consolidationInFlight) {\n if (Date.now() - started > timeoutMs) {\n log.warn(`waitForConsolidationIdle timed out after ${timeoutMs}ms`);\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return true;\n }\n\n async getStorage(namespace?: string): Promise<StorageManager> {\n const ns =\n namespace && namespace.length > 0\n ? namespace\n : this.config.defaultNamespace;\n return this.storageRouter.storageFor(ns);\n }\n\n async processEntitySynthesisQueue(\n namespace?: string,\n maxEntities: number = 5,\n ): Promise<number> {\n if (\n !this.config.entitySummaryEnabled\n || maxEntities <= 0\n || this.config.entitySynthesisMaxTokens <= 0\n ) return 0;\n const storage = await this.getStorage(namespace);\n const queued = await storage.refreshEntitySynthesisQueue();\n let processed = 0;\n let attempted = 0;\n\n for (const entityName of queued) {\n if (attempted >= maxEntities) break;\n attempted += 1;\n try {\n const raw = await storage.readEntity(entityName);\n if (!raw) continue;\n const entity = parseEntityFile(raw, this.config.entitySchemas);\n const previousSynthesis = entity.synthesis || entity.summary || \"\";\n const sortedTimelineEntries = entity.timeline\n .slice()\n .sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));\n const newerTimelineEntries = sortedTimelineEntries.filter(\n (entry) =>\n !entity.synthesisUpdatedAt\n || compareEntityTimestamps(entry.timestamp, entity.synthesisUpdatedAt) > 0,\n );\n const appendedTimelineEntries = entity.synthesisTimelineCount === undefined\n ? []\n : entity.timeline.slice(Math.max(0, entity.synthesisTimelineCount));\n const structuredEvidenceEntries = flattenStructuredSectionEvidence(entity.structuredSections);\n const structuredEvidenceCount = structuredEvidenceEntries.length;\n const structuredEvidenceDigest = fingerprintEntityStructuredFacts(entity);\n const structuredEvidenceDrifted = structuredEvidenceDigest !== (entity.synthesisStructuredFactDigest?.trim() || undefined);\n const appendedStructuredEvidenceEntries = entity.synthesisStructuredFactCount === undefined\n || structuredEvidenceDrifted\n ? structuredEvidenceEntries\n : structuredEvidenceEntries.slice(Math.max(0, entity.synthesisStructuredFactCount));\n const candidateEvidenceEntries = [\n ...newerTimelineEntries,\n ...appendedTimelineEntries,\n ...appendedStructuredEvidenceEntries,\n ]\n .slice()\n .sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));\n const dedupedEvidenceEntries = dedupeEntitySynthesisEvidenceEntries(\n candidateEvidenceEntries.length > 0\n ? candidateEvidenceEntries\n : [...sortedTimelineEntries, ...structuredEvidenceEntries],\n );\n const chronologicalEvidenceEntries = dedupedEvidenceEntries\n .slice()\n .sort((left, right) => compareEntityTimestamps(left.timestamp, right.timestamp));\n if (chronologicalEvidenceEntries.length === 0) continue;\n const latestEvidenceTimestamp = chronologicalEvidenceEntries\n .slice()\n .reverse()\n .map((entry) => entry.timestamp?.trim() || undefined)\n .find((timestamp) => Boolean(timestamp));\n const previousSynthesisUpdatedAt = entity.synthesisUpdatedAt?.trim() || undefined;\n const nextSynthesisUpdatedAt = compareEntityTimestamps(\n latestEvidenceTimestamp,\n previousSynthesisUpdatedAt,\n ) >= 0\n ? latestEvidenceTimestamp\n : previousSynthesisUpdatedAt;\n const evidenceBatches: typeof chronologicalEvidenceEntries[] = [];\n for (let index = 0; index < chronologicalEvidenceEntries.length; index += 8) {\n evidenceBatches.push(chronologicalEvidenceEntries.slice(index, index + 8));\n }\n\n let nextSynthesis = previousSynthesis;\n let batchFailed = false;\n for (const evidenceEntries of evidenceBatches) {\n const evidenceText = evidenceEntries\n .map((entry) => {\n const sectionTitle = entry.source?.startsWith(\"section:\")\n ? entry.source.slice(\"section:\".length)\n : \"\";\n const metadata = [\n `timestamp=${entry.timestamp}`,\n sectionTitle ? `section=${sectionTitle}` : entry.source ? `source=${entry.source}` : \"\",\n entry.sessionKey ? `session=${entry.sessionKey}` : \"\",\n entry.principal ? `principal=${entry.principal}` : \"\",\n ]\n .filter(Boolean)\n .join(\", \");\n return `- ${metadata}: ${entry.text}`;\n })\n .join(\"\\n\");\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content:\n \"Rewrite the entity synthesis as compact current truth. Preserve uncertainty when evidence conflicts. Return plain text only.\",\n },\n {\n role: \"user\",\n content: [\n `Entity: ${entity.name} (${entity.type})`,\n nextSynthesis ? `Previous synthesis:\\n${nextSynthesis}` : \"Previous synthesis: none\",\n `New evidence:\\n${evidenceText}`,\n ].join(\"\\n\\n\"),\n },\n ],\n {\n temperature: 0.2,\n maxTokens: this.config.entitySynthesisMaxTokens,\n operation: \"entity_summary\",\n priority: \"background\",\n },\n );\n const synthesis = response?.content?.trim().replace(/^[\"']|[\"']$/g, \"\");\n const maxSynthesisChars = Math.max(2_000, this.config.entitySynthesisMaxTokens * 8);\n if (!synthesis || synthesis.length < 10 || synthesis.length > maxSynthesisChars) {\n batchFailed = true;\n break;\n }\n nextSynthesis = synthesis;\n }\n if (batchFailed || nextSynthesis.length === 0) continue;\n const latestRaw = await storage.readEntity(entityName);\n if (!latestRaw) continue;\n const latestEntity = parseEntityFile(latestRaw, this.config.entitySchemas);\n if (\n fingerprintEntitySynthesisEvidence(latestEntity)\n !== fingerprintEntitySynthesisEvidence(entity)\n ) {\n continue;\n }\n await storage.updateEntitySynthesis(entityName, nextSynthesis, {\n entityUpdatedAt: new Date().toISOString(),\n synthesisStructuredFactDigest: structuredEvidenceDigest,\n synthesisStructuredFactCount: structuredEvidenceCount,\n synthesisTimelineCount: entity.timeline.length,\n updatedAt: nextSynthesisUpdatedAt,\n });\n processed += 1;\n } catch (err) {\n log.debug(`entity synthesis refresh failed for ${entityName}: ${err}`);\n }\n }\n\n return processed;\n }\n\n async generateDaySummary(\n memories: string | MemoryFile[],\n ): Promise<DaySummaryResult | null> {\n if (this.initPromise) {\n let initGateTimeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n this.initPromise.catch(() => undefined),\n new Promise((resolve) => {\n initGateTimeoutHandle = setTimeout(\n resolve,\n this.config.initGateTimeoutMs,\n );\n }),\n ]);\n } finally {\n if (initGateTimeoutHandle) clearTimeout(initGateTimeoutHandle);\n }\n }\n return this.extraction.generateDaySummary(memories);\n }\n\n /**\n * Auto-gather today's facts and hourly summaries from storage, then generate a day summary.\n * Returns null if no facts are found for today.\n */\n async generateDaySummaryAuto(\n namespace?: string,\n ): Promise<DaySummaryResult | null> {\n const gathered = await this.gatherTodayFacts(namespace);\n if (!gathered || !gathered.trim()) {\n log.warn(\"generateDaySummaryAuto: no facts found for today, skipping\");\n return null;\n }\n return this.generateDaySummary(gathered);\n }\n\n /**\n * Read today's facts and hourly summaries from storage, returning them\n * as a formatted string suitable for generateDaySummary().\n */\n async gatherTodayFacts(namespace?: string): Promise<string> {\n const ns =\n namespace && namespace.length > 0\n ? namespace\n : this.config.defaultNamespace;\n const storage = await this.storageRouter.storageFor(ns);\n // Facts are stored under UTC dates, but a local calendar day can span\n // two UTC dates (e.g. 23:47 local in UTC-6 is 05:47 UTC the next day). To capture\n // all facts for the local day, read from both the current UTC date and\n // yesterday's UTC date (which covers the local day's morning hours).\n const now = new Date();\n const utcToday = now.toISOString().slice(0, 10);\n const yesterday = new Date(now.getTime() - 86_400_000)\n .toISOString()\n .slice(0, 10);\n const datesToScan = [yesterday, utcToday].filter(\n (v, i, a) => a.indexOf(v) === i,\n );\n const factsBaseDir = path.join(storage.dir, \"facts\");\n const MAX_CHARS = 100_000;\n\n // --- Read fact files from each date directory ---\n const facts: MemoryFile[] = [];\n for (const date of datesToScan) {\n const factsDir = path.join(factsBaseDir, date);\n try {\n const entries = await readdir(factsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.name.endsWith(\".md\")) continue;\n const fullPath = path.join(factsDir, entry.name);\n try {\n const raw = await readFile(fullPath, \"utf-8\");\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!fmMatch) continue;\n const fmBlock = fmMatch[1];\n const content = fmMatch[2].trim();\n const fm: Record<string, string> = {};\n for (const line of fmBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n fm[line.slice(0, colonIdx).trim()] = line\n .slice(colonIdx + 1)\n .trim();\n }\n facts.push({\n path: fullPath,\n frontmatter: {\n id: fm.id || path.basename(entry.name, \".md\"),\n category: (fm.category as any) || \"fact\",\n created: fm.created || \"unknown\",\n updated: fm.updated || fm.created || \"unknown\",\n source: fm.source || \"unknown\",\n confidence: parseFloat(fm.confidence || \"0.8\"),\n confidenceTier: (fm.confidenceTier as any) || \"implied\",\n tags: [],\n },\n content,\n });\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Directory doesn't exist — no facts for this date\n }\n }\n\n // Sort facts by created timestamp (most recent last) so truncation keeps newest\n facts.sort((a, b) =>\n a.frontmatter.created < b.frontmatter.created ? -1 : 1,\n );\n\n // --- Read hourly summaries for the scanned dates ---\n const hourlySummaries: string[] = [];\n const hourlyBaseDir = path.join(storage.dir, \"summaries\", \"hourly\");\n try {\n const sessionKeys = await readdir(hourlyBaseDir, { withFileTypes: true });\n for (const sk of sessionKeys) {\n if (!sk.isDirectory()) continue;\n for (const date of datesToScan) {\n const summaryFile = path.join(hourlyBaseDir, sk.name, `${date}.md`);\n try {\n const raw = await readFile(summaryFile, \"utf-8\");\n if (raw.trim().length > 0) {\n hourlySummaries.push(raw.trim());\n }\n } catch {\n // No summary file for this session/date\n }\n }\n }\n } catch {\n // No hourly summaries directory\n }\n\n // --- Format and truncate ---\n let formatted = formatDaySummaryMemories(facts);\n if (hourlySummaries.length > 0) {\n formatted +=\n \"\\n\\n---\\n## Hourly Summaries\\n\\n\" +\n hourlySummaries.join(\"\\n\\n---\\n\\n\");\n }\n\n // Truncate intelligently if over budget: drop oldest facts first\n if (formatted.length > MAX_CHARS) {\n // Re-build with fewer facts, keeping most recent\n while (facts.length > 1 && formatted.length > MAX_CHARS) {\n facts.shift(); // drop oldest\n formatted = formatDaySummaryMemories(facts);\n if (hourlySummaries.length > 0) {\n formatted +=\n \"\\n\\n---\\n## Hourly Summaries\\n\\n\" +\n hourlySummaries.join(\"\\n\\n---\\n\\n\");\n }\n }\n // If still over, hard truncate\n if (formatted.length > MAX_CHARS) {\n formatted = formatted.slice(0, MAX_CHARS);\n }\n }\n\n log.info(\n `gatherTodayFacts: collected ${facts.length} facts, ${hourlySummaries.length} hourly summaries (${formatted.length} chars)`,\n );\n\n return formatted;\n }\n\n previewMemoryActionEvent(\n event: Omit<MemoryActionEvent, \"timestamp\"> & { timestamp?: string },\n ): MemoryActionEvent {\n const namespace =\n typeof event.namespace === \"string\" && event.namespace.length > 0\n ? event.namespace\n : this.config.defaultNamespace;\n const eligibility = parseMemoryActionEligibilityContext(\n event.policyEligibility,\n );\n const policy = evaluateMemoryActionPolicy({\n action: event.action,\n eligibility,\n options: {\n actionsEnabled: this.config.contextCompressionActionsEnabled,\n maxCompressionTokensPerHour: this.config.maxCompressionTokensPerHour,\n },\n });\n const dryRun = event.dryRun === true;\n\n const normalizedOutcome = dryRun\n ? event.outcome === \"failed\"\n ? \"failed\"\n : \"skipped\"\n : policy.decision === \"allow\"\n ? event.outcome\n : event.outcome === \"failed\"\n ? \"failed\"\n : \"skipped\";\n const sourceSessionKey =\n typeof event.sourceSessionKey === \"string\" &&\n event.sourceSessionKey.length > 0\n ? event.sourceSessionKey\n : typeof event.sessionKey === \"string\" && event.sessionKey.length > 0\n ? event.sessionKey\n : undefined;\n const outputMemoryIds = Array.isArray(event.outputMemoryIds)\n ? Array.from(\n new Set(\n event.outputMemoryIds.filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n ),\n ),\n )\n : [];\n\n const reasonParts = [\n event.reason,\n `policy:${policy.decision}`,\n policy.rationale,\n ].filter(\n (part): part is string => typeof part === \"string\" && part.length > 0,\n );\n\n return {\n ...event,\n schemaVersion: event.schemaVersion ?? 1,\n actionId:\n typeof event.actionId === \"string\" && event.actionId.length > 0\n ? event.actionId\n : `memact-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n outcome: normalizedOutcome,\n status:\n event.status ??\n (dryRun && policy.decision === \"allow\" && event.outcome !== \"failed\"\n ? \"validated\"\n : normalizedOutcome === \"applied\"\n ? \"applied\"\n : \"rejected\"),\n actor:\n typeof event.actor === \"string\" && event.actor.length > 0\n ? event.actor\n : \"engram\",\n subsystem:\n typeof event.subsystem === \"string\" && event.subsystem.length > 0\n ? event.subsystem\n : \"memory_action\",\n reason: reasonParts.join(\" | \"),\n namespace,\n sessionKey: sourceSessionKey ?? event.sessionKey,\n sourceSessionKey,\n inputSummary:\n typeof event.inputSummary === \"string\" && event.inputSummary.length > 0\n ? event.inputSummary\n : undefined,\n outputMemoryIds,\n dryRun,\n policyVersion:\n typeof event.policyVersion === \"string\" &&\n event.policyVersion.length > 0\n ? event.policyVersion\n : \"memory-action-policy.v1\",\n timestamp:\n typeof event.timestamp === \"string\" && event.timestamp.length > 0\n ? event.timestamp\n : new Date().toISOString(),\n policyDecision: policy.decision,\n policyRationale: policy.rationale,\n policyEligibility: eligibility,\n };\n }\n\n async appendMemoryActionEvent(\n event: Omit<MemoryActionEvent, \"timestamp\"> & { timestamp?: string },\n ): Promise<boolean> {\n try {\n const toWrite = this.previewMemoryActionEvent(event);\n const storage = await this.getStorage(toWrite.namespace);\n await storage.appendMemoryActionEvents([toWrite]);\n return true;\n } catch (err) {\n log.warn(`appendMemoryActionEvent failed (non-fatal): ${err}`);\n return false;\n }\n }\n\n async getLastGraphRecallSnapshot(\n namespace?: string,\n ): Promise<GraphRecallSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(\n storage.dir,\n \"state\",\n \"last_graph_recall.json\",\n );\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<GraphRecallSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n mode: typeof parsed.mode === \"string\" ? parsed.mode : \"full\",\n queryHash: typeof parsed.queryHash === \"string\" ? parsed.queryHash : \"\",\n queryLength:\n typeof parsed.queryLength === \"number\" ? parsed.queryLength : 0,\n namespaces: Array.isArray(parsed.namespaces)\n ? parsed.namespaces.filter((v): v is string => typeof v === \"string\")\n : [],\n seedCount: typeof parsed.seedCount === \"number\" ? parsed.seedCount : 0,\n expandedCount:\n typeof parsed.expandedCount === \"number\" ? parsed.expandedCount : 0,\n seeds: Array.isArray(parsed.seeds)\n ? parsed.seeds.filter((v): v is string => typeof v === \"string\")\n : [],\n expanded: clampGraphRecallExpandedEntries(parsed.expanded, 64),\n status:\n parsed.status === \"completed\" ||\n parsed.status === \"skipped\" ||\n parsed.status === \"aborted\"\n ? parsed.status\n : undefined,\n reason: typeof parsed.reason === \"string\" ? parsed.reason : undefined,\n shadowMode: parsed.shadowMode === true,\n queryIntent: parseMemoryIntentSnapshot(parsed.queryIntent),\n seedResults: parseGraphRecallRankedResults(parsed.seedResults),\n finalResults: parseGraphRecallRankedResults(parsed.finalResults),\n shadowComparison:\n parsed.shadowComparison && typeof parsed.shadowComparison === \"object\"\n ? {\n baselineCount:\n typeof parsed.shadowComparison.baselineCount === \"number\"\n ? parsed.shadowComparison.baselineCount\n : 0,\n graphCount:\n typeof parsed.shadowComparison.graphCount === \"number\"\n ? parsed.shadowComparison.graphCount\n : 0,\n overlapCount:\n typeof parsed.shadowComparison.overlapCount === \"number\"\n ? parsed.shadowComparison.overlapCount\n : 0,\n overlapRatio:\n typeof parsed.shadowComparison.overlapRatio === \"number\"\n ? parsed.shadowComparison.overlapRatio\n : 0,\n averageOverlapDelta:\n typeof parsed.shadowComparison.averageOverlapDelta ===\n \"number\"\n ? parsed.shadowComparison.averageOverlapDelta\n : 0,\n }\n : undefined,\n };\n } catch {\n return null;\n }\n }\n\n async getLastIntentSnapshot(\n namespace?: string,\n ): Promise<IntentDebugSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(storage.dir, \"state\", \"last_intent.json\");\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<IntentDebugSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n const graphDecision =\n parsed.graphDecision && typeof parsed.graphDecision === \"object\"\n ? parsed.graphDecision\n : undefined;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n promptHash:\n typeof parsed.promptHash === \"string\" ? parsed.promptHash : \"\",\n promptLength:\n typeof parsed.promptLength === \"number\" ? parsed.promptLength : 0,\n retrievalQueryHash:\n typeof parsed.retrievalQueryHash === \"string\"\n ? parsed.retrievalQueryHash\n : \"\",\n retrievalQueryLength:\n typeof parsed.retrievalQueryLength === \"number\"\n ? parsed.retrievalQueryLength\n : 0,\n plannerEnabled: parsed.plannerEnabled !== false,\n plannedMode:\n parsed.plannedMode === \"no_recall\" ||\n parsed.plannedMode === \"minimal\" ||\n parsed.plannedMode === \"full\" ||\n parsed.plannedMode === \"graph_mode\"\n ? parsed.plannedMode\n : \"full\",\n effectiveMode:\n parsed.effectiveMode === \"no_recall\" ||\n parsed.effectiveMode === \"minimal\" ||\n parsed.effectiveMode === \"full\" ||\n parsed.effectiveMode === \"graph_mode\"\n ? parsed.effectiveMode\n : \"full\",\n recallResultLimit:\n typeof parsed.recallResultLimit === \"number\"\n ? parsed.recallResultLimit\n : 0,\n queryIntent: parseMemoryIntentSnapshot(parsed.queryIntent),\n graphExpandedIntentDetected:\n parsed.graphExpandedIntentDetected === true,\n graphDecision: {\n status:\n graphDecision?.status === \"skipped\" ||\n graphDecision?.status === \"completed\" ||\n graphDecision?.status === \"aborted\"\n ? graphDecision.status\n : \"not_requested\",\n reason:\n typeof graphDecision?.reason === \"string\"\n ? graphDecision.reason\n : undefined,\n shadowMode: graphDecision?.shadowMode === true,\n qmdAvailable: graphDecision?.qmdAvailable !== false,\n graphRecallEnabled: graphDecision?.graphRecallEnabled !== false,\n multiGraphMemoryEnabled:\n graphDecision?.multiGraphMemoryEnabled !== false,\n },\n };\n } catch {\n return null;\n }\n }\n\n async getLastQmdRecallSnapshot(\n namespace?: string,\n ): Promise<QmdRecallSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(\n storage.dir,\n \"state\",\n \"last_qmd_recall.json\",\n );\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<QmdRecallSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n queryHash: typeof parsed.queryHash === \"string\" ? parsed.queryHash : \"\",\n queryLength:\n typeof parsed.queryLength === \"number\" ? parsed.queryLength : 0,\n collection:\n typeof parsed.collection === \"string\" ? parsed.collection : undefined,\n namespaces: Array.isArray(parsed.namespaces)\n ? parsed.namespaces.filter(\n (value): value is string => typeof value === \"string\",\n )\n : [],\n fetchLimit:\n typeof parsed.fetchLimit === \"number\" ? parsed.fetchLimit : 0,\n primaryResultCount:\n typeof parsed.primaryResultCount === \"number\"\n ? parsed.primaryResultCount\n : 0,\n hybridResultCount:\n typeof parsed.hybridResultCount === \"number\"\n ? parsed.hybridResultCount\n : 0,\n queryAwareSeedCount:\n typeof parsed.queryAwareSeedCount === \"number\"\n ? parsed.queryAwareSeedCount\n : 0,\n resultCount:\n typeof parsed.resultCount === \"number\" ? parsed.resultCount : 0,\n intentHint:\n typeof parsed.intentHint === \"string\" ? parsed.intentHint : undefined,\n explainEnabled: parsed.explainEnabled === true,\n hybridTopUpUsed: parsed.hybridTopUpUsed === true,\n hybridTopUpSkippedReason:\n typeof parsed.hybridTopUpSkippedReason === \"string\"\n ? parsed.hybridTopUpSkippedReason\n : undefined,\n results: parseQmdRecallResults(parsed.results),\n };\n } catch {\n return null;\n }\n }\n\n async explainLastGraphRecall(options?: {\n namespace?: string;\n maxExpanded?: number;\n }): Promise<string> {\n const snapshot = await this.getLastGraphRecallSnapshot(options?.namespace);\n if (!snapshot) return \"No graph-recall snapshot found yet.\";\n const maxExpanded = Math.max(1, Math.min(50, options?.maxExpanded ?? 10));\n const expanded = snapshot.expanded.slice(0, maxExpanded);\n const seedResults = (snapshot.seedResults ?? []).slice(0, maxExpanded);\n const finalResults = (snapshot.finalResults ?? []).slice(0, maxExpanded);\n const queryIntent = snapshot.queryIntent ?? {\n goal: \"unknown\",\n actionType: \"unknown\",\n entityTypes: [],\n };\n return [\n \"## Last Graph Recall\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Mode: ${snapshot.mode}`,\n `Status: ${snapshot.status ?? \"completed\"}${snapshot.shadowMode ? \" (shadow)\" : \"\"}`,\n `Reason: ${snapshot.reason ?? \"n/a\"}`,\n `Query hash: ${snapshot.queryHash || \"unknown\"} (len=${snapshot.queryLength})`,\n `Query intent: goal=${queryIntent.goal}, action=${queryIntent.actionType}, entityTypes=${queryIntent.entityTypes.length > 0 ? queryIntent.entityTypes.join(\", \") : \"none\"}`,\n `Namespaces: ${snapshot.namespaces.length > 0 ? snapshot.namespaces.join(\", \") : \"none\"}`,\n `Seed results (${snapshot.seedResults?.length ?? 0}, showing ${seedResults.length}):`,\n ...seedResults.map(\n (entry) =>\n `- ${entry.path} (score=${entry.score.toFixed(3)}, sources=${entry.sourceLabels.join(\",\") || \"baseline\"})`,\n ),\n `Seed paths (${snapshot.seedCount}):`,\n ...snapshot.seeds.map((p) => `- ${p}`),\n `Expanded paths (${snapshot.expandedCount}, showing ${expanded.length}):`,\n ...expanded.map((e) => {\n // Issue #681 PR 3/3 — surface per-edge confidence in the\n // graph-explain document. Legacy snapshots without\n // `edgeConfidence` render as `conf=n/a` so older payloads\n // remain readable.\n const confLabel =\n typeof e.edgeConfidence === \"number\" && Number.isFinite(e.edgeConfidence)\n ? e.edgeConfidence.toFixed(2)\n : \"n/a\";\n return `- ${e.path} (score=${e.score.toFixed(3)}, ns=${e.namespace}, seed=${e.seed || \"unknown\"}, hop=${e.hopDepth}, w=${e.decayedWeight.toFixed(3)}, type=${e.graphType}, conf=${confLabel})`;\n }),\n `Final ranked results (${snapshot.finalResults?.length ?? 0}, showing ${finalResults.length}):`,\n ...finalResults.map(\n (entry) =>\n `- ${entry.path} (score=${entry.score.toFixed(3)}, sources=${entry.sourceLabels.join(\",\") || \"baseline\"})`,\n ),\n ...(snapshot.shadowComparison\n ? [\n `Shadow comparison: baseline=${snapshot.shadowComparison.baselineCount}, graph=${snapshot.shadowComparison.graphCount}, overlap=${snapshot.shadowComparison.overlapCount} (${snapshot.shadowComparison.overlapRatio.toFixed(2)}), avgDelta=${snapshot.shadowComparison.averageOverlapDelta.toFixed(3)}`,\n ]\n : []),\n ].join(\"\\n\");\n }\n\n async explainLastIntent(options?: { namespace?: string }): Promise<string> {\n const snapshot = await this.getLastIntentSnapshot(options?.namespace);\n if (!snapshot) return \"No intent-debug snapshot found yet.\";\n return [\n \"## Last Intent Debug\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Prompt hash: ${snapshot.promptHash || \"unknown\"} (len=${snapshot.promptLength})`,\n `Retrieval query hash: ${snapshot.retrievalQueryHash || \"unknown\"} (len=${snapshot.retrievalQueryLength})`,\n `Planner enabled: ${snapshot.plannerEnabled ? \"yes\" : \"no\"}`,\n `Planned mode: ${snapshot.plannedMode}`,\n `Effective mode: ${snapshot.effectiveMode}`,\n `Recall result limit: ${snapshot.recallResultLimit}`,\n `Query intent: goal=${snapshot.queryIntent.goal}, action=${snapshot.queryIntent.actionType}, entityTypes=${snapshot.queryIntent.entityTypes.length > 0 ? snapshot.queryIntent.entityTypes.join(\", \") : \"none\"}`,\n `Broad graph intent: ${snapshot.graphExpandedIntentDetected ? \"yes\" : \"no\"}`,\n `Graph decision: status=${snapshot.graphDecision.status}, reason=${snapshot.graphDecision.reason ?? \"n/a\"}, shadow=${snapshot.graphDecision.shadowMode ? \"yes\" : \"no\"}, qmdAvailable=${snapshot.graphDecision.qmdAvailable ? \"yes\" : \"no\"}, graphRecallEnabled=${snapshot.graphDecision.graphRecallEnabled ? \"yes\" : \"no\"}, multiGraphMemoryEnabled=${snapshot.graphDecision.multiGraphMemoryEnabled ? \"yes\" : \"no\"}`,\n ].join(\"\\n\");\n }\n\n async explainLastQmdRecall(options?: {\n namespace?: string;\n maxResults?: number;\n }): Promise<string> {\n const snapshot = await this.getLastQmdRecallSnapshot(options?.namespace);\n if (!snapshot) return \"No QMD recall snapshot found yet.\";\n const maxResults = Math.max(1, Math.min(25, options?.maxResults ?? 10));\n const shown = snapshot.results.slice(0, maxResults);\n return [\n \"## Last QMD Recall\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Query hash: ${snapshot.queryHash || \"unknown\"} (len=${snapshot.queryLength})`,\n `Collection: ${snapshot.collection ?? \"default\"}`,\n `Namespaces: ${snapshot.namespaces.length > 0 ? snapshot.namespaces.join(\", \") : \"none\"}`,\n `Fetch limit: ${snapshot.fetchLimit}`,\n `Primary results: ${snapshot.primaryResultCount}`,\n `Hybrid top-up results: ${snapshot.hybridResultCount}`,\n `Query-aware seeds: ${snapshot.queryAwareSeedCount}`,\n `Final results: ${snapshot.resultCount}`,\n `Intent hint: ${snapshot.intentHint ?? \"none\"}`,\n `Explain enabled: ${snapshot.explainEnabled ? \"yes\" : \"no\"}`,\n `Hybrid top-up used: ${snapshot.hybridTopUpUsed ? \"yes\" : \"no\"}`,\n `Hybrid top-up skipped reason: ${snapshot.hybridTopUpSkippedReason ?? \"n/a\"}`,\n `Top results (${shown.length}):`,\n ...shown.map((result) => {\n const explainParts = [\n typeof result.explain?.blendedScore === \"number\"\n ? `blended=${result.explain.blendedScore.toFixed(3)}`\n : null,\n typeof result.explain?.rerankScore === \"number\"\n ? `rerank=${result.explain.rerankScore.toFixed(3)}`\n : null,\n typeof result.explain?.rrf === \"number\"\n ? `rrf=${result.explain.rrf.toFixed(3)}`\n : null,\n ].filter((entry): entry is string => Boolean(entry));\n const explainText =\n explainParts.length > 0 ? `, explain=${explainParts.join(\"/\")}` : \"\";\n return `- ${result.path} (score=${result.score.toFixed(3)}, transport=${result.transport ?? \"unknown\"}${explainText})`;\n }),\n ].join(\"\\n\");\n }\n\n private async searchConversationRecallResults(\n retrievalQuery: string,\n topK: number,\n ): Promise<Array<{ path: string; snippet: string; score: number }>> {\n if (this.conversationIndexBackend) {\n return this.conversationIndexBackend.search(retrievalQuery, topK);\n }\n return [];\n }\n\n private formatConversationRecallSection(\n results: Array<{ path: string; snippet: string; score: number }>,\n maxChars: number,\n ): string | null {\n if (!Array.isArray(results) || results.length === 0) return null;\n const lines: string[] = [\"## Semantic Recall (Past Conversations)\", \"\"];\n let used = 0;\n for (const r of results) {\n if (!r?.snippet) continue;\n const chunk =\n `### ${r.path}\\n` +\n `Score: ${r.score.toFixed(3)}\\n\\n` +\n `${r.snippet.trim()}\\n`;\n if (used + chunk.length > maxChars) break;\n lines.push(chunk);\n used += chunk.length;\n }\n return used > 0 ? lines.join(\"\\n\") : null;\n }\n\n private async countConversationChunkDocs(dir: string): Promise<number> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n let total = 0;\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n total += await this.countConversationChunkDocs(fullPath);\n continue;\n }\n if (entry.isFile() && entry.name.endsWith(\".md\")) {\n total += 1;\n }\n }\n return total;\n } catch {\n return 0;\n }\n }\n\n private async buildConversationIndexChunks(\n sessionKey?: string,\n hours: number = 24,\n ): Promise<ReturnType<typeof chunkTranscriptEntries>> {\n const entries = await this.transcript.readRecent(hours, sessionKey);\n const effectiveSessionKey = sessionKey ?? \"all-sessions\";\n return chunkTranscriptEntries(effectiveSessionKey, entries, {\n maxChars: this.config.conversationRecallMaxChars * 2,\n maxTurns: Math.max(10, this.config.hourlySummariesMaxTurnsPerRun),\n });\n }\n\n async getConversationIndexHealth(): Promise<{\n enabled: boolean;\n backend: \"qmd\" | \"faiss\";\n status: \"ok\" | \"degraded\" | \"disabled\";\n chunkDocCount: number;\n lastUpdateAt: string | null;\n qmdAvailable?: boolean;\n faiss?: {\n ok: boolean;\n status: \"ok\" | \"degraded\" | \"error\";\n indexPath: string;\n message?: string;\n manifest?: {\n version: number;\n modelId: string;\n normalizedModelId: string;\n dimension: number;\n chunkCount: number;\n updatedAt: string;\n lastSuccessfulRebuildAt: string;\n };\n };\n }> {\n const chunkDocCount = await this.countConversationChunkDocs(\n this.conversationIndexDir,\n );\n const lastUpdateAtMs = Math.max(\n 0,\n ...this.conversationIndexLastUpdateAtMs.values(),\n );\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!this.config.conversationIndexEnabled) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n chunkDocCount,\n lastUpdateAt,\n };\n }\n const backendHealth = this.conversationIndexBackend\n ? await this.conversationIndexBackend.health()\n : {\n backend: this.config.conversationIndexBackend,\n status: \"degraded\" as const,\n };\n return {\n enabled: true,\n chunkDocCount,\n lastUpdateAt,\n ...backendHealth,\n };\n }\n\n async inspectConversationIndex(): Promise<\n ConversationIndexBackendInspection & {\n enabled: boolean;\n chunkDocCount: number;\n lastUpdateAt: string | null;\n }\n > {\n const chunkDocCount = await this.countConversationChunkDocs(\n this.conversationIndexDir,\n );\n const lastUpdateAtMs = Math.max(\n 0,\n ...this.conversationIndexLastUpdateAtMs.values(),\n );\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!this.config.conversationIndexEnabled) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n available: false,\n indexPath: this.conversationIndexDir,\n supportsIncrementalUpdate: true,\n message: \"Conversation index disabled by config\",\n metadata: {\n chunkCount: chunkDocCount,\n },\n chunkDocCount,\n lastUpdateAt,\n };\n }\n\n const inspection = this.conversationIndexBackend\n ? await this.conversationIndexBackend.inspect()\n : {\n backend: this.config.conversationIndexBackend,\n status: \"degraded\" as const,\n available: false,\n indexPath: this.conversationIndexDir,\n supportsIncrementalUpdate: true,\n message: \"Conversation index backend unavailable\",\n metadata: {\n chunkCount: chunkDocCount,\n },\n };\n\n return {\n enabled: true,\n chunkDocCount,\n lastUpdateAt,\n ...inspection,\n };\n }\n\n async getRecoverySummary(sessionKey?: string): Promise<{\n generatedAt: string;\n sessionKey?: string;\n healthy: boolean;\n issueCount: number;\n incompleteTurns: number;\n brokenChains: number;\n checkpointHealthy: boolean;\n }> {\n return this.transcript.getRecoverySummary(sessionKey);\n }\n\n async updateConversationIndex(\n sessionKey: string,\n hours: number = 24,\n opts?: { embed?: boolean; enforceMinInterval?: boolean },\n ): Promise<{\n chunks: number;\n skipped: boolean;\n reason?: string;\n retryAfterMs?: number;\n embedded?: boolean;\n }> {\n if (!this.config.conversationIndexEnabled) {\n return { chunks: 0, skipped: true, reason: \"disabled\", embedded: false };\n }\n const enforceMinInterval = opts?.enforceMinInterval !== false;\n if (enforceMinInterval) {\n const minIntervalMs = Math.max(\n 0,\n this.config.conversationIndexMinUpdateIntervalMs,\n );\n const now = Date.now();\n const last = this.conversationIndexLastUpdateAtMs.get(sessionKey) ?? 0;\n const elapsed = now - last;\n if (minIntervalMs > 0 && elapsed < minIntervalMs) {\n return {\n chunks: 0,\n skipped: true,\n reason: \"min_interval\",\n retryAfterMs: minIntervalMs - elapsed,\n embedded: false,\n };\n }\n }\n const chunks = await this.buildConversationIndexChunks(sessionKey, hours);\n await writeConversationChunks(this.conversationIndexDir, chunks);\n await cleanupConversationChunks(\n this.conversationIndexDir,\n this.config.conversationIndexRetentionDays,\n );\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n\n if (this.conversationIndexBackend) {\n const result = await this.conversationIndexBackend.update(chunks, {\n embed: shouldEmbed,\n });\n embedded = result.embedded;\n }\n\n this.conversationIndexLastUpdateAtMs.set(sessionKey, Date.now());\n return { chunks: chunks.length, skipped: false, embedded };\n }\n\n async rebuildConversationIndex(\n sessionKey?: string,\n hours: number = 24,\n opts?: { embed?: boolean },\n ): Promise<{\n chunks: number;\n skipped: boolean;\n reason?: string;\n embedded?: boolean;\n rebuilt?: boolean;\n }> {\n if (!this.config.conversationIndexEnabled) {\n return {\n chunks: 0,\n skipped: true,\n reason: \"disabled\",\n embedded: false,\n rebuilt: false,\n };\n }\n\n const chunks = await this.buildConversationIndexChunks(sessionKey, hours);\n await writeConversationChunks(this.conversationIndexDir, chunks);\n await cleanupConversationChunks(\n this.conversationIndexDir,\n this.config.conversationIndexRetentionDays,\n );\n\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n let rebuilt = false;\n if (this.conversationIndexBackend) {\n const result = await this.conversationIndexBackend.rebuild(chunks, {\n embed: shouldEmbed,\n });\n embedded = result.embedded;\n rebuilt = result.rebuilt;\n }\n\n const stamp = Date.now();\n if (sessionKey) {\n this.conversationIndexLastUpdateAtMs.set(sessionKey, stamp);\n } else {\n this.conversationIndexLastUpdateAtMs.set(\"__rebuild__\", stamp);\n }\n return { chunks: chunks.length, skipped: false, embedded, rebuilt };\n }\n\n /**\n * Validate local LLM model availability and context window compatibility.\n * Warns the user if there's a mismatch.\n */\n private async validateLocalLlmModel(): Promise<void> {\n log.debug(\"Local LLM: validating model configuration\");\n try {\n const modelInfo = await this.localLlm.getLoadedModelInfo();\n if (!modelInfo) {\n log.warn(\n \"Local LLM validation: Could not query model info from server\",\n );\n log.warn(\n \"Local LLM validation: Could not query model info. \" +\n \"Ensure LM Studio/Ollama is running with the model loaded.\",\n );\n return;\n }\n\n // Check for context window mismatch\n const configuredMaxContext = this.config.localLlmMaxContext;\n\n if (modelInfo.contextWindow) {\n log.debug(\n `Local LLM: ${modelInfo.id} loaded with ${modelInfo.contextWindow.toLocaleString()} token context window`,\n );\n\n if (\n configuredMaxContext &&\n configuredMaxContext > modelInfo.contextWindow\n ) {\n log.warn(\n `Local LLM context mismatch: engram configured for ${configuredMaxContext.toLocaleString()} tokens, ` +\n `but ${modelInfo.id} only supports ${modelInfo.contextWindow.toLocaleString()}. ` +\n `Reducing to ${modelInfo.contextWindow.toLocaleString()} to avoid errors.`,\n );\n // Update the config in-memory to match actual capability\n // (This is a temporary fix - user should update their config)\n (this.config as { localLlmMaxContext?: number }).localLlmMaxContext =\n modelInfo.contextWindow;\n }\n } else {\n log.debug(\n `Local LLM: ${modelInfo.id} loaded (context window not reported by server)`,\n );\n\n if (!configuredMaxContext) {\n log.warn(\n \"Local LLM: Server did not report context window. \" +\n \"If you get 'context length exceeded' errors, set localLlmMaxContext in your config. \" +\n \"Common defaults: LM Studio (32K), Ollama (2K-128K depending on model).\",\n );\n }\n }\n } catch (err) {\n log.warn(`Local LLM validation failed: ${err}`);\n }\n }\n\n async recall(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n ): Promise<string> {\n const abortController = new AbortController();\n const onAbort = () => {\n abortController.abort();\n };\n if (options.abortSignal?.aborted) {\n abortController.abort();\n } else {\n options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // Wait for initialization to complete before attempting recall. The timeout\n // is configurable so OpenClaw's per-hook budget and Remnic's internal init\n // gate can stay aligned during cold starts.\n let initGateTimeoutHandle: NodeJS.Timeout | null = null;\n let onInitGateAbort: (() => void) | null = null;\n if (this.initPromise) {\n const gateResult = await Promise.race([\n this.initPromise.then(() => \"ok\" as const),\n new Promise<\"timeout\">((resolve) => {\n initGateTimeoutHandle = setTimeout(\n () => resolve(\"timeout\"),\n this.config.initGateTimeoutMs,\n );\n }),\n abortController.signal.aborted\n ? Promise.resolve(\"aborted\" as const)\n : new Promise<\"aborted\">((resolve) => {\n onInitGateAbort = () => resolve(\"aborted\");\n abortController.signal.addEventListener(\n \"abort\",\n onInitGateAbort,\n { once: true },\n );\n }),\n ]);\n if (initGateTimeoutHandle) clearTimeout(initGateTimeoutHandle);\n if (onInitGateAbort)\n abortController.signal.removeEventListener(\"abort\", onInitGateAbort);\n if (gateResult === \"aborted\") {\n this.logRecallFailure(abortRecallError(\"recall aborted before init\"));\n return \"\";\n }\n if (gateResult === \"timeout\") {\n log.warn(\"recall: init gate timed out — proceeding without full init\");\n }\n }\n\n // Secure-store lock gate (issue #690 PR 3/4).\n // If secure-store is enabled but the keyring holds no key for this\n // memory directory, reject recall with a clear human-readable error\n // rather than surfacing a cryptic SecureStoreLockedError from deep\n // inside the storage layer.\n if (this.config.secureStoreEnabled && !this.storage.isSecureStoreUnlocked()) {\n const lockedMsg =\n \"[secure-store locked] Memory store is encrypted and locked. \" +\n \"Run `remnic secure-store unlock` then restart the daemon to decrypt.\";\n log.warn(\"recall blocked: secure-store is locked\");\n return lockedMsg;\n }\n\n // Keep outer recall timeout above worst-case serialized hybrid search:\n // QMD subprocess BM25 (30s) + vector (30s) can consume ~60s under contention.\n try {\n const recallPromise = this.recallInternal(prompt, sessionKey, {\n ...options,\n abortSignal: abortController.signal,\n });\n const RECALL_TIMEOUT_MS = this.config.recallOuterTimeoutMs ?? 75_000;\n if (RECALL_TIMEOUT_MS <= 0) {\n return await recallPromise;\n }\n\n let timeoutHandle: NodeJS.Timeout | null = null;\n const timeoutPromise = new Promise<string>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n abortController.abort();\n reject(new Error(\"recall timeout\"));\n }, RECALL_TIMEOUT_MS);\n });\n\n let recallResult: string;\n try {\n recallResult = await Promise.race([recallPromise, timeoutPromise]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n\n // Observation-mode direct-answer tier (issue #518 slice 3c).\n // Runs after the user's recall already succeeded, fire-and-forget,\n // so annotation latency can never delay the caller's response.\n if (this.config.recallDirectAnswerEnabled && sessionKey) {\n try {\n this.enqueueDirectAnswerObservation(\n prompt,\n sessionKey,\n options.namespace?.trim() || undefined,\n );\n } catch (err) {\n log.debug(`direct-answer observation setup failed: ${err}`);\n }\n }\n\n return recallResult;\n } catch (err) {\n this.logRecallFailure(err);\n // endTrace() is safe here: if no trace is active (disabled or already\n // closed by recallInternal's try/finally), it returns null immediately.\n this.profiler.endTrace();\n return \"\"; // Return empty context on timeout/error\n } finally {\n options.abortSignal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n /**\n * Return the most recent X-ray snapshot captured during a\n * `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).\n * Returns `null` when no such capture has occurred on this\n * orchestrator instance. Returned snapshot is a deep copy so\n * caller mutation cannot tear the stored value.\n */\n getLastXraySnapshot(): RecallXraySnapshot | null {\n if (!this.lastXraySnapshot) return null;\n return structuredClone(this.lastXraySnapshot);\n }\n\n /** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */\n clearLastXraySnapshot(): void {\n this.lastXraySnapshot = null;\n }\n\n /**\n * Await the in-flight observation-mode direct-answer annotation chain.\n * Resolves to true when settled, false on timeout.\n */\n async waitForDirectAnswerObservationIdle(\n timeoutMs: number = 60_000,\n ): Promise<boolean> {\n let timeoutHandle: NodeJS.Timeout | null = null;\n try {\n const timeoutPromise = new Promise<\"timeout\">((resolve) => {\n timeoutHandle = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n const result = await Promise.race([\n this.directAnswerObservationChain.then(() => \"ok\" as const),\n timeoutPromise,\n ]);\n if (result === \"timeout\") {\n log.warn(\n `waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`,\n );\n return false;\n }\n return true;\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n private enqueueDirectAnswerObservation(\n prompt: string,\n sessionKey: string,\n namespaceOverride: string | undefined,\n ): void {\n const expectedSnapshot = this.lastRecall.get(sessionKey);\n if (expectedSnapshot === null) return;\n if (expectedSnapshot.plannerMode === \"no_recall\") return;\n\n const principal = resolvePrincipal(sessionKey, this.config);\n // Coding-agent overlay (issue #569) is applied when the session has a\n // coding context and there is no explicit namespaceOverride — mirrors\n // the main recall path above.\n const observationCodingOverlay =\n namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)\n ? null\n : this.applyCodingRecallOverlay(sessionKey);\n const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);\n const observationCodingSelf = observationCodingOverlay\n ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace)\n : null;\n let observationNamespaces: string[];\n if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {\n observationNamespaces = [namespaceOverride];\n } else if (observationCodingOverlay && observationCodingSelf) {\n // Rule 42 / parity with the main recall path: substitute the self\n // namespace within the principal's recall list rather than\n // replacing the full list. Preserves shared and policy-include\n // namespaces for direct-answer observation queries.\n const base = recallNamespacesForPrincipal(principal, this.config);\n const mapped = base.map((ns) =>\n ns === observationPrincipalSelf ? observationCodingSelf : ns,\n );\n const fallbackNs = observationCodingOverlay.readFallbacks.map((fallback) =>\n combineNamespaces(observationPrincipalSelf, fallback),\n );\n observationNamespaces = Array.from(new Set<string>([...mapped, ...fallbackNs]));\n } else {\n observationNamespaces = recallNamespacesForPrincipal(principal, this.config);\n }\n const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,\n cronRecallNormalizedQueryMaxChars:\n this.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.config.cronConversationRecallMode,\n });\n const observationQuery = observationQueryPolicy.retrievalQuery || prompt;\n const expectedIdentity = {\n writeNonce: expectedSnapshot.writeNonce,\n traceId: expectedSnapshot.traceId,\n recordedAt: expectedSnapshot.recordedAt,\n };\n const previous = this.directAnswerObservationChain;\n this.directAnswerObservationChain = previous\n .catch(() => undefined)\n .then(async () => {\n try {\n await this.annotateDirectAnswerTier(\n observationQuery,\n sessionKey,\n observationNamespaces,\n expectedIdentity,\n undefined,\n );\n } catch (err) {\n log.debug(`direct-answer observation chain error: ${err}`);\n }\n });\n }\n\n private async annotateDirectAnswerTier(\n prompt: string,\n sessionKey: string,\n namespaces: string[],\n expectedIdentity:\n | { writeNonce?: string; traceId?: string; recordedAt?: string }\n | undefined,\n _parentAbortSignal?: AbortSignal,\n ): Promise<void> {\n const tierStart = Date.now();\n try {\n if (namespaces.length === 0) return;\n\n const trustZoneByNsAndRecordId = new Map<\n string,\n \"quarantine\" | \"working\" | \"trusted\"\n >();\n const trustZoneKey = (ns: string, recordId: string) =>\n `${ns}\\u0000${recordId}`;\n const scopedStorages = new Map<\n string,\n Awaited<ReturnType<typeof this.storageRouter.storageFor>>\n >();\n\n for (const ns of namespaces) {\n const storage = await this.storageRouter.storageFor(ns);\n scopedStorages.set(ns, storage);\n const trustZones = await listTrustZoneRecords({\n memoryDir: storage.dir,\n trustZoneStoreDir: this.config.trustZoneStoreDir,\n limit: 200,\n }).catch(() => ({\n allRecords: [] as Array<{\n recordId: string;\n zone: \"quarantine\" | \"working\" | \"trusted\";\n }>,\n }));\n for (const record of trustZones.allRecords ?? []) {\n trustZoneByNsAndRecordId.set(\n trustZoneKey(ns, record.recordId),\n record.zone,\n );\n }\n }\n\n const memoryNamespaceByPath = new Map<string, string>();\n const memoryNamespaceById = new Map<string, string>();\n let candidatesConsidered = 0;\n\n const sources: DirectAnswerSources = {\n taxonomy: DEFAULT_TAXONOMY,\n listCandidateMemories: async (options: { namespace: string; abortSignal?: AbortSignal }) => {\n const targetNs = options.namespace;\n const storage =\n scopedStorages.get(targetNs) ??\n (await this.storageRouter.storageFor(targetNs));\n const all = await storage.readAllMemories();\n const active: MemoryFile[] = [];\n for (const m of all) {\n if ((m.frontmatter.status ?? \"active\") === \"active\") {\n active.push(m);\n memoryNamespaceByPath.set(m.path, targetNs);\n if (m.frontmatter.id) {\n memoryNamespaceById.set(m.frontmatter.id, targetNs);\n }\n }\n }\n candidatesConsidered += active.length;\n return active;\n },\n trustZoneFor: async (memoryId: string) => {\n const ns = memoryNamespaceById.get(memoryId);\n if (!ns) return null;\n return (\n trustZoneByNsAndRecordId.get(\n trustZoneKey(ns, memoryId),\n ) ?? null\n );\n },\n importanceFor: (memory) =>\n typeof memory.frontmatter.importance?.score === \"number\"\n ? memory.frontmatter.importance.score\n : 0,\n };\n\n let result: import(\"./direct-answer.js\").DirectAnswerResult | undefined;\n for (const ns of namespaces) {\n const r = await tryDirectAnswer({\n query: prompt,\n namespace: ns,\n config: this.config,\n sources,\n });\n if (r.eligible && r.winner) {\n result = r;\n break;\n }\n }\n\n if (!result?.eligible || !result?.winner) return;\n\n const explain: RecallTierExplain = {\n tier: \"direct-answer\",\n tierReason: result.narrative,\n filteredBy: result.filteredBy,\n candidatesConsidered,\n latencyMs: Date.now() - tierStart,\n sourceAnchors: [{ path: result.winner.memory.path }],\n };\n\n await this.lastRecall.annotateTierExplain(\n sessionKey,\n explain,\n expectedIdentity,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n log.debug(`direct-answer observation failed: ${err}`);\n }\n }\n\n private logRecallFailure(err: unknown): void {\n const now = Date.now();\n const errorMsg = err instanceof Error ? err.message : String(err);\n const LOG_WINDOW_MS = 60_000;\n const idleSinceLastFailureMs = now - this.lastRecallFailureAtMs;\n this.lastRecallFailureAtMs = now;\n if (idleSinceLastFailureMs >= LOG_WINDOW_MS) {\n this.suppressedRecallFailures = 0;\n }\n\n if (now - this.lastRecallFailureLogAtMs >= LOG_WINDOW_MS) {\n const suffix =\n this.suppressedRecallFailures > 0\n ? ` (suppressed ${this.suppressedRecallFailures} similar failures in last minute)`\n : \"\";\n log.warn(`recall timed out or failed: ${errorMsg}${suffix}`);\n this.lastRecallFailureLogAtMs = now;\n this.suppressedRecallFailures = 0;\n return;\n }\n\n this.suppressedRecallFailures += 1;\n log.debug(`recall timed out or failed (suppressed): ${errorMsg}`);\n }\n\n private artifactTypeForCategory(\n category: string,\n ):\n | \"decision\"\n | \"constraint\"\n | \"todo\"\n | \"definition\"\n | \"commitment\"\n | \"correction\"\n | \"fact\" {\n if (category === \"decision\") return \"decision\";\n if (category === \"commitment\") return \"commitment\";\n if (category === \"correction\") return \"correction\";\n if (category === \"principle\") return \"constraint\";\n return \"fact\";\n }\n\n private truncateArtifactForRecall(text: string, maxChars = 280): string {\n if (text.length <= maxChars) return text;\n return `${text.slice(0, maxChars - 1)}…`;\n }\n\n private async fetchActiveArtifactsForNamespace(\n namespace: string,\n prompt: string,\n targetCount: number,\n ): Promise<MemoryFile[]> {\n const storage = await this.storageRouter.storageFor(namespace);\n let fetchLimit = computeArtifactCandidateFetchLimit(targetCount);\n const maxFetchLimit = Math.min(800, Math.max(fetchLimit, targetCount * 8));\n const MAX_ATTEMPTS = 4;\n let bestFiltered: MemoryFile[] = [];\n\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {\n const rawResults = await storage.searchArtifacts(prompt, fetchLimit);\n const sourceIds = Array.from(\n new Set(\n rawResults\n .map((a) => a.frontmatter.sourceMemoryId)\n .filter(\n (id): id is string => typeof id === \"string\" && id.length > 0,\n ),\n ),\n );\n const sourceStatus =\n sourceIds.length > 0\n ? await this.resolveArtifactSourceStatuses(storage, sourceIds)\n : new Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">();\n\n const filtered: MemoryFile[] = [];\n for (const artifact of rawResults) {\n const sourceId = artifact.frontmatter.sourceMemoryId;\n if (!sourceId) {\n filtered.push(artifact);\n if (filtered.length >= targetCount) break;\n continue;\n }\n const status = sourceStatus.get(sourceId) ?? \"missing\";\n if (status !== \"active\") continue;\n filtered.push(artifact);\n if (filtered.length >= targetCount) break;\n }\n\n if (filtered.length >= targetCount) return filtered.slice(0, targetCount);\n if (filtered.length > bestFiltered.length) {\n bestFiltered = filtered;\n }\n if (rawResults.length === 0) return filtered;\n if (rawResults.length < fetchLimit && filtered.length > 0)\n return filtered;\n if (fetchLimit >= maxFetchLimit) return filtered;\n\n const growth = Math.max(targetCount * 2, 12);\n fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);\n }\n\n return bestFiltered;\n }\n\n private async recallArtifactsAcrossNamespaces(\n prompt: string,\n recallNamespaces: string[],\n targetCount: number,\n ): Promise<MemoryFile[]> {\n if (targetCount <= 0) return [];\n const namespaces = Array.from(new Set(recallNamespaces));\n const filteredByNamespace = await Promise.all(\n namespaces.map((namespace) =>\n this.fetchActiveArtifactsForNamespace(namespace, prompt, targetCount),\n ),\n );\n\n return mergeArtifactRecallCandidates(filteredByNamespace, targetCount);\n }\n\n private scopeQueryAwarePaths(\n paths: Set<string> | null,\n recallNamespaces: string[],\n ): Set<string> | null {\n if (!paths || paths.size === 0) return null;\n const scoped = new Set<string>();\n for (const memoryPath of paths) {\n if (!memoryPath || isArtifactMemoryPath(memoryPath)) continue;\n if (\n this.config.namespacesEnabled &&\n !recallNamespaces.includes(this.namespaceFromPath(memoryPath))\n ) {\n continue;\n }\n scoped.add(memoryPath);\n }\n return scoped.size > 0 ? scoped : null;\n }\n\n private async buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter> {\n if (!this.config.queryAwareIndexingEnabled || !prompt.trim()) {\n return {\n candidatePaths: null,\n temporalFromDate: null,\n matchedTags: [],\n expandedTags: [],\n combination: \"none\",\n filteredToFullSearch: false,\n };\n }\n\n const temporalFromDate = isTemporalQuery(prompt)\n ? recencyWindowFromPrompt(prompt, Date.now())\n : null;\n const [rawTemporal, tagSignals] = await Promise.all([\n temporalFromDate\n ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n resolvePromptTagPrefilterAsync(this.config.memoryDir, prompt).catch(\n () => ({\n matchedTags: extractTagsFromPrompt(prompt),\n expandedTags: extractTagsFromPrompt(prompt),\n paths: null,\n }),\n ),\n ]);\n\n const temporalCandidates = this.scopeQueryAwarePaths(\n rawTemporal,\n recallNamespaces,\n );\n const tagCandidates = this.scopeQueryAwarePaths(\n tagSignals.paths,\n recallNamespaces,\n );\n const maxCandidates = this.config.queryAwareIndexingMaxCandidates;\n\n let candidatePaths: Set<string> | null = null;\n let combination: QueryAwarePrefilter[\"combination\"] = \"none\";\n let filteredToFullSearch = false;\n\n if (temporalCandidates && tagCandidates) {\n const intersection = new Set(\n Array.from(temporalCandidates).filter((memoryPath) =>\n tagCandidates.has(memoryPath),\n ),\n );\n if (intersection.size > 0) {\n candidatePaths = intersection;\n combination = \"intersection\";\n } else {\n candidatePaths = new Set([...temporalCandidates, ...tagCandidates]);\n combination = \"union\";\n }\n } else if (temporalCandidates) {\n candidatePaths = temporalCandidates;\n combination = \"temporal\";\n } else if (tagCandidates) {\n candidatePaths = tagCandidates;\n combination = \"tag\";\n }\n\n if (\n candidatePaths &&\n maxCandidates > 0 &&\n candidatePaths.size > maxCandidates\n ) {\n filteredToFullSearch = true;\n candidatePaths = null;\n }\n\n return {\n candidatePaths,\n temporalFromDate,\n matchedTags: tagSignals.matchedTags,\n expandedTags: tagSignals.expandedTags,\n combination,\n filteredToFullSearch,\n };\n }\n\n private async searchScopedMemoryCandidates(\n candidatePaths: Set<string>,\n query: string,\n limit: number,\n options?: {\n allowArchived?: boolean;\n },\n ): Promise<QmdSearchResult[]> {\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0 || candidatePaths.size === 0) return [];\n\n const tokens = Array.from(new Set(tokenizeRecallQuery(query)));\n const memories = (\n await Promise.all(\n Array.from(candidatePaths).map(async (memoryPath) => {\n const namespace = this.config.namespacesEnabled\n ? this.namespaceFromPath(memoryPath)\n : this.config.defaultNamespace;\n const storage = await this.storageRouter.storageFor(namespace);\n return await storage.readMemoryByPath(memoryPath);\n }),\n )\n ).filter((memory): memory is MemoryFile => memory !== null);\n\n const results: QmdSearchResult[] = [];\n for (const memory of memories) {\n const status = memory.frontmatter.status ?? \"active\";\n if (!options?.allowArchived && status !== \"active\") continue;\n\n const haystack = [\n memory.content,\n memory.frontmatter.category,\n ...(memory.frontmatter.tags ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n let hits = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) hits += 1;\n }\n const score = tokens.length > 0 ? hits / tokens.length : 0.01;\n if (tokens.length > 0 && hits === 0) continue;\n\n results.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n score,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n transport: \"scoped_prefilter\",\n });\n }\n\n return results.sort((a, b) => b.score - a.score).slice(0, cappedLimit);\n }\n\n private async fetchQmdMemoryResultsWithArtifactTopUp(\n prompt: string,\n qmdFetchLimit: number,\n qmdHybridFetchLimit: number,\n options: {\n namespacesEnabled: boolean;\n recallNamespaces: string[];\n resolveNamespace: (path: string) => string;\n collection?: string;\n queryAwarePrefilter?: QueryAwarePrefilter;\n searchOptions?: SearchQueryOptions;\n onDebugSnapshot?: (snapshot: QmdRecallSnapshot) => Promise<void>;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]> {\n throwIfRecallAborted(options.abortSignal);\n const queryAwarePrefilter =\n options.queryAwarePrefilter ??\n (await this.buildQueryAwarePrefilter(prompt, options.recallNamespaces));\n const scopedSeedResults = queryAwarePrefilter.candidatePaths?.size\n ? await this.searchScopedMemoryCandidates(\n queryAwarePrefilter.candidatePaths,\n prompt,\n qmdFetchLimit,\n { allowArchived: options.collection !== undefined },\n )\n : [];\n\n let fetchLimit = Math.max(qmdFetchLimit, qmdHybridFetchLimit);\n const maxFetchLimit = Math.min(\n 320,\n Math.max(fetchLimit, qmdFetchLimit * 5),\n );\n const MAX_ATTEMPTS = 2;\n const qmdRecallBudgetMs = this.config.recallEnrichmentDeadlineMs ?? 25_000;\n const qmdRecallBudgetEnabled = qmdRecallBudgetMs > 0;\n const startedAtMs = Date.now();\n let lastPrimaryResultCount = 0;\n let lastHybridResultCount = 0;\n let lastHybridTopUpUsed = false;\n let lastHybridTopUpSkippedReason: string | undefined;\n const backendHonorsQmdSearchSignals =\n (this.config.searchBackend ?? \"qmd\") === \"qmd\";\n const resolvedSearchOptions = (() => {\n const resolver = (\n this.qmd as {\n resolveSupportedSearchOptions?: (\n options?: SearchQueryOptions,\n ) => SearchQueryOptions | undefined;\n }\n ).resolveSupportedSearchOptions;\n if (typeof resolver === \"function\") {\n return resolver.call(this.qmd, options.searchOptions);\n }\n return options.searchOptions;\n })();\n const primarySearchOptions = backendHonorsQmdSearchSignals\n ? resolvedSearchOptions\n : options.searchOptions;\n const debugSearchOptions = backendHonorsQmdSearchSignals\n ? resolvedSearchOptions\n : undefined;\n let bestFiltered = filterRecallCandidates(scopedSeedResults, {\n namespacesEnabled: options.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: options.resolveNamespace,\n limit: qmdFetchLimit,\n });\n const emitDebugSnapshot = async (\n results: QmdSearchResult[],\n currentFetchLimit: number,\n ) => {\n if (!options.onDebugSnapshot) return;\n await options.onDebugSnapshot({\n recordedAt: new Date().toISOString(),\n queryHash: createHash(\"sha256\").update(prompt).digest(\"hex\"),\n queryLength: prompt.length,\n collection: options.collection,\n namespaces: options.recallNamespaces,\n fetchLimit: currentFetchLimit,\n primaryResultCount: lastPrimaryResultCount,\n hybridResultCount: lastHybridResultCount,\n queryAwareSeedCount: scopedSeedResults.length,\n resultCount: results.length,\n intentHint: debugSearchOptions?.intent,\n explainEnabled: debugSearchOptions?.explain === true,\n hybridTopUpUsed: lastHybridTopUpUsed,\n hybridTopUpSkippedReason: lastHybridTopUpSkippedReason,\n results: results.slice(0, 32).map((result) => ({\n ...result,\n snippet: result.snippet.slice(0, 280),\n })),\n });\n };\n\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {\n throwIfRecallAborted(options.abortSignal);\n if (\n qmdRecallBudgetEnabled &&\n Date.now() - startedAtMs >= qmdRecallBudgetMs\n ) {\n break;\n }\n\n const primaryResults = options.collection\n ? options.abortSignal\n ? await this.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n {\n signal: options.abortSignal,\n },\n )\n : await this.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n )\n : await this.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"search\",\n searchOptions: primarySearchOptions,\n execution: { signal: options.abortSignal },\n });\n lastPrimaryResultCount = primaryResults.length;\n lastHybridResultCount = 0;\n lastHybridTopUpUsed = false;\n lastHybridTopUpSkippedReason = undefined;\n let mergedResults = primaryResults;\n\n // Backfill with hybrid results only when primary retrieval underfills.\n if (\n primaryResults.length < qmdFetchLimit &&\n (!qmdRecallBudgetEnabled ||\n Date.now() - startedAtMs < qmdRecallBudgetMs)\n ) {\n if (debugSearchOptions?.intent) {\n lastHybridTopUpSkippedReason = \"intent_hint_active\";\n } else {\n const hybridResults = options.collection\n ? await this.qmd.hybridSearch(\n prompt,\n options.collection,\n fetchLimit,\n {\n signal: options.abortSignal,\n },\n )\n : await this.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"hybrid\",\n execution: { signal: options.abortSignal },\n });\n lastHybridResultCount = hybridResults.length;\n lastHybridTopUpUsed = hybridResults.length > 0;\n if (hybridResults.length > 0) {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...primaryResults, ...hybridResults]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n transport: result.transport ?? \"hybrid\",\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n mergedResults = [...mergedByPath.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, fetchLimit);\n }\n }\n }\n\n if (scopedSeedResults.length > 0) {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...scopedSeedResults, ...mergedResults]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n mergedResults = [...mergedByPath.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, fetchLimit);\n }\n\n const filteredResults = filterRecallCandidates(mergedResults, {\n namespacesEnabled: options.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: options.resolveNamespace,\n limit: fetchLimit,\n });\n\n if (filteredResults.length >= qmdFetchLimit) {\n const capped = filteredResults.slice(0, qmdFetchLimit);\n await emitDebugSnapshot(capped, fetchLimit);\n return capped;\n }\n if (filteredResults.length > bestFiltered.length) {\n bestFiltered = filteredResults;\n }\n if (mergedResults.length === 0) {\n await emitDebugSnapshot(filteredResults, fetchLimit);\n return filteredResults;\n }\n if (mergedResults.length < fetchLimit && filteredResults.length > 0) {\n await emitDebugSnapshot(filteredResults, fetchLimit);\n return filteredResults;\n }\n if (fetchLimit >= maxFetchLimit) {\n break;\n }\n\n const growth = Math.max(20, Math.floor(fetchLimit / 2));\n fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);\n }\n\n const capped = bestFiltered.slice(0, qmdFetchLimit);\n await emitDebugSnapshot(capped, fetchLimit);\n return capped;\n }\n\n private async expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n /** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */\n includeLowConfidence?: boolean;\n }): Promise<{\n merged: QmdSearchResult[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n seedResults: QmdSearchResult[];\n }> {\n const byNamespace = new Map<string, QmdSearchResult[]>();\n for (const result of options.memoryResults) {\n const ns = this.namespaceFromPath(result.path);\n if (!options.recallNamespaces.includes(ns)) continue;\n const existing = byNamespace.get(ns);\n if (existing) {\n existing.push(result);\n } else {\n byNamespace.set(ns, [result]);\n }\n }\n\n const perNamespaceSeedCap = Math.max(3, options.recallResultLimit);\n const perNamespaceExpandedCap = Math.max(8, options.recallResultLimit * 2);\n const seedPaths: string[] = [];\n const seedResults: QmdSearchResult[] = [];\n const expandedPaths: GraphRecallExpandedEntry[] = [];\n const expandedResults: QmdSearchResult[] = [];\n\n for (const [namespace, nsResults] of byNamespace.entries()) {\n const storage = await this.storageRouter.storageFor(namespace);\n const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);\n seedResults.push(...seedCandidates);\n const seedRelativePaths = seedCandidates\n .map((result) => graphPathRelativeToStorage(storage.dir, result.path))\n .filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n );\n if (seedRelativePaths.length === 0) continue;\n\n const seedRecallScore = seedCandidates.reduce(\n (max, item) => Math.max(max, item.score),\n 0,\n );\n seedPaths.push(\n ...seedRelativePaths.map((rel) => path.join(storage.dir, rel)),\n );\n const seedSet = new Set(seedRelativePaths);\n const expanded = await this.graphIndexFor(storage).spreadingActivation(\n seedRelativePaths,\n this.config.maxGraphTraversalSteps,\n options.includeLowConfidence === true ? { includeLowConfidence: true } : undefined,\n );\n if (expanded.length === 0) continue;\n\n for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {\n if (seedSet.has(candidate.path)) continue;\n const memoryPath = path.resolve(storage.dir, candidate.path);\n const memory = await storage.readMemoryByPath(memoryPath);\n if (!memory) continue;\n if (isArtifactMemoryPath(memory.path)) continue;\n if (memory.frontmatter.status && memory.frontmatter.status !== \"active\")\n continue;\n\n const snippet = memory.content.slice(0, 400);\n const score = blendGraphExpandedRecallScore({\n graphActivationScore: candidate.score,\n seedRecallScore,\n activationWeight: this.config.graphExpansionActivationWeight,\n blendMin: this.config.graphExpansionBlendMin,\n blendMax: this.config.graphExpansionBlendMax,\n });\n expandedResults.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n snippet,\n score,\n });\n expandedPaths.push({\n path: memory.path,\n score,\n namespace,\n seed: path.resolve(storage.dir, candidate.seed),\n hopDepth: candidate.hopDepth,\n decayedWeight: candidate.decayedWeight,\n graphType: candidate.graphType,\n // Issue #681 PR 3/3 — surface the per-edge confidence used for\n // PageRank weighting / floor pruning so downstream observability\n // (recall_xray, memory_graph_explain) can attribute ranking and\n // pruning decisions to specific edges.\n edgeConfidence: candidate.edgeConfidence,\n });\n }\n }\n\n return {\n merged: mergeGraphExpandedResults(options.memoryResults, expandedResults),\n seedPaths,\n expandedPaths,\n seedResults,\n };\n }\n\n private async recordLastGraphRecallSnapshot(options: {\n storage: StorageManager;\n prompt: string;\n recallMode: RecallPlanMode;\n recallNamespaces: string[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n status: \"completed\" | \"skipped\" | \"aborted\";\n reason?: string;\n shadowMode?: boolean;\n queryIntent: MemoryIntent;\n seedResults?: GraphRecallRankedResult[];\n finalResults?: GraphRecallRankedResult[];\n shadowComparison?: GraphRecallShadowComparison;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_graph_recall.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n const now = new Date().toISOString();\n const totalSeedCount = options.seedPaths.length;\n const totalExpandedCount = options.expandedPaths.length;\n const seeds = options.seedPaths.slice(0, 64);\n const expanded = clampGraphRecallExpandedEntries(\n options.expandedPaths,\n 64,\n );\n const payload = {\n recordedAt: now,\n mode: options.recallMode,\n queryHash: createHash(\"sha256\").update(options.prompt).digest(\"hex\"),\n queryLength: options.prompt.length,\n namespaces: options.recallNamespaces,\n seedCount: totalSeedCount,\n expandedCount: totalExpandedCount,\n seeds,\n expanded,\n status: options.status,\n reason: options.reason,\n shadowMode: options.shadowMode === true,\n queryIntent: options.queryIntent,\n seedResults: (options.seedResults ?? []).slice(0, 64),\n finalResults: (options.finalResults ?? []).slice(0, 64),\n shadowComparison: options.shadowComparison,\n };\n await writeFile(snapshotPath, JSON.stringify(payload, null, 2), \"utf-8\");\n } catch (err) {\n log.debug(`last graph recall write failed: ${err}`);\n }\n }\n\n private async recordLastIntentSnapshot(options: {\n storage: StorageManager;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_intent.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last intent write failed: ${err}`);\n }\n }\n\n private async recordLastQmdRecallSnapshot(options: {\n storage: StorageManager;\n snapshot: QmdRecallSnapshot;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_qmd_recall.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last qmd recall write failed: ${err}`);\n }\n }\n\n private async recordLastIntentSnapshotForNamespace(options: {\n namespace: string;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n try {\n const stateDir = await this.resolveStateDirForNamespace(\n options.namespace,\n );\n const snapshotPath = path.join(stateDir, \"last_intent.json\");\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last intent write failed: ${err}`);\n }\n }\n\n private async resolveStateDirForNamespace(\n namespace: string,\n ): Promise<string> {\n if (!this.config.namespacesEnabled) {\n return path.join(this.config.memoryDir, \"state\");\n }\n if (namespace !== this.config.defaultNamespace) {\n return path.join(this.config.memoryDir, \"namespaces\", namespace, \"state\");\n }\n const candidate = path.join(\n this.config.memoryDir,\n \"namespaces\",\n this.config.defaultNamespace,\n );\n try {\n const candidateStat = await stat(candidate);\n if (candidateStat.isDirectory()) {\n return path.join(candidate, \"state\");\n }\n } catch {\n // Fall back to the legacy root when the migrated default namespace directory is absent.\n }\n return path.join(this.config.memoryDir, \"state\");\n }\n\n private buildGraphRecallRankedResults(\n results: QmdSearchResult[],\n sourceLabelResolver: (path: string) => string[],\n limit: number = 64,\n ): GraphRecallRankedResult[] {\n return results.slice(0, limit).map((result) => ({\n path: result.path,\n score: result.score,\n docid: result.docid,\n sourceLabels: sourceLabelResolver(result.path),\n }));\n }\n\n private getRecallSectionEntry(\n sectionId: string,\n ): RecallSectionConfig | undefined {\n const pipeline = Array.isArray(this.config.recallPipeline)\n ? this.config.recallPipeline\n : [];\n return pipeline.find((entry) => entry.id === sectionId);\n }\n\n private isRecallSectionEnabled(\n sectionId: string,\n defaultEnabled: boolean = true,\n ): boolean {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return defaultEnabled;\n return entry.enabled !== false;\n }\n\n private getRecallSectionMaxChars(\n sectionId: string,\n ): number | null | undefined {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return undefined;\n if (entry.maxChars === null) return null;\n if (typeof entry.maxChars !== \"number\") return undefined;\n return Math.max(0, Math.floor(entry.maxChars));\n }\n\n private getRecallSectionNumber(\n sectionId: string,\n key: keyof RecallSectionConfig,\n ): number | undefined {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return undefined;\n const value = entry[key];\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return Math.max(0, Math.floor(value));\n }\n\n private appendRecallSection(\n sectionBuckets: Map<string, string[]>,\n sectionId: string,\n content: string,\n ): boolean {\n // Returns true when the section was actually appended to sectionBuckets,\n // false when it was dropped (disabled, empty, or maxChars===0). Callers\n // that need to know whether injection occurred (e.g. xray annotation for\n // peer-profile) must gate on this return value rather than on whether the\n // section text was computed (Codex P2 finding, PR #764).\n if (!this.isRecallSectionEnabled(sectionId)) return false;\n const trimmed = content.trim();\n if (trimmed.length === 0) return false;\n\n const maxChars = this.getRecallSectionMaxChars(sectionId);\n let finalContent = trimmed;\n if (maxChars === 0) return false;\n if (typeof maxChars === \"number\" && finalContent.length > maxChars) {\n finalContent = `${finalContent.slice(0, maxChars)}\\n\\n...(trimmed)\\n`;\n }\n\n const existing = sectionBuckets.get(sectionId) ?? [];\n existing.push(finalContent);\n sectionBuckets.set(sectionId, existing);\n return true;\n }\n\n private truncateRecallSectionToBudget(\n content: string,\n maxChars: number,\n ): string {\n if (maxChars <= 0) return \"\";\n if (content.length <= maxChars) return content;\n const suffix = \"\\n\\n...(memory context trimmed)\";\n if (maxChars <= suffix.length) {\n return content.slice(0, maxChars);\n }\n return `${content.slice(0, maxChars - suffix.length)}${suffix}`;\n }\n\n private protectedRecallSectionIds(\n sectionBuckets: Map<string, string[]>,\n ): Set<string> {\n const protectedIds = new Set<string>();\n if ((sectionBuckets.get(\"memories\")?.length ?? 0) > 0) {\n protectedIds.add(\"memories\");\n }\n return protectedIds;\n }\n\n private protectedRecallReservationChars(content: string): number {\n const headingBoundary = content.indexOf(\"\\n\\n\");\n const headingChars =\n headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);\n return Math.min(content.length, Math.max(headingChars, 24));\n }\n\n private estimateReservedRecallBudget(\n entries: Array<{ id: string; content: string }>,\n startIndex: number,\n protectedIds: Set<string>,\n alreadyIncludedCount: number,\n ): number {\n const separatorLength = \"\\n\\n---\\n\\n\".length;\n let reserved = 0;\n let simulatedIncluded = alreadyIncludedCount;\n for (let i = startIndex; i < entries.length; i += 1) {\n const entry = entries[i];\n if (!entry || !protectedIds.has(entry.id)) continue;\n if (simulatedIncluded > 0) {\n reserved += separatorLength;\n }\n reserved += this.protectedRecallReservationChars(entry.content);\n simulatedIncluded += 1;\n }\n return reserved;\n }\n\n private getRecallBudgetChars(override?: number): number {\n if (\n typeof override === \"number\" &&\n Number.isFinite(override) &&\n override >= 0\n ) {\n return Math.floor(override);\n }\n const configuredBudget = this.config.recallBudgetChars;\n if (\n typeof configuredBudget === \"number\" &&\n Number.isFinite(configuredBudget) &&\n configuredBudget >= 0\n ) {\n return Math.floor(configuredBudget);\n }\n const tokenBudget = this.config.maxMemoryTokens;\n if (\n typeof tokenBudget === \"number\" &&\n Number.isFinite(tokenBudget) &&\n tokenBudget >= 0\n ) {\n return Math.floor(tokenBudget * 4);\n }\n return 0;\n }\n\n private assembleRecallSections(\n sectionBuckets: Map<string, string[]>,\n budgetOverride?: number,\n ): {\n sections: string[];\n includedIds: string[];\n omittedIds: string[];\n truncated: boolean;\n finalChars: number;\n } {\n const orderedEntries: Array<{ id: string; content: string }> = [];\n const pipeline = Array.isArray(this.config.recallPipeline)\n ? this.config.recallPipeline\n : [];\n const orderedIds = pipeline\n .filter((entry) => entry.enabled !== false)\n .map((entry) => entry.id);\n const seen = new Set<string>();\n\n for (const id of orderedIds) {\n const chunks = sectionBuckets.get(id);\n if (!chunks || chunks.length === 0) continue;\n orderedEntries.push({ id, content: chunks.join(\"\\n\\n\") });\n seen.add(id);\n }\n\n for (const [id, chunks] of sectionBuckets.entries()) {\n if (seen.has(id)) continue;\n if (chunks.length === 0) continue;\n orderedEntries.push({ id, content: chunks.join(\"\\n\\n\") });\n }\n\n const budget = this.getRecallBudgetChars(budgetOverride);\n if (budget === 0) {\n return {\n sections: [],\n includedIds: [],\n omittedIds: orderedEntries.map((entry) => entry.id),\n truncated: orderedEntries.length > 0,\n finalChars: 0,\n };\n }\n\n const separator = \"\\n\\n---\\n\\n\";\n const protectedIds = this.protectedRecallSectionIds(sectionBuckets);\n const sections: string[] = [];\n const includedIds: string[] = [];\n const omittedIds: string[] = [];\n let usedChars = 0;\n let truncated = false;\n\n for (let index = 0; index < orderedEntries.length; index += 1) {\n const entry = orderedEntries[index]!;\n const separatorChars = sections.length > 0 ? separator.length : 0;\n const reserve = protectedIds.has(entry.id)\n ? 0\n : this.estimateReservedRecallBudget(\n orderedEntries,\n index + 1,\n protectedIds,\n sections.length + 1,\n );\n const availableForEntry = budget - usedChars - separatorChars - reserve;\n if (availableForEntry <= 0) {\n omittedIds.push(entry.id);\n truncated = true;\n continue;\n }\n const finalContent = this.truncateRecallSectionToBudget(\n entry.content,\n availableForEntry,\n );\n if (!finalContent) {\n omittedIds.push(entry.id);\n truncated = true;\n continue;\n }\n if (finalContent.length < entry.content.length) {\n truncated = true;\n }\n sections.push(finalContent);\n includedIds.push(entry.id);\n usedChars += separatorChars + finalContent.length;\n }\n\n return {\n sections,\n includedIds,\n omittedIds,\n truncated,\n finalChars: usedChars,\n };\n }\n\n private async recallInternal(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n ): Promise<string> {\n const recallStart = Date.now();\n // Issue #680 — historical recall. Parse `options.asOf` once at the\n // top of the recall so each boost-pass uses identical filter logic.\n // Invalid values are rejected at input boundaries (CLI / HTTP / MCP)\n // per CLAUDE.md rule 51; if a malformed value sneaks through here,\n // we treat it as \"no historical pin\" rather than throwing inside\n // recall — the upstream surfaces are the source of truth.\n let asOfMs: number | undefined;\n if (typeof options.asOf === \"string\" && options.asOf.length > 0) {\n const parsed = Date.parse(options.asOf);\n if (Number.isFinite(parsed)) asOfMs = parsed;\n }\n const timings: Record<string, string> = {};\n const profileTraceId = this.profiler.startTrace(\"recall\", sessionKey, {\n qmdEnabled: this.config.qmdEnabled,\n rerankEnabled: this.config.rerankEnabled,\n parallelRetrieval: this.config.parallelRetrievalEnabled,\n });\n this.profiler.startSpan(\"planning\", profileTraceId);\n let profileTraceClosed = false;\n const closeProfileTrace = () => {\n if (profileTraceClosed) return;\n profileTraceClosed = true;\n this.profiler.endTrace(profileTraceId); // persists to JSONL file\n };\n const recallSectionDeadlineMs = this.config.recallCoreDeadlineMs ?? 75_000;\n const enrichmentSectionDeadlineMs =\n this.config.recallEnrichmentDeadlineMs ?? 25_000;\n // Wrap entire recall body in try/finally so profiling trace is always closed,\n // even on unexpected exceptions (e.g., throwIfRecallAborted, phase-1 errors).\n try {\n type DeferredEnrichmentOutcome<T> =\n | { status: \"resolved\"; value: T }\n | { status: \"rejected\"; error: unknown };\n type ObservedDeferredEnrichmentPromise<T> =\n Promise<DeferredEnrichmentOutcome<T>> & {\n getSettledOutcome: () => DeferredEnrichmentOutcome<T> | undefined;\n cancel: () => void;\n };\n const createEnrichmentAbortHandle = (parentSignal?: AbortSignal) => {\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n if (parentSignal?.aborted) {\n controller.abort();\n } else if (parentSignal) {\n parentSignal.addEventListener(\"abort\", onAbort, { once: true });\n }\n let disposed = false;\n const dispose = () => {\n if (disposed) return;\n disposed = true;\n parentSignal?.removeEventListener(\"abort\", onAbort);\n };\n return {\n signal: controller.signal,\n cancel: () => {\n controller.abort();\n dispose();\n },\n dispose,\n };\n };\n const observeEnrichmentPromise = <T>(\n promise: Promise<T>,\n cancel: () => void = () => {},\n ): ObservedDeferredEnrichmentPromise<T> => {\n let settledOutcome: DeferredEnrichmentOutcome<T> | undefined;\n const observed = promise\n .then<DeferredEnrichmentOutcome<T>, DeferredEnrichmentOutcome<T>>(\n (value) => ({ status: \"resolved\", value }),\n (error) => ({ status: \"rejected\", error }),\n )\n .then((outcome) => {\n settledOutcome = outcome;\n return outcome;\n }) as ObservedDeferredEnrichmentPromise<T>;\n observed.getSettledOutcome = () => settledOutcome;\n observed.cancel = cancel;\n return observed;\n };\n const recordRecallSectionMetric = createRecallSectionMetricRecorder({\n timings,\n logger: log,\n });\n const promptHash = createHash(\"sha256\").update(prompt).digest(\"hex\");\n const traceId = createHash(\"sha256\")\n .update(`${sessionKey ?? \"default\"}:${recallStart}:${promptHash}`)\n .digest(\"hex\")\n .slice(0, 16);\n const sectionBuckets = new Map<string, string[]>();\n const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,\n cronRecallNormalizedQueryMaxChars:\n this.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.config.cronConversationRecallMode,\n });\n const retrievalQuery = queryPolicy.retrievalQuery || prompt;\n const retrievalQueryHash = createHash(\"sha256\")\n .update(retrievalQuery)\n .digest(\"hex\");\n const policyVersion = this.currentPolicyVersion();\n let impressionRecorded = false;\n let recallSource:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\" = \"none\";\n let recalledMemoryCount = 0;\n let recalledMemoryIds: string[] = [];\n let recalledMemoryPaths: string[] = [];\n // Boosted QmdSearchResult array for the serving branch (issue #687 PR 3/4).\n // Populated alongside recalledMemoryPaths so the X-ray capture can read\n // per-result explain data (e.g. reinforcementBoost) from the result that\n // was actually served.\n let xrayRecalledResults: QmdSearchResult[] = [];\n const lcmStructuredXrayResults: RecallXrayResult[] = [];\n // Per-branch pre-limit candidate pool size for the X-ray filter\n // trace (issue #570 PR 1). `recalledMemoryCount` is assigned\n // AFTER MMR + truncation so using it alone would make the\n // `recall-result-limit` trace report `considered == admitted`\n // even when many candidates were dropped. Each entry captures\n // the pool size BEFORE truncation at that branch. The X-ray\n // capture block picks the pool that corresponds to the branch\n // that actually produced the admitted results (via `recallSource`)\n // so a pool from a branch whose candidates were killed by an\n // earlier gate cannot leak into the `considered` count.\n const xrayBranchPoolSize: Record<\n \"hot_qmd\" | \"hot_embedding\" | \"cold_fallback\" | \"recent_scan\",\n number\n > = {\n hot_qmd: 0,\n hot_embedding: 0,\n cold_fallback: 0,\n recent_scan: 0,\n };\n // Shared out-parameter sink the cold-fallback pipeline writes\n // its pre-truncation pool size into (issue #570 PR 1). Declared\n // once so every call to `applyColdFallbackPipeline` (four call\n // sites) updates the same counter; the X-ray capture block\n // reads this as the cold-fallback pool.\n const xrayColdPoolSink = { size: 0 };\n let identityInjectionModeUsed: IdentityInjectionMode | \"none\" = \"none\";\n let identityInjectedChars = 0;\n let identityInjectionTruncated = false;\n timings.queryPolicy = `${queryPolicy.promptShape}/${queryPolicy.retrievalBudgetMode}${queryPolicy.skipConversationRecall ? \"/skip-conv\" : \"\"}`;\n const recallDecision = resolveRecallModeDecision({\n plannerEnabled: this.config.recallPlannerEnabled,\n graphRecallEnabled: this.config.graphRecallEnabled,\n multiGraphMemoryEnabled: this.config.multiGraphMemoryEnabled,\n graphExpandedIntentEnabled:\n this.config.graphExpandedIntentEnabled === true,\n prompt,\n });\n this.profiler.endSpan(\"planning\", profileTraceId);\n const requestedMode = options.mode;\n const recallMode: RecallPlanMode =\n requestedMode ?? recallDecision.effectiveMode;\n const queryIntent = inferIntentFromText(retrievalQuery);\n const qmdSearchOptions =\n this.buildConfiguredQmdSearchOptions(retrievalQuery);\n timings.recallPlan = recallMode;\n const plannerRecallResultLimit =\n recallMode === \"no_recall\"\n ? 0\n : recallMode === \"minimal\"\n ? Math.max(\n 0,\n Math.min(\n this.config.qmdMaxResults,\n this.config.recallPlannerMaxQmdResultsMinimal,\n ),\n )\n : this.config.qmdMaxResults;\n const policyMinimalLimit = Math.max(\n 0,\n Math.min(\n this.config.qmdMaxResults,\n this.config.recallPlannerMaxQmdResultsMinimal,\n ),\n );\n const baseRecallResultLimit =\n recallMode !== \"no_recall\" &&\n queryPolicy.retrievalBudgetMode === \"minimal\"\n ? Math.min(plannerRecallResultLimit, policyMinimalLimit)\n : plannerRecallResultLimit;\n const memoriesSectionEnabled = this.isRecallSectionEnabled(\"memories\");\n const memorySectionMaxResults = this.getRecallSectionNumber(\n \"memories\",\n \"maxResults\",\n );\n const requestedTopK =\n typeof options.topK === \"number\" && Number.isFinite(options.topK)\n ? Math.max(0, Math.min(200, Math.floor(options.topK)))\n : undefined;\n const recallResultLimit = memoriesSectionEnabled\n ? (() => {\n let limit = baseRecallResultLimit;\n if (memorySectionMaxResults !== undefined) {\n limit = Math.min(limit, memorySectionMaxResults);\n }\n if (requestedTopK !== undefined) {\n limit = Math.min(limit, requestedTopK);\n }\n return limit;\n })()\n : 0;\n const recallHeadroom = this.config.verbatimArtifactsEnabled\n ? Math.max(12, this.config.verbatimArtifactsMaxRecall * 4)\n : 12;\n const computedFetchLimit =\n recallResultLimit === 0\n ? 0\n : Math.max(\n recallResultLimit,\n Math.min(200, recallResultLimit + recallHeadroom),\n );\n const qmdFetchLimit = computedFetchLimit;\n const qmdHybridFetchLimit = computeQmdHybridFetchLimit(\n qmdFetchLimit,\n this.config.verbatimArtifactsEnabled,\n this.config.verbatimArtifactsMaxRecall,\n );\n const embeddingFetchLimit = computedFetchLimit;\n // Principal resolution honours the access-surface override (issue\n // #570 PR 4). Access surfaces that have already authenticated the\n // caller at the transport layer (HTTP / MCP) pass their resolved\n // principal directly so namespace ACL decisions use the same\n // identity the surface authorized, instead of re-running\n // `resolvePrincipal(sessionKey)` which only maps raw session keys\n // through configured rules and otherwise collapses to `\"default\"`.\n const principal =\n typeof options.principalOverride === \"string\"\n && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const namespaceOverride = options.namespace?.trim() || undefined;\n const readableRecallNamespaces = recallNamespacesForPrincipal(\n principal,\n this.config,\n );\n if (\n namespaceOverride &&\n !canReadNamespace(principal, namespaceOverride, this.config)\n ) {\n throw new Error(\n `namespace override is not readable: ${namespaceOverride}`,\n );\n }\n // Recall path — overlay the coding-agent namespace (issue #569) when\n // the session has a codingContext and `codingMode.projectScope` is true.\n // Explicit `namespace` option still wins, preserving pre-#569 semantics.\n //\n // Rule 42: the overlay substitutes the SELF namespace within the\n // principal's recall list — it does NOT replace the full list. Shared\n // and `includeInRecallByDefault` policy namespaces stay in the recall\n // set so coding sessions continue to see team/shared memories. The\n // overlay is combined with the principal base through `combineNamespaces`\n // to preserve principal isolation (cross-tenant leakage guard).\n const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);\n const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);\n const codingSelfNamespace = codingOverlay\n ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace)\n : null;\n const selfNamespace =\n namespaceOverride ??\n codingSelfNamespace ??\n principalSelfNamespace;\n let recallNamespaces: string[];\n if (namespaceOverride) {\n recallNamespaces = [namespaceOverride];\n } else if (codingOverlay && codingSelfNamespace) {\n // Substitute the principal's self namespace with the coding-scoped\n // one, and append any read fallbacks (branch→project, PR 3) combined\n // with the principal base so principal isolation is preserved on\n // fallback entries as well.\n const mapped = readableRecallNamespaces.map((ns) =>\n ns === principalSelfNamespace ? codingSelfNamespace : ns,\n );\n const fallbackNs = codingOverlay.readFallbacks.map((fallback) =>\n combineNamespaces(principalSelfNamespace, fallback),\n );\n recallNamespaces = Array.from(new Set<string>([...mapped, ...fallbackNs]));\n } else {\n recallNamespaces = readableRecallNamespaces;\n }\n const qmdAvailable = this.qmd.isAvailable();\n let graphDecisionStatus: IntentDebugSnapshot[\"graphDecision\"][\"status\"] =\n recallDecision.plannedMode === \"graph_mode\" ? \"skipped\" : \"not_requested\";\n let graphDecisionReason = recallDecision.graphReason;\n let graphDecisionShadowMode = false;\n let shouldPersistGraphSnapshot =\n recallDecision.plannedMode === \"graph_mode\";\n let graphSnapshotStatus: GraphRecallSnapshot[\"status\"] | undefined =\n recallDecision.plannedMode === \"graph_mode\" ? \"skipped\" : undefined;\n let graphSnapshotReason = recallDecision.graphReason;\n let graphSnapshotSeedPaths: string[] = [];\n let graphSnapshotExpandedPaths: GraphRecallExpandedEntry[] = [];\n let graphSnapshotSeedResults: GraphRecallRankedResult[] = [];\n let graphSnapshotFinalResults: GraphRecallRankedResult[] = [];\n let graphSnapshotShadowComparison: GraphRecallShadowComparison | undefined;\n const graphBaselinePaths = new Set<string>();\n const graphExpandedResultPaths = new Set<string>();\n const graphSourceLabelsForPath = (resultPath: string): string[] => {\n const labels: string[] = [];\n const normalizedPath = resultPath.split(path.sep).join(\"/\");\n const isEntityPath =\n normalizedPath.startsWith(\"entities/\") ||\n normalizedPath.includes(\"/entities/\");\n if (graphBaselinePaths.has(resultPath)) labels.push(\"baseline\");\n if (graphExpandedResultPaths.has(resultPath))\n labels.push(\"graph_expanded\");\n if (isEntityPath) labels.push(\"reconstructed_entity\");\n return labels.length > 0 ? labels : [\"baseline\"];\n };\n const buildIntentDebugSnapshot = (): IntentDebugSnapshot => ({\n recordedAt: new Date().toISOString(),\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n plannerEnabled: this.config.recallPlannerEnabled,\n plannedMode: requestedMode ?? recallDecision.plannedMode,\n effectiveMode: recallMode,\n recallResultLimit,\n queryIntent,\n graphExpandedIntentDetected: recallDecision.graphExpandedIntentDetected,\n graphDecision: {\n status: graphDecisionStatus,\n reason: graphDecisionReason,\n shadowMode: graphDecisionShadowMode,\n qmdAvailable,\n graphRecallEnabled: this.config.graphRecallEnabled,\n multiGraphMemoryEnabled: this.config.multiGraphMemoryEnabled,\n },\n });\n\n if (recallMode === \"no_recall\") {\n const intentSnapshot = buildIntentDebugSnapshot();\n await this.recordLastIntentSnapshotForNamespace({\n namespace: selfNamespace,\n snapshot: intentSnapshot,\n });\n // Clean up workspace selection before early return to prevent Map leaks.\n const earlySessionKey = sessionKey ?? \"default\";\n this._recallWorkspaceOverrides.delete(earlySessionKey);\n timings.total = `${Date.now() - recallStart}ms`;\n // X-ray capture for the `no_recall` early-return path\n // (issue #570 PR 1). `no_recall` skips retrieval entirely, so\n // the snapshot carries zero results and an empty-budget accounting\n // — but we STILL capture it when the caller opts in so\n // `getLastXraySnapshot()` returns a useful debug document rather\n // than silently `null` (or a stale prior capture).\n //\n // Skip capture when the caller has already aborted this recall —\n // otherwise a canceled call could clobber a prior successful\n // capture (issue #570 PR 1 review follow-up).\n if (\n options.xrayCapture === true &&\n !options.abortSignal?.aborted\n ) {\n try {\n this.lastXraySnapshot = buildXraySnapshot({\n query: retrievalQuery,\n tierExplain: null,\n results: [],\n filters: [\n {\n name: \"planner-mode\",\n considered: 0,\n admitted: 0,\n reason: \"no_recall\",\n },\n ],\n budget: {\n chars: this.getRecallBudgetChars(options.budgetCharsOverride),\n used: 0,\n },\n sessionKey,\n namespace: selfNamespace,\n traceId,\n });\n } catch (err) {\n // Capture is a best-effort side channel: a capture failure\n // must NEVER propagate into the primary recall path.\n log.debug(`x-ray capture (no_recall) failed: ${err}`);\n }\n }\n if (sessionKey) {\n this.lastRecall\n .record({\n sessionKey,\n query: retrievalQuery,\n memoryIds: [],\n namespace: selfNamespace,\n traceId,\n plannerMode: recallMode,\n requestedMode,\n source: recallSource,\n fallbackUsed: false,\n sourcesUsed: [],\n budgetsApplied: this.buildLastRecallBudgetSummary({\n requestedTopK,\n recallResultLimit,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n }),\n latencyMs: Date.now() - recallStart,\n resultPaths: [],\n policyVersion,\n appendImpression: this.config.recordEmptyRecallImpressions,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n })\n .catch((err) => log.debug(`last recall record failed: ${err}`));\n }\n if (sessionKey) {\n this.queueEvalShadowRecall({\n traceId,\n recordedAt: new Date().toISOString(),\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n source: recallSource,\n recalledMemoryCount,\n injected: false,\n contextChars: 0,\n memoryIds: [],\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n }\n closeProfileTrace();\n this.emitTrace({\n kind: \"recall_summary\",\n traceId,\n operation: \"recall\",\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n qmdEnabled: this.config.qmdEnabled,\n qmdAvailable: this.qmd.isAvailable(),\n recallNamespaces: [],\n source: recallSource,\n recalledMemoryCount,\n injected: false,\n contextChars: 0,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n return \"\";\n }\n\n const profileStorage = await this.storageRouter.storageFor(selfNamespace);\n\n // --- Phase 1: Launch ALL independent data fetches in parallel ---\n throwIfRecallAborted(options.abortSignal);\n\n // 0. Shared context (v4.0, optional)\n const sharedContextPromise = (async (): Promise<string | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"shared-context\",\n this.config.sharedContextEnabled === true,\n )\n )\n return null;\n if (!this.sharedContext) return null;\n const t0 = Date.now();\n const [priorities, roundtable, crossSignals] = await Promise.all([\n this.sharedContext.readPriorities(),\n this.sharedContext.readLatestRoundtable(),\n this.sharedContext.readLatestCrossSignals(),\n ]);\n const max = Math.max(500, this.config.sharedContextMaxInjectChars);\n const capSection = (\n label: string,\n body: string | null,\n limit: number,\n ): string => {\n const trimmedBody = body?.trim();\n if (!trimmedBody) return \"\";\n const safeLimit = Math.max(120, limit);\n const section = `${label}\\n\\n${trimmedBody}`;\n return section.length > safeLimit\n ? `${section.slice(0, safeLimit)}\\n\\n...(trimmed)\\n`\n : section;\n };\n\n const prioritiesSection = capSection(\n \"### Priorities\",\n priorities,\n Math.floor(max * 0.35),\n );\n const crossSignalsSection = capSection(\n \"### Latest Cross-Signals\",\n crossSignals,\n Math.floor(max * 0.35),\n );\n const fixedSections = [prioritiesSection, crossSignalsSection].filter(\n (section) => section.trim().length > 0,\n );\n const fixedPrefix = [\"## Shared Context\", ...fixedSections].join(\"\\n\\n\");\n const reserved = fixedPrefix.length + \"\\n\\n\".length;\n const roundtableBudget = Math.max(160, max - reserved);\n const roundtableSection = capSection(\n \"### Latest Roundtable\",\n roundtable,\n roundtableBudget,\n );\n const combined = [\n \"## Shared Context\",\n ...fixedSections,\n roundtableSection,\n ]\n .filter((s) => s.trim().length > 0)\n .join(\"\\n\\n\");\n\n const trimmed =\n combined.length > max\n ? combined.slice(0, max) + \"\\n\\n...(trimmed)\\n\"\n : combined;\n recordRecallSectionMetric({\n section: \"sharedCtx\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return trimmed.trim().length > 0 ? trimmed : null;\n })();\n\n // 1. Profile\n const profilePromise = (async (): Promise<string | null> => {\n if (!this.isRecallSectionEnabled(\"profile\")) return null;\n const t0 = Date.now();\n const profile = await profileStorage.readProfile();\n recordRecallSectionMetric({\n section: \"profile\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return profile || null;\n })();\n\n // 1p. Peer profile injection (issue #679 PR 3/5).\n // Reads the profile.md for the peer registered on this session and\n // injects the most-recently-updated N fields into context. Wrapped\n // in a try-catch (CLAUDE.md #13 — external I/O must not crash the\n // primary recall flow). Gate: `peerProfileRecallEnabled` must be\n // true AND `peerProfileRecallMaxFields` must be > 0 AND a peer ID\n // must be registered for this session (rule 30 — new\n // filters/transforms must have configuration gates).\n //\n // Issue #679 completion: side-channel annotation for recall X-ray.\n // We capture the peer id and injected-field count separately from\n // the promise result string so the xray snapshot builder can record\n // them without re-parsing the rendered section text.\n //\n // Three-state semantics (mirrors docs/peers.md X-ray contract):\n // undefined — feature off, no peer registered, or maxFields=0 (field\n // absent from snapshot — peerProfileInjection not set).\n // null — feature enabled + peer registered, but no profile or no\n // fields found (snapshot carries explicit null).\n // object — injection occurred (snapshot carries { peerId, fieldsInjected }).\n //\n // Cursor Bugbot (PR #764): must start as `undefined` so early-return\n // paths that never enter the feature-enabled branch leave the annotation\n // absent. Starting as `null` incorrectly sets peerProfileInjection:null\n // on the snapshot even when peerProfileRecallEnabled is false.\n let peerProfileXrayAnnotation:\n | { peerId: string; fieldsInjected: number }\n | null\n | undefined = undefined;\n const peerProfileRecallPromise = (async (): Promise<string | null> => {\n if (!this.config.peerProfileRecallEnabled) return null;\n if (this.config.peerProfileRecallMaxFields <= 0) return null;\n const peerId = this.getPeerIdForSession(sessionKey);\n if (!peerId) return null;\n const t0 = Date.now();\n try {\n const { readPeerProfile: _readPeerProfile } = await import(\"./peers/index.js\");\n const peerProfile = await _readPeerProfile(this.config.memoryDir, peerId);\n recordRecallSectionMetric({\n section: \"peerProfile\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n if (!peerProfile) {\n // Feature on + peer registered, but no profile written yet.\n // Three-state contract: explicit null = \"enabled but no profile\".\n peerProfileXrayAnnotation = null;\n return null;\n }\n const allFields = Object.entries(peerProfile.fields);\n if (allFields.length === 0) {\n // Profile exists but has no fields — same semantic as no profile.\n peerProfileXrayAnnotation = null;\n return null;\n }\n // Select the top-N most-recently-updated fields by consulting\n // provenance. Fields without provenance get epoch-0 ms so they\n // sort last (least recent).\n // Codex P2: parse ISO-8601 to epoch ms rather than comparing\n // strings. ISO-8601 strings with different timezone offsets\n // (e.g. \"2026-04-20T00:00:00+05:00\" vs \"2026-04-20T00:00:00Z\")\n // can order incorrectly under lexicographic comparison even\n // though they may refer to different instants. `Date.parse`\n // returns NaN on malformed input — we fall back to 0 (epoch)\n // so invalid timestamps sort last rather than causing NaN\n // comparison instability.\n const fieldsByRecency = allFields\n .map(([key, value]) => {\n const prov = peerProfile.provenance[key];\n // Find the most recent observedAt (epoch ms) across all\n // provenance entries for this field. Fall back to 0 if none\n // recorded or if all entries are malformed.\n let latestMs = 0;\n if (Array.isArray(prov) && prov.length > 0) {\n for (const p of prov) {\n if (typeof p.observedAt === \"string\") {\n const parsed = Date.parse(p.observedAt);\n if (Number.isFinite(parsed) && parsed > latestMs) {\n latestMs = parsed;\n }\n }\n }\n }\n return { key, value, latestMs };\n })\n // Descending: most-recently-updated first (rule 19 — sort\n // comparators must return 0 for equal items so use secondary key).\n .sort((a, b) => {\n if (b.latestMs !== a.latestMs) return b.latestMs - a.latestMs;\n return a.key < b.key ? -1 : a.key > b.key ? 1 : 0;\n });\n const capped = fieldsByRecency.slice(0, this.config.peerProfileRecallMaxFields);\n const lines = capped.map(({ key, value }) => `**${key}**: ${value}`);\n // Record xray annotation: peerId + how many fields were injected.\n peerProfileXrayAnnotation = { peerId, fieldsInjected: capped.length };\n return `## Peer Profile\\n\\n${lines.join(\"\\n\\n\")}`;\n } catch (err) {\n recordRecallSectionMetric({\n section: \"peerProfile\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: false,\n timing: `error(${err instanceof Error ? err.message : String(err)})`,\n });\n log.debug(`peer profile recall injection failed (non-fatal): ${err}`);\n return null;\n }\n })();\n\n // 1a. Identity continuity signals (v8.4)\n const identityContinuityPromise = (async () => {\n if (\n !this.isRecallSectionEnabled(\n \"identity-continuity\",\n this.config.identityContinuityEnabled === true,\n )\n )\n return null;\n const t0 = Date.now();\n const section = await this.buildIdentityContinuitySection({\n storage: profileStorage,\n recallMode,\n prompt: retrievalQuery,\n });\n recordRecallSectionMetric({\n section: \"identityContinuity\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const entityRetrievalPromise = (async (): Promise<string | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"entity-retrieval\",\n this.config.entityRetrievalEnabled,\n )\n )\n return null;\n if (!this.config.entityRetrievalEnabled) return null;\n const maxChars =\n this.getRecallSectionMaxChars(\"entity-retrieval\") ??\n this.config.entityRetrievalMaxChars;\n const maxHints =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxHints\") ??\n this.config.entityRetrievalMaxHints;\n const maxSupportingFacts =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxSupportingFacts\") ??\n this.config.entityRetrievalMaxSupportingFacts;\n const maxRelatedEntities =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxRelatedEntities\") ??\n this.config.entityRetrievalMaxRelatedEntities;\n const recentTurns =\n this.getRecallSectionNumber(\"entity-retrieval\", \"recentTurns\") ??\n this.config.entityRetrievalRecentTurns;\n if (maxChars === 0 || maxHints === 0 || maxSupportingFacts === 0) {\n recordRecallSectionMetric({\n section: \"entityRetrieval\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n const t0 = Date.now();\n const transcriptEntries = sessionKey\n ? await readRecentEntityTranscriptEntries(\n this.transcript.readRecent(\n entityRecentTranscriptLookbackHours,\n sessionKey,\n ),\n recentTurns,\n )\n : [];\n const section = await buildEntityRecallSection({\n config: this.config,\n storage: profileStorage,\n query: retrievalQuery,\n recallNamespaces,\n recentTurns,\n maxHints,\n maxSupportingFacts,\n maxRelatedEntities,\n maxChars,\n transcriptEntries,\n }).catch((err) => {\n log.warn(`entity retrieval build failed: ${err}`);\n return null;\n });\n recordRecallSectionMetric({\n section: \"entityRetrieval\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n // 1b. Knowledge Index (v7.0)\n const knowledgeIndexPromise = (async (): Promise<{\n result: string;\n cached: boolean;\n } | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"knowledge-index\",\n this.config.knowledgeIndexEnabled,\n )\n )\n return null;\n if (!this.config.knowledgeIndexEnabled) return null;\n const t0 = Date.now();\n try {\n const ki = await this.storage.buildKnowledgeIndex(this.config, {\n maxEntities: this.getRecallSectionNumber(\n \"knowledge-index\",\n \"maxEntities\",\n ),\n maxChars: this.getRecallSectionNumber(\"knowledge-index\", \"maxChars\"),\n });\n recordRecallSectionMetric({\n section: \"ki\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: ki.cached ? \"stale\" : \"fresh\",\n success: true,\n timing: `${Date.now() - t0}ms${ki.cached ? \" (cached)\" : \"\"}`,\n });\n return ki.result ? ki : null;\n } catch (err) {\n recordRecallSectionMetric({\n section: \"ki\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: `${Date.now() - t0}ms (err)`,\n });\n log.warn(`Knowledge Index build failed: ${err}`);\n return null;\n }\n })();\n\n // 1c. Verbatim artifacts (v8.0 phase 1)\n const artifactsPromise = (async (): Promise<MemoryFile[]> => {\n if (\n !this.isRecallSectionEnabled(\n \"verbatim-artifacts\",\n this.config.verbatimArtifactsEnabled === true,\n )\n )\n return [];\n if (!this.config.verbatimArtifactsEnabled) return [];\n const t0 = Date.now();\n const targetCount = computeArtifactRecallLimit(\n recallMode,\n recallResultLimit,\n this.config.verbatimArtifactsMaxRecall,\n );\n if (targetCount <= 0) {\n recordRecallSectionMetric({\n section: \"artifacts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return [];\n }\n const results = await this.recallArtifactsAcrossNamespaces(\n retrievalQuery,\n recallNamespaces,\n targetCount,\n );\n\n recordRecallSectionMetric({\n section: \"artifacts\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results;\n })();\n\n const objectiveStatePromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.objectiveStateMemoryEnabled ||\n !this.config.objectiveStateRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"objective-state\",\n this.config.objectiveStateRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"objective-state\", \"maxResults\") ?? 4;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchObjectiveStateSnapshots({\n memoryDir: this.config.memoryDir,\n objectiveStateStoreDir: this.config.objectiveStateStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatObjectiveStateResults(results)\n : null;\n })();\n\n const causalTrajectoryPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.causalTrajectoryMemoryEnabled ||\n !this.config.causalTrajectoryRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"causal-trajectories\",\n this.config.causalTrajectoryRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"causal-trajectories\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchCausalTrajectories({\n memoryDir: this.config.memoryDir,\n causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatCausalTrajectoryResults(results)\n : null;\n })();\n\n const cmcRetrievalPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.cmcRetrievalEnabled ||\n !this.isRecallSectionEnabled(\n \"cmc-causal-chains\",\n this.config.cmcRetrievalEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n try {\n const { retrieveCausalChains } = await import(\"./causal-retrieval.js\");\n const section = await retrieveCausalChains({\n memoryDir: this.config.memoryDir,\n causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,\n query: retrievalQuery,\n sessionKey,\n config: {\n maxDepth: this.config.cmcRetrievalMaxDepth,\n maxChars: this.config.cmcRetrievalMaxChars,\n counterfactualBoost: this.config.cmcRetrievalCounterfactualBoost,\n },\n });\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n } catch (err) {\n log.warn(\"[cmc] causal retrieval failed (non-fatal)\", err);\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: \"error\",\n });\n return null;\n }\n })();\n\n const calibrationPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.calibrationEnabled ||\n !this.isRecallSectionEnabled(\n \"calibration-rules\",\n this.config.calibrationEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n try {\n const { getCalibrationRulesForRecall, buildCalibrationRecallSection } =\n await import(\"./calibration.js\");\n const rules = await getCalibrationRulesForRecall(this.config.memoryDir);\n if (rules.length === 0) {\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(no-rules)\",\n });\n return null;\n }\n const section = buildCalibrationRecallSection(\n rules.slice(0, this.config.calibrationMaxRulesPerRecall),\n retrievalQuery,\n this.config.calibrationMaxChars,\n );\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n } catch (err) {\n log.warn(\"[calibration] recall section failed (non-fatal)\", err);\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: \"error\",\n });\n return null;\n }\n })();\n\n const trustZonePromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.trustZonesEnabled ||\n !this.config.trustZoneRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"trust-zones\",\n this.config.trustZoneRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"trust-zones\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchTrustZoneRecords({\n memoryDir: this.config.memoryDir,\n trustZoneStoreDir: this.config.trustZoneStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0 ? this.formatTrustZoneResults(results) : null;\n })();\n\n const harmonicRetrievalAbort = createEnrichmentAbortHandle(\n options.abortSignal,\n );\n const harmonicRetrievalPromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.harmonicRetrievalEnabled ||\n !this.isRecallSectionEnabled(\n \"harmonic-retrieval\",\n this.config.harmonicRetrievalEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"harmonic-retrieval\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchHarmonicRetrieval({\n memoryDir: this.config.memoryDir,\n abstractionNodeStoreDir: this.config.abstractionNodeStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n anchorsEnabled: this.config.abstractionAnchorsEnabled,\n abortSignal: harmonicRetrievalAbort.signal,\n });\n\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatHarmonicRetrievalResults(results)\n : null;\n })().finally(() => harmonicRetrievalAbort.dispose()),\n () => harmonicRetrievalAbort.cancel(),\n );\n\n // Verified recall and semantic rules both need readAllMemories().\n // Instead of a shared preload (which has namespace/dir mismatch issues),\n // each subsystem calls readAllMemories() on its correct storage instance.\n // The process-level memory cache (keyed by baseDir + memoryStatusVersion)\n // ensures only one actual disk scan happens — subsequent calls return\n // from cache in <1ms.\n\n const verifiedRecallPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.verifiedRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"verified-episodes\",\n this.config.verifiedRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"verified-episodes\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const VERIFIED_RECALL_TIMEOUT_MS = 15_000;\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const results = await Promise.race([\n searchVerifiedEpisodes({\n memoryDir: profileStorage.dir,\n query: retrievalQuery,\n maxResults,\n boxRecallDays: this.config.boxRecallDays,\n }),\n new Promise<[]>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve([]),\n VERIFIED_RECALL_TIMEOUT_MS,\n );\n }),\n ]).catch(() => [] as VerifiedEpisodeResult[]);\n if (timeoutHandle) clearTimeout(timeoutHandle);\n\n const durationMs = Date.now() - t0;\n if (durationMs >= VERIFIED_RECALL_TIMEOUT_MS) {\n log.debug(\n `verified recall: timed out after ${VERIFIED_RECALL_TIMEOUT_MS}ms`,\n );\n }\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs,\n deadlineMs: VERIFIED_RECALL_TIMEOUT_MS,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatVerifiedEpisodeResults(results)\n : null;\n })();\n\n const verifiedRulesPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.semanticRuleVerificationEnabled ||\n !this.isRecallSectionEnabled(\n \"verified-rules\",\n this.config.semanticRuleVerificationEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"verified-rules\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const VERIFIED_RULES_TIMEOUT_MS = 15_000;\n let rulesTimeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const results = await Promise.race([\n searchVerifiedSemanticRules({\n memoryDir: this.config.memoryDir,\n query: retrievalQuery,\n maxResults,\n }),\n new Promise<[]>((resolve) => {\n rulesTimeoutHandle = setTimeout(\n () => resolve([]),\n VERIFIED_RULES_TIMEOUT_MS,\n );\n }),\n ]).catch(() => [] as VerifiedSemanticRuleResult[]);\n if (rulesTimeoutHandle) clearTimeout(rulesTimeoutHandle);\n\n const durationMs = Date.now() - t0;\n if (durationMs >= VERIFIED_RULES_TIMEOUT_MS) {\n log.debug(\n `verified rules: timed out after ${VERIFIED_RULES_TIMEOUT_MS}ms`,\n );\n }\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs,\n deadlineMs: VERIFIED_RULES_TIMEOUT_MS,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatVerifiedSemanticRuleResults(results)\n : null;\n })();\n\n const workProductsPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.creationMemoryEnabled ||\n !this.config.workProductRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"work-products\",\n this.config.workProductRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"work-products\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchWorkProductLedgerEntries({\n memoryDir: this.config.memoryDir,\n workProductLedgerDir: this.config.workProductLedgerDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0 ? this.formatWorkProductResults(results) : null;\n })();\n\n const queryAwarePrefilterPromise =\n (async (): Promise<QueryAwarePrefilter> => {\n const t0 = Date.now();\n if (!this.config.queryAwareIndexingEnabled || !prompt.trim()) {\n recordRecallSectionMetric({\n section: \"queryAware\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return {\n candidatePaths: null,\n temporalFromDate: null,\n matchedTags: [],\n expandedTags: [],\n combination: \"none\",\n filteredToFullSearch: false,\n };\n }\n\n const prefilter = await this.buildQueryAwarePrefilter(\n retrievalQuery,\n recallNamespaces,\n );\n const candidateCount = prefilter.candidatePaths?.size ?? 0;\n const temporalLabel = prefilter.temporalFromDate ?? \"-\";\n const tagLabel =\n prefilter.expandedTags.length > 0\n ? prefilter.expandedTags.join(\"|\")\n : \"-\";\n const fallbackLabel = prefilter.filteredToFullSearch\n ? \"/full-search\"\n : \"\";\n recordRecallSectionMetric({\n section: \"queryAware\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: prefilter.filteredToFullSearch ? \"stale\" : \"fresh\",\n success: true,\n timing: `${Date.now() - t0}ms(${prefilter.combination}${fallbackLabel};count=${candidateCount};time=${temporalLabel};tags=${tagLabel})`,\n });\n return prefilter;\n })();\n\n // 2. QMD search (the slow part — runs in parallel with preamble)\n type QmdPhaseResult = {\n memoryResultsLists: QmdSearchResult[][];\n globalResults: QmdSearchResult[];\n /** Top QMD score BEFORE contextual weight scaling from the agent merge.\n * Used by the confidence gate so that enabling parallel retrieval doesn't\n * silently lower scores below the calibrated gate threshold. */\n preAugmentTopScore: number;\n /** Max score from direct + temporal agents (post-weight) BEFORE merge.\n * Included in the confidence gate so that strong specialized hits (e.g.\n * an exact entity-name match) are not discarded just because the QMD\n * contextual pass returned a weak result. */\n maxSpecializedScore: number;\n } | null;\n\n const qmdEnrichmentAbort = createEnrichmentAbortHandle(options.abortSignal);\n const qmdPromise = observeEnrichmentPromise(\n (async (): Promise<QmdPhaseResult> => {\n const t0 = Date.now();\n if (recallResultLimit <= 0) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const qmdCacheKey = buildQmdRecallCacheKey({\n query: retrievalQuery,\n namespaces: recallNamespaces,\n recallMode,\n maxResults: qmdFetchLimit,\n memoryDir: this.config.memoryDir,\n searchOptions: qmdSearchOptions,\n });\n const cachedQmd = getCachedQmdRecall<Exclude<QmdPhaseResult, null>>(\n qmdCacheKey,\n {\n freshTtlMs: this.config.qmdRecallCacheTtlMs ?? 60_000,\n staleTtlMs: this.config.qmdRecallCacheStaleTtlMs ?? 10 * 60_000,\n },\n );\n const staleQmdFallback =\n cachedQmd?.source === \"stale\" ? cachedQmd : null;\n if (cachedQmd?.source === \"fresh\") {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: cachedQmd.source,\n success: true,\n timing: `${Math.max(0, Math.round(cachedQmd.ageMs))}ms-cache`,\n });\n return cachedQmd.value;\n }\n\n if (!this.qmd.isAvailable()) {\n const now = Date.now();\n const QMD_REPROBE_COOLDOWN_MS = 60_000;\n if (\n this.lastQmdReprobeAtMs &&\n now - this.lastQmdReprobeAtMs < QMD_REPROBE_COOLDOWN_MS\n ) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(reprobe-cooldown:${Math.max(0, Math.round(staleQmdFallback.ageMs))}ms)`,\n });\n return staleQmdFallback.value;\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(reprobe-cooldown)\",\n });\n return null;\n }\n this.lastQmdReprobeAtMs = now;\n const reprobed = await this.qmd.probe();\n if (!reprobed) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(reprobe-failed:${Math.max(0, Math.round(staleQmdFallback.ageMs))}ms)`,\n });\n return staleQmdFallback.value;\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n log.debug(\n `Search skip (re-probe failed): ${this.qmd.debugStatus()}`,\n );\n return null;\n }\n log.info(`QMD re-probe succeeded: ${this.qmd.debugStatus()}`);\n }\n\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const maxPerAgent = this.config.parallelMaxResultsPerAgent;\n const specializedAgentPromise: Promise<\n [ParallelSearchResult[], ParallelSearchResult[]]\n > | null =\n this.config.parallelRetrievalEnabled && maxPerAgent > 0\n ? Promise.all([\n shouldRunAgent(\"direct\", retrievalQuery, 0)\n ? runDirectAgent(\n retrievalQuery,\n profileStorage.dir,\n maxPerAgent,\n ).catch((err) => {\n log.debug(`DirectAgent pre-start failed: ${err}`);\n return [] as ParallelSearchResult[];\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n shouldRunAgent(\"temporal\", retrievalQuery, 0)\n ? runTemporalAgent(\n retrievalQuery,\n this.config.memoryDir,\n maxPerAgent,\n queryAwarePrefilter.candidatePaths,\n ).catch((err) => {\n log.debug(`TemporalAgent pre-start failed: ${err}`);\n return [] as ParallelSearchResult[];\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n ])\n : null;\n\n try {\n const filteredResults =\n await this.fetchQmdMemoryResultsWithArtifactTopUp(\n retrievalQuery,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n queryAwarePrefilter,\n searchOptions: qmdSearchOptions,\n abortSignal: qmdEnrichmentAbort.signal,\n onDebugSnapshot: async (snapshot) => {\n await this.recordLastQmdRecallSnapshot({\n storage: profileStorage,\n snapshot,\n });\n },\n },\n );\n\n const preAugmentTopScore =\n filteredResults.length > 0\n ? Math.max(...filteredResults.map((r) => r.score))\n : 0;\n let augmentedResults = filteredResults;\n let maxSpecializedScore = 0;\n if (this.config.parallelRetrievalEnabled && specializedAgentPromise) {\n try {\n const [directResults, temporalResults] =\n await specializedAgentPromise;\n if (filteredResults.length > 0) {\n const w = this.config.parallelAgentWeights;\n maxSpecializedScore = Math.max(\n directResults.length > 0\n ? Math.max(...directResults.map((r) => r.score * w.direct))\n : 0,\n temporalResults.length > 0\n ? Math.max(\n ...temporalResults.map((r) => r.score * w.temporal),\n )\n : 0,\n );\n const lifecycleHeadroom =\n this.config.parallelMaxResultsPerAgent * 2;\n augmentedResults = await mergeWithAgentResults(\n filteredResults,\n directResults,\n temporalResults,\n this.config.parallelAgentWeights,\n qmdFetchLimit + lifecycleHeadroom,\n );\n }\n } catch (err) {\n log.debug(\n `parallelRetrieval augmentation failed, using base results: ${err}`,\n );\n maxSpecializedScore = 0;\n }\n }\n\n const result = {\n memoryResultsLists: [augmentedResults],\n globalResults: [],\n preAugmentTopScore,\n maxSpecializedScore,\n };\n if (\n augmentedResults.length > 0 ||\n result.globalResults.length > 0\n ) {\n setCachedQmdRecall(qmdCacheKey, result, {\n maxEntries: this.config.qmdRecallCacheMaxEntries ?? 128,\n });\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return result;\n } catch (err) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(${err instanceof Error ? err.message : String(err)})`,\n });\n return staleQmdFallback.value;\n }\n throw err;\n }\n })()\n .catch((err): QmdPhaseResult => {\n if (options.abortSignal?.aborted) {\n log.debug(\n `recall phase-1 enrichment [qmd]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n log.warn(\n `recall phase-1 enrichment [qmd] failed open: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n })\n .finally(() => qmdEnrichmentAbort.dispose()),\n () => qmdEnrichmentAbort.cancel(),\n );\n\n const transcriptPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.transcriptEnabled ||\n !this.isRecallSectionEnabled(\"transcript\", true)\n ) {\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const transcriptMaxTokens =\n this.getRecallSectionNumber(\"transcript\", \"maxTokens\") ??\n this.config.maxTranscriptTokens;\n const transcriptMaxTurns =\n this.getRecallSectionNumber(\"transcript\", \"maxTurns\") ??\n this.config.maxTranscriptTurns;\n const transcriptLookbackHours =\n this.getRecallSectionNumber(\"transcript\", \"lookbackHours\") ??\n this.config.transcriptRecallHours;\n if (\n transcriptMaxTokens === 0 ||\n transcriptMaxTurns === 0 ||\n transcriptLookbackHours === 0\n ) {\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n let section: string | null = null;\n // Try checkpoint first (post-compaction recovery)\n let checkpointInjected = false;\n if (this.config.checkpointEnabled) {\n const checkpoint = await this.transcript.loadCheckpoint(sessionKey);\n log.debug(\n `recall: checkpoint loaded, turns=${checkpoint?.turns?.length ?? 0}`,\n );\n if (checkpoint && checkpoint.turns.length > 0) {\n const formatted = this.transcript.formatForRecall(\n checkpoint.turns,\n transcriptMaxTokens,\n );\n if (formatted) {\n section = `## Working Context (Recovered)\\n\\n${formatted}`;\n checkpointInjected = true;\n // Clear checkpoint after injection\n await this.transcript.clearCheckpoint();\n }\n }\n }\n\n if (!checkpointInjected) {\n const entries = await this.transcript.readRecent(\n transcriptLookbackHours,\n sessionKey,\n );\n log.debug(\n `recall: read ${entries.length} transcript entries for sessionKey=${sessionKey}`,\n );\n\n // Apply max turns cap\n const cappedEntries = entries.slice(-transcriptMaxTurns);\n if (cappedEntries.length > 0) {\n log.debug(\n `recall: injecting ${cappedEntries.length} transcript entries`,\n );\n const formatted = this.transcript.formatForRecall(\n cappedEntries,\n transcriptMaxTokens,\n );\n if (formatted) section = formatted;\n }\n }\n\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n // Compaction reset runs independently of transcript — it must work even when\n // transcriptEnabled=false, since compaction recovery is a separate concern.\n const compactionPromise = (async (): Promise<string | null> => {\n // Always clean up per-session workspace selections, even if the feature is off,\n // to prevent the Map from accumulating stale entries on long-running gateways.\n const effectiveSessionKey = sessionKey ?? \"default\";\n const compactionWorkspaceDir =\n this._recallWorkspaceOverrides.get(effectiveSessionKey);\n this._recallWorkspaceOverrides.delete(effectiveSessionKey);\n\n if (!this.config.compactionResetEnabled) return null;\n\n const workspaceDir =\n compactionWorkspaceDir ||\n this.config.workspaceDir ||\n defaultWorkspaceDir();\n const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);\n const signalPath = path.join(\n workspaceDir,\n `.compaction-reset-signal-${safeSessionKey}`,\n );\n const bootPath = path.join(workspaceDir, \"BOOT.md\");\n\n try {\n const signalStat = await stat(signalPath).catch(() => null);\n if (!signalStat) return null;\n\n const signalAge = Date.now() - signalStat.mtimeMs;\n const signalData = JSON.parse(await readFile(signalPath, \"utf-8\"));\n\n // Validate signal belongs to this session (defense-in-depth: filename\n // is already per-session, but the sessionKey inside provides a second check).\n // Use strict !== so missing/null sessionKey also fails validation.\n if (signalData.sessionKey !== effectiveSessionKey) {\n log.debug(\n `recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} — skipping`,\n );\n return null;\n }\n\n if (signalAge >= COMPACTION_SIGNAL_MAX_AGE_MS) {\n log.debug(\n `recall: stale compaction signal (${Math.round(signalAge / 1000)}s old), skipping`,\n );\n await unlink(signalPath).catch(() => {});\n return null;\n }\n\n // Signal is fresh and belongs to this session — build recovery context\n let section = \"\\n\\n## Session Recovery (Post-Compaction)\\n\\n\";\n section += `⚠️ A compaction occurred at ${signalData.compactedAt} and this is a fresh session.\\n\\n`;\n\n try {\n const bootContent = await readFile(bootPath, \"utf-8\");\n section += \"### BOOT.md (working state before compaction)\\n\\n\";\n section += bootContent + \"\\n\";\n } catch {\n section += \"### ⚠️ BOOT.md is MISSING\\n\\n\";\n section +=\n \"The memory flush may not have written BOOT.md before compaction. \";\n section += \"Ask the user what you were working on — do not guess.\\n\";\n }\n\n log.info(\n `recall: injected compaction reset context for ${effectiveSessionKey}`,\n );\n await unlink(signalPath).catch(() => {});\n return section;\n } catch (err) {\n log.debug(\"recall: compaction signal check failed:\", err);\n // Remove corrupt/unreadable signal files so they don't cause repeated\n // parse failures on every recall() until the 1-hour sweep runs.\n await unlink(signalPath).catch(() => {});\n return null;\n }\n })();\n\n const summariesPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.hourlySummariesEnabled ||\n !sessionKey ||\n !this.isRecallSectionEnabled(\"summaries\", true)\n ) {\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const summariesLookbackHours =\n this.getRecallSectionNumber(\"summaries\", \"lookbackHours\") ??\n this.config.summaryRecallHours;\n const summariesMaxCount =\n this.getRecallSectionNumber(\"summaries\", \"maxCount\") ??\n this.config.maxSummaryCount;\n if (summariesLookbackHours <= 0 || summariesMaxCount <= 0) {\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const summaries = await this.summarizer.readRecent(\n sessionKey,\n summariesLookbackHours,\n );\n const cappedSummaries = summaries.slice(0, summariesMaxCount);\n const section =\n cappedSummaries.length > 0\n ? this.summarizer.formatForRecall(cappedSummaries, summariesMaxCount)\n : null;\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const nativeKnowledgeAbort = createEnrichmentAbortHandle(\n options.abortSignal,\n );\n const nativeKnowledgePromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.nativeKnowledge?.enabled ||\n !this.isRecallSectionEnabled(\n \"native-knowledge\",\n this.config.nativeKnowledge.enabled,\n )\n ) {\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n if (\n this.config.nativeKnowledge.maxResults === 0 ||\n this.config.nativeKnowledge.maxChars === 0\n ) {\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const chunks = await collectNativeKnowledgeChunks({\n workspaceDir: this.config.workspaceDir,\n memoryDir: this.config.memoryDir,\n config: this.config.nativeKnowledge,\n recallNamespaces: this.config.namespacesEnabled\n ? recallNamespaces\n : undefined,\n defaultNamespace: this.config.defaultNamespace,\n abortSignal: nativeKnowledgeAbort.signal,\n }).catch(() => []);\n const results = searchNativeKnowledge({\n query: retrievalQuery,\n chunks,\n maxResults:\n this.getRecallSectionNumber(\"native-knowledge\", \"maxResults\") ??\n this.config.nativeKnowledge.maxResults,\n });\n const section = formatNativeKnowledgeSection({\n results,\n maxChars:\n this.getRecallSectionNumber(\"native-knowledge\", \"maxChars\") ??\n this.config.nativeKnowledge.maxChars,\n });\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })().finally(() => nativeKnowledgeAbort.dispose()),\n () => nativeKnowledgeAbort.cancel(),\n );\n\n const conversationRecallPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.conversationIndexEnabled ||\n queryPolicy.skipConversationRecall ||\n !this.isRecallSectionEnabled(\"conversation-recall\", true)\n ) {\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n\n const topKOverride = this.getRecallSectionNumber(\n \"conversation-recall\",\n \"topK\",\n );\n if (topKOverride === 0) {\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(topK=0)\",\n });\n return null;\n }\n\n const startedAtMs = Date.now();\n const timeoutMs = Math.max(\n 200,\n this.getRecallSectionNumber(\"conversation-recall\", \"timeoutMs\") ??\n this.config.conversationRecallTimeoutMs,\n );\n const topK = Math.max(\n 1,\n topKOverride ?? this.config.conversationRecallTopK,\n );\n const maxChars = Math.max(\n 400,\n this.getRecallSectionNumber(\"conversation-recall\", \"maxChars\") ??\n this.config.conversationRecallMaxChars,\n );\n\n const results = (await Promise.race([\n this.searchConversationRecallResults(retrievalQuery, topK),\n new Promise<[]>((resolve) => setTimeout(() => resolve([]), timeoutMs)),\n ]).catch(() => [])) as Array<{\n path: string;\n snippet: string;\n score: number;\n }>;\n\n const durationMs = Date.now() - startedAtMs;\n if (durationMs >= timeoutMs) {\n log.debug(`conversation recall: timed out after ${timeoutMs}ms`);\n }\n\n const section = this.formatConversationRecallSection(results, maxChars);\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: timeoutMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const procedureRecallPromise = (async (): Promise<string | null> => {\n if (this.config.procedural?.enabled !== true) return null;\n if (!this.isRecallSectionEnabled(\"procedure-recall\", true)) return null;\n try {\n return await buildProcedureRecallSection(\n profileStorage,\n retrievalQuery,\n this.config,\n );\n } catch (err) {\n log.debug(\n `procedure-recall: failed open: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n })();\n\n const compoundingPromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.compounding ||\n !this.config.compoundingInjectEnabled ||\n !this.isRecallSectionEnabled(\"compounding\", true)\n ) {\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxPatterns =\n this.getRecallSectionNumber(\"compounding\", \"maxPatterns\") ?? 40;\n const maxRubrics =\n this.getRecallSectionNumber(\"compounding\", \"maxRubrics\") ?? 4;\n if (maxPatterns === 0 && maxRubrics === 0) {\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n const section = await this.compounding.buildRecallSection(\n retrievalQuery,\n { maxPatterns, maxRubrics },\n );\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })(),\n );\n\n // Start memory-boxes read in parallel with the rest of phase-1 (it can take\n // several seconds on large box directories due to sequential I/O). We kick it\n // off here so it overlaps with QMD and other concurrent work rather than\n // running sequentially in phase-2 and blocking assembly.\n const recentBoxesPromise: Promise<BoxFrontmatter[]> =\n this.isRecallSectionEnabled(\n \"memory-boxes\",\n this.config.memoryBoxesEnabled === true,\n ) &&\n this.config.memoryBoxesEnabled &&\n this.config.boxRecallDays > 0\n ? this.boxBuilderFor(profileStorage)\n .readRecentBoxes(this.config.boxRecallDays)\n .catch(() => [] as BoxFrontmatter[])\n : Promise.resolve([] as BoxFrontmatter[]);\n\n // --- Wait for core sections first, then bounded enrichment ---\n this.profiler.startSpan(\"phase-1-parallel\", profileTraceId);\n const phase1Start = Date.now();\n log.info(\n `recall phase-1: starting parallel work at +${phase1Start - recallStart}ms`,\n );\n const [\n sharedCtx,\n profile,\n identityContinuity,\n entityRetrievalSection,\n kiResult,\n artifacts,\n objectiveStateSection,\n causalTrajectorySection,\n cmcCausalChainsSection,\n calibrationSection,\n procedureRecallSection,\n trustZoneSection,\n verifiedRecallSection,\n verifiedRulesSection,\n workProductsSection,\n transcriptSection,\n compactionSection,\n summariesSection,\n conversationRecallSection,\n peerProfileSection,\n ] = await raceRecallAbort(\n Promise.all(\n (\n [\n [\"shared\", sharedContextPromise],\n [\"profile\", profilePromise],\n [\"identity\", identityContinuityPromise],\n [\"entity\", entityRetrievalPromise],\n [\"ki\", knowledgeIndexPromise],\n [\"artifacts\", artifactsPromise],\n [\"objState\", objectiveStatePromise],\n [\"causalTraj\", causalTrajectoryPromise],\n [\"cmc\", cmcRetrievalPromise],\n [\"calibration\", calibrationPromise],\n [\"procedureRecall\", procedureRecallPromise],\n [\"trustZone\", trustZonePromise],\n [\"verifiedRecall\", verifiedRecallPromise],\n [\"verifiedRules\", verifiedRulesPromise],\n [\"workProducts\", workProductsPromise],\n [\"transcript\", transcriptPromise],\n [\"compaction\", compactionPromise],\n [\"summaries\", summariesPromise],\n [\"convRecall\", conversationRecallPromise],\n [\"peerProfile\", peerProfileRecallPromise],\n ] as const\n ).map(([name, p]) =>\n (p as Promise<unknown>).then((v) => {\n log.debug(\n `recall phase-1 core [${name}]: resolved at +${Date.now() - phase1Start}ms`,\n );\n return v;\n }),\n ),\n ) as Promise<\n [\n typeof sharedContextPromise extends Promise<infer T> ? T : never,\n typeof profilePromise extends Promise<infer T> ? T : never,\n typeof identityContinuityPromise extends Promise<infer T> ? T : never,\n typeof entityRetrievalPromise extends Promise<infer T> ? T : never,\n typeof knowledgeIndexPromise extends Promise<infer T> ? T : never,\n typeof artifactsPromise extends Promise<infer T> ? T : never,\n typeof objectiveStatePromise extends Promise<infer T> ? T : never,\n typeof causalTrajectoryPromise extends Promise<infer T> ? T : never,\n typeof cmcRetrievalPromise extends Promise<infer T> ? T : never,\n typeof calibrationPromise extends Promise<infer T> ? T : never,\n typeof procedureRecallPromise extends Promise<infer T> ? T : never,\n typeof trustZonePromise extends Promise<infer T> ? T : never,\n typeof verifiedRecallPromise extends Promise<infer T> ? T : never,\n typeof verifiedRulesPromise extends Promise<infer T> ? T : never,\n typeof workProductsPromise extends Promise<infer T> ? T : never,\n typeof transcriptPromise extends Promise<infer T> ? T : never,\n typeof compactionPromise extends Promise<infer T> ? T : never,\n typeof summariesPromise extends Promise<infer T> ? T : never,\n typeof conversationRecallPromise extends Promise<infer T> ? T : never,\n typeof peerProfileRecallPromise extends Promise<infer T> ? T : never,\n ]\n >,\n options.abortSignal,\n \"recall aborted during phase-one preamble\",\n );\n\n this.profiler.endSpan(\"phase-1-parallel\", profileTraceId);\n log.info(\n `recall phase-1: core work done at +${Date.now() - recallStart}ms ` +\n `(phase took ${Date.now() - phase1Start}ms); continuing with incremental enrichment assembly`,\n );\n throwIfRecallAborted(options.abortSignal);\n\n const enrichmentAssemblyDeadlineAtMs =\n enrichmentSectionDeadlineMs > 0\n ? Date.now() + enrichmentSectionDeadlineMs\n : null;\n\n const awaitEnrichmentSection = async <T>(\n name: string,\n promise: ObservedDeferredEnrichmentPromise<T>,\n ): Promise<T | null> => {\n const finalizeEnrichmentOutcome = (\n outcome: DeferredEnrichmentOutcome<T>,\n ): T | null => {\n if (outcome.status === \"resolved\") {\n log.debug(\n `recall phase-1 enrichment [${name}]: resolved at +${Date.now() - phase1Start}ms`,\n );\n return outcome.value;\n }\n\n if (options.abortSignal?.aborted) {\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n log.warn(\n `recall phase-1 enrichment [${name}] failed open: ` +\n `${outcome.error instanceof Error ? outcome.error.message : String(outcome.error)}`,\n );\n return null;\n };\n\n if (options.abortSignal?.aborted) {\n promise.cancel();\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutMs =\n enrichmentAssemblyDeadlineAtMs === null\n ? null\n : Math.max(0, enrichmentAssemblyDeadlineAtMs - Date.now());\n if (timeoutMs === 0) {\n const settledOutcome = promise.getSettledOutcome();\n if (settledOutcome) {\n log.debug(\n `recall phase-1 enrichment [${name}]: consumed already-settled result after shared ${enrichmentSectionDeadlineMs}ms budget expired ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n return finalizeEnrichmentOutcome(settledOutcome);\n }\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after shared ${enrichmentSectionDeadlineMs}ms budget expired ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n promise.cancel();\n return null;\n }\n\n const outcome = await (timeoutMs !== null\n ? Promise.race<DeferredEnrichmentOutcome<T> | { status: \"timed_out\" }>([\n promise,\n new Promise<{ status: \"timed_out\" }>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve({ status: \"timed_out\" }),\n timeoutMs,\n );\n }),\n ])\n : promise);\n if (timeoutHandle) clearTimeout(timeoutHandle);\n\n if (outcome.status === \"timed_out\") {\n log.debug(\n `recall phase-1 enrichment [${name}]: timed out within shared ${enrichmentSectionDeadlineMs}ms budget ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n promise.cancel();\n return null;\n }\n\n return finalizeEnrichmentOutcome(outcome);\n };\n\n // --- Phase 2: Assemble sections in correct order ---\n this.profiler.startSpan(\"assembly\", profileTraceId);\n\n // 0. Shared context\n if (sharedCtx)\n this.appendRecallSection(sectionBuckets, \"shared-context\", sharedCtx);\n\n // 0a. Explicit cue evidence\n const explicitCueMaxChars =\n this.getRecallSectionMaxChars(\"explicit-cue\") ??\n this.config.explicitCueRecallMaxChars;\n if (\n this.config.explicitCueRecallEnabled &&\n this.isRecallSectionEnabled(\"explicit-cue\") &&\n explicitCueMaxChars !== 0 &&\n this.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n try {\n const explicitCueSection = await buildExplicitCueRecallSection({\n engine: this.lcmEngine,\n sessionId: sessionKey,\n query: retrievalQuery,\n maxChars: explicitCueMaxChars,\n maxReferences:\n this.getRecallSectionNumber(\"explicit-cue\", \"maxResults\") ??\n this.config.explicitCueRecallMaxReferences,\n });\n if (explicitCueSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"explicit-cue\",\n explicitCueSection,\n );\n }\n } catch (err) {\n log.debug(`Explicit cue recall assembly error: ${err}`);\n }\n }\n\n // 1. Profile\n if (profile)\n this.appendRecallSection(\n sectionBuckets,\n \"profile\",\n `## User Profile\\n\\n${profile}`,\n );\n\n // 1p. Peer profile (issue #679 PR 3/5)\n // Codex P2 (PR #764): only finalize the xray annotation when the section\n // was actually appended — appendRecallSection may drop it (disabled,\n // maxChars===0). We clear the annotation when the section is dropped so\n // the xray snapshot never reports injection that didn't happen.\n if (peerProfileSection) {\n const peerSectionAppended = this.appendRecallSection(\n sectionBuckets,\n \"peer-profile\",\n peerProfileSection,\n );\n if (!peerSectionAppended) {\n // Section was gated out — treat as null (feature on + peer registered,\n // but no context actually injected).\n peerProfileXrayAnnotation = null;\n }\n }\n\n // 1-pre. Calibration rules (injected early so model sees adjustments first)\n if (calibrationSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"calibration-rules\",\n calibrationSection,\n );\n }\n\n if (procedureRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"procedure-recall\",\n procedureRecallSection,\n );\n }\n\n // 1a. Identity continuity\n if (identityContinuity) {\n this.appendRecallSection(\n sectionBuckets,\n \"identity-continuity\",\n identityContinuity.section,\n );\n identityInjectionModeUsed = identityContinuity.mode;\n identityInjectedChars = identityContinuity.injectedChars;\n identityInjectionTruncated = identityContinuity.truncated;\n }\n\n if (entityRetrievalSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"entity-retrieval\",\n entityRetrievalSection,\n );\n }\n\n // 1b. Knowledge Index\n if (kiResult?.result) {\n this.appendRecallSection(\n sectionBuckets,\n \"knowledge-index\",\n kiResult.result,\n );\n log.debug(\n `Knowledge Index: ${kiResult.result.split(\"\\n\").length - 4} entities, ${kiResult.result.length} chars${kiResult.cached ? \" (cached)\" : \"\"}`,\n );\n }\n\n const nativeKnowledgeSection = await awaitEnrichmentSection(\n \"nativeKnowledge\",\n nativeKnowledgePromise,\n );\n if (nativeKnowledgeSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"native-knowledge\",\n nativeKnowledgeSection,\n );\n }\n\n // 1c. Verbatim artifacts (quote-first anchors)\n if (artifacts.length > 0) {\n const lines = artifacts.map((a) => {\n const artifactType = a.frontmatter.artifactType ?? \"fact\";\n const createdRaw =\n typeof a.frontmatter.created === \"string\"\n ? a.frontmatter.created\n : \"\";\n const created = createdRaw\n ? createdRaw.slice(0, 19).replace(\"T\", \" \")\n : \"unknown-time\";\n return `- [${artifactType}] \"${this.truncateArtifactForRecall(a.content)}\" (${created})`;\n });\n this.appendRecallSection(\n sectionBuckets,\n \"verbatim-artifacts\",\n `## Verbatim Artifacts\\n\\n${lines.join(\"\\n\")}`,\n );\n }\n\n // 1d. Memory Boxes (topic continuity windows, v8.0 Phase 2A)\n // recentBoxesPromise was kicked off before phase-1 so it ran concurrently.\n {\n const recentBoxes = await recentBoxesPromise;\n if (recentBoxes.length > 0) {\n const boxLines = recentBoxes.slice(0, 5).map((b: BoxFrontmatter) => {\n const sealedDate = b.sealedAt\n ? b.sealedAt.slice(0, 16).replace(\"T\", \" \")\n : \"?\";\n const traceNote = b.traceId\n ? ` [trace: ${b.traceId.slice(0, 12)}]`\n : \"\";\n return `- [${sealedDate}${traceNote}] Topics: ${b.topics.join(\", \")} (${b.memoryIds.length} memories)`;\n });\n this.appendRecallSection(\n sectionBuckets,\n \"memory-boxes\",\n `## Recent Topic Windows\\n\\n${boxLines.join(\"\\n\")}`,\n );\n }\n }\n\n // 1e. TMT node (temporal memory tree, v8.2)\n if (\n this.isRecallSectionEnabled(\n \"temporal-memory-tree\",\n this.config.temporalMemoryTreeEnabled === true,\n ) &&\n this.config.temporalMemoryTreeEnabled &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n const tmtNode = await this.tmtBuilder.getMostRelevantNode();\n if (tmtNode) {\n const levelLabel =\n tmtNode.level.charAt(0).toUpperCase() + tmtNode.level.slice(1);\n this.appendRecallSection(\n sectionBuckets,\n \"temporal-memory-tree\",\n `## Memory Timeline (${levelLabel})\\n\\n${tmtNode.summary}`,\n );\n }\n }\n\n // LCM compressed history section\n if (\n this.lcmEngine?.enabled &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n try {\n const structuredMatches = await this.lcmEngine.searchStructuredParts(\n sessionKey ?? \"default\",\n retrievalQuery,\n );\n const structuredSection = this.lcmEngine.formatStructuredRecall(\n structuredMatches,\n Math.ceil(this.config.recallBudgetChars * 0.08),\n );\n if (structuredSection) {\n const structuredAppended = this.appendRecallSection(\n sectionBuckets,\n \"lcm-message-parts\",\n structuredSection,\n );\n if (structuredAppended) {\n for (const match of structuredMatches) {\n lcmStructuredXrayResults.push({\n memoryId: `lcm-message-part-${match.part_id}`,\n path: `lcm://${match.session_id}/turn/${match.turn_index}/part/${match.part_id}`,\n servedBy: match.file_path ? \"lcm-file-parts\" : \"lcm-tool-parts\",\n scoreDecomposition: { final: match.score },\n admittedBy: [\"lcm-message-parts\"],\n });\n }\n }\n }\n const lcmSection = await this.lcmEngine.assembleRecall(\n sessionKey ?? \"default\",\n this.config.recallBudgetChars,\n );\n if (lcmSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"lcm-compressed-history\",\n lcmSection,\n );\n }\n } catch (err) {\n log.debug(`LCM recall assembly error: ${err}`);\n }\n }\n\n if (objectiveStateSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"objective-state\",\n objectiveStateSection,\n );\n }\n\n if (causalTrajectorySection) {\n this.appendRecallSection(\n sectionBuckets,\n \"causal-trajectories\",\n causalTrajectorySection,\n );\n }\n\n if (cmcCausalChainsSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"cmc-causal-chains\",\n cmcCausalChainsSection,\n );\n }\n\n if (trustZoneSection) {\n this.appendRecallSection(sectionBuckets, \"trust-zones\", trustZoneSection);\n }\n\n const harmonicRetrievalSection = await awaitEnrichmentSection(\n \"harmonic\",\n harmonicRetrievalPromise,\n );\n if (harmonicRetrievalSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"harmonic-retrieval\",\n harmonicRetrievalSection,\n );\n }\n\n if (verifiedRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"verified-episodes\",\n verifiedRecallSection,\n );\n }\n\n if (verifiedRulesSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"verified-rules\",\n verifiedRulesSection,\n );\n }\n\n if (workProductsSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"work-products\",\n workProductsSection,\n );\n }\n\n // 2. QMD results — post-process and format\n const qmdResult = await awaitEnrichmentSection(\"qmd\", qmdPromise);\n if (qmdResult) {\n const t0 = Date.now();\n const {\n memoryResultsLists,\n globalResults,\n preAugmentTopScore,\n maxSpecializedScore,\n } = qmdResult;\n\n // Merge/dedupe by path; keep the best score and first non-empty snippet.\n const memoryResultsRaw = mergeGraphExpandedResults(\n memoryResultsLists.flat(),\n [],\n );\n\n let memoryResults = memoryResultsRaw;\n\n // Enforce namespace read policies by filtering paths.\n if (this.config.namespacesEnabled) {\n memoryResults = memoryResults.filter((r) =>\n recallNamespaces.includes(this.namespaceFromPath(r.path)),\n );\n }\n // Artifacts are injected through dedicated verbatim recall flow only.\n memoryResults = memoryResults.filter(\n (r) => !isArtifactMemoryPath(r.path),\n );\n\n const isFullModeGraphAssist =\n this.config.multiGraphMemoryEnabled &&\n this.config.graphAssistInFullModeEnabled !== false &&\n recallMode === \"full\" &&\n memoryResults.length >=\n Math.max(1, this.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n recallMode === \"graph_mode\" || isFullModeGraphAssist;\n const graphShadowEvalEnabled =\n isFullModeGraphAssist &&\n this.config.graphAssistShadowEvalEnabled === true;\n if (shouldRunGraphExpansion) {\n shouldPersistGraphSnapshot = true;\n graphDecisionShadowMode = graphShadowEvalEnabled;\n }\n if (shouldRunGraphExpansion) {\n const baselineMemoryResults = memoryResults;\n graphBaselinePaths.clear();\n baselineMemoryResults.forEach((result) =>\n graphBaselinePaths.add(result.path),\n );\n if (baselineMemoryResults.length === 0) {\n graphSnapshotStatus = \"skipped\";\n graphDecisionStatus = \"skipped\";\n graphDecisionReason =\n \"graph recall skipped because baseline retrieval produced no seed results\";\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = [];\n graphSnapshotSeedResults = [];\n graphSnapshotExpandedPaths = [];\n graphExpandedResultPaths.clear();\n } else {\n try {\n const {\n merged,\n seedPaths,\n expandedPaths,\n seedResults = baselineMemoryResults,\n } = await this.expandResultsViaGraph({\n memoryResults,\n recallNamespaces,\n recallResultLimit,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n graphSnapshotStatus = \"completed\";\n graphDecisionStatus = \"completed\";\n graphDecisionReason = graphShadowEvalEnabled\n ? \"graph shadow evaluation completed without altering injected context\"\n : \"graph expansion merged into recall ranking\";\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = seedPaths;\n graphSnapshotExpandedPaths = expandedPaths;\n graphSnapshotSeedResults = this.buildGraphRecallRankedResults(\n seedResults,\n () => [\"baseline\"],\n );\n graphExpandedResultPaths.clear();\n expandedPaths.forEach((entry) =>\n graphExpandedResultPaths.add(entry.path),\n );\n memoryResults = graphShadowEvalEnabled\n ? baselineMemoryResults\n : merged;\n\n if (graphShadowEvalEnabled) {\n const comparison = summarizeGraphShadowComparison(\n baselineMemoryResults,\n merged,\n recallResultLimit,\n );\n graphSnapshotShadowComparison = comparison;\n recordRecallSectionMetric({\n section: \"graphShadow\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n timing:\n `on b=${comparison.baselineCount} g=${comparison.graphCount} ` +\n `ov=${comparison.overlapCount} (${comparison.overlapRatio.toFixed(2)}) ` +\n `avgDelta=${comparison.averageOverlapDelta.toFixed(3)}`,\n });\n }\n } catch (err) {\n graphSnapshotStatus = \"aborted\";\n graphDecisionStatus = \"aborted\";\n graphDecisionReason = `graph expansion failed: ${err instanceof Error ? err.message : String(err)}`;\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = baselineMemoryResults\n .slice(0, Math.max(1, recallResultLimit))\n .map((result) => result.path);\n graphSnapshotSeedResults = this.buildGraphRecallRankedResults(\n baselineMemoryResults,\n () => [\"baseline\"],\n );\n graphSnapshotExpandedPaths = [];\n graphExpandedResultPaths.clear();\n log.warn(`graph recall failed open: ${graphDecisionReason}`);\n memoryResults = baselineMemoryResults;\n }\n }\n }\n\n // Apply recency and access count boosting\n memoryResults = await this.boostSearchResults(\n memoryResults,\n recallNamespaces,\n retrievalQuery,\n undefined,\n { asOfMs },\n );\n\n // Optional LLM reranking (default off). Fail-open if rerank fails/slow.\n if (this.config.rerankEnabled && this.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: retrievalQuery,\n candidates: memoryResults\n .slice(0, this.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.config.rerankTimeoutMs,\n maxCandidates: this.config.rerankMaxCandidates,\n cache: this.rerankCache,\n cacheEnabled: this.config.rerankCacheEnabled,\n cacheTtlMs: this.config.rerankCacheTtlMs,\n });\n if (ranked && ranked.length > 0) {\n const byPath = new Map(memoryResults.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const p of ranked) {\n const it = byPath.get(p);\n if (it) reordered.push(it);\n }\n // Append any unranked items in original order.\n const rankedSet = new Set(ranked);\n for (const r of memoryResults) {\n if (!rankedSet.has(r.path)) reordered.push(r);\n }\n memoryResults = reordered;\n }\n }\n if (this.config.rerankEnabled && this.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Memory Worth recall filter (issue #560 PR 4). When enabled, multiply\n // each candidate's score by its Memory Worth factor so memories with\n // a history of failed outcomes sink. Default off in this PR; PR 5\n // flips the default once bench shows tie-or-win. Fail-open: any\n // lookup error leaves the original scores untouched rather than\n // breaking recall for the whole namespace.\n if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {\n try {\n memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);\n } catch (err) {\n log.debug(\"memory-worth filter failed open\", { error: (err as Error).message });\n }\n }\n\n // Synapse-inspired confidence gate: check scores BEFORE slicing so\n // reranking doesn't affect which score the gate evaluates.\n //\n // Gate exclusively on the pre-augmentation QMD top score so the threshold\n // stays on the same scale it was calibrated against (raw QMD scores, not\n // post-merge weighted scores). This avoids two pitfalls:\n // 1. The 0.7× contextual weight silently lowering scores below threshold.\n // 2. A direct/temporal hit on a different scale inflating the gate score.\n // We also include maxSpecializedScore so that a strong direct/temporal hit (e.g.\n // an exact entity-name match at score 1.0) is not discarded just because the QMD\n // contextual pass returned a weak result. maxSpecializedScore is post-weight, so\n // direct hits at weight 1.0 stay on the same 0-1 scale as QMD scores.\n // IMPORTANT: maxSpecializedScore is only included when QMD also found something\n // (preAugmentTopScore > 0). When QMD returns nothing, a weak specialized hit must\n // NOT block the embedding fallback safety net — that path exists precisely for the\n // case where QMD finds nothing. Setting effectiveGateScore = 0 when QMD is empty\n // preserves the original behaviour: empty QMD → gate skipped → fallback available.\n const effectiveGateScore =\n preAugmentTopScore > 0\n ? Math.max(preAugmentTopScore, maxSpecializedScore)\n : 0;\n // Capture pre-gate pool size for X-ray before the confidence\n // gate can zero `memoryResults`. Placing the capture after the\n // gate would record 0 instead of the true pre-gate pool size\n // (issue #570 PR 1 review follow-up).\n xrayBranchPoolSize.hot_qmd = Math.max(\n xrayBranchPoolSize.hot_qmd,\n memoryResults.length,\n );\n let confidenceGateRejected = false;\n if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {\n if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {\n log.debug(\n `recall: confidence gate rejected ${memoryResults.length} results (effective score ${effectiveGateScore.toFixed(3)} below ${this.config.recallConfidenceGateThreshold})`,\n );\n memoryResults = [];\n confidenceGateRejected = true;\n }\n }\n\n // Diversify via MMR over the full candidate pool *before* truncating to\n // the final recall limit. Running MMR after the slice would be unable\n // to promote diverse candidates sitting just below the cutoff.\n memoryResults = this.diversifyAndLimitRecallResults(\n \"memories\",\n memoryResults,\n recallResultLimit,\n retrievalQuery,\n );\n\n // E-Mem-inspired memory reconstruction: fill gaps for referenced entities\n if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {\n try {\n const snippets = memoryResults.map((r) => r.snippet);\n // Extract entity paths already present in recall results to avoid duplicates\n const coveredRefs = memoryResults\n .map((r) => r.path)\n .filter((p) => p.startsWith(\"entities/\"))\n .map((p) => p.replace(/^entities\\//, \"\").replace(/\\.md$/, \"\"));\n const knownEntities = await profileStorage.listEntityNames();\n const missing = findUnresolvedEntityRefs(\n snippets,\n coveredRefs,\n knownEntities,\n );\n if (missing.length > 0) {\n // Allow up to maxExpansions successful entity expansions\n const budget = this.config.memoryReconstructionMaxExpansions;\n let expanded = 0;\n for (const entityName of missing) {\n if (expanded >= budget) break;\n const raw = await profileStorage.readEntity(entityName);\n if (raw && raw.length > 0) {\n const snippet =\n raw.length > 300 ? raw.slice(0, 300) + \"…\" : raw;\n memoryResults.push({\n docid: `entity:${entityName}`,\n path: `entities/${entityName}.md`,\n snippet: `[Entity: ${entityName}] ${snippet}`,\n score: 0.1,\n });\n expanded++;\n }\n }\n if (expanded > 0) {\n log.debug(`recall: reconstructed ${expanded} entity contexts`);\n }\n }\n } catch (err) {\n log.warn(\"recall: memory reconstruction failed (non-fatal)\", err);\n }\n }\n\n if (memoryResults.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n memoryResults,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_qmd\";\n recalledMemoryCount = memoryResults.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: memoryResults,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(memoryResults);\n recalledMemoryPaths = memoryResults\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = memoryResults;\n impressionRecorded = true;\n } else if (!confidenceGateRejected) {\n // Only attempt fallback paths if the confidence gate did NOT fire.\n // When the gate rejects, all recall pathways are skipped to prevent\n // low-relevance results from polluting context.\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const embeddingResults = await this.searchEmbeddingFallback(\n retrievalQuery,\n embeddingFetchLimit,\n );\n const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(\n embeddingResults,\n queryAwarePrefilter.candidatePaths,\n );\n const scopedCandidates = filterRecallCandidates(\n prefilteredEmbeddingResults,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.boostSearchResults(\n scopedCandidates,\n recallNamespaces,\n retrievalQuery,\n undefined,\n { asOfMs },\n );\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.hot_embedding = Math.max(\n xrayBranchPoolSize.hot_embedding,\n boostedScoped.length,\n );\n const scoped = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n );\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: scoped,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(scoped);\n recalledMemoryPaths = scoped\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = scoped;\n impressionRecorded = true;\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n }\n }\n\n if (globalResults.length > 0) {\n this.appendRecallSection(\n sectionBuckets,\n \"workspace-context\",\n this.formatQmdResults(\"Workspace Context\", globalResults),\n );\n }\n\n recordRecallSectionMetric({\n section: \"qmdPost\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n\n // If the user is pushing back (\"that's not right\", \"why did you say that\"),\n // gently suggest an explicit workflow to inspect what was recalled and record feedback.\n // IMPORTANT: this is suggestion-only; never auto-mark negatives.\n if (isDisagreementPrompt(prompt)) {\n this.appendRecallSection(\n sectionBuckets,\n \"memories\",\n [\n \"## Retrieval Feedback Helper\",\n \"\",\n \"The user may be disputing an answer. To debug whether retrieval misled the response:\",\n \"- Use tool `memory_last_recall` to see which memory IDs were injected into context.\",\n \"- Use tool `memory_intent_debug` to inspect the planner mode decision and graph fallback reason.\",\n \"- If negative examples are enabled, you can use `memory_feedback_last_recall` to mark specific recalled IDs as not useful.\",\n \"\",\n \"Safety: do not mass-mark negatives automatically; prefer explicit IDs.\",\n ].join(\"\\n\"),\n );\n }\n } else if (recallResultLimit > 0 && !this.qmd.isAvailable()) {\n // Fallback: embeddings first, then recency-only.\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const embeddingResults = await this.searchEmbeddingFallback(\n retrievalQuery,\n embeddingFetchLimit,\n );\n const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(\n embeddingResults,\n queryAwarePrefilter.candidatePaths,\n );\n const scopedCandidates = filterRecallCandidates(\n prefilteredEmbeddingResults,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.boostSearchResults(\n scopedCandidates,\n recallNamespaces,\n retrievalQuery,\n undefined,\n { asOfMs },\n );\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.hot_embedding = Math.max(\n xrayBranchPoolSize.hot_embedding,\n boostedScoped.length,\n );\n const scoped = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n );\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: scoped,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(scoped);\n recalledMemoryPaths = scoped\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = scoped;\n impressionRecorded = true;\n } else {\n const memories =\n await this.readAllMemoriesForNamespaces(recallNamespaces);\n if (memories.length > 0) {\n // Filter out non-active memories. Delegate to\n // shouldFilterSupersededFromRecall for superseded-status logic so\n // that the recent-scan path and the boostSearchResults (QMD) path\n // have identical semantics:\n // • temporalSupersessionEnabled=false → never filter superseded\n // (mirrors QMD path; user disabled the feature, so old marks\n // are ignored and all memories surface)\n // • temporalSupersessionIncludeInRecall=true → never filter (audit mode)\n // • enabled=true + includeInRecall=false → filter superseded\n // Previously the recent-scan path checked `enabled && includeInRecall`\n // directly, which disagreed with the QMD path when enabled=false\n // (memories were still filtered, contrary to the kill-switch intent).\n // Using the shared gate fixes both Finding 2 and Finding 3 from\n // PR #402 (round 6).\n const supersessionOptions = {\n enabled: this.config.temporalSupersessionEnabled,\n includeInRecall: this.config.temporalSupersessionIncludeInRecall,\n };\n // Cursor Medium on PR #713: when `as_of` is active, the\n // recent-scan path used to strip every non-active status\n // (including superseded) before `boostSearchResults` ran,\n // so the as_of bypass inside boostSearchResults never had\n // a chance to admit historically-valid records. Pass\n // superseded candidates through here when as_of is active;\n // boostSearchResults's `[valid_at, invalid_at)` evaluation\n // is the authoritative gate. Other non-active statuses\n // (archived, forgotten, rejected) stay excluded — historical\n // recall is about supersession history, not about reviving\n // records the operator explicitly dropped.\n const asOfActive =\n typeof asOfMs === \"number\" && Number.isFinite(asOfMs);\n const activeMemories = memories.filter(\n (m) => {\n if (isArtifactMemoryPath(m.path)) return false;\n const status = m.frontmatter.status;\n if (!status || status === \"active\") return true;\n if (status === \"superseded\") {\n if (asOfActive) return true;\n // Include superseded memory only if the canonical gate says\n // NOT to filter it (kill switch off or audit mode on).\n return !shouldFilterSupersededFromRecall(m.frontmatter, supersessionOptions);\n }\n // Other non-active statuses (archived, retired, etc.) are\n // excluded from the recent-scan path by default.\n return false;\n },\n );\n // Convert all active memories to QmdSearchResult with recency-based\n // baseline score, then pass through boostSearchResults so temporal/tag\n // boosts apply consistently with the primary QMD retrieval path.\n // Cap AFTER boosting so boosted-but-recency-ranked memories can surface.\n // Pass a pre-populated memoryByPath so boostSearchResults skips redundant\n // disk reads for files already loaded by readAllMemoriesForNamespaces.\n const queryAwareScopedMemories = queryAwarePrefilter.candidatePaths\n ? activeMemories.filter((memory) =>\n queryAwarePrefilter.candidatePaths?.has(memory.path),\n )\n : activeMemories;\n if (\n queryAwarePrefilter.candidatePaths &&\n queryAwareScopedMemories.length === 0\n ) {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n if (longTerm.length > 0) {\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n } else {\n const recentSorted = queryAwareScopedMemories.sort(\n (a, b) =>\n new Date(b.frontmatter.updated).getTime() -\n new Date(a.frontmatter.updated).getTime(),\n );\n const preloadedMap = new Map<string, MemoryFile>(\n queryAwareScopedMemories\n .filter((m) => m.path)\n .map((m) => [m.path, m]),\n );\n const recentAsResults: QmdSearchResult[] = recentSorted.map(\n (m, i) => ({\n docid: m.frontmatter.id,\n path: m.path,\n snippet: m.content,\n score: 1.0 - i / Math.max(recentSorted.length, 1),\n }),\n );\n const boostedRecent = (\n await this.boostSearchResults(\n recentAsResults,\n recallNamespaces,\n retrievalQuery,\n preloadedMap,\n { asOfMs },\n )\n ).sort((a, b) => b.score - a.score);\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.recent_scan = Math.max(\n xrayBranchPoolSize.recent_scan,\n boostedRecent.length,\n );\n const recent = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedRecent,\n recallResultLimit,\n retrievalQuery,\n );\n\n if (recent.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n recent,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"recent_scan\";\n recalledMemoryCount = recent.length;\n this.publishRecallResults({\n title: \"Recent Memories\",\n results: recent,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(recent);\n recalledMemoryPaths = recent\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = recent;\n impressionRecorded = true;\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults =\n this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n }\n }\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n }\n }\n\n if (isDisagreementPrompt(prompt)) {\n this.appendRecallSection(\n sectionBuckets,\n \"memories\",\n [\n \"## Retrieval Feedback Helper\",\n \"\",\n \"The user may be disputing an answer. To debug whether retrieval misled the response:\",\n \"- Use tool `memory_last_recall` to see which memory IDs were injected into context.\",\n \"- Use tool `memory_intent_debug` to inspect the planner mode decision and graph fallback reason.\",\n \"- If graph recall is enabled, use `memory_graph_explain_last_recall` to inspect seed/expanded graph paths.\",\n \"- If negative examples are enabled, you can use `memory_feedback_last_recall` to mark specific recalled IDs as not useful.\",\n \"\",\n \"Safety: do not mass-mark negatives automatically; prefer explicit IDs.\",\n ].join(\"\\n\"),\n );\n }\n }\n\n const phase2AfterQmdMs = Date.now() - recallStart;\n if (shouldPersistGraphSnapshot) {\n if (!graphSnapshotStatus) {\n graphSnapshotStatus = \"skipped\";\n }\n if (!graphSnapshotReason) {\n graphSnapshotReason = qmdAvailable\n ? \"graph recall skipped before expansion\"\n : \"graph recall skipped because QMD was unavailable\";\n }\n if (graphDecisionStatus === \"not_requested\") {\n graphDecisionStatus = graphSnapshotStatus;\n }\n if (!graphDecisionReason) {\n graphDecisionReason = graphSnapshotReason;\n }\n await this.recordLastGraphRecallSnapshot({\n storage: profileStorage,\n prompt: retrievalQuery,\n recallMode,\n recallNamespaces,\n seedPaths: graphSnapshotSeedPaths,\n expandedPaths: graphSnapshotExpandedPaths,\n status: graphSnapshotStatus,\n reason: graphSnapshotReason,\n shadowMode: graphDecisionShadowMode,\n queryIntent,\n seedResults: graphSnapshotSeedResults,\n finalResults: graphSnapshotFinalResults,\n shadowComparison: graphSnapshotShadowComparison,\n });\n }\n await this.recordLastIntentSnapshot({\n storage: profileStorage,\n snapshot: buildIntentDebugSnapshot(),\n });\n\n // 2.5. Compression guideline recall section (v8.11 Task 5)\n if (\n this.isRecallSectionEnabled(\n \"compression-guidelines\",\n this.config.compressionGuidelineLearningEnabled === true,\n )\n ) {\n const compressionGuidelineSection =\n await this.buildCompressionGuidelineRecallSection();\n if (compressionGuidelineSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compression-guidelines\",\n compressionGuidelineSection,\n );\n }\n }\n\n // 3. Transcript/summaries/conversation/compounding are fetched in parallel above,\n // then assembled here according to recallPipeline order.\n if (transcriptSection) {\n this.appendRecallSection(sectionBuckets, \"transcript\", transcriptSection);\n }\n // Compaction reset context — independent section so it works even when transcript is disabled.\n if (compactionSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compaction-reset\",\n compactionSection,\n );\n }\n if (summariesSection) {\n this.appendRecallSection(sectionBuckets, \"summaries\", summariesSection);\n }\n if (conversationRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"conversation-recall\",\n conversationRecallSection,\n );\n }\n const compoundingSection = await awaitEnrichmentSection(\n \"compounding\",\n compoundingPromise,\n );\n if (compoundingSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compounding\",\n compoundingSection,\n );\n }\n\n // 5. Inject most relevant question (if enabled) (existing)\n if (\n this.config.injectQuestions &&\n this.isRecallSectionEnabled(\"questions\", true)\n ) {\n const questions = await profileStorage.readQuestions({\n unresolvedOnly: true,\n });\n if (questions.length > 0) {\n // Find the most relevant question to the current prompt\n // Simple approach: use the highest-priority unresolved question\n // TODO: Could use QMD search to find the most contextually relevant one\n const topQuestion = questions[0]; // Already sorted by priority desc\n this.appendRecallSection(\n sectionBuckets,\n \"questions\",\n `## Open Question\\n\\nSomething I've been curious about: ${topQuestion.question}\\n\\n_Context: ${topQuestion.context}_`,\n );\n }\n }\n\n const phase2QuestionsDoneMs = Date.now() - recallStart;\n const finalizedQueryAwarePrefilter = await queryAwarePrefilterPromise;\n const phase2QapDoneMs = Date.now() - recallStart;\n throwIfRecallAborted(options.abortSignal);\n if (\n timings.queryAware &&\n finalizedQueryAwarePrefilter.candidatePaths?.size\n ) {\n const helpedCount = recalledMemoryPaths.filter((memoryPath) =>\n finalizedQueryAwarePrefilter.candidatePaths?.has(memoryPath),\n ).length;\n timings.queryAware = `${timings.queryAware};helped=${helpedCount}`;\n }\n\n // --- Timing summary ---\n timings.total = `${Date.now() - recallStart}ms`;\n this.profiler.endSpan(\"assembly\", profileTraceId);\n log.info(\n `recall phase-2 checkpoints: afterQmd=${phase2AfterQmdMs}ms, afterQuestions=${phase2QuestionsDoneMs}ms, afterQap=${phase2QapDoneMs}ms`,\n );\n const timingParts = Object.entries(timings)\n .map(([k, v]) => `${k}=${v}`)\n .join(\", \");\n log.info(`recall timings: ${timingParts}`);\n\n const assembledRecall = this.assembleRecallSections(\n sectionBuckets,\n options.budgetCharsOverride,\n );\n const context =\n assembledRecall.sections.length === 0\n ? \"\"\n : assembledRecall.sections.join(\"\\n\\n---\\n\\n\");\n const sourcesUsed = this.collectLastRecallSources(\n sectionBuckets,\n recallSource,\n );\n const budgetsApplied = this.buildLastRecallBudgetSummary({\n requestedTopK,\n recallResultLimit,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n finalContextChars: assembledRecall.finalChars,\n truncated: assembledRecall.truncated,\n includedSections: assembledRecall.includedIds,\n omittedSections: assembledRecall.omittedIds,\n });\n\n // X-ray capture (issue #570 PR 1). Only fires when the caller\n // explicitly opts in via `xrayCapture: true`. No behavior change\n // when the flag is absent — this branch and the setter both\n // short-circuit. Captured data is composed from values we have\n // already derived above, so capture cost is a single object\n // allocation; no new recall work is performed.\n //\n // Skip capture when the caller has already aborted this recall —\n // otherwise a canceled call could clobber a prior successful\n // capture that the capturing caller has not yet read back\n // (issue #570 PR 1 review follow-up).\n if (\n options.xrayCapture === true &&\n !options.abortSignal?.aborted\n ) {\n try {\n const servedBy = mapRecallSourceToXrayServedBy(recallSource);\n // Derive xray results from `recalledMemoryPaths` as the single\n // source of truth — `recalledMemoryIds` and `recalledMemoryPaths`\n // are built with two independent filters upstream\n // (`extractMemoryIdsFromResults` drops paths whose filename does\n // not match `*.md`, while `.map(path).filter(Boolean)` drops\n // empty paths only), so zipping them positionally would silently\n // misalign when the two filters differ. Re-deriving `memoryId`\n // from the path here guarantees `memoryId` and `path` refer to\n // the same underlying result.\n const idFromPath = (p: string): string | null => {\n const match = p.match(/([^/]+)\\.md$/);\n return match ? match[1] ?? null : null;\n };\n // Build a path → QmdSearchResult index so we can pull per-result\n // explain data (e.g. reinforcementBoost) from the result that\n // boostSearchResults annotated before surfacing to xray.\n const xrayResultByPath = new Map<string, QmdSearchResult>(\n xrayRecalledResults.map((xr) => [xr.path, xr]),\n );\n const results: RecallXrayResult[] = [];\n for (const recalledPath of recalledMemoryPaths) {\n const derivedId = idFromPath(recalledPath);\n if (!derivedId) continue;\n const xrayResult = xrayResultByPath.get(recalledPath);\n const scoreDecomposition: RecallXrayScoreDecomposition = {\n final: xrayResult?.score ?? 0,\n };\n if (\n xrayResult?.explain?.reinforcementBoost !== undefined &&\n xrayResult.explain.reinforcementBoost > 0\n ) {\n scoreDecomposition.reinforcementBoost =\n xrayResult.explain.reinforcementBoost;\n }\n results.push({\n memoryId: derivedId,\n path: recalledPath,\n servedBy,\n scoreDecomposition,\n admittedBy: [],\n });\n }\n // `considered` must reflect the pool size of the branch that\n // actually produced the admitted results, NOT the max across\n // every branch that ran. Otherwise a flow where hot_qmd\n // assembled a large pool that was killed by the confidence\n // gate and a different branch (or none) ultimately served\n // the recall would report hot_qmd's pool as \"considered\" —\n // incorrectly attributing those drops to the result limit.\n // Pick the pool by `recallSource`; fall back to\n // `recalledMemoryCount` when no branch ran (e.g. every branch\n // returned zero). This path never runs for `no_recall` —\n // that branch captures its own snapshot earlier.\n let xrayConsidered: number;\n switch (recallSource) {\n case \"hot_qmd\":\n xrayConsidered = xrayBranchPoolSize.hot_qmd;\n break;\n case \"hot_embedding\":\n xrayConsidered = xrayBranchPoolSize.hot_embedding;\n break;\n case \"cold_fallback\":\n xrayConsidered = xrayColdPoolSink.size;\n break;\n case \"recent_scan\":\n xrayConsidered = xrayBranchPoolSize.recent_scan;\n break;\n case \"none\":\n xrayConsidered = recalledMemoryCount;\n break;\n default: {\n // Compile-time guard: adding a new `recallSource` value\n // must force this switch to be updated.\n const _exhaustive: never = recallSource;\n void _exhaustive;\n xrayConsidered = recalledMemoryCount;\n }\n }\n // `considered` must never be less than `admitted` — in degenerate\n // flows where a branch's pool counter missed an assignment, prefer\n // the admitted count as the floor so the trace stays self-consistent.\n xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);\n const filters: RecallFilterTrace[] = [\n {\n name: \"recall-result-limit\",\n considered: xrayConsidered,\n admitted: recalledMemoryIds.length,\n },\n ];\n if (lcmStructuredXrayResults.length > 0) {\n filters.push({\n name: \"lcm-message-parts\",\n considered: lcmStructuredXrayResults.length,\n admitted: lcmStructuredXrayResults.length,\n });\n }\n this.lastXraySnapshot = buildXraySnapshot({\n query: retrievalQuery,\n tierExplain: null,\n results: [...results, ...lcmStructuredXrayResults],\n filters,\n budget: {\n chars: this.getRecallBudgetChars(options.budgetCharsOverride),\n used: assembledRecall.finalChars,\n },\n sessionKey,\n namespace: selfNamespace,\n traceId,\n // Issue #679 completion: record peer-profile injection in the\n // xray snapshot. peerProfileXrayAnnotation is set inside\n // peerProfileRecallPromise when injection actually occurred,\n // and stays null otherwise. By the time xray capture runs,\n // phase-1 parallel work is complete so the annotation is\n // guaranteed to be populated.\n peerProfileInjection: peerProfileXrayAnnotation,\n });\n } catch (err) {\n // Capture is a best-effort side channel: a capture failure\n // must NEVER propagate into the primary recall path.\n log.debug(`x-ray capture failed: ${err}`);\n }\n }\n\n if (sessionKey) {\n throwIfRecallAborted(options.abortSignal);\n this.lastRecall\n .record({\n sessionKey,\n query: retrievalQuery,\n memoryIds: recalledMemoryIds,\n namespace: selfNamespace,\n traceId,\n plannerMode: recallMode,\n requestedMode,\n source: recallSource,\n fallbackUsed: recallSource !== \"none\" && recallSource !== \"hot_qmd\",\n sourcesUsed,\n budgetsApplied,\n latencyMs: Date.now() - recallStart,\n resultPaths: recalledMemoryPaths,\n policyVersion,\n appendImpression:\n impressionRecorded ||\n recalledMemoryIds.length > 0 ||\n this.config.recordEmptyRecallImpressions,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n })\n .catch((err) => log.debug(`last recall record failed: ${err}`));\n }\n if (sessionKey) {\n this.queueEvalShadowRecall({\n traceId,\n recordedAt: new Date().toISOString(),\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n source: recallSource,\n recalledMemoryCount,\n injected: context.length > 0,\n contextChars: context.length,\n memoryIds: recalledMemoryIds,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n }\n closeProfileTrace();\n this.emitTrace({\n kind: \"recall_summary\",\n traceId,\n operation: \"recall\",\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n qmdEnabled: this.config.qmdEnabled,\n qmdAvailable: this.qmd.isAvailable(),\n recallNamespaces,\n source: recallSource,\n recalledMemoryCount,\n injected: context.length > 0,\n contextChars: context.length,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n recalledContent:\n this.config.traceRecallContent && context.length > 0\n ? context\n : undefined,\n });\n\n return context;\n } finally {\n closeProfileTrace();\n }\n }\n\n async processTurn(\n role: \"user\" | \"assistant\",\n content: string,\n sessionKey?: string,\n options: {\n bufferKey?: string;\n logicalSessionKey?: string;\n providerThreadId?: string | null;\n turnFingerprint?: string;\n persistProcessedFingerprint?: boolean;\n } = {},\n ): Promise<void> {\n if (role !== \"user\" && role !== \"assistant\") {\n log.debug(`processTurn: ignoring unsupported role=${String(role)}`);\n return;\n }\n if (shouldSkipImplicitExtraction(this.config)) {\n log.debug(\n \"processTurn: skipping implicit extraction because captureMode=explicit\",\n );\n return;\n }\n\n const bufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : typeof sessionKey === \"string\" && sessionKey.length > 0\n ? sessionKey\n : \"default\";\n const turn: BufferTurn = {\n role,\n content,\n timestamp: new Date().toISOString(),\n sessionKey,\n logicalSessionKey: options.logicalSessionKey ?? bufferKey,\n providerThreadId: options.providerThreadId ?? null,\n turnFingerprint: options.turnFingerprint,\n persistProcessedFingerprint: options.persistProcessedFingerprint === true,\n };\n\n const decision = await this.buffer.addTurn(bufferKey, turn);\n\n if (decision === \"keep_buffering\") return;\n await this.queueBufferedExtraction(\n this.buffer.getTurns(bufferKey),\n \"trigger_mode\",\n { bufferKey },\n );\n }\n\n async flushSession(\n sessionKey: string,\n options: {\n reason: string;\n abortSignal?: AbortSignal;\n bufferKey?: string;\n },\n ): Promise<void> {\n const explicitBufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : null;\n const discoveredBufferKeys =\n explicitBufferKey ||\n typeof sessionKey !== \"string\" ||\n sessionKey.length === 0 ||\n typeof this.buffer.findBufferKeysForSession !== \"function\"\n ? []\n : await this.buffer.findBufferKeysForSession(sessionKey);\n const bufferKeys = explicitBufferKey\n ? [explicitBufferKey]\n : discoveredBufferKeys.length > 0\n ? discoveredBufferKeys\n : typeof sessionKey === \"string\" && sessionKey.length > 0\n ? [sessionKey]\n : [\"default\"];\n for (const bufferKey of bufferKeys) {\n const turns = this.buffer.getTurns(bufferKey);\n if (turns.length === 0) continue;\n await new Promise<void>((resolve, reject) => {\n void this\n .queueBufferedExtraction(turns, \"trigger_mode\", {\n bufferKey,\n clearBufferAfterExtraction: true,\n skipDedupeCheck: true,\n abortSignal: options.abortSignal,\n onTaskSettled: (error) => (error ? reject(error) : resolve()),\n })\n .catch(reject);\n });\n }\n }\n\n async ingestReplayBatch(\n turns: ReplayTurn[],\n options: { deadlineMs?: number; archiveLcm?: boolean } = {},\n ): Promise<void> {\n if (!Array.isArray(turns) || turns.length === 0) return;\n if (shouldSkipImplicitExtraction(this.config)) {\n log.debug(\n \"ingestReplayBatch: skipping implicit extraction because captureMode=explicit\",\n );\n return;\n }\n\n const bySession = new Map<string, BufferTurn[]>();\n for (const turn of turns) {\n if (turn.role !== \"user\" && turn.role !== \"assistant\") continue;\n const key = normalizeReplaySessionKey(turn.sessionKey);\n const list = bySession.get(key) ?? [];\n list.push({\n role: turn.role,\n content: turn.content,\n timestamp: turn.timestamp,\n sessionKey: key,\n parts: turn.parts,\n rawContent: turn.rawContent,\n sourceFormat: turn.sourceFormat,\n });\n bySession.set(key, list);\n }\n\n const replayTasks: Array<Promise<void>> = [];\n for (const [key, sessionTurns] of bySession.entries()) {\n if (sessionTurns.length === 0) continue;\n if (options.archiveLcm !== false && this.lcmEngine?.enabled) {\n await this.lcmEngine.observeMessages(\n key,\n sessionTurns.map((turn) => ({\n role: turn.role,\n content: turn.content,\n parts: turn.parts,\n rawContent: turn.rawContent,\n sourceFormat: turn.sourceFormat,\n })),\n );\n }\n replayTasks.push(\n new Promise<void>((resolve, reject) => {\n void this.queueBufferedExtraction(sessionTurns, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n bufferKey: key,\n extractionDeadlineMs: options.deadlineMs,\n onTaskSettled: (err) => (err ? reject(err) : resolve()),\n }).catch(reject);\n }),\n );\n }\n if (replayTasks.length > 0) {\n const settled = await Promise.allSettled(replayTasks);\n const firstRejected = settled.find(\n (result): result is PromiseRejectedResult =>\n result.status === \"rejected\",\n );\n if (firstRejected) {\n throw firstRejected.reason;\n }\n }\n }\n\n /**\n * Return the namespace that `ingestBulkImportBatch` writes into (#460).\n *\n * Exposed so host CLIs can snapshot the same storage root that extraction\n * actually writes to, avoiding the \"CLI counts files at namespace A while\n * writes land in namespace B\" footgun that a naïve\n * `config.defaultNamespace` snapshot could hit when a namespace policy\n * named `\"default\"` also exists.\n *\n * Today bulk-import is pinned to `config.defaultNamespace`; future\n * per-invocation namespace routing would thread an explicit target here\n * and through `ingestBulkImportBatch`.\n */\n bulkImportWriteNamespace(): string {\n return this.config.defaultNamespace;\n }\n\n /**\n * Ingest a batch of bulk-import turns (#460). Like ingestReplayBatch, this\n * normalizes user/assistant turns into the extraction buffer and awaits\n * settlement, but it intentionally bypasses the captureMode=\"explicit\"\n * gate because bulk-import is itself an explicit user action — the user\n * ran `bulk-import --source <name> --file ...` and would be surprised to\n * see the command silently no-op when capture is otherwise restricted.\n *\n * Turns with role=\"other\" are skipped (not supported by the extraction\n * pipeline).\n *\n * Two design decisions worth calling out:\n *\n * - **sessionKey is truthy and per-batch-unique.**\n * `ThreadingManager.shouldStartNewThread` only applies the session-key\n * boundary check when `turn.sessionKey` is truthy (threading.ts:82);\n * with an empty string, imported turns could attach to the current\n * live thread or merge across unrelated import batches. A unique\n * `bulk-import:batch:<timestamp>-<rand>` key forces a fresh thread per\n * batch without matching common prefix/map rules in\n * `principalFromSessionKeyRules`. (Catch-all regex rules could still\n * remap the principal, but that only affects metadata provenance —\n * see the next point for why write routing is unaffected.)\n *\n * - **writeNamespaceOverride pins the storage target.**\n * We pass `writeNamespaceOverride: this.bulkImportWriteNamespace()` to\n * `queueBufferedExtraction`, which tells `runExtraction` to skip\n * `defaultNamespaceForPrincipal` and write directly into the\n * orchestrator's declared bulk-import write namespace. This keeps\n * writes deterministic even when namespace policies named `\"default\"`\n * exist alongside a different `config.defaultNamespace`, and also\n * guards against regex-catch-all principal rules steering bulk-import\n * into an unexpected tenant.\n *\n * Per-invocation namespace routing (letting callers target a namespace\n * other than `bulkImportWriteNamespace()`) is a separate feature tracked\n * as a follow-up — the hook is the `writeNamespaceOverride` option, but\n * the CLI surface does not yet expose a `--namespace` flag.\n */\n async ingestBulkImportBatch(\n turns: ImportTurn[],\n options: {\n deadlineMs?: number;\n } = {},\n ): Promise<void> {\n if (!Array.isArray(turns) || turns.length === 0) return;\n\n // Per-batch unique sessionKey keeps threading honest without matching\n // typical prefix/map routing rules. Combined with writeNamespaceOverride\n // below, the storage target is independent of principal resolution.\n // Uses crypto.randomBytes (not Math.random) so CodeQL does not flag a\n // security-context insecure-randomness use even though this value never\n // leaves the process; the bytes just need to be collision-resistant\n // across concurrent bulk-import batches.\n const sessionKey =\n `bulk-import:batch:${Date.now().toString(36)}-` +\n randomBytes(6).toString(\"hex\");\n\n const sessionTurns: BufferTurn[] = [];\n for (const turn of turns) {\n if (turn.role !== \"user\" && turn.role !== \"assistant\") continue;\n sessionTurns.push({\n role: turn.role,\n content: turn.content,\n timestamp: turn.timestamp,\n sessionKey,\n parts: turn.parts,\n rawContent: turn.rawContent,\n sourceFormat: turn.sourceFormat,\n });\n }\n if (sessionTurns.length === 0) return;\n\n if (this.lcmEngine?.enabled) {\n await this.lcmEngine.observeMessages(\n sessionKey,\n sessionTurns.map((turn) => ({\n role: turn.role,\n content: turn.content,\n parts: turn.parts,\n rawContent: turn.rawContent,\n sourceFormat: turn.sourceFormat,\n })),\n );\n }\n\n await new Promise<void>((resolve, reject) => {\n void this.queueBufferedExtraction(sessionTurns, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n bufferKey: sessionKey,\n extractionDeadlineMs: options.deadlineMs,\n writeNamespaceOverride: this.bulkImportWriteNamespace(),\n onTaskSettled: (err) => (err ? reject(err) : resolve()),\n }).catch(reject);\n });\n }\n\n async observeSessionHeartbeat(\n sessionKey: string,\n options: { bufferKey?: string } = {},\n ): Promise<void> {\n if (this.config.sessionObserverEnabled !== true) return;\n if (!sessionKey || sessionKey.length === 0) return;\n\n const bufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : sessionKey;\n const previous =\n this.heartbeatObserverChains.get(sessionKey) ?? Promise.resolve();\n const next = previous\n .catch(() => undefined)\n .then(async () => {\n const turns = this.buffer.getTurns(bufferKey);\n if (turns.length === 0) return;\n const normalizedSessionKey = normalizeReplaySessionKey(sessionKey);\n const allowSharedSessionBuffer = bufferKey.startsWith(\n CODEX_THREAD_KEY_PREFIX,\n );\n if (\n !allowSharedSessionBuffer &&\n turns.some(\n (turn) =>\n turn.sessionKey &&\n normalizeReplaySessionKey(turn.sessionKey) !== normalizedSessionKey,\n )\n ) {\n log.debug(\n `heartbeat observer skipped: mixed-session buffer contents for ${bufferKey}`,\n );\n return;\n }\n if (!this.shouldQueueExtraction(turns, {\n commit: false,\n bufferKey,\n })) {\n log.debug(\n `heartbeat observer skipped: extraction dedupe for ${bufferKey}`,\n );\n return;\n }\n const footprint =\n await this.transcript.estimateSessionFootprint(sessionKey);\n const decision = await this.sessionObserver.observe({\n sessionKey,\n totalBytes: footprint.bytes,\n totalTokens: footprint.tokens,\n });\n if (!decision.triggered) return;\n log.debug(\n `heartbeat observer trigger: session=${sessionKey} deltaBytes=${decision.deltaBytes} deltaTokens=${decision.deltaTokens}`,\n );\n await this.queueBufferedExtraction(turns, \"heartbeat_observer\", {\n bufferKey,\n });\n });\n\n this.heartbeatObserverChains.set(sessionKey, next);\n try {\n await next;\n } finally {\n if (this.heartbeatObserverChains.get(sessionKey) === next) {\n this.heartbeatObserverChains.delete(sessionKey);\n }\n }\n }\n\n private async queueBufferedExtraction(\n turnsToExtract: BufferTurn[],\n reason: \"trigger_mode\" | \"heartbeat_observer\",\n options: {\n skipDedupeCheck?: boolean;\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n extractionDeadlineMs?: number;\n onTaskSettled?: (error?: unknown) => void;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n /**\n * Explicit namespace override for the write path (#460). When set,\n * `runExtraction` writes to this namespace instead of deriving one\n * from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.\n * Used by bulk-import to pin writes to a deterministic namespace\n * regardless of user-configured principal routing rules.\n */\n writeNamespaceOverride?: string;\n } = {},\n ): Promise<void> {\n const bufferKey = options.bufferKey ?? turnsToExtract[0]?.sessionKey ?? \"default\";\n if (\n !options.skipDedupeCheck &&\n !this.shouldQueueExtraction(turnsToExtract, { bufferKey })\n ) {\n log.debug(`extraction dedupe skip: preserving buffer (${reason})`);\n options.onTaskSettled?.();\n return;\n }\n\n this.extractionQueue.push(async () => {\n try {\n await this.runExtraction(turnsToExtract, {\n clearBufferAfterExtraction:\n options.clearBufferAfterExtraction ?? true,\n skipCharThreshold: options.skipCharThreshold ?? false,\n deadlineMs: options.extractionDeadlineMs,\n bufferKey,\n abortSignal: options.abortSignal,\n writeNamespaceOverride: options.writeNamespaceOverride,\n });\n options.onTaskSettled?.();\n } catch (err) {\n options.onTaskSettled?.(err);\n throw err;\n }\n });\n\n if (!this.queueProcessing) {\n this.queueProcessing = true;\n this.processQueue().catch((err) => {\n this.logExtractionQueueFailure(err, \"processor\");\n this.queueProcessing = false;\n });\n }\n log.debug(`queued extraction from ${reason}`);\n }\n\n private normalizeExtractionFingerprintTurns(turns: BufferTurn[]): string[] {\n if (!Array.isArray(turns) || turns.length === 0) return [];\n return turns\n .filter((turn) => turn.role === \"user\" || turn.role === \"assistant\")\n .map((turn) => {\n if (\n typeof turn.turnFingerprint === \"string\" &&\n turn.turnFingerprint.length > 0\n ) {\n return `fp:${turn.turnFingerprint}`;\n }\n return `${turn.role}:${(turn.content ?? \"\").replace(/\\s+/g, \" \").trim().slice(0, this.config.extractionMaxTurnChars)}`;\n })\n .filter((value) => value.length > 0);\n }\n\n private buildExtractionFingerprint(\n turns: BufferTurn[],\n bufferKey: string,\n ): string | null {\n const normalized = this.normalizeExtractionFingerprintTurns(turns).join(\"\\n\");\n if (!normalized) return null;\n return createHash(\"sha256\")\n .update(`${bufferKey}\\n${normalized}`)\n .digest(\"hex\");\n }\n\n private shouldQueueExtraction(\n turns: BufferTurn[],\n options: { commit?: boolean; bufferKey?: string } = {},\n ): boolean {\n if (!this.config.extractionDedupeEnabled) return true;\n if (!Array.isArray(turns) || turns.length === 0) return false;\n\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const fingerprint = this.buildExtractionFingerprint(turns, bufferKey);\n if (!fingerprint) return false;\n const now = Date.now();\n const seenAt = this.recentExtractionFingerprints.get(fingerprint);\n if (seenAt && now - seenAt < this.config.extractionDedupeWindowMs) {\n log.debug(\"extraction dedupe: skipped duplicate buffered turn set\");\n return false;\n }\n\n if (options.commit !== false) {\n this.recentExtractionFingerprints.set(fingerprint, now);\n }\n // Keep this cache bounded to avoid unbounded growth.\n if (\n options.commit !== false &&\n this.recentExtractionFingerprints.size > 200\n ) {\n const entries = Array.from(\n this.recentExtractionFingerprints.entries(),\n ).sort((a, b) => a[1] - b[1]);\n for (const [key] of entries.slice(0, entries.length - 200)) {\n this.recentExtractionFingerprints.delete(key);\n }\n }\n\n return true;\n }\n\n /**\n * Background serial queue processor.\n * Processes extractions one at a time to avoid race conditions.\n * Called automatically when items are queued.\n */\n private async processQueue(): Promise<void> {\n while (this.extractionQueue.length > 0) {\n const task = this.extractionQueue.shift();\n if (task) {\n try {\n await task();\n } catch (err) {\n this.logExtractionQueueFailure(err, \"task\");\n }\n }\n }\n\n this.queueProcessing = false;\n }\n\n /**\n * Classify + log a failure from either the per-task catch inside\n * `processQueue()` or the outer `processQueue().catch(...)` in\n * `queueBufferedExtraction()`. Issue #549: `throwIfRecallAborted`\n * (used throughout `runExtraction`) raises an Error whose `name` is\n * `\"AbortError\"`. That path fires when `before_reset` aborts a\n * queued task to avoid duplicate extraction — it is intentional\n * cancellation, not a failure. Downgrading the log to debug\n * prevents spurious `error`-level lines that routinely appear\n * right next to a successful `persisted: N facts, M entities` log\n * and that confuse operators into thinking extraction is broken.\n * Genuine extraction failures (network, parse, I/O) still log at\n * `error`.\n *\n * Source differentiates the two call sites so the log message\n * names the right layer (`task` vs `processor`).\n */\n private logExtractionQueueFailure(\n err: unknown,\n source: \"task\" | \"processor\",\n ): void {\n const aborted =\n source === \"task\"\n ? \"background extraction task aborted (session transition)\"\n : \"background extraction queue processor aborted (session transition)\";\n const failed =\n source === \"task\"\n ? \"background extraction task failed\"\n : \"background extraction queue processor failed\";\n if (isAbortError(err)) {\n log.debug(aborted);\n } else {\n log.error(failed, err);\n }\n }\n\n private async runExtraction(\n turns: BufferTurn[],\n options: {\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n deadlineMs?: number;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n /**\n * Explicit namespace override for the write path (#460). When set,\n * extraction writes go to this namespace instead of the one derived\n * from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.\n * The resolved `principal` is still threaded into memory metadata\n * for provenance; only the storage target is overridden.\n */\n writeNamespaceOverride?: string;\n } = {},\n ): Promise<void> {\n log.debug(`running extraction on ${turns.length} turns`);\n const clearBufferAfterExtraction =\n options.clearBufferAfterExtraction ?? true;\n const skipCharThreshold = options.skipCharThreshold ?? false;\n const deadlineMs =\n typeof options.deadlineMs === \"number\" &&\n Number.isFinite(options.deadlineMs)\n ? options.deadlineMs\n : undefined;\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const throwIfDeadlineExceeded = (stage: string): void => {\n if (typeof deadlineMs === \"number\" && Date.now() > deadlineMs) {\n throw new Error(`replay extraction deadline exceeded (${stage})`);\n }\n };\n const throwIfAborted = (stage: string): void => {\n throwIfRecallAborted(options.abortSignal, `extraction aborted (${stage})`);\n };\n const clearBuffer = async (options?: { ignoreAbort?: boolean }) => {\n if (options?.ignoreAbort !== true) {\n throwIfAborted(\"before_clear_buffer\");\n }\n if (clearBufferAfterExtraction) {\n await this.buffer.clearAfterExtraction(bufferKey);\n }\n };\n\n // Skip extraction for cron job sessions - these are system operations, not user conversations\n const sessionKey = turns[0]?.sessionKey ?? \"\";\n if (sessionKey.includes(\":cron:\")) {\n log.debug(`skipping extraction for cron session: ${sessionKey}`);\n await clearBuffer();\n return;\n }\n\n const normalizedTurns = turns\n .filter(\n (t) =>\n (t.role === \"user\" || t.role === \"assistant\") &&\n typeof t.content === \"string\",\n )\n .map((t) => ({\n ...t,\n content: t.content.trim().slice(0, this.config.extractionMaxTurnChars),\n }))\n .filter((t) => t.content.length > 0);\n throwIfDeadlineExceeded(\"before_extract\");\n throwIfAborted(\"before_extract\");\n\n const userTurns = normalizedTurns.filter((t) => t.role === \"user\");\n const totalChars = normalizedTurns.reduce(\n (sum, t) => sum + t.content.length,\n 0,\n );\n const belowCharThreshold = totalChars < this.config.extractionMinChars;\n const belowUserTurnThreshold =\n userTurns.length < this.config.extractionMinUserTurns;\n if ((!skipCharThreshold && belowCharThreshold) || belowUserTurnThreshold) {\n log.debug(\n `skipping extraction: below threshold (totalChars=${totalChars}, userTurns=${userTurns.length})`,\n );\n await clearBuffer();\n return;\n }\n\n const principal = resolvePrincipal(sessionKey, this.config);\n // Write path — overlay the coding-agent namespace (issue #569) when the\n // session has a codingContext and `codingMode.projectScope` is true.\n // Explicit `writeNamespaceOverride` from callers still wins, matching\n // pre-#569 semantics.\n const selfNamespace =\n typeof options.writeNamespaceOverride === \"string\" &&\n options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : this.applyCodingNamespaceOverlay(\n sessionKey,\n defaultNamespaceForPrincipal(principal, this.config),\n );\n const storage = await this.storageRouter.storageFor(selfNamespace);\n const shouldPersistProcessedFingerprint = normalizedTurns.some(\n (turn) => turn.persistProcessedFingerprint === true,\n );\n const extractionFingerprint = this.buildExtractionFingerprint(\n normalizedTurns,\n bufferKey,\n );\n let meta =\n extractionFingerprint && shouldPersistProcessedFingerprint\n ? await storage.loadMeta()\n : null;\n if (\n extractionFingerprint &&\n shouldPersistProcessedFingerprint &&\n (meta?.processedExtractionFingerprints ?? []).some(\n (entry) => entry.fingerprint === extractionFingerprint,\n )\n ) {\n log.debug(\n `runExtraction: skipping already-processed extraction fingerprint for ${bufferKey}`,\n );\n await clearBuffer();\n return;\n }\n\n // Pass existing entity names so the LLM can reuse them instead of inventing variants\n const existingEntities = await storage.listEntityNames();\n const result = await raceRecallAbort(\n this.extraction.extract(\n normalizedTurns,\n existingEntities,\n ),\n options.abortSignal,\n \"extraction aborted (during_extract)\",\n );\n throwIfDeadlineExceeded(\"before_persist\");\n throwIfAborted(\"before_persist\");\n\n // Defensive: validate extraction result before processing\n if (!result) {\n log.warn(\"runExtraction: extraction returned null/undefined\");\n await clearBuffer();\n return;\n }\n if (!Array.isArray(result.facts)) {\n log.warn(\n \"runExtraction: extraction returned invalid facts (not an array)\",\n { factsType: typeof result.facts, resultKeys: Object.keys(result) },\n );\n await clearBuffer();\n return;\n }\n if (\n result.facts.length === 0 &&\n result.entities.length === 0 &&\n result.questions.length === 0 &&\n result.profileUpdates.length === 0\n ) {\n log.debug(\n \"runExtraction: extraction produced no durable outputs; skipping persistence\",\n );\n await clearBuffer();\n return;\n }\n\n let threadIdForExtraction: string | null = null;\n if (this.config.threadingEnabled && turns.length > 0) {\n const lastTurn = turns[turns.length - 1];\n try {\n threadIdForExtraction = await this.threading.processTurn(lastTurn, []);\n } catch (err) {\n // Fail-open: threading errors must not block memory persistence.\n log.warn(\n \"[threading] processTurn failed before persistence (non-fatal)\",\n err,\n );\n }\n }\n\n const persistedIds = await this.persistExtraction(\n result,\n storage,\n threadIdForExtraction,\n { sessionKey, principal },\n );\n meta ??= await storage.loadMeta();\n if (extractionFingerprint && shouldPersistProcessedFingerprint) {\n try {\n await this.recordProcessedExtractionFingerprint(\n storage,\n extractionFingerprint,\n meta,\n );\n } catch (error) {\n log.warn(\n \"runExtraction: failed to persist processed extraction fingerprint; continuing with buffer clear\",\n error,\n );\n }\n }\n // Persist extraction counters and processed fingerprints before running\n // follow-on helpers so replay dedupe survives any later non-essential\n // failure. If this aggregate meta write fails, still clear the buffer:\n // the durable memories are already written and replaying the same turns\n // would duplicate them.\n meta.extractionCount += 1;\n meta.lastExtractionAt = new Date().toISOString();\n meta.totalMemories += Array.isArray(result?.facts)\n ? result.facts.length\n : 0;\n meta.totalEntities += Array.isArray(result?.entities)\n ? result.entities.length\n : 0;\n let postPersistMetaError: unknown;\n try {\n await storage.saveMeta(meta);\n } catch (error) {\n postPersistMetaError = error;\n }\n\n // Buffer retention for defer verdicts (issue #562, PR 2). When the judge\n // deferred at least one candidate, retain the tail of the current turn\n // window so the next extraction pass has the surrounding context that\n // may disambiguate the deferred fact. Non-defer runs clear the slot.\n //\n // Gated on:\n // - `clearBufferAfterExtraction` — replay / bulk-import paths call\n // `runExtraction` with this false and do not operate on live buffer\n // state. Writing retention there would create synthetic buffer\n // entries and cross-contaminate future live extractions.\n // - NOT `extractionJudgeShadow` — in shadow mode the judge is only\n // advisory; facts are still persisted regardless of verdict, so\n // retaining the turn window on top of a persisted write would both\n // waste buffer space and cause the same facts to re-enter the\n // pipeline on the next pass.\n try {\n if (\n clearBufferAfterExtraction &&\n !this.config.extractionJudgeShadow\n ) {\n const deferredCount = this.lastPersistExtractionDeferredCount;\n if (deferredCount > 0 && normalizedTurns.length > 0) {\n await this.buffer.retainDeferredTurns(\n bufferKey,\n normalizedTurns as BufferTurn[],\n 10,\n );\n } else {\n await this.buffer.retainDeferredTurns(bufferKey, [], 0);\n }\n }\n } catch (err) {\n // Fail-open: retention is a nice-to-have. If it fails the judge will\n // still cap deferrals and convert to reject on the next pass.\n log.debug(\n `extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n await clearBuffer({ ignoreAbort: true });\n\n // Build memory box from this extraction (v8.0 Phase 2A)\n // Topics are derived from the current extraction's facts and entities only —\n // not from readAllMemories() — so box topics accurately reflect the current\n // session window and the call is free of expensive full-corpus I/O.\n if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {\n const extractionTopics = deriveTopicsFromExtraction(result);\n // Derive episodic metadata from buffer turns (REMem-inspired)\n const firstUserTurn = turns.find((t) => t.role === \"user\");\n const boxGoal =\n firstUserTurn?.content?.slice(0, 100)?.trim() || undefined;\n await this.boxBuilderFor(storage)\n .onExtraction({\n topics: extractionTopics,\n memoryIds: persistedIds,\n timestamp: new Date().toISOString(),\n goal: boxGoal,\n })\n .catch((err) =>\n log.warn(\"[boxes] onExtraction failed (non-fatal)\", err),\n );\n }\n\n // Batch-append persisted IDs so non-fact memories (entities/questions) are\n // always attached to the thread.\n if (\n this.config.threadingEnabled &&\n threadIdForExtraction &&\n persistedIds.length > 0\n ) {\n try {\n await this.threading.appendEpisodeIds(\n threadIdForExtraction,\n persistedIds,\n );\n } catch (err) {\n log.warn(\n \"[threading] appendEpisodeIds failed after persistence (non-fatal)\",\n err,\n );\n }\n }\n\n // Thread title update for the already-established thread context.\n if (this.config.threadingEnabled && threadIdForExtraction) {\n const conversationContent = turns.map((t) => t.content).join(\" \");\n await this.threading.updateThreadTitle(\n threadIdForExtraction,\n conversationContent,\n );\n }\n\n // Check if consolidation is needed (debounced + non-zero gated).\n const nonZeroExtraction =\n result.facts.length > 0 ||\n result.entities.length > 0 ||\n result.questions.length > 0 ||\n result.profileUpdates.length > 0;\n if (nonZeroExtraction) this.nonZeroExtractionsSinceConsolidation += 1;\n this.maybeScheduleConsolidation(nonZeroExtraction);\n\n this.requestQmdMaintenance();\n await this.runTierMigrationCycle(storage, \"extraction\");\n\n if (postPersistMetaError) {\n throw postPersistMetaError;\n }\n }\n\n private async recordProcessedExtractionFingerprint(\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>,\n ): Promise<void> {\n const meta = preloadedMeta ?? (await storage.loadMeta());\n const observedAt = new Date().toISOString();\n const seen = new Map(\n (meta.processedExtractionFingerprints ?? []).map((entry) => [\n entry.fingerprint,\n entry.observedAt,\n ]),\n );\n seen.set(fingerprint, observedAt);\n meta.processedExtractionFingerprints = Array.from(seen.entries())\n .map(([value, at]) => ({ fingerprint: value, observedAt: at }))\n .sort((left, right) => left.observedAt.localeCompare(right.observedAt))\n .slice(-500);\n if (!preloadedMeta) {\n await storage.saveMeta(meta);\n }\n }\n\n private async runTierMigrationCycle(\n storage: StorageManager,\n trigger: \"extraction\" | \"maintenance\" | \"manual\",\n options?: {\n dryRun?: boolean;\n limitOverride?: number;\n force?: boolean;\n },\n ): Promise<TierMigrationCycleSummary> {\n const dryRun = options?.dryRun === true;\n const persistSkipped = options?.force === true || trigger === \"manual\";\n if (!this.config.qmdTierMigrationEnabled && options?.force !== true) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"tier_migration_disabled\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (\n trigger === \"maintenance\" &&\n !this.config.qmdTierAutoBackfillEnabled &&\n options?.force !== true\n ) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"maintenance_backfill_disabled\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (this.tierMigrationInFlight) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"migration_in_flight\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const budgetTrigger = trigger === \"manual\" ? \"maintenance\" : trigger;\n const budget =\n this.compounding?.tierMigrationCycleBudget(budgetTrigger) ??\n defaultTierMigrationCycleBudget(this.config, budgetTrigger);\n const limit =\n options?.limitOverride !== undefined\n ? Math.max(0, Math.floor(options.limitOverride))\n : budget.limit;\n const nowMs = Date.now();\n if (\n options?.force !== true &&\n nowMs - this.lastTierMigrationRunAtMs < budget.minIntervalMs\n ) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit,\n dryRun,\n skipped: \"min_interval\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const policy = applyUtilityPromotionRuntimePolicy(\n {\n enabled: this.config.qmdTierMigrationEnabled,\n demotionMinAgeDays: this.config.qmdTierDemotionMinAgeDays,\n demotionValueThreshold: this.config.qmdTierDemotionValueThreshold,\n promotionValueThreshold: this.config.qmdTierPromotionValueThreshold,\n },\n this.utilityRuntimeValues,\n );\n\n this.tierMigrationInFlight = true;\n try {\n const coldStorage = new StorageManager(path.join(storage.dir, \"cold\"));\n const [hotMemories, coldMemories] = await Promise.all([\n storage.readAllMemories(),\n coldStorage.readAllMemories(),\n ]);\n const now = new Date();\n const scanLimit = Math.max(0, Math.floor(budget.scanLimit));\n const hotScanLimit = Math.min(\n hotMemories.length,\n Math.ceil(scanLimit * 0.75),\n );\n const coldScanLimit = Math.min(\n coldMemories.length,\n Math.max(0, scanLimit - hotScanLimit),\n );\n const toTimestamp = (memory: MemoryFile): number =>\n Date.parse(memory.frontmatter.updated ?? memory.frontmatter.created);\n const hotCandidates = hotMemories\n .map((memory) => ({ memory, tier: \"hot\" as MemoryTier }))\n .sort((a, b) => toTimestamp(a.memory) - toTimestamp(b.memory))\n .slice(0, hotScanLimit);\n const coldCandidates = coldMemories\n .map((memory) => ({ memory, tier: \"cold\" as MemoryTier }))\n .sort((a, b) => toTimestamp(b.memory) - toTimestamp(a.memory))\n .slice(0, coldScanLimit);\n const candidates = [...hotCandidates, ...coldCandidates];\n\n const migration = new TierMigrationExecutor({\n storage,\n qmd: this.qmd,\n hotCollection: this.config.qmdCollection,\n coldCollection:\n this.config.qmdColdCollection ?? `${this.config.qmdCollection}-cold`,\n autoEmbed: this.config.qmdAutoEmbedEnabled,\n });\n\n let migrated = 0;\n let promoted = 0;\n let demoted = 0;\n for (const candidate of candidates) {\n if (migrated >= limit) break;\n const decision = decideTierTransition(\n candidate.memory,\n candidate.tier,\n policy,\n now,\n );\n if (!decision.changed) continue;\n\n if (!dryRun) {\n const res = await migration.migrateMemory({\n memory: candidate.memory,\n fromTier: candidate.tier,\n toTier: decision.nextTier,\n reason: `${trigger}:${decision.reason}`,\n });\n if (!res.changed) continue;\n }\n migrated += 1;\n if (decision.nextTier === \"cold\") demoted += 1;\n if (decision.nextTier === \"hot\") promoted += 1;\n }\n\n if (!dryRun) this.lastTierMigrationRunAtMs = Date.now();\n log.debug(\n `tier migration cycle completed: trigger=${trigger} scanned=${candidates.length} migrated=${migrated} limit=${limit}${dryRun ? \" dryRun=true\" : \"\"}`,\n );\n const summary: TierMigrationCycleSummary = {\n trigger,\n scanned: candidates.length,\n migrated,\n promoted,\n demoted,\n limit,\n dryRun,\n };\n const shouldPersistCycle = trigger === \"manual\" || migrated > 0;\n if (shouldPersistCycle)\n await this.tierMigrationStatus.recordCycle(summary);\n return summary;\n } catch (err) {\n this.lastTierMigrationRunAtMs = Date.now();\n log.warn(`tier migration cycle failed (${trigger}, fail-open): ${err}`);\n const failed: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit,\n dryRun,\n errorCount: 1,\n };\n await this.tierMigrationStatus.recordCycle(failed);\n return failed;\n } finally {\n this.tierMigrationInFlight = false;\n }\n }\n\n async getTierMigrationStatus(): Promise<TierMigrationStatusSnapshot> {\n return this.tierMigrationStatus.get();\n }\n\n async runTierMigrationNow(options?: {\n dryRun?: boolean;\n limit?: number;\n }): Promise<TierMigrationCycleSummary> {\n return this.runTierMigrationCycle(this.storage, \"manual\", {\n dryRun: options?.dryRun === true,\n limitOverride: options?.limit,\n force: false,\n });\n }\n\n private maybeScheduleConsolidation(nonZeroExtraction: boolean): void {\n if (this.config.consolidationRequireNonZeroExtraction && !nonZeroExtraction)\n return;\n if (\n this.nonZeroExtractionsSinceConsolidation < this.config.consolidateEveryN\n )\n return;\n\n const now = Date.now();\n if (\n now - this.lastConsolidationRunAtMs <\n this.config.consolidationMinIntervalMs\n )\n return;\n if (this.consolidationInFlight) return;\n\n this.consolidationInFlight = true;\n this.lastConsolidationRunAtMs = now;\n this.nonZeroExtractionsSinceConsolidation = 0;\n this.runConsolidation()\n .catch((err) => log.error(\"background consolidation failed\", err))\n .finally(() => {\n this.consolidationInFlight = false;\n });\n }\n\n private requestQmdMaintenance(): void {\n if (!this.qmd.isAvailable()) return;\n if (!this.config.qmdMaintenanceEnabled) return;\n\n this.qmdMaintenancePending = true;\n if (this.qmdMaintenanceTimer) return;\n\n this.qmdMaintenanceTimer = setTimeout(() => {\n this.qmdMaintenanceTimer = null;\n this.runQmdMaintenance().catch((err) =>\n log.debug(`background qmd maintenance failed: ${err}`),\n );\n }, this.config.qmdMaintenanceDebounceMs);\n }\n\n /**\n * Public entrypoint for tool-driven QMD maintenance requests.\n * Routes through existing debounced/singleflight maintenance controls.\n */\n requestQmdMaintenanceForTool(reason: string): void {\n try {\n this.requestQmdMaintenance();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`qmd maintenance request failed (${reason}): ${msg}`);\n }\n }\n\n private async runQmdMaintenance(): Promise<void> {\n if (this.qmdMaintenanceInFlight) return;\n if (!this.qmdMaintenancePending) return;\n this.qmdMaintenanceInFlight = true;\n this.qmdMaintenancePending = false;\n\n try {\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.updateNamespaces(\n this.configuredNamespaces(),\n );\n } else {\n await this.qmd.update();\n }\n const now = Date.now();\n if (\n this.config.qmdAutoEmbedEnabled &&\n now - this.lastQmdEmbedAtMs >= this.config.qmdEmbedMinIntervalMs\n ) {\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.embedNamespaces(\n this.configuredNamespaces(),\n );\n } else {\n await this.qmd.embed();\n }\n this.lastQmdEmbedAtMs = now;\n }\n } finally {\n this.qmdMaintenanceInFlight = false;\n if (this.qmdMaintenancePending) {\n this.requestQmdMaintenance();\n }\n }\n }\n\n private async persistExtraction(\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: { sessionKey?: string; principal?: string },\n ): Promise<string[]> {\n // Inline source attribution (issue #369). When enabled, every extracted\n // fact is rewritten to carry a compact provenance tag inside its body so\n // the citation survives hostile memory text, copy/paste, and LLM quoting.\n // The helper is a no-op when the feature flag is off, so legacy pipelines\n // see zero behavioral change.\n const citationEnabled = this.config.inlineSourceAttributionEnabled === true;\n const citationTemplate = this.config.inlineSourceAttributionFormat;\n // The stable fields (agent, session) are computed once; `ts` is intentionally\n // omitted here and added fresh per invocation so each fact in a large batch\n // gets its own insertion timestamp rather than sharing a single batch-start time.\n const citationContextBase: Omit<CitationContext, \"ts\"> = citationEnabled\n ? {\n agent: sourceContext?.principal,\n session: sourceContext?.sessionKey,\n }\n : {};\n const applyInlineCitation = (content: string): string => {\n if (!citationEnabled) return content;\n if (typeof content !== \"string\" || content.length === 0) return content;\n // Build a fresh CitationContext per call so `ts` reflects the actual\n // insertion time of each individual fact rather than the batch-start time.\n const citationContext: CitationContext = {\n ...citationContextBase,\n ts: new Date().toISOString(),\n };\n // `attachCitation` already calls `hasCitationForTemplate` internally and\n // is a no-op when the content already carries a citation (default or\n // custom template). The outer check was redundant and has been removed\n // to avoid a maintenance hazard where the two guard paths could diverge.\n return attachCitation(content, citationContext, citationTemplate);\n };\n const persistedIds: string[] = [];\n const persistedIdsByStorage = new Map<\n string,\n { storage: StorageManager; ids: string[] }\n >();\n const trackPersistedId = (\n targetStorage: StorageManager,\n id: string,\n options: { includeReturnedIds?: boolean } = {},\n ): void => {\n if (options.includeReturnedIds !== false) {\n persistedIds.push(id);\n }\n const key = targetStorage.dir;\n const existing = persistedIdsByStorage.get(key);\n if (existing) {\n existing.ids.push(id);\n return;\n }\n persistedIdsByStorage.set(key, { storage: targetStorage, ids: [id] });\n };\n let dedupedCount = 0;\n // Counter for facts skipped by the importance write-gate (issue #372).\n // Emitted via the `importance_gated` metric below and rolled into the\n // final `persisted:` log line so operators can tune the threshold.\n let importanceGatedCount = 0;\n // UUI2: short-circuit semantic dedup after first backend-unavailable signal\n // within this batch. Once any fact in the batch gets reason=\"backend_unavailable\"\n // (meaning the embedding backend is degraded), subsequent facts skip the\n // lookup entirely and proceed directly to write. This prevents N-fact batches\n // from paying N × timeout when the backend is down. The flag resets per-batch\n // (declared here, inside persistExtraction) so a transient hiccup in one\n // batch does not permanently disable dedup in future batches.\n let batchBackendUnavailable = false;\n const behaviorSignalsByStorage = new Map<\n string,\n { storage: StorageManager; events: BehaviorSignalEvent[] }\n >();\n const trackBehaviorSignals = (\n targetStorage: StorageManager,\n events: BehaviorSignalEvent[],\n ): void => {\n if (events.length === 0) return;\n const key = targetStorage.dir;\n const existing = behaviorSignalsByStorage.get(key);\n if (existing) {\n existing.events.push(...events);\n return;\n }\n behaviorSignalsByStorage.set(key, {\n storage: targetStorage,\n events: [...events],\n });\n };\n const confidenceTierOrder = [\n \"explicit\",\n \"implied\",\n \"inferred\",\n \"speculative\",\n ] as const;\n const shouldPromoteToShared = (\n targetStorage: StorageManager,\n category: string,\n confidence: number,\n ): boolean => {\n if (\n !this.config.namespacesEnabled ||\n !this.config.autoPromoteToSharedEnabled\n )\n return false;\n if (\n this.namespaceFromStorageDir(targetStorage.dir) ===\n this.config.sharedNamespace\n )\n return false;\n if (!this.config.autoPromoteToSharedCategories.includes(category as any))\n return false;\n const actualTier = confidenceTier(confidence);\n const actualRank = confidenceTierOrder.indexOf(actualTier);\n const minimumRank = confidenceTierOrder.indexOf(\n this.config.autoPromoteMinConfidenceTier,\n );\n if (actualRank === -1 || minimumRank === -1) return false;\n return actualRank <= minimumRank;\n };\n const promoteMemoryToShared = async (options: {\n sourceStorage: StorageManager;\n category: string;\n content: string;\n confidence: number;\n tags: string[];\n entityRef?: string;\n structuredAttributes?: Record<string, string>;\n sourceMemoryId: string;\n importance?: ReturnType<typeof scoreImportance>;\n intentGoal?: string;\n intentActionType?: string;\n intentEntityTypes?: string[];\n memoryKind?: MemoryFrontmatter[\"memoryKind\"];\n source: string;\n }): Promise<void> => {\n if (\n !shouldPromoteToShared(\n options.sourceStorage,\n options.category,\n options.confidence,\n )\n )\n return;\n try {\n const sharedStorage = await this.storageRouter.storageFor(\n this.config.sharedNamespace,\n );\n // Dedup gate: canonicalize content before hashing.\n //\n // Issue #369 (PR #401): When inline attribution is enabled,\n // `applyInlineCitation` appends a timestamp-bearing marker (e.g.\n // `[Source: ..., ts=2026-04-11T...]`). Because the timestamp changes\n // on every call, hashing cited content produces a unique hash each\n // time — defeating dedup entirely and allowing the same logical fact to\n // be promoted repeatedly. Also, both promotion call sites pass\n // `fact.content`, which can already carry an inline citation (e.g. a\n // relayed or reprocessed fact). Strip any pre-existing citation so the\n // dedup key matches the hash stored from the original un-cited write.\n //\n // PR #402 round-6 (Fix #2 / chatgpt-codex P1 PRRT_kwDORJXyws56U74n):\n // Compute the enriched content before the hash-dedup check so the\n // lookup uses the same content that writeMemory will actually store.\n // When structuredAttributes are present, writeMemory appends an\n // \"[Attributes: ...]\" suffix before hashing; hasFactContentHash must\n // receive the same enriched body or the check is against a different\n // hash and dedup fails to fire (letting duplicates through) or fires\n // when it shouldn't (collapsing memories with different enrichments).\n // Fix #1 (P2 PRRT_kwDORJXyws56VHZc): use normalizeAttributePairs so\n // key order and casing are canonical — identical to the enrichment\n // applied by storage.writeMemory — preventing spurious hash misses\n // when attribute maps arrive with different insertion orders or casing.\n //\n // Fix #4 (Low PRRT_kwDORJXyws56VHth): sanitize the base content before\n // building dedupContent. writeMemory runs sanitizeMemoryContent on the\n // enriched body before hashing; if sanitization redacts the content to\n // REDACTED_PLACEHOLDER the stored hash is for the redacted form, not\n // the raw form. Computing dedupContent from sanitized.text here ensures\n // the hash lookup and the normalizedIncoming comparison both use the\n // same content that writeMemory will actually store.\n //\n // Combined fix: strip any pre-existing citation FIRST to obtain\n // rawContent (the canonical body), then sanitize rawContent (not\n // options.content) when building dedupContent, so that citation\n // stripping and sanitization are applied in a consistent order.\n const rawContent =\n citationEnabled &&\n hasCitationForTemplate(options.content, citationTemplate)\n ? stripCitationForTemplate(options.content, citationTemplate)\n : options.content;\n const citedContent = applyInlineCitation(rawContent);\n const sanitizedBase = sanitizeMemoryContent(rawContent);\n const dedupContent =\n options.category === \"fact\" &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ? `${sanitizedBase.text}\\n[Attributes: ${normalizeAttributePairs(options.structuredAttributes)}]`\n : sanitizedBase.text;\n if (\n options.category === \"fact\" &&\n (await sharedStorage.hasFactContentHash(dedupContent))\n ) {\n // Uj6H fix: shared-namespace temporal supersession must also run when\n // the hash-dedup short-circuit fires. Without this, an existing shared\n // fact whose structuredAttributes are stale (or an older conflicting\n // shared fact that is still active) never gets retired — supersession\n // only ran in the post-writeMemory block which is unreachable here.\n //\n // Strategy: scan the shared namespace for the existing fact whose\n // normalized content matches the incoming content, then run\n // applyTemporalSupersession against it using the same logic that\n // would have run post-writeMemory. This is a best-effort / fail-open\n // step — if the lookup fails we skip silently (same as the normal path).\n if (\n this.config.temporalSupersessionEnabled &&\n options.entityRef &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ) {\n // PR #402 round-7 (Fix #2 / Codex P1 PRRT_kwDORJXyws56VALC):\n // Track whether matchingFact lookup completed before the try block\n // so the catch block can distinguish an early-lookup failure (where\n // we don't know if a duplicate exists) from a post-lookup supersession\n // failure (where we confirmed a duplicate and must skip the write).\n let hashDedupMatchingFact: MemoryFile | undefined;\n let hashDedupLookupComplete = false;\n try {\n // Fix #2 (P2 PRRT_kwDORJXyws56VHZf): dedupContent is now built\n // from sanitizedBase.text (see fix #4 above), so normalizedIncoming\n // uses the same sanitized+normalized content that writeMemory hashes\n // and that hasFactContentHash just matched. Previously this used the\n // raw options.content, which diverged from the stored hash when\n // sanitization redacted the content, causing the candidate lookup to\n // return undefined and leaving stale facts active.\n const normalizedIncoming = ContentHashIndex.normalizeContent(dedupContent);\n const allShared = await sharedStorage.readAllMemories();\n // PR #402 round-12 (Finding Uybg): restrict hash-dedup matching to\n // the SAME entity. Content-hash equality alone can collide across\n // entities when two entities share identical fact text. Using an\n // unrelated entity's existing fact as `newMemoryId` would anchor\n // supersession to that entity's record and corrupt its\n // `supersededBy` links. Only consider facts whose normalized\n // `entityRef` matches the incoming entity.\n const incomingEntityNorm = normalizeSupersessionKey(options.entityRef);\n hashDedupMatchingFact = allShared.find((m) => {\n if (m.frontmatter.category !== \"fact\") return false;\n if ((m.frontmatter.status ?? \"active\") !== \"active\") return false;\n // Same-entity guard: skip if entity doesn't match.\n if (!m.frontmatter.entityRef) return false;\n if (normalizeSupersessionKey(m.frontmatter.entityRef) !== incomingEntityNorm) {\n log.debug(\n `persistExtraction: hash-dedup skipping cross-entity match (incoming=\"${incomingEntityNorm}\" candidate=\"${normalizeSupersessionKey(m.frontmatter.entityRef)}\")`,\n );\n return false;\n }\n // PR #402 round-7 (Fix #2): compare stored fact's full body\n // (including any appended \"[Attributes: ...]\" suffix) against the\n // enriched normalizedIncoming so the candidate selected is the one\n // whose hash actually matched in hasFactContentHash.\n return ContentHashIndex.normalizeContent(m.content ?? \"\") === normalizedIncoming;\n });\n hashDedupLookupComplete = true;\n if (hashDedupMatchingFact) {\n // Finding UvU1 (PR #402 round-11): anchor supersession to the\n // CURRENT wall-clock time, not the existing fact's persisted\n // `created`. The matching fact may be an old shared copy whose\n // `created` predates the incoming promotion event — using it as\n // `createdAt` would make the new memory appear older than the\n // existing one, preventing supersession from firing.\n // PR #402 round-12 (Finding Uyui): the matching fact is an\n // existing OLD memory — its persisted `frontmatter.created` is\n // stale relative to the incoming promotion event. Pass\n // `useCallerTimestamp: true` so the function uses\n // `createdAt` (current wall-clock) as the ordering anchor\n // instead of the old fact's timestamp, ensuring supersession\n // fires correctly even when the matching fact predates\n // conflicting candidates.\n await applyTemporalSupersession({\n storage: sharedStorage,\n newMemoryId: hashDedupMatchingFact.frontmatter.id,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: true,\n useCallerTimestamp: true,\n });\n // Active matching fact exists — normal short-circuit is safe.\n return;\n }\n // No active same-entity shared fact found with this content hash.\n // This can happen when the previously-written shared fact has since\n // been superseded (e.g. Austin → NYC → Austin reversion): the hash\n // index still records the hash but the fact is no longer active.\n // Fall through to the write path below so a new active shared\n // memory is created, then supersession fires post-write as usual.\n log.debug(\n `persistExtraction: hash-dedup found no active same-entity shared fact for ${options.sourceMemoryId}; falling through to write`,\n );\n } catch (hashDedupSupersessionErr) {\n log.warn(\n `persistExtraction: shared-namespace supersession on hash-dedup path failed open for ${options.sourceMemoryId}: ${hashDedupSupersessionErr}`,\n );\n // PR #402 round-7 (Fix #1 / cursor Medium PRRT_kwDORJXyws56U_ig):\n // Only skip the write if we CONFIRMED a matching active shared fact\n // before the error occurred (hashDedupLookupComplete is true AND\n // hashDedupMatchingFact is set). If the error was thrown before\n // matchingFact was resolved — e.g. readAllMemories() threw — we\n // cannot assume a duplicate exists, and unconditionally returning\n // would permanently lose the shared promotion. Fall through to the\n // write path so the fact is not silently dropped.\n if (hashDedupLookupComplete && hashDedupMatchingFact) {\n // A matching active shared fact was confirmed — skip the write to\n // avoid duplicating content that is already present. The existing\n // fact remains active and the supersession failure is logged above.\n return;\n }\n // Lookup did not complete or no candidate was found — we cannot\n // confirm a duplicate. Fall through to the write + post-write\n // supersession path so the shared promotion is not lost.\n log.debug(\n `persistExtraction: hash-dedup catch: lookup incomplete or no candidate found for ${options.sourceMemoryId}; falling through to write`,\n );\n }\n } else {\n // temporalSupersessionEnabled is off or no entity/attributes — keep\n // the original short-circuit behaviour.\n return;\n }\n }\n const promotedId = await sharedStorage.writeMemory(\n options.category as any,\n citedContent,\n {\n confidence: options.confidence,\n tags: [...options.tags, \"shared-promotion\"],\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n source: `${options.source}-shared-promotion`,\n importance: options.importance,\n lineage: [options.sourceMemoryId],\n sourceMemoryId: options.sourceMemoryId,\n intentGoal: options.intentGoal,\n intentActionType: options.intentActionType,\n intentEntityTypes: options.intentEntityTypes,\n memoryKind: options.memoryKind,\n // Index the RAW content hash so hasFactContentHash(rawContent)\n // returns true on subsequent extractions. Without this, the index\n // would record the hash of citedContent (which changes every call\n // due to an updated timestamp), causing duplicate promotions.\n contentHashSource: rawContent,\n },\n );\n // PR #402 Finding 3 fix: run temporal supersession against the shared\n // namespace after the promoted write lands so stale shared-namespace\n // copies of the same entity attribute are retired. Without this,\n // source-namespace supersession leaves the shared copy active and\n // shared recall continues returning the stale state. Reuses the same\n // applyTemporalSupersession helper — no logic duplication.\n if (\n this.config.temporalSupersessionEnabled &&\n options.entityRef &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ) {\n try {\n await applyTemporalSupersession({\n storage: sharedStorage,\n newMemoryId: promotedId,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: true,\n });\n } catch (sharedSupersessionErr) {\n log.warn(\n `persistExtraction: shared-namespace temporal supersession failed open for promoted ${promotedId}: ${sharedSupersessionErr}`,\n );\n }\n }\n trackPersistedId(sharedStorage, promotedId, {\n includeReturnedIds: false,\n });\n await this.indexPersistedMemory(sharedStorage, promotedId);\n trackBehaviorSignals(\n sharedStorage,\n buildBehaviorSignalsForMemory({\n memoryId: promotedId,\n category: options.category as any,\n content: options.content,\n namespace: this.config.sharedNamespace,\n confidence: options.confidence,\n source: \"extraction\",\n }),\n );\n } catch (err) {\n log.warn(\n `persistExtraction: shared promotion failed open for ${options.sourceMemoryId}: ${err}`,\n );\n }\n };\n\n // Defensive: validate result and facts array\n if (!result || !Array.isArray(result.facts)) {\n log.warn(\n \"persistExtraction: result or result.facts is invalid, skipping\",\n { resultType: typeof result, factsType: typeof result?.facts },\n );\n return persistedIds;\n }\n\n // Chunking config from plugin settings\n const chunkingConfig: ChunkingConfig = {\n targetTokens: this.config.chunkingTargetTokens,\n minTokens: this.config.chunkingMinTokens,\n overlapSentences: this.config.chunkingOverlapSentences,\n };\n\n const rawEntities = Array.isArray((result as any).entities)\n ? (result as any).entities\n : [];\n const rawQuestions = Array.isArray((result as any).questions)\n ? (result as any).questions\n : [];\n const rawProfileUpdates = Array.isArray((result as any).profileUpdates)\n ? (result as any).profileUpdates\n : [];\n\n const facts = result.facts.slice(0, this.config.extractionMaxFactsPerRun);\n const entities = rawEntities.slice(\n 0,\n this.config.extractionMaxEntitiesPerRun,\n );\n const questions = rawQuestions.slice(\n 0,\n this.config.extractionMaxQuestionsPerRun,\n );\n const profileUpdates = rawProfileUpdates.slice(\n 0,\n this.config.extractionMaxProfileUpdatesPerRun,\n );\n\n if (\n facts.length < result.facts.length ||\n entities.length < result.entities.length ||\n questions.length < result.questions.length ||\n profileUpdates.length < result.profileUpdates.length\n ) {\n log.warn(\n \"persistExtraction: capped extraction payload to guardrails \" +\n `(facts ${facts.length}/${result.facts.length}, entities ${entities.length}/${result.entities.length}, ` +\n `questions ${questions.length}/${result.questions.length}, profile ${profileUpdates.length}/${result.profileUpdates.length})`,\n );\n }\n\n // v8.2: pre-load all memories once for entity-sibling graph edges (avoids per-fact disk scan)\n type GraphStorageContext = {\n allMemsForGraph: Awaited<\n ReturnType<typeof storage.readAllMemories>\n > | null;\n memoryPathById: Map<string, string>;\n previousPersistedRelPath?: string;\n };\n const graphContextByStorageDir = new Map<string, GraphStorageContext>();\n const ensureGraphContext = async (\n targetStorage: StorageManager,\n ): Promise<GraphStorageContext> => {\n const existing = graphContextByStorageDir.get(targetStorage.dir);\n if (existing) return existing;\n const created: GraphStorageContext = {\n allMemsForGraph: null,\n memoryPathById: new Map<string, string>(),\n };\n if (this.config.multiGraphMemoryEnabled) {\n try {\n created.allMemsForGraph = await targetStorage.readAllMemories();\n for (const [id, relPath] of buildMemoryPathById(\n created.allMemsForGraph,\n targetStorage.dir,\n )) {\n created.memoryPathById.set(id, relPath);\n }\n } catch {\n /* fail-open */\n }\n }\n graphContextByStorageDir.set(targetStorage.dir, created);\n return created;\n };\n let threadEpisodeIdsForGraph: string[] | undefined;\n if (this.config.multiGraphMemoryEnabled && threadIdForExtraction) {\n try {\n const thread = await this.threading.loadThread(threadIdForExtraction);\n threadEpisodeIdsForGraph = thread?.episodeIds\n ? [...thread.episodeIds]\n : [];\n } catch {\n /* fail-open */\n }\n }\n const routeRules = await this.loadRoutingRules();\n const routeOptions = this.routeEngineOptions();\n\n // Pre-routing pass: compute the routed category for every fact BEFORE\n // building judge candidates. Route rules may override f.category (e.g.\n // via taxonomy remapping), and the judge must evaluate against the\n // *final* category that will actually be persisted — not the raw\n // extraction-time category. The per-fact write loop below reuses\n // these pre-computed results so routing is evaluated exactly once per\n // fact (no duplicated logic).\n const preRoutedCategories: Array<string | undefined> = new Array(facts.length);\n if (routeRules.length > 0) {\n for (let fi = 0; fi < facts.length; fi++) {\n const f = facts[fi];\n if (\n !f ||\n typeof f.content !== \"string\" ||\n !f.content.trim() ||\n typeof f.category !== \"string\" ||\n !f.category.trim()\n ) {\n continue;\n }\n try {\n const tags = Array.isArray(f.tags) ? f.tags : [];\n const routeText = `${f.category} ${tags.join(\" \")} ${f.content}`;\n const selected = selectRouteRule(routeText, routeRules, routeOptions);\n if (selected?.target.category) {\n preRoutedCategories[fi] = selected.target.category;\n }\n } catch {\n // Fail-open: routing errors fall through to the extracted category.\n }\n }\n }\n\n // Extraction judge gate (issue #376). When enabled, batch-evaluate all\n // candidate facts for durability before the per-fact write loop.\n // The verdicts map is keyed by candidate index — we maintain a\n // candidateIndexToFactIndex mapping so the write loop can look up\n // verdicts by original fact index.\n //\n // Candidates are built using the *routed* category (preRoutedCategories)\n // so the judge evaluates durability against the same category that will\n // be persisted, not the raw extraction-time category.\n let judgeVerdictsByFactIndex: Map<number, import(\"./extraction-judge.js\").JudgeVerdict> | null = null;\n let judgeGatedCount = 0;\n // Reset the side-channel defer count at the start of every\n // persistExtraction call so stale state from a prior call cannot leak\n // into the caller's buffer-retention decision.\n this.lastPersistExtractionDeferredCount = 0;\n if (this.config.extractionJudgeEnabled) {\n try {\n const judgeCandidates: JudgeCandidate[] = [];\n const candidateToFactIndex: number[] = [];\n for (let fi = 0; fi < facts.length; fi++) {\n const f = facts[fi];\n if (\n !f ||\n typeof f.content !== \"string\" ||\n !f.content.trim() ||\n typeof f.category !== \"string\" ||\n !f.category.trim()\n ) {\n continue;\n }\n // Use the routed category when available so the judge sees the\n // final persisted category, not the raw extraction-time value.\n // Cast to MemoryCategory — routing targets are always valid\n // category slugs defined in the taxonomy; the fallback is the\n // original ExtractedFact.category which is already typed.\n const judgeCategory = (preRoutedCategories[fi] ?? f.category) as import(\"./types.js\").MemoryCategory;\n if (judgeCategory === \"procedure\") {\n continue;\n }\n const tags = Array.isArray(f.tags) ? f.tags : [];\n const imp = scoreImportance(\n f.content,\n judgeCategory,\n tags,\n );\n // Pre-filter: skip facts below importance threshold to avoid\n // wasting LLM calls on facts that will be filtered anyway in\n // the per-fact write loop (issue #376 review finding).\n if (\n !isAboveImportanceThreshold(\n imp.level,\n this.config.extractionMinImportanceLevel,\n )\n ) {\n continue;\n }\n judgeCandidates.push({\n text: f.content,\n category: judgeCategory,\n confidence: typeof f.confidence === \"number\" ? f.confidence : 0.7,\n tags,\n importanceLevel: imp.level,\n });\n candidateToFactIndex.push(fi);\n }\n // Telemetry + training-pair emit (issue #562 PR 3 + PR 4). The\n // orchestrator wires two fire-and-forget writers behind a single\n // callback so `judgeFactDurability` does not need to know about\n // either ledger. Both handlers are skipped when their flags are\n // off; the combined callback itself is undefined when both are\n // disabled so there is zero overhead in the default configuration.\n const judgeTelemetryOpts = {\n enabled: this.config.extractionJudgeTelemetryEnabled === true,\n memoryDir: this.config.memoryDir,\n };\n const judgeTrainingOpts = {\n enabled: this.config.collectJudgeTrainingPairs === true,\n ...(this.config.judgeTrainingDir\n ? { directory: this.config.judgeTrainingDir }\n : {}),\n };\n const judgeTelemetryHandler =\n judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled\n ? (obs: import(\"./extraction-judge.js\").JudgeVerdictObservation) => {\n const ts = new Date().toISOString();\n const verdictKind = getVerdictKind(obs.verdict);\n if (judgeTelemetryOpts.enabled) {\n const event: import(\"./extraction-judge-telemetry.js\").JudgeVerdictEvent = {\n version: 1,\n category: EXTRACTION_JUDGE_VERDICT_CATEGORY,\n ts,\n verdictKind,\n reason: obs.verdict.reason,\n deferrals: obs.priorDeferrals,\n elapsedMs: obs.elapsedMs,\n candidateCategory: obs.candidate.category,\n confidence: obs.candidate.confidence,\n contentHash: obs.contentHash,\n fromCache: obs.source === \"cache\",\n ...(obs.source === \"llm-cap-rejected\"\n ? { deferCapTriggered: true }\n : {}),\n };\n void recordJudgeVerdict(event, judgeTelemetryOpts);\n }\n if (judgeTrainingOpts.enabled) {\n const pair: import(\"./extraction-judge-training.js\").JudgeTrainingPair = {\n version: 1,\n ts,\n candidateText: obs.candidate.text,\n candidateCategory: obs.candidate.category,\n ...(typeof obs.candidate.confidence === \"number\"\n ? { candidateConfidence: obs.candidate.confidence }\n : {}),\n verdictKind,\n reason: obs.verdict.reason,\n priorDeferrals: obs.priorDeferrals,\n };\n void recordJudgeTrainingPair(pair, judgeTrainingOpts);\n }\n }\n : undefined;\n const judgeResult = await judgeFactDurability(\n judgeCandidates,\n this.config,\n this.localLlm,\n new FallbackLlmClient(this.config.gatewayConfig),\n this.judgeVerdictCache,\n this.judgeDeferCounts,\n judgeTelemetryHandler,\n );\n // Remap candidate-indexed verdicts to original fact indexes\n judgeVerdictsByFactIndex = new Map();\n for (const [candidateIdx, verdict] of judgeResult.verdicts) {\n const factIdx = candidateToFactIndex[candidateIdx];\n if (factIdx !== undefined) {\n judgeVerdictsByFactIndex.set(factIdx, verdict);\n }\n }\n log.info(\n `extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ` +\n `${judgeResult.cached} cached, ${judgeResult.judged} judged, ` +\n `${judgeResult.deferred} deferred` +\n (judgeResult.deferredCappedToReject > 0\n ? ` (${judgeResult.deferredCappedToReject} cap-rejected)`\n : \"\") +\n `, ${judgeResult.elapsed}ms`,\n );\n // Expose defer count to the caller (issue #562 PR 2) so it can decide\n // whether to retain buffer turns for the next extraction pass.\n this.lastPersistExtractionDeferredCount = judgeResult.deferred;\n } catch (err) {\n // Fail-open: if the entire judge pipeline errors, proceed without filtering\n log.warn(\n `extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n let factLoopIndex = -1;\n for (const fact of facts) {\n factLoopIndex++;\n if (\n !fact ||\n typeof (fact as any).content !== \"string\" ||\n !(fact as any).content.trim()\n ) {\n continue;\n }\n if (\n typeof (fact as any).category !== \"string\" ||\n !(fact as any).category.trim()\n ) {\n continue;\n }\n (fact as any).tags = Array.isArray((fact as any).tags)\n ? (fact as any).tags.filter((t: any) => typeof t === \"string\")\n : [];\n (fact as any).confidence =\n typeof (fact as any).confidence === \"number\"\n ? (fact as any).confidence\n : 0.7;\n\n // Content-hash dedup check (v6.0)\n //\n // Canonicalize pre-tagged facts before hashing (Codex P2 — issue #369).\n // When a fact already carries an inline citation (e.g. relayed or\n // reprocessed), hashing `fact.content` as-is would produce a different\n // hash than the one stored from the original write (which used the raw,\n // un-cited body as contentHashSource). Strip any citation first so the\n // dedup key matches what the hash index recorded.\n //\n // stripCitationForTemplate handles both the default and custom template\n // formats. For all-placeholder templates it cannot detect citations and\n // returns the text unchanged — dedup may miss in that edge case, which\n // is acceptable (no false-positive suppression).\n //\n // Routing runs before content-hash dedup and scoring so category overrides\n // affect both the dedup fingerprint and importance (issue #519 procedure routing).\n let writeCategory = fact.category;\n let targetStorage = storage;\n let routedRuleId: string | undefined;\n let routedNamespaceExplicit = false;\n if (routeRules.length > 0) {\n try {\n const routeText = `${fact.category} ${fact.tags.join(\" \")} ${fact.content}`;\n const selected = selectRouteRule(routeText, routeRules, routeOptions);\n if (selected) {\n routedRuleId = selected.rule.id;\n if (selected.target.category) {\n writeCategory = selected.target.category;\n }\n if (selected.target.namespace) {\n routedNamespaceExplicit = true;\n targetStorage = await this.storageRouter.storageFor(\n selected.target.namespace,\n );\n }\n }\n } catch (err) {\n log.warn(\n `routing evaluation failed; fail-open to extracted category/namespace: ${err}`,\n );\n }\n }\n\n // Scope-based namespace routing: when scope classification is enabled\n // and the LLM tagged this fact as \"global\", route it to the shared\n // namespace so cross-project knowledge is visible everywhere. Only\n // applies when namespaces are enabled and the fact was not already\n // routed to a specific namespace by a routing rule (routing rules\n // that set an explicit namespace take precedence; category-only rules\n // do not block scope routing). Rule 30: gated by\n // extractionScopeClassificationEnabled.\n if (\n this.config.extractionScopeClassificationEnabled &&\n this.config.namespacesEnabled &&\n fact.scope === \"global\" &&\n !routedNamespaceExplicit\n ) {\n const currentNs = this.namespaceFromStorageDir(targetStorage.dir);\n if (currentNs !== this.config.sharedNamespace) {\n try {\n targetStorage = await this.storageRouter.storageFor(\n this.config.sharedNamespace,\n );\n log.debug(\n `scope-routing: fact \"${fact.content.slice(0, 60)}…\" routed to shared namespace (scope=global)`,\n );\n } catch (scopeRouteErr) {\n log.warn(\n `scope-routing: failed to resolve shared namespace storage; writing to session namespace (fail-open): ${scopeRouteErr}`,\n );\n }\n }\n }\n\n // Procedures: fingerprint the full serialized body (title + steps), not\n // the title alone, so distinct step lists are not collapsed (issue #519).\n const canonicalContentForHash =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const contentHashDedupKey =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : canonicalContentForHash;\n if (this.contentHashIndex && this.contentHashIndex.has(contentHashDedupKey)) {\n log.debug(\n `dedup: skipping duplicate fact \"${fact.content.slice(0, 60)}…\"`,\n );\n dedupedCount++;\n continue;\n }\n\n // Score importance using local heuristics (Phase 1B).\n // writeCategory / targetStorage already reflect routing.\n const importance = scoreImportance(\n fact.content,\n writeCategory,\n fact.tags,\n );\n\n if (writeCategory === \"procedure\" && this.config.procedural?.enabled !== true) {\n log.debug(\"persistExtraction: skip procedure memory (procedural.enabled is false)\");\n continue;\n }\n\n // Importance write-gate (issue #372). Drop facts whose locally-scored\n // level falls below the configured minimum BEFORE the semantic dedup\n // lookup so that low-importance facts never incur an embedding search.\n // scoreImportance() already applies category boosts (e.g. corrections\n // +0.15) before deriving the level, so a correction at raw ~0.35\n // still lands at \"normal\" and passes the default gate. Without this\n // gate, trivial turn-level chatter (\"hi\", \"k\", heartbeat pings) gets\n // persisted as a fact memory and dilutes the store.\n if (\n !isAboveImportanceThreshold(\n importance.level,\n this.config.extractionMinImportanceLevel,\n )\n ) {\n importanceGatedCount++;\n const snippet = fact.content.slice(0, 60).replace(/\\s+/g, \" \").trim();\n log.debug(`extraction: skip trivial \"${snippet}\"`);\n // Log-based counter (no dedicated metric bus in remnic-core yet).\n // Operators can grep for `metric:importance_gated` in gateway.log\n // to tune extractionMinImportanceLevel.\n log.debug(\n `metric:importance_gated level=${importance.level} threshold=${this.config.extractionMinImportanceLevel} category=${writeCategory} count=${importanceGatedCount}`,\n );\n continue;\n }\n\n // Extraction judge gate (issue #376 + #562 PR 2). After the local\n // importance gate passes, consult the judge verdict (computed before\n // the loop). In active mode, non-durable facts are dropped. In shadow\n // mode, verdicts are logged but all facts proceed to write.\n //\n // Defer verdicts (issue #562): do not persist now, but also do not\n // cache the outcome so the candidate is re-evaluated on a later\n // extraction pass. The judge module tracks how many times the same\n // content has been deferred and converts to reject at the configured\n // cap, so the orchestrator only needs to skip the write here.\n if (judgeVerdictsByFactIndex) {\n const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);\n if (verdict && !verdict.durable) {\n const verdictKind = getVerdictKind(verdict);\n if (this.config.extractionJudgeShadow) {\n log.info(\n `extraction-judge[shadow]: would ${verdictKind} \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n } else if (verdictKind === \"defer\") {\n judgeGatedCount++;\n log.debug(\n `extraction-judge: deferred \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n continue;\n } else {\n judgeGatedCount++;\n log.debug(\n `extraction-judge: rejected \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n continue;\n }\n }\n }\n\n // Procedure extraction gate (issue #519): ≥2 steps + trigger phrasing.\n // Runs even when extractionJudgeEnabled is false (durability judge is unrelated).\n // Never tied to extractionJudgeShadow — that flag is only for the LLM durability judge.\n if (writeCategory === \"procedure\") {\n const procGate = validateProcedureExtraction({\n content: fact.content,\n procedureSteps: fact.procedureSteps,\n });\n if (!procGate.durable) {\n log.debug(\n `extraction-procedure-gate: rejected \"${fact.content.slice(0, 60)}…\" reason=\"${procGate.reason}\"`,\n );\n continue;\n }\n }\n\n // Issue #373 — write-time semantic similarity guard. Hook runs after\n // the exact content-hash miss and the importance gate so that:\n // (a) paraphrased near-duplicates never reach writeMemory(), and\n // (b) low-importance facts that will be dropped never trigger an\n // embedding lookup (avoids unnecessary API latency/cost).\n // Fails open when the embedding backend is unavailable.\n //\n // Defense in depth (PR #399 review): decideSemanticDedup already\n // catches lookup errors internally, and the embedding fetch is\n // bounded by a timeout in embedding-fallback.ts. We still wrap the\n // whole call in its own try/catch here so that any unexpected\n // rejection (future refactors, misbehaving custom backends, etc.)\n // can never block the persist loop — a failure in the dedup path\n // must always default to \"not a duplicate\".\n // Track a pending semantic-skip decision (populated inside the block\n // below). The actual drop happens AFTER contradiction detection so that\n // a high-similarity update/correction is linked as a superseding\n // contradiction rather than silently dropped.\n let pendingSemanticSkip: (SemanticDedupDecision & { action: \"skip\" }) | null = null;\n if (this.config.semanticDedupEnabled) {\n let semanticDecision: SemanticDedupDecision;\n // UUI2: skip embedding lookup for the rest of this batch once we know\n // the backend is unavailable. The flag is reset per-batch (set to false\n // at the top of persistExtraction), so a transient hiccup in one call\n // does not permanently disable dedup in subsequent calls.\n if (batchBackendUnavailable) {\n semanticDecision = { action: \"keep\", reason: \"backend_unavailable\" };\n } else {\n try {\n // Pass the resolved target storage so the lookup scopes the\n // embedding index to the target namespace (PR #399 P1 fix).\n // Without this, a high-similarity hit in a different namespace\n // would cause the fact to be dropped here — cross-namespace\n // write suppression / data loss.\n const lookupStorage = targetStorage;\n semanticDecision = await decideSemanticDedup(\n fact.content,\n (content, limit) =>\n this.semanticDedupLookup(content, limit, lookupStorage),\n {\n enabled: true,\n threshold: this.config.semanticDedupThreshold,\n candidates: this.config.semanticDedupCandidates,\n },\n );\n } catch (err) {\n log.warn(\n `semantic dedup decision failed; failing open and writing fact: ${err}`,\n );\n semanticDecision = {\n action: \"keep\",\n reason: \"backend_unavailable\",\n };\n }\n // UUI2: cache the backend-unavailable signal for the rest of this batch.\n if (semanticDecision.reason === \"backend_unavailable\") {\n batchBackendUnavailable = true;\n }\n }\n if (semanticDecision.action === \"skip\") {\n pendingSemanticSkip = semanticDecision;\n }\n }\n\n const inferredIntent = this.config.intentRoutingEnabled\n ? inferIntentFromText(\n `${writeCategory} ${fact.tags.join(\" \")} ${fact.content}`,\n )\n : null;\n const extractionWriteSource =\n (fact as any).source === \"proactive\"\n ? \"extraction-proactive\"\n : \"extraction\";\n\n // Check for contradictions before writing (Phase 2B).\n // NOTE: This block was moved above the chunking branch so that the\n // pendingSemanticSkip guard (below) can also protect the chunking path.\n // Previously, contradiction detection only ran on the non-chunked path,\n // meaning chunked facts could be persisted even when semanticDecision was\n // \"skip\" (the deferred guard was bypassed by the chunking `continue`).\n let supersedes: string | undefined;\n let links: MemoryLink[] = [];\n // True when contradiction detection ran and confirmed a contradiction,\n // regardless of whether auto-resolve is enabled. Used by the\n // semantic-skip guard so that contradictory updates are never silently\n // dropped — even when `contradictionAutoResolve=false` (in which case\n // `supersedes` is intentionally left unset to avoid retiring the old\n // memory without user confirmation).\n let contradictionDetected = false;\n\n if (this.config.contradictionDetectionEnabled && this.qmd.isAvailable()) {\n const targetNamespace = this.namespaceFromStorageDir(targetStorage.dir);\n const contradiction = await this.checkForContradiction(\n fact.content,\n writeCategory,\n targetNamespace,\n );\n if (contradiction) {\n contradictionDetected = true;\n // When auto-resolve is enabled the existing memory has already been\n // marked superseded; set `supersedes` so the new write carries the\n // relationship. When auto-resolve is disabled we still record the\n // contradiction link (so the memory is annotated for manual review)\n // but do NOT set `supersedes` on the new write — the old memory\n // remains active until a human resolves it.\n if (this.config.contradictionAutoResolve) {\n supersedes = contradiction.supersededId;\n }\n links.push({\n targetId: contradiction.supersededId,\n linkType: \"contradicts\",\n strength: contradiction.confidence,\n reason: contradiction.reason,\n });\n // Deindex the superseded memory so stale paths don't remain in\n // index_time.json / index_tags.json after the incremental update.\n // Only applicable when auto-resolve is on and the old memory is\n // actually being retired; skip when manual review is required.\n if (\n this.config.contradictionAutoResolve &&\n this.config.queryAwareIndexingEnabled &&\n contradiction.supersededPath\n ) {\n deindexMemory(\n this.config.memoryDir,\n contradiction.supersededPath,\n contradiction.supersededCreated,\n contradiction.supersededTags,\n );\n }\n }\n }\n\n // Apply the deferred semantic-skip now that contradiction detection has\n // run. If a contradiction was found (contradictionDetected is true), the\n // candidate is a contradictory update and must be written — do not skip\n // it. Only drop it when there is no detected contradiction (true\n // near-duplicate). This check intentionally runs BEFORE the chunking\n // branch so that a fact flagged as a semantic near-duplicate cannot be\n // persisted (with its hash registered) simply because it was long enough\n // to trigger chunking.\n //\n // NOTE: We use `contradictionDetected` rather than `!!supersedes` here\n // so that facts are preserved even when `contradictionAutoResolve=false`.\n // When auto-resolve is disabled `supersedes` is intentionally unset, but\n // the write must still proceed so the user can manually reconcile the\n // two memories later.\n //\n // UUI1: correction category writes are NEVER suppressed by the semantic\n // skip fallback, regardless of whether supersedes is set. When contradiction\n // detection is disabled or QMD is unavailable, supersedes is never set —\n // without this exemption a high-similarity correction would be silently\n // dropped, leaving a stale fact active. writeCategory (not fact.category)\n // is used because routing rules may have overridden the raw category.\n const isCorrection = writeCategory === \"correction\";\n if (pendingSemanticSkip && !contradictionDetected && !isCorrection) {\n log.debug(\n `dedup: skipping semantic near-duplicate fact \"${fact.content\n .slice(0, 60)\n .replace(/\\s+/g, \" \")}…\" score=${pendingSemanticSkip.topScore.toFixed(\n 3,\n )} neighbor=${pendingSemanticSkip.topId}`,\n );\n dedupedCount++;\n // Do NOT add fact.content to contentHashIndex here. No memory was\n // persisted for this fact, so registering a synthetic hash would\n // permanently suppress exact-copy writes once the neighbor memory is\n // archived or deleted (the hash would linger with no backing record).\n continue;\n }\n\n // Check if chunking is enabled and content should be chunked.\n // When semanticChunkingEnabled is true, prefer the embedding-based\n // semantic chunker which produces more coherent topic-aligned segments.\n // Falls back to the recursive sentence-boundary chunker on failure.\n if (this.config.chunkingEnabled && writeCategory !== \"procedure\") {\n let chunkResult: { chunked: boolean; chunks: { content: string; index: number; tokenCount: number }[] };\n\n if (this.config.semanticChunkingEnabled) {\n try {\n const embedFn = this.embeddingFallback.embedTexts.bind(this.embeddingFallback);\n const semanticResult: SemanticChunkResult = await semanticChunkContent(\n fact.content,\n embedFn,\n this.config.semanticChunkingConfig,\n );\n chunkResult = semanticResult;\n } catch (err) {\n // Honor the fallbackToRecursive contract: when the user explicitly\n // disables fallback, re-throw so extraction fails fast instead of\n // silently using the recursive chunker. semanticChunkContent already\n // throws when fallback is disabled, but this outer catch swallowed\n // that signal. (PR #439 post-merge Finding 1.)\n if (this.config.semanticChunkingConfig?.fallbackToRecursive === false) {\n throw err;\n }\n log.debug(\n `semantic chunking failed, falling back to recursive chunker: ${err}`,\n );\n chunkResult = chunkContent(fact.content, chunkingConfig);\n }\n } else {\n chunkResult = chunkContent(fact.content, chunkingConfig);\n }\n\n if (chunkResult.chunked && chunkResult.chunks.length > 1) {\n // Classify memory kind (v8.0 Phase 2B: HiMem episode/note dual store)\n const memoryKind = this.config.episodeNoteModeEnabled\n ? classifyMemoryKind(fact.content, fact.tags ?? [], writeCategory)\n : undefined;\n\n // Write the parent memory first (with full content for reference).\n //\n // Compute the cited content once so that writeMemory and writeArtifact\n // (when verbatim artifacts are enabled) share the same citation timestamp.\n // See the normal write path comment for the full dedup rationale.\n //\n // Propagate supersedes/links from contradiction detection (round 6\n // fix): contradiction detection now runs BEFORE this branch so the\n // parent must carry the supersession relationship — without it the\n // old memory is deindexed but the new chunked parent has no link\n // back, leaving a dangling deindex with no replacement reference.\n // Child chunks intentionally do NOT carry supersedes; only the\n // parent represents the logical memory unit.\n //\n // Canonicalize contentHashSource before writing (Thread 3 — Codex P2,\n // issue #369). If fact.content already carries an inline citation\n // (e.g. re-processed or relayed fact), strip it so contentHashSource\n // records the raw un-cited body — matching what the dedup check hashes\n // via stripCitationForTemplate before calling hasFactContentHash.\n const rawChunkedContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const citedChunkedContent = applyInlineCitation(rawChunkedContent);\n const parentId = await targetStorage.writeMemory(\n writeCategory,\n citedChunkedContent,\n {\n confidence: fact.confidence,\n tags: [...fact.tags, \"chunked\"],\n entityRef: fact.entityRef,\n source: extractionWriteSource,\n importance,\n supersedes,\n links: links.length > 0 ? links : undefined,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n structuredAttributes: fact.structuredAttributes,\n contentHashSource: rawChunkedContent,\n },\n );\n\n // Write individual chunks with parent reference\n for (const chunk of chunkResult.chunks) {\n // Score each chunk's importance separately\n const chunkImportance = scoreImportance(\n chunk.content,\n writeCategory,\n fact.tags,\n );\n const chunkWriteSource =\n (fact as any).source === \"proactive\"\n ? \"chunking-proactive\"\n : \"chunking\";\n\n await targetStorage.writeChunk(\n parentId,\n chunk.index,\n chunkResult.chunks.length,\n writeCategory,\n // Each chunk carries its own inline citation so provenance\n // survives when a single chunk is quoted in isolation.\n applyInlineCitation(chunk.content),\n {\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef: fact.entityRef,\n source: chunkWriteSource,\n importance: chunkImportance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n },\n );\n }\n\n if (routedRuleId) {\n log.debug(\n `routing applied for chunked memory ${parentId}: rule=${routedRuleId} category=${writeCategory} storage=${targetStorage.dir}`,\n );\n }\n log.debug(\n `chunked memory ${parentId} into ${chunkResult.chunks.length} chunks`,\n );\n trackPersistedId(targetStorage, parentId);\n if (\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(parentId)\n ) {\n threadEpisodeIdsForGraph.push(parentId);\n }\n await this.indexPersistedMemory(targetStorage, parentId);\n // PR #402 Thread 1 fix: run source-namespace temporal supersession for\n // chunked writes, matching the non-chunked path. Without this the\n // source namespace retains stale facts that should have been superseded.\n try {\n const supersessionEntityRef =\n typeof (fact as any).entityRef === \"string\"\n ? ((fact as any).entityRef as string)\n : undefined;\n await applyTemporalSupersession({\n storage: targetStorage,\n newMemoryId: parentId,\n entityRef: supersessionEntityRef,\n structuredAttributes: fact.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: this.config.temporalSupersessionEnabled,\n });\n } catch (err) {\n log.warn(`temporal-supersession (chunked): unexpected error: ${err}`);\n }\n await promoteMemoryToShared({\n sourceStorage: targetStorage,\n category: writeCategory,\n content: fact.content,\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef: fact.entityRef,\n structuredAttributes: fact.structuredAttributes,\n sourceMemoryId: parentId,\n importance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n source: extractionWriteSource,\n });\n // Register chunked content in hash index too.\n // Thread 3 fix: canonicalize by stripping any pre-existing citation\n // so the stored hash matches what the dedup check computes via\n // stripCitationForTemplate before calling contentHashIndex.has().\n if (this.contentHashIndex) {\n const canonicalChunkedContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n this.contentHashIndex.add(canonicalChunkedContent);\n }\n\n for (const chunk of chunkResult.chunks) {\n const chunkId = `${parentId}-chunk-${chunk.index}`;\n // Do NOT push chunkId into persistedIds — chunk IDs must not leak\n // into boxBuilder.onExtraction() or threading.processTurn(), which\n // only expect canonical parent memory IDs. Call indexPersistedMemory\n // directly for embedding-fallback sync of each chunk document.\n await this.indexPersistedMemory(targetStorage, chunkId);\n }\n if (\n this.config.verbatimArtifactsEnabled &&\n this.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.config.verbatimArtifactsMinConfidence\n ) {\n // Reuse citedChunkedContent so the artifact carries the same citation\n // timestamp as the parent memory write above (Fix #3 — duplicate-citation).\n await targetStorage.writeArtifact(citedChunkedContent, {\n confidence: fact.confidence,\n tags: [...fact.tags, \"artifact\", \"chunked-parent\"],\n artifactType: this.artifactTypeForCategory(writeCategory),\n sourceMemoryId: parentId,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n });\n }\n // v8.2: graph edge building for chunked memories\n if (this.config.multiGraphMemoryEnabled) {\n try {\n const graphContext = await ensureGraphContext(targetStorage);\n const entityRef =\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined;\n const parentRelPath = resolvePersistedMemoryRelativePath({\n memoryId: parentId,\n pathById: graphContext.memoryPathById,\n category: writeCategory,\n });\n graphContext.memoryPathById.set(parentId, parentRelPath);\n appendMemoryToGraphContext({\n allMemsForGraph: graphContext.allMemsForGraph,\n storageDir: targetStorage.dir,\n memoryRelPath: parentRelPath,\n memoryId: parentId,\n category: writeCategory,\n content: fact.content ?? \"\",\n entityRef,\n });\n await this.buildGraphEdge(\n targetStorage,\n parentRelPath,\n entityRef,\n parentId,\n fact.content ?? \"\",\n graphContext.allMemsForGraph,\n graphContext.memoryPathById,\n threadIdForExtraction ?? undefined,\n threadEpisodeIdsForGraph,\n graphContext.previousPersistedRelPath,\n );\n graphContext.previousPersistedRelPath = parentRelPath;\n } catch {\n /* fail-open */\n }\n }\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId: parentId,\n category: writeCategory,\n content: fact.content,\n namespace: this.namespaceFromStorageDir(targetStorage.dir),\n confidence: fact.confidence,\n source: \"extraction\",\n }),\n );\n continue; // Skip the normal write below\n }\n }\n\n // Suggest links for this memory (Phase 3A)\n if (this.config.memoryLinkingEnabled && this.qmd.isAvailable()) {\n const targetNamespace = this.namespaceFromStorageDir(targetStorage.dir);\n const suggestedLinks = await this.suggestLinksForMemory(\n fact.content,\n writeCategory,\n targetNamespace,\n );\n if (suggestedLinks.length > 0) {\n links.push(...suggestedLinks);\n }\n }\n\n // Classify memory kind (v8.0 Phase 2B: HiMem episode/note dual store)\n const memoryKind =\n writeCategory === \"procedure\"\n ? undefined\n : this.config.episodeNoteModeEnabled\n ? classifyMemoryKind(fact.content, fact.tags ?? [], writeCategory)\n : undefined;\n\n // Normal write (no chunking)\n //\n // Compute the cited content once so that writeMemory and writeArtifact\n // (when verbatim artifacts are enabled) share the same citation timestamp.\n // Calling applyInlineCitation twice on the same raw content would produce\n // two different timestamps, creating duplicate citations with divergent\n // provenance metadata on the memory and artifact copies of the same fact.\n //\n // Pass the RAW (pre-citation) fact as `contentHashSource` so the\n // fact-content hash index records the hash of the canonical fact text\n // rather than the citation-annotated variant. When inline attribution is\n // enabled, `applyInlineCitation` appends a timestamp-bearing marker, so\n // hashing the persisted body would produce a different hash on every\n // write and defeat cross-session dedup (see `findDuplicateExplicitCapture`\n // in explicit-capture.ts which calls `hasFactContentHash(candidate.content)`\n // on raw content).\n const rawPersistBody =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : fact.content;\n const citedFactContent = applyInlineCitation(rawPersistBody);\n const memoryId = await targetStorage.writeMemory(\n writeCategory,\n citedFactContent,\n {\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef:\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined,\n source: extractionWriteSource,\n importance,\n supersedes,\n links: links.length > 0 ? links : undefined,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n structuredAttributes: fact.structuredAttributes,\n contentHashSource: writeCategory === \"fact\" ? fact.content : undefined,\n },\n );\n if (routedRuleId) {\n log.debug(\n `routing applied for memory ${memoryId}: rule=${routedRuleId} category=${writeCategory} storage=${targetStorage.dir}`,\n );\n }\n // Temporal supersession (issue #375): when the new fact has structured\n // attributes, retire any older fact with the same entity + attribute\n // key that has a conflicting value.\n try {\n const supersessionEntityRef =\n typeof (fact as any).entityRef === \"string\"\n ? ((fact as any).entityRef as string)\n : undefined;\n await applyTemporalSupersession({\n storage: targetStorage,\n newMemoryId: memoryId,\n entityRef: supersessionEntityRef,\n structuredAttributes: fact.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: this.config.temporalSupersessionEnabled,\n });\n } catch (err) {\n log.warn(`temporal-supersession: unexpected error: ${err}`);\n }\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId,\n category: writeCategory,\n content: fact.content,\n namespace: this.namespaceFromStorageDir(targetStorage.dir),\n confidence: fact.confidence,\n source: \"extraction\",\n }),\n );\n trackPersistedId(targetStorage, memoryId);\n if (\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(memoryId)\n ) {\n threadEpisodeIdsForGraph.push(memoryId);\n }\n await this.indexPersistedMemory(targetStorage, memoryId);\n await promoteMemoryToShared({\n sourceStorage: targetStorage,\n category: writeCategory,\n content: fact.content,\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef:\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined,\n structuredAttributes: fact.structuredAttributes,\n sourceMemoryId: memoryId,\n importance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n source: extractionWriteSource,\n });\n // v8.2: graph edge building (fail-open — errors caught inside GraphIndex)\n if (this.config.multiGraphMemoryEnabled) {\n try {\n const graphContext = await ensureGraphContext(targetStorage);\n const entityRef =\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined;\n const memoryRelPath = resolvePersistedMemoryRelativePath({\n memoryId,\n pathById: graphContext.memoryPathById,\n category: writeCategory,\n });\n graphContext.memoryPathById.set(memoryId, memoryRelPath);\n appendMemoryToGraphContext({\n allMemsForGraph: graphContext.allMemsForGraph,\n storageDir: targetStorage.dir,\n memoryRelPath: memoryRelPath,\n memoryId,\n category: writeCategory,\n content: fact.content ?? \"\",\n entityRef,\n });\n await this.buildGraphEdge(\n targetStorage,\n memoryRelPath,\n entityRef,\n memoryId,\n fact.content ?? \"\",\n graphContext.allMemsForGraph,\n graphContext.memoryPathById,\n threadIdForExtraction ?? undefined,\n threadEpisodeIdsForGraph,\n graphContext.previousPersistedRelPath,\n );\n graphContext.previousPersistedRelPath = memoryRelPath;\n } catch {\n /* fail-open */\n }\n }\n if (\n this.config.verbatimArtifactsEnabled &&\n this.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.config.verbatimArtifactsMinConfidence\n ) {\n // Reuse citedFactContent so the artifact carries the same citation\n // timestamp as the memory write above (Fix #3 — duplicate-citation).\n await targetStorage.writeArtifact(citedFactContent, {\n confidence: fact.confidence,\n tags: [...fact.tags, \"artifact\"],\n artifactType: this.artifactTypeForCategory(writeCategory),\n sourceMemoryId: memoryId,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n });\n }\n // Register in content-hash index after successful write.\n // Thread 3 fix: canonicalize by stripping any pre-existing citation so\n // the stored hash matches what the dedup check computes via\n // stripCitationForTemplate before calling contentHashIndex.has().\n if (this.contentHashIndex) {\n const canonicalFactContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const hashRegisterKey =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : canonicalFactContent;\n this.contentHashIndex.add(hashRegisterKey);\n }\n }\n\n for (const entity of entities) {\n try {\n const name = (entity as any)?.name;\n const type = (entity as any)?.type;\n if (\n typeof name !== \"string\" ||\n !name.trim() ||\n typeof type !== \"string\" ||\n !type.trim()\n ) {\n continue;\n }\n const safeFacts = Array.isArray((entity as any)?.facts)\n ? (entity as any).facts.filter((f: any) => typeof f === \"string\")\n : [];\n const id = await storage.writeEntity(name, type, safeFacts, {\n source: typeof (entity as any)?.source === \"string\" ? (entity as any).source : \"extraction\",\n sessionKey: sourceContext?.sessionKey,\n principal: sourceContext?.principal,\n structuredSections: Array.isArray((entity as any)?.structuredSections)\n ? (entity as any).structuredSections\n : undefined,\n });\n if (id) trackPersistedId(storage, id);\n } catch (err) {\n log.warn(`persistExtraction: entity write failed: ${err}`);\n }\n }\n\n // Persist entity relationships (v7.0)\n if (\n this.config.entityRelationshipsEnabled &&\n Array.isArray(result.relationships)\n ) {\n for (const rel of result.relationships.slice(0, 5)) {\n if (!rel.source || !rel.target || !rel.label) continue;\n try {\n // Add bidirectional relationship\n await storage.addEntityRelationship(rel.source, {\n target: rel.target,\n label: rel.label,\n });\n await storage.addEntityRelationship(rel.target, {\n target: rel.source,\n label: `${rel.label} (reverse)`,\n });\n } catch (err) {\n log.debug(`relationship persist failed: ${err}`);\n }\n }\n }\n\n // Persist entity activity (v7.0)\n if (this.config.entityActivityLogEnabled) {\n const today = new Date().toISOString().slice(0, 10);\n for (const entity of entities) {\n const name = (entity as any)?.name;\n const type = (entity as any)?.type;\n if (typeof name !== \"string\" || typeof type !== \"string\") continue;\n try {\n const normalized = normalizeEntityName(name, type);\n await storage.addEntityActivity(\n normalized,\n { date: today, note: \"Mentioned in conversation\" },\n this.config.entityActivityLogMaxEntries,\n );\n } catch (err) {\n log.debug(`activity persist failed: ${err}`);\n }\n }\n }\n\n if (profileUpdates.length > 0) {\n await storage.appendToProfile(profileUpdates);\n }\n\n // Persist questions\n for (const q of questions) {\n const id = await storage.writeQuestion(q.question, q.context, q.priority);\n if (id) trackPersistedId(storage, id);\n }\n\n // Persist identity reflection\n if (this.config.identityEnabled && result.identityReflection) {\n try {\n await storage.appendIdentityReflection(result.identityReflection);\n } catch (err) {\n log.debug(`identity reflection write failed: ${err}`);\n }\n }\n\n // Save content-hash index after batch\n if (this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) => log.warn(`content-hash index save failed: ${err}`));\n }\n\n for (const {\n storage: targetStorage,\n events,\n } of behaviorSignalsByStorage.values()) {\n const dedupedSignals = dedupeBehaviorSignalsByMemoryAndHash(events);\n if (dedupedSignals.length === 0) continue;\n await targetStorage\n .appendBehaviorSignals(dedupedSignals)\n .catch((err) =>\n log.warn(`appendBehaviorSignals failed (non-fatal): ${err}`),\n );\n }\n\n const dedupSuffix = dedupedCount > 0 ? ` (${dedupedCount} deduped)` : \"\";\n const gatedSuffix =\n importanceGatedCount > 0 ? ` (${importanceGatedCount} gated)` : \"\";\n const judgeSuffix =\n judgeGatedCount > 0 ? ` (${judgeGatedCount} judge-rejected)` : \"\";\n log.info(\n `persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}, ${entities.length} entities, ${questions.length} questions, ${profileUpdates.length} profile updates`,\n );\n\n // Update temporal + tag indexes (v8.1) — fire-and-forget, fail-open\n void (async () => {\n if (persistedIdsByStorage.size === 0) {\n await this.updateTemporalTagIndexes(storage, []);\n return;\n }\n for (const entry of persistedIdsByStorage.values()) {\n await this.updateTemporalTagIndexes(entry.storage, entry.ids);\n }\n })().catch((err) =>\n log.debug(`temporal-index update error (non-fatal): ${err}`),\n );\n\n // Return the persisted fact IDs for threading\n return persistedIds;\n }\n\n private async indexPersistedMemory(\n storage: StorageManager,\n memoryId: string,\n ): Promise<void> {\n if (!this.config.embeddingFallbackEnabled) return;\n if (!(await this.embeddingFallback.isAvailable())) return;\n const memory = await storage.getMemoryById(memoryId);\n if (!memory) return;\n await this.embeddingFallback.indexFile(\n memoryId,\n memory.content,\n memory.path,\n );\n }\n\n /**\n * Build a graph edge for a persisted memory (v8.2).\n * Shared helper used by both the chunked and non-chunked write paths to avoid duplication.\n * Fail-open: caller wraps in try/catch.\n */\n private async buildGraphEdge(\n storage: StorageManager,\n memoryRelPath: string,\n entityRef: string | undefined,\n memoryId: string,\n factContent: string,\n allMemsForGraph: import(\"./types.js\").MemoryFile[] | null | undefined,\n memoryPathById: Map<string, string>,\n threadIdForEdge: string | undefined,\n threadEpisodeIdsForGraph: string[] | undefined,\n fallbackCausalPredecessor: string | undefined,\n ): Promise<void> {\n // Entity siblings: other memories sharing the same entityRef\n const entitySiblings: string[] = [];\n if (entityRef) {\n try {\n const allMems = allMemsForGraph ?? [];\n for (const m of allMems) {\n if (m.frontmatter.entityRef === entityRef) {\n const rel = path.relative(storage.dir, m.path);\n if (rel !== memoryRelPath) entitySiblings.push(rel);\n }\n }\n } catch {\n /* fail-open */\n }\n }\n // Recent thread memories for time graph\n const recentInThread: string[] = [];\n if (threadIdForEdge && threadEpisodeIdsForGraph?.length) {\n try {\n recentInThread.push(\n ...resolveRecentThreadMemoryPaths({\n threadEpisodeIds: threadEpisodeIdsForGraph,\n currentMemoryId: memoryId,\n allMemsForGraph,\n pathById: memoryPathById,\n storageDir: storage.dir,\n maxRecent: 3,\n }),\n );\n } catch {\n /* fail-open */\n }\n }\n if (\n recentInThread.length === 0 &&\n this.config.graphWriteSessionAdjacencyEnabled !== false &&\n fallbackCausalPredecessor &&\n fallbackCausalPredecessor !== memoryRelPath\n ) {\n recentInThread.push(fallbackCausalPredecessor);\n }\n const causalPredecessor =\n recentInThread[recentInThread.length - 1] ?? fallbackCausalPredecessor;\n await this.graphIndexFor(storage).onMemoryWritten({\n memoryPath: memoryRelPath,\n entityRef,\n content: factContent,\n created: new Date().toISOString(),\n threadId: threadIdForEdge,\n recentInThread,\n entitySiblings,\n causalPredecessor,\n });\n }\n\n private graphIndexFor(storage: StorageManager): GraphIndex {\n const key = storage.dir;\n const existing = this.graphIndexes.get(key);\n if (existing) return existing;\n const created = new GraphIndex(key, this.config);\n this.graphIndexes.set(key, created);\n return created;\n }\n\n /**\n * Batch-update temporal and tag indexes after extraction (v8.1).\n * Reads each persisted memory's path + frontmatter and adds them to\n * state/index_time.json and state/index_tags.json.\n * Fail-open: any error is logged but does not abort extraction.\n */\n private async updateTemporalTagIndexes(\n storage: StorageManager,\n persistedIds: string[],\n ): Promise<void> {\n // Build temporal/tag indexes whenever either consumer is enabled:\n // - queryAwareIndexingEnabled: uses indexes for query-aware prefiltering in recall\n // - parallelRetrievalEnabled: temporal agent reads index_time.json for date-range lookup\n // Enabling only parallelRetrievalEnabled without queryAwareIndexingEnabled would silently\n // produce an empty temporal index, leaving the temporal agent with no data to work from.\n if (\n !this.config.queryAwareIndexingEnabled &&\n !this.config.parallelRetrievalEnabled\n )\n return;\n // Check for missing indexes BEFORE the early-return so first-time enablement\n // can bootstrap the full corpus even when this extraction turn persisted nothing.\n const needsFullRebuild = !indexesExist(this.config.memoryDir);\n if (!needsFullRebuild && persistedIds.length === 0) return;\n try {\n // Read the corpus once to avoid N separate full-corpus scans.\n // On full rebuild with namespaces enabled, span all configured namespaces so\n // memories written to other namespaces before the index existed are also captured.\n const allMemories =\n needsFullRebuild && this.config.namespacesEnabled\n ? await this.readAllMemoriesForNamespaces(\n Array.from(\n new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]),\n ),\n )\n : await storage.readAllMemories();\n\n // Bootstrap: index only active (non-archived, non-superseded) memories.\n // Incremental: index only the newly persisted IDs.\n const pool = needsFullRebuild\n ? allMemories.filter((m) => isActiveMemoryStatus(m.frontmatter.status))\n : (() => {\n const idSet = new Set(persistedIds);\n return allMemories.filter((m) => idSet.has(m.frontmatter.id));\n })();\n\n const entries: Array<{\n path: string;\n createdAt: string;\n tags: string[];\n }> = [];\n for (const mem of pool) {\n if (mem.path && mem.frontmatter?.created) {\n entries.push({\n path: mem.path,\n createdAt: mem.frontmatter.created,\n tags: mem.frontmatter.tags ?? [],\n });\n }\n }\n if (needsFullRebuild) {\n // Always write empty indexes on full rebuild — even when the active pool\n // is empty (e.g. store contains only archived/superseded entries).\n // This marks bootstrap completion so indexesExist() returns true and\n // subsequent extractions skip the full-corpus scan.\n clearIndexes(this.config.memoryDir);\n if (entries.length > 0) {\n indexMemoriesBatch(this.config.memoryDir, entries);\n }\n log.info(\n `temporal-index: bootstrapped from ${entries.length} active memories`,\n );\n } else if (entries.length > 0) {\n indexMemoriesBatch(this.config.memoryDir, entries);\n }\n } catch (err) {\n log.debug(`temporal-index update failed (non-fatal): ${err}`);\n }\n }\n\n /** IDs of facts persisted in the last extraction */\n private lastPersistedIds: string[] = [];\n\n private async runConsolidation(): Promise<{\n memoriesProcessed: number;\n merged: number;\n invalidated: number;\n }> {\n log.info(\"running consolidation pass\");\n let merged = 0;\n let invalidated = 0;\n\n // Flush access tracking buffer first\n if (this.accessTrackingBuffer.size > 0) {\n await this.flushAccessTracking();\n }\n\n let allMemories = await this.storage.readAllMemories();\n if (allMemories.length < 5) {\n return { memoriesProcessed: allMemories.length, merged, invalidated };\n }\n\n const recent = allMemories\n .sort(\n (a, b) =>\n new Date(b.frontmatter.created).getTime() -\n new Date(a.frontmatter.created).getTime(),\n )\n .slice(0, 20);\n\n const older = allMemories.sort(\n (a, b) =>\n new Date(a.frontmatter.created).getTime() -\n new Date(b.frontmatter.created).getTime(),\n );\n\n const profile = await this.storage.readProfile();\n const result = await this.extraction.consolidate(recent, older, profile);\n\n // Build a lookup map from the already-loaded corpus to avoid repeated\n // readAllMemories() scans inside getMemoryById for pre-action deindex reads.\n const memoryLookup = this.config.queryAwareIndexingEnabled\n ? new Map(allMemories.map((m) => [m.frontmatter.id, m]))\n : null;\n\n for (const item of result.items) {\n switch (item.action) {\n case \"INVALIDATE\": {\n // Capture path/frontmatter before invalidation for index cleanup\n const toInvalidate = this.config.queryAwareIndexingEnabled\n ? (memoryLookup?.get(item.existingId) ?? null)\n : null;\n if (await this.storage.invalidateMemory(item.existingId)) {\n invalidated += 1;\n await this.embeddingFallback.removeFromIndex(item.existingId);\n if (toInvalidate?.path && toInvalidate.frontmatter?.created) {\n deindexMemory(\n this.config.memoryDir,\n toInvalidate.path,\n toInvalidate.frontmatter.created,\n toInvalidate.frontmatter.tags ?? [],\n );\n }\n }\n break;\n }\n case \"UPDATE\":\n if (item.updatedContent) {\n await this.storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n lineage: [item.existingId],\n },\n );\n await this.indexPersistedMemory(this.storage, item.existingId);\n // updateMemory() only changes content/updated/lineage — path, created, and tags\n // are preserved, so the temporal/tag index entry is already correct; no reindex needed.\n }\n break;\n case \"MERGE\":\n if (item.updatedContent && item.mergeWith) {\n await this.storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n supersedes: item.mergeWith,\n lineage: [item.existingId, item.mergeWith],\n },\n );\n await this.indexPersistedMemory(this.storage, item.existingId);\n // updateMemory() only changes content/updated/supersedes/lineage — path, created, and tags\n // are preserved, so the temporal/tag index entry for the survivor is already correct.\n // Capture before invalidation for index cleanup\n const toMergeInvalidate = this.config.queryAwareIndexingEnabled\n ? (memoryLookup?.get(item.mergeWith) ?? null)\n : null;\n if (await this.storage.invalidateMemory(item.mergeWith)) {\n invalidated += 1;\n merged += 1;\n await this.embeddingFallback.removeFromIndex(item.mergeWith);\n if (\n toMergeInvalidate?.path &&\n toMergeInvalidate.frontmatter?.created\n ) {\n deindexMemory(\n this.config.memoryDir,\n toMergeInvalidate.path,\n toMergeInvalidate.frontmatter.created,\n toMergeInvalidate.frontmatter.tags ?? [],\n );\n }\n }\n }\n break;\n }\n }\n\n if (result.profileUpdates.length > 0) {\n await this.storage.appendToProfile(result.profileUpdates);\n }\n\n for (const entity of result.entityUpdates) {\n const safeFacts = Array.isArray((entity as any)?.facts)\n ? (entity as any).facts.filter((f: any) => typeof f === \"string\")\n : [];\n await this.storage.writeEntity(entity.name, entity.type, safeFacts, {\n source: \"consolidation\",\n structuredSections: Array.isArray((entity as any)?.structuredSections)\n ? (entity as any).structuredSections\n : undefined,\n });\n }\n\n // Merge fragmented entity files\n const entitiesMerged = await this.storage.mergeFragmentedEntities();\n if (entitiesMerged > 0) {\n log.info(`merged ${entitiesMerged} fragmented entity files`);\n }\n\n if (this.config.entitySummaryEnabled) {\n try {\n const synthesized = await this.processEntitySynthesisQueue(\n this.config.defaultNamespace,\n 5,\n );\n if (synthesized > 0) {\n log.info(`refreshed ${synthesized} entity syntheses`);\n }\n } catch (err) {\n log.debug(`entity synthesis pass failed: ${err}`);\n }\n }\n\n // Clean expired commitments\n const deletedCommitments = await this.storage.cleanExpiredCommitments(\n this.config.commitmentDecayDays,\n );\n if (deletedCommitments.length > 0) {\n log.info(`cleaned ${deletedCommitments.length} expired commitments`);\n if (this.config.queryAwareIndexingEnabled) {\n for (const m of deletedCommitments) {\n deindexMemory(\n this.config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n }\n }\n\n if (\n this.config.creationMemoryEnabled &&\n this.config.commitmentLedgerEnabled &&\n this.config.commitmentLifecycleEnabled\n ) {\n try {\n const lifecycle = await applyCommitmentLedgerLifecycle({\n memoryDir: this.config.memoryDir,\n commitmentLedgerDir: this.config.commitmentLedgerDir,\n enabled: true,\n decayDays: this.config.commitmentDecayDays,\n });\n if (\n lifecycle.transitionedToExpired.length > 0 ||\n lifecycle.deletedResolved.length > 0\n ) {\n log.info(\n `commitment ledger lifecycle: expired ${lifecycle.transitionedToExpired.length}, cleaned ${lifecycle.deletedResolved.length}`,\n );\n }\n } catch (err) {\n log.debug(`commitment ledger lifecycle pass failed: ${err}`);\n }\n }\n\n // Clean memories past their TTL (speculative memories auto-expire)\n const deletedTTL = await this.storage.cleanExpiredTTL();\n if (deletedTTL.length > 0) {\n log.info(`cleaned ${deletedTTL.length} TTL-expired memories`);\n if (this.config.queryAwareIndexingEnabled) {\n for (const m of deletedTTL) {\n deindexMemory(\n this.config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n }\n }\n\n // v8.3 Lifecycle policy pass — deterministic promotion/decay metadata\n if (this.config.lifecyclePolicyEnabled) {\n try {\n const lightSleepStartedAt = new Date().toISOString();\n const lifecycleCorpus = await this.storage.readAllMemories();\n await this.runLifecyclePolicyPass(lifecycleCorpus);\n await this.recordScheduledDreamsPhaseRun(\n \"lightSleep\",\n lifecycleCorpus.length,\n `scheduled lifecycle policy pass assessed ${lifecycleCorpus.length} memories`,\n {\n startedAt: lightSleepStartedAt,\n completedAt: new Date().toISOString(),\n },\n );\n } catch (err) {\n log.warn(`lifecycle policy pass failed (ignored): ${err}`);\n }\n }\n\n // v8.3 Compression guideline learning pass (default off, fail-open).\n await this.runCompressionGuidelineLearningPass();\n\n try {\n const deepSleepStartedAt = new Date().toISOString();\n await this.runTierMigrationCycle(this.storage, \"maintenance\");\n allMemories = await this.storage.readAllMemories();\n\n // Fact archival pass (v6.0) — move old, low-importance, rarely-accessed facts to archive/\n if (this.config.factArchivalEnabled) {\n const archived = await this.runFactArchival(allMemories);\n if (archived > 0) {\n log.info(`archived ${archived} old low-importance facts`);\n }\n }\n await this.recordScheduledDreamsPhaseRun(\n \"deepSleep\",\n allMemories.length,\n `scheduled deep-sleep maintenance assessed ${allMemories.length} memories`,\n {\n startedAt: deepSleepStartedAt,\n completedAt: new Date().toISOString(),\n },\n );\n } catch (err) {\n log.warn(`deep-sleep maintenance pass failed (ignored): ${err}`);\n try {\n allMemories = await this.storage.readAllMemories();\n } catch (readErr) {\n log.warn(`deep-sleep maintenance recovery read failed: ${readErr}`);\n throw err;\n }\n }\n\n // Semantic consolidation pass — find similar memories, synthesize canonical versions\n if (this.config.semanticConsolidationEnabled) {\n try {\n const stateFilePath = path.join(\n this.config.memoryDir,\n \"state\",\n \"semantic-consolidation-last-run.json\",\n );\n let shouldRun = true;\n try {\n const stateRaw = await readFile(stateFilePath, \"utf-8\");\n const stateData = JSON.parse(stateRaw) as { lastRunAt?: string };\n if (stateData.lastRunAt) {\n const lastRunMs = new Date(stateData.lastRunAt).getTime();\n const intervalMs =\n this.config.semanticConsolidationIntervalHours * 60 * 60 * 1000;\n if (Date.now() - lastRunMs < intervalMs) {\n shouldRun = false;\n log.debug(\n \"[semantic-consolidation] skipping — not enough time since last run\",\n );\n }\n }\n } catch {\n // No state file yet — first run\n }\n\n if (shouldRun) {\n const remStartedAt = new Date().toISOString();\n const semResult = await this.runSemanticConsolidation();\n let remItemsProcessed = allMemories.length;\n try {\n allMemories = await this.storage.readAllMemories();\n remItemsProcessed = allMemories.length;\n } catch (err) {\n log.warn(\n `[semantic-consolidation] post-run telemetry refresh failed (non-fatal): ${err}`,\n );\n }\n await this.recordScheduledDreamsPhaseRun(\n \"rem\",\n remItemsProcessed,\n `scheduled REM consolidation found ${semResult.clustersFound} clusters`,\n {\n startedAt: remStartedAt,\n completedAt: new Date().toISOString(),\n },\n );\n if (semResult.memoriesArchived > 0) {\n log.info(\n `[semantic-consolidation] archived ${semResult.memoriesArchived} memories during maintenance`,\n );\n }\n // Only persist last-run timestamp if the run succeeded (had no errors or made progress)\n if (semResult.errors === 0 || semResult.memoriesArchived > 0) {\n const stateDir = path.join(this.config.memoryDir, \"state\");\n await mkdir(stateDir, { recursive: true });\n await writeFile(\n stateFilePath,\n JSON.stringify({ lastRunAt: new Date().toISOString() }),\n \"utf-8\",\n );\n }\n }\n } catch (err) {\n log.warn(\n `[semantic-consolidation] maintenance pass failed (non-fatal): ${err}`,\n );\n }\n }\n\n // Auto-consolidate IDENTITY.md if it's getting large\n if (this.config.identityEnabled) {\n await this.autoConsolidateIdentity();\n }\n\n // Auto-consolidate profile.md if it exceeds max lines\n const profileSection = this.getRecallSectionEntry(\"profile\");\n const profileConsolidationTriggerLines =\n typeof profileSection?.consolidateTriggerLines === \"number\"\n ? Math.max(0, Math.floor(profileSection.consolidateTriggerLines))\n : undefined;\n const profileConsolidationTargetLines =\n typeof profileSection?.consolidateTargetLines === \"number\"\n ? Math.max(0, Math.floor(profileSection.consolidateTargetLines))\n : 50;\n if (\n await this.storage.profileNeedsConsolidation(\n profileConsolidationTriggerLines,\n )\n ) {\n log.info(\"profile.md exceeds max lines — running smart consolidation\");\n const currentProfile = await this.storage.readProfile();\n if (currentProfile) {\n const profileResult = await this.extraction.consolidateProfile(\n currentProfile,\n profileConsolidationTargetLines,\n );\n if (profileResult) {\n await this.storage.writeProfile(profileResult.consolidatedProfile);\n log.info(\n `profile.md consolidated: removed ${profileResult.removedCount} items — ${profileResult.summary}`,\n );\n }\n }\n }\n\n // Memory Summarization (Phase 4A)\n if (this.config.summarizationEnabled) {\n await this.runSummarization(allMemories);\n }\n\n // Topic Extraction (Phase 4B)\n if (this.config.topicExtractionEnabled) {\n await this.runTopicExtraction(allMemories);\n }\n\n const meta = await this.storage.loadMeta();\n meta.lastConsolidationAt = new Date().toISOString();\n await this.storage.saveMeta(meta);\n\n // Temporal Memory Tree (v8.2) — rebuild nodes from all memories, fail-open\n if (this.config.temporalMemoryTreeEnabled) {\n try {\n const tmtEntries = allMemories\n .filter(\n (m) =>\n m.frontmatter.status !== \"superseded\" &&\n m.frontmatter.status !== \"archived\" &&\n m.frontmatter.status !== \"forgotten\",\n )\n .map((m) => ({\n path: m.path,\n id: m.frontmatter.id,\n created: m.frontmatter.created,\n content: m.content,\n }));\n await this.tmtBuilder.maybeRebuildNodes(\n tmtEntries,\n async (texts, level) => {\n const prompt = `You are a memory archivist. Summarize the following ${level}-level memories into 3–5 sentences, preserving key facts, decisions, and preferences.\\n\\n${texts.map((t, i) => `[${i + 1}] ${t}`).join(\"\\n\\n\")}`;\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content:\n \"Respond with a 3–5 sentence narrative summary. No JSON, just plain prose.\",\n },\n { role: \"user\", content: prompt },\n ],\n {\n temperature: 0.3,\n maxTokens: this.config.tmtSummaryMaxTokens,\n operation: \"tmt_summary\",\n priority: \"background\",\n },\n );\n return response?.content?.trim() || texts.slice(0, 3).join(\" \");\n },\n );\n } catch (err) {\n log.warn(`tmt: consolidation hook failed (ignored): ${err}`);\n }\n }\n\n if (this.consolidationObservers.size > 0) {\n const observation: ConsolidationObservation = {\n runAt: new Date().toISOString(),\n recentMemories: recent,\n existingMemories: older.slice(-50),\n profile,\n result,\n merged,\n invalidated,\n };\n for (const observer of this.consolidationObservers) {\n try {\n await observer(observation);\n } catch (err) {\n log.warn(`consolidation observer failed (ignored): ${err}`);\n }\n }\n }\n\n log.info(\"consolidation complete\");\n return { memoriesProcessed: allMemories.length, merged, invalidated };\n }\n\n async optimizeCompressionGuidelines(options?: {\n dryRun?: boolean;\n eventLimit?: number;\n }): Promise<{\n enabled: boolean;\n dryRun: boolean;\n eventCount: number;\n previousGuidelineVersion: number | null;\n nextGuidelineVersion: number;\n changedRules: number;\n semanticRefinementApplied: boolean;\n persisted: boolean;\n draftContentHash: string | null;\n }> {\n const dryRun = options?.dryRun === true;\n const eventLimit =\n typeof options?.eventLimit === \"number\"\n ? Math.max(0, Math.floor(options.eventLimit))\n : 500;\n\n const [activeState, draftState] = await Promise.all([\n this.storage.readCompressionGuidelineOptimizerState(),\n this.storage.readCompressionGuidelineDraftState().catch(() => null),\n ]);\n const previousState =\n draftState &&\n ((activeState?.guidelineVersion ?? 0) < draftState.guidelineVersion ||\n (activeState?.guidelineVersion ?? 0) === draftState.guidelineVersion)\n ? draftState\n : activeState;\n\n if (!this.config.compressionGuidelineLearningEnabled) {\n return {\n enabled: false,\n dryRun,\n eventCount: 0,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: previousState?.guidelineVersion ?? 0,\n changedRules: 0,\n semanticRefinementApplied: false,\n persisted: false,\n draftContentHash: null,\n };\n }\n\n let events = await this.storage.readMemoryActionEvents(eventLimit);\n if (eventLimit > 0) {\n let effectiveEvents = events.filter((event) => event.dryRun !== true);\n let fetchLimit = eventLimit;\n while (\n effectiveEvents.length < eventLimit &&\n events.length === fetchLimit\n ) {\n fetchLimit = Math.min(fetchLimit * 2, fetchLimit + 1000);\n if (fetchLimit <= events.length) break;\n events = await this.storage.readMemoryActionEvents(fetchLimit);\n effectiveEvents = events.filter((event) => event.dryRun !== true);\n }\n events = effectiveEvents.slice(-eventLimit);\n }\n const generatedAt = new Date().toISOString();\n const candidate = computeCompressionGuidelineCandidate(events, {\n generatedAtIso: generatedAt,\n previousState,\n });\n if (candidate.eventCounts.total === 0) {\n return {\n enabled: true,\n dryRun,\n eventCount: 0,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: previousState?.guidelineVersion ?? 0,\n changedRules: 0,\n semanticRefinementApplied: false,\n persisted: false,\n draftContentHash: null,\n };\n }\n const refinedCandidate =\n await refineCompressionGuidelineCandidateSemantically(candidate, {\n enabled: this.config.compressionGuidelineSemanticRefinementEnabled,\n timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,\n runRefinement: async (baseline) => {\n const prompt = [\n \"You refine compression policy suggestions conservatively.\",\n \"Return JSON only in this shape:\",\n '{\"updates\":[{\"action\":\"summarize_node\",\"delta\":0.02,\"confidence\":\"medium\",\"note\":\"...\"}]}',\n \"Constraints:\",\n \"- Keep updates sparse and conservative.\",\n \"- delta must stay between -0.15 and 0.15.\",\n \"- Only include actions present in the input.\",\n \"Input candidate:\",\n JSON.stringify(baseline),\n ].join(\"\\n\");\n\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content: \"Respond with strict JSON only. No markdown.\",\n },\n { role: \"user\", content: prompt },\n ],\n {\n temperature: 0.1,\n maxTokens: 400,\n operation: \"compression_guideline_semantic_refinement\",\n priority: \"background\",\n },\n );\n\n return this.parseCompressionSemanticRefinement(\n response?.content ?? \"\",\n );\n },\n });\n\n const content = renderCompressionGuidelinesMarkdown(refinedCandidate);\n const contentHash = createHash(\"sha256\").update(content).digest(\"hex\");\n const semanticRefinementApplied =\n JSON.stringify(refinedCandidate.ruleUpdates) !==\n JSON.stringify(candidate.ruleUpdates);\n const changedRules = refinedCandidate.ruleUpdates.filter(\n (rule) => rule.delta !== 0,\n ).length;\n\n if (!dryRun) {\n await this.storage.writeCompressionGuidelineDraft(content);\n await this.storage.writeCompressionGuidelineDraftState({\n version: refinedCandidate.optimizerVersion,\n updatedAt: refinedCandidate.generatedAt,\n sourceWindow: refinedCandidate.sourceWindow,\n eventCounts: refinedCandidate.eventCounts,\n guidelineVersion: refinedCandidate.guidelineVersion,\n contentHash,\n activationState: \"draft\",\n actionSummaries: refinedCandidate.actionSummaries,\n ruleUpdates: refinedCandidate.ruleUpdates,\n });\n }\n\n return {\n enabled: true,\n dryRun,\n eventCount: candidate.eventCounts.total,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: refinedCandidate.guidelineVersion,\n changedRules,\n semanticRefinementApplied,\n persisted: !dryRun,\n draftContentHash: dryRun ? null : contentHash,\n };\n }\n\n async activateCompressionGuidelineDraft(options?: {\n expectedContentHash?: string;\n expectedGuidelineVersion?: number;\n }): Promise<{\n enabled: boolean;\n activated: boolean;\n guidelineVersion: number | null;\n reason?:\n | \"disabled\"\n | \"missing_draft\"\n | \"expected_revision_required\"\n | \"content_hash_mismatch\"\n | \"guideline_version_mismatch\"\n | \"draft_changed\";\n }> {\n if (!this.config.compressionGuidelineLearningEnabled) {\n return {\n enabled: false,\n activated: false,\n guidelineVersion: null,\n reason: \"disabled\",\n };\n }\n\n const draftState = await this.storage.readCompressionGuidelineDraftState();\n if (!draftState) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"missing_draft\",\n };\n }\n\n const expectedContentHash = options?.expectedContentHash?.trim();\n const expectedGuidelineVersion = options?.expectedGuidelineVersion;\n\n if (\n (!expectedContentHash || expectedContentHash.length === 0) &&\n typeof expectedGuidelineVersion !== \"number\"\n ) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"expected_revision_required\",\n };\n }\n\n if (expectedContentHash && draftState.contentHash !== expectedContentHash) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"content_hash_mismatch\",\n };\n }\n\n if (\n typeof expectedGuidelineVersion === \"number\" &&\n draftState.guidelineVersion !== expectedGuidelineVersion\n ) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"guideline_version_mismatch\",\n };\n }\n\n const activated = await this.storage.activateCompressionGuidelineDraft({\n ...(expectedContentHash ? { expectedContentHash } : {}),\n ...(typeof expectedGuidelineVersion === \"number\"\n ? { expectedGuidelineVersion }\n : {}),\n });\n return {\n enabled: true,\n activated,\n guidelineVersion: activated ? draftState.guidelineVersion : null,\n ...(activated ? {} : { reason: \"draft_changed\" as const }),\n };\n }\n\n private async runCompressionGuidelineLearningPass(): Promise<void> {\n if (!this.config.compressionGuidelineLearningEnabled) return;\n try {\n const result = await this.optimizeCompressionGuidelines({\n dryRun: false,\n eventLimit: 500,\n });\n log.info(\n `compression guideline learning updated (${result.eventCount} events)`,\n );\n } catch (err) {\n log.warn(`compression guideline learning failed (ignored): ${err}`);\n }\n }\n\n private async buildCompressionGuidelineRecallSection(): Promise<\n string | null\n > {\n if (!this.config.contextCompressionActionsEnabled) return null;\n if (!this.config.compressionGuidelineLearningEnabled) return null;\n\n const state = await this.storage\n .readCompressionGuidelineOptimizerState()\n .catch(() => null);\n if (!state || state.guidelineVersion <= 0) return null;\n\n const raw = await this.storage\n .readCompressionGuidelines()\n .catch(() => null);\n const summary = raw ? formatCompressionGuidelinesForRecall(raw, 5) : null;\n if (!summary) return null;\n\n return [\n \"## Active Compression Guidelines\",\n \"\",\n `Guideline version: ${state.guidelineVersion}`,\n `Updated: ${state.updatedAt}`,\n \"\",\n summary,\n ].join(\"\\n\");\n }\n\n private parseCompressionSemanticRefinement(raw: string): {\n updates: Array<{\n action: MemoryActionType;\n delta?: number;\n confidence?: \"low\" | \"medium\" | \"high\";\n note?: string;\n }>;\n } | null {\n if (typeof raw !== \"string\" || raw.trim().length === 0) return null;\n const trimmed = raw.trim();\n const start = trimmed.indexOf(\"{\");\n const end = trimmed.lastIndexOf(\"}\");\n if (start === -1 || end === -1 || end <= start) return null;\n\n try {\n const parsed = JSON.parse(trimmed.slice(start, end + 1)) as {\n updates?: Array<{\n action?: unknown;\n delta?: unknown;\n confidence?: unknown;\n note?: unknown;\n }>;\n };\n if (!Array.isArray(parsed?.updates)) return null;\n\n const validActions = new Set<MemoryActionType>([\n \"store_episode\",\n \"store_note\",\n \"update_note\",\n \"create_artifact\",\n \"summarize_node\",\n \"discard\",\n \"link_graph\",\n ]);\n\n const updates = parsed.updates\n .filter(\n (item) =>\n item &&\n typeof item.action === \"string\" &&\n validActions.has(item.action as MemoryActionType),\n )\n .map((item) => {\n const confidence: \"low\" | \"medium\" | \"high\" | undefined =\n item.confidence === \"low\" ||\n item.confidence === \"medium\" ||\n item.confidence === \"high\"\n ? item.confidence\n : undefined;\n return {\n action: item.action as MemoryActionType,\n delta:\n typeof item.delta === \"number\" && Number.isFinite(item.delta)\n ? item.delta\n : undefined,\n confidence,\n note: typeof item.note === \"string\" ? item.note : undefined,\n };\n });\n\n return { updates };\n } catch {\n return null;\n }\n }\n\n private actionOutcomePriorDelta(event: MemoryActionEvent): number {\n if (event.outcome === \"failed\") return -0.3;\n if (event.policyDecision === \"deny\") return -0.22;\n if (event.policyDecision === \"defer\") return -0.14;\n if (event.outcome === \"skipped\") return -0.1;\n\n if (event.outcome !== \"applied\") return 0;\n switch (event.action) {\n case \"store_episode\":\n case \"store_note\":\n case \"update_note\":\n return 0.08;\n case \"create_artifact\":\n case \"summarize_node\":\n case \"link_graph\":\n return 0.04;\n case \"discard\":\n return -0.03;\n default:\n return 0;\n }\n }\n\n private async buildLifecycleActionPriors(\n storage: StorageManager = this.storage,\n ): Promise<Map<string, number>> {\n const events = await storage.readMemoryActionEvents(1200);\n if (events.length === 0) return new Map<string, number>();\n\n const nowMs = Date.now();\n const windowMs = 14 * 24 * 60 * 60 * 1000;\n const byMemory = new Map<\n string,\n Array<{ weightedDelta: number; weight: number }>\n >();\n\n for (const event of events) {\n if (\n typeof event.memoryId !== \"string\" ||\n event.memoryId.trim().length === 0\n )\n continue;\n const ts = Date.parse(event.timestamp);\n if (!Number.isFinite(ts)) continue;\n const ageMs = nowMs - ts;\n if (ageMs < 0 || ageMs > windowMs) continue;\n\n const delta = this.actionOutcomePriorDelta(event);\n if (delta === 0) continue;\n\n const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);\n const list = byMemory.get(event.memoryId) ?? [];\n if (list.length >= 8) list.shift();\n list.push({\n weightedDelta: delta * recencyWeight,\n weight: recencyWeight,\n });\n byMemory.set(event.memoryId, list);\n }\n\n const out = new Map<string, number>();\n for (const [memoryId, deltas] of byMemory.entries()) {\n if (deltas.length === 0) continue;\n const weightedSum = deltas.reduce(\n (sum, item) => sum + item.weightedDelta,\n 0,\n );\n const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);\n if (weightTotal <= 0) continue;\n const score = weightedSum / weightTotal;\n out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));\n }\n return out;\n }\n\n private async recordScheduledDreamsPhaseRun(\n phase: \"lightSleep\" | \"rem\" | \"deepSleep\",\n itemsProcessed: number,\n notes: string,\n timing: { startedAt?: string; completedAt?: string } = {},\n ): Promise<void> {\n try {\n const { recordDreamsPhaseRun } = await import(\"./maintenance/dreams-ledger.js\");\n await recordDreamsPhaseRun({\n memoryDir: this.storage.dir,\n phase,\n trigger: \"scheduled\",\n itemsProcessed,\n notes,\n startedAt: timing.startedAt,\n completedAt: timing.completedAt,\n });\n } catch (error) {\n log.debug(`dreams ledger scheduled ${phase} write failed (non-fatal): ${error}`);\n }\n }\n\n async runLifecyclePolicyNow(storage: StorageManager = this.storage): Promise<{ memoriesAssessed: number }> {\n const lifecycleCorpus = await storage.readAllMemories();\n await this.runLifecyclePolicyPass(lifecycleCorpus, storage);\n return { memoriesAssessed: lifecycleCorpus.length };\n }\n\n private async runLifecyclePolicyPass(\n allMemories: MemoryFile[],\n storage: StorageManager = this.storage,\n ): Promise<void> {\n const now = new Date();\n const nowIso = now.toISOString();\n const countsByState: Record<LifecycleState, number> = {\n candidate: 0,\n validated: 0,\n active: 0,\n stale: 0,\n archived: 0,\n };\n const transitionCounts: Record<string, number> = {};\n let updatedCount = 0;\n let disputedCount = 0;\n let evaluatedCount = 0;\n\n const thresholds = this.effectiveLifecycleThresholds();\n const policy = {\n promoteHeatThreshold: thresholds.promoteHeatThreshold,\n staleDecayThreshold: thresholds.staleDecayThreshold,\n archiveDecayThreshold: thresholds.archiveDecayThreshold,\n protectedCategories: this.config.lifecycleProtectedCategories,\n };\n const actionPriors = await this.buildLifecycleActionPriors(storage);\n\n for (const memory of allMemories) {\n if (\n memory.frontmatter.status === \"superseded\" ||\n memory.frontmatter.status === \"forgotten\"\n ) {\n continue;\n }\n evaluatedCount += 1;\n const currentState = resolveLifecycleState(memory.frontmatter);\n const actionPriorScore = actionPriors.get(memory.frontmatter.id);\n const signals: LifecycleSignals | undefined =\n typeof actionPriorScore === \"number\" &&\n Number.isFinite(actionPriorScore)\n ? { actionPriorScore }\n : undefined;\n const decision = decideLifecycleTransition(memory, policy, now, signals);\n const nextState: LifecycleState =\n memory.frontmatter.status === \"archived\"\n ? \"archived\"\n : decision.nextState;\n\n countsByState[nextState] += 1;\n if (memory.frontmatter.verificationState === \"disputed\") {\n disputedCount += 1;\n }\n if (nextState !== currentState) {\n const key = `${currentState}->${nextState}`;\n transitionCounts[key] = (transitionCounts[key] ?? 0) + 1;\n }\n\n const prevHeat = memory.frontmatter.heatScore;\n const prevDecay = memory.frontmatter.decayScore;\n const scoreDelta =\n Math.abs((prevHeat ?? -1) - decision.heatScore) +\n Math.abs((prevDecay ?? -1) - decision.decayScore);\n const shouldPersist =\n memory.frontmatter.lifecycleState !== nextState ||\n memory.frontmatter.heatScore === undefined ||\n memory.frontmatter.decayScore === undefined ||\n memory.frontmatter.lastValidatedAt === undefined ||\n scoreDelta >= 0.01;\n\n if (!shouldPersist) continue;\n\n const wrote = await storage.writeMemoryFrontmatter(memory, {\n lifecycleState: nextState,\n heatScore: decision.heatScore,\n decayScore: decision.decayScore,\n lastValidatedAt: nowIso,\n });\n if (wrote) updatedCount += 1;\n }\n\n if (!this.config.lifecycleMetricsEnabled) return;\n\n const total = evaluatedCount;\n const metrics = {\n generatedAt: nowIso,\n memoriesEvaluated: total,\n memoriesUpdated: updatedCount,\n countsByLifecycleState: countsByState,\n transitionCounts,\n staleRatio: total > 0 ? countsByState.stale / total : 0,\n disputedRatio: total > 0 ? disputedCount / total : 0,\n policy: {\n promoteHeatThreshold: thresholds.promoteHeatThreshold,\n staleDecayThreshold: thresholds.staleDecayThreshold,\n archiveDecayThreshold: thresholds.archiveDecayThreshold,\n protectedCategories: this.config.lifecycleProtectedCategories,\n },\n };\n const metricsPath = path.join(\n storage.dir,\n \"state\",\n \"lifecycle-metrics.json\",\n );\n await mkdir(path.dirname(metricsPath), { recursive: true });\n await writeFile(metricsPath, JSON.stringify(metrics, null, 2), \"utf-8\");\n }\n\n /**\n * Archive old, low-importance, rarely-accessed facts (v6.0).\n * Moves eligible facts from facts/ to archive/YYYY-MM-DD/.\n * Returns the number of archived facts.\n */\n private async runFactArchival(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<number> {\n const now = Date.now();\n const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1000;\n const protectedCategories = new Set(\n this.config.factArchivalProtectedCategories,\n );\n let archivedCount = 0;\n\n for (const memory of allMemories) {\n const fm = memory.frontmatter;\n\n // Skip already-archived or superseded\n if (fm.status && fm.status !== \"active\") continue;\n\n // Skip protected categories\n if (protectedCategories.has(fm.category)) continue;\n\n // Skip corrections (always keep)\n if (fm.category === \"correction\") continue;\n\n // Check age requirement\n const createdMs = new Date(fm.created).getTime();\n if (now - createdMs < ageCutoffMs) continue;\n\n // Check importance (only archive low-importance facts)\n const importanceScore = fm.importance?.score ?? 0.5;\n if (importanceScore >= this.config.factArchivalMaxImportance) continue;\n\n // Check access count\n const accessCount = fm.accessCount ?? 0;\n if (accessCount > this.config.factArchivalMaxAccessCount) continue;\n\n // All criteria met — archive\n const result = await this.storage.archiveMemory(memory);\n if (result) {\n // Remove from content-hash index since it's no longer in hot search.\n // Prefer the raw-content hash stored on the frontmatter at write\n // time (contentHash) — it is format-agnostic and survives any\n // citation template.\n if (this.contentHashIndex) {\n if (memory.frontmatter.contentHash) {\n // Modern memory: frontmatter.contentHash is already a SHA-256\n // hex string — use removeByHash to avoid double-hashing.\n this.contentHashIndex.removeByHash(memory.frontmatter.contentHash);\n } else {\n // Legacy memory written before contentHash was stored on the\n // frontmatter. Pre-#369 facts were stored without inline\n // citations, so memory.content is the raw fact text and we can\n // remove the hash directly from the content. This clears\n // stale dedup entries so the fact can be re-extracted.\n log.warn(\n `[fact-archival] removing hash for legacy memory ${memory.frontmatter.id ?? \"(unknown)\"} via content fallback — no contentHash in frontmatter`,\n );\n this.contentHashIndex.remove(memory.content);\n }\n }\n await this.embeddingFallback.removeFromIndex(memory.frontmatter.id);\n if (\n this.config.queryAwareIndexingEnabled &&\n memory.path &&\n memory.frontmatter?.created\n ) {\n deindexMemory(\n this.config.memoryDir,\n memory.path,\n memory.frontmatter.created,\n memory.frontmatter.tags ?? [],\n );\n }\n archivedCount++;\n }\n }\n\n // Save hash index if we removed any entries\n if (archivedCount > 0 && this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) =>\n log.warn(`content-hash index save failed during archival: ${err}`),\n );\n }\n\n return archivedCount;\n }\n\n /**\n * Run memory summarization if memory count exceeds threshold (Phase 4A).\n */\n private async runSummarization(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<void> {\n // Only active memories count toward the threshold\n const activeMemories = allMemories.filter(\n (m) => isActiveMemoryStatus(m.frontmatter.status),\n );\n\n if (activeMemories.length < this.config.summarizationTriggerCount) {\n return;\n }\n\n log.info(\n `memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) — running summarization`,\n );\n\n // Sort by creation date, oldest first\n const sorted = activeMemories.sort(\n (a, b) =>\n new Date(a.frontmatter.created).getTime() -\n new Date(b.frontmatter.created).getTime(),\n );\n\n // Keep recent memories\n const toKeep = sorted.slice(-this.config.summarizationRecentToKeep);\n const toSummarize = sorted.slice(0, -this.config.summarizationRecentToKeep);\n\n // Filter candidates for summarization\n const candidates = toSummarize.filter((m) => {\n // Skip if protected by entity reference\n if (m.frontmatter.entityRef) return false;\n\n // Skip if protected by tag\n const protectedTags = this.config.summarizationProtectedTags;\n if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))\n return false;\n\n // Skip if importance is above threshold\n const importance = m.frontmatter.importance?.score ?? 0.5;\n if (importance >= this.config.summarizationImportanceThreshold)\n return false;\n\n return true;\n });\n\n if (candidates.length < 50) {\n log.debug(\n `only ${candidates.length} candidates for summarization — skipping`,\n );\n return;\n }\n\n // Summarize in batches of 50\n const batchSize = 50;\n for (let i = 0; i < candidates.length; i += batchSize) {\n const batch = candidates.slice(i, i + batchSize);\n const batchData = batch.map((m) => ({\n id: m.frontmatter.id,\n content: m.content,\n category: m.frontmatter.category,\n created: m.frontmatter.created,\n }));\n\n const result = await this.extraction.summarizeMemories(batchData);\n if (!result) continue;\n\n // Create summary\n const summary: MemorySummary = {\n id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,\n createdAt: new Date().toISOString(),\n timeRangeStart: batch[0].frontmatter.created,\n timeRangeEnd: batch[batch.length - 1].frontmatter.created,\n summaryText: result.summaryText,\n keyFacts: result.keyFacts,\n keyEntities: result.keyEntities,\n sourceEpisodeIds: batch.map((m) => m.frontmatter.id),\n };\n\n await this.storage.writeSummary(summary);\n\n // Archive source memories\n const archived = await this.storage.archiveMemories(\n batch.map((m) => m.frontmatter.id),\n summary.id,\n );\n\n log.info(\n `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`,\n );\n }\n }\n\n /**\n * Run topic extraction on all memories (Phase 4B).\n */\n private async runTopicExtraction(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<void> {\n // Only extract from active memories\n const activeMemories = allMemories.filter(\n (m) => isActiveMemoryStatus(m.frontmatter.status),\n );\n\n if (activeMemories.length === 0) return;\n\n const topics = extractTopics(\n activeMemories,\n this.config.topicExtractionTopN,\n );\n await this.storage.saveTopics(topics);\n\n log.debug(\n `extracted ${topics.length} topics from ${activeMemories.length} memories`,\n );\n }\n\n /** Threshold (bytes) at which IDENTITY.md reflections get auto-consolidated */\n private static readonly IDENTITY_CONSOLIDATE_THRESHOLD = 8_000;\n\n private async autoConsolidateIdentity(): Promise<void> {\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n\n for (const namespace of namespaces) {\n const storage = await this.storageRouter.storageFor(namespace);\n const identityNamespace =\n this.config.namespacesEnabled &&\n namespace !== this.config.defaultNamespace\n ? namespace\n : undefined;\n const reflectionsContent =\n (await storage.readIdentityReflections()) ?? \"\";\n\n const existingIdentity = await storage.readIdentity(\n this.config.workspaceDir,\n identityNamespace,\n );\n const headerEnd =\n existingIdentity.indexOf(\"## Learned Patterns\") !== -1\n ? existingIdentity.indexOf(\"## Learned Patterns\")\n : existingIdentity.indexOf(\"## Reflection\");\n const staticHeader =\n (headerEnd !== -1\n ? existingIdentity.slice(0, headerEnd)\n : existingIdentity\n ).trimEnd() || \"# IDENTITY\";\n const identityContent = `${staticHeader}\\n\\n${reflectionsContent.trim()}\\n`;\n if (identityContent.length < Orchestrator.IDENTITY_CONSOLIDATE_THRESHOLD)\n continue;\n\n log.info(\n `IDENTITY(${namespace}) is ${identityContent.length} chars — auto-consolidating reflections`,\n );\n const result = await this.extraction.consolidateIdentity(\n identityContent,\n \"## Reflection\",\n );\n\n if (!result || result.learnedPatterns.length === 0) {\n log.warn(\n `identity consolidation produced no patterns for namespace=${namespace}`,\n );\n continue;\n }\n\n const patternsSection = [\n \"## Learned Patterns (consolidated from reflections, \" +\n new Date().toISOString().slice(0, 10) +\n \")\",\n \"\",\n ...result.learnedPatterns.map((p) => `- ${p}`),\n \"\",\n ].join(\"\\n\");\n\n const newContent = staticHeader + \"\\n\\n\" + patternsSection + \"\\n\";\n\n await storage.writeIdentity(\n this.config.workspaceDir,\n newContent,\n identityNamespace,\n );\n await storage.writeIdentityReflections(\"\");\n log.info(\n `IDENTITY(${namespace}) consolidated: ${identityContent.length} → ${newContent.length} chars, ${result.learnedPatterns.length} patterns`,\n );\n }\n }\n\n private formatQmdResults(title: string, results: QmdSearchResult[]): string {\n const lines = results.map((r, i) => {\n const snippet = r.snippet\n ? r.snippet.slice(0, 500).replace(/\\n/g, \" \")\n : \"(no preview)\";\n return `[${i + 1}] ${r.path} (score: ${r.score.toFixed(3)})\\n${snippet}`;\n });\n return `## ${title}\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatObjectiveStateResults(\n results: ObjectiveStateSearchResult[],\n ): string {\n const lines = results.map(({ snapshot }, index) => {\n const parts = [\n snapshot.recordedAt.replace(\"T\", \" \").slice(0, 16),\n `${snapshot.kind}/${snapshot.changeKind}`,\n ];\n if (snapshot.outcome) parts.push(snapshot.outcome);\n const header = `[${index + 1}] ${parts.join(\" | \")} | ${snapshot.scope}`;\n const detailParts = [snapshot.summary];\n if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);\n else if (snapshot.toolName)\n detailParts.push(`tool: ${snapshot.toolName}`);\n return `${header}\\n${detailParts.join(\" | \")}`;\n });\n return `## Objective State\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatCausalTrajectoryResults(\n results: CausalTrajectorySearchResult[],\n ): string {\n const lines = results.map(({ record, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${record.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n record.outcomeKind,\n ].join(\" | \");\n const details = [\n `goal: ${record.goal}`,\n `action: ${record.actionSummary}`,\n `observation: ${record.observationSummary}`,\n `outcome: ${record.outcomeSummary}`,\n ];\n if (record.followUpSummary)\n details.push(`follow-up: ${record.followUpSummary}`);\n if (matchedFields.length > 0)\n details.push(`matched: ${matchedFields.join(\", \")}`);\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Causal Trajectories\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatTrustZoneResults(results: TrustZoneSearchResult[]): string {\n const lines = results.map(({ record, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${record.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n record.zone,\n record.kind,\n ].join(\" | \");\n const details = [\n record.summary,\n `provenance: ${record.provenance.sourceClass}`,\n ];\n if (record.entityRefs && record.entityRefs.length > 0) {\n details.push(`entities: ${record.entityRefs.join(\", \")}`);\n }\n if (record.tags && record.tags.length > 0) {\n details.push(`tags: ${record.tags.join(\", \")}`);\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Trust Zones\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatHarmonicRetrievalResults(\n results: HarmonicRetrievalResult[],\n ): string {\n const lines = results.map(\n (\n { node, matchedAnchors, matchedFields, nodeScore, anchorScore },\n index,\n ) => {\n const header = [\n `[${index + 1}] ${node.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n `${node.kind}/${node.abstractionLevel}`,\n node.sessionKey,\n ].join(\" | \");\n const details = [\n node.title,\n node.summary,\n `scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`,\n ];\n if (matchedAnchors.length > 0) {\n details.push(\n `anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join(\"; \")}`,\n );\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Harmonic Retrieval\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatWorkProductResults(\n results: WorkProductLedgerSearchResult[],\n ): string {\n const lines = results.map(({ entry, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${entry.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n `${entry.kind}/${entry.action}`,\n entry.sessionKey,\n ].join(\" | \");\n const details = [entry.summary, `scope: ${entry.scope}`];\n if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);\n if (entry.tags && entry.tags.length > 0)\n details.push(`tags: ${entry.tags.join(\", \")}`);\n if (matchedFields.length > 0)\n details.push(`matched: ${matchedFields.join(\", \")}`);\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Work Products\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatVerifiedEpisodeResults(\n results: VerifiedEpisodeResult[],\n ): string {\n const lines = results.map(\n ({ box, verifiedEpisodeCount, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${box.sealedAt.replace(\"T\", \" \").slice(0, 16)}`,\n box.traceId ? `trace:${box.traceId.slice(0, 12)}` : \"trace:none\",\n ].join(\" | \");\n const details = [\n box.goal ?? `topics: ${box.topics.join(\", \")}`,\n `verified episodes: ${verifiedEpisodeCount}`,\n ];\n if (box.toolsUsed && box.toolsUsed.length > 0) {\n details.push(`tools: ${box.toolsUsed.join(\", \")}`);\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Verified Episodes\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatVerifiedSemanticRuleResults(\n results: VerifiedSemanticRuleResult[],\n ): string {\n const lines = results.map(\n (\n {\n rule,\n sourceMemoryId,\n verificationStatus,\n effectiveConfidence,\n matchedFields,\n },\n index,\n ) => {\n const header = [\n `[${index + 1}] ${rule.frontmatter.updated.replace(\"T\", \" \").slice(0, 16)}`,\n verificationStatus,\n `confidence:${effectiveConfidence.toFixed(2)}`,\n ].join(\" | \");\n const details = [rule.content, `source memory: ${sourceMemoryId}`];\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Verified Rules\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private summarizeIdentityText(\n raw: string,\n maxLines: number,\n maxChars: number,\n ): string {\n const lines = raw\n .replace(/\\r/g, \"\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n const compact = lines.slice(0, Math.max(1, maxLines)).join(\" \");\n if (compact.length <= maxChars) return compact;\n return `${compact.slice(0, Math.max(0, maxChars - 1))}…`;\n }\n\n private formatOpenIncidentLine(\n incident: ContinuityIncidentRecord,\n includeDetails: boolean,\n ): string {\n const base = `[${incident.id}] ${incident.symptom.trim()}`;\n if (!includeDetails) return `- ${base}`;\n const parts = [base];\n if (incident.suspectedCause)\n parts.push(`cause: ${incident.suspectedCause.trim()}`);\n if (incident.triggerWindow)\n parts.push(`window: ${incident.triggerWindow.trim()}`);\n return `- ${parts.join(\" | \")}`;\n }\n\n private trimIdentitySection(\n content: string,\n maxChars: number,\n ): { text: string; truncated: boolean } {\n if (maxChars <= 0) return { text: \"\", truncated: false };\n if (content.length <= maxChars) return { text: content, truncated: false };\n const suffix = \"\\n\\n...(identity continuity trimmed)\";\n if (maxChars <= suffix.length) {\n return { text: content.slice(0, maxChars), truncated: true };\n }\n const headroom = Math.max(0, maxChars - suffix.length);\n return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };\n }\n\n private async buildIdentityContinuitySection(options: {\n storage: StorageManager;\n recallMode: RecallPlanMode;\n prompt: string;\n }): Promise<{\n section: string;\n mode: IdentityInjectionMode;\n injectedChars: number;\n truncated: boolean;\n } | null> {\n if (!this.config.identityContinuityEnabled) return null;\n if (this.config.identityMaxInjectChars <= 0) return null;\n\n const resolved = resolveEffectiveIdentityInjectionMode({\n configuredMode: this.config.identityInjectionMode,\n recallMode: options.recallMode,\n prompt: options.prompt,\n });\n if (!resolved.shouldInject) return null;\n\n const [anchorRaw, loopsRaw, incidents] = await Promise.all([\n options.storage.readIdentityAnchor(),\n options.storage.readIdentityImprovementLoops(),\n options.storage.readContinuityIncidents(200),\n ]);\n const openIncidents = incidents.filter(\n (incident) => incident.state === \"open\",\n );\n\n const lines: string[] = [];\n if (resolved.mode === \"full\") {\n lines.push(\"## Identity Continuity\");\n if (anchorRaw && anchorRaw.trim().length > 0) {\n lines.push(\"\", \"### Anchor\", \"\", anchorRaw.trim());\n }\n if (loopsRaw && loopsRaw.trim().length > 0) {\n lines.push(\"\", \"### Improvement Loops\", \"\", loopsRaw.trim());\n }\n lines.push(\"\", \"### Open Incidents\", \"\");\n if (openIncidents.length === 0) {\n lines.push(\"- none\");\n } else {\n lines.push(\n ...openIncidents\n .slice(0, 5)\n .map((incident) => this.formatOpenIncidentLine(incident, true)),\n );\n }\n } else {\n const anchorSummary = anchorRaw\n ? this.summarizeIdentityText(anchorRaw, 3, 320)\n : \"\";\n const loopsSummary = loopsRaw\n ? this.summarizeIdentityText(loopsRaw, 2, 240)\n : \"\";\n lines.push(\"## Identity Continuity Signals\", \"\");\n if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);\n if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);\n if (openIncidents.length === 0) {\n lines.push(\"- incidents: 0 open\");\n } else {\n lines.push(`- incidents: ${openIncidents.length} open`);\n lines.push(\n ...openIncidents\n .slice(0, 2)\n .map((incident) => this.formatOpenIncidentLine(incident, false)),\n );\n }\n }\n\n const body = lines.join(\"\\n\").trim();\n if (!body) return null;\n\n const { text, truncated } = this.trimIdentitySection(\n body,\n this.config.identityMaxInjectChars,\n );\n if (!text) return null;\n\n return {\n section: text,\n mode: resolved.mode,\n injectedChars: text.length,\n truncated,\n };\n }\n\n private emitTrace(event: EngramTraceEvent): void {\n try {\n const cb = (globalThis as any).__openclawEngramTrace;\n if (typeof cb === \"function\") cb(event);\n } catch (err) {\n log.debug(`trace callback failed: ${err}`);\n }\n }\n\n private queueEvalShadowRecall(\n record: Omit<EvalShadowRecallRecord, \"schemaVersion\">,\n ): void {\n if (!this.config.evalHarnessEnabled || !this.config.evalShadowModeEnabled)\n return;\n this.evalShadowWriteChain = this.evalShadowWriteChain\n .catch(() => undefined)\n .then(async () => {\n try {\n await recordEvalShadowRecall({\n memoryDir: this.config.memoryDir,\n evalStoreDir: this.config.evalStoreDir,\n record: {\n schemaVersion: 1,\n ...record,\n },\n });\n } catch (err) {\n log.debug(`eval shadow recall write failed: ${err}`);\n }\n });\n }\n\n private publishRecallResults(options: {\n title: string;\n results: QmdSearchResult[];\n sectionBuckets: Map<string, string[]>;\n retrievalQuery: string;\n sessionKey: string | undefined;\n identityInjection?: {\n mode: IdentityInjectionMode | \"none\";\n injectedChars: number;\n truncated: boolean;\n };\n }): void {\n const sectionId = \"memories\";\n const memoryIds = this.extractMemoryIdsFromResults(options.results);\n this.trackMemoryAccess(memoryIds);\n\n this.appendRecallSection(\n options.sectionBuckets,\n sectionId,\n this.formatQmdResults(options.title, options.results),\n );\n }\n\n /**\n * Apply MMR over the pre-truncation recall candidate pool and then slice\n * the result to `limit`. This is the single place in the pipeline where\n * MMR runs, and it must be called *before* callers throw away candidates\n * that would otherwise sit below the final cutoff. Running MMR post-slice\n * is a no-op in the cases we care about — diverse candidates just below\n * the cutoff are already gone and can never be promoted.\n *\n * Callers must pass the full candidate pool (post-rerank, pre-slice).\n */\n private async applyMemoryWorthRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<QmdSearchResult[]> {\n // Build the counter lookup. We union frontmatter counters across every\n // namespace the recall spans — the recall path itself already\n // aggregates candidates from multiple namespaces, so we must do the\n // same when looking up counters. Per-namespace results are cached with\n // a short TTL so interactive recall doesn't trigger a full\n // `readAllMemories` scan per query (addresses codex P2 on PR 4).\n const counters = new Map<string, MemoryWorthCounters>();\n const seenNamespaces = new Set<string>();\n const nowMs = Date.now();\n\n // Evict all expired entries on every call so long-running processes\n // touching a high-cardinality namespace set (coding/project overlays,\n // per-branch) don't grow the cache unboundedly. Without this, an entry\n // for a namespace that's never looked up again would pin its full\n // counter map forever.\n for (const [key, entry] of this.memoryWorthCounterCache) {\n if (nowMs - entry.at >= Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {\n this.memoryWorthCounterCache.delete(key);\n }\n }\n\n for (const ns of namespaces) {\n if (seenNamespaces.has(ns)) continue;\n seenNamespaces.add(ns);\n try {\n const cached = this.memoryWorthCounterCache.get(ns);\n let nsMap: ReadonlyMap<string, MemoryWorthCounters> | undefined;\n if (\n cached &&\n nowMs - cached.at < Orchestrator.MEMORY_WORTH_CACHE_TTL_MS\n ) {\n nsMap = cached.counters;\n } else {\n const storage = await this.getStorage(ns);\n const memories = await storage.readAllMemories();\n nsMap = buildMemoryWorthCounterMap(memories);\n this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });\n }\n for (const [path, c] of nsMap) counters.set(path, c);\n } catch (err) {\n log.debug(\"memory-worth: failed to read namespace, skipping\", {\n namespace: ns,\n error: (err as Error).message,\n });\n }\n }\n\n // For candidates whose path didn't show up in any hot-tier namespace\n // scan (typical of cold-tier / archive fallback), try a direct\n // per-path read. Without this, cold-tier candidates always stay at\n // multiplier 1.0 even when they have outcome history. Errors are\n // swallowed so a single unreadable archive entry can't break the\n // whole recall.\n const missing = results.filter((r) => !counters.has(r.path));\n if (missing.length > 0) {\n // Use the first-seen namespace's storage as the reader — all\n // StorageManagers share the same on-disk format, and\n // `readMemoryByPath` takes an absolute path so the baseDir doesn't\n // have to match.\n let reader: StorageManager | null = null;\n for (const ns of namespaces) {\n try {\n reader = await this.getStorage(ns);\n break;\n } catch {\n // try next namespace\n }\n }\n if (reader) {\n for (const r of missing) {\n try {\n const memory = await reader.readMemoryByPath(r.path);\n if (!memory) continue;\n const fm = memory.frontmatter;\n if (fm.mw_success === undefined && fm.mw_fail === undefined) continue;\n counters.set(r.path, {\n mw_success: fm.mw_success,\n mw_fail: fm.mw_fail,\n lastAccessed: fm.lastAccessed,\n });\n } catch (err) {\n log.debug(\"memory-worth: direct path lookup failed\", {\n path: r.path,\n error: (err as Error).message,\n });\n }\n }\n }\n }\n\n // If no memory in the candidate set has any counter data, the filter\n // would be a no-op — skip the reorder to avoid spurious log spam.\n if (counters.size === 0) return results;\n\n // Preserve upstream ordering (reranker, specialized tiers, etc.) for\n // neutral candidates. The upstream stages set `memoryResults` in their\n // intended order but often leave `r.score` as the raw QMD score. If we\n // sorted by `r.score * multiplier` directly, neutral candidates\n // (multiplier 1.0) would snap back to raw-QMD order and silently undo\n // the reranker. Feed the filter a synthetic monotone-decreasing rank\n // score so it uses input position as the baseline, then applies the\n // multiplier on top. Ties fall back to the stable secondary key in\n // `applyMemoryWorthFilter`.\n const rankedInputs = results.map((r, i) => ({\n path: r.path,\n // Large positive rank score so multiplier math stays well-scaled and\n // we never hit zero; descending so earlier items rank higher.\n score: results.length - i,\n }));\n const filtered = applyMemoryWorthFilter(rankedInputs, {\n counters,\n now: new Date(),\n halfLifeMs:\n this.config.recallMemoryWorthHalfLifeMs > 0\n ? this.config.recallMemoryWorthHalfLifeMs\n : undefined,\n });\n\n // Reconstruct the QmdSearchResult list in the new order. `.score` is\n // preserved from the upstream pipeline (rerank, tier scoring, etc.) —\n // we only reorder. Writing the synthetic rank-weighted score back\n // would contaminate downstream logic (telemetry, confidence gates)\n // that expects the original QMD/rerank score semantics.\n const byPath = new Map(results.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const item of filtered) {\n const original = byPath.get(item.path);\n if (original) reordered.push(original);\n }\n return reordered;\n }\n\n private diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n ): QmdSearchResult[] {\n const safeLimit =\n typeof limit === \"number\" && Number.isFinite(limit)\n ? Math.max(0, Math.floor(limit))\n : 0;\n if (!Array.isArray(results) || results.length === 0) return [];\n // `recallResultLimit === 0` is a true zero limit (e.g. when\n // `memoriesSectionEnabled` is false) and must return an empty array so\n // the memories section is genuinely skipped. This mirrors the\n // `slice(0, 0)` semantics of every call site this helper replaced.\n if (safeLimit === 0) return [];\n // Issue #564 PR 3: when the feature flag is on, boost reasoning_trace\n // memories for problem-solving asks so they bubble up ahead of ordinary\n // facts/decisions before MMR picks the final section. No-op when the\n // flag is off or the query is not a problem-solving ask.\n const boosted =\n this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === \"string\"\n ? applyReasoningTraceBoost(results, {\n enabled: true,\n query: retrievalQuery,\n })\n : results;\n const diversified = this.applyMmrToQmdResults(sectionId, boosted);\n return diversified.slice(0, safeLimit);\n }\n\n /**\n * Apply Maximal Marginal Relevance to a section's ordered candidate list.\n *\n * Operates per-section so one redundant cluster cannot dominate a section,\n * and so one section's MMR pass cannot starve other sections. Returns the\n * input unchanged when disabled, when there are fewer than 2 candidates, or\n * when no budget information is available.\n */\n private applyMmrToQmdResults(\n sectionId: string,\n results: QmdSearchResult[],\n ): QmdSearchResult[] {\n if (this.config.recallMmrEnabled === false) return results;\n if (!Array.isArray(results) || results.length < 2) return results;\n\n // Config is runtime API (see AGENTS.md §4): preserve `0` as a true zero\n // limit rather than coercing it to a non-zero value. A configured topN of\n // 0 means \"apply MMR over an empty window\" — i.e. skip the reorder and\n // return the upstream candidates unchanged. This keeps read-time\n // behavior symmetric with the write-time semantics parseConfig exposes.\n const configuredTopN = this.config.recallMmrTopN;\n const topN =\n typeof configuredTopN === \"number\" && Number.isFinite(configuredTopN)\n ? Math.max(0, Math.floor(configuredTopN))\n : 40;\n if (topN === 0) return results;\n const lambda = this.config.recallMmrLambda ?? 0.7;\n\n // Delegate to the pure helper so candidate keying (path-first, index\n // suffixed for uniqueness) and the head-of-list diversity metric are\n // exercised by the same code path that the unit tests cover.\n const { reordered, diversity } = reorderRecallResultsWithMmr(results, {\n lambda,\n topN,\n });\n\n try {\n log.info(\n `recall_mmr: section=${sectionId} kept=${diversity.kept}/${diversity.considered} ` +\n `headReorderCount=${diversity.headReorderCount} ` +\n `avgSimBefore=${diversity.avgPairwiseSimBefore.toFixed(3)} ` +\n `avgSimAfter=${diversity.avgPairwiseSimAfter.toFixed(3)} ` +\n `lambda=${lambda.toFixed(2)}`,\n );\n } catch {\n // Metrics must never break recall.\n }\n\n return reordered;\n }\n\n private buildLastRecallBudgetSummary(options: {\n requestedTopK?: number;\n recallResultLimit: number;\n qmdFetchLimit: number;\n qmdHybridFetchLimit: number;\n finalContextChars?: number;\n truncated?: boolean;\n includedSections?: string[];\n omittedSections?: string[];\n }): LastRecallBudgetSummary {\n return {\n requestedTopK: options.requestedTopK,\n appliedTopK: options.recallResultLimit,\n recallBudgetChars: this.getRecallBudgetChars(),\n maxMemoryTokens: this.config.maxMemoryTokens,\n qmdFetchLimit: options.qmdFetchLimit,\n qmdHybridFetchLimit: options.qmdHybridFetchLimit,\n finalContextChars: options.finalContextChars,\n truncated: options.truncated,\n includedSections: [...(options.includedSections ?? [])],\n omittedSections: [...(options.omittedSections ?? [])],\n };\n }\n\n private collectLastRecallSources(\n sectionBuckets: Map<string, string[]>,\n recallSource:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\",\n ): string[] {\n const used = new Set<string>();\n if (recallSource !== \"none\") {\n used.add(recallSource);\n }\n for (const [sectionId, chunks] of sectionBuckets.entries()) {\n if (chunks.length > 0) {\n used.add(sectionId);\n }\n }\n return [...used];\n }\n\n /**\n * Issue #373 — nearest-neighbor lookup for the write-time semantic dedup\n * guard. Returns the top-K embedding hits against the currently indexed\n * memories, or an empty array when the embedding backend is unavailable.\n * Intentionally does NOT throw; `decideSemanticDedup` treats both \"empty\"\n * and \"error\" outcomes as fail-open (keep the candidate).\n *\n * PR #399 P1 fix: when namespaces are enabled the lookup must be scoped\n * to the SAME namespace as the fact being written. Otherwise a\n * high-similarity memory from another namespace can suppress a write in\n * the target namespace — cross-tenant data loss. Callers pass the target\n * storage so we can translate its root directory into the correct index\n * path prefix (and, for the legacy default-namespace layout at\n * `memoryDir` root, an exclusion list for `namespaces/*`).\n */\n async semanticDedupLookup(\n content: string,\n limit: number,\n targetStorage: StorageManager,\n ): Promise<SemanticDedupHit[]> {\n // Round 6 fix (Finding 3): backend-unavailable conditions must THROW so\n // that `decideSemanticDedup`'s catch block can return\n // reason=\"backend_unavailable\". Previously all error/unavailable paths\n // returned [] — causing decideSemanticDedup to always report\n // reason=\"no_candidates\" even when the provider was actually down.\n //\n // Contract after this fix:\n // • embeddingFallbackEnabled=false → throw (feature not configured;\n // caller treats this as backend_unavailable and fails open).\n // • isAvailable() returns false → throw (provider is reachable but\n // reports itself unavailable; distinct from empty index).\n // • search() throws → re-throw (network/provider error).\n // • search() returns [] → return [] (empty index, not a\n // backend failure; decideSemanticDedup reports no_candidates).\n if (!this.config.embeddingFallbackEnabled) {\n throw new Error(\"semantic dedup: embedding backend not configured\");\n }\n if (!(await this.embeddingFallback.isAvailable())) {\n log.debug(\"semantic dedup: embedding backend unavailable, skipping\");\n throw new Error(\"semantic dedup: embedding backend unavailable\");\n }\n // search() may throw — let it propagate so decideSemanticDedup catches it\n // and returns reason=\"backend_unavailable\". Pass throwOnTimeout:true so\n // EmbeddingTimeoutError is re-thrown here (Round 10 fix, Ui1J+Ui1L: the\n // recall-path caller searchEmbeddingFallback does NOT pass this flag,\n // keeping its fail-open [] contract on timeout).\n const scope = this.semanticDedupScopeFor(targetStorage);\n const hits = await this.embeddingFallback.search(content, limit, { ...scope, throwOnTimeout: true });\n if (!Array.isArray(hits) || hits.length === 0) return [];\n return hits.map((hit) => ({\n id: hit.id,\n score: hit.score,\n path: hit.path,\n }));\n }\n\n /**\n * Resolve the namespace-scoped filter to pass into\n * `EmbeddingFallback.search()` for semantic dedup. Returns an empty\n * object (no filter) when namespaces are disabled, preserving the\n * pre-PR #399 behavior for single-tenant installs.\n *\n * Index entries are stored as paths relative to `config.memoryDir`, so:\n * - A non-default namespace `ns` lives under `namespaces/<ns>/…` and\n * we include exactly that prefix.\n * - The default namespace may live at `memoryDir` root (legacy) or at\n * `memoryDir/namespaces/<default>/…` (migrated). When it lives at\n * root we include everything but EXCLUDE all `namespaces/…` entries\n * so facts from non-default namespaces can't cross-match.\n */\n private semanticDedupScopeFor(targetStorage: StorageManager): {\n pathPrefix?: string;\n pathExcludePrefixes?: readonly string[];\n } {\n if (!this.config.namespacesEnabled) return {};\n const memoryDir = path.resolve(this.config.memoryDir);\n const storageDir = path.resolve(targetStorage.dir);\n if (storageDir === memoryDir) {\n // Default namespace at legacy root. Include everything that isn't\n // under `namespaces/*` (those belong to other namespaces).\n return { pathExcludePrefixes: [\"namespaces/\"] };\n }\n let rel = path.relative(memoryDir, storageDir);\n if (!rel || rel.startsWith(\"..\")) {\n // Round 12 fix (PR #399 thread PRRT_kwDORJXyws56U6Gj): when\n // targetStorage.dir is outside memoryDir (custom namespace routing),\n // toMemoryRelativePath() stores the absolute file path in the index\n // rather than a memoryDir-relative path. Return the absolute storageDir\n // as the pathPrefix so the search() filter still scopes the lookup to\n // the correct tenant's files. Previously this returned {} (no scoping),\n // which let high-similarity hits from other namespaces' absolute-path\n // entries suppress writes in the target namespace — a cross-tenant\n // dedup suppression path.\n log.debug(\n `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`,\n );\n const absPrefix = storageDir.replace(/\\\\/g, \"/\");\n return { pathPrefix: absPrefix.endsWith(\"/\") ? absPrefix : `${absPrefix}/` };\n }\n rel = rel.replace(/\\\\/g, \"/\");\n if (!rel.endsWith(\"/\")) rel = `${rel}/`;\n return { pathPrefix: rel };\n }\n\n private async searchEmbeddingFallback(\n query: string,\n limit: number,\n ): Promise<QmdSearchResult[]> {\n if (!this.config.embeddingFallbackEnabled) return [];\n if (!(await this.embeddingFallback.isAvailable())) return [];\n const hits = await this.embeddingFallback.search(query, limit);\n if (hits.length === 0) return [];\n\n const results: QmdSearchResult[] = [];\n for (const hit of hits) {\n const fullPath = path.isAbsolute(hit.path)\n ? hit.path\n : path.join(this.config.memoryDir, hit.path);\n const memory = await this.storage.readMemoryByPath(fullPath);\n if (!memory) continue;\n results.push({\n docid: hit.id,\n path: fullPath,\n score: hit.score,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n });\n }\n return results;\n }\n\n /**\n * Long-term fallback retrieval.\n * Searches archived memories only, and is invoked only when hot recall returns zero hits.\n */\n private async searchLongTermArchiveFallback(\n prompt: string,\n recallNamespaces: string[],\n limit: number,\n queryAwarePrefilter?: QueryAwarePrefilter,\n abortSignal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n throwIfRecallAborted(abortSignal);\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0) return [];\n\n const scopedSeedResults = queryAwarePrefilter?.candidatePaths?.size\n ? await this.searchScopedMemoryCandidates(\n queryAwarePrefilter.candidatePaths,\n prompt,\n cappedLimit,\n { allowArchived: true },\n )\n : [];\n if (scopedSeedResults.length >= cappedLimit) {\n return scopedSeedResults\n .filter((result) => !isArtifactMemoryPath(result.path))\n .slice(0, cappedLimit);\n }\n\n const tokens = Array.from(new Set(tokenizeRecallQuery(prompt)));\n if (tokens.length === 0) return scopedSeedResults;\n\n throwIfRecallAborted(abortSignal);\n const archivedMemories =\n await this.readArchivedMemoriesForNamespaces(recallNamespaces);\n if (archivedMemories.length === 0) return scopedSeedResults;\n\n const scored: QmdSearchResult[] = [];\n for (const memory of archivedMemories) {\n throwIfRecallAborted(abortSignal);\n const haystack = [\n memory.content,\n memory.frontmatter.category,\n ...(memory.frontmatter.tags ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n let hits = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) hits += 1;\n }\n if (hits === 0) continue;\n const normalized = hits / tokens.length;\n scored.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n score: normalized,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n });\n }\n\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...scopedSeedResults, ...scored]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n\n return [...mergedByPath.values()]\n .filter((result) => !isArtifactMemoryPath(result.path))\n .sort((a, b) => b.score - a.score)\n .slice(0, cappedLimit);\n }\n\n private async applyColdFallbackPipeline(options: {\n prompt: string;\n recallNamespaces: string[];\n recallResultLimit: number;\n recallMode: RecallPlanMode;\n queryAwarePrefilter?: QueryAwarePrefilter;\n abortSignal?: AbortSignal;\n /** Issue #680 — historical recall point in ms-since-epoch. */\n asOfMs?: number;\n /**\n * Optional out-parameter that receives the pre-MMR / pre-truncation\n * pool size captured inside the pipeline (issue #570 PR 1). The\n * X-ray capture block in `recallInternal` passes a small sink so\n * the cold-fallback branch's pre-truncation pool size can be\n * attributed back to the branch when `recallSource === \"cold_fallback\"`.\n * Unset by default so existing call sites are unaffected.\n */\n xrayPoolSizeSink?: { size: number };\n /** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */\n includeLowConfidence?: boolean;\n }): Promise<QmdSearchResult[]> {\n const coldQmdEnabled = this.config.qmdColdTierEnabled === true;\n const coldCollection =\n this.config.qmdColdCollection ?? \"openclaw-engram-cold\";\n const coldMaxResults =\n this.config.qmdColdMaxResults ?? this.config.qmdMaxResults;\n\n let longTerm: QmdSearchResult[] = [];\n if (coldQmdEnabled && this.qmd.isAvailable()) {\n const coldFetchLimit = Math.max(\n 0,\n Math.min(options.recallResultLimit, Math.max(0, coldMaxResults)),\n );\n if (coldFetchLimit > 0) {\n const coldHybridLimit = computeQmdHybridFetchLimit(\n coldFetchLimit,\n false,\n 0,\n );\n longTerm = await this.fetchQmdMemoryResultsWithArtifactTopUp(\n options.prompt,\n coldFetchLimit,\n coldHybridLimit,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n collection: coldCollection,\n queryAwarePrefilter: options.queryAwarePrefilter,\n searchOptions: this.buildConfiguredQmdSearchOptions(options.prompt),\n abortSignal: options.abortSignal,\n },\n );\n if (longTerm.length > 0) {\n log.debug(\n `cold-tier recall source=cold-qmd collection=${coldCollection} hits=${longTerm.length}`,\n );\n }\n }\n }\n if (longTerm.length === 0) {\n longTerm = await this.searchLongTermArchiveFallback(\n options.prompt,\n options.recallNamespaces,\n options.recallResultLimit,\n options.queryAwarePrefilter,\n options.abortSignal,\n );\n if (longTerm.length > 0) {\n log.debug(\"cold-tier recall source=archive-scan\");\n }\n }\n if (longTerm.length === 0) return [];\n\n let results = longTerm;\n if (this.config.namespacesEnabled) {\n results = results.filter((r) =>\n options.recallNamespaces.includes(this.namespaceFromPath(r.path)),\n );\n }\n // Artifact isolation contract: generic recall paths must exclude artifacts.\n results = results.filter((r) => !isArtifactMemoryPath(r.path));\n if (results.length === 0) return [];\n\n const isFullModeGraphAssist =\n this.config.qmdTierParityGraphEnabled &&\n this.config.multiGraphMemoryEnabled &&\n this.config.graphAssistInFullModeEnabled !== false &&\n options.recallMode === \"full\" &&\n results.length >= Math.max(1, this.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n this.config.qmdTierParityGraphEnabled &&\n (options.recallMode === \"graph_mode\" || isFullModeGraphAssist);\n\n if (shouldRunGraphExpansion) {\n const { merged } = await this.expandResultsViaGraph({\n memoryResults: results,\n recallNamespaces: options.recallNamespaces,\n recallResultLimit: options.recallResultLimit,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n results = merged;\n }\n\n results = await this.boostSearchResults(\n results,\n options.recallNamespaces,\n options.prompt,\n undefined,\n { allowLifecycleFiltered: true, asOfMs: options.asOfMs },\n );\n\n if (this.config.rerankEnabled && this.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: options.prompt,\n candidates: results\n .slice(0, this.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.config.rerankTimeoutMs,\n maxCandidates: this.config.rerankMaxCandidates,\n cache: this.rerankCache,\n cacheEnabled: this.config.rerankCacheEnabled,\n cacheTtlMs: this.config.rerankCacheTtlMs,\n });\n if (ranked && ranked.length > 0) {\n const byPath = new Map(results.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const p of ranked) {\n const it = byPath.get(p);\n if (it) reordered.push(it);\n }\n const rankedSet = new Set(ranked);\n for (const r of results) {\n if (!rankedSet.has(r.path)) reordered.push(r);\n }\n results = reordered;\n }\n }\n if (this.config.rerankEnabled && this.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Memory Worth filter — must fire on the cold fallback path too, or the\n // feature flag produces divergent behavior by retrieval path (CLAUDE.md\n // rule 39). Fail-open on lookup errors.\n if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {\n try {\n results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);\n } catch (err) {\n log.debug(\"memory-worth filter (cold) failed open\", {\n error: (err as Error).message,\n });\n }\n }\n\n // Apply MMR before final truncation so the cold fallback path mirrors\n // the diversification policy applied in the hot QMD/embedding/recent\n // paths. Running MMR post-slice would be unable to promote diverse\n // candidates sitting just below the cutoff.\n if (options.xrayPoolSizeSink) {\n options.xrayPoolSizeSink.size = Math.max(\n options.xrayPoolSizeSink.size,\n results.length,\n );\n }\n return this.diversifyAndLimitRecallResults(\n \"memories\",\n results,\n options.recallResultLimit,\n options.prompt,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Access Tracking (Phase 1A)\n // ---------------------------------------------------------------------------\n\n /**\n * Record that memories were accessed (retrieved).\n * Updates are batched in memory and flushed during consolidation.\n */\n trackMemoryAccess(memoryIds: string[]): void {\n if (!this.config.accessTrackingEnabled) return;\n\n const now = new Date().toISOString();\n for (const id of memoryIds) {\n const existing = this.accessTrackingBuffer.get(id);\n this.accessTrackingBuffer.set(id, {\n count: (existing?.count ?? 0) + 1,\n lastAccessed: now,\n });\n }\n\n // Flush if buffer exceeds max size\n if (\n this.accessTrackingBuffer.size >= this.config.accessTrackingBufferMaxSize\n ) {\n this.flushAccessTracking().catch((err) =>\n log.debug(`background access tracking flush failed: ${err}`),\n );\n }\n }\n\n /**\n * Flush access tracking buffer to disk.\n * Called during consolidation or when buffer is full.\n */\n async flushAccessTracking(): Promise<void> {\n if (this.accessTrackingBuffer.size === 0) return;\n\n // Build entries from buffer, merging with existing counts\n const entries: AccessTrackingEntry[] = [];\n const namespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]),\n )\n : [this.config.defaultNamespace];\n const memories = await this.readAllMemoriesForNamespaces(namespaces);\n const memoryMap = new Map(memories.map((m) => [m.frontmatter.id, m]));\n\n for (const [memoryId, update] of this.accessTrackingBuffer) {\n const memory = memoryMap.get(memoryId);\n const existingCount = memory?.frontmatter.accessCount ?? 0;\n entries.push({\n memoryId,\n newCount: existingCount + update.count,\n lastAccessed: update.lastAccessed,\n });\n }\n\n const byNamespace = new Map<string, AccessTrackingEntry[]>();\n for (const e of entries) {\n const m = memoryMap.get(e.memoryId);\n if (!m) continue;\n const ns = this.namespaceFromPath(m.path);\n const list = byNamespace.get(ns) ?? [];\n list.push(e);\n byNamespace.set(ns, list);\n }\n for (const [ns, list] of byNamespace) {\n const sm = await this.storageRouter.storageFor(ns);\n await sm.flushAccessTracking(list);\n }\n this.accessTrackingBuffer.clear();\n log.debug(`flushed ${entries.length} access tracking entries`);\n }\n\n /**\n * Apply recency, access count, and importance boosting to QMD search results.\n * Returns re-ranked results.\n */\n private async boostSearchResults(\n results: QmdSearchResult[],\n _recallNamespaces: string[],\n prompt?: string,\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n /**\n * Historical recall point in ms-since-epoch (issue #680). When\n * set, drops candidates that were not authoritative at this\n * instant per `temporal-validity.isValidAsOf`. Caller is\n * responsible for parsing/validating the user-supplied ISO\n * string at the input boundary (CLI / HTTP / MCP).\n */\n asOfMs?: number;\n },\n ): Promise<QmdSearchResult[]> {\n if (results.length === 0) return results;\n\n const now = Date.now();\n // Seed with any pre-loaded memories (e.g. from the recency fallback path)\n // to avoid redundant disk reads for files already in memory.\n const memoryByPath: Map<string, MemoryFile> = preloadedMemoryMap\n ? new Map(preloadedMemoryMap)\n : new Map();\n\n // Determine temporal/tag query params before I/O (pure computation).\n const resultPaths = new Set(\n results.map((r) => r.path).filter(Boolean) as string[],\n );\n let temporalFromDate: string | null = null;\n let promptTags: string[] = [];\n if (this.config.queryAwareIndexingEnabled && prompt) {\n if (isTemporalQuery(prompt)) {\n temporalFromDate = recencyWindowFromPrompt(prompt, now);\n }\n promptTags = extractTagsFromPrompt(prompt);\n }\n\n // Run all file I/O in parallel: memory files not yet preloaded + index files.\n const [, rawTemporal, rawTags] = await Promise.all([\n Promise.all(\n results.map(async (r) => {\n if (!r.path || memoryByPath.has(r.path)) return;\n const mem = await this.storage.readMemoryByPath(r.path);\n if (mem) memoryByPath.set(r.path, mem);\n }),\n ),\n temporalFromDate !== null\n ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n promptTags.length > 0\n ? queryByTagsAsync(this.config.memoryDir, promptTags)\n : Promise.resolve<Set<string> | null>(null),\n ]);\n\n const queryIntent =\n this.config.intentRoutingEnabled && prompt\n ? inferIntentFromText(prompt)\n : null;\n\n // v8.1: Temporal + Tag prefilter candidate set\n // Scope to result paths first so cross-namespace paths don't consume the cap.\n let temporalCandidates: Set<string> | null = null;\n let tagCandidates: Set<string> | null = null;\n if (this.config.queryAwareIndexingEnabled && prompt) {\n const maxCandidates = this.config.queryAwareIndexingMaxCandidates;\n const capSet = (s: Set<string> | null): Set<string> | null => {\n if (!s) return null;\n // Intersect with result paths first so out-of-scope paths don't exhaust the budget\n const scoped = new Set(Array.from(s).filter((p) => resultPaths.has(p)));\n if (maxCandidates === 0 || scoped.size <= maxCandidates)\n return scoped.size > 0 ? scoped : null;\n return new Set(Array.from(scoped).slice(0, maxCandidates));\n };\n if (temporalFromDate !== null) {\n temporalCandidates = capSet(rawTemporal);\n }\n if (promptTags.length > 0) {\n tagCandidates = capSet(rawTags);\n }\n }\n\n let lifecycleFilteredCount = 0;\n let temporalSupersededFilteredCount = 0;\n let dedicatedSurfaceFilteredCount = 0;\n let forgottenFilteredCount = 0;\n const boosted: QmdSearchResult[] = [];\n const recencyWeight = this.effectiveRecencyWeight();\n for (const r of results) {\n const memory = memoryByPath.get(r.path);\n let score = r.score;\n\n if (memory) {\n if (memory.frontmatter.status === \"forgotten\") {\n forgottenFilteredCount += 1;\n continue;\n }\n\n if (\n options?.allowLifecycleFiltered !== true &&\n shouldFilterLifecycleRecallCandidate(memory.frontmatter, {\n lifecyclePolicyEnabled: this.config.lifecyclePolicyEnabled,\n lifecycleFilterStaleEnabled:\n this.config.lifecycleFilterStaleEnabled,\n })\n ) {\n lifecycleFilteredCount += 1;\n continue;\n }\n\n // Historical recall (issue #680): when the caller pinned the\n // recall to a specific point in time, evaluate temporal validity\n // at that instant FIRST and bypass the supersession filter\n // entirely. A fact that is currently superseded but was valid\n // at `as_of` is exactly what historical recall should surface;\n // running supersession filtering before the as_of check would\n // drop it and break the worked example in docs/temporal-recall.md\n // (codex P1 / cursor High on PR #713).\n const asOfActive =\n typeof options?.asOfMs === \"number\" && Number.isFinite(options.asOfMs);\n if (asOfActive) {\n if (!isValidAsOf(memory.frontmatter, options!.asOfMs!)) {\n temporalSupersededFilteredCount += 1;\n continue;\n }\n } else if (\n // Temporal supersession filter (issue #375): drop memories that\n // a newer fact has retired, unless the caller opted in to history.\n // NOTE: This check is intentionally independent of\n // allowLifecycleFiltered (Finding A fix) — cold fallback sets\n // allowLifecycleFiltered=true to include archived/retired\n // candidates, but superseded memories must still be filtered\n // unless temporalSupersessionIncludeInRecall is set.\n // Skipped entirely when `as_of` is active (above branch); the\n // half-open `[valid_at, invalid_at)` evaluation in isValidAsOf\n // is the authoritative gate for historical recall.\n shouldFilterSupersededFromRecall(memory.frontmatter, {\n enabled: this.config.temporalSupersessionEnabled,\n includeInRecall: this.config.temporalSupersessionIncludeInRecall,\n })\n ) {\n temporalSupersededFilteredCount += 1;\n continue;\n }\n\n if (\n options?.allowDedicatedSurface !== true &&\n (memory.frontmatter.memoryKind === \"dream\" ||\n memory.frontmatter.memoryKind === \"procedural\")\n ) {\n dedicatedSurfaceFilteredCount += 1;\n continue;\n }\n\n // Recency boost: exponential decay over 7 days\n if (recencyWeight > 0) {\n const createdAt = new Date(memory.frontmatter.created).getTime();\n const ageMs = now - createdAt;\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n const halfLifeDays = 7;\n const recencyScore = Math.pow(0.5, ageDays / halfLifeDays);\n score = score * (1 - recencyWeight) + recencyScore * recencyWeight;\n }\n\n // Access count boost: log scale, capped\n if (this.config.boostAccessCount && memory.frontmatter.accessCount) {\n const accessBoost =\n Math.log10(memory.frontmatter.accessCount + 1) / 3;\n score += applyUtilityRankingRuntimeDelta(\n Math.min(accessBoost, 0.1),\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n\n // Importance boost (Phase 1B): higher importance = higher rank\n if (memory.frontmatter.importance) {\n const importanceScore = memory.frontmatter.importance.score;\n // Boost important memories, slightly penalize trivial ones\n // Scale: trivial (-0.05) to critical (+0.15)\n const importanceBoost = (importanceScore - 0.4) * 0.25;\n score += applyUtilityRankingRuntimeDelta(\n importanceBoost,\n this.utilityRuntimeValues,\n importanceBoost >= 0 ? \"boost\" : \"suppress\",\n );\n }\n\n // Feedback bias (v2.2): apply small user-provided up/down vote adjustments.\n if (this.config.feedbackEnabled) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const feedbackDelta = this.relevance.adjustment(memoryId);\n score += applyUtilityRankingRuntimeDelta(\n feedbackDelta,\n this.utilityRuntimeValues,\n feedbackDelta >= 0 ? \"boost\" : \"suppress\",\n );\n }\n }\n\n // Negative examples (v2.2): apply a small penalty for memories repeatedly marked \"not useful\".\n if (this.config.negativeExamplesEnabled) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const negativePenalty = this.negatives.penalty(memoryId, {\n perHit: this.config.negativeExamplesPenaltyPerHit,\n cap: this.config.negativeExamplesPenaltyCap,\n });\n score -= applyUtilityRankingRuntimeDelta(\n negativePenalty,\n this.utilityRuntimeValues,\n \"suppress\",\n );\n }\n }\n\n if (\n queryIntent &&\n memory.frontmatter.intentGoal &&\n memory.frontmatter.intentActionType\n ) {\n const compatibility = intentCompatibilityScore(queryIntent, {\n goal: memory.frontmatter.intentGoal,\n actionType: memory.frontmatter.intentActionType,\n entityTypes: memory.frontmatter.intentEntityTypes ?? [],\n });\n score += applyUtilityRankingRuntimeDelta(\n compatibility * this.config.intentRoutingBoost,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n\n // v8.1: Temporal + Tag index boost\n // Results that match the detected temporal window or tag query get a small additive boost.\n if (this.config.queryAwareIndexingEnabled && r.path) {\n if (temporalCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.08,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n if (tagCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.06,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n }\n\n // v8.3: lifecycle retrieval weighting (fail-open on legacy memories).\n const lifecycleDelta = lifecycleRecallScoreAdjustment(\n memory.frontmatter,\n {\n lifecyclePolicyEnabled: this.config.lifecyclePolicyEnabled,\n },\n );\n score += applyUtilityRankingRuntimeDelta(\n lifecycleDelta,\n this.utilityRuntimeValues,\n lifecycleDelta >= 0 ? \"boost\" : \"suppress\",\n );\n\n // Reinforcement recall boost (issue #687 PR 3/4).\n // Applies an additive score bonus proportional to how many times the\n // pattern-reinforcement job has promoted this memory as a canonical.\n // Formula: min(reinforcement_count * weight, max).\n // Gated by reinforcementRecallBoostEnabled (default false).\n let reinforcementBoost = 0;\n if (\n this.config.reinforcementRecallBoostEnabled &&\n typeof memory.frontmatter.reinforcement_count === \"number\" &&\n memory.frontmatter.reinforcement_count > 0\n ) {\n reinforcementBoost = Math.min(\n memory.frontmatter.reinforcement_count *\n this.config.reinforcementRecallBoostWeight,\n this.config.reinforcementRecallBoostMax,\n );\n score += reinforcementBoost;\n }\n if (reinforcementBoost > 0) {\n boosted.push({\n ...r,\n score,\n explain: { ...(r.explain ?? {}), reinforcementBoost },\n });\n continue;\n }\n }\n\n boosted.push({ ...r, score });\n }\n if (lifecycleFilteredCount > 0) {\n log.debug(\n `lifecycle retrieval filter removed ${lifecycleFilteredCount} stale/archived candidates`,\n );\n }\n if (temporalSupersededFilteredCount > 0) {\n log.debug(\n `temporal supersession filter removed ${temporalSupersededFilteredCount} superseded candidates`,\n );\n }\n if (dedicatedSurfaceFilteredCount > 0) {\n log.debug(\n `dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural candidates from generic recall`,\n );\n }\n if (forgottenFilteredCount > 0) {\n log.debug(\n `forgotten status filter removed ${forgottenFilteredCount} candidates from recall`,\n );\n }\n\n // Re-sort by boosted score\n return boosted.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Extract memory IDs from QMD search results for access tracking.\n */\n private extractMemoryIdsFromResults(results: QmdSearchResult[]): string[] {\n // QMD results have paths like /path/to/fact-123.md\n // Extract the ID from the filename\n return results\n .map((r) => {\n const match = r.path.match(/([^/]+)\\.md$/);\n return match ? match[1] : null;\n })\n .filter((id): id is string => id !== null);\n }\n\n // ---------------------------------------------------------------------------\n // Contradiction Detection (Phase 2B)\n // ---------------------------------------------------------------------------\n\n // ---------------------------------------------------------------------------\n // Feedback (v2.2)\n // ---------------------------------------------------------------------------\n\n async recordMemoryFeedback(\n memoryId: string,\n vote: \"up\" | \"down\",\n note?: string,\n ): Promise<void> {\n await this.relevance.record(memoryId, vote, note);\n }\n\n // Negative Examples (v2.2)\n async recordNotUsefulMemories(\n memoryIds: string[],\n note?: string,\n ): Promise<void> {\n await this.negatives.recordNotUseful(memoryIds, note);\n }\n\n getLastRecall(sessionKey: string): LastRecallSnapshot | null {\n return this.lastRecall.get(sessionKey);\n }\n\n /**\n * Check if a new memory contradicts an existing one.\n * Uses QMD to find similar memories, then LLM to verify contradiction.\n */\n private async checkForContradiction(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<{\n supersededId: string;\n confidence: number;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n } | null> {\n if (!this.isSearchAvailableForNamespaceRouting()) return null;\n\n // Search for similar memories\n const results = await this.searchAcrossNamespaces({\n query: content,\n namespaces: [namespaceScope],\n maxResults: 5,\n mode: \"search\",\n });\n\n for (const result of results) {\n // Check similarity threshold\n if (result.score < this.config.contradictionSimilarityThreshold) {\n continue;\n }\n\n // Get the existing memory\n const memoryId = this.extractMemoryIdsFromResults([result])[0];\n if (!memoryId) continue;\n\n const resultNamespace = this.namespaceFromPath(result.path);\n if (resultNamespace !== namespaceScope) continue;\n const resultStorage =\n await this.storageRouter.storageFor(resultNamespace);\n const existingMemory = await resultStorage.getMemoryById(memoryId);\n if (!existingMemory) continue;\n\n // Skip memories already resolved or explicitly forgotten. Other\n // non-active statuses remain valid contradiction candidates.\n if (\n existingMemory.frontmatter.status === \"superseded\" ||\n existingMemory.frontmatter.status === \"forgotten\"\n ) {\n continue;\n }\n\n // Verify contradiction with LLM\n const verification = await this.extraction.verifyContradiction(\n { content, category },\n {\n id: existingMemory.frontmatter.id,\n content: existingMemory.content,\n category: existingMemory.frontmatter.category,\n created: existingMemory.frontmatter.created,\n },\n );\n\n if (!verification) continue;\n\n // Check if it's a real contradiction with high confidence\n if (\n verification.isContradiction &&\n verification.confidence >= this.config.contradictionMinConfidence\n ) {\n // When the LLM says the existing memory is newer (whichIsNewer ===\n // \"first\") the incoming fact is the stale one in both resolve modes —\n // log and continue so the caller never marks contradictionDetected and\n // the semantic-skip gate can discard the outdated write normally.\n if (verification.whichIsNewer === \"first\") {\n log.info(\n `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory — existing is newer, incoming fact is stale`,\n );\n continue;\n }\n\n // The new fact is newer than the existing one. When auto-resolve is\n // enabled, immediately retire the old memory. When disabled, leave the\n // old memory active for manual review.\n if (this.config.contradictionAutoResolve) {\n await resultStorage.supersedeMemory(\n existingMemory.frontmatter.id,\n \"pending-new\", // Will be updated after the new memory is written\n verification.reasoning,\n );\n }\n\n // Return the contradiction info regardless of auto-resolve setting.\n // The caller uses this to set `contradictionDetected=true` which\n // prevents the semantic-skip guard from silently dropping a\n // legitimately contradictory update (the regression this fixes).\n log.info(\n `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${this.config.contradictionAutoResolve ? \" (auto-resolved)\" : \" (queued for manual review)\"}`,\n );\n return {\n supersededId: existingMemory.frontmatter.id,\n confidence: verification.confidence,\n reason: verification.reasoning,\n supersededPath: existingMemory.path,\n supersededCreated: existingMemory.frontmatter.created,\n supersededTags: existingMemory.frontmatter.tags ?? [],\n };\n }\n }\n\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // Memory Linking (Phase 3A)\n // ---------------------------------------------------------------------------\n\n /**\n * Suggest links for a new memory based on similar existing memories.\n */\n private async suggestLinksForMemory(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<MemoryLink[]> {\n if (!this.isSearchAvailableForNamespaceRouting()) return [];\n\n // Search for related memories\n const results = await this.searchAcrossNamespaces({\n query: content,\n namespaces: [namespaceScope],\n maxResults: 5,\n mode: \"search\",\n });\n if (results.length === 0) return [];\n\n // Get full memory details for candidates\n const candidates: Array<{ id: string; content: string; category: string }> =\n [];\n for (const result of results) {\n const memoryId = this.extractMemoryIdsFromResults([result])[0];\n if (!memoryId) continue;\n\n const resultNamespace = this.namespaceFromPath(result.path);\n if (resultNamespace !== namespaceScope) continue;\n const resultStorage =\n await this.storageRouter.storageFor(resultNamespace);\n const memory = await resultStorage.getMemoryById(memoryId);\n if (\n memory &&\n memory.frontmatter.status !== \"superseded\" &&\n memory.frontmatter.status !== \"forgotten\"\n ) {\n candidates.push({\n id: memory.frontmatter.id,\n content: memory.content,\n category: memory.frontmatter.category,\n });\n }\n }\n\n if (candidates.length === 0) return [];\n\n // Ask LLM for link suggestions\n const suggestions = await this.extraction.suggestLinks(\n { content, category },\n candidates,\n );\n\n if (!suggestions || suggestions.links.length === 0) return [];\n\n // Convert to MemoryLink format\n return suggestions.links.map((link) => ({\n targetId: link.targetId,\n linkType: link.linkType,\n strength: link.strength,\n reason: link.reason || undefined,\n }));\n }\n\n private namespaceFromPath(p: string): string {\n if (!this.config.namespacesEnabled) return this.config.defaultNamespace;\n const m = p.match(/[\\\\/]+namespaces[\\\\/]+([^\\\\/]+)(?:[\\\\/]|$)/);\n return m && m[1] ? m[1] : this.config.defaultNamespace;\n }\n\n private namespaceFromStorageDir(storageDir: string): string {\n if (!this.config.namespacesEnabled) return this.config.defaultNamespace;\n const resolvedStorageDir = path.resolve(storageDir);\n const resolvedMemoryDir = path.resolve(this.config.memoryDir);\n if (resolvedStorageDir === resolvedMemoryDir)\n return this.config.defaultNamespace;\n const m = resolvedStorageDir.match(/[\\\\/]namespaces[\\\\/]([^\\\\/]+)$/);\n return m && m[1] ? m[1] : this.config.defaultNamespace;\n }\n\n private async readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n const uniq = Array.from(new Set(namespaces.filter(Boolean)));\n const lists = await Promise.all(\n uniq.map(async (ns) => {\n const sm = await this.storageRouter.storageFor(ns);\n return sm.readAllMemories();\n }),\n );\n return lists.flat();\n }\n\n private async readArchivedMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n const uniq = Array.from(new Set(namespaces.filter(Boolean)));\n const lists = await Promise.all(\n uniq.map(async (ns) => {\n const sm = await this.storageRouter.storageFor(ns);\n return sm.readArchivedMemories();\n }),\n );\n return lists.flat();\n }\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n copyFile,\n mkdir,\n open,\n readFile,\n readdir,\n rm,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { resolveHomeDir } from \"../runtime/env.js\";\nimport { launchProcessSync } from \"../runtime/child-process.js\";\n\nexport interface MigrationResult {\n status: \"fresh-install\" | \"already-migrated\" | \"migrated\";\n copied: string[];\n tokensRegenerated: number;\n servicesReinstalled: string[];\n rollbackCommand: string;\n}\n\ninterface RollbackManifestEntry {\n targetPath: string;\n backupPath?: string;\n createdByMigration?: boolean;\n}\n\ninterface RollbackManifest {\n version: 1;\n createdAt: string;\n entries: RollbackManifestEntry[];\n}\n\nexport interface MigrationOptions {\n connectorConfigPaths?: string[];\n cwd?: string;\n execCommand?: (command: string, args: string[]) => void;\n homeDir?: string;\n logger?: (message: string) => void;\n platform?: NodeJS.Platform;\n quiet?: boolean;\n}\n\nexport interface RollbackResult {\n removed: string[];\n restored: string[];\n}\n\ninterface TokenEntry {\n connector: string;\n createdAt: string;\n token: string;\n}\n\nconst MARKER_FILE = \".migrated-from-engram\";\nconst LOCK_FILE = \".migration.lock\";\nconst ROLLBACK_MANIFEST = \".rollback.json\";\nconst BACKUP_DIR = \".backup\";\nconst LOCK_RETRY_MS = 100;\nconst LOCK_STALE_MS = 30_000;\nconst LOCK_TIMEOUT_MS = 5_000;\n\nfunction resolvePlatform(options?: MigrationOptions): NodeJS.Platform {\n return options?.platform ?? process.platform;\n}\n\nfunction resolveMigrationHome(options?: MigrationOptions): string {\n return options?.homeDir ?? resolveHomeDir();\n}\n\nfunction resolveLogger(options?: MigrationOptions): (message: string) => void {\n const sink = options?.logger ?? ((message: string) => console.log(message));\n return (message: string) => {\n if (!options?.quiet) sink(`[remnic] ${message}`);\n };\n}\n\nfunction resolveExec(options?: MigrationOptions): (command: string, args: string[]) => void {\n return options?.execCommand ?? ((command: string, args: string[]) => {\n const result = launchProcessSync(command, args, { stdio: \"ignore\" });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const reason = result.status === null\n ? `signal ${result.signal ?? \"unknown\"}`\n : `exit code ${result.status}`;\n throw new Error(`migration command failed: ${command} ${args.join(\" \")} (${reason})`);\n }\n });\n}\n\nfunction remnicRoot(homeDir: string): string {\n return path.join(homeDir, \".remnic\");\n}\n\nfunction legacyRoot(homeDir: string): string {\n return path.join(homeDir, \".engram\");\n}\n\nfunction legacyConfigPath(homeDir: string): string {\n return path.join(homeDir, \".config\", \"engram\", \"config.json\");\n}\n\nfunction remnicConfigPath(homeDir: string): string {\n return path.join(homeDir, \".config\", \"remnic\", \"config.json\");\n}\n\nfunction markerPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), MARKER_FILE);\n}\n\nfunction lockPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), LOCK_FILE);\n}\n\nfunction rollbackManifestPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), ROLLBACK_MANIFEST);\n}\n\nfunction backupRoot(homeDir: string): string {\n return path.join(remnicRoot(homeDir), BACKUP_DIR);\n}\n\nfunction defaultRollbackCommand(): string {\n return \"remnic migrate --rollback\";\n}\n\nasync function ensureParent(filePath: string): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n}\n\nasync function copyTreeMissing(source: string, destination: string, copied: string[]): Promise<void> {\n if (!existsSync(source)) return;\n const sourceStat = await stat(source);\n if (sourceStat.isDirectory()) {\n await mkdir(destination, { recursive: true });\n const entries = await readdir(source, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === MARKER_FILE || entry.name === LOCK_FILE || entry.name === ROLLBACK_MANIFEST) {\n continue;\n }\n await copyTreeMissing(\n path.join(source, entry.name),\n path.join(destination, entry.name),\n copied,\n );\n }\n return;\n }\n\n if (existsSync(destination)) return;\n await ensureParent(destination);\n await copyFile(source, destination);\n copied.push(destination);\n}\n\nfunction rewriteRemnicText(content: string): string {\n return content\n .replaceAll(\".engram/\", \".remnic/\")\n .replaceAll(\".engram\\\\\", \".remnic\\\\\")\n .replaceAll(\"ENGRAM_\", \"REMNIC_\")\n .replaceAll(\"{{ENGRAM_TOKEN}}\", \"{{REMNIC_TOKEN}}\")\n .replaceAll(\"${ENGRAM_AUTH_TOKEN}\", \"${REMNIC_AUTH_TOKEN}\")\n .replaceAll(\"ai.engram.daemon\", \"ai.remnic.daemon\")\n .replaceAll(\"engram.service\", \"remnic.service\");\n}\n\nfunction rewriteTokenValue(token: string): string {\n return token.startsWith(\"engram_\") ? `remnic_${token.slice(\"engram_\".length)}` : token;\n}\n\nfunction parseTokenEntries(raw: unknown): TokenEntry[] {\n if (typeof raw !== \"object\" || raw === null) return [];\n\n if (Array.isArray((raw as { tokens?: unknown }).tokens)) {\n return ((raw as { tokens: unknown[] }).tokens)\n .filter((entry): entry is TokenEntry => {\n if (typeof entry !== \"object\" || entry === null) return false;\n const candidate = entry as Partial<TokenEntry>;\n return typeof candidate.connector === \"string\" &&\n candidate.connector.length > 0 &&\n typeof candidate.token === \"string\" &&\n candidate.token.length > 0 &&\n typeof candidate.createdAt === \"string\" &&\n candidate.createdAt.length > 0;\n })\n .map((entry) => ({ ...entry }));\n }\n\n return Object.entries(raw)\n .filter(([key, value]) => key !== \"tokens\" && typeof value === \"string\" && value.length > 0)\n .map(([connector, token]) => ({\n connector,\n createdAt: new Date().toISOString(),\n token,\n }));\n}\n\nasync function rewriteTokensIfPresent(filePath: string): Promise<number> {\n if (!existsSync(filePath)) return 0;\n let raw: Record<string, unknown>;\n try {\n raw = JSON.parse(await readFile(filePath, \"utf8\")) as Record<string, unknown>;\n } catch {\n return 0;\n }\n let rewritten = 0;\n\n if (Array.isArray(raw.tokens)) {\n for (const entry of raw.tokens as Array<Record<string, unknown>>) {\n if (typeof entry.token === \"string\") {\n const next = rewriteTokenValue(entry.token);\n if (next !== entry.token) {\n entry.token = next;\n rewritten += 1;\n }\n }\n }\n } else {\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value === \"string\") {\n const next = rewriteTokenValue(value);\n if (next !== value) {\n raw[key] = next;\n rewritten += 1;\n }\n }\n }\n }\n\n if (rewritten > 0) {\n await writeFile(filePath, `${JSON.stringify(raw, null, 2)}\\n`, \"utf8\");\n }\n return rewritten;\n}\n\nasync function mergeLegacyTokens(\n legacyTokensPath: string,\n remnicTokensPath: string,\n homeDir: string,\n manifest: RollbackManifest,\n backupExisting: boolean,\n): Promise<number> {\n if (!existsSync(remnicTokensPath)) return 0;\n if (!existsSync(legacyTokensPath)) return rewriteTokensIfPresent(remnicTokensPath);\n\n let remnicRaw: unknown;\n let legacyRaw: unknown;\n const originalRemnic = await readFile(remnicTokensPath, \"utf8\");\n\n try {\n remnicRaw = JSON.parse(originalRemnic) as unknown;\n legacyRaw = JSON.parse(await readFile(legacyTokensPath, \"utf8\")) as unknown;\n } catch {\n try {\n legacyRaw = JSON.parse(await readFile(legacyTokensPath, \"utf8\")) as unknown;\n } catch {\n return rewriteTokensIfPresent(remnicTokensPath);\n }\n\n const legacyEntries = parseTokenEntries(legacyRaw);\n let rewritten = 0;\n const recoveredEntries = legacyEntries.map((entry) => {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) rewritten += 1;\n return {\n ...entry,\n token: nextToken,\n };\n });\n\n if (backupExisting) {\n await backupFile(remnicTokensPath, originalRemnic, homeDir, manifest);\n }\n\n await writeFile(\n remnicTokensPath,\n `${JSON.stringify({ tokens: recoveredEntries }, null, 2)}\\n`,\n \"utf8\",\n );\n return rewritten;\n }\n\n const mergedEntries = parseTokenEntries(remnicRaw);\n const legacyEntries = parseTokenEntries(legacyRaw);\n const existingConnectors = new Set(mergedEntries.map((entry) => entry.connector));\n let rewritten = 0;\n let changed = false;\n\n for (const entry of mergedEntries) {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) {\n entry.token = nextToken;\n rewritten += 1;\n changed = true;\n }\n }\n\n for (const entry of legacyEntries) {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) {\n rewritten += 1;\n }\n if (existingConnectors.has(entry.connector)) continue;\n mergedEntries.push({ ...entry, token: nextToken });\n existingConnectors.add(entry.connector);\n changed = true;\n }\n\n if (!changed) return rewritten;\n\n if (backupExisting) {\n await backupFile(remnicTokensPath, originalRemnic, homeDir, manifest);\n }\n\n await writeFile(\n remnicTokensPath,\n `${JSON.stringify({ tokens: mergedEntries }, null, 2)}\\n`,\n \"utf8\",\n );\n return rewritten;\n}\n\nasync function rewriteJsonFile(\n targetPath: string,\n homeDir: string,\n manifest: RollbackManifest,\n): Promise<boolean> {\n if (!existsSync(targetPath)) return false;\n\n const original = await readFile(targetPath, \"utf8\");\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(original) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n let changed = false;\n if (\n parsed.mcpServers &&\n typeof parsed.mcpServers === \"object\" &&\n !Array.isArray(parsed.mcpServers)\n ) {\n const servers = parsed.mcpServers as Record<string, unknown>;\n if (servers.engram && !servers.remnic) {\n servers.remnic = servers.engram;\n delete servers.engram;\n changed = true;\n }\n }\n\n const rewritten = rewriteRemnicText(JSON.stringify(parsed, null, 2));\n const next = `${rewritten}\\n`;\n if (!changed && next === original) return false;\n\n await backupFile(targetPath, original, homeDir, manifest);\n await writeFile(targetPath, next, \"utf8\");\n return true;\n}\n\nasync function backupFile(\n targetPath: string,\n originalContent: string,\n homeDir: string,\n manifest: RollbackManifest,\n): Promise<void> {\n if (manifest.entries.some((entry) => entry.targetPath === targetPath && entry.backupPath)) {\n return;\n }\n const digest = createHash(\"sha256\").update(targetPath).digest(\"hex\").slice(0, 12);\n const backupPath = path.join(backupRoot(homeDir), \"mcp\", `${digest}.json`);\n await ensureParent(backupPath);\n await writeFile(backupPath, originalContent, \"utf8\");\n manifest.entries.push({ targetPath, backupPath });\n}\n\nasync function recordCreatedPath(filePath: string, manifest: RollbackManifest): Promise<void> {\n if (manifest.entries.some((entry) => entry.targetPath === filePath)) return;\n manifest.entries.push({ targetPath: filePath, createdByMigration: true });\n}\n\nfunction defaultConnectorConfigPaths(homeDir: string, cwd: string): string[] {\n return [\n path.join(homeDir, \".claude.json\"),\n path.join(homeDir, \".claude\", \".mcp.json\"),\n path.join(cwd, \"packages\", \"plugin-claude-code\", \".mcp.json\"),\n path.join(cwd, \"packages\", \"plugin-codex\", \".mcp.json\"),\n ];\n}\n\nasync function updateConnectorConfigs(\n homeDir: string,\n cwd: string,\n options: MigrationOptions | undefined,\n manifest: RollbackManifest,\n): Promise<string[]> {\n const updated: string[] = [];\n const candidates = options?.connectorConfigPaths ?? defaultConnectorConfigPaths(homeDir, cwd);\n for (const targetPath of candidates) {\n if (await rewriteJsonFile(targetPath, homeDir, manifest)) {\n updated.push(targetPath);\n }\n }\n return updated;\n}\n\nasync function copyLegacyConfig(homeDir: string, copied: string[]): Promise<void> {\n const source = legacyConfigPath(homeDir);\n const destination = remnicConfigPath(homeDir);\n if (!existsSync(source) || existsSync(destination)) return;\n await ensureParent(destination);\n const original = await readFile(source, \"utf8\");\n let next = rewriteRemnicText(original);\n try {\n const parsed = JSON.parse(next) as Record<string, unknown>;\n if (parsed.engram && !parsed.remnic) {\n parsed.remnic = parsed.engram;\n delete parsed.engram;\n next = JSON.stringify(parsed, null, 2);\n }\n } catch {\n // Keep rewritten text when config is not JSON.\n }\n await writeFile(destination, `${next.trimEnd()}\\n`, \"utf8\");\n copied.push(destination);\n}\n\nfunction rewriteServiceText(content: string): string {\n return rewriteRemnicText(content);\n}\n\nasync function migrateServices(\n homeDir: string,\n options: MigrationOptions | undefined,\n manifest: RollbackManifest,\n): Promise<string[]> {\n const logger = resolveLogger(options);\n const exec = resolveExec(options);\n const servicesReinstalled: string[] = [];\n const platform = resolvePlatform(options);\n\n if (platform === \"darwin\") {\n const legacyPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.engram.daemon.plist\");\n const remnicPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.remnic.daemon.plist\");\n if (existsSync(legacyPlist) && !existsSync(remnicPlist)) {\n const next = rewriteServiceText(await readFile(legacyPlist, \"utf8\"));\n await ensureParent(remnicPlist);\n await writeFile(remnicPlist, next, \"utf8\");\n await recordCreatedPath(remnicPlist, manifest);\n try {\n exec(\"launchctl\", [\"unload\", legacyPlist]);\n } catch {\n // Keep migration fail-open when launchd rejects unload.\n }\n try {\n exec(\"launchctl\", [\"load\", \"-w\", remnicPlist]);\n } catch {\n // Keep migration fail-open when launchd rejects load.\n }\n servicesReinstalled.push(\"ai.remnic.daemon\");\n logger(\"launchd: ai.engram.daemon unloaded, ai.remnic.daemon installed\");\n }\n return servicesReinstalled;\n }\n\n if (platform === \"linux\") {\n const legacyUnit = path.join(homeDir, \".config\", \"systemd\", \"user\", \"engram.service\");\n const remnicUnit = path.join(homeDir, \".config\", \"systemd\", \"user\", \"remnic.service\");\n if (existsSync(legacyUnit) && !existsSync(remnicUnit)) {\n const next = rewriteServiceText(await readFile(legacyUnit, \"utf8\"));\n await ensureParent(remnicUnit);\n await writeFile(remnicUnit, next, \"utf8\");\n await recordCreatedPath(remnicUnit, manifest);\n try {\n exec(\"systemctl\", [\"--user\", \"stop\", \"engram.service\"]);\n exec(\"systemctl\", [\"--user\", \"disable\", \"engram.service\"]);\n exec(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n exec(\"systemctl\", [\"--user\", \"enable\", \"remnic.service\"]);\n exec(\"systemctl\", [\"--user\", \"start\", \"remnic.service\"]);\n } catch {\n // Keep migration fail-open when systemd is unavailable.\n }\n servicesReinstalled.push(\"remnic.service\");\n logger(\"systemd: engram.service disabled, remnic.service installed\");\n }\n }\n\n return servicesReinstalled;\n}\n\nasync function writeRollbackManifest(homeDir: string, manifest: RollbackManifest): Promise<void> {\n await ensureParent(rollbackManifestPath(homeDir));\n await writeFile(\n rollbackManifestPath(homeDir),\n `${JSON.stringify(manifest, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nasync function readRollbackManifest(homeDir: string): Promise<RollbackManifest | null> {\n const target = rollbackManifestPath(homeDir);\n if (!existsSync(target)) return null;\n try {\n return JSON.parse(await readFile(target, \"utf8\")) as RollbackManifest;\n } catch {\n return null;\n }\n}\n\nasync function acquireLock(homeDir: string): Promise<() => Promise<void>> {\n const target = lockPath(homeDir);\n await mkdir(remnicRoot(homeDir), { recursive: true });\n const started = Date.now();\n\n while (true) {\n try {\n const handle = await open(target, \"wx\");\n await handle.writeFile(`${process.pid}\\n${Date.now()}\\n`, \"utf8\");\n return async () => {\n try {\n await handle.close();\n } finally {\n await unlink(target).catch(() => undefined);\n }\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") throw error;\n\n const details = await readFile(target, \"utf8\").catch(() => \"\");\n const lines = details.split(\"\\n\");\n const pid = Number.parseInt(lines[0] ?? \"\", 10);\n const createdAt = Number.parseInt(lines[1] ?? \"\", 10);\n const malformed = !Number.isFinite(pid) || !Number.isFinite(createdAt);\n const stale = Number.isFinite(createdAt) && Date.now() - createdAt > LOCK_STALE_MS;\n const deadPid = Number.isFinite(pid) && pid > 0 ? !processIsAlive(pid) : false;\n if (malformed || stale || deadPid) {\n await rm(target, { force: true }).catch(() => undefined);\n continue;\n }\n if (Date.now() - started > LOCK_TIMEOUT_MS) {\n throw new Error(`timed out waiting for migration lock: ${target}`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));\n }\n }\n}\n\nfunction processIsAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function rollbackFromEngramMigration(options?: MigrationOptions): Promise<RollbackResult> {\n const homeDir = resolveMigrationHome(options);\n const manifest = await readRollbackManifest(homeDir);\n const exec = resolveExec(options);\n const platform = resolvePlatform(options);\n const restored: string[] = [];\n const removed: string[] = [];\n\n if (!manifest) return { restored, removed };\n\n if (platform === \"darwin\") {\n const remnicPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.remnic.daemon.plist\");\n if (existsSync(remnicPlist)) {\n try {\n exec(\"launchctl\", [\"unload\", remnicPlist]);\n } catch {\n // Ignore launchctl rollback failures.\n }\n }\n } else if (platform === \"linux\") {\n try {\n exec(\"systemctl\", [\"--user\", \"stop\", \"remnic.service\"]);\n exec(\"systemctl\", [\"--user\", \"disable\", \"remnic.service\"]);\n } catch {\n // Ignore systemd rollback failures.\n }\n }\n\n for (const entry of [...manifest.entries].reverse()) {\n if (entry.backupPath && existsSync(entry.backupPath)) {\n await ensureParent(entry.targetPath);\n await copyFile(entry.backupPath, entry.targetPath);\n restored.push(entry.targetPath);\n continue;\n }\n if (entry.createdByMigration && existsSync(entry.targetPath)) {\n await rm(entry.targetPath, { recursive: true, force: true });\n removed.push(entry.targetPath);\n }\n }\n\n if (platform === \"linux\") {\n try {\n exec(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n } catch {\n // Ignore systemd rollback failures after removing unit files.\n }\n }\n\n await rm(markerPath(homeDir), { force: true }).catch(() => undefined);\n await rm(rollbackManifestPath(homeDir), { force: true }).catch(() => undefined);\n return { restored, removed };\n}\n\nexport async function migrateFromEngram(options?: MigrationOptions): Promise<MigrationResult> {\n const homeDir = resolveMigrationHome(options);\n const cwd = options?.cwd ?? process.cwd();\n const logger = resolveLogger(options);\n const copied: string[] = [];\n let tokensRegenerated = 0;\n let servicesReinstalled: string[] = [];\n\n if (existsSync(markerPath(homeDir))) {\n return {\n status: \"already-migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const hasLegacyRoot = existsSync(legacyRoot(homeDir));\n const hasLegacyConfig = existsSync(legacyConfigPath(homeDir));\n if (!hasLegacyRoot && !hasLegacyConfig) {\n return {\n status: \"fresh-install\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const releaseLock = await acquireLock(homeDir);\n try {\n if (existsSync(markerPath(homeDir))) {\n return {\n status: \"already-migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const manifest: RollbackManifest = {\n version: 1,\n createdAt: new Date().toISOString(),\n entries: [],\n };\n\n logger(\"First run after Engram -> Remnic rename. Migrating...\");\n await mkdir(remnicRoot(homeDir), { recursive: true });\n await copyTreeMissing(legacyRoot(homeDir), remnicRoot(homeDir), copied);\n await copyLegacyConfig(homeDir, copied);\n\n const legacyTokens = path.join(legacyRoot(homeDir), \"tokens.json\");\n const remnicTokens = path.join(remnicRoot(homeDir), \"tokens.json\");\n if (copied.includes(remnicTokens)) {\n tokensRegenerated += await rewriteTokensIfPresent(remnicTokens);\n } else {\n tokensRegenerated += await mergeLegacyTokens(\n legacyTokens,\n remnicTokens,\n homeDir,\n manifest,\n true,\n );\n }\n if (existsSync(remnicTokens)) {\n logger(\"tokens copied to ~/.remnic/tokens.json (legacy prefixes rewritten)\");\n }\n\n const updatedConfigs = await updateConnectorConfigs(homeDir, cwd, options, manifest);\n for (const updated of updatedConfigs) {\n logger(`Updated connector config: ${updated}`);\n }\n\n servicesReinstalled = await migrateServices(homeDir, options, manifest);\n await writeRollbackManifest(homeDir, manifest);\n await writeFile(markerPath(homeDir), `${new Date().toISOString()}\\n`, \"utf8\");\n logger(\"Migration complete. Welcome to Remnic.\");\n\n return {\n status: \"migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n } finally {\n await releaseLock();\n }\n}\n","/**\n * Intent-gated recall for active procedure memories (issue #519).\n */\n\nimport type { MemoryFile, PluginConfig } from \"../types.js\";\nimport type { StorageManager } from \"../storage.js\";\nimport { inferIntentFromText, intentCompatibilityScore, isTaskInitiationIntent } from \"../intent.js\";\nimport { isActiveMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\n\nfunction tokenOverlapScore(prompt: string, memoryText: string): number {\n const norm = (s: string) =>\n s\n .toLowerCase()\n .split(/[^a-z0-9]+/)\n .filter((t) => t.length > 2);\n const promptTokens = new Set(norm(prompt));\n const memTokens = new Set(norm(memoryText));\n if (promptTokens.size === 0 || memTokens.size === 0) return 0;\n let inter = 0;\n for (const t of promptTokens) {\n if (memTokens.has(t)) inter++;\n }\n const union = new Set([...promptTokens, ...memTokens]);\n return inter / Math.max(1, union.size);\n}\n\nfunction scoreProcedureForPrompt(\n m: MemoryFile,\n prompt: string,\n queryIntent: ReturnType<typeof inferIntentFromText>,\n): number {\n const memText = `${m.content}\\n${(m.frontmatter.tags ?? []).join(\" \")}`;\n const jaccard = tokenOverlapScore(prompt, memText);\n const memIntent = inferIntentFromText(m.content.slice(0, 2000));\n const intentScore = intentCompatibilityScore(queryIntent, memIntent);\n return jaccard * 0.55 + intentScore * 0.45;\n}\n\n/**\n * Build markdown for the recall pipeline when procedural memory is enabled and\n * the prompt looks like task initiation.\n */\nexport async function buildProcedureRecallSection(\n storage: StorageManager,\n prompt: string,\n config: PluginConfig,\n): Promise<string | null> {\n if (config.procedural?.enabled !== true) return null;\n const trimmed = typeof prompt === \"string\" ? prompt.trim() : \"\";\n if (!trimmed) return null;\n\n const queryIntent = inferIntentFromText(trimmed);\n if (!isTaskInitiationIntent(queryIntent)) return null;\n\n const maxN = Math.min(\n 10,\n Math.max(\n 1,\n typeof config.procedural.recallMaxProcedures === \"number\" &&\n Number.isFinite(config.procedural.recallMaxProcedures)\n ? Math.floor(config.procedural.recallMaxProcedures)\n // Safer-by-default fallback (issue #567 PR 3/5): must match\n // config.ts's canonical default (2). Cursor review on PR #607:\n // divergent fallbacks silently regressed the safer cap whenever\n // the config value was missing or non-finite at this call site.\n : 2,\n ),\n );\n\n const all = await storage.readAllMemories();\n const scored = all\n .filter(\n (m) =>\n m.frontmatter.category === \"procedure\" &&\n isActiveMemoryStatus(m.frontmatter.status),\n )\n .map((m) => ({ m, score: scoreProcedureForPrompt(m, trimmed, queryIntent) }))\n .filter((x) => x.score > 0.04)\n .sort((a, b) => b.score - a.score)\n .slice(0, maxN);\n\n if (scored.length === 0) return null;\n\n const blocks = scored.map(({ m, score }) => {\n const id = m.frontmatter.id;\n const flat = m.content.replace(/\\s+/g, \" \").trim();\n const preview = flat.slice(0, 320);\n const suffix = flat.length > 320 ? \"…\" : \"\";\n return `### ${id} (match ${score.toFixed(2)})\\n\\n${preview}${suffix}`;\n });\n\n return `## Relevant procedures\\n\\n${blocks.join(\"\\n\\n\")}`;\n}\n","import { mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst DAY_SUMMARY_CRON_ID = \"engram-day-summary\";\nconst GOVERNANCE_CRON_ID = \"engram-nightly-governance\";\nconst PROCEDURAL_MINING_CRON_ID = \"engram-procedural-mining\";\nconst CONTRADICTION_SCAN_CRON_ID = \"engram-contradiction-scan\";\nconst PATTERN_REINFORCEMENT_CRON_ID = \"engram-pattern-reinforcement\";\nconst GRAPH_EDGE_DECAY_CRON_ID = \"engram-graph-edge-decay\";\n\ntype CronJobsShape =\n | Array<Record<string, unknown>>\n | {\n jobs: Array<Record<string, unknown>>;\n [key: string]: unknown;\n };\n\nasync function acquireCronJobsLock(jobsPath: string): Promise<() => Promise<void>> {\n const lockPath = `${jobsPath}.lock`;\n const start = Date.now();\n const staleMs = 30_000;\n const timeoutMs = 5_000;\n await mkdir(path.dirname(lockPath), { recursive: true });\n\n while (Date.now() - start < timeoutMs) {\n try {\n await mkdir(lockPath);\n return async () => {\n try {\n await rm(lockPath, { recursive: true, force: true });\n } catch {\n // Lock cleanup should not fail cron registration.\n }\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n try {\n const lockStat = await stat(lockPath);\n if (Date.now() - lockStat.mtimeMs > staleMs) {\n await rm(lockPath, { recursive: true, force: true });\n continue;\n }\n } catch {\n // Lock may have been released between stat/rm attempts.\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n throw new Error(`cron jobs lock acquisition timed out after ${timeoutMs}ms`);\n}\n\nfunction parseCronJobsShape(raw: string): { parsed: CronJobsShape; jobs: Array<Record<string, unknown>> } {\n const parsed = JSON.parse(raw) as CronJobsShape;\n const jobs = Array.isArray(parsed) ? parsed : Array.isArray(parsed.jobs) ? parsed.jobs : null;\n if (!jobs) {\n throw new Error(\"jobs.json has unexpected structure\");\n }\n return { parsed, jobs };\n}\n\nasync function writeCronJobsAtomic(jobsPath: string, value: CronJobsShape): Promise<void> {\n const tempPath = `${jobsPath}.${process.pid}.${Date.now()}.tmp`;\n await writeFile(tempPath, JSON.stringify(value, null, 2) + \"\\n\", \"utf-8\");\n await rename(tempPath, jobsPath);\n}\n\nexport async function ensureCronJob(\n jobsPath: string,\n jobId: string,\n buildJob: () => Record<string, unknown>,\n): Promise<{ created: boolean; jobId: string }> {\n const releaseLock = await acquireCronJobsLock(jobsPath);\n try {\n const raw = await readFile(jobsPath, \"utf-8\");\n const { parsed, jobs } = parseCronJobsShape(raw);\n\n if (jobs.some((job) => job.id === jobId)) {\n return { created: false, jobId };\n }\n\n jobs.push(buildJob());\n const output = Array.isArray(parsed) ? jobs : { ...parsed, jobs };\n await writeCronJobsAtomic(jobsPath, output);\n return { created: true, jobId };\n } finally {\n await releaseLock();\n }\n}\n\nexport async function ensureDaySummaryCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, DAY_SUMMARY_CRON_ID, () => ({\n id: DAY_SUMMARY_CRON_ID,\n agentId,\n name: \"Remnic Day Summary (auto)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: \"47 23 * * *\",\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool engram.day_summary with empty params (it will auto-gather today's facts). If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureNightlyGovernanceCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n recentDays?: number;\n maxMemories?: number;\n batchSize?: number;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const recentDays =\n typeof options.recentDays === \"number\" && Number.isFinite(options.recentDays)\n ? Math.max(1, Math.floor(options.recentDays))\n : 2;\n const maxMemories =\n typeof options.maxMemories === \"number\" && Number.isFinite(options.maxMemories)\n ? Math.max(1, Math.floor(options.maxMemories))\n : 500;\n const batchSize =\n typeof options.batchSize === \"number\" && Number.isFinite(options.batchSize)\n ? Math.max(1, Math.floor(options.batchSize))\n : 100;\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"23 2 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, GOVERNANCE_CRON_ID, () => ({\n id: GOVERNANCE_CRON_ID,\n agentId,\n name: \"Remnic Nightly Governance (batched)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call the tool `engram.memory_governance_run` with params \" +\n `{\"mode\": \"apply\", \"recentDays\": ${recentDays}, \"maxMemories\": ${maxMemories}, \"batchSize\": ${batchSize}}` +\n \". If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureProceduralMiningCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"17 3 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, PROCEDURAL_MINING_CRON_ID, () => ({\n id: PROCEDURAL_MINING_CRON_ID,\n agentId,\n name: \"Remnic Procedural Mining (nightly)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.procedure_mining_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureContradictionScanCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"37 3 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, CONTRADICTION_SCAN_CRON_ID, () => ({\n id: CONTRADICTION_SCAN_CRON_ID,\n agentId,\n name: \"Remnic Contradiction Scan (nightly)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.contradiction_scan_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensurePatternReinforcementCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n /**\n * Cron expression. Default `\"53 4 * * 0\"` — Sunday 04:53 in the\n * configured timezone, deliberately offset from sibling crons\n * (`23 2 * * *`, `17 3 * * *`, `37 3 * * *`) so the maintenance\n * passes don't pile up on the same minute.\n */\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"53 4 * * 0\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, PATTERN_REINFORCEMENT_CRON_ID, () => ({\n id: PATTERN_REINFORCEMENT_CRON_ID,\n agentId,\n name: \"Remnic Pattern Reinforcement (weekly)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.pattern_reinforcement_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\n/**\n * Register a cron job that runs the graph-edge-decay maintenance pass\n * (issue #681 PR 2/3). Default schedule is weekly on Sunday 04:13 — the\n * cadence is configurable via `scheduleExpr`. Cadence is also expressible\n * in milliseconds via `Config.graphEdgeDecayCadenceMs`; the orchestrator\n * picks the right cron expression for sub-daily, daily, or weekly cadence.\n */\nexport async function ensureGraphEdgeDecayCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"13 4 * * 0\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n const scheduleLabel = graphEdgeDecayScheduleLabel(scheduleExpr);\n\n return ensureCronJob(jobsPath, GRAPH_EDGE_DECAY_CRON_ID, () => ({\n id: GRAPH_EDGE_DECAY_CRON_ID,\n agentId,\n // Schedule label reflects the actual cron expression (`daily` /\n // `weekly` / `custom`) so cron dashboards do not show \"weekly\"\n // when the schedule is in fact daily — Cursor review on PR #729.\n name: `Remnic Graph Edge Decay (${scheduleLabel})`,\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.graph_edge_decay_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\n/**\n * Pick a cron expression that approximates a cadence in milliseconds.\n *\n * - cadence < 7 days → daily at 04:13 (sub-daily cadence is not natively\n * expressible in 5-field cron without `*\\/N` patterns; daily is the\n * safe upper bound that won't trip the cron more often than requested).\n * - cadence ≥ 7 days → weekly on Sunday 04:13.\n *\n * Operators who need finer-grained control should set `scheduleExpr`\n * directly via `ensureGraphEdgeDecayCron`.\n */\nexport function graphEdgeDecayCadenceToCronExpr(cadenceMs: number): string {\n if (!Number.isFinite(cadenceMs) || cadenceMs <= 0) {\n return \"13 4 * * 0\";\n }\n const day = 24 * 60 * 60 * 1000;\n if (cadenceMs < 7 * day) return \"13 4 * * *\";\n return \"13 4 * * 0\";\n}\n\n/**\n * Derive a human-friendly schedule label (\"daily\" / \"weekly\" / \"custom\")\n * for the given cron expression. Used to keep the cron job name in\n * sync with the actual schedule (Cursor review on PR #729).\n */\nfunction graphEdgeDecayScheduleLabel(scheduleExpr: string): string {\n if (scheduleExpr === \"13 4 * * *\") return \"daily\";\n if (scheduleExpr === \"13 4 * * 0\") return \"weekly\";\n return \"custom\";\n}\n","/**\n * Pattern-reinforcement maintenance job (issue #687 PR 2/4).\n *\n * Reads all memories via `StorageManager.readAllMemories()`, clusters\n * non-procedural memories by normalized content, and reinforces the\n * most-recent member of each large-enough cluster:\n *\n * 1. Cluster across active AND already-superseded members. This is\n * load-bearing: after the first reinforcement pass, older\n * duplicates are marked `superseded`, so on the next pass the\n * \"active count\" alone would be just `canonical + N-new`. By\n * keeping superseded members in the cluster for the threshold\n * check, an established canonical (count >= minCount) keeps\n * growing as soon as a single new duplicate arrives.\n * `forgotten` / `archived` / `quarantined` / `pending_review` /\n * `rejected` stay excluded per CLAUDE.md rule 53.\n * 2. Pick the most-recent ACTIVE member of each cluster as the\n * canonical. Stamp it with `reinforcement_count` (total cluster\n * size including superseded members) and `last_reinforced_at`.\n * Record provenance: `derived_from = [...source-ids...]` and\n * `derived_via = \"pattern-reinforcement\"`.\n * 3. Mark any still-active duplicates with `status: \"superseded\"`\n * and point `supersededBy` at the canonical id.\n *\n * The job is idempotent: re-running on the same corpus does not\n * double-bump `reinforcement_count` (the bump-only-on-change guard\n * compares cluster size to the canonical's previous counter), and\n * already-superseded duplicates simply pass through.\n *\n * Recall integration (boost from `reinforcement_count`) and the CLI\n * surface ship in PR 3/4 and PR 4/4 respectively — this PR only wires\n * the maintenance job and storage plumbing.\n */\n\nimport { clusterByKey } from \"../procedural/reinforcement-core.js\";\nimport type {\n MemoryFile,\n MemoryFrontmatter,\n MemoryStatus,\n} from \"../types.js\";\n\n/**\n * Storage surface the job needs. Defined as a structural interface so\n * tests can pass an in-memory stub without booting a full\n * `StorageManager` (mirrors the pattern in `forget.ts`).\n */\nexport interface PatternReinforcementStorage {\n readAllMemories(): Promise<MemoryFile[]>;\n writeMemoryFrontmatter(\n memory: MemoryFile,\n patch: Partial<MemoryFrontmatter>,\n ): Promise<boolean>;\n}\n\nexport interface PatternReinforcementOptions {\n /** Categories the job considers (e.g. [\"preference\", \"fact\", \"decision\"]). */\n categories: readonly string[];\n /** Minimum cluster size required to promote a canonical. */\n minCount: number;\n /** ISO 8601 timestamp source. Defaults to `Date.now()`. */\n now?: () => Date;\n}\n\nexport interface PatternReinforcementClusterResult {\n /** Memory id of the canonical (most-recent) member. */\n canonicalId: string;\n /** Cluster size at run time (mirrors `reinforcement_count`). */\n count: number;\n /** IDs of the source memories that contributed (canonical + duplicates). */\n sourceIds: readonly string[];\n /** IDs of the older duplicates that were marked superseded. */\n supersededIds: readonly string[];\n /**\n * `true` when the canonical's `reinforcement_count` actually\n * changed during this run. False when the job converged\n * idempotently (same cluster size as the previous run).\n */\n reinforcementBumped: boolean;\n}\n\nexport interface PatternReinforcementResult {\n /** Number of clusters that met the `minCount` threshold. */\n clustersFound: number;\n /** Number of canonical memories whose reinforcement counter changed. */\n canonicalsUpdated: number;\n /** Total duplicate memories newly marked `status: \"superseded\"`. */\n duplicatesSuperseded: number;\n /** Per-cluster details for tests / observability. */\n clusters: PatternReinforcementClusterResult[];\n}\n\n/**\n * Cluster key derivation: lowercase + collapse whitespace + truncate to\n * 200 chars. Pure helper so callers and tests can compute the same key\n * without re-implementing the rule.\n *\n * Truncation is intentional — long-form content with a stable opening\n * still clusters together even when the tail differs slightly. 200\n * chars matches the spec.\n *\n * @deprecated Prefer `patternReinforcementClusterKey(category, content)`\n * which partitions by memory category so identical text in different\n * categories does not get cross-superseded (PR #730 review feedback,\n * Codex P2). This bare helper is kept exported for backward\n * compatibility with callers that already partition by category\n * upstream.\n */\nexport function patternReinforcementKey(content: string): string {\n return content.trim().toLowerCase().replace(/\\s+/g, \" \").slice(0, 200);\n}\n\n/**\n * Cluster key derivation that includes the memory category as a prefix\n * so identical text under different categories (e.g. `fact` and\n * `decision`) does not collapse into one cluster. Without this,\n * pattern reinforcement would silently supersede a fact when a\n * decision happens to share the same canonical text — distorting\n * downstream category-scoped retrieval and governance behavior (PR\n * #730 review feedback, Codex P2).\n */\nexport function patternReinforcementClusterKey(category: string, content: string): string {\n // Use a `::` separator that cannot appear in either component so\n // a category like `fact` plus content starting with `decision:...`\n // cannot collide with category `decision`.\n return `${category}::${patternReinforcementKey(content)}`;\n}\n\n/**\n * Compare two memories by their effective timestamp.\n *\n * Parses each timestamp to an *instant* (epoch ms) via `Date.parse`\n * rather than lexicographic `localeCompare` so ISO-8601 variants with\n * non-`Z` offsets (e.g. `2026-04-26T10:00:00+02:00`) and mixed\n * millisecond precision compare by actual time rather than by raw\n * string (PR #730 review feedback, Codex P2). Imported / hand-edited\n * memory files routinely use such variants.\n *\n * Falls back to the raw string when an instant is unparseable (a\n * corrupt frontmatter is rare but possible) and tie-breaks on memory\n * id for stable ordering.\n */\nfunction pickCanonical(memories: MemoryFile[]): MemoryFile {\n let best = memories[0];\n let bestInstant = memoryInstant(best);\n let bestStamp = memoryStamp(best);\n for (let i = 1; i < memories.length; i += 1) {\n const candidate = memories[i];\n const instant = memoryInstant(candidate);\n const stamp = memoryStamp(candidate);\n let cmp: number;\n if (instant !== null && bestInstant !== null) {\n cmp = instant - bestInstant;\n } else {\n // One side is unparseable — fall back to lexicographic compare\n // on raw strings. This keeps ordering deterministic even when\n // a corrupt timestamp slipped past the parser.\n cmp = stamp.localeCompare(bestStamp);\n }\n if (cmp > 0 || (cmp === 0 && candidate.frontmatter.id > best.frontmatter.id)) {\n best = candidate;\n bestInstant = instant;\n bestStamp = stamp;\n }\n }\n return best;\n}\n\nfunction memoryStamp(memory: MemoryFile): string {\n // Prefer `updated`, fall back to `created`. Both are ISO-8601 and\n // present on every well-formed memory; the parser default-fills them\n // when absent.\n return memory.frontmatter.updated || memory.frontmatter.created || \"\";\n}\n\n/**\n * Parse a memory's effective timestamp to epoch milliseconds. Returns\n * `null` for an unparseable / empty stamp so callers can fall back to\n * a string compare without observing `NaN` propagation.\n */\nfunction memoryInstant(memory: MemoryFile): number | null {\n const stamp = memoryStamp(memory);\n if (stamp.length === 0) return null;\n const parsed = Date.parse(stamp);\n return Number.isFinite(parsed) ? parsed : null;\n}\n\nconst ACTIVE_STATUS: MemoryStatus = \"active\";\n\n/**\n * Run pattern reinforcement across the configured categories.\n *\n * The function is intentionally pure (modulo the storage handle): no\n * cron scheduling, no telemetry side effects, no logging. Callers\n * (orchestrator cron path / CLI surface in PR 4) own those concerns.\n */\nexport async function runPatternReinforcement(\n storage: PatternReinforcementStorage,\n options: PatternReinforcementOptions,\n): Promise<PatternReinforcementResult> {\n const minCount = Math.max(2, Math.floor(options.minCount));\n const targetCategories = new Set(options.categories);\n const now = options.now ?? (() => new Date());\n const nowIso = now().toISOString();\n\n // No-op fast paths so unconfigured callers get a clean result rather\n // than walking the entire corpus.\n if (targetCategories.size === 0) {\n return emptyResult();\n }\n\n const memories = await storage.readAllMemories();\n\n // Cluster across BOTH active and already-superseded memories so a\n // canonical that has previously absorbed duplicates still gets\n // reinforced when a single new duplicate arrives (Codex P1).\n // Without this, the post-first-pass active set is just\n // `canonical + N-new`, which falls below `minCount` for any\n // realistic cadence. CLAUDE.md rule 53 still applies — forgotten,\n // archived, quarantined, pending_review, and rejected memories\n // remain excluded.\n const eligible = memories.filter((m) => {\n if (!targetCategories.has(m.frontmatter.category)) return false;\n const status = m.frontmatter.status ?? ACTIVE_STATUS;\n return status === ACTIVE_STATUS || status === \"superseded\";\n });\n\n if (eligible.length === 0) return emptyResult();\n\n // Cluster by `<category> <content>` so identical text in different\n // categories does not get cross-superseded (PR #730 review feedback,\n // Codex P2).\n const clusters = clusterByKey(eligible, (m) =>\n patternReinforcementClusterKey(m.frontmatter.category, m.content),\n );\n\n const result: PatternReinforcementResult = {\n clustersFound: 0,\n canonicalsUpdated: 0,\n duplicatesSuperseded: 0,\n clusters: [],\n };\n\n for (const cluster of clusters.values()) {\n // The cluster represents the full historical pattern — its size\n // is the threshold the user configured against.\n if (cluster.length < minCount) continue;\n\n // Active members are the only ones we can write to (or pick as\n // canonical). If every member is already superseded — e.g. a\n // prior canonical was archived externally — there's nothing to\n // do for this cluster on this pass.\n const activeMembers = cluster.filter((m) => {\n const status = m.frontmatter.status ?? ACTIVE_STATUS;\n return status === ACTIVE_STATUS;\n });\n if (activeMembers.length === 0) continue;\n\n result.clustersFound += 1;\n\n const canonical = pickCanonical(activeMembers);\n const activeDuplicates = activeMembers.filter((m) => m !== canonical);\n\n // Source-id provenance: include the canonical + every member\n // that contributed to the cluster (active and superseded), so\n // the lineage is fully reconstructible. Sort ids\n // deterministically (CLAUDE.md rule 38) so re-runs produce\n // stable on-disk output.\n const sourceIds = [...cluster]\n .map((m) => m.frontmatter.id)\n .filter((id): id is string => typeof id === \"string\" && id.length > 0)\n .sort();\n\n // Use `sourceIds.length` (the filtered, valid-ID set) as the\n // canonical cluster count for both the reinforcement bump guard\n // and the on-disk `reinforcement_count` field. Using the raw\n // `cluster.length` would inflate the metric whenever any member\n // lacks a valid string ID, causing telemetry to diverge from\n // what is actually being reinforced (PR #730 review, Cursor).\n const previousCount = canonical.frontmatter.reinforcement_count ?? 0;\n const newCount = sourceIds.length;\n const reinforcementBumped = newCount > previousCount;\n\n // Refresh provenance on the canonical whenever cluster membership\n // changes — even if the cluster size happens to stay constant\n // (e.g. one older member archived externally while a new\n // duplicate arrived). Without this, `derived_from` would\n // silently fall out of sync with the actual contributors and\n // diagnostics would surface false-positive \"missing source\"\n // signals (PR #730 review feedback, Codex P2).\n const previousDerivedFrom = Array.isArray(canonical.frontmatter.derived_from)\n ? [...canonical.frontmatter.derived_from].sort()\n : [];\n const sortedSourceIds = [...sourceIds].sort();\n const membershipChanged =\n previousDerivedFrom.length !== sortedSourceIds.length ||\n previousDerivedFrom.some((id, i) => id !== sortedSourceIds[i]);\n const previousVia = canonical.frontmatter.derived_via;\n const viaChanged = previousVia !== \"pattern-reinforcement\";\n const canonicalNeedsRefresh =\n reinforcementBumped || membershipChanged || viaChanged;\n\n // Patch the canonical when the cluster grew, the cluster\n // membership rotated, or the canonical was previously stamped by\n // a different operator. Idempotent re-runs on a stable corpus\n // (same size, same members, same operator) still produce zero\n // writes.\n //\n // On a provenance-only refresh (membership rotated but count\n // unchanged), preserve the existing `reinforcement_count` and\n // `last_reinforced_at` so they remain monotonic and only advance\n // on genuine reinforcement events (PR #730 review, Codex P2).\n if (canonicalNeedsRefresh) {\n const patch: Partial<MemoryFrontmatter> = {\n derived_from: sourceIds,\n derived_via: \"pattern-reinforcement\",\n updated: nowIso,\n };\n if (reinforcementBumped) {\n patch.reinforcement_count = newCount;\n patch.last_reinforced_at = nowIso;\n } else {\n // Carry forward the existing values so a provenance-only\n // refresh does not reset or re-timestamp the counter.\n patch.reinforcement_count =\n canonical.frontmatter.reinforcement_count ?? newCount;\n patch.last_reinforced_at =\n canonical.frontmatter.last_reinforced_at ?? nowIso;\n }\n await storage.writeMemoryFrontmatter(canonical, patch);\n result.canonicalsUpdated += 1;\n }\n\n // Supersede any still-active duplicates. Already-superseded\n // members were filtered out above, which doubles as our\n // crash-recovery guard: a previous run that died mid-supersede\n // simply re-runs the active half on the next pass.\n const supersededIds: string[] = [];\n for (const dup of activeDuplicates) {\n const patch: Partial<MemoryFrontmatter> = {\n status: \"superseded\",\n supersededBy: canonical.frontmatter.id,\n supersededAt: nowIso,\n updated: nowIso,\n };\n await storage.writeMemoryFrontmatter(dup, patch);\n supersededIds.push(dup.frontmatter.id);\n result.duplicatesSuperseded += 1;\n }\n\n result.clusters.push({\n canonicalId: canonical.frontmatter.id,\n count: newCount,\n sourceIds,\n supersededIds,\n reinforcementBumped,\n });\n }\n\n return result;\n}\n\nfunction emptyResult(): PatternReinforcementResult {\n return {\n clustersFound: 0,\n canonicalsUpdated: 0,\n duplicatesSuperseded: 0,\n clusters: [],\n };\n}\n","/**\n * @remnic/core — Write-time semantic dedup guard\n *\n * Complements the exact content-hash check in the orchestrator's write path\n * by detecting near-duplicate candidate facts via embedding cosine similarity.\n *\n * The module intentionally has no dependency on the EmbeddingFallback or QMD\n * classes directly — callers pass in a `lookup` function that returns the\n * top-K nearest neighbors with their cosine scores. This keeps the decision\n * logic pure and trivially testable with synthetic fixtures, and lets the\n * orchestrator reuse whichever backend it already has wired up.\n *\n * Related issue: joshuaswarren/remnic#373\n */\n\n// ── Public types ──────────────────────────────────────────────────────────────\n\n/** A single nearest-neighbor hit from the embedding backend. */\nexport interface SemanticDedupHit {\n /** Memory id of the existing neighbor. */\n id: string;\n /** Cosine similarity score in [0, 1]. */\n score: number;\n /** Optional source path, purely informational. */\n path?: string;\n}\n\n/**\n * Lookup function passed by the caller. Must return an array of hits sorted\n * descending by score. Implementations should return an empty array (never\n * throw) when the embedding backend is unavailable — the decision function\n * treats that as \"no near duplicate\" (fail-open).\n */\nexport type SemanticDedupLookup = (\n content: string,\n limit: number,\n) => Promise<SemanticDedupHit[]>;\n\nexport interface SemanticDedupOptions {\n /** Master switch. When false, `decideSemanticDedup` always returns `keep`. */\n enabled: boolean;\n /** Cosine similarity threshold (0-1). ≥ threshold ⇒ treat as duplicate. */\n threshold: number;\n /** How many nearest neighbors to compare against. */\n candidates: number;\n}\n\nexport type SemanticDedupDecision =\n | {\n action: \"keep\";\n reason:\n | \"disabled\"\n | \"backend_unavailable\"\n | \"no_candidates\"\n | \"no_near_duplicate\";\n topScore?: number;\n topId?: string;\n }\n | {\n action: \"skip\";\n reason: \"near_duplicate\";\n topScore: number;\n topId: string;\n topPath?: string;\n };\n\n// ── Pure decision function ────────────────────────────────────────────────────\n\n/**\n * Pure decision function: given a lookup callback and options, decide whether\n * the candidate content should be written or skipped as a near-duplicate.\n *\n * Contract:\n * - When `options.enabled` is false → always keep, reason=\"disabled\".\n * - When the lookup throws (provider down / network error) → keep,\n * reason=\"backend_unavailable\". Fail-open: a lookup failure must not block\n * writes.\n * - When the lookup succeeds but returns 0 hits (empty index or no\n * neighbors above the score floor) → keep, reason=\"no_candidates\".\n * This is distinct from backend_unavailable so telemetry dashboards can\n * correctly distinguish \"provider is down\" from \"index is empty\".\n * - When the top hit's score ≥ threshold → skip with reason=\"near_duplicate\".\n * - Otherwise → keep with reason=\"no_near_duplicate\".\n */\nexport async function decideSemanticDedup(\n content: string,\n lookup: SemanticDedupLookup,\n options: SemanticDedupOptions,\n): Promise<SemanticDedupDecision> {\n if (!options.enabled) {\n return { action: \"keep\", reason: \"disabled\" };\n }\n // Zero candidates means the operator has disabled the embedding lookup.\n // Treat it identically to enabled=false so no backend call is made.\n if (options.candidates === 0) {\n return { action: \"keep\", reason: \"disabled\" };\n }\n const trimmed = typeof content === \"string\" ? content.trim() : \"\";\n if (!trimmed) {\n return { action: \"keep\", reason: \"no_near_duplicate\" };\n }\n const candidates = Math.max(1, Math.floor(options.candidates));\n let hits: SemanticDedupHit[] = [];\n try {\n hits = await lookup(trimmed, candidates);\n } catch {\n // Fail-open: a lookup error must not block writes.\n return { action: \"keep\", reason: \"backend_unavailable\" };\n }\n if (!Array.isArray(hits) || hits.length === 0) {\n // Provider responded (no throw) but returned no hits: the embedding index\n // is empty or contains no neighbors above the score floor. Use a distinct\n // reason so callers and telemetry can differentiate this from a genuine\n // backend failure.\n return { action: \"keep\", reason: \"no_candidates\" };\n }\n\n // Defensive: callers ought to return sorted, but don't trust it.\n let top: SemanticDedupHit | undefined;\n for (const hit of hits) {\n if (!hit || typeof hit.score !== \"number\" || !Number.isFinite(hit.score)) {\n continue;\n }\n if (!top || hit.score > top.score) {\n top = hit;\n }\n }\n if (!top) {\n return { action: \"keep\", reason: \"no_near_duplicate\" };\n }\n\n if (top.score >= options.threshold) {\n return {\n action: \"skip\",\n reason: \"near_duplicate\",\n topScore: top.score,\n topId: top.id,\n topPath: top.path,\n };\n }\n\n return {\n action: \"keep\",\n reason: \"no_near_duplicate\",\n topScore: top.score,\n topId: top.id,\n };\n}\n","/**\n * Default MECE taxonomy that maps every existing MemoryCategory value\n * to exactly one taxonomy category, ordered by priority.\n */\n\nimport type { Taxonomy } from \"./types.js\";\n\nexport const DEFAULT_TAXONOMY: Taxonomy = {\n version: 1,\n categories: [\n {\n id: \"corrections\",\n name: \"Corrections\",\n description: \"Corrections to previously stored information\",\n filingRules: [\"Any update that supersedes a prior fact\"],\n priority: 10,\n memoryCategories: [\"correction\"],\n },\n {\n id: \"principles\",\n name: \"Principles\",\n description: \"Rules, guidelines, and recurring patterns\",\n filingRules: [\"A guiding principle, rule, or skill\"],\n priority: 20,\n memoryCategories: [\"principle\", \"rule\", \"skill\"],\n },\n {\n id: \"procedures\",\n name: \"Procedures\",\n description: \"Ordered multi-step workflows the user repeats\",\n filingRules: [\"A repeatable sequence of steps or commands for a task\"],\n priority: 25,\n memoryCategories: [\"procedure\"],\n },\n {\n id: \"entities\",\n name: \"Entities\",\n description: \"People, organizations, places, projects\",\n filingRules: [\"Named entity with attributes\"],\n priority: 30,\n memoryCategories: [\"entity\", \"relationship\"],\n },\n {\n id: \"decisions\",\n name: \"Decisions\",\n description: \"Choices made and their rationale\",\n filingRules: [\"A decision or commitment with reasoning\"],\n priority: 35,\n memoryCategories: [\"decision\", \"commitment\"],\n },\n {\n id: \"preferences\",\n name: \"Preferences\",\n description: \"User likes, dislikes, and style choices\",\n filingRules: [\"Anything expressing a preference or taste\"],\n priority: 40,\n memoryCategories: [\"preference\"],\n },\n {\n id: \"facts\",\n name: \"Facts\",\n description: \"Objective statements about the world\",\n filingRules: [\"Any factual claim or piece of information\"],\n priority: 50,\n memoryCategories: [\"fact\"],\n },\n {\n id: \"moments\",\n name: \"Moments\",\n description: \"Significant events or experiences\",\n filingRules: [\"A specific event worth remembering\"],\n priority: 60,\n memoryCategories: [\"moment\"],\n },\n {\n id: \"reasoning-traces\",\n name: \"Reasoning Traces\",\n description:\n \"Stored intermediate reasoning / solution chains for a problem the agent previously solved\",\n filingRules: [\n \"A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem\",\n ],\n priority: 55,\n memoryCategories: [\"reasoning_trace\"],\n },\n ],\n};\n","/**\n * Generates a markdown decision-tree document (RESOLVER.md) from a\n * taxonomy definition.\n *\n * The document walks a user through filing a new piece of knowledge\n * by checking each category in priority order (lowest number first).\n */\n\nimport type { Taxonomy } from \"./types.js\";\n\n/**\n * Produce a markdown decision tree for the given taxonomy.\n *\n * Categories are listed in priority order (lowest number = checked first).\n * Each step asks whether the knowledge fits the category and, if so,\n * instructs the reader to file it there.\n */\nexport function generateResolverDocument(taxonomy: Taxonomy): string {\n const sorted = [...taxonomy.categories].sort((a, b) => {\n if (a.priority !== b.priority) return a.priority - b.priority;\n return a.id.localeCompare(b.id);\n });\n\n const lines: string[] = [\n \"# Memory Filing Resolver\",\n \"\",\n \"Given a new piece of knowledge, follow this tree to determine where it belongs.\",\n \"\",\n ];\n\n let step = 1;\n for (const cat of sorted) {\n lines.push(`## Step ${step}: ${cat.description}?`);\n lines.push(\"\");\n for (const rule of cat.filingRules) {\n lines.push(`- ${rule}`);\n }\n lines.push(\"\");\n lines.push(\n `> YES: File under **${cat.id}/** (priority ${cat.priority})`,\n );\n lines.push(\"\");\n step++;\n }\n\n lines.push(\"## Tie-breaking\");\n lines.push(\"\");\n lines.push(\n \"If a fact could go in multiple categories, file under the one with the **lowest priority number**.\",\n );\n lines.push(\"\");\n lines.push(`---`);\n lines.push(`*Generated from taxonomy v${taxonomy.version}*`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","/**\n * Loads and validates a user-customized taxonomy from disk, merging\n * with the built-in defaults.\n *\n * User taxonomies are stored at `<memoryDir>/.taxonomy/taxonomy.json`.\n */\n\nimport { readFile, mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Taxonomy, TaxonomyCategory } from \"./types.js\";\nimport { DEFAULT_TAXONOMY } from \"./default-taxonomy.js\";\n\nconst TAXONOMY_DIR = \".taxonomy\";\nconst TAXONOMY_FILE = \"taxonomy.json\";\n\n/** Maximum allowed slug length */\nconst MAX_SLUG_LENGTH = 32;\n\n/** Regex for valid slug: lowercase letters, digits, hyphens */\nconst SLUG_RE = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Validate a taxonomy category slug.\n * Throws if the slug is invalid.\n */\nexport function validateSlug(slug: string): void {\n if (slug.length === 0) {\n throw new Error(\"Taxonomy category ID must not be empty\");\n }\n if (slug.length > MAX_SLUG_LENGTH) {\n throw new Error(\n `Taxonomy category ID \"${slug}\" exceeds ${MAX_SLUG_LENGTH} characters`,\n );\n }\n if (!SLUG_RE.test(slug)) {\n throw new Error(\n `Taxonomy category ID \"${slug}\" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`,\n );\n }\n}\n\n/**\n * Validate an entire taxonomy for structural correctness.\n * Throws on the first error found.\n */\nexport function validateTaxonomy(taxonomy: Taxonomy): void {\n if (typeof taxonomy.version !== \"number\" || taxonomy.version < 1) {\n throw new Error(\"Taxonomy version must be a positive integer\");\n }\n if (!Array.isArray(taxonomy.categories)) {\n throw new Error(\"Taxonomy categories must be an array\");\n }\n\n const seenIds = new Set<string>();\n for (const cat of taxonomy.categories) {\n validateSlug(cat.id);\n if (seenIds.has(cat.id)) {\n throw new Error(`Duplicate taxonomy category ID: \"${cat.id}\"`);\n }\n seenIds.add(cat.id);\n\n if (typeof cat.name !== \"string\" || cat.name.trim().length === 0) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a non-empty name`);\n }\n if (typeof cat.description !== \"string\" || cat.description.trim().length === 0) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a non-empty description`);\n }\n if (!Array.isArray(cat.filingRules)) {\n throw new Error(`Taxonomy category \"${cat.id}\" filingRules must be an array`);\n }\n if (typeof cat.priority !== \"number\" || !Number.isFinite(cat.priority)) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a finite numeric priority`);\n }\n if (!Array.isArray(cat.memoryCategories)) {\n throw new Error(`Taxonomy category \"${cat.id}\" memoryCategories must be an array`);\n }\n if (cat.parentId !== undefined) {\n if (typeof cat.parentId !== \"string\") {\n throw new Error(`Taxonomy category \"${cat.id}\" parentId must be a string if set`);\n }\n }\n }\n\n // Validate parentId references\n for (const cat of taxonomy.categories) {\n if (cat.parentId !== undefined && !seenIds.has(cat.parentId)) {\n throw new Error(\n `Taxonomy category \"${cat.id}\" references unknown parentId \"${cat.parentId}\"`,\n );\n }\n }\n}\n\n/**\n * Load a taxonomy from the user's memory directory.\n *\n * If `<memoryDir>/.taxonomy/taxonomy.json` exists, loads it, validates\n * it, and merges with the defaults (user categories override defaults\n * by ID). If the file does not exist, returns the defaults.\n */\nexport async function loadTaxonomy(memoryDir: string): Promise<Taxonomy> {\n const taxonomyPath = path.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);\n let raw: string;\n try {\n raw = await readFile(taxonomyPath, \"utf-8\");\n } catch (err: unknown) {\n // Only fall back to defaults for missing file; rethrow permission / I/O errors\n if (err instanceof Error && (err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return structuredClone(DEFAULT_TAXONOMY);\n }\n throw err;\n }\n\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"taxonomy.json must be a JSON object\");\n }\n\n const obj = parsed as Record<string, unknown>;\n const userVersion = typeof obj.version === \"number\" ? obj.version : DEFAULT_TAXONOMY.version;\n const userCategories = Array.isArray(obj.categories)\n ? (obj.categories as TaxonomyCategory[])\n : [];\n\n // Validate: reject duplicate IDs in user categories before merging.\n // Without this check, duplicates are silently collapsed with last-write-wins\n // semantics when inserted into the Map.\n const userIdCounts = new Map<string, number>();\n for (const cat of userCategories) {\n const id = typeof cat.id === \"string\" ? cat.id : String(cat.id);\n userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);\n }\n const duplicateIds = [...userIdCounts.entries()]\n .filter(([, count]) => count > 1)\n .map(([id]) => id);\n if (duplicateIds.length > 0) {\n throw new Error(\n `Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `\"${id}\"`).join(\", \")}`,\n );\n }\n\n // Merge: user categories override defaults by ID\n const mergedMap = new Map<string, TaxonomyCategory>();\n for (const cat of DEFAULT_TAXONOMY.categories) {\n mergedMap.set(cat.id, { ...cat });\n }\n for (const cat of userCategories) {\n mergedMap.set(cat.id, cat);\n }\n\n const merged: Taxonomy = {\n version: userVersion,\n categories: [...mergedMap.values()],\n };\n\n validateTaxonomy(merged);\n return merged;\n}\n\n/**\n * Save a taxonomy to the user's memory directory.\n */\nexport async function saveTaxonomy(\n memoryDir: string,\n taxonomy: Taxonomy,\n): Promise<void> {\n validateTaxonomy(taxonomy);\n const dir = path.join(memoryDir, TAXONOMY_DIR);\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, TAXONOMY_FILE);\n await writeFile(filePath, JSON.stringify(taxonomy, null, 2) + \"\\n\", \"utf-8\");\n}\n\n/**\n * Get the taxonomy directory path for a given memory directory.\n */\nexport function getTaxonomyDir(memoryDir: string): string {\n return path.join(memoryDir, TAXONOMY_DIR);\n}\n\n/**\n * Get the taxonomy file path for a given memory directory.\n */\nexport function getTaxonomyFilePath(memoryDir: string): string {\n return path.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);\n}\n","import path from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport { log } from \"../logger.js\";\nimport {\n openBetterSqlite3,\n type BetterSqlite3Database,\n} from \"../runtime/better-sqlite.js\";\n\nconst LCM_SCHEMA_VERSION = 2;\n\nexport function openLcmDatabase(memoryDir: string): BetterSqlite3Database {\n const dbPath = path.join(memoryDir, \"state\", \"lcm.sqlite\");\n const db = openBetterSqlite3(dbPath);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.pragma(\"synchronous = NORMAL\");\n applySchema(db);\n return db;\n}\n\nexport async function ensureLcmStateDir(memoryDir: string): Promise<void> {\n await mkdir(path.join(memoryDir, \"state\"), { recursive: true });\n}\n\n/**\n * Apply (or upgrade) the LCM schema on an already-open SQLite handle.\n *\n * Exposed so optional host packages — e.g. importers using an in-memory\n * destination database for true read-only `--dry-run` execution — can\n * bootstrap the schema without going through `openLcmDatabase()` (which\n * always touches the filesystem).\n */\nexport function applyLcmSchema(db: BetterSqlite3Database): void {\n applySchema(db);\n}\n\nfunction applySchema(db: BetterSqlite3Database): void {\n const versionRow = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'\")\n .get() as { name: string } | undefined;\n\n if (!versionRow) {\n createTables(db);\n return;\n }\n\n const meta = db\n .prepare(\"SELECT value FROM lcm_meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined;\n const currentVersion = meta ? parseInt(meta.value, 10) : 0;\n\n if (currentVersion < LCM_SCHEMA_VERSION) {\n log.info(`LCM schema upgrade: v${currentVersion} → v${LCM_SCHEMA_VERSION}`);\n createTables(db);\n }\n}\n\nfunction createTables(db: BetterSqlite3Database): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS lcm_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS lcm_messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n turn_index INTEGER NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n metadata TEXT\n );\n CREATE INDEX IF NOT EXISTS idx_lcm_messages_session\n ON lcm_messages(session_id, turn_index);\n\n CREATE TABLE IF NOT EXISTS lcm_message_parts (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n message_id INTEGER NOT NULL REFERENCES lcm_messages(id) ON DELETE CASCADE,\n ordinal INTEGER NOT NULL,\n kind TEXT NOT NULL,\n payload TEXT NOT NULL,\n tool_name TEXT,\n file_path TEXT,\n created_at TEXT NOT NULL\n );\n CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_msg\n ON lcm_message_parts(message_id, ordinal);\n CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_tool\n ON lcm_message_parts(tool_name);\n CREATE INDEX IF NOT EXISTS idx_lcm_message_parts_file\n ON lcm_message_parts(file_path);\n\n CREATE TABLE IF NOT EXISTS lcm_summary_nodes (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n depth INTEGER NOT NULL,\n parent_id TEXT,\n summary_text TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n msg_start INTEGER NOT NULL,\n msg_end INTEGER NOT NULL,\n escalation INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n FOREIGN KEY (parent_id) REFERENCES lcm_summary_nodes(id)\n );\n CREATE INDEX IF NOT EXISTS idx_lcm_summary_session\n ON lcm_summary_nodes(session_id, depth);\n CREATE INDEX IF NOT EXISTS idx_lcm_summary_range\n ON lcm_summary_nodes(session_id, msg_start, msg_end);\n\n CREATE TABLE IF NOT EXISTS lcm_compaction_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n fired_at TEXT NOT NULL,\n msg_before INTEGER NOT NULL,\n tokens_before INTEGER NOT NULL,\n tokens_after INTEGER NOT NULL\n );\n `);\n\n // FTS5 tables — created separately so IF NOT EXISTS works correctly\n const hasFts = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_messages_fts'\")\n .get();\n if (!hasFts) {\n db.exec(`\n CREATE VIRTUAL TABLE lcm_messages_fts USING fts5(\n content,\n content=lcm_messages,\n content_rowid=id\n );\n `);\n }\n\n const hasSummaryFts = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_summaries_fts'\")\n .get();\n if (!hasSummaryFts) {\n db.exec(`\n CREATE VIRTUAL TABLE lcm_summaries_fts USING fts5(\n summary_text,\n content=lcm_summary_nodes,\n content_rowid=rowid\n );\n `);\n }\n\n // Upsert meta version\n db.prepare(\"INSERT OR REPLACE INTO lcm_meta (key, value) VALUES ('schema_version', ?)\").run(\n String(LCM_SCHEMA_VERSION),\n );\n}\n","export type LcmMessagePartKind =\n | \"text\"\n | \"tool_call\"\n | \"tool_result\"\n | \"patch\"\n | \"file_read\"\n | \"file_write\"\n | \"step_start\"\n | \"step_finish\"\n | \"snapshot\"\n | \"retry\";\n\nexport const LCM_MESSAGE_PART_KINDS: readonly LcmMessagePartKind[] = [\n \"text\",\n \"tool_call\",\n \"tool_result\",\n \"patch\",\n \"file_read\",\n \"file_write\",\n \"step_start\",\n \"step_finish\",\n \"snapshot\",\n \"retry\",\n] as const;\n\nexport type MessagePartSourceFormat =\n | \"openai\"\n | \"anthropic\"\n | \"openclaw\"\n | \"lossless-claw\"\n | \"remnic\";\n\nexport interface LcmMessagePartInput {\n ordinal?: number | null;\n kind: LcmMessagePartKind;\n payload: Record<string, unknown>;\n toolName?: string | null;\n tool_name?: string | null;\n filePath?: string | null;\n file_path?: string | null;\n createdAt?: string | null;\n created_at?: string | null;\n}\n\nexport interface LcmMessagePartRow extends LcmMessagePartInput {\n id: number;\n messageId: number;\n ordinal: number;\n payloadJson: string;\n createdAt: string;\n}\n\nexport interface ParseMessagePartsOptions {\n sourceFormat?: MessagePartSourceFormat;\n renderedContent?: string;\n}\n\nconst SECRET_KEY_RE = /(api[_-]?key|authorization|bearer|credential|password|secret|token)/i;\nconst MAX_PAYLOAD_STRING = 8_000;\nconst MAX_FILE_SCAN_CHARS = 20_000;\n\nexport function isLcmMessagePartKind(value: unknown): value is LcmMessagePartKind {\n return (\n typeof value === \"string\" &&\n (LCM_MESSAGE_PART_KINDS as readonly string[]).includes(value)\n );\n}\n\nexport function parseMessageParts(\n input: unknown,\n options: ParseMessagePartsOptions = {},\n): LcmMessagePartInput[] {\n const explicit = normalizeExplicitParts(input);\n if (explicit.length > 0) return explicit;\n\n const format = options.sourceFormat ?? inferSourceFormat(input);\n switch (format) {\n case \"openai\":\n return withRenderedFallback(parseOpenAiMessageParts(input, options), options);\n case \"anthropic\":\n return withRenderedFallback(parseAnthropicMessageParts(input, options), options);\n case \"openclaw\":\n return withRenderedFallback(parseOpenClawMessageParts(input, options), options);\n case \"lossless-claw\":\n case \"remnic\":\n return withRenderedFallback(normalizeExplicitParts(input), options);\n default:\n return renderedFallbackParts(options);\n }\n}\n\nexport function normalizeExplicitParts(input: unknown): LcmMessagePartInput[] {\n const rawParts = pickArray(input, \"parts\") ?? pickArray(input, \"message_parts\");\n if (!rawParts) return [];\n\n const parts: LcmMessagePartInput[] = [];\n rawParts.forEach((raw, index) => {\n if (!raw || typeof raw !== \"object\" || Array.isArray(raw)) return;\n const obj = raw as Record<string, unknown>;\n const kind = normalizeKind(obj.kind ?? obj.type);\n if (!kind) return;\n\n const payload =\n obj.payload && typeof obj.payload === \"object\" && !Array.isArray(obj.payload)\n ? (obj.payload as Record<string, unknown>)\n : { value: sanitizePayload(obj) };\n const toolName = asNonEmptyString(obj.toolName ?? obj.tool_name ?? obj.name);\n const filePath = asNonEmptyString(obj.filePath ?? obj.file_path ?? obj.path);\n const ordinal =\n typeof obj.ordinal === \"number\" && Number.isInteger(obj.ordinal)\n ? Math.max(0, obj.ordinal)\n : index;\n\n parts.push({\n ordinal,\n kind,\n payload: sanitizePayload(payload) as Record<string, unknown>,\n toolName,\n filePath,\n createdAt: asNonEmptyString(obj.createdAt ?? obj.created_at),\n });\n });\n return parts;\n}\n\nexport function parseOpenAiMessageParts(\n input: unknown,\n _options: ParseMessagePartsOptions = {},\n): LcmMessagePartInput[] {\n const items = gatherOpenAiItems(input);\n const parts: LcmMessagePartInput[] = [];\n for (const item of items) {\n const type = asNonEmptyString(item.type) ?? asNonEmptyString(item.kind);\n if (!type) continue;\n if (isOpenAiContentBlock(item)) {\n const text = asNonEmptyString(item.text ?? item.content);\n if (text) parts.push(makePart(\"text\", { type, text }, { filePath: firstFilePath(text) }));\n continue;\n }\n if (type === \"message\") {\n for (const block of gatherContentBlocks(item.content)) {\n const text = asNonEmptyString(block.text ?? block.content);\n if (text) parts.push(makePart(\"text\", { type, text }, { filePath: firstFilePath(text) }));\n }\n continue;\n }\n if (type === \"function_call\") {\n const toolName = asNonEmptyString(item.name ?? item.tool_name);\n const payload = {\n id: item.id ?? item.call_id,\n name: toolName,\n arguments: parseMaybeJson(item.arguments),\n };\n parts.push(classifyToolPart(toolName, payload));\n continue;\n }\n if (type === \"function_call_output\") {\n const output = asNonEmptyString(item.output) ?? JSON.stringify(sanitizePayload(item.output ?? item));\n parts.push(makePart(\"tool_result\", { id: item.id ?? item.call_id, output }, {\n filePath: firstFilePath(output),\n }));\n continue;\n }\n if (type === \"reasoning\") {\n parts.push(makePart(\"step_start\", { type, summary: sanitizePayload(item.summary ?? item) }));\n continue;\n }\n if (type === \"retry\") {\n parts.push(makePart(\"retry\", { type, item: sanitizePayload(item) }));\n }\n }\n return withOrdinals(parts);\n}\n\nexport function parseAnthropicMessageParts(\n input: unknown,\n _options: ParseMessagePartsOptions = {},\n): LcmMessagePartInput[] {\n const blocks = gatherContentBlocks(\n Array.isArray(input) ? input : input && typeof input === \"object\" ? (input as Record<string, unknown>).content : input,\n );\n const parts: LcmMessagePartInput[] = [];\n for (const block of blocks) {\n const type = asNonEmptyString(block.type);\n if (type === \"text\") {\n const text = asNonEmptyString(block.text);\n if (text) parts.push(makePart(\"text\", { type, text }, { filePath: firstFilePath(text) }));\n continue;\n }\n if (type === \"tool_use\") {\n const toolName = asNonEmptyString(block.name);\n parts.push(classifyToolPart(toolName, {\n id: block.id,\n name: toolName,\n input: sanitizePayload(block.input),\n }));\n continue;\n }\n if (type === \"tool_result\") {\n const content = block.content;\n const rendered = renderUnknownContent(content);\n parts.push(makePart(\"tool_result\", { id: block.tool_use_id, content: sanitizePayload(content) }, {\n filePath: firstFilePath(rendered),\n }));\n continue;\n }\n if (type === \"thinking\") {\n parts.push(makePart(\"step_start\", {\n type,\n thinking: truncateString(asNonEmptyString(block.thinking) ?? \"\"),\n signature: asNonEmptyString(block.signature),\n }));\n continue;\n }\n if (type === \"redacted_thinking\") {\n parts.push(makePart(\"step_finish\", { type }));\n }\n }\n return withOrdinals(parts);\n}\n\nexport function parseOpenClawMessageParts(\n input: unknown,\n options: ParseMessagePartsOptions = {},\n): LcmMessagePartInput[] {\n const explicit = normalizeExplicitParts(input);\n if (explicit.length > 0) return explicit;\n if (!input || typeof input !== \"object\") return [];\n const obj = input as Record<string, unknown>;\n\n const content = obj.content;\n if (Array.isArray(content)) {\n const hasOpenAiBlocks = content.some(isOpenAiContentBlock);\n if (hasOpenAiBlocks) return parseOpenAiMessageParts(content, options);\n const hasAnthropicBlocks = content.some(\n (block) =>\n block &&\n typeof block === \"object\" &&\n typeof (block as Record<string, unknown>).type === \"string\",\n );\n if (hasAnthropicBlocks) return parseAnthropicMessageParts({ content }, options);\n }\n\n const toolName = asNonEmptyString(obj.toolName ?? obj.tool_name ?? obj.name);\n if (toolName) {\n return withOrdinals([\n classifyToolPart(toolName, {\n name: toolName,\n input: sanitizePayload(obj.input ?? obj.arguments ?? obj.params),\n output: sanitizePayload(obj.output ?? obj.result),\n }),\n ]);\n }\n\n const rendered = options.renderedContent ?? asNonEmptyString(obj.content);\n return rendered ? withOrdinals(partsFromRenderedText(rendered)) : [];\n}\n\nexport function partsFromRenderedText(text: string): LcmMessagePartInput[] {\n if (text.includes(\"*** Begin Patch\")) {\n const paths = extractFilePaths(text);\n const patchPaths = extractPatchPaths(text);\n return withOrdinals((patchPaths.length > 0 ? patchPaths : paths).map((filePath) =>\n makePart(\"patch\", { text: truncateString(text) }, { filePath })\n ));\n }\n const paths = extractFilePaths(text);\n if (paths.length === 0) return [];\n return withOrdinals(paths.map((filePath) =>\n makePart(\"file_read\", { text: truncateString(text) }, { filePath })\n ));\n}\n\nfunction inferSourceFormat(input: unknown): MessagePartSourceFormat | undefined {\n if (input && typeof input === \"object\") {\n const obj = input as Record<string, unknown>;\n const explicit = asNonEmptyString(obj.sourceFormat ?? obj.source_format);\n if (explicit === \"openai\" || explicit === \"anthropic\" || explicit === \"openclaw\" || explicit === \"lossless-claw\" || explicit === \"remnic\") {\n return explicit;\n }\n if (Array.isArray(obj.output)) return \"openai\";\n if (isOpenAiResponseItem(obj)) return \"openai\";\n if (Array.isArray(obj.content) && obj.content.some(isOpenAiContentBlock)) return \"openai\";\n if (Array.isArray(obj.content)) return \"anthropic\";\n }\n if (Array.isArray(input)) {\n return input.some((item) =>\n isRecord(item) && (isOpenAiResponseItem(item) || isOpenAiContentBlock(item))\n )\n ? \"openai\"\n : \"anthropic\";\n }\n return undefined;\n}\n\nfunction isOpenAiResponseItem(obj: Record<string, unknown>): boolean {\n const type = asNonEmptyString(obj.type ?? obj.kind);\n return (\n type === \"message\" ||\n type === \"function_call\" ||\n type === \"function_call_output\" ||\n type === \"reasoning\" ||\n type === \"retry\"\n );\n}\n\nfunction isOpenAiContentBlock(value: unknown): boolean {\n if (!isRecord(value)) return false;\n const type = asNonEmptyString(value.type);\n return (\n type === \"input_text\" ||\n type === \"output_text\" ||\n type === \"input_image\" ||\n type === \"input_file\" ||\n type === \"refusal\"\n );\n}\n\nfunction gatherOpenAiItems(input: unknown): Record<string, unknown>[] {\n if (Array.isArray(input)) return input.filter(isRecord);\n if (!isRecord(input)) return [];\n if (Array.isArray(input.output)) return input.output.filter(isRecord);\n if (Array.isArray(input.items)) return input.items.filter(isRecord);\n return [input];\n}\n\nfunction gatherContentBlocks(input: unknown): Record<string, unknown>[] {\n if (Array.isArray(input)) return input.filter(isRecord);\n if (typeof input === \"string\") return [{ type: \"text\", text: input }];\n if (isRecord(input)) return [input];\n return [];\n}\n\nfunction classifyToolPart(\n toolName: string | null | undefined,\n payload: Record<string, unknown>,\n): LcmMessagePartInput {\n const normalized = (toolName ?? \"\").toLowerCase();\n const rendered = renderUnknownContent(payload);\n const filePath =\n firstFilePathFromObject(payload) ?? firstFilePath(rendered) ?? null;\n\n if (normalized.includes(\"apply_patch\") || rendered.includes(\"*** Begin Patch\")) {\n return makePart(\"patch\", payload, { toolName, filePath: filePath ?? extractPatchPaths(rendered)[0] ?? null });\n }\n if (/(write|edit|multiedit|create|save)/i.test(normalized)) {\n return makePart(\"file_write\", payload, { toolName, filePath });\n }\n if (/(read|grep|glob|search|list|ls)/i.test(normalized)) {\n return makePart(\"file_read\", payload, { toolName, filePath });\n }\n return makePart(\"tool_call\", payload, { toolName, filePath });\n}\n\nfunction makePart(\n kind: LcmMessagePartKind,\n payload: Record<string, unknown>,\n options: { toolName?: string | null; filePath?: string | null } = {},\n): LcmMessagePartInput {\n return {\n kind,\n payload: sanitizePayload(payload) as Record<string, unknown>,\n toolName: options.toolName ?? null,\n filePath: options.filePath ?? null,\n };\n}\n\nfunction withOrdinals(parts: LcmMessagePartInput[]): LcmMessagePartInput[] {\n return parts.map((part, ordinal) => ({ ...part, ordinal: part.ordinal ?? ordinal }));\n}\n\nfunction withRenderedFallback(\n parts: LcmMessagePartInput[],\n options: ParseMessagePartsOptions,\n): LcmMessagePartInput[] {\n return parts.length > 0 ? parts : renderedFallbackParts(options);\n}\n\nfunction renderedFallbackParts(options: ParseMessagePartsOptions): LcmMessagePartInput[] {\n const rendered = asNonEmptyString(options.renderedContent);\n return rendered ? partsFromRenderedText(rendered) : [];\n}\n\nfunction normalizeKind(value: unknown): LcmMessagePartKind | null {\n if (isLcmMessagePartKind(value)) return value;\n if (value === \"tool_use\" || value === \"function_call\") return \"tool_call\";\n if (value === \"function_call_output\") return \"tool_result\";\n if (value === \"thinking\" || value === \"reasoning\") return \"step_start\";\n return null;\n}\n\nfunction pickArray(input: unknown, key: string): unknown[] | null {\n if (!input || typeof input !== \"object\" || Array.isArray(input)) return null;\n const value = (input as Record<string, unknown>)[key];\n return Array.isArray(value) ? value : null;\n}\n\nfunction asNonEmptyString(value: unknown): string | null {\n if (typeof value !== \"string\") return null;\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : null;\n}\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return !!value && typeof value === \"object\" && !Array.isArray(value);\n}\n\nfunction parseMaybeJson(value: unknown): unknown {\n if (typeof value !== \"string\") return sanitizePayload(value);\n try {\n return sanitizePayload(JSON.parse(value));\n } catch {\n return truncateString(value);\n }\n}\n\nfunction sanitizePayload(value: unknown, depth = 0): unknown {\n if (value === null || value === undefined) return value;\n if (typeof value === \"string\") return truncateString(value);\n if (typeof value === \"number\" || typeof value === \"boolean\") return value;\n if (Array.isArray(value)) {\n if (depth >= 4) return \"[truncated]\";\n return value.slice(0, 100).map((item) => sanitizePayload(item, depth + 1));\n }\n if (typeof value === \"object\") {\n if (depth >= 4) return \"[truncated]\";\n const out: Record<string, unknown> = {};\n for (const [key, child] of Object.entries(value as Record<string, unknown>)) {\n out[key] = SECRET_KEY_RE.test(key) ? \"[redacted]\" : sanitizePayload(child, depth + 1);\n }\n return out;\n }\n return String(value);\n}\n\nfunction truncateString(value: string): string {\n return value.length > MAX_PAYLOAD_STRING\n ? `${value.slice(0, MAX_PAYLOAD_STRING)}...[truncated]`\n : value;\n}\n\nfunction renderUnknownContent(value: unknown): string {\n if (typeof value === \"string\") return value;\n try {\n return JSON.stringify(value ?? \"\");\n } catch {\n return String(value ?? \"\");\n }\n}\n\nfunction firstFilePathFromObject(value: unknown): string | null {\n if (!isRecord(value)) return null;\n const keys = [\"file_path\", \"filePath\", \"path\", \"filename\", \"cwd\"];\n for (const key of keys) {\n const candidate = asNonEmptyString(value[key]);\n if (candidate) return candidate;\n }\n for (const child of Object.values(value)) {\n if (typeof child === \"string\") {\n const fromText = extractPatchPaths(child)[0] ?? firstFilePath(child);\n if (fromText) return fromText;\n }\n if (isRecord(child)) {\n const nested = firstFilePathFromObject(child);\n if (nested) return nested;\n }\n }\n return null;\n}\n\nfunction firstFilePath(text: string): string | null {\n return extractFilePaths(text)[0] ?? null;\n}\n\nfunction extractFilePaths(text: string): string[] {\n const out = new Set<string>();\n let token = \"\";\n const scanLength = Math.min(text.length, MAX_FILE_SCAN_CHARS);\n for (let index = 0; index <= scanLength; index += 1) {\n const char = index < scanLength ? text[index]! : \" \";\n if (isFilePathTokenSeparator(char)) {\n addFilePathCandidate(out, token);\n token = \"\";\n continue;\n }\n token += char;\n if (token.length > 512) {\n addFilePathCandidate(out, token);\n token = \"\";\n }\n }\n return [...out].slice(0, 20);\n}\n\nfunction isFilePathTokenSeparator(char: string): boolean {\n return (\n char === \" \" ||\n char === \"\\n\" ||\n char === \"\\r\" ||\n char === \"\\t\" ||\n char === \"\\\"\" ||\n char === \"'\" ||\n char === \"`\" ||\n char === \"(\" ||\n char === \")\" ||\n char === \"[\" ||\n char === \"]\" ||\n char === \"{\" ||\n char === \"}\" ||\n char === \"<\" ||\n char === \">\" ||\n char === \",\"\n );\n}\n\nfunction addFilePathCandidate(out: Set<string>, raw: string): void {\n const candidate = trimFilePathPunctuation(raw);\n if (candidate.length === 0 || candidate.includes(\"://\")) return;\n if (isLikelyFilePath(candidate)) out.add(candidate);\n}\n\nfunction trimFilePathPunctuation(raw: string): string {\n let start = 0;\n let end = raw.length;\n while (start < end && isLeadingFilePathPunctuation(raw[start]!)) start += 1;\n while (end > start && isTrailingFilePathPunctuation(raw[end - 1]!)) end -= 1;\n return raw.slice(start, end);\n}\n\nfunction isLeadingFilePathPunctuation(char: string): boolean {\n return (\n char === \":\" ||\n char === \";\" ||\n char === \"!\" ||\n char === \"?\" ||\n char === \"|\" ||\n char === \"*\" ||\n char === \"=\"\n );\n}\n\nfunction isTrailingFilePathPunctuation(char: string): boolean {\n return (\n char === \".\" ||\n char === \":\" ||\n char === \";\" ||\n char === \"!\" ||\n char === \"?\" ||\n char === \"|\" ||\n char === \"*\" ||\n char === \"=\"\n );\n}\n\nfunction isLikelyFilePath(value: string): boolean {\n if (value.startsWith(\"/\") || value.startsWith(\"./\") || value.startsWith(\"../\") || value.startsWith(\"~/\")) {\n return hasValidFileExtension(value);\n }\n if (value.includes(\"/\")) return hasValidFileExtension(value);\n return hasValidFileExtension(value);\n}\n\nfunction hasValidFileExtension(value: string): boolean {\n const lastSlash = value.lastIndexOf(\"/\");\n const basename = value.slice(lastSlash + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0 || dot === basename.length - 1) return false;\n const ext = basename.slice(dot + 1);\n if (ext.length < 1 || ext.length > 12) return false;\n for (const char of ext) {\n if (!isFileExtensionChar(char)) return false;\n }\n return true;\n}\n\nfunction isFileExtensionChar(char: string): boolean {\n const code = char.charCodeAt(0);\n return (\n (code >= 48 && code <= 57) ||\n (code >= 65 && code <= 90) ||\n (code >= 97 && code <= 122) ||\n char === \"_\" ||\n char === \"+\" ||\n char === \"-\"\n );\n}\n\nfunction extractPatchPaths(text: string): string[] {\n const out = new Set<string>();\n for (const line of text.split(/\\r?\\n/)) {\n const match = line.match(/^\\*\\*\\* (?:Add|Update|Delete) File: (.+)$/);\n if (match?.[1]) out.add(match[1].trim());\n const move = line.match(/^\\*\\*\\* Move to: (.+)$/);\n if (move?.[1]) out.add(move[1].trim());\n }\n return [...out].slice(0, 20);\n}\n","import type Database from \"better-sqlite3\";\nimport { log } from \"../logger.js\";\nimport {\n parseMessageParts,\n type LcmMessagePartInput,\n type MessagePartSourceFormat,\n} from \"../message-parts/index.js\";\n\nexport interface LcmMessage {\n id: number;\n session_id: string;\n turn_index: number;\n role: string;\n content: string;\n token_count: number;\n created_at: string;\n metadata: string | null;\n}\n\nexport interface LcmSearchResult {\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n score: number;\n}\n\nexport interface LcmSearchWithContentResult {\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n score: number;\n}\n\nexport interface LcmStructuredRecallMatch {\n part_id: number;\n message_id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n kind: string;\n tool_name: string | null;\n file_path: string | null;\n payload: string;\n score: number;\n}\n\n/** Rough token count: ~4 chars per token. */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport class LcmArchive {\n constructor(private readonly db: Database.Database) {}\n\n /** Append a message to the archive. Returns the row id. */\n appendMessage(\n sessionId: string,\n turnIndex: number,\n role: string,\n content: string,\n metadata?: Record<string, unknown>,\n parts?: LcmMessagePartInput[],\n ): number {\n const tokenCount = estimateTokens(content);\n const now = new Date().toISOString();\n const metaJson = metadata ? JSON.stringify(metadata) : null;\n\n const stmt = this.db.prepare(`\n INSERT INTO lcm_messages (session_id, turn_index, role, content, token_count, created_at, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n const result = stmt.run(sessionId, turnIndex, role, content, tokenCount, now, metaJson);\n const rowId = Number(result.lastInsertRowid);\n\n // Keep FTS in sync\n this.db\n .prepare(\"INSERT INTO lcm_messages_fts (rowid, content) VALUES (?, ?)\")\n .run(rowId, content);\n\n if (parts && parts.length > 0) {\n this.insertMessageParts(rowId, parts, now);\n }\n\n return rowId;\n }\n\n /** Append multiple messages in a single transaction. */\n appendMessages(\n sessionId: string,\n messages: Array<{\n turnIndex: number;\n role: string;\n content: string;\n metadata?: Record<string, unknown>;\n parts?: LcmMessagePartInput[];\n rawContent?: unknown;\n sourceFormat?: MessagePartSourceFormat;\n }>,\n options: { messagePartsEnabled?: boolean } = {},\n ): void {\n if (messages.length === 0) return;\n const captureMessageParts = options.messagePartsEnabled !== false;\n\n const txn = this.db.transaction(() => {\n for (const msg of messages) {\n const explicitParts =\n msg.parts && msg.parts.length > 0 ? msg.parts : undefined;\n const rawContent = msg.rawContent ?? msg.content;\n const parts =\n captureMessageParts\n ? explicitParts ??\n parseMessageParts(rawContent, {\n sourceFormat: msg.sourceFormat,\n renderedContent: msg.content,\n })\n : undefined;\n this.appendMessage(\n sessionId,\n msg.turnIndex,\n msg.role,\n msg.content,\n msg.metadata,\n parts,\n );\n }\n });\n txn();\n }\n\n insertMessageParts(\n messageId: number,\n parts: LcmMessagePartInput[],\n fallbackCreatedAt: string,\n ): void {\n if (parts.length === 0) return;\n const stmt = this.db.prepare(`\n INSERT INTO lcm_message_parts (message_id, ordinal, kind, payload, tool_name, file_path, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n for (let index = 0; index < parts.length; index += 1) {\n const part = parts[index]!;\n const rawPart = part as unknown as Record<string, unknown>;\n const toolName = part.toolName ?? asNullableString(rawPart.tool_name);\n const filePath = part.filePath ?? asNullableString(rawPart.file_path);\n const createdAt = part.createdAt ?? asNullableString(rawPart.created_at);\n stmt.run(\n messageId,\n part.ordinal ?? index,\n part.kind,\n JSON.stringify(part.payload ?? {}),\n toolName ?? null,\n filePath ?? null,\n createdAt ?? fallbackCreatedAt,\n );\n }\n }\n\n /** Get the highest turn_index for a session, or -1 if none. */\n getMaxTurnIndex(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT MAX(turn_index) as max_turn FROM lcm_messages WHERE session_id = ?\")\n .get(sessionId) as { max_turn: number | null } | undefined;\n return row?.max_turn ?? -1;\n }\n\n /** Retrieve messages in a turn range (inclusive). */\n getMessages(sessionId: string, fromTurn: number, toTurn: number): LcmMessage[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_messages WHERE session_id = ? AND turn_index >= ? AND turn_index <= ? ORDER BY turn_index\",\n )\n .all(sessionId, fromTurn, toTurn) as LcmMessage[];\n }\n\n /** Retrieve unsummarized messages (after last leaf summary). */\n getUnsummarizedMessages(sessionId: string): LcmMessage[] {\n const lastLeafEnd = this.db\n .prepare(\n \"SELECT MAX(msg_end) as last_end FROM lcm_summary_nodes WHERE session_id = ? AND depth = 0\",\n )\n .get(sessionId) as { last_end: number | null } | undefined;\n\n const lastSummarized = lastLeafEnd?.last_end ?? -1;\n return this.db\n .prepare(\n \"SELECT * FROM lcm_messages WHERE session_id = ? AND turn_index > ? ORDER BY turn_index\",\n )\n .all(sessionId, lastSummarized) as LcmMessage[];\n }\n\n /** Full-text search across all messages. */\n search(query: string, limit: number, sessionId?: string): LcmSearchResult[] {\n try {\n const ftsQuery = sanitizeFtsQuery(query);\n if (!ftsQuery) return [];\n\n let sql: string;\n const params: unknown[] = [ftsQuery];\n\n if (sessionId) {\n sql = `\n SELECT m.turn_index, m.role, snippet(lcm_messages_fts, 0, '>>>', '<<<', '...', 48) as snippet,\n m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n AND m.session_id = ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(sessionId, limit);\n } else {\n sql = `\n SELECT m.turn_index, m.role, snippet(lcm_messages_fts, 0, '>>>', '<<<', '...', 48) as snippet,\n m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(limit);\n }\n\n const rows = this.db.prepare(sql).all(...params) as Array<{\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n rank: number;\n }>;\n\n return rows.map((r) => ({\n turn_index: r.turn_index,\n role: r.role,\n snippet: r.snippet,\n session_id: r.session_id,\n score: -r.rank, // FTS5 rank is negative; negate for ascending score\n }));\n } catch (err) {\n log.debug(`LCM FTS search error: ${err}`);\n return [];\n }\n }\n\n /**\n * Full-text search returning focused excerpts around matching terms.\n * Returns ~1000-char windows centered on query term matches.\n * Deduplicates by message id and returns results sorted by FTS rank.\n */\n searchWithContent(query: string, limit: number, sessionId?: string, excerptChars = 1000): LcmSearchWithContentResult[] {\n try {\n const ftsQuery = sanitizeFtsQuery(query);\n if (!ftsQuery) return [];\n\n // Extract content words from query for excerpt windowing\n const queryWords = query\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 1 && !STOPWORDS.has(w.toLowerCase()))\n .map((w) => w.toLowerCase());\n\n let sql: string;\n const params: unknown[] = [ftsQuery];\n\n if (sessionId) {\n sql = `\n SELECT m.id, m.turn_index, m.role, m.content, m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n AND m.session_id = ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(sessionId, limit);\n } else {\n sql = `\n SELECT m.id, m.turn_index, m.role, m.content, m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(limit);\n }\n\n const rows = this.db.prepare(sql).all(...params) as Array<{\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n rank: number;\n }>;\n\n // Deduplicate by message id (same message may match multiple terms)\n const seen = new Set<number>();\n const results: LcmSearchWithContentResult[] = [];\n for (const r of rows) {\n if (seen.has(r.id)) continue;\n seen.add(r.id);\n results.push({\n id: r.id,\n turn_index: r.turn_index,\n role: r.role,\n content: extractExcerpt(r.content, queryWords, excerptChars),\n session_id: r.session_id,\n score: -r.rank,\n });\n }\n return results;\n } catch (err) {\n log.debug(`LCM FTS searchWithContent error: ${err}`);\n return [];\n }\n }\n\n searchStructuredParts(\n query: string,\n limit: number,\n sessionId?: string,\n ): LcmStructuredRecallMatch[] {\n const cappedLimit = Math.max(0, Math.min(20, Math.floor(limit)));\n if (cappedLimit === 0) return [];\n\n const fileTerms = extractStructuredFileTerms(query);\n const toolTerms = extractStructuredToolTerms(query);\n if (fileTerms.length === 0 && toolTerms.length === 0) return [];\n\n const matchWhere: string[] = [];\n const whereParams: unknown[] = [];\n for (const term of fileTerms) {\n matchWhere.push(\"(p.file_path = ? OR p.file_path LIKE ? ESCAPE '\\\\')\");\n whereParams.push(term, `%${escapeLike(term)}%`);\n }\n for (const term of toolTerms) {\n matchWhere.push(\"p.tool_name LIKE ? ESCAPE '\\\\'\");\n whereParams.push(`%${escapeLike(term)}%`);\n }\n const where = [`(${matchWhere.join(\" OR \")})`];\n if (sessionId) {\n where.push(\"m.session_id = ?\");\n whereParams.push(sessionId);\n }\n const exactFileScoreParams = [...fileTerms];\n const sqlParams = [...exactFileScoreParams, ...whereParams, cappedLimit];\n\n const rows = this.db.prepare(`\n SELECT\n p.id AS part_id,\n p.message_id AS message_id,\n m.turn_index AS turn_index,\n m.role AS role,\n m.content AS content,\n m.session_id AS session_id,\n p.kind AS kind,\n p.tool_name AS tool_name,\n p.file_path AS file_path,\n p.payload AS payload,\n CASE\n WHEN p.file_path IN (${fileTerms.map(() => \"?\").join(\",\") || \"NULL\"}) THEN 3\n WHEN p.file_path IS NOT NULL THEN 2\n WHEN p.tool_name IS NOT NULL THEN 1\n ELSE 0\n END AS score\n FROM lcm_message_parts p\n JOIN lcm_messages m ON m.id = p.message_id\n WHERE ${where.join(\" AND \")}\n ORDER BY score DESC, m.turn_index DESC, p.ordinal ASC\n LIMIT ?\n `).all(...sqlParams) as LcmStructuredRecallMatch[];\n\n return rows;\n }\n\n /** Get total message count for a session. */\n getMessageCount(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_messages WHERE session_id = ?\")\n .get(sessionId) as { cnt: number };\n return row.cnt;\n }\n\n /** Get total message count across all sessions. */\n getTotalMessageCount(): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_messages\")\n .get() as { cnt: number };\n return row.cnt;\n }\n\n /** Prune messages older than retentionDays. */\n pruneOldMessages(retentionDays: number): number {\n const cutoff = new Date(Date.now() - retentionDays * 86400_000).toISOString();\n\n // Delete from FTS first\n this.db\n .prepare(\n \"DELETE FROM lcm_messages_fts WHERE rowid IN (SELECT id FROM lcm_messages WHERE created_at < ?)\",\n )\n .run(cutoff);\n\n const result = this.db\n .prepare(\"DELETE FROM lcm_messages WHERE created_at < ?\")\n .run(cutoff);\n return result.changes;\n }\n}\n\n/**\n * Extract a focused excerpt from content centered on query term matches.\n * Returns a window of ~excerptChars around the first matching term.\n * If content is shorter than excerptChars, returns the full content.\n */\nfunction extractExcerpt(content: string, queryWords: string[], excerptChars: number): string {\n if (content.length <= excerptChars) return content;\n\n // Find the earliest position of any query word in the content\n const contentLower = content.toLowerCase();\n let bestPos = -1;\n for (const word of queryWords) {\n const pos = contentLower.indexOf(word);\n if (pos !== -1 && (bestPos === -1 || pos < bestPos)) {\n bestPos = pos;\n }\n }\n\n // If no match found (shouldn't happen for FTS results), return start\n if (bestPos === -1) {\n return content.slice(0, excerptChars) + \"...\";\n }\n\n // Center the window around the match\n const halfWindow = Math.floor(excerptChars / 2);\n let start = Math.max(0, bestPos - halfWindow);\n let end = Math.min(content.length, start + excerptChars);\n\n // Adjust start if we hit the end\n if (end === content.length) {\n start = Math.max(0, end - excerptChars);\n }\n\n // Extend to sentence boundaries if possible\n if (start > 0) {\n const sentenceStart = content.lastIndexOf(\". \", start);\n if (sentenceStart !== -1 && start - sentenceStart < 200) {\n start = sentenceStart + 2;\n }\n }\n if (end < content.length) {\n const sentenceEnd = content.indexOf(\". \", end - 1);\n if (sentenceEnd !== -1 && sentenceEnd - end < 200) {\n end = sentenceEnd + 1;\n }\n }\n\n const prefix = start > 0 ? \"...\" : \"\";\n const suffix = end < content.length ? \"...\" : \"\";\n return prefix + content.slice(start, end) + suffix;\n}\n\nconst STOPWORDS = new Set([\n \"a\", \"an\", \"the\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\n \"have\", \"has\", \"had\", \"do\", \"does\", \"did\", \"will\", \"would\", \"could\",\n \"should\", \"may\", \"might\", \"shall\", \"can\", \"to\", \"of\", \"in\", \"for\",\n \"on\", \"with\", \"at\", \"by\", \"from\", \"as\", \"into\", \"about\", \"between\",\n \"through\", \"during\", \"before\", \"after\", \"and\", \"but\", \"or\", \"nor\",\n \"not\", \"so\", \"if\", \"then\", \"than\", \"that\", \"this\", \"it\", \"its\",\n \"what\", \"which\", \"who\", \"whom\", \"how\", \"when\", \"where\", \"why\",\n \"all\", \"each\", \"every\", \"both\", \"few\", \"more\", \"most\", \"other\",\n \"some\", \"such\", \"no\", \"only\", \"own\", \"same\", \"just\", \"very\",\n \"my\", \"your\", \"his\", \"her\", \"our\", \"their\", \"me\", \"him\", \"us\", \"them\",\n \"i\", \"you\", \"he\", \"she\", \"we\", \"they\",\n]);\n\nfunction extractStructuredFileTerms(query: string): string[] {\n const terms = new Set<string>();\n for (const raw of splitQueryTerms(query)) {\n const cleaned = trimStructuredQueryTerm(raw);\n if (\n cleaned.includes(\"/\") ||\n hasStructuredFileExtension(cleaned)\n ) {\n terms.add(cleaned);\n const basename = cleaned.split(\"/\").pop();\n if (basename && basename !== cleaned) terms.add(basename);\n }\n }\n return [...terms].filter((term) => term.length > 1).slice(0, 12);\n}\n\nfunction splitQueryTerms(query: string): string[] {\n const terms: string[] = [];\n let term = \"\";\n for (const char of query.slice(0, 20_000)) {\n if (char === \" \" || char === \"\\n\" || char === \"\\r\" || char === \"\\t\") {\n if (term.length > 0) terms.push(term);\n term = \"\";\n continue;\n }\n term += char;\n if (term.length > 512) {\n terms.push(term);\n term = \"\";\n }\n }\n if (term.length > 0) terms.push(term);\n return terms;\n}\n\nfunction trimStructuredQueryTerm(raw: string): string {\n const leading = new Set([\"`\", \"'\", \"\\\"\", \"(\", \"[\", \"{\"]);\n const trailing = new Set([\"`\", \"'\", \"\\\"\", \",\", \".\", \"?\", \"!\", \":\", \";\", \")\", \"]\", \"}\"]);\n let start = 0;\n let end = raw.length;\n while (start < end && leading.has(raw[start]!)) start += 1;\n while (end > start && trailing.has(raw[end - 1]!)) end -= 1;\n return raw.slice(start, end);\n}\n\nfunction hasStructuredFileExtension(value: string): boolean {\n const slash = value.lastIndexOf(\"/\");\n const basename = value.slice(slash + 1);\n const dot = basename.lastIndexOf(\".\");\n if (dot <= 0 || dot === basename.length - 1) return false;\n const ext = basename.slice(dot + 1);\n if (ext.length < 1 || ext.length > 12) return false;\n for (const char of ext) {\n const code = char.charCodeAt(0);\n const valid =\n (code >= 48 && code <= 57) ||\n (code >= 65 && code <= 90) ||\n (code >= 97 && code <= 122) ||\n char === \"_\" ||\n char === \"+\" ||\n char === \"-\";\n if (!valid) return false;\n }\n return true;\n}\n\nfunction extractStructuredToolTerms(query: string): string[] {\n const lower = query.toLowerCase();\n if (!/\\b(tool|command|invocation|called|used|ran|read|write|patch|edit|grep|search)\\b/.test(lower)) {\n return [];\n }\n return query\n .replace(/[^\\w.-]/g, \" \")\n .split(/\\s+/)\n .filter((term) => term.length > 2 && !STOPWORDS.has(term.toLowerCase()))\n .slice(0, 8);\n}\n\nfunction escapeLike(value: string): string {\n return value.replace(/[\\\\%_]/g, (char) => `\\\\${char}`);\n}\n\nfunction asNullableString(value: unknown): string | null {\n return typeof value === \"string\" && value.trim().length > 0 ? value : null;\n}\n\n/**\n * Sanitize a query for FTS5 MATCH.\n * Uses OR logic so partial matches rank higher than no matches.\n * Filters stopwords to focus on content words.\n */\nfunction sanitizeFtsQuery(raw: string): string {\n const words = raw\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 1 && !STOPWORDS.has(w.toLowerCase()));\n if (words.length === 0) {\n // If all words were stopwords, fall back to using all words\n const allWords = raw.replace(/[^\\w\\s]/g, \" \").split(/\\s+/).filter((w) => w.length > 1);\n if (allWords.length === 0) return \"\";\n return allWords.map((w) => `\"${w}\"`).join(\" OR \");\n }\n return words.map((w) => `\"${w}\"`).join(\" OR \");\n}\n","import type Database from \"better-sqlite3\";\nimport { log } from \"../logger.js\";\n\nexport interface SummaryNode {\n id: string;\n session_id: string;\n depth: number;\n parent_id: string | null;\n summary_text: string;\n token_count: number;\n msg_start: number;\n msg_end: number;\n escalation: number;\n created_at: string;\n}\n\nexport class LcmDag {\n constructor(private readonly db: Database.Database) {}\n\n /** Insert a new summary node. */\n insertNode(node: Omit<SummaryNode, \"created_at\">): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`\n INSERT INTO lcm_summary_nodes (id, session_id, depth, parent_id, summary_text, token_count, msg_start, msg_end, escalation, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n .run(\n node.id,\n node.session_id,\n node.depth,\n node.parent_id,\n node.summary_text,\n node.token_count,\n node.msg_start,\n node.msg_end,\n node.escalation,\n now,\n );\n\n // Keep FTS in sync\n const rowid = this.db\n .prepare(\"SELECT rowid FROM lcm_summary_nodes WHERE id = ?\")\n .get(node.id) as { rowid: number } | undefined;\n if (rowid) {\n this.db\n .prepare(\"INSERT INTO lcm_summaries_fts (rowid, summary_text) VALUES (?, ?)\")\n .run(rowid.rowid, node.summary_text);\n }\n }\n\n /** Get leaf nodes (depth=0) for a session without a parent yet, ordered by msg_start. */\n getOrphanNodesAtDepth(sessionId: string, depth: number): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? AND depth = ? AND parent_id IS NULL ORDER BY msg_start\",\n )\n .all(sessionId, depth) as SummaryNode[];\n }\n\n /** Get all nodes at a given depth for a session. */\n getNodesAtDepth(sessionId: string, depth: number): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? AND depth = ? ORDER BY msg_start\",\n )\n .all(sessionId, depth) as SummaryNode[];\n }\n\n /** Get child nodes of a parent. */\n getChildren(parentId: string): SummaryNode[] {\n return this.db\n .prepare(\"SELECT * FROM lcm_summary_nodes WHERE parent_id = ? ORDER BY msg_start\")\n .all(parentId) as SummaryNode[];\n }\n\n /** Get the deepest summary nodes covering a session (highest depth, broadest coverage). */\n getDeepestNodes(sessionId: string): SummaryNode[] {\n const maxDepth = this.db\n .prepare(\"SELECT MAX(depth) as max_depth FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { max_depth: number | null } | undefined;\n\n if (!maxDepth?.max_depth && maxDepth?.max_depth !== 0) return [];\n\n return this.getNodesAtDepth(sessionId, maxDepth.max_depth);\n }\n\n /** Get the maximum depth for a session. */\n getMaxDepth(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT MAX(depth) as max_depth FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { max_depth: number | null } | undefined;\n return row?.max_depth ?? -1;\n }\n\n /** Get summary nodes that best cover a turn range, preferring higher depth. */\n getCoveringNodes(sessionId: string, fromTurn: number, toTurn: number): SummaryNode[] {\n return this.db\n .prepare(`\n SELECT * FROM lcm_summary_nodes\n WHERE session_id = ?\n AND msg_start <= ?\n AND msg_end >= ?\n ORDER BY depth DESC, msg_start\n `)\n .all(sessionId, toTurn, fromTurn) as SummaryNode[];\n }\n\n /** Get all nodes for a session, ordered by depth then range. */\n getAllNodes(sessionId: string): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? ORDER BY depth, msg_start\",\n )\n .all(sessionId) as SummaryNode[];\n }\n\n /** Get total node count for a session. */\n getNodeCount(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { cnt: number };\n return row.cnt;\n }\n\n /** Set parent_id for a list of child node IDs. */\n setParent(childIds: string[], parentId: string): void {\n const stmt = this.db.prepare(\n \"UPDATE lcm_summary_nodes SET parent_id = ? WHERE id = ?\",\n );\n const txn = this.db.transaction(() => {\n for (const childId of childIds) {\n stmt.run(parentId, childId);\n }\n });\n txn();\n }\n\n /** Record a compaction event. */\n recordCompaction(\n sessionId: string,\n msgBefore: number,\n tokensBefore: number,\n tokensAfter: number,\n ): void {\n this.db\n .prepare(`\n INSERT INTO lcm_compaction_events (session_id, fired_at, msg_before, tokens_before, tokens_after)\n VALUES (?, ?, ?, ?, ?)\n `)\n .run(sessionId, new Date().toISOString(), msgBefore, tokensBefore, tokensAfter);\n }\n\n /** Prune summary nodes for old sessions. */\n pruneOldNodes(retentionDays: number): number {\n const cutoff = new Date(Date.now() - retentionDays * 86400_000).toISOString();\n\n this.db\n .prepare(\n \"DELETE FROM lcm_summaries_fts WHERE rowid IN (SELECT rowid FROM lcm_summary_nodes WHERE created_at < ?)\",\n )\n .run(cutoff);\n\n const result = this.db\n .prepare(\"DELETE FROM lcm_summary_nodes WHERE created_at < ?\")\n .run(cutoff);\n return result.changes;\n }\n}\n","import { log } from \"../logger.js\";\nimport type { LcmArchive, LcmMessage } from \"./archive.js\";\nimport { LcmDag } from \"./dag.js\";\nimport { estimateTokens } from \"./archive.js\";\n\n/** Generate a ULID-like ID (timestamp + random). */\nfunction generateNodeId(): string {\n const ts = Date.now().toString(36).padStart(9, \"0\");\n const rand = Math.random().toString(36).slice(2, 10);\n return `lcm-${ts}-${rand}`;\n}\n\nexport type SummarizeFn = (\n text: string,\n targetTokens: number,\n aggressive: boolean,\n) => Promise<string | null>;\n\nexport interface LcmSummarizerConfig {\n leafBatchSize: number;\n rollupFanIn: number;\n maxDepth: number;\n deterministicMaxTokens: number;\n}\n\nexport class LcmSummarizer {\n constructor(\n private readonly archive: LcmArchive,\n private readonly dag: LcmDag,\n private readonly summarizeFn: SummarizeFn,\n private readonly config: LcmSummarizerConfig,\n ) {}\n\n /**\n * Run incremental summarization for a session.\n * Creates leaf nodes from unsummarized messages, then rolls up as needed.\n */\n async summarizeIncremental(sessionId: string): Promise<number> {\n let nodesCreated = 0;\n\n // Phase 1: Create leaf nodes from unsummarized messages\n const unsummarized = this.archive.getUnsummarizedMessages(sessionId);\n if (unsummarized.length >= this.config.leafBatchSize) {\n const batches = chunkArray(unsummarized, this.config.leafBatchSize);\n // Only process complete batches (leave partial for next time)\n const completeBatches = unsummarized.length % this.config.leafBatchSize === 0\n ? batches\n : batches.slice(0, -1);\n\n for (const batch of completeBatches) {\n const created = await this.createLeafNode(sessionId, batch);\n if (created) nodesCreated++;\n }\n }\n\n // Phase 2: Roll up at each depth level\n if (nodesCreated > 0) {\n nodesCreated += await this.rollupAll(sessionId);\n }\n\n return nodesCreated;\n }\n\n /** Create a leaf summary node (depth 0) from a batch of messages. */\n private async createLeafNode(\n sessionId: string,\n messages: LcmMessage[],\n ): Promise<boolean> {\n if (messages.length === 0) return false;\n\n const combinedText = messages\n .map((m) => `[${m.role}] ${m.content}`)\n .join(\"\\n\\n\");\n\n const inputTokens = estimateTokens(combinedText);\n const targetTokens = Math.max(64, Math.ceil(inputTokens * 0.25));\n\n const summary = await this.summarizeWithEscalation(combinedText, targetTokens);\n\n this.dag.insertNode({\n id: generateNodeId(),\n session_id: sessionId,\n depth: 0,\n parent_id: null,\n summary_text: summary.text,\n token_count: estimateTokens(summary.text),\n msg_start: messages[0].turn_index,\n msg_end: messages[messages.length - 1].turn_index,\n escalation: summary.escalation,\n });\n\n return true;\n }\n\n /** Roll up orphan nodes at each depth level up to maxDepth. */\n private async rollupAll(sessionId: string): Promise<number> {\n let totalCreated = 0;\n\n for (let depth = 0; depth < this.config.maxDepth; depth++) {\n const orphans = this.dag.getOrphanNodesAtDepth(sessionId, depth);\n if (orphans.length < this.config.rollupFanIn) continue;\n\n const batches = chunkArray(orphans, this.config.rollupFanIn);\n // Only process complete batches\n const completeBatches = orphans.length % this.config.rollupFanIn === 0\n ? batches\n : batches.slice(0, -1);\n\n for (const batch of completeBatches) {\n const combinedText = batch\n .map((n) => n.summary_text)\n .join(\"\\n\\n\");\n\n const inputTokens = estimateTokens(combinedText);\n const targetTokens = Math.max(64, Math.ceil(inputTokens * 0.25));\n\n const summary = await this.summarizeWithEscalation(combinedText, targetTokens);\n\n const parentId = generateNodeId();\n this.dag.insertNode({\n id: parentId,\n session_id: sessionId,\n depth: depth + 1,\n parent_id: null,\n summary_text: summary.text,\n token_count: estimateTokens(summary.text),\n msg_start: batch[0].msg_start,\n msg_end: batch[batch.length - 1].msg_end,\n escalation: summary.escalation,\n });\n\n this.dag.setParent(\n batch.map((n) => n.id),\n parentId,\n );\n\n totalCreated++;\n }\n }\n\n return totalCreated;\n }\n\n /**\n * Three-level escalation:\n * 0 = Normal LLM summary\n * 1 = Aggressive bullet compression\n * 2 = Deterministic truncation (no LLM)\n */\n private async summarizeWithEscalation(\n text: string,\n targetTokens: number,\n ): Promise<{ text: string; escalation: number }> {\n // Level 0: Normal LLM summary\n try {\n const result = await this.summarizeFn(text, targetTokens, false);\n if (result && estimateTokens(result) <= targetTokens * 1.5) {\n return { text: result, escalation: 0 };\n }\n // If too long, try aggressive\n } catch (err) {\n log.debug(`LCM level-0 summary failed: ${err}`);\n }\n\n // Level 1: Aggressive bullet compression\n try {\n const aggressiveTarget = Math.max(32, Math.ceil(targetTokens * 0.5));\n const result = await this.summarizeFn(text, aggressiveTarget, true);\n if (result && estimateTokens(result) <= targetTokens * 1.5) {\n return { text: result, escalation: 1 };\n }\n } catch (err) {\n log.debug(`LCM level-1 summary failed: ${err}`);\n }\n\n // Level 2: Deterministic truncation (guaranteed, no LLM)\n return {\n text: deterministicTruncate(text, this.config.deterministicMaxTokens),\n escalation: 2,\n };\n }\n}\n\n/** Deterministic truncation: first and last sentence, plus middle truncation. */\nfunction deterministicTruncate(text: string, maxTokens: number): string {\n const maxChars = maxTokens * 4;\n if (text.length <= maxChars) return text;\n\n const sentences = text.split(/(?<=[.!?])\\s+/).filter((s) => s.length > 0);\n if (sentences.length <= 2) {\n return text.slice(0, maxChars);\n }\n\n const first = sentences[0];\n const last = sentences[sentences.length - 1];\n const budget = maxChars - first.length - last.length - 20;\n\n if (budget <= 0) {\n return text.slice(0, maxChars);\n }\n\n // Fill from the beginning until budget runs out\n const middle: string[] = [];\n let used = 0;\n for (let i = 1; i < sentences.length - 1; i++) {\n if (used + sentences[i].length > budget) break;\n middle.push(sentences[i]);\n used += sentences[i].length;\n }\n\n return `${first} ${middle.join(\" \")}${middle.length < sentences.length - 2 ? \" [...] \" : \" \"}${last}`;\n}\n\nfunction chunkArray<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n}\n","import type { LcmDag, SummaryNode } from \"./dag.js\";\nimport type { LcmArchive } from \"./archive.js\";\nimport { log } from \"../logger.js\";\n\nexport interface LcmRecallConfig {\n freshTailTurns: number;\n budgetChars: number;\n}\n\n/**\n * Assemble a compressed session history section from the summary DAG.\n *\n * Strategy:\n * 1. For the \"fresh tail\" (most recent N turns), use leaf-level summaries for maximum detail.\n * 2. For older portions, use the deepest available summary nodes (most compressed).\n * 3. Fill within budget, prioritizing recent content.\n */\nexport function assembleCompressedHistory(\n dag: LcmDag,\n archive: LcmArchive,\n sessionId: string,\n config: LcmRecallConfig,\n): string {\n const maxTurn = archive.getMaxTurnIndex(sessionId);\n if (maxTurn < 0) return \"\";\n\n const allNodes = dag.getAllNodes(sessionId);\n if (allNodes.length === 0) return \"\";\n\n const freshTailStart = Math.max(0, maxTurn - config.freshTailTurns + 1);\n const sections: string[] = [];\n let usedChars = 0;\n\n // Collect nodes covering the \"old\" portion (before fresh tail)\n if (freshTailStart > 0) {\n const oldNodes = selectBestCoverage(allNodes, 0, freshTailStart - 1);\n for (const node of oldNodes) {\n const label = formatRangeLabel(node, maxTurn);\n const entry = `**${label}** (depth ${node.depth}):\\n${node.summary_text}`;\n if (usedChars + entry.length > config.budgetChars) break;\n sections.push(entry);\n usedChars += entry.length;\n }\n }\n\n // Collect leaf nodes that overlap with the fresh tail region.\n // The old section uses deep nodes (depth > 0), so leaf nodes included here\n // won't duplicate old-section content. Use msg_end >= freshTailStart to\n // include straddling leaf nodes that partially cover the fresh region.\n const freshNodes = allNodes\n .filter(\n (n) => n.depth === 0 && n.msg_end >= freshTailStart && n.msg_end <= maxTurn,\n )\n .sort((a, b) => a.msg_start - b.msg_start);\n\n for (const node of freshNodes) {\n const label = `Recent (turns ${node.msg_start}-${node.msg_end})`;\n const entry = `**${label}**:\\n${node.summary_text}`;\n if (usedChars + entry.length > config.budgetChars) break;\n sections.push(entry);\n usedChars += entry.length;\n }\n\n if (sections.length === 0) return \"\";\n\n return `## Session History (Compressed)\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n/**\n * Select the best coverage for a turn range.\n * Prefers deeper (more compressed) nodes. Avoids overlapping coverage.\n */\nfunction selectBestCoverage(\n allNodes: SummaryNode[],\n fromTurn: number,\n toTurn: number,\n): SummaryNode[] {\n // Filter to nodes that overlap with the requested range\n const candidates = allNodes.filter(\n (n) => n.msg_start <= toTurn && n.msg_end >= fromTurn,\n );\n\n if (candidates.length === 0) return [];\n\n // Sort by msg_start ascending, then depth descending (prefer deeper at same position)\n candidates.sort((a, b) => {\n if (a.msg_start !== b.msg_start) return a.msg_start - b.msg_start;\n return b.depth - a.depth;\n });\n\n // Greedily select non-overlapping nodes, preferring deeper coverage.\n // Clamp msg_end to toTurn to prevent deep nodes from extending\n // past the requested range (e.g., into the fresh tail region).\n const selected: SummaryNode[] = [];\n let coveredUpTo = fromTurn - 1;\n\n for (const node of candidates) {\n if (node.msg_start > coveredUpTo) {\n selected.push(node);\n coveredUpTo = Math.min(node.msg_end, toTurn);\n if (coveredUpTo >= toTurn) break;\n }\n }\n\n // Re-sort selected by msg_start for chronological output\n selected.sort((a, b) => a.msg_start - b.msg_start);\n return selected;\n}\n\nfunction formatRangeLabel(node: SummaryNode, maxTurn: number): string {\n const startPct = Math.round((node.msg_start / Math.max(1, maxTurn)) * 100);\n const endPct = Math.round((node.msg_end / Math.max(1, maxTurn)) * 100);\n\n if (startPct < 33) return `Early session (turns ${node.msg_start}-${node.msg_end})`;\n if (endPct < 66) return `Mid session (turns ${node.msg_start}-${node.msg_end})`;\n return `Later session (turns ${node.msg_start}-${node.msg_end})`;\n}\n","export interface LcmObserveMessage {\n role: string;\n content: string;\n parts?: import(\"../message-parts/index.js\").LcmMessagePartInput[];\n rawContent?: unknown;\n sourceFormat?: import(\"../message-parts/index.js\").MessagePartSourceFormat;\n}\n\nexport interface LcmWorkQueueHooks {\n onJobStart?: (input: {\n sessionId: string;\n depth: number;\n inFlight: number;\n waitMs: number;\n }) => void;\n onJobFinish?: (input: {\n sessionId: string;\n depth: number;\n inFlight: number;\n waitMs: number;\n runMs: number;\n totalMs: number;\n error?: unknown;\n }) => void;\n}\n\nexport interface LcmWorkQueueOptions {\n concurrency?: number;\n worker: (sessionId: string, messages: LcmObserveMessage[]) => Promise<void>;\n hooks?: LcmWorkQueueHooks;\n}\n\ninterface PendingJob {\n sessionId: string;\n messages: LcmObserveMessage[];\n enqueuedAt: number;\n}\n\n/**\n * Small keyed work queue for LCM observe processing.\n *\n * Jobs are coalesced per session while they are pending. A session can have\n * at most one in-flight job at a time, and the queue processes jobs FIFO up to\n * the configured concurrency limit.\n */\nexport class LcmWorkQueue {\n private readonly concurrency: number;\n private readonly worker: (\n sessionId: string,\n messages: LcmObserveMessage[],\n ) => Promise<void>;\n private readonly hooks: LcmWorkQueueHooks;\n private readonly pending = new Map<string, PendingJob>();\n private readonly inFlightSessions = new Set<string>();\n private inFlight = 0;\n private readonly idleWaiters: Array<() => void> = [];\n private readonly sessionIdleWaiters = new Map<string, Array<() => void>>();\n private drainScheduled = false;\n\n constructor(options: LcmWorkQueueOptions) {\n this.concurrency = Math.max(1, Math.floor(options.concurrency ?? 1));\n this.worker = options.worker;\n this.hooks = options.hooks ?? {};\n }\n\n enqueue(sessionId: string, messages: LcmObserveMessage[]): void {\n if (messages.length === 0) return;\n\n const now = Date.now();\n const existing = this.pending.get(sessionId);\n if (existing) {\n existing.messages.push(...messages.map((message) => ({ ...message })));\n } else {\n this.pending.set(sessionId, {\n sessionId,\n messages: messages.map((message) => ({ ...message })),\n enqueuedAt: now,\n });\n }\n\n this.scheduleDrain();\n }\n\n get depth(): number {\n return this.pending.size;\n }\n\n get inFlightCount(): number {\n return this.inFlight;\n }\n\n async whenIdle(): Promise<void> {\n if (this.depth === 0 && this.inFlight === 0) return;\n await new Promise<void>((resolve) => {\n this.idleWaiters.push(resolve);\n });\n }\n\n async whenSessionIdle(sessionId: string): Promise<void> {\n if (!this.pending.has(sessionId) && !this.inFlightSessions.has(sessionId))\n return;\n await new Promise<void>((resolve) => {\n const waiters = this.sessionIdleWaiters.get(sessionId) ?? [];\n waiters.push(resolve);\n this.sessionIdleWaiters.set(sessionId, waiters);\n });\n }\n\n private startAvailableJobs(): void {\n while (this.inFlight < this.concurrency && this.pending.size > 0) {\n const next = Array.from(this.pending.entries()).find(\n ([sessionId]) => !this.inFlightSessions.has(sessionId),\n );\n if (!next) break;\n\n const [sessionId, job] = next;\n this.pending.delete(sessionId);\n this.inFlight++;\n this.inFlightSessions.add(sessionId);\n\n const startedAt = Date.now();\n const waitMs = startedAt - job.enqueuedAt;\n this.hooks.onJobStart?.({\n sessionId,\n depth: this.depth,\n inFlight: this.inFlight,\n waitMs,\n });\n\n void this.runJob(job, startedAt, waitMs);\n }\n\n this.resolveIdleWaitersIfNeeded();\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n\n queueMicrotask(() => {\n this.drainScheduled = false;\n this.startAvailableJobs();\n });\n }\n\n private async runJob(\n job: PendingJob,\n startedAt: number,\n waitMs: number,\n ): Promise<void> {\n let error: unknown;\n\n try {\n await this.worker(job.sessionId, job.messages);\n } catch (err) {\n error = err;\n } finally {\n const finishedAt = Date.now();\n const runMs = finishedAt - startedAt;\n const totalMs = finishedAt - job.enqueuedAt;\n\n this.inFlight--;\n this.inFlightSessions.delete(job.sessionId);\n this.hooks.onJobFinish?.({\n sessionId: job.sessionId,\n depth: this.depth,\n inFlight: this.inFlight,\n waitMs,\n runMs,\n totalMs,\n error,\n });\n\n if (this.pending.size > 0) {\n this.scheduleDrain();\n } else {\n this.resolveIdleWaitersIfNeeded();\n }\n this.resolveSessionIdleWaitersIfNeeded(job.sessionId);\n }\n }\n\n private resolveIdleWaitersIfNeeded(): void {\n if (this.depth !== 0 || this.inFlight !== 0) return;\n\n const waiters = this.idleWaiters.splice(0, this.idleWaiters.length);\n for (const resolve of waiters) resolve();\n }\n\n private resolveSessionIdleWaitersIfNeeded(sessionId: string): void {\n if (this.pending.has(sessionId) || this.inFlightSessions.has(sessionId))\n return;\n\n const waiters = this.sessionIdleWaiters.get(sessionId);\n if (!waiters || waiters.length === 0) return;\n\n this.sessionIdleWaiters.delete(sessionId);\n for (const resolve of waiters) resolve();\n }\n}\n","import type Database from \"better-sqlite3\";\nimport { openLcmDatabase, ensureLcmStateDir } from \"./schema.js\";\nimport { LcmArchive, type LcmStructuredRecallMatch } from \"./archive.js\";\nimport { LcmDag } from \"./dag.js\";\nimport { LcmSummarizer, type SummarizeFn } from \"./summarizer.js\";\nimport { assembleCompressedHistory, type LcmRecallConfig } from \"./recall.js\";\nimport { LcmWorkQueue, type LcmObserveMessage } from \"./queue.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { log } from \"../logger.js\";\n\nexport interface LcmEngineConfig {\n enabled: boolean;\n leafBatchSize: number;\n rollupFanIn: number;\n freshTailTurns: number;\n maxDepth: number;\n deterministicMaxTokens: number;\n archiveRetentionDays: number;\n recallBudgetShare: number;\n messagePartsEnabled: boolean;\n messagePartsRecallMaxResults: number;\n}\n\nexport function extractLcmConfig(cfg: PluginConfig): LcmEngineConfig {\n return {\n enabled: (cfg as any).lcmEnabled === true,\n leafBatchSize: (cfg as any).lcmLeafBatchSize ?? 8,\n rollupFanIn: (cfg as any).lcmRollupFanIn ?? 4,\n freshTailTurns: (cfg as any).lcmFreshTailTurns ?? 16,\n maxDepth: (cfg as any).lcmMaxDepth ?? 5,\n deterministicMaxTokens: (cfg as any).lcmDeterministicMaxTokens ?? 512,\n archiveRetentionDays: (cfg as any).lcmArchiveRetentionDays ?? 90,\n recallBudgetShare: (cfg as any).lcmRecallBudgetShare ?? 0.15,\n messagePartsEnabled: (cfg as any).messagePartsEnabled === true,\n messagePartsRecallMaxResults:\n typeof (cfg as any).messagePartsRecallMaxResults === \"number\"\n ? Math.max(0, Math.floor((cfg as any).messagePartsRecallMaxResults))\n : 6,\n };\n}\n\nexport class LcmEngine {\n private db: Database.Database | null = null;\n private archive: LcmArchive | null = null;\n private dag: LcmDag | null = null;\n private summarizer: LcmSummarizer | null = null;\n private observeQueue: LcmWorkQueue | null = null;\n private closed = false;\n private readonly config: LcmEngineConfig;\n private readonly memoryDir: string;\n private initPromise: Promise<void> | null = null;\n private readonly pendingObserveInitCounts = new Map<string, number>();\n private readonly pendingObserveInitWaiters = new Map<string, Array<() => void>>();\n private readonly pendingObserveInitIdleWaiters: Array<() => void> = [];\n\n constructor(\n pluginConfig: PluginConfig,\n private readonly summarizeFn: SummarizeFn,\n ) {\n this.config = extractLcmConfig(pluginConfig);\n this.memoryDir = pluginConfig.memoryDir;\n }\n\n get enabled(): boolean {\n return this.config.enabled;\n }\n\n /** Lazy init — open database on first use. */\n async ensureInitialized(): Promise<void> {\n if (this.closed) return;\n if (this.db) return;\n if (this.initPromise) {\n await this.initPromise;\n return;\n }\n this.initPromise = this.doInit().catch((err) => {\n // Reset so next call retries instead of caching the failure\n this.initPromise = null;\n throw err;\n });\n await this.initPromise;\n }\n\n private async doInit(): Promise<void> {\n await ensureLcmStateDir(this.memoryDir);\n const db = openLcmDatabase(this.memoryDir);\n const archive = new LcmArchive(db);\n const dag = new LcmDag(db);\n const summarizer = new LcmSummarizer(\n archive,\n dag,\n this.summarizeFn,\n {\n leafBatchSize: this.config.leafBatchSize,\n rollupFanIn: this.config.rollupFanIn,\n maxDepth: this.config.maxDepth,\n deterministicMaxTokens: this.config.deterministicMaxTokens,\n },\n );\n const observeQueue = new LcmWorkQueue({\n concurrency: 1,\n worker: async (sessionId, messages) => {\n await this.processObserveMessages(sessionId, messages);\n },\n hooks: {\n onJobStart: ({ sessionId, depth, inFlight, waitMs }) => {\n log.debug(\n `LCM observe queue start: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms`,\n );\n },\n onJobFinish: ({\n sessionId,\n depth,\n inFlight,\n waitMs,\n runMs,\n totalMs,\n error,\n }) => {\n if (error) {\n log.error(\n `LCM observe queue failure: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms, run=${runMs}ms, total=${totalMs}ms, error=${error}`,\n );\n return;\n }\n\n log.debug(\n `LCM observe queue finish: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms, run=${runMs}ms, total=${totalMs}ms`,\n );\n },\n },\n });\n\n if (this.closed) {\n db.close();\n return;\n }\n\n this.db = db;\n this.archive = archive;\n this.dag = dag;\n this.summarizer = summarizer;\n this.observeQueue = observeQueue;\n log.info(\"LCM engine initialized\");\n }\n\n /**\n * Enqueue messages from agent_end hook.\n * The queue worker performs the archive append and incremental summarization.\n */\n async observeMessages(\n sessionId: string,\n messages: LcmObserveMessage[],\n ): Promise<void> {\n this.enqueueObserveMessages(sessionId, messages);\n }\n\n /** Enqueue an observe job without waiting for worker completion. */\n enqueueObserveMessages(\n sessionId: string,\n messages: LcmObserveMessage[],\n ): void {\n if (!this.config.enabled || this.closed) return;\n if (messages.length === 0) return;\n\n this.reservePendingObserveInit(sessionId);\n\n void this.ensureInitialized()\n .then(() => {\n if (this.closed || !this.observeQueue) return;\n this.observeQueue.enqueue(sessionId, messages);\n log.debug(\n `LCM observe enqueued: session=${sessionId}, depth=${this.observeQueue.depth}, inFlight=${this.observeQueue.inFlightCount}`,\n );\n })\n .catch((err) => {\n if (this.closed) return;\n log.error(`LCM observe enqueue initialization error: ${err}`);\n })\n .finally(() => {\n this.releasePendingObserveInit(sessionId);\n });\n }\n\n private async processObserveMessages(\n sessionId: string,\n messages: LcmObserveMessage[],\n ): Promise<void> {\n if (this.closed) return;\n await this.ensureInitialized();\n if (this.closed || !this.archive || !this.summarizer) return;\n\n if (messages.length === 0) return;\n\n const currentMax = this.archive.getMaxTurnIndex(sessionId);\n const newMessages = messages.map((m, i) => ({\n turnIndex: currentMax + 1 + i,\n role: m.role,\n content: m.content,\n parts: this.config.messagePartsEnabled ? m.parts : undefined,\n rawContent: this.config.messagePartsEnabled ? m.rawContent : undefined,\n sourceFormat: this.config.messagePartsEnabled ? m.sourceFormat : undefined,\n }));\n\n this.archive.appendMessages(sessionId, newMessages, {\n messagePartsEnabled: this.config.messagePartsEnabled,\n });\n\n // Trigger incremental summarization inside the worker, after append.\n try {\n await this.summarizer.summarizeIncremental(sessionId);\n } catch (err) {\n log.debug(`LCM incremental summarization error: ${err}`);\n }\n }\n\n get observeQueueDepth(): number {\n return this.observeQueue?.depth ?? 0;\n }\n\n get observeQueueInFlightCount(): number {\n return this.observeQueue?.inFlightCount ?? 0;\n }\n\n async waitForObserveQueueIdle(): Promise<void> {\n if (!this.config.enabled || this.closed) return;\n await this.ensureInitialized();\n if (this.closed) return;\n await this.waitForPendingObserveInitIdle();\n await this.observeQueue?.whenIdle();\n }\n\n async waitForSessionObserveIdle(sessionId: string): Promise<void> {\n if (!this.config.enabled || this.closed) return;\n await this.ensureInitialized();\n if (this.closed) return;\n await this.waitForPendingObserveInitIdle(sessionId);\n await this.observeQueue?.whenSessionIdle(sessionId);\n }\n\n private reservePendingObserveInit(sessionId: string): void {\n const count = this.pendingObserveInitCounts.get(sessionId) ?? 0;\n this.pendingObserveInitCounts.set(sessionId, count + 1);\n }\n\n private releasePendingObserveInit(sessionId: string): void {\n const count = this.pendingObserveInitCounts.get(sessionId);\n if (!count) return;\n\n if (count === 1) {\n this.pendingObserveInitCounts.delete(sessionId);\n const waiters = this.pendingObserveInitWaiters.get(sessionId) ?? [];\n this.pendingObserveInitWaiters.delete(sessionId);\n for (const resolve of waiters) resolve();\n if (this.pendingObserveInitCounts.size === 0) {\n const idleWaiters = this.pendingObserveInitIdleWaiters.splice(\n 0,\n this.pendingObserveInitIdleWaiters.length,\n );\n for (const resolve of idleWaiters) resolve();\n }\n return;\n }\n\n this.pendingObserveInitCounts.set(sessionId, count - 1);\n }\n\n private async waitForPendingObserveInitIdle(sessionId?: string): Promise<void> {\n if (sessionId) {\n if (!this.pendingObserveInitCounts.has(sessionId)) return;\n await new Promise<void>((resolve) => {\n const waiters = this.pendingObserveInitWaiters.get(sessionId) ?? [];\n waiters.push(resolve);\n this.pendingObserveInitWaiters.set(sessionId, waiters);\n });\n return;\n }\n\n if (this.pendingObserveInitCounts.size === 0) return;\n await new Promise<void>((resolve) => {\n this.pendingObserveInitIdleWaiters.push(resolve);\n });\n }\n\n /** Build the compressed history recall section for a session. */\n async assembleRecall(\n sessionId: string,\n budgetChars: number,\n ): Promise<string> {\n if (!this.config.enabled) return \"\";\n await this.ensureInitialized();\n\n const effectiveBudget = Math.ceil(\n budgetChars * this.config.recallBudgetShare,\n );\n if (effectiveBudget <= 0) return \"\";\n\n return assembleCompressedHistory(this.dag!, this.archive!, sessionId, {\n freshTailTurns: this.config.freshTailTurns,\n budgetChars: effectiveBudget,\n });\n }\n\n async searchStructuredParts(\n sessionId: string,\n query: string,\n limit = this.config.messagePartsRecallMaxResults,\n ): Promise<LcmStructuredRecallMatch[]> {\n if (!this.config.enabled || !this.config.messagePartsEnabled) return [];\n await this.ensureInitialized();\n if (!this.archive) return [];\n return this.archive.searchStructuredParts(query, limit, sessionId);\n }\n\n formatStructuredRecall(\n matches: LcmStructuredRecallMatch[],\n budgetChars: number,\n ): string {\n if (matches.length === 0 || budgetChars <= 0) return \"\";\n const lines: string[] = [];\n let used = \"## Structured Session Matches\\n\\n\".length;\n for (const match of matches) {\n const label = match.file_path\n ? `${match.kind} ${match.file_path}`\n : match.tool_name\n ? `${match.kind} ${match.tool_name}`\n : match.kind;\n const excerpt = match.content.replace(/\\s+/g, \" \").slice(0, 220);\n const line = `- turn ${match.turn_index} (${match.role}): ${label} — ${excerpt}`;\n if (used + line.length + 1 > budgetChars) break;\n lines.push(line);\n used += line.length + 1;\n }\n return lines.length > 0 ? `## Structured Session Matches\\n\\n${lines.join(\"\\n\")}` : \"\";\n }\n\n /** Flush pending summaries before compaction (called from before_compaction hook). */\n async preCompactionFlush(sessionId: string): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n try {\n await this.summarizer!.summarizeIncremental(sessionId);\n } catch (err) {\n log.debug(`LCM pre-compaction flush error: ${err}`);\n }\n }\n\n /** Record a compaction event with real token counts (called from after_compaction hook). */\n async recordCompaction(\n sessionId: string,\n tokensBefore: number,\n tokensAfter: number,\n ): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n const maxTurn = this.archive!.getMaxTurnIndex(sessionId);\n\n this.dag!.recordCompaction(sessionId, maxTurn, tokensBefore, tokensAfter);\n log.info(\n `LCM compaction recorded: session=${sessionId}, turn=${maxTurn}, tokens ${tokensBefore}→${tokensAfter}`,\n );\n }\n\n /** Verify archive coverage after compaction. */\n async verifyPostCompaction(sessionId: string): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n const msgCount = this.archive!.getMessageCount(sessionId);\n const nodeCount = this.dag!.getNodeCount(sessionId);\n log.debug(\n `LCM post-compaction verify: session=${sessionId}, messages=${msgCount}, summaryNodes=${nodeCount}`,\n );\n }\n\n // ── MCP Tool implementations ──\n\n /** Search across all conversation history via FTS (snippet mode). */\n async searchContext(\n query: string,\n limit: number,\n sessionId?: string,\n ): Promise<\n Array<{\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n }>\n > {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n return this.archive!.search(query, limit, sessionId);\n }\n\n /** Search via FTS returning full message content (not snippets). */\n async searchContextFull(\n query: string,\n limit: number,\n sessionId?: string,\n ): Promise<\n Array<{\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n score: number;\n }>\n > {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n return this.archive!.searchWithContent(query, limit, sessionId);\n }\n\n /** Get a compressed summary of a turn range. */\n async describeContext(\n sessionId: string,\n fromTurn: number,\n toTurn: number,\n ): Promise<{ summary: string; turn_count: number; depth: number } | null> {\n if (!this.config.enabled) return null;\n await this.ensureInitialized();\n\n const nodes = this.dag!.getCoveringNodes(sessionId, fromTurn, toTurn);\n if (nodes.length === 0) {\n // No summary exists — build a description from raw messages\n const messages = this.archive!.getMessages(sessionId, fromTurn, toTurn);\n if (messages.length === 0) return null;\n const preview = messages\n .slice(0, 5)\n .map((m) => `[${m.role}] ${m.content.slice(0, 100)}`)\n .join(\"\\n\");\n return {\n summary: `No summary available for this range. Preview of ${messages.length} messages:\\n${preview}`,\n turn_count: messages.length,\n depth: -1,\n };\n }\n\n // Use the deepest covering node\n const best = nodes[0]; // Already sorted by depth DESC\n return {\n summary: best.summary_text,\n turn_count: best.msg_end - best.msg_start + 1,\n depth: best.depth,\n };\n }\n\n /** Retrieve raw messages for a turn range (lossless expansion). */\n async expandContext(\n sessionId: string,\n fromTurn: number,\n toTurn: number,\n maxTokens: number,\n ): Promise<Array<{ turn_index: number; role: string; content: string }>> {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n\n const messages = this.archive!.getMessages(sessionId, fromTurn, toTurn);\n if (messages.length === 0) return [];\n\n // Enforce token budget — keep first and last, truncate middle\n const maxChars = maxTokens * 4;\n let totalChars = 0;\n for (const m of messages) totalChars += m.content.length;\n\n if (totalChars <= maxChars) {\n return messages.map((m) => ({\n turn_index: m.turn_index,\n role: m.role,\n content: m.content,\n }));\n }\n\n // Keep first and last messages, truncate from middle\n const result: Array<{ turn_index: number; role: string; content: string }> =\n [];\n let budget = maxChars;\n\n // Reserve space for the last message\n const lastMsg = messages[messages.length - 1];\n const lastMsgChars = Math.min(\n lastMsg.content.length,\n Math.floor(maxChars * 0.3),\n );\n budget -= lastMsgChars;\n\n // Add messages from the beginning\n for (let i = 0; i < messages.length - 1; i++) {\n if (budget <= 0) break;\n const m = messages[i];\n const truncated = m.content.slice(0, budget);\n result.push({\n turn_index: m.turn_index,\n role: m.role,\n content: truncated,\n });\n budget -= truncated.length;\n }\n\n // Always append the last message\n result.push({\n turn_index: lastMsg.turn_index,\n role: lastMsg.role,\n content: lastMsg.content.slice(0, lastMsgChars + Math.max(0, budget)),\n });\n\n return result;\n }\n\n /** Get statistics about the LCM archive. */\n async getStats(sessionId?: string): Promise<{\n totalMessages: number;\n totalSummaryNodes: number;\n maxDepth: number;\n }> {\n if (!this.config.enabled)\n return { totalMessages: 0, totalSummaryNodes: 0, maxDepth: -1 };\n await this.ensureInitialized();\n\n if (sessionId) {\n return {\n totalMessages: this.archive!.getMessageCount(sessionId),\n totalSummaryNodes: this.dag!.getNodeCount(sessionId),\n maxDepth: this.dag!.getMaxDepth(sessionId),\n };\n }\n\n return {\n totalMessages: this.archive!.getTotalMessageCount(),\n totalSummaryNodes: 0, // Would need a global count query\n maxDepth: -1,\n };\n }\n\n /** Prune old data beyond retention period. */\n async prune(): Promise<{ messagesPruned: number; nodesPruned: number }> {\n if (!this.config.enabled) return { messagesPruned: 0, nodesPruned: 0 };\n await this.ensureInitialized();\n\n const messagesPruned = this.archive!.pruneOldMessages(\n this.config.archiveRetentionDays,\n );\n const nodesPruned = this.dag!.pruneOldNodes(\n this.config.archiveRetentionDays,\n );\n return { messagesPruned, nodesPruned };\n }\n\n /** Close the database connection. */\n close(): void {\n this.closed = true;\n if (this.db) {\n this.db.close();\n }\n this.db = null;\n this.archive = null;\n this.dag = null;\n this.summarizer = null;\n this.observeQueue = null;\n this.initPromise = null;\n }\n}\n","import { Type } from \"@sinclair/typebox\";\nimport type { LcmEngine } from \"./engine.js\";\nimport { log } from \"../logger.js\";\n\ninterface ToolApi {\n registerTool(\n spec: {\n name: string;\n label: string;\n description: string;\n parameters: unknown;\n execute: (\n toolCallId: string,\n params: Record<string, unknown>,\n signal?: AbortSignal,\n ) => Promise<{ content: Array<{ type: string; text: string }>; details: undefined }>;\n },\n options: { name: string },\n ): void;\n}\n\nfunction toolResult(text: string) {\n return { content: [{ type: \"text\" as const, text }], details: undefined as undefined };\n}\n\nfunction registerAliasedTool(\n api: ToolApi,\n name: string,\n label: string,\n description: string,\n parameters: unknown,\n execute: (\n toolCallId: string,\n params: Record<string, unknown>,\n signal?: AbortSignal,\n ) => Promise<{ content: Array<{ type: string; text: string }>; details: undefined }>,\n): void {\n const aliases = [name];\n if (name.startsWith(\"engram_\")) {\n aliases.unshift(`remnic_${name.slice(\"engram_\".length)}`);\n }\n\n for (const alias of aliases) {\n api.registerTool(\n {\n name: alias,\n label,\n description,\n parameters,\n execute,\n },\n { name: alias },\n );\n }\n}\n\nexport function registerLcmTools(api: ToolApi, engine: LcmEngine): void {\n // engram.context_search — FTS search across conversation history\n registerAliasedTool(\n api,\n \"engram_context_search\",\n \"Search Conversation History\",\n \"Search all conversation history (including compacted regions) by keyword. Returns matching message snippets from the lossless context archive.\",\n Type.Object({\n query: Type.String({\n description: \"Search query — keywords or phrases\",\n }),\n limit: Type.Optional(\n Type.Number({\n description: \"Maximum results (default: 10)\",\n minimum: 1,\n maximum: 50,\n }),\n ),\n session_id: Type.Optional(\n Type.String({\n description: \"Limit search to a specific session\",\n }),\n ),\n }),\n async (_toolCallId, params) => {\n const query = params.query as string;\n const limit = (params.limit as number) ?? 10;\n const sessionId = params.session_id as string | undefined;\n\n const results = await engine.searchContext(query, limit, sessionId);\n\n if (results.length === 0) {\n return toolResult(`No results found for \"${query}\" in conversation history.`);\n }\n\n const formatted = results\n .map(\n (r, i) =>\n `${i + 1}. [${r.session_id}:${r.turn_index}] (${r.role})\\n ${r.snippet}`,\n )\n .join(\"\\n\\n\");\n\n return toolResult(\n `## Context Search: \"${query}\"\\n\\nFound ${results.length} result(s):\\n\\n${formatted}`,\n );\n },\n );\n\n // engram.context_describe — Get compressed summary of a turn range\n registerAliasedTool(\n api,\n \"engram_context_describe\",\n \"Describe Conversation Range\",\n \"Get a compressed summary of a conversation turn range. Uses the hierarchical summary DAG to provide the best available summary.\",\n Type.Object({\n session_id: Type.String({\n description: \"Session ID to describe\",\n }),\n from_turn: Type.Number({\n description: \"Start turn index\",\n minimum: 0,\n }),\n to_turn: Type.Number({\n description: \"End turn index\",\n minimum: 0,\n }),\n }),\n async (_toolCallId, params) => {\n const sessionId = params.session_id as string;\n const fromTurn = params.from_turn as number;\n const toTurn = params.to_turn as number;\n\n const result = await engine.describeContext(sessionId, fromTurn, toTurn);\n if (!result) {\n return toolResult(`No data found for session \"${sessionId}\" turns ${fromTurn}-${toTurn}.`);\n }\n\n return toolResult(\n `## Context Description (turns ${fromTurn}-${toTurn})\\n\\n` +\n `**Turns covered:** ${result.turn_count} | **Summary depth:** ${result.depth}\\n\\n` +\n result.summary,\n );\n },\n );\n\n // engram.context_expand — Retrieve raw messages (lossless)\n registerAliasedTool(\n api,\n \"engram_context_expand\",\n \"Expand Conversation Range\",\n \"Retrieve full conversation messages for a turn range (lossless). Use this to recover the exact content of messages that may have been compacted.\",\n Type.Object({\n session_id: Type.String({\n description: \"Session ID to expand\",\n }),\n from_turn: Type.Number({\n description: \"Start turn index\",\n minimum: 0,\n }),\n to_turn: Type.Number({\n description: \"End turn index\",\n minimum: 0,\n }),\n max_tokens: Type.Optional(\n Type.Number({\n description: \"Maximum tokens to return (default: 8000)\",\n minimum: 100,\n maximum: 32000,\n }),\n ),\n }),\n async (_toolCallId, params) => {\n const sessionId = params.session_id as string;\n const fromTurn = params.from_turn as number;\n const toTurn = params.to_turn as number;\n const maxTokens = (params.max_tokens as number) ?? 8000;\n\n const messages = await engine.expandContext(sessionId, fromTurn, toTurn, maxTokens);\n if (messages.length === 0) {\n return toolResult(\n `No messages found for session \"${sessionId}\" turns ${fromTurn}-${toTurn}.`,\n );\n }\n\n const formatted = messages\n .map((m) => `### Turn ${m.turn_index} (${m.role})\\n\\n${m.content}`)\n .join(\"\\n\\n---\\n\\n\");\n\n return toolResult(\n `## Context Expansion (turns ${fromTurn}-${toTurn})\\n\\n` +\n `**Messages:** ${messages.length}\\n\\n${formatted}`,\n );\n },\n );\n}\n","import type { TranscriptEntry } from \"../types.js\";\n\nexport interface ConversationChunk {\n id: string;\n sessionKey: string;\n startTs: string;\n endTs: string;\n text: string;\n}\n\nexport function chunkTranscriptEntries(\n sessionKey: string,\n entries: TranscriptEntry[],\n opts: { maxChars: number; maxTurns: number },\n): ConversationChunk[] {\n const maxChars = Math.max(500, opts.maxChars);\n const maxTurns = Math.max(5, opts.maxTurns);\n const sorted = [...entries].sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n const out: ConversationChunk[] = [];\n let buf: TranscriptEntry[] = [];\n let bufChars = 0;\n\n function flush(): void {\n if (buf.length === 0) return;\n const startTs = buf[0]!.timestamp;\n const endTs = buf[buf.length - 1]!.timestamp;\n const text = buf.map((e) => `[${e.role}] ${e.content}`).join(\"\\n\\n\");\n const id = `${startTs}-${out.length}`.replace(/[:.]/g, \"-\");\n out.push({ id, sessionKey, startTs, endTs, text });\n buf = [];\n bufChars = 0;\n }\n\n for (const e of sorted) {\n const line = `[${e.role}] ${e.content}\\n\\n`;\n if (buf.length >= maxTurns || bufChars + line.length > maxChars) {\n flush();\n }\n buf.push(e);\n bufChars += line.length;\n }\n flush();\n\n return out;\n}\n\n","import { readdir, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { log } from \"../logger.js\";\n\n/**\n * Best-effort retention cleanup for conversation chunk docs.\n *\n * Layout (written by indexer.ts):\n * <root>/<safeSessionKey>/<YYYY-MM-DD>/<chunkId>.md\n *\n * We prune day directories older than retentionDays, and remove empty session dirs.\n */\nexport async function cleanupConversationChunks(\n rootDir: string,\n retentionDays: number,\n): Promise<void> {\n if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;\n\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;\n\n try {\n const sessions = await readdir(rootDir, { withFileTypes: true });\n for (const s of sessions) {\n if (!s.isDirectory()) continue;\n const sessionDir = path.join(rootDir, s.name);\n const dayDirs = await readdir(sessionDir, { withFileTypes: true });\n\n for (const d of dayDirs) {\n if (!d.isDirectory()) continue;\n // Expect YYYY-MM-DD\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(d.name)) continue;\n const dayMs = new Date(d.name + \"T00:00:00.000Z\").getTime();\n if (!Number.isFinite(dayMs)) continue;\n if (dayMs < cutoffMs) {\n await rm(path.join(sessionDir, d.name), { recursive: true, force: true });\n }\n }\n\n // Remove empty session dirs after pruning.\n try {\n const remaining = await readdir(sessionDir);\n if (remaining.length === 0) {\n await rm(sessionDir, { recursive: true, force: true });\n }\n } catch {\n // ignore\n }\n }\n } catch (err) {\n log.debug(`conversation chunk cleanup failed: ${err}`);\n }\n}\n\n","/**\n * Coding-agent namespace overlay (issue #569 PR 2 + PR 3).\n *\n * Given a `CodingContext` (from `resolveGitContext`) and a `CodingModeConfig`,\n * returns the namespace that recall + write paths should use — or `null` when\n * no overlay should apply (coding mode disabled, no context supplied, or\n * feature flags off).\n *\n * PR 2 ships the project overlay. PR 3 will add the branch overlay; the\n * function here already handles both flags so the schema / types / plumbing\n * don't have to change a second time when branch-scope lands.\n *\n * Pure function — no orchestrator, no config side-effects. Callers keep rule\n * 42 (read + write through same namespace layer) by consulting the same\n * function on both paths.\n */\n\nimport type { CodingContext, CodingModeConfig } from \"../types.js\";\nimport { stableHash } from \"./git-context.js\";\n\nexport interface CodingNamespaceOverlay {\n /**\n * Effective namespace to use for this session's memory operations. When\n * `branchScope` is on, takes the form `project:<id>/branch:<b>`; otherwise\n * `project:<id>`.\n */\n namespace: string;\n /**\n * Read fallbacks — additional namespaces a caller should include in recall\n * so that, for example, a branch-scoped session still sees project-level\n * memories that were written before the branch scope was enabled.\n *\n * Writes MUST go to `namespace` only; these are read-side only.\n *\n * Introduced to carry PR 3's branch→project fallback; PR 2 returns an empty\n * array here.\n */\n readFallbacks: string[];\n /**\n * `\"project\"` when only project scope applies, `\"branch\"` when branch scope\n * is also layered on. Used for diagnostics (`remnic doctor`) and logging.\n */\n scope: \"project\" | \"branch\";\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Sanitization\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a projectId / branch fragment so the resulting namespace passes\n * the router's `isSafeRouteNamespace` check (`[A-Za-z0-9._-]{1,64}`).\n *\n * Namespaces are used as filesystem directory names and must not contain\n * path separators (`/`, `\\`) or colons — so both `:` and `/` collapse to `-`.\n * The project-id format `origin:<8hex>` and branch names like `feat/x` both\n * flow through this helper before hitting the storage layer.\n *\n * NOT a security boundary — projectIds come from `resolveGitContext` (known\n * hex), and branch names come from local git. This defends against corrupt\n * input only.\n */\n/**\n * Single-pass sanitization — each input character is visited exactly once.\n * Rewriting as an explicit loop (instead of chained `replace()` calls with\n * greedy quantifiers) closes the polynomial-backtracking surface that\n * CodeQL flagged on patterns like `-+` and `^-+|-+$`.\n */\nfunction sanitizeFragment(input: string): string {\n if (typeof input !== \"string\") return \"\";\n const trimmed = input.trim().toLowerCase();\n let out = \"\";\n let prevIsDash = true; // suppress leading dashes\n for (let i = 0; i < trimmed.length; i += 1) {\n const c = trimmed[i]!;\n const cc = trimmed.charCodeAt(i);\n const isSafe =\n (cc >= 48 && cc <= 57) /* 0-9 */ ||\n (cc >= 97 && cc <= 122) /* a-z */ ||\n cc === 46 /* . */ ||\n cc === 95 /* _ */;\n if (isSafe) {\n out += c;\n prevIsDash = false;\n } else if (!prevIsDash) {\n out += \"-\";\n prevIsDash = true;\n }\n }\n // Strip a single trailing dash introduced by the final run of unsafe chars.\n if (out.endsWith(\"-\")) out = out.slice(0, -1);\n return out;\n}\n\n/**\n * Cap to the router's per-namespace upper bound.\n *\n * Raw truncation alone would collapse distinct long inputs that differ near\n * the end (e.g. two `feat/...` branches with different suffixes) into the\n * same namespace — silently mixing recall/write state across branches or\n * projects. When truncation is needed, we append a short deterministic\n * hash suffix (`-<8hex>`) derived from the FULL pre-truncated value so\n * collisions only happen under true hash collisions, not simple prefix\n * overlap.\n *\n * The tail is trimmed to leave room for the separator and 8-char hash and\n * any trailing `-` introduced by the slice is stripped so the final\n * character before `-<hash>` is always alphanumeric or `.`/`_`.\n */\nconst MAX_NAMESPACE_LEN = 64;\nconst HASH_SUFFIX_LEN = 9; // \"-\" + 8 hex chars\n\nfunction capLength(value: string): string {\n if (value.length <= MAX_NAMESPACE_LEN) return value;\n // Reuse the FNV-1a 32-bit hash from git-context — one canonical\n // implementation, one set of edge-case fixes. Uses Math.imul for\n // correct 32-bit wrap-around, which plain `*` would not guarantee\n // for the largest intermediate products.\n const hash = stableHash(value);\n // Trim trailing '-' with a linear, non-backtracking loop. A regex\n // like `-+$` is linear too, but an explicit loop keeps CodeQL happy\n // about polynomial backtracking warnings when several `\\-+` patterns\n // appear in the same module.\n let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;\n while (end > 0 && value.charCodeAt(end - 1) === 45 /* '-' */) end -= 1;\n return `${value.slice(0, end)}-${hash}`;\n}\n\n/**\n * Produce the project-scope namespace name. Exported for tests and for\n * `remnic doctor` to render. Guaranteed to satisfy `isSafeRouteNamespace`:\n * no `/`, no `:`, lowercase only, length-capped to 64 chars.\n */\nexport function projectNamespaceName(projectId: string): string {\n const frag = sanitizeFragment(projectId);\n return capLength(`project-${frag || \"unknown\"}`);\n}\n\n/**\n * Preserve case when sanitizing a principal-derived base namespace. The\n * router's `isSafeRouteNamespace` check accepts `[A-Za-z0-9._-]{1,64}`, so\n * upper-case characters in the principal name are safe and MUST be kept to\n * avoid colliding two otherwise-distinct principals (e.g. `Alice` vs\n * `alice`) into the same combined namespace.\n *\n * Otherwise identical to `sanitizeFragment`: single-pass, linear, no\n * polynomial-backtracking quantifiers, unsafe chars collapse to `-` with\n * leading/trailing dashes suppressed.\n */\nfunction sanitizeBaseFragment(input: string): string {\n if (typeof input !== \"string\") return \"\";\n const trimmed = input.trim();\n let out = \"\";\n let prevIsDash = true;\n for (let i = 0; i < trimmed.length; i += 1) {\n const c = trimmed[i]!;\n const cc = trimmed.charCodeAt(i);\n const isSafe =\n (cc >= 48 && cc <= 57) /* 0-9 */ ||\n (cc >= 65 && cc <= 90) /* A-Z */ ||\n (cc >= 97 && cc <= 122) /* a-z */ ||\n cc === 46 /* . */ ||\n cc === 95 /* _ */;\n if (isSafe) {\n out += c;\n prevIsDash = false;\n } else if (!prevIsDash) {\n out += \"-\";\n prevIsDash = true;\n }\n }\n if (out.endsWith(\"-\")) out = out.slice(0, -1);\n return out;\n}\n\n/**\n * Combine a principal-derived base namespace (e.g. `default`, `alice`) with a\n * coding-agent overlay namespace (e.g. `project-origin-abcd1234`). The result\n * is a single safe-route token that preserves principal isolation (CLAUDE.md\n * rule 42: read + write must resolve through the same namespace layer — and\n * here, through the same principal-scoped prefix) while layering project or\n * project/branch scope on top.\n *\n * Multiple principals working in the same repo thus get distinct namespaces:\n *\n * alice + project-origin-ab12 → alice-project-origin-ab12\n * bob + project-origin-ab12 → bob-project-origin-ab12\n * Alice + project-origin-ab12 → Alice-project-origin-ab12 (distinct)\n *\n * The base fragment preserves case so `Alice` and `alice` remain distinct;\n * the overlay fragment is still lowercase-sanitized because it derives from\n * deterministic, pre-lowercased git hashes.\n *\n * Output is re-capped through `capLength` so a very long base + overlay\n * combination still fits inside `isSafeRouteNamespace` (≤ 64 chars). The\n * deterministic hash suffix on truncation keeps distinct inputs distinct.\n */\nexport function combineNamespaces(base: string, overlay: string): string {\n const baseFrag = sanitizeBaseFragment(base);\n const overlayFrag = sanitizeFragment(overlay);\n if (!baseFrag) return capLength(overlayFrag || \"unknown\");\n if (!overlayFrag) return capLength(baseFrag);\n return capLength(`${baseFrag}-${overlayFrag}`);\n}\n\n/**\n * Produce the branch-scope namespace name. Format:\n * `project-<id>-branch-<name>[-<hash>]`. Uses `-` as the structural separator\n * rather than `/` or `:` so the result is a single safe route-namespace\n * token that can be used directly as a filesystem directory.\n *\n * Two failure modes must not collapse distinct branches to one namespace:\n *\n * 1. Sanitization is lossy (`feat/x` and `feat-x` both sanitize to\n * `feat-x`; `Feature` and `feature` both sanitize to `feature`). When\n * sanitization rewrote any character, we append a short hash of the\n * RAW branch so distinct inputs stay distinct.\n * 2. Truncation is applied when the total exceeds 64 chars. In that\n * mode `capLength` appends its own hash of the full pre-truncated\n * value.\n *\n * Long branches that also sanitize may receive both kinds of hashes — that\n * is acceptable: the router only requires the result be unique and\n * deterministic, and the two hashes derive from different domains so they\n * don't conflict.\n */\nexport function branchNamespaceName(projectId: string, branch: string): string {\n const projectFrag = sanitizeFragment(projectId);\n const trimmedBranch = branch.trim();\n const branchFrag = sanitizeFragment(trimmedBranch);\n // Lossy-sanitization disambiguator: append hash of the raw (trimmed)\n // branch when sanitization actually changed the string. Preserves\n // distinctness across `feat/x` vs `feat-x` and `Feature` vs `feature`.\n // The comparison uses the raw trimmed value (NOT `.toLowerCase()`) so\n // case-only variants are treated as lossy and receive their own hash.\n // Empty / already-safe-lowercase inputs get no hash so the common case\n // stays readable.\n const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;\n const base = `project-${projectFrag || \"unknown\"}-branch-${branchFrag || \"unknown\"}`;\n const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;\n return capLength(suffixed);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Overlay resolver\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute the namespace overlay for a session.\n *\n * Returns `null` when no overlay applies — callers should then use their\n * existing `defaultNamespaceForPrincipal(...)` result unchanged. This keeps\n * CLAUDE.md #30 (escape hatch): setting `codingMode.projectScope: false`\n * exactly restores pre-#569 behaviour at every call site.\n *\n * @param codingContext — git context from the connector\n * @param config — coding mode flags (projectScope, branchScope, globalFallback)\n * @param defaultNamespace — retained for call-site compatibility; no longer\n * used. The global fallback is expressed as an empty-string sentinel in\n * `readFallbacks`, which `combineNamespaces(principal, \"\")` resolves to the\n * principal's own namespace at the call site.\n */\nexport function resolveCodingNamespaceOverlay(\n codingContext: CodingContext | null | undefined,\n config: Pick<CodingModeConfig, \"projectScope\" | \"branchScope\" | \"globalFallback\">,\n defaultNamespace?: string,\n): CodingNamespaceOverlay | null {\n // No context supplied (session isn't in a git repo, or connector didn't\n // attach one) → no overlay.\n if (!codingContext) return null;\n\n // Project scope disabled → no overlay at all. Branch scope depends on\n // project scope being on; there is no branch-only mode.\n if (!config.projectScope) return null;\n\n // Require a non-empty projectId — defensive.\n const projectId = typeof codingContext.projectId === \"string\" ? codingContext.projectId.trim() : \"\";\n if (!projectId) return null;\n\n const projectNs = projectNamespaceName(projectId);\n\n // Root/global namespace fallback: when `globalFallback` is true, include\n // the principal's self namespace in readFallbacks so cross-project knowledge\n // remains visible. CLAUDE.md #30: the gate is `globalFallback` — set to\n // false for strict project isolation.\n //\n // The fallback value is \"\" (empty string), NOT the defaultNamespace name.\n // The orchestrator passes each fallback through combineNamespaces(principal, fallback),\n // and combineNamespaces(base, \"\") returns base unchanged — yielding the\n // principal's own namespace. Using the actual namespace name (e.g., \"default\")\n // would produce \"default-default\" after combination, missing the target.\n const includeRoot = config.globalFallback === true;\n\n // Branch-scope layering (PR 3):\n // - only when config.branchScope is explicitly true\n // - only when we actually have a branch (null in detached HEAD)\n // - project namespace becomes a read fallback so project-level memories\n // remain visible from any branch (deliberate asymmetry — branch writes\n // don't leak up, but project reads leak down).\n // - when globalFallback is on, the root namespace is also appended so\n // globally useful memories surface in every branch.\n if (config.branchScope && typeof codingContext.branch === \"string\" && codingContext.branch.length > 0) {\n const branchNs = branchNamespaceName(projectId, codingContext.branch);\n const fallbacks = [projectNs];\n if (includeRoot) fallbacks.push(\"\");\n return {\n namespace: branchNs,\n readFallbacks: fallbacks,\n scope: \"branch\",\n };\n }\n\n return {\n namespace: projectNs,\n readFallbacks: includeRoot ? [\"\"] : [],\n scope: \"project\",\n };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Diagnostics (issue #569 PR 3 + PR 8)\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface CodingScopeDescription {\n /** \"none\" when no overlay is active; otherwise the resolved scope level. */\n scope: \"none\" | \"project\" | \"branch\";\n /** Project id (raw, not sanitized) when a context is attached. */\n projectId: string | null;\n /** Branch name (raw, not sanitized) when available. */\n branch: string | null;\n /** Effective namespace writes route to. `null` when no overlay applies. */\n effectiveNamespace: string | null;\n /** Read fallbacks included in recall (non-empty only when branch-scope is on). */\n readFallbacks: string[];\n /**\n * Why no overlay applies, when `scope === \"none\"`. One of:\n * - `\"no-context\"` — connector didn't attach a CodingContext\n * - `\"disabled\"` — codingMode.projectScope is false\n * - `\"empty-project\"` — codingContext.projectId was empty/whitespace\n */\n disabledReason: \"no-context\" | \"disabled\" | \"empty-project\" | null;\n}\n\n/**\n * Human-readable description of the coding-agent scope that currently applies\n * for a session. Consumed by `remnic doctor` (PR 8) and by logs to surface\n * why recall routes where it does.\n *\n * Pure — callers pass the coding context + config they already have.\n */\nexport function describeCodingScope(\n codingContext: CodingContext | null | undefined,\n config: Pick<CodingModeConfig, \"projectScope\" | \"branchScope\" | \"globalFallback\">,\n defaultNamespace?: string,\n): CodingScopeDescription {\n const projectId = codingContext?.projectId ?? null;\n const branch = codingContext?.branch ?? null;\n\n if (!codingContext) {\n return {\n scope: \"none\",\n projectId: null,\n branch: null,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"no-context\",\n };\n }\n if (!config.projectScope) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"disabled\",\n };\n }\n const trimmedId = typeof projectId === \"string\" ? projectId.trim() : \"\";\n if (!trimmedId) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"empty-project\",\n };\n }\n\n const overlay = resolveCodingNamespaceOverlay(codingContext, config, defaultNamespace);\n // Unreachable in practice given the guards above, but keep the return\n // shape consistent if the resolver grows new null branches later.\n if (!overlay) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"disabled\",\n };\n }\n return {\n scope: overlay.scope,\n projectId,\n branch,\n effectiveNamespace: overlay.namespace,\n readFallbacks: overlay.readFallbacks,\n disabledReason: null,\n };\n}\n"],"mappings":"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","names":["path","createHash","existsSync","mkdir","readdir","readFile","stat","unlink","writeFile","legacyEntries","rewritten","mkdir","readFile","rm","stat","writeFile","path","lockPath","readFile","mkdir","writeFile","path","path","readFile","mkdir","writeFile","path","mkdir","path","mkdir","paths","sessionId","readdir","rm","path","readdir","path","rm","createHash","path","buildCompressionGuidelinesMarkdown","result","readdir","stat","unlink","existsSync","readFile","writeFile","mkdir","FallbackLlmClient","llm","capped","profile","outcome","throwIfAborted","options","memoryKind"]}