@remnic/core 9.3.749 → 9.3.751
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-boundary.d.ts +8 -8
- package/dist/access-boundary.js +15 -15
- package/dist/access-cli.js +39 -39
- package/dist/access-http.d.ts +8 -8
- package/dist/access-http.js +20 -20
- package/dist/access-mcp.d.ts +8 -8
- package/dist/access-mcp.js +19 -19
- package/dist/access-operations-batch.js +16 -16
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +18 -18
- package/dist/access-schema.d.ts +2 -2
- package/dist/access-schema.js +5 -5
- package/dist/{access-service-5-EVpt3v.d.ts → access-service-DmAEOJdJ.d.ts} +11 -3
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +14 -14
- package/dist/access-surface-catalog.d.ts +8 -8
- package/dist/action-confidence.d.ts +1 -1
- package/dist/active-memory-bridge.d.ts +1 -1
- package/dist/active-recall.d.ts +1 -1
- package/dist/active-recall.js +8 -1
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.d.ts +1 -1
- package/dist/behavior-signals.d.ts +1 -1
- package/dist/bootstrap.d.ts +7 -7
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +7 -7
- package/dist/buffer-surprise-report.d.ts +1 -1
- package/dist/buffer.d.ts +1 -1
- package/dist/calibration.d.ts +1 -1
- package/dist/capabilities.d.ts +1 -1
- package/dist/{catalog-D_ZDxu8Y.d.ts → catalog-BpOcwHdE.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +1 -1
- package/dist/causal-consolidation.d.ts +1 -1
- package/dist/causal-consolidation.js +8 -8
- package/dist/causal-trajectory-graph.d.ts +1 -1
- package/dist/{chunk-C5WN74HH.js → chunk-2HAG7JOI.js} +8 -2
- package/dist/chunk-2HAG7JOI.js.map +1 -0
- package/dist/{chunk-GKRLPHPU.js → chunk-2KK5WNQB.js} +2 -2
- package/dist/{chunk-JRDPT6DA.js → chunk-4NWIGAIC.js} +2 -2
- package/dist/{chunk-OBJUKYDO.js → chunk-4XL3CVII.js} +2 -2
- package/dist/{chunk-WWVXXSLF.js → chunk-5PZCDUJ6.js} +4 -4
- package/dist/{chunk-URQLO7BX.js → chunk-6FNZ3NMS.js} +2 -2
- package/dist/{chunk-DRUDC2UX.js → chunk-6MMONPHM.js} +2 -2
- package/dist/{chunk-RB6A7OUN.js → chunk-6SXNQFHB.js} +2 -2
- package/dist/{chunk-ZGZNLRKF.js → chunk-7TWA7DKP.js} +5 -5
- package/dist/{chunk-KMNYXLPL.js → chunk-B35L45HZ.js} +2 -2
- package/dist/{chunk-SIV3JZPP.js → chunk-CGZWGVQF.js} +5 -5
- package/dist/{chunk-CKFLLAIS.js → chunk-DANV2HTH.js} +3 -3
- package/dist/{chunk-NVYF5OB6.js → chunk-DBRVU5PR.js} +3 -3
- package/dist/{chunk-LMFS64GY.js → chunk-E4PFDD3N.js} +4 -4
- package/dist/{chunk-DIHCFJVV.js → chunk-HYI2GP3F.js} +4 -4
- package/dist/{chunk-UIKZZ242.js → chunk-IKHKHADN.js} +2 -2
- package/dist/{chunk-PUR2CKX2.js → chunk-JS2HKKOK.js} +1 -1
- package/dist/{chunk-PUR2CKX2.js.map → chunk-JS2HKKOK.js.map} +1 -1
- package/dist/{chunk-R2OAN6IP.js → chunk-K2JM4DZZ.js} +2 -2
- package/dist/{chunk-3IJGF6K2.js → chunk-K2R3DEEH.js} +2 -2
- package/dist/{chunk-HIHCB2S6.js → chunk-QRRBXD24.js} +2 -2
- package/dist/{chunk-PNUOQYRJ.js → chunk-RWZB6MAY.js} +1953 -2172
- package/dist/chunk-RWZB6MAY.js.map +1 -0
- package/dist/{chunk-ZPZ4VVLT.js → chunk-SD34EK4Z.js} +2 -2
- package/dist/{chunk-WK3NK6SP.js → chunk-SNEXVX3U.js} +6 -6
- package/dist/{chunk-FVZ2ISIX.js → chunk-TPLE6SNY.js} +7 -7
- package/dist/{chunk-24YDB5QP.js → chunk-UETBEHBA.js} +44 -24
- package/dist/chunk-UETBEHBA.js.map +1 -0
- package/dist/{chunk-5IN26V6W.js → chunk-UU32EAIY.js} +5 -5
- package/dist/{chunk-ZGAJB74V.js → chunk-W3BFT5OJ.js} +2 -2
- package/dist/{chunk-L4N7SVNN.js → chunk-WA7FECSG.js} +11 -11
- package/dist/{chunk-Q3X7GUAQ.js → chunk-WOX2UW4K.js} +2 -2
- package/dist/{chunk-XTEWVF3C.js → chunk-WWSXVOGY.js} +2 -2
- package/dist/{chunk-PWWWLD7D.js → chunk-X64YLC24.js} +153 -27
- package/dist/chunk-X64YLC24.js.map +1 -0
- package/dist/{chunk-P4FW3ZU5.js → chunk-YGGXUNS4.js} +20 -20
- package/dist/{chunk-JHQUIH3W.js → chunk-ZBVQ4ZM4.js} +19 -19
- package/dist/{cli-DuWWjaKT.d.ts → cli-lmf5RGyQ.d.ts} +3 -3
- package/dist/cli.d.ts +9 -9
- package/dist/cli.js +33 -33
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +7 -7
- package/dist/compounding/preference-consolidator.d.ts +1 -1
- package/dist/compression-optimizer.d.ts +1 -1
- package/dist/config.d.ts +1 -1
- package/dist/config.js +8 -1
- package/dist/connectors/codex-materialize-runner.d.ts +1 -1
- package/dist/connectors/codex-materialize-runner.js +7 -7
- package/dist/connectors/codex-materialize.d.ts +1 -1
- package/dist/connectors/index.d.ts +1 -1
- package/dist/connectors/index.js +7 -7
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/conversation-index/backend.d.ts +1 -1
- package/dist/conversation-index/chunker.d.ts +1 -1
- package/dist/conversation-index/faiss-adapter.d.ts +1 -1
- package/dist/conversation-index/indexer.d.ts +1 -1
- package/dist/conversation-index/search.d.ts +1 -1
- package/dist/day-summary.d.ts +1 -1
- package/dist/delinearize.d.ts +1 -1
- package/dist/direct-answer-wiring.d.ts +1 -1
- package/dist/direct-answer.d.ts +1 -1
- package/dist/embedding-fallback.d.ts +1 -1
- package/dist/enrichment/index.d.ts +1 -1
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +7 -7
- package/dist/entity-schema.d.ts +1 -1
- package/dist/explicit-capture.d.ts +7 -7
- package/dist/extraction-faithfulness.d.ts +1 -1
- package/dist/extraction-judge-telemetry.d.ts +1 -1
- package/dist/extraction-judge-training.d.ts +1 -1
- package/dist/extraction-judge.d.ts +1 -1
- package/dist/extraction.d.ts +1 -1
- package/dist/fallback-llm.d.ts +1 -1
- package/dist/graph-dashboard-diff.d.ts +1 -1
- package/dist/graph-dashboard-key.d.ts +1 -1
- package/dist/graph-dashboard-parser.d.ts +1 -1
- package/dist/graph-edge-reinforcement.d.ts +1 -1
- package/dist/graph-snapshot.d.ts +1 -1
- package/dist/graph.d.ts +1 -1
- package/dist/identity-continuity.d.ts +1 -1
- package/dist/importance.d.ts +1 -1
- package/dist/index.d.ts +10 -10
- package/dist/index.js +76 -72
- package/dist/intent.d.ts +1 -1
- package/dist/lcm/engine.d.ts +1 -1
- package/dist/lcm/index.d.ts +1 -1
- package/dist/lcm/tools.d.ts +1 -1
- package/dist/lifecycle.d.ts +1 -1
- package/dist/live-connectors-runner.d.ts +1 -1
- package/dist/local-llm.d.ts +1 -1
- package/dist/local-model-endpoint.d.ts +1 -1
- package/dist/maintenance/memory-governance.d.ts +1 -1
- package/dist/maintenance/memory-governance.js +7 -7
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +7 -7
- package/dist/maintenance/rebuild-memory-projection.js +8 -8
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-action-policy.d.ts +1 -1
- package/dist/memory-cache.d.ts +1 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +1 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-provenance.d.ts +1 -1
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/models-json.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +2 -2
- package/dist/namespaces/migrate.js +8 -8
- package/dist/namespaces/principal.d.ts +1 -1
- package/dist/namespaces/search.d.ts +1 -1
- package/dist/namespaces/search.js +1 -1
- package/dist/namespaces/storage.d.ts +2 -2
- package/dist/namespaces/storage.js +7 -7
- package/dist/native-knowledge.d.ts +1 -1
- package/dist/offline-sync.d.ts +108 -1
- package/dist/offline-sync.js +7 -1
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +15 -12
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +9 -9
- package/dist/{orchestrator-CZI6hO_R.d.ts → orchestrator-D7bb8ZGp.d.ts} +193 -201
- package/dist/orchestrator.d.ts +5 -5
- package/dist/orchestrator.js +51 -41
- package/dist/patterns-cli.d.ts +1 -1
- package/dist/policy-runtime.d.ts +1 -1
- package/dist/provenance.d.ts +1 -1
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd.d.ts +1 -1
- package/dist/recall-disclosure-escalation.d.ts +1 -1
- package/dist/recall-explain-renderer.d.ts +1 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-planner-llm.d.ts +1 -1
- package/dist/recall-state.d.ts +1 -1
- package/dist/recall-tag-filter.d.ts +1 -1
- package/dist/recall-xray-cli.d.ts +1 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +1 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +1 -1
- package/dist/recall-xray.js +2 -2
- package/dist/resolve-auth-token.d.ts +1 -1
- package/dist/resume-bundles.js +9 -2
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-tiers.d.ts +1 -1
- package/dist/routing/engine.d.ts +1 -1
- package/dist/routing/store.d.ts +1 -1
- package/dist/schemas.d.ts +22 -22
- package/dist/search/embed-helper.d.ts +1 -1
- package/dist/search/factory.d.ts +1 -1
- package/dist/search/factory.js +1 -1
- package/dist/search/index.d.ts +1 -1
- package/dist/search/index.js +1 -1
- package/dist/search/lancedb-backend.d.ts +1 -1
- package/dist/search/lancedb-backend.js +1 -1
- package/dist/search/meilisearch-backend.d.ts +1 -1
- package/dist/search/meilisearch-backend.js +1 -1
- package/dist/search/noop-backend.d.ts +1 -1
- package/dist/search/orama-backend.d.ts +1 -1
- package/dist/search/orama-backend.js +1 -1
- package/dist/search/port.d.ts +1 -1
- package/dist/search/remote-backend.d.ts +1 -1
- package/dist/{semantic-consolidation-D3aSiu9t.d.ts → semantic-consolidation-CTfbVwCA.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +8 -8
- package/dist/semantic-rule-promotion.js +7 -7
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +7 -7
- package/dist/session-observer-bands.d.ts +1 -1
- package/dist/session-observer-state.d.ts +1 -1
- package/dist/shared-context/manager.d.ts +1 -1
- package/dist/signal.d.ts +1 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +6 -6
- package/dist/summarizer.d.ts +1 -1
- package/dist/summary-snapshot.d.ts +1 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-validity.d.ts +1 -1
- package/dist/threading.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-routing.d.ts +1 -1
- package/dist/topics.d.ts +1 -1
- package/dist/transcript.d.ts +1 -1
- package/dist/transfer/types.d.ts +12 -12
- package/dist/trust-score-stage.d.ts +1 -1
- package/dist/trust-score.d.ts +1 -1
- package/dist/{types-CZm6rx9-.d.ts → types-D4NYDtXI.d.ts} +7 -0
- package/dist/types.d.ts +1 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +1 -1
- package/dist/verified-recall.js +7 -7
- package/package.json +2 -2
- package/src/access-service.ts +22 -0
- package/src/config.ts +5 -0
- package/src/index.ts +3 -1
- package/src/offline-sync.test.ts +354 -52
- package/src/offline-sync.ts +332 -24
- package/src/orchestration/extraction-run.ts +4 -34
- package/src/orchestration/namespace-read-fanout.ts +484 -0
- package/src/orchestration/orchestrator-helpers.ts +1130 -0
- package/src/orchestration/self-deps.ts +50 -0
- package/src/orchestration/workspace-ops.ts +789 -0
- package/src/orchestrator.ts +177 -2296
- package/src/types.ts +9 -0
- package/dist/chunk-24YDB5QP.js.map +0 -1
- package/dist/chunk-C5WN74HH.js.map +0 -1
- package/dist/chunk-PNUOQYRJ.js.map +0 -1
- package/dist/chunk-PWWWLD7D.js.map +0 -1
- /package/dist/{chunk-GKRLPHPU.js.map → chunk-2KK5WNQB.js.map} +0 -0
- /package/dist/{chunk-JRDPT6DA.js.map → chunk-4NWIGAIC.js.map} +0 -0
- /package/dist/{chunk-OBJUKYDO.js.map → chunk-4XL3CVII.js.map} +0 -0
- /package/dist/{chunk-WWVXXSLF.js.map → chunk-5PZCDUJ6.js.map} +0 -0
- /package/dist/{chunk-URQLO7BX.js.map → chunk-6FNZ3NMS.js.map} +0 -0
- /package/dist/{chunk-DRUDC2UX.js.map → chunk-6MMONPHM.js.map} +0 -0
- /package/dist/{chunk-RB6A7OUN.js.map → chunk-6SXNQFHB.js.map} +0 -0
- /package/dist/{chunk-ZGZNLRKF.js.map → chunk-7TWA7DKP.js.map} +0 -0
- /package/dist/{chunk-KMNYXLPL.js.map → chunk-B35L45HZ.js.map} +0 -0
- /package/dist/{chunk-SIV3JZPP.js.map → chunk-CGZWGVQF.js.map} +0 -0
- /package/dist/{chunk-CKFLLAIS.js.map → chunk-DANV2HTH.js.map} +0 -0
- /package/dist/{chunk-NVYF5OB6.js.map → chunk-DBRVU5PR.js.map} +0 -0
- /package/dist/{chunk-LMFS64GY.js.map → chunk-E4PFDD3N.js.map} +0 -0
- /package/dist/{chunk-DIHCFJVV.js.map → chunk-HYI2GP3F.js.map} +0 -0
- /package/dist/{chunk-UIKZZ242.js.map → chunk-IKHKHADN.js.map} +0 -0
- /package/dist/{chunk-R2OAN6IP.js.map → chunk-K2JM4DZZ.js.map} +0 -0
- /package/dist/{chunk-3IJGF6K2.js.map → chunk-K2R3DEEH.js.map} +0 -0
- /package/dist/{chunk-HIHCB2S6.js.map → chunk-QRRBXD24.js.map} +0 -0
- /package/dist/{chunk-ZPZ4VVLT.js.map → chunk-SD34EK4Z.js.map} +0 -0
- /package/dist/{chunk-WK3NK6SP.js.map → chunk-SNEXVX3U.js.map} +0 -0
- /package/dist/{chunk-FVZ2ISIX.js.map → chunk-TPLE6SNY.js.map} +0 -0
- /package/dist/{chunk-5IN26V6W.js.map → chunk-UU32EAIY.js.map} +0 -0
- /package/dist/{chunk-ZGAJB74V.js.map → chunk-W3BFT5OJ.js.map} +0 -0
- /package/dist/{chunk-L4N7SVNN.js.map → chunk-WA7FECSG.js.map} +0 -0
- /package/dist/{chunk-Q3X7GUAQ.js.map → chunk-WOX2UW4K.js.map} +0 -0
- /package/dist/{chunk-XTEWVF3C.js.map → chunk-WWSXVOGY.js.map} +0 -0
- /package/dist/{chunk-P4FW3ZU5.js.map → chunk-YGGXUNS4.js.map} +0 -0
- /package/dist/{chunk-JHQUIH3W.js.map → chunk-ZBVQ4ZM4.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/orchestrator.ts","../src/orchestration/tier-migration-coordinator.ts","../src/orchestration/extraction-queue-coordinator.ts","../src/orchestration/semantic-consolidation-coordinator.ts","../src/orchestration/lifecycle-policy-coordinator.ts","../src/orchestration/entity-synthesis-coordinator.ts","../src/orchestration/recall-result-formatter.ts","../src/orchestration/conversation-index-coordinator.ts","../src/orchestration/recall-rerank-coordinator.ts","../src/orchestration/recall-section-coordinator.ts","../src/orchestration/qmd-result-resolver.ts","../src/orchestration/contradiction-linking-coordinator.ts","../src/orchestration/extraction-run.ts","../src/orchestration/orchestrator-helpers.ts","../src/orchestration/consolidation-run.ts","../src/dedup/semantic.ts","../src/orchestration/extraction-persist.ts","../src/orchestration/recall-internal.ts","../src/orchestration/graph-recall-coordinator.ts","../src/procedural/procedure-recall.ts","../src/orchestration/recall-search-pipeline.ts","../src/recall/archive-scoring.ts","../src/orchestration/turn-ingestion.ts","../src/orchestration/recall-introspection.ts","../src/taxonomy/default-taxonomy.ts","../src/taxonomy/resolver-doc-generator.ts","../src/taxonomy/taxonomy-loader.ts","../src/orchestration/orchestrator-init.ts","../src/orchestration/persistence-index.ts","../src/orchestration/workspace-ops.ts","../src/maintenance/pattern-reinforcement.ts","../src/wearables/registry.ts","../src/wearables/service.ts","../src/orchestration/namespace-read-fanout.ts","../src/orchestration/self-deps.ts","../src/coding/review-context.ts","../src/coding/structural-context.ts","../src/coding/structural-subprocess-provider.ts","../src/binary-lifecycle/types.ts","../src/binary-lifecycle/backend.ts","../src/binary-lifecycle/scanner.ts","../src/binary-lifecycle/manifest.ts","../src/binary-lifecycle/pipeline.ts","../src/projection/index.ts","../src/onboarding/index.ts","../src/curation/index.ts","../src/dedup/index.ts","../src/review/index.ts","../src/sync/index.ts","../src/spaces/index.ts","../src/memory-extension/shared-instructions.ts","../src/memory-extension/codex-publisher.ts","../src/memory-extension/claude-code-publisher.ts","../src/memory-extension/hermes-publisher.ts","../src/memory-extension/index.ts","../src/session-summaries/index.ts","../src/session-summaries/adapters.ts","../src/session-summaries/redaction.ts","../src/transfer/capsule-fork.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport {\n buildChainFollowupGenerator,\n type BriefingFollowupGenerator,\n} from \"./briefing.js\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { existsSync, readFileSync } from \"node:fs\";\nimport {\n lstat,\n mkdir,\n readdir,\n readFile,\n realpath,\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 { detectPassiveCorrections } from \"./correction/passive-correction-detector.js\";\nimport { capturePassiveCorrections, type PassiveCaptureConfig } from \"./correction/passive-capture.js\";\nimport { createCorrectionService } from \"./correction/correction-access-wiring.js\";\nimport type { CorrectionService } from \"./correction/correction-service.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 applyFaithfulnessVerdict,\n createFaithfulnessCounters,\n runFaithfulnessGateBatch,\n} from \"./extraction-faithfulness.js\";\nimport {\n contentMatchesRedactionRules,\n loadRedactionRules,\n type CompiledRedactionRule,\n} from \"./extraction-redaction-rules.js\";\nimport type { FaithfulnessGateCounters } from \"./extraction-faithfulness.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 SearchDegradation,\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 StorageManager,\n ContentHashIndex,\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 {\n FallbackLlmClient,\n fallbackLlmRuntimeContextFromConfig,\n gatewayTaskChainOptions,\n} from \"./fallback-llm.js\";\nimport { MaintenanceScheduler } from \"./orchestration/maintenance.js\";\nimport { TierMigrationCoordinator } from \"./orchestration/tier-migration-coordinator.js\";\nimport { ExtractionQueueCoordinator } from \"./orchestration/extraction-queue-coordinator.js\";\nimport { CompressionGuidelineCoordinator } from \"./orchestration/compression-guideline-coordinator.js\";\nimport { SemanticConsolidationCoordinator } from \"./orchestration/semantic-consolidation-coordinator.js\";\nimport { LifecyclePolicyCoordinator } from \"./orchestration/lifecycle-policy-coordinator.js\";\nimport { EntitySynthesisCoordinator } from \"./orchestration/entity-synthesis-coordinator.js\";\nimport { RecallResultFormatter } from \"./orchestration/recall-result-formatter.js\";\nimport { ConversationIndexCoordinator } from \"./orchestration/conversation-index-coordinator.js\";\nimport { RecallRerankCoordinator } from \"./orchestration/recall-rerank-coordinator.js\";\nimport { RecallSectionCoordinator } from \"./orchestration/recall-section-coordinator.js\";\nimport { QmdResultResolver, qmdCollectionPathParts, qmdResultPathCandidates } from \"./orchestration/qmd-result-resolver.js\";\nimport { ContradictionLinkingCoordinator } from \"./orchestration/contradiction-linking-coordinator.js\";\nimport { ExtractionRunCoordinator, type ExtractionRunResult } from \"./orchestration/extraction-run.js\";\nimport { ConsolidationRunCoordinator } from \"./orchestration/consolidation-run.js\";\nimport { ExtractionPersistCoordinator } from \"./orchestration/extraction-persist.js\";\nimport { RecallInternalCoordinator } from \"./orchestration/recall-internal.js\";\nimport { RecallSearchPipelineCoordinator } from \"./orchestration/recall-search-pipeline.js\";\nimport { TurnIngestionCoordinator } from \"./orchestration/turn-ingestion.js\";\nimport { RecallIntrospectionCoordinator } from \"./orchestration/recall-introspection.js\";\nimport { OrchestratorInitCoordinator } from \"./orchestration/orchestrator-init.js\";\nimport { PersistenceIndexCoordinator } from \"./orchestration/persistence-index.js\";\nimport { WorkspaceOpsCoordinator } from \"./orchestration/workspace-ops.js\";\nimport { NamespaceReadFanoutCoordinator } from \"./orchestration/namespace-read-fanout.js\";\nimport { selfDeps } from \"./orchestration/self-deps.js\";\nimport {\n abortRecallError,\n buildCompressionGuidelinesMarkdown,\n buildQmdIntentHint,\n isArtifactMemoryPath,\n mergeArtifactRecallCandidates,\n tokenizeRecallQuery,\n type BulkImportBatchIngestResult,\n type DaySummaryGatherOptions,\n type GraphRecallSnapshot,\n type IntentDebugSnapshot,\n type QmdRecallSnapshot,\n type QueryAwarePrefilter,\n type RecallInvocationOptions,\n} from \"./orchestration/orchestrator-helpers.js\";\n// Issue #1526 seam 25: module-level helpers moved to\n// orchestration/orchestrator-helpers.ts; re-exported here so existing\n// importers (coordinators, tests, root shims) keep working.\nexport {\n BulkImportBatchPartialFailureError,\n COMPACTION_SIGNAL_MAX_AGE_MS,\n appendMemoryToGraphContext,\n applyQueryAwareCandidateFilter,\n buildCompressionGuidelinesMarkdown,\n buildMemoryPathById,\n computeArtifactCandidateFetchLimit,\n computeArtifactRecallLimit,\n computeQmdHybridFetchLimit,\n defaultWorkspaceDir,\n filterHourlySummaryMarkdownForLocalDay,\n filterRecallCandidates,\n formatDateInTimeZone,\n isArtifactMemoryPath,\n lifecycleRecallScoreAdjustment,\n mapRecallSourceToXrayServedBy,\n mergeArtifactRecallCandidates,\n normalizeIanaTimeZone,\n parseFiniteDate,\n parseGraphRecallRankedResults,\n parseMemoryIntentSnapshot,\n parseQmdRecallResults,\n qmdStartupCollectionCheckWithTimeout,\n raceRecallAbort,\n resolveEffectiveRecallMode,\n resolvePersistedMemoryRelativePath,\n resolveRecallModeDecision,\n resolveRecallModeDecisionAsync,\n resolveRecentThreadMemoryPaths,\n sanitizeSessionKeyForFilename,\n shouldFilterLifecycleRecallCandidate,\n splitTurnsBySourceValidAt,\n summarizeGraphShadowComparison,\n targetSourceValidAtSortMs,\n throwIfRecallAborted,\n tokenizeRecallQuery,\n utcDateKeysForLocalDay,\n type BulkImportBatchIngestResult,\n type DaySummaryGatherOptions,\n type GraphRecallSnapshot,\n type IntentDebugSnapshot,\n type QmdRecallSnapshot,\n type QueryAwarePrefilter,\n type RecallInvocationOptions,\n type RecallModeDecision,\n} from \"./orchestration/orchestrator-helpers.js\";\n\nexport { hasIdentityRecoveryIntent, resolveEffectiveIdentityInjectionMode } from \"./orchestration/recall-result-formatter.js\";\nimport {\n GraphRecallCoordinator,\n mergeGraphExpandedResults,\n graphPathRelativeToStorage,\n blendGraphExpandedRecallScore,\n type GraphRecallRankedResult,\n type GraphRecallShadowComparison,\n} from \"./orchestration/graph-recall-coordinator.js\";\nexport { mergeGraphExpandedResults, graphPathRelativeToStorage, blendGraphExpandedRecallScore } from \"./orchestration/graph-recall-coordinator.js\";\nexport type { GraphRecallRankedResult, GraphRecallShadowComparison } from \"./orchestration/graph-recall-coordinator.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 { projectTrustForXray } from \"./trust-score-stage.js\";\nimport type { TrustStageResultItem } from \"./trust-score-stage.js\";\nimport { buildRetrievedMemoryProvenance } from \"./memory-provenance.js\";\nimport {\n applyTemporalSupersession,\n normalizeSupersessionKey,\n shouldFilterSupersededFromRecall,\n} from \"./temporal-supersession.js\";\nimport { isValidAsOf, isValidityExpiredNow } from \"./temporal-validity.js\";\nimport { pickFactEventTimeAnchor, resolveFactEventTime } from \"./event-time.js\";\nimport { RelevanceStore } from \"./relevance.js\";\nimport { NegativeExampleStore } from \"./negative.js\";\nimport {\n LastRecallStore,\n RecallHandleHistoryStore,\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 buildHandleIndexForResults,\n MEMORY_ID_PATTERN,\n parseIdOrHandle,\n resolveHandle,\n stripHandles,\n type RecallSnapshotIds,\n} from \"./recall-handles.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 throwIfAborted as sharedThrowIfAborted,\n} from \"./abort-error.js\";\nimport { CODEX_THREAD_KEY_PREFIX } from \"./thread-key.js\";\nimport { isDisagreementPrompt } from \"./signal.js\";\nimport { lintWorkspaceFiles, rotateMarkdownFileToArchive } from \"./hygiene.js\";\nimport { isPathInsideStorageRoot } from \"./storage-paths.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 buildTargetedFactRecallSection,\n shouldRecallTargetedFactEvidence,\n} from \"./targeted-fact-recall.js\";\nimport {\n buildFocusedListRecallSection,\n shouldRecallFocusedListEvidence,\n} from \"./focused-list-recall.js\";\nimport {\n buildResponseGuidanceRecallSection,\n shouldRecallResponseGuidance,\n} from \"./response-guidance-recall.js\";\nimport {\n buildEventOrderRecallSection,\n shouldRecallEventOrderEvidence,\n} from \"./event-order-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} from \"./compression-optimizer.js\";\nexport { formatCompressionGuidelinesForRecall } from \"./orchestration/compression-guideline-coordinator.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 objectiveStateStoreOverrideForNamespace,\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 { resolveNamespaceCapabilities,\n resolveCapabilities,\n resolveGraphConstructionCapabilities,\n resolveMemoryLifecycleCapabilities,\n resolveIndexingCapabilities,\n resolveCreationMemoryCapabilities,\n type CapabilitySet,\n type GraphConstructionCapabilitySet,\n type MemoryLifecycleCapabilitySet,\n type IndexingCapabilitySet,\n type CreationMemoryCapabilitySet,\n resolveQmdCapabilities,\n resolveIdentityContinuityCapabilities,\n resolveLocalLlmCapabilities,\n resolveSecurityCapabilities, resolveEvalCapabilities, resolveUtilityLearningCapabilities, resolveObjectiveStateCapabilities, resolveCompressionCapabilities, resolvePresentationCapabilities, resolveConsolidationCapabilities, resolveRecallAuxiliaryCapabilities ,\n resolveRecallEnhancementCapabilities,\n resolvePipelineProcessingCapabilities,\n resolveConversationContextCapabilities,\n} from \"./capabilities.js\";\nimport { DEFAULT_TAXONOMY } from \"./taxonomy/index.js\";\nimport {\n searchHarmonicRetrieval,\n type HarmonicRetrievalResult,\n} from \"./harmonic-retrieval.js\";\nimport {\n compareVerifiedEpisodeResults,\n searchVerifiedEpisodes,\n type VerifiedEpisodeResult,\n} from \"./verified-recall.js\";\nimport {\n compareVerifiedSemanticRuleResults,\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 { WearablesService } from \"./wearables/service.js\";\nimport {\n type AgentPersonaModelConfig,\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 {\n type ConversationIndexBackend,\n type ConversationIndexBackendInspection,\n type ConversationQmdRuntime,\n} from \"./conversation-index/backend.js\";\nimport {\n NamespaceStorageRouter,\n} from \"./namespaces/storage.js\";\nimport {\n NamespaceCatalog,\n} from \"./namespaces/catalog.js\";\nimport {\n planNamespaceMaintenance,\n type NamespaceMaintenanceSummary,\n} from \"./maintenance/namespace-planner.js\";\nimport {\n runNamespaceMaintenanceFanout,\n summarizeNamespaceMaintenanceHealth,\n type NamespaceMaintenanceFanoutRunnerContext,\n type NamespaceMaintenanceHealthSummary,\n} from \"./maintenance/namespace-maintenance-fanout.js\";\nimport {\n namespaceIdentityFromToken,\n namespaceIdentityToken,\n normalizeNamespaceIdentity,\n} from \"./namespaces/identity.js\";\nimport {\n canReadNamespace,\n canWriteNamespace,\n defaultNamespaceForPrincipal,\n recallNamespacesForPrincipal,\n resolvePrincipal,\n} from \"./namespaces/principal.js\";\nimport {\n getConfiguredNamespaces,\n resolveNamespaceFromStorageDir,\n resolveScopePlan,\n} from \"./scopes/scope-plan.js\";\nimport {\n expandScopeProfileReadNamespaces,\n resolveScopeProfilePlan,\n type ResolvedScopeProfilePlan,\n} from \"./namespaces/scope-profiles.js\";\nimport {\n combineNamespaces,\n lcmReadSessionIdsForNamespaces,\n resolveCodingNamespaceOverlay,\n} from \"./coding/coding-namespace.js\";\nimport type { CodingContext, ProvenanceSource } from \"./types.js\";\nimport {\n NamespaceSearchRouter,\n type NamespaceSearchHealth,\n} from \"./namespaces/search.js\";\nimport { SharedContextManager } from \"./shared-context/manager.js\";\nimport {\n CompoundingEngine,\n defaultTierMigrationCycleBudget,\n} from \"./compounding/engine.js\";\nimport { parseFlexibleIsoTimestamp } from \"./utils/iso-timestamp.js\";\nimport { categoryDirName, RECALL_FALLBACK_DIRS } from \"./utils/category-dir.js\";\nimport { assertPathInsideRoot } from \"./utils/path-containment.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 isSafeRouteNamespace,\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 {\n keyring,\n secureStoreDir,\n SecureStoreLockedError,\n} 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} from \"./types.js\";\nimport { disposeDefaultArchiveScoring, getDefaultArchiveScoring, memoryFileToScoreItem } from \"./recall/archive-scoring.js\";\n\n\n// Issue #1526 seam 15: ExtractionRunResult moved to orchestration/extraction-run.ts.\nexport type { ExtractionRunResult } from \"./orchestration/extraction-run.js\";\n\n\n// Issue #1526 seam 15: deriveTopicsFromExtraction moved to orchestration/extraction-run.ts.\nexport { deriveTopicsFromExtraction } from \"./orchestration/extraction-run.js\";\n\n\nexport class Orchestrator {\n\n readonly storage: StorageManager;\n private readonly storageRouter: NamespaceStorageRouter;\n /** Rebuildable namespace catalog (issue #1499). Inert unless namespaces enabled. */\n readonly namespaceCatalog: NamespaceCatalog;\n private readonly namespaceStorageDirHints = new Map<string, Set<string>>();\n private namespaceStorageDirHintsLoaded = false;\n private readonly namespaceSearchRouter: NamespaceSearchRouter;\n qmd: SearchBackend;\n /**\n * Maintenance scheduler (issue #1526 PR1). Owns cron auto-registration,\n * debounced QMD index maintenance, and consolidation scheduling. Job\n * runners (consolidation/pattern-reinforcement/governance) stay here.\n */\n readonly maintenanceScheduler: MaintenanceScheduler;\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 * Faithfulness gate distribution counters (issue #1576). Per-orchestrator\n * running tally surfaced via console_state telemetry. No module-level state\n * (rule 11) — these hang off the orchestrator instance.\n */\n private faithfulnessCounters: FaithfulnessGateCounters = createFaithfulnessCounters();\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 /**\n * Side-channel (#1635): pending_review persisted ids from the last\n * persistExtraction; runExtraction excludes them from the thread episode set.\n */\n private lastPersistExtractionPendingReviewIds: string[] = [];\n private readonly _fastGatewayLlm: FallbackLlmClient | null;\n\n get fastGatewayLlm(): FallbackLlmClient | null {\n return this._fastGatewayLlm;\n }\n\n getConsoleFaithfulnessDistribution(): FaithfulnessGateCounters | undefined {\n return this.recallIntrospectionCoordinator.getConsoleFaithfulnessDistribution(\n );\n }\n readonly modelRegistry: ModelRegistry;\n readonly relevance: RelevanceStore;\n readonly negatives: NegativeExampleStore;\n readonly lastRecall: LastRecallStore;\n readonly handleHistory: RecallHandleHistoryStore;\n readonly tierMigrationStatus: TierMigrationStatusStore;\n readonly tierMigrationCoordinator: TierMigrationCoordinator;\n readonly compressionGuidelineCoordinator: CompressionGuidelineCoordinator;\n readonly semanticConsolidationCoordinator: SemanticConsolidationCoordinator;\n readonly lifecyclePolicyCoordinator: LifecyclePolicyCoordinator;\n readonly entitySynthesisCoordinator: EntitySynthesisCoordinator;\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 * 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 contentHashIndexesByStorageDir = new Map<string, ContentHashIndex>();\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 /** Read by NamespaceReadFanoutCoordinator (seam 26), hence not `private`. */\n 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 // Passive correction capture (issue #1581) — dedup state + lazy service.\n private passiveCorrectionDedup: Set<string> = new Set();\n private _passiveCorrectionService: CorrectionService | null = null;\n private passiveCorrectionTelemetry: {\n detected: number;\n queued: number;\n autoApplied: number;\n suppressedReasonCounts: Record<string, number>;\n } = { detected: 0, queued: 0, autoApplied: 0, suppressedReasonCounts: {} };\n\n /**\n * Background serial extraction queue coordinator (issue #1526 — moved\n * from inline `extractionQueue`/`queueProcessing` fields). Owns queue\n * state + scheduling + the serial drain + failure classification; the\n * orchestrator builds each task closure in `queueBufferedExtraction` and\n * hands it to `enqueue`.\n */\n readonly extractionQueueCoordinator: ExtractionQueueCoordinator;\n /**\n * Extraction-run pipeline coordinator (issue #1526 seam 15). Owns\n * `runExtraction` + dedupe fingerprint helpers + processed-fingerprint\n * recording. The orchestrator delegates and injects its own methods.\n */\n private _extractionRunCoordinator: ExtractionRunCoordinator | undefined;\n\n /**\n * Lazy getter: creates the ExtractionRunCoordinator on first access using\n * the orchestrator's live field references. Supports Object.create(prototype)\n * tests that set fields post-construction without invoking the constructor.\n */\n private get extractionRunCoordinator(): ExtractionRunCoordinator {\n if (!this._extractionRunCoordinator) {\n this._extractionRunCoordinator = new ExtractionRunCoordinator({\n config: this.config,\n getBuffer: () => this.buffer,\n getExtraction: () => this.extraction,\n getStorageRouter: () => this.storageRouter,\n getThreading: () => this.threading,\n persistExtraction: (result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps) =>\n this.persistExtraction(result, storage, threadId, sourceContext, baseNamespace, scopeProfileWritePlan, sourceText, graphCaps, lifecycleCaps),\n maybeCapturePassiveCorrections: (turns, opts) => this.maybeCapturePassiveCorrections(turns, opts),\n resolveSelfNamespace: (sessionKey) => this.resolveSelfNamespace(sessionKey),\n getCodingContextForSession: (sessionKey) => this.getCodingContextForSession(sessionKey),\n applyCodingNamespaceOverlay: (sessionKey, namespace) => this.applyCodingNamespaceOverlay(sessionKey, namespace),\n boxBuilderFor: (storage) => this.boxBuilderFor(storage),\n appendPersistedThreadEpisodes: (threadId, ids) => this.appendPersistedThreadEpisodes(threadId, ids),\n maybeScheduleConsolidation: (nonZero) => this.maybeScheduleConsolidation(nonZero),\n requestQmdMaintenance: () => this.requestQmdMaintenance(),\n runTierMigrationCycle: (storage, trigger, options) => this.runTierMigrationCycle(storage, trigger, options),\n getLastPersistExtractionDeferredCount: () => this.lastPersistExtractionDeferredCount,\n recordProcessedExtractionFingerprint: (storage, fingerprint, preloadedMeta) =>\n this.recordProcessedExtractionFingerprint(storage, fingerprint, preloadedMeta),\n });\n }\n return this._extractionRunCoordinator;\n }\n /**\n * Consolidation-run coordinator (issue #1526 seam 17). Owns\n * the full consolidation maintenance pass (LLM merge/invalidate/update,\n * entity merge, commitment/TTL cleanup, lifecycle policy, compression\n * guideline learning, tier migration, fact archival, semantic consolidation,\n * identity consolidation, profile consolidation, summarization, topic\n * extraction, TMT rebuild). The orchestrator delegates and injects\n * its own methods + coordinators.\n */\n private _consolidationRunCoordinator: ConsolidationRunCoordinator | undefined;\n\n private get consolidationRunCoordinator(): ConsolidationRunCoordinator {\n if (!this._consolidationRunCoordinator) {\n this._consolidationRunCoordinator = new ConsolidationRunCoordinator({\n config: this.config,\n getStorage: () => this.storage,\n getStorageRouter: () => this.storageRouter,\n getExtraction: () => this.extraction,\n embeddingFallback: this.embeddingFallback,\n tmtBuilder: this.tmtBuilder,\n consolidationObservers: this.consolidationObservers,\n getAccessTrackingBuffer: () => this.accessTrackingBuffer,\n lifecyclePolicyCoordinator: this.lifecyclePolicyCoordinator,\n compressionGuidelineCoordinator: this.compressionGuidelineCoordinator,\n semanticConsolidationCoordinator: this.semanticConsolidationCoordinator,\n entitySynthesisCoordinator: this.entitySynthesisCoordinator,\n recallSectionCoordinator: this.recallSectionCoordinator,\n tierMigrationCoordinator: this.tierMigrationCoordinator,\n flushAccessTracking: () => this.flushAccessTracking(),\n indexPersistedMemory: (storage, memoryId) => this.indexPersistedMemory(storage, memoryId),\n autoConsolidateIdentity: () => this.autoConsolidateIdentity(),\n fastChatCompletion: (messages, options) => this.fastChatCompletion(messages, options),\n });\n }\n return this._consolidationRunCoordinator;\n }\n\n /**\n * Extraction-persist coordinator (issue #1526 seam 16). Owns the\n * `persistExtraction` pipeline. Lazy: created on first access so\n * Object.create(prototype) tests that set fields post-construction work.\n */\n private _extractionPersistCoordinator: ExtractionPersistCoordinator | undefined;\n\n private get extractionPersistCoordinator(): ExtractionPersistCoordinator {\n if (!this._extractionPersistCoordinator) {\n this._extractionPersistCoordinator = new ExtractionPersistCoordinator({\n config: this.config,\n getStorageRouter: () => this.storageRouter,\n getThreading: () => this.threading,\n getLocalLlm: () => this.localLlm,\n getQmd: () => this.qmd,\n getJudgeVerdictCache: () => this.judgeVerdictCache,\n getJudgeDeferCounts: () => this.judgeDeferCounts,\n getFaithfulnessCounters: () => this.faithfulnessCounters,\n getEmbeddingFallback: () => this.embeddingFallback,\n setLastPersistExtractionDeferredCount: (v) => { this.lastPersistExtractionDeferredCount = v; },\n setLastPersistExtractionPendingReviewIds: (ids) => { this.lastPersistExtractionPendingReviewIds = ids; },\n addContentHashDedup: (targetStorage, content) => this.addContentHashDedup(targetStorage, content),\n hasContentHashDedup: (targetStorage, content) => this.hasContentHashDedup(targetStorage, content),\n backfillTemporalBoundsOnDedupHit: (targetStorage, dedupContent, bounds, entityRef) =>\n this.backfillTemporalBoundsOnDedupHit(targetStorage, dedupContent, bounds, entityRef),\n saveContentHashIndexes: () => this.saveContentHashIndexes(),\n artifactTypeForCategory: (category) => this.artifactTypeForCategory(category),\n loadRoutingRules: () => this.loadRoutingRules(),\n routeEngineOptions: () => this.routeEngineOptions(),\n semanticDedupLookup: (content, limit, targetStorage) =>\n this.semanticDedupLookup(content, limit, targetStorage),\n checkForContradiction: (content, category, namespaceScope) =>\n this.checkForContradiction(content, category, namespaceScope),\n applyDeferredContradictionResolve: (contradiction, storage, newMemoryId, postWriteGuard) =>\n this.applyDeferredContradictionResolve(contradiction, storage, newMemoryId, postWriteGuard),\n suggestLinksForMemory: (content, category, namespaceScope) =>\n this.suggestLinksForMemory(content, category, namespaceScope),\n storageDirNamespace: (storageDir) => this.storageDirNamespace(storageDir),\n indexPersistedMemory: (storage, memoryId) => this.indexPersistedMemory(storage, memoryId),\n buildGraphEdge: (storage, memoryRelPath, entityRef, memoryId, factContent, allMemsForGraph, memoryPathById, threadIdForEdge, threadEpisodeIdsForGraph, fallbackCausalPredecessor, graphCaps) =>\n this.buildGraphEdge(storage, memoryRelPath, entityRef, memoryId, factContent, allMemsForGraph, memoryPathById, threadIdForEdge, threadEpisodeIdsForGraph, fallbackCausalPredecessor, graphCaps),\n updateTemporalTagIndexes: (storage, persistedIds) =>\n this.updateTemporalTagIndexes(storage, persistedIds),\n });\n }\n return this._extractionPersistCoordinator;\n }\n /**\n * Issue #1526: recall result formatting + identity continuity section moved\n * to RecallResultFormatter.\n */\n readonly recallResultFormatter: RecallResultFormatter;\n /**\n * Issue #1526: conversation-index subsystem moved to\n * ConversationIndexCoordinator.\n */\n readonly conversationIndexCoordinator: ConversationIndexCoordinator;\n readonly recallRerankCoordinator: RecallRerankCoordinator;\n readonly recallSectionCoordinator: RecallSectionCoordinator;\n readonly qmdResultResolver: QmdResultResolver;\n readonly contradictionLinkingCoordinator: ContradictionLinkingCoordinator;\n readonly graphRecallCoordinator: GraphRecallCoordinator;\n private heartbeatObserverChains = new Map<string, Promise<void>>();\n private recentExtractionFingerprints = new Map<string, number>();\n private readonly consolidationObservers = new Set<\n (observation: ConsolidationObservation) => Promise<void> | void\n >();\n private wearablesServiceInstance: WearablesService | null = null;\n private wearablesAutoSyncHandle: { stop(): Promise<void> } | null = null;\n private lastQmdReprobeAtMs = 0;\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 /**\n * Stop background initialization and release runtime-owned handles.\n * Long-lived hosts should call this from their shutdown path; one-shot\n * commands should call it before returning to let Node exit naturally.\n */\n async destroy(): Promise<void> {\n this.abortDeferredInit();\n if (this.wearablesAutoSyncHandle) {\n // Aborts in-flight provider fetches and waits for the tick to\n // settle, so nothing is writing or reindexing past destroy().\n await this.wearablesAutoSyncHandle.stop();\n this.wearablesAutoSyncHandle = null;\n }\n this.maintenanceScheduler.dispose();\n await this.namespaceSearchRouter.dispose();\n await this.disposeSearchBackendIfNeeded();\n if (this.conversationQmd && this.conversationQmd !== this.qmd) {\n await (this.conversationQmd as { dispose?: () => void | Promise<void> }).dispose?.();\n }\n // Issue #1674: terminate archive-scoring worker threads on destroy.\n await disposeDefaultArchiveScoring();\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 | undefined {\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 * Effective namespace a same-session LCM/structured-history READER must use\n * to find what the access `observe` surface WROTE (#1495 thread 2).\n *\n * This MUST mirror the `observe` scope plan's write-namespace resolution, NOT\n * `resolveSelfNamespace`: when no coding overlay applies, `observe` archives\n * under `config.defaultNamespace` (an unqualified observed turn is NOT moved\n * to the principal self namespace — identical to\n * `resolveCodingScopedWriteNamespace`/`memory_store`, rule 39). Only when a\n * coding overlay actually changes the namespace does the writer (and so the\n * reader) use the overlaid `project-*` namespace. Returning the self base for\n * the no-overlay case would prefix the read key with a namespace the writer\n * never used, so the reader would miss its own evidence.\n *\n * Honours the access-surface `principalOverride` (#1505 thread 2, codex): when\n * a recall supplies an authenticated principal NOT encoded in the raw\n * `sessionKey`, `observe` archived LCM under THAT principal's base namespace.\n * Deriving the base from `resolvePrincipal(sessionKey)` alone could fall back\n * to `default`, so principal `alice` observing `sess-1` would write under\n * `alice` but READ under `default`. Threading the override here keeps the read\n * base identical to the write base.\n *\n * READ-AUTHORIZATION gate (#1505 round 3, codex P2 \"Gate LCM recall keys by\n * readable namespaces\"): the overlay LCM read key is a `<principal>-project-*`\n * sub-namespace of the principal SELF base. The normal recall namespace set\n * below only substitutes the coding overlay when the principal SELF base is\n * actually in the readable recall set (`recallNamespacesForPrincipal` — gated\n * by `defaultRecallNamespaces.includes(\"self\")` AND `canReadNamespace`). If a\n * principal can WRITE but not READ its self namespace (or `defaultRecall-\n * Namespaces` omits `self`), QMD/file recall never touches those overlay rows,\n * so neither may the LCM read key. When the self base is NOT readable, fall\n * back to the default store — exactly what an unqualified, unauthorized recall\n * resolves to — rather than injecting overlay rows the rest of recall excludes\n * (rule 42 read/write parity; rule 48 least-privilege).\n */\n private lcmReadNamespaceForSession(\n sessionKey?: string,\n principalOverride?: string,\n ): string {\n const principal =\n typeof principalOverride === \"string\" && principalOverride.length > 0\n ? principalOverride\n : this.resolvePrincipal(sessionKey);\n const base = defaultNamespaceForPrincipal(principal, this.config);\n const overlaid = this.applyCodingNamespaceOverlay(sessionKey, base);\n // No overlay → collapse to the default store so the LCM key is the raw\n // sessionKey, exactly what an unqualified observe archived under.\n if (overlaid === base) return this.config.defaultNamespace;\n // Overlay applied. Only honour it when the principal SELF base is in the\n // readable recall set (same gate the recall namespace set uses to\n // substitute the overlay). Otherwise the overlay rows are unauthorized for\n // this reader — fall back to the default store so the LCM read matches\n // what QMD/file recall would surface.\n const selfReadableInRecall = recallNamespacesForPrincipal(\n principal,\n this.config,\n ).includes(base);\n return selfReadableInRecall ? overlaid : this.config.defaultNamespace;\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 (!resolveNamespaceCapabilities(this.config).namespaces) 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 (!resolveNamespaceCapabilities(this.config).namespaces) 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 configuredNamespaceList(): string[] {\n // #1521: delegates to the scope-module resolver. The inline derivation is\n // retired so the adHocNamespaceResolutions ratchet no longer counts this\n // site.\n return getConfiguredNamespaces(this.config);\n }\n\n private rememberNamespaceStorageDirHint(namespace: string, storageDir?: string): void {\n if (!resolveNamespaceCapabilities(this.config).namespaces || !storageDir) return;\n const ns = normalizeNamespaceIdentity(namespace);\n if (!ns) return;\n const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);\n if (ns !== defaultNs && !isSafeRouteNamespace(ns)) return;\n\n if (!this.storageDirMatchesNamespaceHint(ns, storageDir)) return;\n\n const resolvedStorageDir = path.resolve(storageDir);\n let hints = this.namespaceStorageDirHints.get(resolvedStorageDir);\n if (!hints) {\n hints = new Set<string>();\n this.namespaceStorageDirHints.set(resolvedStorageDir, hints);\n }\n hints.add(ns);\n }\n\n private storageDirMatchesNamespaceHint(namespace: string, storageDir: string): boolean {\n const ns = normalizeNamespaceIdentity(namespace);\n if (!ns) return false;\n\n const resolvedStorageDir = path.resolve(storageDir);\n const resolvedMemoryDir = path.resolve(this.config.memoryDir);\n const defaultNs = normalizeNamespaceIdentity(this.config.defaultNamespace);\n if (resolvedStorageDir === resolvedMemoryDir) return ns === defaultNs;\n\n const resolvedNamespacesDir = path.join(resolvedMemoryDir, \"namespaces\");\n if (!isPathInsideStorageRoot(resolvedNamespacesDir, resolvedStorageDir)) return false;\n\n const rawRoot = path.resolve(resolvedNamespacesDir, ns);\n const tokenRoot = path.resolve(resolvedNamespacesDir, namespaceIdentityToken(ns));\n return resolvedStorageDir === rawRoot || resolvedStorageDir === tokenRoot;\n }\n\n private namespaceStorageDirHintOwnershipRank(\n record: { namespace: string },\n resolvedStorageDir: string,\n configured: Set<string>,\n ): number {\n if (resolvedStorageDir === path.resolve(this.config.memoryDir)) {\n return record.namespace === normalizeNamespaceIdentity(this.config.defaultNamespace)\n ? 0\n : 3;\n }\n\n const leaf = path.basename(resolvedStorageDir);\n const tokenOwnsRoot = namespaceIdentityToken(record.namespace) === leaf;\n if (tokenOwnsRoot && configured.has(record.namespace)) return 0;\n if (record.namespace === leaf) return 1;\n if (tokenOwnsRoot) return 2;\n return 3;\n }\n\n private preferNamespaceStorageDirHintOwner(\n current: { namespace: string; identityToken: string; storageDir: string },\n candidate: { namespace: string; identityToken: string; storageDir: string },\n resolvedStorageDir: string,\n configured: Set<string>,\n ): { namespace: string; identityToken: string; storageDir: string } {\n return this.namespaceReadFanoutCoordinator.preferNamespaceStorageDirHintOwner(\n current,\n candidate,\n resolvedStorageDir,\n configured,\n );\n }\n\n private loadNamespaceStorageDirHintsFromCatalog(): void {\n return this.namespaceReadFanoutCoordinator.loadNamespaceStorageDirHintsFromCatalog(\n );\n }\n\n private async maintenanceNamespaces(\n jobName = \"qmd\",\n budgetMode: \"cycle\" | \"unbounded\" = \"unbounded\",\n ): Promise<string[]> {\n const plan = await planNamespaceMaintenance(this.config, {\n jobName,\n catalog: this.namespaceCatalog,\n budgetMode,\n });\n return plan.namespaces.map((candidate) => candidate.namespace);\n }\n\n /**\n * Fan out a maintenance job across all maintained namespaces (issue #1500).\n *\n * Delegates to the namespace-maintenance-fanout coordinator, which plans\n * namespace discovery (configured + catalog), applies the cycle budget,\n * acquires per-job+namespace locks, records status files, and touches the\n * catalog's `lastMaintenanceAt`. The runner receives a per-namespace\n * candidate and a storage resolver wired to `this.getStorage(namespace)`.\n *\n * When namespaces are disabled the planner returns only the default\n * namespace, so the job runs exactly once — preserving single-user behavior.\n */\n async runNamespaceMaintenanceFanoutForJob(\n jobName: string,\n runner: (ctx: NamespaceMaintenanceFanoutRunnerContext) => Promise<{ itemCount?: number } | undefined>,\n options: { enabled?: boolean } = {},\n ): Promise<NamespaceMaintenanceSummary> {\n return runNamespaceMaintenanceFanout({\n config: this.config,\n catalog: this.namespaceCatalog,\n jobName,\n runner,\n resolveStorage: (namespace) => this.getStorage(namespace),\n enabled: options.enabled,\n });\n }\n\n /**\n * Read-only namespace maintenance health summary for doctor / dashboard /\n * CLI (issue #1500). Aggregates all per-namespace maintenance status files\n * into one report without running any maintenance.\n */\n async readNamespaceMaintenanceHealth(): Promise<NamespaceMaintenanceHealthSummary> {\n return summarizeNamespaceMaintenanceHealth(this.config);\n }\n\n private buildConfiguredQmdSearchOptions(\n queryText: string,\n ): SearchQueryOptions | undefined {\n const intentHint = resolveQmdCapabilities(this.config).qmdIntentHints\n ? buildQmdIntentHint(inferIntentFromText(queryText))\n : undefined;\n const explain = resolveQmdCapabilities(this.config).qmdExplain === 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 return this.namespaceReadFanoutCoordinator.searchAcrossNamespaces(\n options,\n );\n }\n\n async searchHealthForNamespace(\n namespace: string,\n execution?: SearchExecutionOptions,\n ): Promise<NamespaceSearchHealth> {\n return await this.namespaceSearchRouter.healthForNamespace(namespace, execution);\n }\n\n private isSearchAvailableForNamespaceRouting(): boolean {\n if (resolveNamespaceCapabilities(this.config).namespaces) return true;\n return this.qmd.isAvailable();\n }\n\n invalidateLiveContentHashIndex(): void {\n this.contentHashIndex = null;\n this.contentHashIndexesByStorageDir.clear();\n }\n\n private async contentHashIndexForStorage(\n targetStorage: StorageManager,\n ): Promise<ContentHashIndex | null> {\n if (!resolveRecallAuxiliaryCapabilities(this.config).factDeduplication) return null;\n\n if (targetStorage.dir === this.storage.dir) {\n if (!this.contentHashIndex) {\n this.contentHashIndex = this.storage.createContentHashIndex();\n await this.contentHashIndex.load();\n }\n return this.contentHashIndex;\n }\n\n const cached = this.contentHashIndexesByStorageDir.get(targetStorage.dir);\n if (cached) return cached;\n\n const index = targetStorage.createContentHashIndex();\n await index.load();\n this.contentHashIndexesByStorageDir.set(targetStorage.dir, index);\n log.info(\n `content-hash dedup: loaded ${index.size} hashes for storage ${targetStorage.dir}`,\n );\n return index;\n }\n\n private async hasContentHashDedup(\n targetStorage: StorageManager,\n content: string,\n ): Promise<boolean> {\n return this.persistenceIndexCoordinator.hasContentHashDedup(\n targetStorage,\n content,\n );\n }\n\n private async addContentHashDedup(\n targetStorage: StorageManager,\n content: string,\n ): Promise<void> {\n return this.persistenceIndexCoordinator.addContentHashDedup(\n targetStorage,\n content,\n );\n }\n\n private async removeContentHashForMemory(\n targetStorage: StorageManager,\n memory: MemoryFile,\n context: string,\n ): Promise<void> {\n return this.persistenceIndexCoordinator.removeContentHashForMemory(\n targetStorage,\n memory,\n context,\n );\n }\n\n private async backfillTemporalBoundsOnDedupHit(\n targetStorage: StorageManager,\n dedupContent: string,\n bounds: {\n invalidAt?: string;\n // #1707 thread 2 — per-fact start bound (valid_at). Carried so a\n // re-extracted duplicate whose event time yields only a start bound\n // (\"since 2024\", \"yesterday\", an absolute date) gets the corrected\n // per-fact anchoring onto the existing copy.\n validFrom?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n },\n entityRef?: string,\n ): Promise<void> {\n return this.persistenceIndexCoordinator.backfillTemporalBoundsOnDedupHit(\n targetStorage,\n dedupContent,\n bounds,\n entityRef,\n );\n }\n\n private async saveContentHashIndexes(): Promise<void> {\n return this.persistenceIndexCoordinator.saveContentHashIndexes(\n );\n }\n\n constructor(config: PluginConfig) {\n this.config = config;\n this.profiler = new ProfilingCollector({\n enabled: resolvePipelineProcessingCapabilities(this.config).profiling,\n storageDir: config.profilingStorageDir || path.join(config.memoryDir, \"profiling\"),\n maxTraces: config.profilingMaxTraces,\n });\n // Namespace catalog (issue #1499): downstream, rebuildable metadata index.\n // Inert unless namespacesEnabled is true. Storage resolution registers\n // namespaces via the router's onResolve hook; the touch is best-effort and\n // a catalog write failure never affects storage resolution.\n this.namespaceCatalog = new NamespaceCatalog(config);\n this.storageRouter = new NamespaceStorageRouter(config, {\n // Return the registration promise (round 6, codex P2 — NEFoX) so the\n // router's resolve-hook dedup only marks a namespace notified when the\n // catalog actually APPENDED. A dropped append (rebuild-lock timeout) or a\n // failure resolves to `false`/rejects, so the next `storageFor` retries.\n onResolve: (namespace, storageDir) => {\n this.rememberNamespaceStorageDirHint(namespace, storageDir);\n return this.namespaceCatalog.registerResolved(namespace, storageDir);\n },\n }, this.namespaceCatalog);\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 // #1522: bind the post-write catalog touch at the storage chokepoint.\n if (config.defaultNamespace) this.storageRouter.bindCatalogWriteHook(this.storage, config.defaultNamespace);\n // Wire page-level versioning (issue #371)\n this.storage.setVersioningConfig({\n enabled: resolveRecallAuxiliaryCapabilities(config).versioning,\n maxVersionsPerPage: config.versioningMaxPerPage,\n sidecarDir: config.versioningSidecarDir,\n });\n // Wire the tombstone non-resurrection invariant (issue #1579) on the\n // primary default-namespace storage. Router-created namespace storages\n // get the same config via NamespaceStorageRouter.bindTombstonesConfig\n // (installed below) so every write path funnels through the chokepoint.\n const { tombstonesEnabled, tombstonesSemanticMatch, tombstonesSemanticThreshold } = config;\n this.storage.setTombstonesConfig({\n enabled: tombstonesEnabled,\n semanticMatch: tombstonesSemanticMatch,\n semanticThreshold: tombstonesSemanticThreshold,\n namespace: config.defaultNamespace,\n });\n this.storageRouter.bindTombstonesConfig(this.storage, config.defaultNamespace, {\n enabled: tombstonesEnabled,\n semanticMatch: tombstonesSemanticMatch,\n semanticThreshold: tombstonesSemanticThreshold,\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 (resolveRecallAuxiliaryCapabilities(config).secureStore) {\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 this.maintenanceScheduler = new MaintenanceScheduler({\n config,\n // Live accessor: the orchestrator reassigns this.qmd to NoopSearchBackend\n // after construction when the collection is missing (initialize /\n // startupSearchSync); the scheduler must read the current backend so\n // debounced maintenance never runs against a stale/disposed one.\n getQmd: () => this.qmd,\n namespaceSearchRouter: this.namespaceSearchRouter,\n namespaceCatalog: this.namespaceCatalog,\n });\n // Issue #1526: background extraction queue lives on its own coordinator.\n this.extractionQueueCoordinator = new ExtractionQueueCoordinator();\n\n this.recallResultFormatter = new RecallResultFormatter(this.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 = resolveConversationContextCapabilities(this.config).sharedContext\n ? new SharedContextManager(config)\n : undefined;\n this.compounding = resolveConsolidationCapabilities(config).compounding\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.conversationIndexCoordinator = new ConversationIndexCoordinator({\n config,\n getTranscript: () => this.transcript,\n getBackend: () => this.conversationIndexBackend,\n indexDir: this.conversationIndexDir,\n });\n this.recallRerankCoordinator = new RecallRerankCoordinator({\n getConfig: () => this.config,\n getStorage: (namespace) => this.getStorage(namespace),\n readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) =>\n this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces),\n });\n this.recallSectionCoordinator = new RecallSectionCoordinator({\n getConfig: () => this.config,\n resolveSectionEnabled: (id, def) => this.isRecallSectionEnabled(id, def),\n });\n this.contradictionLinkingCoordinator = new ContradictionLinkingCoordinator({\n getConfig: () => this.config,\n isSearchAvailable: () => this.isSearchAvailableForNamespaceRouting(),\n searchAcrossNamespaces: (options) => this.searchAcrossNamespaces(options),\n extractMemoryIdsFromResults: (results) => this.extractMemoryIdsFromResults(results),\n namespaceFromPath: (p) => this.namespaceFromPath(p),\n storageForNamespace: (namespace) => this.storageRouter.storageFor(namespace),\n getExtraction: () => this.extraction,\n });\n this.modelRegistry = new ModelRegistry(config.memoryDir);\n this.graphRecallCoordinator = new GraphRecallCoordinator({\n getConfig: () => this.config,\n getStorage: () => this.storage,\n storageFor: (namespace) => this.storageRouter.storageFor(namespace),\n graphIndexFor: (storage) => this.graphIndexFor(storage),\n namespaceFromPath: (p) => this.namespaceFromPath(p),\n resolveColdQmdResultForRecall: (result, fallbackStorage, recallNamespaces) =>\n this.resolveColdQmdResultForRecall(result, fallbackStorage, recallNamespaces),\n storageForAbsoluteQmdResultPath: (resultPath, fallbackStorage, recallNamespaces) =>\n this.storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces),\n readQmdResultMemory: (resultPath, fallbackStorage, recallNamespaces) =>\n this.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces),\n });\n this.relevance = new RelevanceStore(config.memoryDir);\n this.negatives = new NegativeExampleStore(config.memoryDir);\n this.lastRecall = new LastRecallStore(config.memoryDir);\n this.handleHistory = new RecallHandleHistoryStore(config.memoryDir, {\n maxDepth: config.recallHandleSnapshotDepth,\n });\n this.tierMigrationStatus = new TierMigrationStatusStore(config.memoryDir);\n this.tierMigrationCoordinator = new TierMigrationCoordinator({\n config,\n getQmd: () => this.qmd,\n tierMigrationStatus: this.tierMigrationStatus,\n getUtilityRuntimeValues: () => this.utilityRuntimeValues,\n getCompounding: () => this.compounding,\n createColdStorage: (parentDir) => new StorageManager(parentDir),\n });\n this.compressionGuidelineCoordinator = new CompressionGuidelineCoordinator({\n config,\n getStorage: () => this.storage,\n fastChatCompletion: (messages, options) =>\n this.fastChatCompletion(messages, options),\n });\n this.entitySynthesisCoordinator = new EntitySynthesisCoordinator({\n config,\n getStorage: (namespace) => this.getStorage(namespace),\n fastChatCompletion: (messages, options) =>\n this.fastChatCompletion(messages, options),\n });\n this.qmdResultResolver = new QmdResultResolver({\n getConfig: () => this.config,\n storageFor: (namespace) => this.storageRouter.storageFor(namespace),\n storageDirNamespace: (storageDir) => this.storageDirNamespace(storageDir),\n qmdCollectionNamespaceFromPrefix: (prefix) => this.qmdCollectionNamespaceFromPrefix(prefix),\n namespaceFromPath: (p) => this.namespaceFromPath(p),\n });\n\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 = resolvePipelineProcessingCapabilities(this.config).localLlmFast\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 this.semanticConsolidationCoordinator = new SemanticConsolidationCoordinator({\n config,\n getStorage: () => this.storage,\n getFastLlm: () => this.fastLlm,\n embeddingFallback: this.embeddingFallback,\n removeContentHashForMemory: (targetStorage, memory, context) =>\n this.removeContentHashForMemory(targetStorage, memory, context),\n saveContentHashIndexes: () => this.saveContentHashIndexes(),\n });\n // Initialize gateway fast LLM for fast-tier ops when modelSource is \"gateway\"\n this._fastGatewayLlm = config.modelSource === \"gateway\"\n ? new FallbackLlmClient(\n config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(config),\n )\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.lifecyclePolicyCoordinator = new LifecyclePolicyCoordinator({\n config,\n getStorage: () => this.storage,\n extraction: this.extraction,\n embeddingFallback: this.embeddingFallback,\n getEffectiveLifecycleThresholds: () => this.effectiveLifecycleThresholds(),\n removeContentHashForMemory: (targetStorage, memory, context) =>\n this.removeContentHashForMemory(targetStorage, memory, context),\n saveContentHashIndexes: () => this.saveContentHashIndexes(),\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 const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);\n // Temporal Memory Tree (v8.2) — lazy build during consolidation\n this.tmtBuilder = new TmtBuilder(config.memoryDir, {\n temporalMemoryTreeEnabled: lifecycleCaps.temporalMemoryTree,\n tmtHourlyMinMemories: config.tmtHourlyMinMemories,\n tmtSummaryMaxTokens: config.tmtSummaryMaxTokens,\n });\n\n // Lossless Context Management (LCM) — proactive session archive + DAG summarization\n if (resolvePipelineProcessingCapabilities(this.config).lcm) {\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 messages = [\n { role: \"system\" as const, content: instructionText },\n { role: \"user\" as const, content: text.slice(0, 12000) },\n ];\n const result = this.config.modelSource === \"gateway\" && this._fastGatewayLlm\n ? await this._fastGatewayLlm.chatCompletion(messages, {\n maxTokens: targetTokens * 2,\n timeoutMs: this.config.localLlmFastTimeoutMs,\n // LCM is latency-sensitive. A configured fast persona is the\n // explicit fast-tier route; otherwise use taskModelChain so LCM\n // avoids falling to an expensive gateway default. Issue #1473.\n ...(this.config.fastGatewayAgentId\n ? { agentId: this.config.fastGatewayAgentId }\n : gatewayTaskChainOptions(this.config)),\n })\n : await this.localLlm.chatCompletion(messages, {\n maxTokens: targetTokens * 2,\n operation: \"lcm-summarize\",\n priority: \"background\",\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: resolvePresentationCapabilities(this.config).memoryBoxes,\n traceWeaverEnabled: resolvePipelineProcessingCapabilities(this.config).traceWeaver,\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 = resolveNamespaceCapabilities(this.config).namespaces\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 (!resolvePipelineProcessingCapabilities(this.config).routingRules) 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 return this.namespaceReadFanoutCoordinator.resolveArtifactSourceStatuses(\n storage,\n sourceIds,\n );\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, {\n ...options,\n forceDisableThinking: true,\n });\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 {\n chatCompletion: (messages, options) =>\n this.fastLlm.chatCompletion(messages, {\n ...(options ?? {}),\n forceDisableThinking: true,\n }),\n };\n }\n\n /**\n * Build a briefing follow-up generator backed by the configured LLM chain\n * (gateway model source or local LLM). Returns `undefined` when no chain\n * is available so `buildBriefing` can surface a clear unavailable reason\n * instead of failing at call time. Used by the access service and CLI as\n * the fallback when no direct `openaiApiKey` is configured, so briefing\n * follow-ups ride the same routing as every other fast-tier LLM feature.\n */\n get briefingChainFollowupGenerator(): BriefingFollowupGenerator | undefined {\n // Plugin mode gates on `localLlmEnabled` alone: `LocalLlmClient.chatCompletion`\n // returns null when the master switch is off, so `localLlmFastEnabled` by\n // itself cannot serve requests (Cursor review on PR #1463).\n const chainAvailable =\n this.config.modelSource === \"gateway\"\n ? this._fastGatewayLlm?.isAvailable(\n this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined,\n ) === true\n : resolveLocalLlmCapabilities(this.config).localLlm;\n if (!chainAvailable) return undefined;\n return buildChainFollowupGenerator(this.fastLlmForRerank);\n }\n\n async initialize(): Promise<void> {\n return this.orchestratorInitCoordinator.initialize(\n );\n }\n\n private async deferredInitialize(signal: AbortSignal): Promise<void> {\n return this.orchestratorInitCoordinator.deferredInitialize(\n signal,\n );\n }\n\n async startupSearchSync(signal?: AbortSignal): Promise<boolean> {\n return this.orchestratorInitCoordinator.startupSearchSync(\n signal,\n );\n }\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 return this.workspaceOpsCoordinator.runPatternReinforcement(\n options,\n );\n }\n\n async runPatternReinforcementFanout(options: {\n force?: boolean;\n } = {}): Promise<NamespaceMaintenanceSummary> {\n return this.workspaceOpsCoordinator.runPatternReinforcementFanout(\n options,\n );\n }\n\n /**\n * Fan out lifecycle/governance policy across all maintained namespaces\n * (issue #1500). Each namespace gets its own lifecycle pass against its\n * namespace-scoped storage. When namespaces are disabled, runs once against\n * default storage.\n */\n async runLifecyclePolicyFanout(): Promise<NamespaceMaintenanceSummary> {\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);\n return this.runNamespaceMaintenanceFanoutForJob(\n \"lifecycle\",\n async (ctx) => {\n const storage = await this.getStorage(ctx.candidate.namespace);\n const corpus = await storage.readAllMemories();\n const assessed = await this.runLifecyclePolicyPass(corpus, storage);\n return { itemCount: assessed };\n },\n { enabled: lifecycleCaps.lifecyclePolicy },\n );\n }\n\n /**\n * Fan out semantic consolidation across all maintained namespaces (issue #1500).\n * Each namespace gets its own consolidation pass against its namespace-scoped\n * storage. When namespaces are disabled, runs once against default storage.\n */\n async runSemanticConsolidationFanout(options: {\n dryRun?: boolean;\n } = {}): Promise<NamespaceMaintenanceSummary> {\n return this.runNamespaceMaintenanceFanoutForJob(\n \"semantic-consolidation\",\n async (ctx) => {\n const storage = await this.getStorage(ctx.candidate.namespace);\n const result = await this.runSemanticConsolidation({\n dryRun: options.dryRun,\n thresholdOverride: undefined,\n force: true,\n storage,\n });\n return { itemCount: result.clustersFound };\n },\n { enabled: resolveConsolidationCapabilities(this.config).semanticConsolidation },\n );\n }\n\n /**\n * Fan out deep-sleep governance across all maintained namespaces (issue #1500).\n * Each namespace gets its own governance scan against its namespace-scoped\n * storage. When namespaces are disabled, runs once against default storage.\n */\n async runDeepSleepGovernanceFanout(options: {\n dryRun?: boolean;\n } = {}): Promise<NamespaceMaintenanceSummary> {\n return this.runNamespaceMaintenanceFanoutForJob(\n \"governance\",\n async (ctx) => {\n const storage = await this.getStorage(ctx.candidate.namespace);\n const result = await this.runDeepSleepGovernanceNow({\n dryRun: options.dryRun,\n storage,\n });\n return { itemCount: result.scannedMemories };\n },\n { enabled: this.config.dreamsPhases.deepSleep.enabled },\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 return this.workspaceOpsCoordinator.maybeRunFileHygiene(\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.storageDirNamespace(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 // Issue #1526 (seam 5): semantic consolidation moved to\n // SemanticConsolidationCoordinator. Thin delegation keeps all\n // call sites (runConsolidation, runSemanticConsolidationNow,\n // runSemanticConsolidationFanout) stable.\n private async runSemanticConsolidation(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n force?: boolean;\n storage?: StorageManager;\n }): Promise<SemanticConsolidationResult> {\n return this.semanticConsolidationCoordinator.runSemanticConsolidation(options);\n }\n\n async waitForExtractionIdle(timeoutMs: number = 60_000): Promise<boolean> {\n // Issue #1526: queue state + idle wait moved to ExtractionQueueCoordinator.\n return this.extractionQueueCoordinator.waitForIdle(timeoutMs);\n }\n\n async waitForConsolidationIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.maintenanceScheduler.isConsolidationInFlight()) {\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 // Issue #1526: entity synthesis lifecycle moved to EntitySynthesisCoordinator.\n // Thin delegation keeps all call sites (consolidation pass, access-service)\n // and tests that exercise the public API working unchanged.\n return this.entitySynthesisCoordinator.processQueue(namespace, maxEntities);\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 options: DaySummaryGatherOptions = {},\n ): Promise<DaySummaryResult | null> {\n const gathered = await this.gatherTodayFacts(namespace, options);\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 async gatherTodayFacts(\n namespace?: string,\n options: DaySummaryGatherOptions = {},\n ): Promise<string> {\n return this.workspaceOpsCoordinator.gatherTodayFacts(\n namespace,\n options,\n );\n }\n\n previewMemoryActionEvent(\n event: Omit<MemoryActionEvent, \"timestamp\"> & { timestamp?: string },\n ): MemoryActionEvent {\n return this.workspaceOpsCoordinator.previewMemoryActionEvent(\n event,\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 return this.recallIntrospectionCoordinator.getLastGraphRecallSnapshot(\n namespace,\n );\n }\n\n async getLastIntentSnapshot(\n namespace?: string,\n ): Promise<IntentDebugSnapshot | null> {\n return this.recallIntrospectionCoordinator.getLastIntentSnapshot(\n namespace,\n );\n }\n\n async getLastQmdRecallSnapshot(\n namespace?: string,\n ): Promise<QmdRecallSnapshot | null> {\n return this.recallIntrospectionCoordinator.getLastQmdRecallSnapshot(\n namespace,\n );\n }\n\n async explainLastGraphRecall(options?: {\n namespace?: string;\n maxExpanded?: number;\n }): Promise<string> {\n return this.recallIntrospectionCoordinator.explainLastGraphRecall(\n options,\n );\n }\n\n async explainLastIntent(options?: { namespace?: string }): Promise<string> {\n return this.recallIntrospectionCoordinator.explainLastIntent(\n options,\n );\n }\n\n async explainLastQmdRecall(options?: {\n namespace?: string;\n maxResults?: number;\n }): Promise<string> {\n return this.recallIntrospectionCoordinator.explainLastQmdRecall(\n options,\n );\n }\n\n private async searchConversationRecallResults(\n retrievalQuery: string,\n topK: number,\n ): Promise<Array<{ path: string; snippet: string; score: number }>> {\n return this.conversationIndexCoordinator.search(retrievalQuery, topK);\n }\n\n private formatConversationRecallSection(\n results: Array<{ path: string; snippet: string; score: number }>,\n maxChars: number,\n ): string | null {\n return this.conversationIndexCoordinator.formatRecallSection(\n results,\n maxChars,\n );\n }\n\n // Issue #1526: countConversationChunkDocs / buildConversationIndexChunks moved\n // to ConversationIndexCoordinator (internal helpers, no orchestrator callers).\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 return this.conversationIndexCoordinator.getHealth();\n }\n\n async inspectConversationIndex(): Promise<\n ConversationIndexBackendInspection & {\n enabled: boolean;\n chunkDocCount: number;\n lastUpdateAt: string | null;\n }\n > {\n return this.conversationIndexCoordinator.inspect();\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 return this.conversationIndexCoordinator.update(sessionKey, hours, opts);\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 return this.conversationIndexCoordinator.rebuild(sessionKey, hours, opts);\n }\n\n private async validateLocalLlmModel(): Promise<void> {\n return this.workspaceOpsCoordinator.validateLocalLlmModel(\n );\n }\n\n async recall(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n ): Promise<string> {\n // Resolve the recall-operation capability gates ONCE, at the operation\n // entry, and thread the frozen set down (issue #1523). Never re-read the\n // migrated flags off `this.config` mid-operation.\n const caps = resolveCapabilities(this.config);\n const graphCaps = resolveGraphConstructionCapabilities(this.config); // #1566 Cluster A\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 const principal =\n typeof options.principalOverride === \"string\" &&\n options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const namespacesEnabled = resolveNamespaceCapabilities(this.config).namespaces;\n if (namespacesEnabled && !principal) {\n throw new Error(\"authentication required: namespaces are enabled and no principal was supplied\");\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 (resolveRecallAuxiliaryCapabilities(this.config).secureStore && !this.storage.isSecureStoreUnlocked()) {\n const lockedMsg =\n \"[secure-store locked] Memory store is encrypted and locked. \" +\n \"Unlock the secure-store inside this daemon process, or restart the daemon through a secure-store aware launcher that installs the key.\";\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 }, caps, graphCaps);\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 (caps.recallDirectAnswer && sessionKey) {\n try {\n this.enqueueDirectAnswerObservation(\n prompt,\n sessionKey,\n options.namespace?.trim() || undefined,\n options.principalOverride,\n caps,\n namespacesEnabled,\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 async waitForDirectAnswerObservationIdle(\n timeoutMs: number = 60_000,\n ): Promise<boolean> {\n return this.recallIntrospectionCoordinator.waitForDirectAnswerObservationIdle(\n timeoutMs,\n );\n }\n\n private enqueueDirectAnswerObservation(\n prompt: string,\n sessionKey: string,\n namespaceOverride: string | undefined,\n principalOverride: string | undefined,\n caps: CapabilitySet,\n namespacesEnabled: boolean,\n ): void {\n return this.recallIntrospectionCoordinator.enqueueDirectAnswerObservation(\n prompt,\n sessionKey,\n namespaceOverride,\n principalOverride,\n caps,\n namespacesEnabled,\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 caps: CapabilitySet,\n _parentAbortSignal?: AbortSignal,\n ): Promise<void> {\n return this.recallIntrospectionCoordinator.annotateDirectAnswerTier(\n prompt,\n sessionKey,\n namespaces,\n expectedIdentity,\n caps,\n _parentAbortSignal,\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 return this.recallSearchPipelineCoordinator.fetchActiveArtifactsForNamespace(\n namespace,\n prompt,\n targetCount,\n );\n }\n\n private async recallArtifactsAcrossNamespaces(\n prompt: string,\n recallNamespaces: string[],\n targetCount: number,\n ): Promise<MemoryFile[]> {\n return this.namespaceReadFanoutCoordinator.recallArtifactsAcrossNamespaces(\n prompt,\n recallNamespaces,\n targetCount,\n );\n }\n\n private scopeQueryAwarePaths(\n paths: Set<string> | null,\n recallNamespaces: string[],\n ): Set<string> | null {\n if (!paths) return null;\n const scoped = new Set<string>();\n for (const memoryPath of paths) {\n if (!memoryPath || isArtifactMemoryPath(memoryPath)) continue;\n if (\n resolveNamespaceCapabilities(this.config).namespaces &&\n !recallNamespaces.includes(this.namespaceFromPath(memoryPath))\n ) {\n continue;\n }\n scoped.add(memoryPath);\n }\n return scoped;\n }\n\n private async buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter> {\n return this.recallSearchPipelineCoordinator.buildQueryAwarePrefilter(\n prompt,\n recallNamespaces,\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 return this.namespaceReadFanoutCoordinator.searchScopedMemoryCandidates(\n candidatePaths,\n query,\n limit,\n options,\n );\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 /** Backend degradation observer, threaded into every QMD call (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]> {\n return this.recallSearchPipelineCoordinator.fetchQmdMemoryResultsWithArtifactTopUp(\n prompt,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n options,\n );\n }\n\n // Issue #1526 (seam 14): graph-recall expansion moved to\n // GraphRecallCoordinator. Thin delegation keeps the private API stable\n // for callers (recallInternal, cold-fallback pipeline) + tests.\n private async expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n deadlineAtMs?: number | null;\n includeLowConfidence?: boolean;\n }): Promise<{\n merged: QmdSearchResult[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n seedResults: QmdSearchResult[];\n }> {\n return this.graphRecallCoordinator.expandResultsViaGraph(options);\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 return this.recallIntrospectionCoordinator.recordLastGraphRecallSnapshot(\n options,\n );\n }\n private async recordLastIntentSnapshot(options: {\n storage: StorageManager;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n return this.recallIntrospectionCoordinator.recordLastIntentSnapshot(\n options,\n );\n }\n\n private async recordLastQmdRecallSnapshot(options: {\n storage: StorageManager;\n snapshot: QmdRecallSnapshot;\n }): Promise<void> {\n return this.recallIntrospectionCoordinator.recordLastQmdRecallSnapshot(\n options,\n );\n }\n\n private async recordLastIntentSnapshotForNamespace(options: {\n namespace: string;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n return this.recallIntrospectionCoordinator.recordLastIntentSnapshotForNamespace(\n options,\n );\n }\n\n private async resolveStateDirForNamespace(\n namespace: string,\n ): Promise<string> {\n return this.namespaceReadFanoutCoordinator.resolveStateDirForNamespace(\n namespace,\n );\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 // Issue #1526 (seam 13): recall section budgeting/assembly moved to\n // RecallSectionCoordinator. Thin delegation keeps the orchestrator's\n // recallInternal call sites stable.\n private getRecallSectionEntry(\n sectionId: string,\n ): RecallSectionConfig | undefined {\n return this.recallSectionCoordinator.getRecallSectionEntry(sectionId);\n }\n\n private isRecallSectionEnabled(\n sectionId: string,\n defaultEnabled: boolean = true,\n ): boolean {\n return this.recallSectionCoordinator.isRecallSectionEnabled(\n sectionId,\n defaultEnabled,\n );\n }\n\n private isSpecializedRecallSectionEnabled(\n sectionId: string,\n topLevelEnabled: boolean,\n ): boolean {\n return this.recallSectionCoordinator.isSpecializedRecallSectionEnabled(\n sectionId,\n topLevelEnabled,\n );\n }\n\n private getRecallSectionMaxChars(\n sectionId: string,\n ): number | null | undefined {\n return this.recallSectionCoordinator.getRecallSectionMaxChars(sectionId);\n }\n\n private getRecallSectionNumber(\n sectionId: string,\n key: keyof RecallSectionConfig,\n ): number | undefined {\n return this.recallSectionCoordinator.getRecallSectionNumber(sectionId, key);\n }\n\n private appendRecallSection(\n sectionBuckets: Map<string, string[]>,\n sectionId: string,\n content: string,\n ): boolean {\n return this.recallSectionCoordinator.appendRecallSection(\n sectionBuckets,\n sectionId,\n content,\n );\n }\n\n private truncateRecallSectionToBudget(\n content: string,\n maxChars: number,\n ): string {\n return this.recallSectionCoordinator.truncateRecallSectionToBudget(\n content,\n maxChars,\n );\n }\n\n private getRecallBudgetChars(override?: number): number {\n return this.recallSectionCoordinator.getRecallBudgetChars(override);\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 return this.recallSectionCoordinator.assembleRecallSections(\n sectionBuckets,\n budgetOverride,\n );\n }\n\n\n /**\n * Clock source for the shared post-retrieval assembly/enrichment budget. The\n * deadline is set from this value and every expiry check reads it back, so a\n * test can drive the budget deterministically instead of racing the few-ms\n * wall-clock window that made the \"skips … after budget expires\" tests flaky.\n * Production behavior is unchanged — it returns the wall clock.\n */\n protected recallAssemblyClockMs(): number {\n return Date.now();\n }\n\n /**\n * Recall-internal coordinator (issue #1526 seam 18). Owns the full\n * `recallInternal` assembly pipeline. Lazy: created on first access so\n * Object.create(prototype) tests that set fields post-construction work,\n * and so subclass/test overrides of orchestrator members (e.g. the\n * `recallAssemblyClockMs` clock seam) are observed live via accessors.\n */\n private _recallInternalCoordinator: RecallInternalCoordinator | undefined;\n\n private get recallInternalCoordinator(): RecallInternalCoordinator {\n if (!this._recallInternalCoordinator) {\n this._recallInternalCoordinator = new RecallInternalCoordinator(\n selfDeps<ConstructorParameters<typeof RecallInternalCoordinator>[0]>(this),\n );\n }\n return this._recallInternalCoordinator;\n }\n\n /**\n * Recall search-pipeline coordinator (issue #1526 seam 19). Owns QMD\n * search post-processing (prefilter, fallbacks, safety filter, boost).\n * Lazy + accessor-wired for the same reasons as seam 18: instance-level\n * test overrides of orchestrator members must stay live.\n */\n private _recallSearchPipelineCoordinator: RecallSearchPipelineCoordinator | undefined;\n\n private get recallSearchPipelineCoordinator(): RecallSearchPipelineCoordinator {\n if (!this._recallSearchPipelineCoordinator) {\n this._recallSearchPipelineCoordinator = new RecallSearchPipelineCoordinator(\n selfDeps<ConstructorParameters<typeof RecallSearchPipelineCoordinator>[0]>(this),\n );\n }\n return this._recallSearchPipelineCoordinator;\n }\n\n /**\n * Turn-ingestion coordinator (issue #1526 seam 20). Owns the buffer-side\n * extraction entry points. Lazy + accessor-wired so prototype-call tests\n * and instance-level stubs stay live (same rule as seams 18/19).\n */\n private _turnIngestionCoordinator: TurnIngestionCoordinator | undefined;\n\n private get turnIngestionCoordinator(): TurnIngestionCoordinator {\n if (!this._turnIngestionCoordinator) {\n this._turnIngestionCoordinator = new TurnIngestionCoordinator(\n selfDeps<ConstructorParameters<typeof TurnIngestionCoordinator>[0]>(this),\n );\n }\n return this._turnIngestionCoordinator;\n }\n\n /**\n * Recall-introspection coordinator (issue #1526 seam 21). Owns the\n * last-recall snapshot/explain surfaces and direct-answer annotation.\n * Lazy + accessor-wired (late-binding rule, seams 18–20).\n */\n private _recallIntrospectionCoordinator: RecallIntrospectionCoordinator | undefined;\n\n private get recallIntrospectionCoordinator(): RecallIntrospectionCoordinator {\n if (!this._recallIntrospectionCoordinator) {\n this._recallIntrospectionCoordinator = new RecallIntrospectionCoordinator(\n selfDeps<ConstructorParameters<typeof RecallIntrospectionCoordinator>[0]>(this),\n );\n }\n return this._recallIntrospectionCoordinator;\n }\n\n /**\n * Orchestrator-init coordinator (issue #1526 seam 22). Owns\n * initialize/deferredInitialize/startupSearchSync. Lazy + accessor-wired\n * (late-binding rule, seams 18–21); the init gate fields stay on the\n * orchestrator and are mutated through set accessors.\n */\n private _orchestratorInitCoordinator: OrchestratorInitCoordinator | undefined;\n\n private get orchestratorInitCoordinator(): OrchestratorInitCoordinator {\n if (!this._orchestratorInitCoordinator) {\n this._orchestratorInitCoordinator = new OrchestratorInitCoordinator(\n selfDeps<ConstructorParameters<typeof OrchestratorInitCoordinator>[0]>(this),\n );\n }\n return this._orchestratorInitCoordinator;\n }\n\n /**\n * Persistence-index coordinator (issue #1526 seam 23). Owns post-persist\n * bookkeeping (content-hash dedup, temporal indexes, graph edges,\n * semantic dedup lookup). Lazy + accessor-wired (late-binding rule).\n */\n private _persistenceIndexCoordinator: PersistenceIndexCoordinator | undefined;\n\n private get persistenceIndexCoordinator(): PersistenceIndexCoordinator {\n if (!this._persistenceIndexCoordinator) {\n this._persistenceIndexCoordinator = new PersistenceIndexCoordinator(\n selfDeps<ConstructorParameters<typeof PersistenceIndexCoordinator>[0]>(this),\n );\n }\n return this._persistenceIndexCoordinator;\n }\n\n /**\n * Workspace-ops coordinator (issue #1526 seam 24). Owns periodic\n * workspace/operations surfaces. Lazy + accessor-wired (late-binding\n * rule, seams 18–23).\n */\n private _workspaceOpsCoordinator: WorkspaceOpsCoordinator | undefined;\n\n private get workspaceOpsCoordinator(): WorkspaceOpsCoordinator {\n if (!this._workspaceOpsCoordinator) {\n this._workspaceOpsCoordinator = new WorkspaceOpsCoordinator(\n selfDeps<ConstructorParameters<typeof WorkspaceOpsCoordinator>[0]>(this),\n );\n }\n return this._workspaceOpsCoordinator;\n }\n\n /**\n * Namespace read-fanout coordinator (issue #1526 seam 26). Owns\n * namespace-scoped read fanout (hints, cross-namespace search/reads,\n * artifact statuses). Lazy + accessor-wired (late-binding rule).\n */\n private _namespaceReadFanoutCoordinator: NamespaceReadFanoutCoordinator | undefined;\n\n private get namespaceReadFanoutCoordinator(): NamespaceReadFanoutCoordinator {\n if (!this._namespaceReadFanoutCoordinator) {\n this._namespaceReadFanoutCoordinator = new NamespaceReadFanoutCoordinator(\n selfDeps<ConstructorParameters<typeof NamespaceReadFanoutCoordinator>[0]>(this),\n );\n }\n return this._namespaceReadFanoutCoordinator;\n }\n\n private async recallInternal(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n caps: CapabilitySet = resolveCapabilities(this.config),\n graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),\n lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.config),\n ): Promise<string> {\n return this.recallInternalCoordinator.recallInternal(\n prompt,\n sessionKey,\n options,\n caps,\n graphCaps,\n lifecycleCaps,\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 return this.turnIngestionCoordinator.processTurn(\n role,\n content,\n sessionKey,\n options,\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: {\n deadlineMs?: number;\n archiveLcm?: boolean;\n abortSignal?: AbortSignal;\n /**\n * Pin extraction writes to this namespace instead of deriving one from\n * `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))` + the\n * coding overlay (#1495). The access `observe` surface resolves a single\n * effective scope plan and passes its `writeNamespace` here so the\n * extracted memories land in the SAME namespace as LCM archival,\n * objective-state snapshots, and project-scoped recall — without relying\n * on re-deriving the namespace from a namespace-prefixed session key.\n * Same hook bulk-import uses (#460).\n */\n writeNamespaceOverride?: string;\n /**\n * Pin the provenance PRINCIPAL instead of deriving it from\n * `resolvePrincipal(turn.sessionKey)` (#1495 thread 1). The access\n * `observe` surface authenticates the caller at the transport layer and\n * passes its resolved principal here so extracted-memory provenance uses\n * the SAME identity the surface authorized — independent of storage\n * routing (`writeNamespaceOverride`) and of whatever `resolvePrincipal`\n * would parse from the raw session key. Mirrors the recall path's\n * `principalOverride` (issue #570 PR 4).\n */\n principalOverride?: string;\n } = {},\n ): Promise<void> {\n return this.turnIngestionCoordinator.ingestReplayBatch(\n turns,\n options,\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 getWearablesService(): WearablesService {\n return this.workspaceOpsCoordinator.getWearablesService(\n );\n }\n\n async ingestBulkImportBatch(\n turns: ImportTurn[],\n options: {\n deadlineMs?: number;\n failOnExtractionFailure?: boolean;\n includeSourceValidAtContext?: boolean;\n } = {},\n ): Promise<BulkImportBatchIngestResult> {\n return this.turnIngestionCoordinator.ingestBulkImportBatch(\n turns,\n options,\n );\n }\n\n async observeSessionHeartbeat(\n sessionKey: string,\n options: { bufferKey?: string } = {},\n ): Promise<void> {\n return this.turnIngestionCoordinator.observeSessionHeartbeat(\n sessionKey,\n options,\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 skipUserTurnThreshold?: boolean;\n extractionDeadlineMs?: number;\n failOnExtractionFailure?: boolean;\n onTaskSettled?: (\n error?: unknown,\n result?: ExtractionRunResult,\n ) => 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 * Pin the provenance principal (#1495 thread 1). Forwarded to\n * `runExtraction` so access `observe` can record provenance under the\n * authenticated principal instead of `resolvePrincipal(sessionKey)`.\n */\n principalOverride?: string;\n } = {},\n ): Promise<void> {\n return this.turnIngestionCoordinator.queueBufferedExtraction(\n turnsToExtract,\n reason,\n options,\n );\n }\n\n private normalizeExtractionFingerprintTurns(turns: BufferTurn[]): string[] {\n return this.extractionRunCoordinator.normalizeExtractionFingerprintTurns(turns);\n }\n\n private buildExtractionFingerprint(turns: BufferTurn[], bufferKey: string): string | null {\n return this.extractionRunCoordinator.buildExtractionFingerprint(turns, bufferKey);\n }\n\n private shouldQueueExtraction(\n turns: BufferTurn[],\n options: { commit?: boolean; bufferKey?: string } = {},\n ): boolean {\n return this.extractionRunCoordinator.shouldQueueExtraction(turns, options);\n }\n\n private async maybeCapturePassiveCorrections(\n turns: readonly BufferTurn[],\n opts: {\n sessionKey: string;\n principal?: string;\n namespace: string;\n bufferKey: string;\n isLiveSession: boolean;\n },\n ): Promise<void> {\n return this.turnIngestionCoordinator.maybeCapturePassiveCorrections(\n turns,\n opts,\n );\n }\n\n /** Lazily construct the CorrectionService for passive capture. Stateless\n * across requests (per #1580 design); cached for the orchestrator's life. */\n private passiveCorrectionService(): CorrectionService {\n if (this._passiveCorrectionService) return this._passiveCorrectionService;\n this._passiveCorrectionService = createCorrectionService({\n orchestrator: this,\n // Session-scoped write ACL (review: \"passive capture bypasses write\n // ACL\"). A correction detected in session S plans only against S readable\n // namespaces and applies only to writable ones (rule 42) — passive\n // capture never becomes a cross-tenant mutation vector. Mirrors the\n // access-service createCorrectionService wiring rather than bypassing it.\n resolveAuthorizedNamespace: async (req) => {\n const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);\n const ns = req.namespace ?? defaultNamespaceForPrincipal(principal, this.config);\n if (!canWriteNamespace(principal, ns, this.config)) {\n throw new Error(\n `passive correction: namespace \"${ns}\" is not writable for principal ${principal ?? \"(none)\"}`,\n );\n }\n return ns;\n },\n resolveReadableNamespaces: (req) => {\n const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);\n return recallNamespacesForPrincipal(principal, this.config);\n },\n canWriteNamespace: async (req) => {\n const principal = req.principal || resolvePrincipal(req.sessionKey, this.config);\n return canWriteNamespace(principal, req.namespace, this.config);\n },\n llmComplete: async ({ system, user }) => {\n const llmResult = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: system },\n { role: \"user\", content: user },\n ],\n { operation: \"correction-classify\", priority: \"background\" },\n );\n if (!llmResult) {\n throw new Error(\n \"passive correction classify+draft: local LLM unavailable (disabled or in cooldown)\",\n );\n }\n return llmResult.content;\n },\n });\n return this._passiveCorrectionService;\n }\n\n async runExtraction(\n ...args: Parameters<ExtractionRunCoordinator[\"runExtraction\"]>\n ): Promise<ExtractionRunResult> {\n return this.extractionRunCoordinator.runExtraction(...args);\n }\n\n private async recordProcessedExtractionFingerprint(\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>,\n ): Promise<void> {\n return this.extractionRunCoordinator.recordProcessedExtractionFingerprint(\n storage, fingerprint, preloadedMeta,\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 return this.tierMigrationCoordinator.runCycle(storage, trigger, options);\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 this.maintenanceScheduler.maybeScheduleConsolidation(\n nonZeroExtraction,\n () => this.runConsolidation(),\n );\n }\n\n requestQmdMaintenance(): void {\n this.maintenanceScheduler.requestQmdMaintenanceForTool(\"__internal__\");\n }\n\n /**\n * Public entrypoint for tool-driven QMD maintenance requests.\n * Delegates to the maintenance scheduler (issue #1526 PR1).\n */\n requestQmdMaintenanceForTool(reason: string): void {\n this.maintenanceScheduler.requestQmdMaintenanceForTool(reason);\n }\n\n private async persistExtraction(\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: { sessionKey?: string; principal?: string; validAt?: string },\n baseNamespace?: string,\n scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,\n /** Verbatim source turn text the facts were extracted from (faithfulness gate #1576). */\n sourceText?: string,\n graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),\n lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.config),\n ): Promise<string[]> {\n return this.extractionPersistCoordinator.persistExtraction(\n result,\n storage,\n threadIdForExtraction,\n sourceContext,\n baseNamespace,\n scopeProfileWritePlan,\n sourceText,\n graphCaps,\n lifecycleCaps,\n );\n }\n /**\n * Append persisted ids to the thread episode set, excluding pending_review\n * fact ids (#1635) so they don't re-seed predecessor edges. Fail-open like\n * the raw appendEpisodeIds call it replaces.\n */\n private async appendPersistedThreadEpisodes(\n threadId: string,\n persistedIds: string[],\n ): Promise<void> {\n const pendingReviewIds = this.lastPersistExtractionPendingReviewIds ?? [];\n const episodeIds =\n pendingReviewIds.length > 0\n ? persistedIds.filter((id) => !pendingReviewIds.includes(id))\n : persistedIds;\n if (episodeIds.length === 0) return;\n try {\n await this.threading.appendEpisodeIds(threadId, episodeIds);\n } catch (err) {\n log.warn(\n \"[threading] appendEpisodeIds failed after persistence (non-fatal)\",\n err,\n );\n }\n }\n\n private async indexPersistedMemory(\n storage: StorageManager,\n memoryId: string,\n ): Promise<void> {\n return this.persistenceIndexCoordinator.indexPersistedMemory(\n storage,\n memoryId,\n );\n }\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 graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.config),\n ): Promise<void> {\n return this.persistenceIndexCoordinator.buildGraphEdge(\n storage,\n memoryRelPath,\n entityRef,\n memoryId,\n factContent,\n allMemsForGraph,\n memoryPathById,\n threadIdForEdge,\n threadEpisodeIdsForGraph,\n fallbackCausalPredecessor,\n graphCaps,\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 private async updateTemporalTagIndexes(\n storage: StorageManager,\n persistedIds: string[],\n ): Promise<void> {\n return this.persistenceIndexCoordinator.updateTemporalTagIndexes(\n storage,\n persistedIds,\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 return this.consolidationRunCoordinator.run();\n }\n\n async optimizeCompressionGuidelines(options?: {\n dryRun?: boolean;\n eventLimit?: number;\n }) {\n return this.compressionGuidelineCoordinator.optimizeCompressionGuidelines(options);\n }\n\n async activateCompressionGuidelineDraft(options?: {\n expectedContentHash?: string;\n expectedGuidelineVersion?: number;\n }) {\n return this.compressionGuidelineCoordinator.activateCompressionGuidelineDraft(options);\n }\n\n // Issue #1526 (seam 4): compression-guideline learning moved to\n // CompressionGuidelineCoordinator. Thin delegation keeps the\n private async buildCompressionGuidelineRecallSection(): Promise<string | null> {\n return this.compressionGuidelineCoordinator.buildCompressionGuidelineRecallSection();\n }\n\n\n async runLifecyclePolicyNow(storage: StorageManager = this.storage): Promise<{ memoriesAssessed: number }> {\n const lifecycleCorpus = await storage.readAllMemories();\n // Record the catalog write when the pass rewrote any frontmatter (codex NR-tS).\n if ((await this.runLifecyclePolicyPass(lifecycleCorpus, storage)) > 0) {\n }\n return { memoriesAssessed: lifecycleCorpus.length };\n }\n\n private async runLifecyclePolicyPass(\n allMemories: MemoryFile[],\n storage: StorageManager = this.storage,\n ): Promise<number> {\n return this.lifecyclePolicyCoordinator.runLifecyclePolicyPass(allMemories, storage);\n }\n /**\n * Threshold (bytes) at which IDENTITY.md reflections get auto-consolidated.\n * Read by WorkspaceOpsCoordinator (seam 24) via `Orchestrator.…`, hence\n * not `private`.\n */\n static readonly IDENTITY_CONSOLIDATE_THRESHOLD = 8_000;\n\n private async autoConsolidateIdentity(): Promise<void> {\n return this.workspaceOpsCoordinator.autoConsolidateIdentity(\n );\n }\n\n // Issue #1526: recall result formatting moved to RecallResultFormatter. Thin\n // delegation keeps the private API stable for callers + tests.\n private formatQmdResults(\n title: string,\n results: QmdSearchResult[],\n sessionKey?: string,\n trustByPath?: Map<string, TrustStageResultItem> | null,\n ): string {\n return this.recallResultFormatter.formatQmdResults(title, results, sessionKey, trustByPath);\n }\n\n private formatObjectiveStateResults(\n results: ObjectiveStateSearchResult[],\n ): string {\n return this.recallResultFormatter.formatObjectiveStateResults(results);\n }\n\n private formatCausalTrajectoryResults(\n results: CausalTrajectorySearchResult[],\n ): string {\n return this.recallResultFormatter.formatCausalTrajectoryResults(results);\n }\n\n private formatTrustZoneResults(results: TrustZoneSearchResult[]): string {\n return this.recallResultFormatter.formatTrustZoneResults(results);\n }\n\n private formatHarmonicRetrievalResults(\n results: HarmonicRetrievalResult[],\n ): string {\n return this.recallResultFormatter.formatHarmonicRetrievalResults(results);\n }\n\n private formatWorkProductResults(\n results: WorkProductLedgerSearchResult[],\n ): string {\n return this.recallResultFormatter.formatWorkProductResults(results);\n }\n\n private formatVerifiedEpisodeResults(\n results: VerifiedEpisodeResult[],\n ): string {\n return this.recallResultFormatter.formatVerifiedEpisodeResults(results);\n }\n\n private formatVerifiedSemanticRuleResults(\n results: VerifiedSemanticRuleResult[],\n ): string {\n return this.recallResultFormatter.formatVerifiedSemanticRuleResults(results);\n }\n\n private summarizeIdentityText(\n raw: string,\n maxLines: number,\n maxChars: number,\n ): string {\n return this.recallResultFormatter.summarizeIdentityText(raw, maxLines, maxChars);\n }\n\n private formatOpenIncidentLine(\n incident: ContinuityIncidentRecord,\n includeDetails: boolean,\n ): string {\n return this.recallResultFormatter.formatOpenIncidentLine(incident, includeDetails);\n }\n\n private trimIdentitySection(\n content: string,\n maxChars: number,\n ): { text: string; truncated: boolean } {\n return this.recallResultFormatter.trimIdentitySection(content, maxChars);\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 return this.recallResultFormatter.buildIdentityContinuitySection(options);\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 (!resolveEvalCapabilities(this.config).evalHarness || !resolveEvalCapabilities(this.config).evalShadowMode)\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 /**\n * Issue #1577 — per-recall trust map. When present, quarantined items\n * are filtered from injection on EVERY recall path (hot QMD, embedding\n * fallback, cold archive, recent) so a faithfulness-contradicted memory\n * cannot sneak in via a branch that bypasses trust scoring (review:\n * fallback paths bypass trust). The map is also threaded to\n * formatQmdResults for the epistemic hedge.\n */\n trustByPath?: Map<string, TrustStageResultItem> | null;\n }): void {\n const sectionId = \"memories\";\n // Filter quarantined items from ALL recall paths so no branch can inject\n // a hard-negative memory that trust scoring excluded on another path.\n const trustByPath = options.trustByPath ?? null;\n const injectable = trustByPath\n ? options.results.filter((r) => !trustByPath.get(r.path)?.quarantined)\n : options.results;\n const memoryIds = this.extractMemoryIdsFromResults(injectable);\n this.trackMemoryAccess(memoryIds);\n\n this.appendRecallSection(\n options.sectionBuckets,\n sectionId,\n this.formatQmdResults(options.title, injectable, options.sessionKey, trustByPath),\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 qmdCollectionNamespaceFromPrefix(collectionPrefix: string): string | null {\n const baseCollection = this.config.qmdCollection;\n if (collectionPrefix === baseCollection) return this.config.defaultNamespace;\n const namespaceSuffix = collectionPrefix.startsWith(`${baseCollection}--`)\n ? collectionPrefix.slice(baseCollection.length + 2)\n : \"\";\n if (!namespaceSuffix) return null;\n\n const decoded = namespaceIdentityFromToken(namespaceSuffix);\n if (decoded !== null) return decoded || this.config.defaultNamespace;\n if (namespaceSuffix.startsWith(\"ns--\")) {\n const legacyNamespace = namespaceSuffix.slice(\"ns--\".length).trim();\n return legacyNamespace || null;\n }\n return null;\n }\n\n // Issue #1526 seam 11: QMD result-resolution methods moved to QmdResultResolver.\n // Thin delegation keeps the private API stable for callers + tests.\n private async readQmdResultMemory(\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<MemoryFile | null> {\n return this.qmdResultResolver.readQmdResultMemory(resultPath, fallbackStorage, recallNamespaces);\n }\n\n private async resolveColdQmdResultForRecall(\n result: QmdSearchResult,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<{ namespace: string; result: QmdSearchResult } | null> {\n return this.qmdResultResolver.resolveColdQmdResultForRecall(result, fallbackStorage, recallNamespaces);\n }\n\n private async storageForAbsoluteQmdResultPath(\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<{ storage: StorageManager; dir: string; namespace: string } | null> {\n return this.qmdResultResolver.storageForAbsoluteQmdResultPath(resultPath, fallbackStorage, recallNamespaces);\n }\n\n // Issue #1526: recall-rerank methods moved to RecallRerankCoordinator.\n // Thin delegation keeps the private API stable for callers + tests.\n private async applyMemoryWorthRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<QmdSearchResult[]> {\n return this.recallRerankCoordinator.applyMemoryWorthRerank(results, namespaces);\n }\n\n private async applyTrustScoreRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }> {\n return this.recallRerankCoordinator.applyTrustScoreRerank(results, namespaces);\n }\n\n private async applyTrustScoreToBranch(\n results: QmdSearchResult[],\n namespaces: string[],\n caps: CapabilitySet,\n label: string,\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }> {\n return this.recallRerankCoordinator.applyTrustScoreToBranch(results, namespaces, caps, label);\n }\n\n private diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n caps: CapabilitySet = resolveCapabilities(this.config),\n ): QmdSearchResult[] {\n return this.recallRerankCoordinator.diversifyAndLimitRecallResults(sectionId, results, limit, retrievalQuery, caps);\n }\n\n private applyMmrToQmdResults(\n sectionId: string,\n results: QmdSearchResult[],\n caps: CapabilitySet = resolveCapabilities(this.config),\n ): QmdSearchResult[] {\n return this.recallRerankCoordinator.applyMmrToQmdResults(sectionId, results, caps);\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 this.recallSectionCoordinator.buildLastRecallBudgetSummary(options);\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 return this.recallSectionCoordinator.collectLastRecallSources(\n sectionBuckets,\n recallSource,\n );\n }\n\n async semanticDedupLookup(\n content: string,\n limit: number,\n targetStorage: StorageManager,\n ): Promise<SemanticDedupHit[]> {\n return this.persistenceIndexCoordinator.semanticDedupLookup(\n content,\n limit,\n targetStorage,\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 (!resolveNamespaceCapabilities(this.config).namespaces) 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 return this.recallSearchPipelineCoordinator.searchEmbeddingFallback(\n query,\n limit,\n );\n }\n\n private async searchLongTermArchiveFallback(\n prompt: string,\n recallNamespaces: string[],\n limit: number,\n queryAwarePrefilter?: QueryAwarePrefilter,\n abortSignal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n return this.recallSearchPipelineCoordinator.searchLongTermArchiveFallback(\n prompt,\n recallNamespaces,\n limit,\n queryAwarePrefilter,\n abortSignal,\n );\n }\n\n private async applyColdFallbackPipeline(options: {\n prompt: string;\n recallNamespaces: string[];\n recallResultLimit: number;\n recallMode: RecallPlanMode;\n /**\n * Recall-operation capability gates resolved once at recall entry (#1523).\n * OPTIONAL and additive: the recall pipeline threads a resolved set, but\n * callers that omit it (e.g. direct unit-test invocations) get an\n * equivalent config-derived set — behavior-preserving.\n */\n caps?: CapabilitySet;\n /** Graph-construction gates resolved at recall entry (#1566 Cluster A). */\n graphCaps?: GraphConstructionCapabilitySet;\n queryAwarePrefilter?: QueryAwarePrefilter;\n abortSignal?: AbortSignal;\n /** Backend degradation observer — cold-tier QMD must report like hot (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\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 /**\n * Issue #1577 — out-parameter that receives the TrustScore stage's\n * per-path trust map (admitted + quarantined) when the cold path runs\n * trust scoring. Mirrors the xrayPoolSizeSink pattern so recallInternal\n can propagate trust data for epistemic rendering and X-ray visibility\n without changing the cold pipeline's return type.\n */\n trustByPathSink?: { trustByPath: Map<string, TrustStageResultItem> | null };\n deadlineAtMs?: number | null;\n /** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */\n includeLowConfidence?: boolean;\n }): Promise<QmdSearchResult[]> {\n return this.recallSearchPipelineCoordinator.applyColdFallbackPipeline(\n options,\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 (!resolveRecallEnhancementCapabilities(this.config).accessTracking) 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 async flushAccessTracking(): Promise<void> {\n return this.workspaceOpsCoordinator.flushAccessTracking(\n );\n }\n\n private async loadSearchResultMemoryMap(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{\n memoryByPath: Map<string, MemoryFile>;\n checkedPaths: Set<string>;\n unreadablePaths: Set<string>;\n completed: boolean;\n }> {\n return this.recallSearchPipelineCoordinator.loadSearchResultMemoryMap(\n results,\n preloadedMemoryMap,\n options,\n );\n }\n\n private filterSearchResultsByRecallSafety(\n results: QmdSearchResult[],\n memoryByPath: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n blockedPaths?: Set<string>;\n },\n ): QmdSearchResult[] {\n return this.recallSearchPipelineCoordinator.filterSearchResultsByRecallSafety(\n results,\n memoryByPath,\n options,\n );\n }\n\n private async filterSearchResultsForRecall(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n dropUnresolved?: boolean;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{ results: QmdSearchResult[]; memoryByPath: Map<string, MemoryFile> }> {\n return this.recallSearchPipelineCoordinator.filterSearchResultsForRecall(\n results,\n preloadedMemoryMap,\n options,\n );\n }\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 return this.recallSearchPipelineCoordinator.boostSearchResults(\n results,\n _recallNamespaces,\n prompt,\n preloadedMemoryMap,\n options,\n );\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 * Issue #1582 — resolve a memory handle (`[m:4f2a]` / bare hex) to its memory\n * id against THIS session's recent recall history. Returns the id on a unique\n * hit, `null` on a miss, and throws on ambiguity (callers must disambiguate —\n * rule 34/51). Resolution is per-session and snapshot-scoped; there is no\n * global handle→id map (rule 42).\n */\n resolveMemoryHandle(handle: string, sessionKey: string): string | null {\n if (!sessionKey) return null;\n const depth = this.config.recallHandleSnapshotDepth;\n const snapshots: RecallSnapshotIds[] = this.handleHistory\n .recent(sessionKey, depth)\n .map((ids) => ({ memoryIds: ids }));\n const result = resolveHandle(handle, snapshots, depth);\n if (result.ok) return result.memoryId;\n if (result.reason === \"ambiguous\") {\n throw new Error(\n `Memory handle ${handle} is ambiguous in session ${sessionKey}: ` +\n `${result.candidates.join(\", \")}. Cite a unique memory id instead.`,\n );\n }\n return null;\n }\n\n /**\n * Issue #1582 — resolve a caller reference that may be EITHER a memory id or\n * a handle to a concrete memory id. Handles resolve against the session's\n * recall history; raw ids pass through unchanged. The single shared helper\n * every surface (memory_get / feedback / outcome / correction targetIds)\n * calls so handle resolution has one path (rule 22).\n */\n resolveMemoryIdOrHandle(ref: string, sessionKey?: string): string {\n const parsed = parseIdOrHandle(ref);\n if (!parsed.isHandle) return parsed.value;\n if (!sessionKey) {\n throw new Error(\n `Memory handle ${ref} cannot be resolved without a session key.`,\n );\n }\n const resolved = this.resolveMemoryHandle(parsed.value, sessionKey);\n if (resolved === null) {\n throw new Error(\n `Memory handle ${ref} was not found in the recent recall history for session ${sessionKey}.`,\n );\n }\n return resolved;\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 return this.contradictionLinkingCoordinator.checkForContradiction(\n content,\n category,\n namespaceScope,\n );\n }\n\n /**\n * #1645: Complete the deferred contradiction auto-resolve after writeMemory\n * returns and the new write's tombstone status is known. Retires the old\n * memory + deindexes it ONLY when the new write is genuinely active (not\n * tombstone-blocked / pending_review). A blocked write must not retire the\n * only active copy — deferring here closes the \"contradictionAutoResolve\n * supersedes before tombstone status is known\" defect class.\n */\n private async applyDeferredContradictionResolve(\n contradiction: {\n supersededId: string;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n } | null | undefined,\n storage: StorageManager,\n newMemoryId: string,\n postWriteGuard: boolean,\n ): Promise<void> {\n return this.contradictionLinkingCoordinator.applyDeferredContradictionResolve(\n contradiction,\n storage,\n newMemoryId,\n postWriteGuard,\n );\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 return this.contradictionLinkingCoordinator.suggestLinksForMemory(\n content,\n category,\n namespaceScope,\n );\n }\n\n private namespaceFromPath(p: string): string {\n return this.namespaceReadFanoutCoordinator.namespaceFromPath(\n p,\n );\n }\n\n private storageDirNamespace(storageDir: string): string {\n return this.namespaceReadFanoutCoordinator.storageDirNamespace(\n storageDir,\n );\n }\n\n // #1522: catalog touch methods removed — touches now happen at the storage chokepoint.\n\n /**\n * Public best-effort catalog write touch (issue #1499). User-facing explicit\n * captures (`memory_store`) and review-queue approvals persist via\n * `persistExplicitCapture()` → `storage.writeMemory()`, which bypasses the\n * extraction write path that owns the catalog touch. Without this their\n * namespaces never record `lastWriteAt`, so the catalog under-reports write\n * recency (round 5, codex P2). Fire-and-forget and failure-tolerant — a\n * catalog error must never affect the explicit write (gotcha #13, rule #40).\n *\n * An undefined/empty `namespace` means the write targeted the DEFAULT namespace\n * (`getStorage(undefined)` routes there), so we record it under the configured\n * default rather than skipping it (round 6, codex P2 — default `memory_store`\n * and inline-note writes were missing from `writtenSince`/maintenance).\n */\n\n\n // markCatalogRead removed — use storageRouter.recordRead() instead (#1522).\n\n private async readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n return this.namespaceReadFanoutCoordinator.readAllMemoriesForNamespaces(\n namespaces,\n );\n }\n\n private async readArchivedMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n return this.namespaceReadFanoutCoordinator.readArchivedMemoriesForNamespaces(\n namespaces,\n );\n }\n}\n","/**\n * Tier migration coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the hot/cold tier-migration lifecycle for a single cycle:\n * - gating (config flags, in-flight guard, min-interval throttle)\n * - budget selection (compounding override or config default)\n * - candidate scanning across hot + cold storage\n * - promotion/demotion execution via TierMigrationExecutor\n * - status recording through TierMigrationStatusStore\n *\n * The orchestrator constructs one instance and delegates the three public\n * entrypoints (`runTierMigrationCycle`, `runTierMigrationNow`,\n * `getTierMigrationStatus`) to it. Storage is passed per-call so extraction\n * (which writes to a namespace-scoped storage) and maintenance/manual (which\n * use the default storage) share one coordinator.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps thin delegating methods so existing call sites and\n * tests that exercise the public API continue to work.\n */\n\nimport path from \"node:path\";\n\n// StorageManager type comes from the package barrel (type-only) so this\n// module does not add a direct storage.ts import (#1533 ratchet).\nimport type { StorageManager } from \"../index.js\";\nimport type { SearchBackend } from \"../search/port.js\";\nimport { TierMigrationExecutor } from \"../tier-migration.js\";\nimport { decideTierTransition, type MemoryTier } from \"../tier-routing.js\";\nimport {\n TierMigrationStatusStore,\n type TierMigrationCycleSummary,\n type TierMigrationStatusSnapshot,\n} from \"../recall-state.js\";\nimport {\n type CompoundingEngine,\n defaultTierMigrationCycleBudget,\n} from \"../compounding/engine.js\";\nimport {\n applyUtilityPromotionRuntimePolicy,\n type UtilityRuntimeValues,\n} from \"../utility-runtime.js\";\nimport type { PluginConfig, MemoryFile } from \"../types.js\";\nimport { log } from \"../logger.js\";\nimport { resolveQmdCapabilities } from \"../capabilities.js\";\n\n/** Dependencies injected by the orchestrator. All stable references or live\n * accessors (the orchestrator reassigns `qmd` to NoopSearchBackend and\n * `utilityRuntimeValues` after async init, so those arrive as getters). */\nexport interface TierMigrationCoordinatorDeps {\n config: PluginConfig;\n /** Live accessor — the orchestrator reassigns this.qmd to NoopSearchBackend\n * after construction when the collection is missing. */\n getQmd: () => SearchBackend;\n tierMigrationStatus: TierMigrationStatusStore;\n /** Live accessor — loaded asynchronously during init, null before that. */\n getUtilityRuntimeValues: () => UtilityRuntimeValues | null;\n /** Live accessor — undefined when compounding is disabled. */\n getCompounding: () => CompoundingEngine | undefined;\n /** Constructs the cold-tier StorageManager for a given parent memory dir.\n * Injected so this module owns no direct storage.ts import (#1533). */\n createColdStorage: (parentDir: string) => StorageManager;\n}\n\n/**\n * Coordinates a single tier-migration cycle. Owns the in-flight guard and\n * last-run timestamp that previously lived as private orchestrator fields.\n */\nexport class TierMigrationCoordinator {\n private inFlight = false;\n private lastRunAtMs = 0;\n\n constructor(private readonly deps: TierMigrationCoordinatorDeps) {}\n\n /** Whether a migration cycle is currently executing (diagnostics). */\n isInFlight(): boolean {\n return this.inFlight;\n }\n\n /** Latest status snapshot (delegates to the status store). */\n getStatus(): TierMigrationStatusSnapshot {\n return this.deps.tierMigrationStatus.get();\n }\n\n /**\n * Run one tier-migration cycle. Behavior-preserving move of the\n * orchestrator's former `runTierMigrationCycle`.\n */\n async runCycle(\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 { config, tierMigrationStatus } = this.deps;\n const dryRun = options?.dryRun === true;\n const persistSkipped = options?.force === true || trigger === \"manual\";\n if (!resolveQmdCapabilities(config).qmdTierMigration && 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 tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (\n trigger === \"maintenance\" &&\n !resolveQmdCapabilities(config).qmdTierAutoBackfill &&\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 tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (this.inFlight) {\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 tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const budgetTrigger = trigger === \"manual\" ? \"maintenance\" : trigger;\n const budget =\n this.deps.getCompounding()?.tierMigrationCycleBudget(budgetTrigger) ??\n defaultTierMigrationCycleBudget(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.lastRunAtMs < 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 tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const policy = applyUtilityPromotionRuntimePolicy(\n {\n enabled: resolveQmdCapabilities(config).qmdTierMigration,\n demotionMinAgeDays: config.qmdTierDemotionMinAgeDays,\n demotionValueThreshold: config.qmdTierDemotionValueThreshold,\n promotionValueThreshold: config.qmdTierPromotionValueThreshold,\n },\n this.deps.getUtilityRuntimeValues(),\n );\n\n this.inFlight = true;\n try {\n const coldStorage = this.deps.createColdStorage(\n path.join(storage.dir, \"cold\"),\n );\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.deps.getQmd(),\n hotCollection: config.qmdCollection,\n coldCollection:\n config.qmdColdCollection ?? `${config.qmdCollection}-cold`,\n autoEmbed: resolveQmdCapabilities(config).qmdAutoEmbed,\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.lastRunAtMs = 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) await tierMigrationStatus.recordCycle(summary);\n return summary;\n } catch (err) {\n this.lastRunAtMs = 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 tierMigrationStatus.recordCycle(failed);\n return failed;\n } finally {\n this.inFlight = false;\n }\n }\n}\n","/**\n * Extraction queue coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the background serial queue that drains extraction tasks one at a\n * time to avoid races between concurrent flush/heartbeat/bulk-import\n * triggers:\n * - queue state (`extractionQueue` + `queueProcessing`)\n * - the scheduling trigger (start the drain when the first task lands and\n * the processor is idle)\n * - the serial drain loop itself (`processQueue`)\n * - failure classification (`logExtractionQueueFailure`) — issue #549:\n * AbortError from session transitions logs at debug, real failures at\n * error\n * - the idle wait (`waitForIdle`) used by bootstrap and tests\n *\n * Does NOT own the WHAT — `runExtraction`, the dedupe fingerprint check,\n * the deadline timer, and the buffer-clear policy remain on the\n * orchestrator (they need the full extraction dependency surface). The\n * orchestrator builds each task closure and hands it to `enqueue`; the\n * coordinator owns only the queue mechanics.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating `waitForExtractionIdle` and the\n * `queueBufferedExtraction` builder delegates push+scheduling here.\n */\n\nimport { isAbortError } from \"../abort-error.js\";\nimport { log } from \"../logger.js\";\n\n/**\n * Coordinates the background serial extraction queue. Owns the in-flight\n * guard + queue array that previously lived as private orchestrator fields.\n */\nexport class ExtractionQueueCoordinator {\n /**\n * Background serial queue for extractions (agent_end optimization).\n * Queue stores tasks that resolve when extraction should run.\n */\n private readonly queue: Array<() => Promise<void>> = [];\n /** Whether the serial drain loop is currently running. */\n private processing = false;\n\n /** Current queue depth (idle-wait + test seam). */\n get length(): number {\n return this.queue.length;\n }\n\n /** Whether the serial drain loop is currently running (idle-wait + test seam). */\n get isProcessing(): boolean {\n return this.processing;\n }\n\n /**\n * Enqueue a task and start the serial processor if it is idle. This is\n * the production entry point — the orchestrator's `queueBufferedExtraction`\n * builds each task closure and hands it here.\n */\n enqueue(task: () => Promise<void>): void {\n this.queue.push(task);\n if (!this.processing) {\n this.processing = true;\n this.processQueue().catch((err) => {\n this.logExtractionQueueFailure(err, \"processor\");\n this.processing = false;\n });\n }\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 via `enqueue`; also exposed\n * for the characterization tests that push raw tasks and assert drain\n * semantics directly.\n */\n async processQueue(): Promise<void> {\n while (this.queue.length > 0) {\n const task = this.queue.shift();\n if (task) {\n try {\n await task();\n } catch (err) {\n this.logExtractionQueueFailure(err, \"task\");\n }\n }\n }\n\n this.processing = 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 * `enqueue()`. 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 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 /**\n * Wait until the extraction queue is fully drained (no tasks queued, no\n * drain in flight) or `timeoutMs` elapses. Used by bootstrap (after a\n * dry-run import) and by tests that need to assert extraction settled.\n * Returns false on timeout, true once idle.\n */\n async waitForIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.processing || this.queue.length > 0) {\n if (Date.now() - started > timeoutMs) {\n log.warn(`waitForExtractionIdle timed out after ${timeoutMs}ms`);\n return false;\n }\n const { promise, resolve } = Promise.withResolvers<void>();\n setTimeout(resolve, 50);\n await promise;\n }\n return true;\n }\n\n // ── Test seams ─────────────────────────────────────────────────────────\n // Mirror the pre-extraction `orchestrator.extractionQueue` /\n // `orchestrator.queueProcessing` direct-field access the characterization\n // and flush deadline tests relied on. Each is a thin, well-named handle\n // onto the coordinator's private state — no behavior change.\n\n /**\n * Push a raw task WITHOUT auto-starting the processor, matching the\n * pre-extraction `this.extractionQueue.push(...)` used by the\n * characterization tests that drive the drain manually via `processQueue`.\n */\n pushRaw(task: () => Promise<void>): void {\n this.queue.push(task);\n }\n\n /** Remove + return the front task (test seam for the flush deadline tests). */\n shift(): (() => Promise<void>) | undefined {\n return this.queue.shift();\n }\n\n /**\n * Force the processor-busy flag so `enqueue` does not auto-start the\n * drain — used by the flush deadline test to simulate a busy queue and\n * assert a queued task's deadline expires while it waits.\n */\n setProcessingForTest(value: boolean): void {\n this.processing = value;\n }\n}\n","/**\n * Semantic-consolidation coordinator — extracted from the orchestrator\n * (issue #1526, seam 5).\n *\n * Owns the semantic-consolidation lifecycle: discovering clusters of\n * similar memories, synthesizing a canonical memory per cluster via the\n * LLM (operator-aware or legacy), archiving the superseded sources, and\n * firing post-consolidation hooks (Codex materialize, peer-profile\n * reasoner).\n *\n * The orchestrator constructs one instance and delegates the internal\n * entrypoint (`runSemanticConsolidation`) to it. The public wrappers\n * (`runSemanticConsolidationNow`, `runSemanticConsolidationFanout`)\n * remain on the orchestrator as thin pass-throughs. Storage is the\n * orchestrator's stable `this.storage` (or a per-namespace override\n * passed via options); the fast-tier LLM, content-hash removal, and\n * index save arrive as callbacks so the orchestrator keeps ownership of\n * gateway routing and cross-subsystem persistence.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating method so existing call sites\n * and tests that exercise the public API continue to work.\n */\n\nimport {\n findSimilarClusters,\n buildConsolidationPrompt,\n parseConsolidationResponse,\n buildOperatorAwareConsolidationPrompt,\n parseOperatorAwareConsolidationResponse,\n chooseConsolidationOperator,\n buildExtensionsBlockForConsolidation,\n materializeAfterSemanticConsolidation,\n} from \"../semantic-consolidation.js\";\nimport type {\n SemanticConsolidationLlmOperator,\n SemanticConsolidationResult,\n} from \"../semantic-consolidation.js\";\nimport {\n FallbackLlmClient,\n fallbackLlmRuntimeContextFromConfig,\n gatewayTaskChainOptions,\n} from \"../fallback-llm.js\";\nimport { resolveIndexingCapabilities, resolveConsolidationCapabilities } from \"../capabilities.js\";\nimport { deindexMemory } from \"../temporal-index.js\";\nimport { runPeerProfileReasoner } from \"../peers/index.js\";\nimport type { StorageManager } from \"../index.js\";\nimport type { LocalLlmClient } from \"../local-llm.js\";\nimport type { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport type { PluginConfig, MemoryFile, AgentPersonaModelConfig } from \"../types.js\";\nimport { log } from \"../logger.js\";\nimport { resolveConversationContextCapabilities } from \"../capabilities.js\";\n\n/** Dependencies injected by the orchestrator. All stable references or\n * live accessors. */\nexport interface SemanticConsolidationCoordinatorDeps {\n config: PluginConfig;\n /** Live accessor: the orchestrator's storage manager (stable post-ctor). */\n getStorage: () => StorageManager;\n /** Live accessor for the fast-tier local LLM client (falls back to main\n * local LLM when localLlmFastEnabled is false — orchestrator ctor handles\n * this). Injected as an accessor so tests that overwrite orchestrator.fastLlm\n * after construction still take effect. */\n getFastLlm: () => LocalLlmClient;\n /** The embedding-fallback manager used for index cleanup on archival. */\n embeddingFallback: EmbeddingFallback;\n /** Remove a memory's content-hash entry from the storage-scoped index.\n * Delegated to the orchestrator which owns the per-storage index map. */\n removeContentHashForMemory: (\n targetStorage: StorageManager,\n memory: MemoryFile,\n context: string,\n ) => Promise<void>;\n /** Persist all dirty content-hash indexes to disk. */\n saveContentHashIndexes: () => Promise<void>;\n}\n\n/**\n * Coordinates semantic consolidation. Holds no mutable state of its own —\n * all persistence flows through the injected storage managers and\n * callbacks.\n */\nexport class SemanticConsolidationCoordinator {\n constructor(private readonly deps: SemanticConsolidationCoordinatorDeps) {}\n\n private get config(): PluginConfig {\n return this.deps.config;\n }\n\n async runSemanticConsolidation(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n force?: boolean;\n storage?: StorageManager;\n }): Promise<SemanticConsolidationResult> {\n const targetStorage = options?.storage ?? this.deps.getStorage();\n const result: SemanticConsolidationResult = {\n clustersFound: 0,\n memoriesConsolidated: 0,\n memoriesArchived: 0,\n errors: 0,\n clusters: [],\n };\n\n if (!resolveConsolidationCapabilities(this.config).semanticConsolidation && !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 useGateway = this.config.modelSource === \"gateway\";\n const modelSetting = this.config.semanticConsolidationModel;\n if (modelSetting === \"fast\" && this.deps.getFastLlm() && !useGateway) {\n log.info(\"[semantic-consolidation] using fast local LLM for synthesis\");\n }\n // Gateway routing: an explicit \"fast\" setting keeps the fast persona chain\n // (the operator's deliberate fast-tier choice). Otherwise route through the\n // shared task-chain resolution so taskModelChain applies to semantic\n // consolidation like every other background task (gotcha #22). Issue #1365.\n const gatewayChainOptions: { modelChain?: AgentPersonaModelConfig; agentId?: string } =\n !useGateway\n ? {}\n : modelSetting === \"fast\"\n ? (this.config.fastGatewayAgentId\n ? { agentId: this.config.fastGatewayAgentId }\n : this.config.gatewayAgentId\n ? { agentId: this.config.gatewayAgentId }\n : {})\n : gatewayTaskChainOptions(this.config);\n const llm = new FallbackLlmClient(\n this.config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(this.config),\n );\n if (!llm.isAvailable(gatewayChainOptions) && !(modelSetting === \"fast\" && this.deps.getFastLlm() && !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 let canonicalWriteCompleted = false;\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 resolveConversationContextCapabilities(this.config).operatorAwareConsolidation === 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, ...gatewayChainOptions });\n } else if (modelSetting === \"fast\" && this.deps.getFastLlm()) {\n const fastResult = await this.deps.getFastLlm().chatCompletion(messages, {\n operation: \"semantic-consolidation\",\n maxTokens: llmOpts.maxTokens,\n temperature: llmOpts.temperature,\n priority: \"background\",\n forceDisableThinking: true,\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 { id: canonicalId, tombstoneBlocked: canonicalBlocked } = 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 if (canonicalBlocked) {\n // #1645: canonical matched a tombstone (pending_review). Don't archive\n // the sources — consolidation must never delete the only active copy.\n log.info(`[semantic-consolidation] cluster in \"${cluster.category}\" tombstone-blocked — keeping ${cluster.memories.length} source(s) active (pending_review ${canonicalId})`);\n continue;\n }\n canonicalWriteCompleted = true;\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 the same storage-scoped content-hash index that\n // originally deduped this memory.\n await this.deps.removeContentHashForMemory(\n targetStorage,\n m,\n \"semantic-consolidation\",\n );\n // Best-effort index cleanup: a failure here (e.g. on-disk index save\n // under disk-full) must NOT abort the archival loop and thereby skip\n // the catalog write touch below for an already-durable canonical write\n // (kilo NV0mh).\n try {\n await this.deps.embeddingFallback.removeFromIndex(m.frontmatter.id);\n if (\n resolveIndexingCapabilities(this.config).queryAwareIndexing &&\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 } catch (cleanupErr) {\n log.warn(\n `[semantic-consolidation] index cleanup failed (non-fatal): ${cleanupErr}`,\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 } finally {\n if (canonicalWriteCompleted) {\n // Catalog write touch (issue #1499 sweep): record after the canonical\n // write and, on the happy path, after archival of superseded cluster\n // memories, so `lastWriteAt` reflects every durable mutation in this\n // consolidation (cursor NUtCK). The `finally` also covers partial\n // failures where the canonical memory was written but a later archive\n // step throws and the cluster catch continues (codex NY-dK).\n // Best-effort; namespace decoded from the storage dir since this path\n // #1522: catalog touch handled at the storage chokepoint.\n }\n }\n }\n\n // Save hash indexes if we modified them.\n if (result.memoriesArchived > 0) {\n await this.deps.saveContentHashIndexes().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 (resolveConversationContextCapabilities(this.config).peerProfileReasoner) {\n try {\n const peerLlm = new FallbackLlmClient(\n this.config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(this.config),\n );\n const peerResult = await runPeerProfileReasoner({\n memoryDir: targetStorage.dir,\n enabled: true,\n llm: peerLlm,\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","/**\n * Lifecycle-policy coordinator — extracted from the orchestrator\n * (issue #1526, seam 6).\n *\n * Owns the deterministic memory-lifecycle pipeline: heat/decay scoring\n * (`runLifecyclePolicyPass`), fact archival (`runFactArchival`),\n * summarization (`runSummarization`), and topic extraction\n * (`runTopicExtraction`). Also owns the action-outcome prior builder\n * (`buildLifecycleActionPriors` / `actionOutcomePriorDelta`) that feeds\n * the lifecycle transition decider.\n *\n * The orchestrator constructs one instance and delegates the internal\n * entrypoints to it. The public wrapper (`runLifecyclePolicyNow`)\n * remains on the orchestrator as a thin pass-through. Storage is the\n * orchestrator's stable `this.storage` (or a per-namespace override\n * passed via options); the extraction engine, embedding-fallback, and\n * content-hash callbacks arrive as deps so the orchestrator keeps\n * ownership of gateway routing and cross-subsystem persistence.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps thin delegating methods so existing call sites\n * and tests that exercise the public API continue to work.\n */\n\nimport {\n decideLifecycleTransition,\n resolveLifecycleState,\n type LifecycleSignals,\n} from \"../lifecycle.js\";\nimport type { LifecycleState } from \"../types.js\";\nimport {\n resolveIndexingCapabilities,\n resolveMemoryLifecycleCapabilities,\n resolveCreationMemoryCapabilities,\n} from \"../capabilities.js\";\nimport { isActiveMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { deindexMemory } from \"../temporal-index.js\";\nimport { extractTopics } from \"../topics.js\";\nimport { log } from \"../logger.js\";\nimport path from \"node:path\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport type { StorageManager } from \"../index.js\";\nimport type { ExtractionEngine } from \"../extraction.js\";\nimport type { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport type {\n PluginConfig,\n MemoryFile,\n MemoryActionEvent,\n MemorySummary,\n} from \"../types.js\";\n\n/** Dependencies injected by the orchestrator. All stable references or\n * live accessors. */\nexport interface LifecyclePolicyCoordinatorDeps {\n config: PluginConfig;\n /** Live accessor: the orchestrator's storage manager (stable post-ctor). */\n getStorage: () => StorageManager;\n /** The extraction engine — used for summarization. */\n extraction: ExtractionEngine;\n /** The embedding-fallback manager used for index cleanup on archival. */\n embeddingFallback: EmbeddingFallback;\n /** Effective lifecycle thresholds (promote/stale/archive). Delegated to\n * the orchestrator which owns runtime-policy-values overlay. */\n getEffectiveLifecycleThresholds: () => {\n promoteHeatThreshold: number;\n staleDecayThreshold: number;\n archiveDecayThreshold: number;\n };\n /** Remove a memory's content-hash entry from the storage-scoped index.\n * Delegated to the orchestrator which owns the per-storage index map. */\n removeContentHashForMemory: (\n targetStorage: StorageManager,\n memory: MemoryFile,\n context: string,\n ) => Promise<void>;\n /** Persist all dirty content-hash indexes to disk. */\n saveContentHashIndexes: () => Promise<void>;\n}\n\n/**\n * Coordinates the memory-lifecycle policy pipeline. Holds no mutable\n * state of its own — all persistence flows through the injected storage\n * managers and callbacks.\n */\nexport class LifecyclePolicyCoordinator {\n constructor(\n private readonly deps: LifecyclePolicyCoordinatorDeps,\n ) {}\n\n private get config(): PluginConfig {\n return this.deps.config;\n }\n\n // -------------------------------------------------------------------------\n // Action-outcome priors (feeds lifecycle transition decisions)\n // -------------------------------------------------------------------------\n\n 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 async buildLifecycleActionPriors(\n storage: StorageManager = this.deps.getStorage(),\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 // -------------------------------------------------------------------------\n // Lifecycle policy pass (heat/decay scoring + transition)\n // -------------------------------------------------------------------------\n\n async runLifecyclePolicyPass(\n allMemories: MemoryFile[],\n storage: StorageManager = this.deps.getStorage(),\n ): Promise<number> {\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 const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);\n\n const thresholds = this.deps.getEffectiveLifecycleThresholds();\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 // Report how many memories had frontmatter rewritten so callers can record a\n // catalog write touch for lifecycle-only passes (codex NR-tS).\n if (!lifecycleCaps.lifecycleMetrics) return updatedCount;\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 return updatedCount;\n }\n\n // -------------------------------------------------------------------------\n // Fact archival\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 async runFactArchival(\n allMemories: MemoryFile[],\n ): Promise<number> {\n const storage = this.deps.getStorage();\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 storage.archiveMemory(memory);\n if (result) {\n // Remove from the same storage-scoped content-hash index since it is\n // no longer in hot search.\n await this.deps.removeContentHashForMemory(\n storage,\n memory,\n \"fact-archival\",\n );\n await this.deps.embeddingFallback.removeFromIndex(memory.frontmatter.id);\n if (\n resolveIndexingCapabilities(this.config).queryAwareIndexing &&\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 indexes if we removed any entries.\n if (archivedCount > 0) {\n await this.deps.saveContentHashIndexes().catch((err) =>\n log.warn(`content-hash index save failed during archival: ${err}`),\n );\n }\n\n return archivedCount;\n }\n\n // -------------------------------------------------------------------------\n // Summarization (Phase 4A)\n // -------------------------------------------------------------------------\n\n /**\n * Run memory summarization if memory count exceeds threshold (Phase 4A).\n */\n async runSummarization(\n allMemories: MemoryFile[],\n ): Promise<void> {\n const storage = this.deps.getStorage();\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, with explicit zero handling so `slice(-0)` does not\n // accidentally keep every memory out of the summarization candidate set.\n const recentToKeep = Math.max(0, this.config.summarizationRecentToKeep);\n const toSummarize = recentToKeep > 0 ? sorted.slice(0, -recentToKeep) : sorted;\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.deps.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 storage.writeSummary(summary);\n\n // Archive source memories\n const archived = await storage.archiveMemories(\n batch.map((m) => m.frontmatter.id),\n summary.id,\n );\n\n // Catalog write touch (issue #1499 sweep): summarization writes a durable\n // summary and then rewrites source-memory archive status, bypassing the\n // extraction write path. Record the touch after both mutations complete so\n // `lastWriteAt` covers the final archived-state write.\n // #1522: catalog touch handled at the storage chokepoint.\n\n log.info(\n `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`,\n );\n }\n }\n\n // -------------------------------------------------------------------------\n // Topic extraction (Phase 4B)\n // -------------------------------------------------------------------------\n\n /**\n * Run topic extraction on all memories (Phase 4B).\n */\n async runTopicExtraction(\n allMemories: MemoryFile[],\n ): Promise<void> {\n const storage = this.deps.getStorage();\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 storage.saveTopics(topics);\n\n log.debug(\n `extracted ${topics.length} topics from ${activeMemories.length} memories`,\n );\n }\n}\n","/**\n * Entity synthesis coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the entity-synthesis lifecycle: processing the queued entities whose\n * evidence has changed since their last synthesis, gathering timeline +\n * structured-section evidence, deduplicating it, batch-feeding it through the\n * fast-tier LLM to produce a compact \"current truth\" synthesis, and persisting\n * the result with drift/bookkeeping metadata.\n *\n * Moved here (behavior-preserving):\n * - module-level helpers `dedupeEntitySynthesisEvidenceEntries`,\n * `flattenStructuredSectionEvidence`, `fingerprintEntitySynthesisEvidence`\n * - the orchestrator method `processEntitySynthesisQueue`\n *\n * The orchestrator constructs one instance and delegates the public entrypoint\n * to it. Storage is resolved per-call via the injected accessor so namespace-\n * scoped and default-namespace calls share one coordinator.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating `processEntitySynthesisQueue` so\n * existing call sites (consolidation pass, access-service) and tests that\n * exercise the public API continue to work.\n */\n\nimport { createHash } from \"node:crypto\";\n\nimport type { StorageManager } from \"../index.js\";\nimport {\n compareEntityTimestamps,\n fingerprintEntityStructuredFacts,\n parseEntityFile,\n} from \"../storage.js\";\nimport type {\n EntityStructuredSection,\n EntityTimelineEntry,\n PluginConfig,\n} from \"../types.js\";\nimport { log } from \"../logger.js\";\nimport { resolvePresentationCapabilities } from \"../capabilities.js\";\n\n// ---------------------------------------------------------------------------\n// Evidence helpers (moved verbatim from orchestrator.ts module scope)\n// ---------------------------------------------------------------------------\n\n/**\n * Deduplicate synthesis-evidence entries by normalized text, keeping the\n * newest and oldest timestamp per unique fact when they differ.\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\n// ---------------------------------------------------------------------------\n// Coordinator\n// ---------------------------------------------------------------------------\n\n/** Dependencies injected by the orchestrator. */\nexport interface EntitySynthesisCoordinatorDeps {\n config: PluginConfig;\n /** Resolve the storage manager for a namespace (or the default). */\n getStorage: (namespace?: string) => Promise<StorageManager>;\n /** Fast-tier LLM completion (same signature as Orchestrator.fastChatCompletion). */\n fastChatCompletion: (\n messages: Array<{ role: string; content: string }>,\n options: {\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n operation?: string;\n priority?: \"background\" | \"recall-critical\";\n },\n ) => Promise<{ content: string } | null>;\n}\n\n/**\n * Coordinates entity synthesis refresh for queued entities. Owns the\n * evidence-gathering, dedup, batched-LLM-synthesis, and persistence logic\n * that previously lived inline in the orchestrator.\n */\nexport class EntitySynthesisCoordinator {\n constructor(private readonly deps: EntitySynthesisCoordinatorDeps) {}\n\n /**\n * Process up to `maxEntities` entities from the synthesis queue for the\n * given namespace. Returns the number of entities whose synthesis was\n * successfully refreshed.\n */\n async processQueue(\n namespace?: string,\n maxEntities: number = 5,\n ): Promise<number> {\n const { config } = this.deps;\n if (\n !resolvePresentationCapabilities(config).entitySummary\n || maxEntities <= 0\n || config.entitySynthesisMaxTokens <= 0\n ) return 0;\n const storage = await this.deps.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, 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.deps.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: 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, 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, 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","/**\n * Recall result formatter — extracted from the orchestrator (issue #1526).\n *\n * Owns the formatting of recall search results into display sections, plus the\n * identity-continuity section assembly:\n * - QMD result formatting (with memory handles + epistemic hedge rendering)\n * - Specialized recall result formatters (objective-state, causal-trajectory,\n * trust-zone, harmonic-retrieval, work-product, verified-episode,\n * verified-semantic-rule)\n * - Identity continuity helpers (summarizeIdentityText, formatOpenIncidentLine,\n * trimIdentitySection) and the full buildIdentityContinuitySection builder\n * - Module-level helpers hasIdentityRecoveryIntent and\n * resolveEffectiveIdentityInjectionMode (only consumed here)\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator constructs one instance and keeps thin delegating methods so\n * existing call sites and tests that exercise the private API continue to work.\n */\n\nimport { buildHandleIndexForResults } from \"../recall-handles.js\";\nimport { renderEpistemicHedge } from \"../trust-score.js\";\nimport { resolveIdentityContinuityCapabilities } from \"../capabilities.js\";\nimport type { StorageManager } from \"../index.js\";\nimport type { ObjectiveStateSearchResult } from \"../objective-state.js\";\nimport type { CausalTrajectorySearchResult } from \"../causal-trajectory.js\";\nimport type { TrustZoneSearchResult } from \"../trust-zones.js\";\nimport type { HarmonicRetrievalResult } from \"../harmonic-retrieval.js\";\nimport type { VerifiedEpisodeResult } from \"../verified-recall.js\";\nimport type { VerifiedSemanticRuleResult } from \"../semantic-rule-verifier.js\";\nimport type { WorkProductLedgerSearchResult } from \"../work-product-ledger.js\";\nimport type { TrustStageResultItem } from \"../trust-score-stage.js\";\nimport type {\n ContinuityIncidentRecord,\n IdentityInjectionMode,\n PluginConfig,\n QmdSearchResult,\n RecallPlanMode,\n} from \"../types.js\";\n\n// ---------------------------------------------------------------------------\n// Identity injection mode helpers (moved verbatim from orchestrator.ts)\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\n// ---------------------------------------------------------------------------\n// Coordinator\n// ---------------------------------------------------------------------------\n\n/**\n * Formats recall search results into display sections and assembles the\n * identity-continuity section. Holds a reference to config for feature-gated\n * rendering (memory handles, epistemic hedges, identity injection mode).\n */\nexport class RecallResultFormatter {\n constructor(private readonly config: PluginConfig) {}\n\n // ── QMD results (memory handles + epistemic hedge) ──────────────────────\n\n formatQmdResults(\n title: string,\n results: QmdSearchResult[],\n sessionKey?: string,\n trustByPath?: Map<string, TrustStageResultItem> | null,\n ): string {\n // Issue #1582 — handles are only rendered when a session key is available:\n // resolution requires the handle history to have been recorded for this\n // session, which only happens when sessionKey is present. Rendering handles\n // without recording would show tokens a user can never resolve (cursor\n // review). The rendering logic itself lives in the pure handles module.\n const handleByIndex = buildHandleIndexForResults(\n results,\n this.config.recallMemoryHandles === true && sessionKey != null,\n );\n // Issue #1577 — epistemic hedge. Append a deterministic, component-derived\n // suffix so the downstream model knows each memory's trust status (the\n // cheap lever against confident-stale-answer failures). Gated separately\n // from scoring so rendering can ship after the stage is stable. High-band\n // and neutral items get no suffix (don't waste tokens on the common case).\n const renderHedge = this.config.trustScoreEpistemicRendering && trustByPath !== null && trustByPath !== undefined;\n const hedgeMap = renderHedge ? trustByPath : null;\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 const source = typeof r.line === \"number\" ? `${r.path}:${r.line}` : r.path;\n const head = `[${i + 1}] ${source} (score: ${r.score.toFixed(3)})\\n${snippet}`;\n const handle = handleByIndex.get(i);\n const hedged = head.replace(/\\s+$/, \"\");\n const withHandle = handle ? `${hedged} ${handle}` : hedged;\n if (hedgeMap) {\n const item = hedgeMap.get(r.path);\n if (item) {\n const hedge = renderEpistemicHedge(item.trust);\n if (hedge.length > 0) return `${withHandle} ${hedge}`;\n }\n }\n return withHandle;\n });\n return `## ${title}\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n // ── Specialized recall result formatters ────────────────────────────────\n\n 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 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 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 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 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 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 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 // ── Identity continuity helpers ─────────────────────────────────────────\n\n 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 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 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 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 (!resolveIdentityContinuityCapabilities(this.config).identityContinuity) 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","/**\n * Conversation index coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the conversation-index subsystem: semantic recall over past\n * conversations, plus the build / update / rebuild / inspect / health\n * lifecycle of the on-disk chunk store and its pluggable search backend\n * (qmd or faiss). Behavior-preserving move from orchestrator.ts — no logic\n * changes; the orchestrator constructs one instance and keeps thin\n * delegating methods so existing call sites and tests that exercise the\n * private API continue to work.\n *\n * The backend and transcript are read through getters (not captured at\n * construction) so that post-construction reassignment of the orchestrator's\n * live fields — exercised by the conversation-index integration tests and by\n * backend swap-in at deferred-init time — is honored. This mirrors the\n * TierMigrationCoordinator accessor pattern.\n */\n\nimport { readdir } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { resolveIndexingCapabilities } from \"../capabilities.js\";\nimport { cleanupConversationChunks } from \"../conversation-index/cleanup.js\";\nimport { chunkTranscriptEntries } from \"../conversation-index/chunker.js\";\nimport type { ConversationChunk } from \"../conversation-index/chunker.js\";\nimport { writeConversationChunks } from \"../conversation-index/indexer.js\";\nimport type {\n ConversationIndexBackend,\n ConversationIndexBackendHealth,\n ConversationIndexBackendInspection,\n} from \"../conversation-index/backend.js\";\nimport type { ConversationSearchResult } from \"../conversation-index/search.js\";\nimport type { TranscriptManager } from \"../transcript.js\";\nimport type { PluginConfig } from \"../types.js\";\n\n/**\n * Coordinator for the conversation-index subsystem.\n *\n * Holds the per-session last-update timestamps (previously an orchestrator\n * field) and delegates chunk building / persistence / embedding to the\n * configured backend.\n */\nexport class ConversationIndexCoordinator {\n private readonly config: PluginConfig;\n private readonly getTranscript: () => TranscriptManager;\n private readonly getBackend: () => ConversationIndexBackend | undefined;\n private readonly indexDir: string;\n private readonly lastUpdateAtMs = new Map<string, number>();\n\n constructor(options: {\n config: PluginConfig;\n getTranscript: () => TranscriptManager;\n getBackend: () => ConversationIndexBackend | undefined;\n indexDir: string;\n }) {\n this.config = options.config;\n this.getTranscript = options.getTranscript;\n this.getBackend = options.getBackend;\n this.indexDir = options.indexDir;\n }\n\n /** Semantic recall over past-conversation chunks (fail-open: empty on miss). */\n async search(\n retrievalQuery: string,\n topK: number,\n ): Promise<ConversationSearchResult[]> {\n const backend = this.getBackend();\n if (backend) {\n return backend.search(retrievalQuery, topK);\n }\n return [];\n }\n\n /** Render conversation-recall search hits as a budgeted markdown section. */\n formatRecallSection(\n results: ConversationSearchResult[],\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 /** Recursively count `.md` chunk documents under a directory. */\n async countChunkDocs(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.countChunkDocs(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 /** Read recent transcript entries and chunk them for indexing. */\n async buildChunks(\n sessionKey?: string,\n hours: number = 24,\n ): Promise<ConversationChunk[]> {\n const entries = await this.getTranscript().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 getHealth(): 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.countChunkDocs(this.indexDir);\n const lastUpdateAtMs = Math.max(0, ...this.lastUpdateAtMs.values());\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!resolveIndexingCapabilities(this.config).conversationIndex) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n chunkDocCount,\n lastUpdateAt,\n };\n }\n const backend = this.getBackend();\n const backendHealth: ConversationIndexBackendHealth = backend\n ? await backend.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 inspect(): Promise<\n ConversationIndexBackendInspection & {\n enabled: boolean;\n chunkDocCount: number;\n lastUpdateAt: string | null;\n }\n > {\n const chunkDocCount = await this.countChunkDocs(this.indexDir);\n const lastUpdateAtMs = Math.max(0, ...this.lastUpdateAtMs.values());\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!resolveIndexingCapabilities(this.config).conversationIndex) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n available: false,\n indexPath: this.indexDir,\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 backend = this.getBackend();\n const inspection: ConversationIndexBackendInspection = backend\n ? await backend.inspect()\n : {\n backend: this.config.conversationIndexBackend,\n status: \"degraded\" as const,\n available: false,\n indexPath: this.indexDir,\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 update(\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 (!resolveIndexingCapabilities(this.config).conversationIndex) {\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.lastUpdateAtMs.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.buildChunks(sessionKey, hours);\n await writeConversationChunks(this.indexDir, chunks);\n const retentionCutoffMs =\n Number.isFinite(this.config.conversationIndexRetentionDays) &&\n this.config.conversationIndexRetentionDays > 0\n ? Date.now() -\n this.config.conversationIndexRetentionDays * 24 * 60 * 60 * 1000\n : undefined;\n await cleanupConversationChunks(\n this.indexDir,\n this.config.conversationIndexRetentionDays,\n );\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n\n const backend = this.getBackend();\n if (backend) {\n const result = await backend.update(chunks, {\n embed: shouldEmbed,\n ...(retentionCutoffMs !== undefined ? { retentionCutoffMs } : {}),\n });\n embedded = result.embedded;\n }\n\n this.lastUpdateAtMs.set(sessionKey, Date.now());\n return { chunks: chunks.length, skipped: false, embedded };\n }\n\n async rebuild(\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 (!resolveIndexingCapabilities(this.config).conversationIndex) {\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.buildChunks(sessionKey, hours);\n await writeConversationChunks(this.indexDir, chunks);\n await cleanupConversationChunks(\n this.indexDir,\n this.config.conversationIndexRetentionDays,\n );\n\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n let rebuilt = false;\n const backend = this.getBackend();\n if (backend) {\n const result = await backend.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.lastUpdateAtMs.set(sessionKey, stamp);\n } else {\n this.lastUpdateAtMs.set(\"__rebuild__\", stamp);\n }\n return { chunks: chunks.length, skipped: false, embedded, rebuilt };\n }\n}\n","/**\n * Recall rerank coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the post-retrieval result-ranking subsystem: Memory-Worth reranking,\n * TrustScore scoring + quarantine, reasoning-trace boost, and MMR\n * diversification/limiting. Behavior-preserving move from orchestrator.ts —\n * no logic changes; the orchestrator constructs one instance and keeps thin\n * delegating methods so existing call sites (recallInternal,\n * applyColdFallbackPipeline) continue to work.\n *\n * Config, storage, and the QMD-result memory reader are accessed through\n * getter callbacks (not captured at construction) so that post-construction\n * reassignment of the orchestrator's live fields is honored. This mirrors\n * the ConversationIndexCoordinator / TierMigrationCoordinator accessor\n * pattern.\n */\n\nimport { resolveCapabilities, type CapabilitySet } from \"../capabilities.js\";\nimport type { PluginConfig, QmdSearchResult, MemoryFile } from \"../types.js\";\nimport type { StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport {\n applyMemoryWorthFilter,\n buildMemoryWorthCounterMap,\n type MemoryWorthCounters,\n} from \"../memory-worth-filter.js\";\nimport {\n applyTrustScoreStage,\n buildTrustSignalsForRerank,\n type TrustStageResultItem,\n} from \"../trust-score-stage.js\";\nimport type { TrustSignals } from \"../trust-score.js\";\nimport { reorderRecallResultsWithMmr } from \"../recall-mmr.js\";\nimport { applyReasoningTraceBoost } from \"../reasoning-trace-recall.js\";\n\n/**\n * Coordinator for the recall-result reranking subsystem.\n *\n * Holds the per-namespace caches for memory-worth counters and trust signals\n * (previously orchestrator fields) so the reranking stages don't trigger a\n * full `readAllMemories` scan per query.\n */\nexport class RecallRerankCoordinator {\n private readonly getConfig: () => PluginConfig;\n private readonly getStorage: (namespace: string) => Promise<StorageManager>;\n private readonly readQmdResultMemory: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<MemoryFile | null>;\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 private readonly trustSignalCache = new Map<\n string,\n { at: number; signals: ReadonlyMap<string, TrustSignals> }\n >();\n private static readonly TRUST_SIGNAL_CACHE_TTL_MS = 30_000;\n\n constructor(options: {\n getConfig: () => PluginConfig;\n getStorage: (namespace: string) => Promise<StorageManager>;\n readQmdResultMemory: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<MemoryFile | null>;\n }) {\n this.getConfig = options.getConfig;\n this.getStorage = options.getStorage;\n this.readQmdResultMemory = options.readQmdResultMemory;\n }\n\n 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 >= RecallRerankCoordinator.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 < RecallRerankCoordinator.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 this.readQmdResultMemory(r.path, reader, namespaces);\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 config = this.getConfig();\n const filtered = applyMemoryWorthFilter(rankedInputs, {\n counters,\n now: new Date(),\n halfLifeMs:\n config.recallMemoryWorthHalfLifeMs > 0\n ? 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 /**\n * Issue #1577 — unified TrustScore recall stage. Thin wiring over the pure\n * {@link applyTrustScoreStage} scorer + the {@link buildTrustSignalsForRerank}\n * signal builder. The stage subsumes the Memory Worth multiplier — the\n * orchestrator runs exactly one of the two (mutual exclusion, rule 39; the\n * double-multiplier test in trust-score-stage.test.ts pins it structurally).\n *\n * Returns the admitted results AND the per-path trust map (including\n * quarantined items) so the caller can: (a) render epistemic hedges, (b)\n * surface quarantined items in X-ray with a reason (rule 34), and (c) filter\n * quarantined paths from fallback recall branches. The trust map is a\n * per-recall local — never instance state — so concurrent recalls cannot\n * race on it (review: shared-trust-map concurrency).\n */\n async applyTrustScoreRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }> {\n if (results.length === 0) return { results, trustByPath: null };\n const config = this.getConfig();\n const now = new Date();\n const halfLifeDays =\n config.recallMemoryWorthHalfLifeMs > 0\n ? config.recallMemoryWorthHalfLifeMs / (24 * 60 * 60 * 1000)\n : undefined;\n // Cold-tier direct-fallback reader: resolve once, reuse for every missing\n // candidate (mirrors the memory-worth filter's reader selection).\n let fallbackReader: StorageManager | null = null;\n const signals = await buildTrustSignalsForRerank(\n results.map((r) => r.path),\n namespaces,\n {\n readNamespaceMemories: async (ns) => (await this.getStorage(ns)).readAllMemories(),\n readMemoryFrontmatter: async (path) => {\n if (!fallbackReader) {\n for (const ns of namespaces) {\n try {\n fallbackReader = await this.getStorage(ns);\n break;\n } catch {\n // try next namespace\n }\n }\n }\n if (!fallbackReader) return null;\n const memory = await this.readQmdResultMemory(path, fallbackReader, namespaces);\n return memory ? memory.frontmatter : null;\n },\n },\n { cache: this.trustSignalCache, ttlMs: RecallRerankCoordinator.TRUST_SIGNAL_CACHE_TTL_MS },\n now,\n {\n recencyHalfLifeDays: halfLifeDays,\n logDebug: (message, context) => log.debug(message, context),\n },\n );\n if (signals.size === 0) {\n return { results, trustByPath: null };\n }\n // Synthetic monotone-decreasing rank so the multiplier rebias is applied\n // on top of upstream ordering, not raw QMD scores (see applyMemoryWorthRerank).\n const rankedInputs = results.map((r, i) => ({ path: r.path, score: results.length - i }));\n const stage = applyTrustScoreStage(rankedInputs, {\n signals,\n weights: config.trustScoreWeights,\n minMultiplier: config.trustScoreMinMultiplier,\n maxMultiplier: config.trustScoreMaxMultiplier,\n quarantine: config.trustScoreQuarantine,\n });\n const trustByPath = new Map(stage.all.map((item) => [item.path, item]));\n const byPath = new Map(results.map((r) => [r.path, r]));\n const admitted = stage.admitted\n .map((item) => byPath.get(item.path))\n .filter((r): r is QmdSearchResult => r !== undefined);\n return { results: admitted, trustByPath };\n }\n\n /**\n * Issue #1577 — apply the TrustScore stage (or, when trust is off, the Memory\n * Worth multiplier fallback) to ONE recall branch's results, returning the\n * scored results + the per-path trust map. Thin wiring over\n * {@link applyTrustScoreRerank} so every recall path — hot QMD, embedding\n * fallback, recent scan — applies the SAME multiplier gate (rule 41: a\n * feature gate must apply across ALL parallel recall paths). TrustScore\n * subsumes Memory Worth; exactly one runs (rule 39). Fail-open on lookup\n * errors so a storage hiccup never breaks a fallback path.\n */\n async applyTrustScoreToBranch(\n results: QmdSearchResult[],\n namespaces: string[],\n caps: CapabilitySet,\n label: string,\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }> {\n if (caps.recallTrustScore && results.length > 0) {\n try {\n return await this.applyTrustScoreRerank(results, namespaces);\n } catch (err) {\n log.debug(`trust-score stage (${label}) failed open`, {\n error: (err as Error).message,\n });\n }\n } else if (caps.recallMemoryWorthFilter && results.length > 0) {\n try {\n const filtered = await this.applyMemoryWorthRerank(results, namespaces);\n return { results: filtered, trustByPath: null };\n } catch (err) {\n log.debug(`memory-worth filter (${label}) failed open`, {\n error: (err as Error).message,\n });\n }\n }\n return { results, trustByPath: null };\n }\n\n diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n // `caps` is additive AND last (issue #1523) so the positional call shape\n // stays backward-compatible: the recall pipeline threads a resolved set,\n // but callers that omit it (e.g. direct unit-test invocations) get an\n // equivalent set derived from the same config — behavior-preserving.\n caps: CapabilitySet = resolveCapabilities(this.getConfig()),\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 caps.recallReasoningTraceBoost && typeof retrievalQuery === \"string\"\n ? applyReasoningTraceBoost(results, {\n enabled: true,\n query: retrievalQuery,\n })\n : results;\n const diversified = this.applyMmrToQmdResults(sectionId, boosted, caps);\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 applyMmrToQmdResults(\n sectionId: string,\n results: QmdSearchResult[],\n // Additive `caps` (issue #1523); defaults to a config-derived set so direct\n // callers that omit it behave identically to the threaded recall path.\n caps: CapabilitySet = resolveCapabilities(this.getConfig()),\n ): QmdSearchResult[] {\n if (!caps.recallMmr) 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 config = this.getConfig();\n const configuredTopN = 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 = 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","/**\n * Recall section coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the recall-output section-budgeting subsystem: section enablement\n * lookups, per-section maxChars/number resolution, section bucket appends,\n * budget-aware section truncation, and final ordered assembly of recall\n * sections within the configured character budget. Also builds the\n * LastRecallBudgetSummary and collects the sources used for X-ray tracing.\n *\n * Behavior-preserving move from orchestrator.ts — no logic changes; the\n * orchestrator constructs one instance and keeps thin delegating methods so\n * existing call sites (recallInternal, consolidation) continue to work.\n *\n * Config is accessed through a getter callback (not captured at construction)\n * so that post-construction reassignment of the orchestrator's live\n * `config` field is honored. This mirrors the ConversationIndexCoordinator /\n * TierMigrationCoordinator accessor pattern.\n */\n\nimport type { PluginConfig, RecallSectionConfig } from \"../types.js\";\nimport type { LastRecallBudgetSummary } from \"../recall-state.js\";\n\n/**\n * Coordinator for the recall section budgeting + assembly subsystem.\n *\n * All methods are pure with respect to the coordinator's own state — they\n * read config via the getter and operate on the caller-provided section\n * buckets. No caches are held because the config-derived values are cheap\n * to recompute and the buckets are transient (per-recall-call).\n */\nexport class RecallSectionCoordinator {\n private readonly getConfig: () => PluginConfig;\n private readonly resolveSectionEnabled: (\n sectionId: string,\n defaultEnabled: boolean,\n ) => boolean;\n\n constructor(options: {\n getConfig: () => PluginConfig;\n resolveSectionEnabled?: (\n sectionId: string,\n defaultEnabled: boolean,\n ) => boolean;\n }) {\n this.getConfig = options.getConfig;\n // Default to the coordinator's own config-based check so standalone usage\n // (e.g. config-recall-pipeline tests) keeps self-gating. The orchestrator\n // injects its own resolver so appendRecallSection flows through the same\n // overridable isRecallSectionEnabled that the recallInternal computation\n // gates use — keeping compute-side and append-side enablement coherent\n // (seam 13). This preserves the recall-hardening test seam where tests\n // override orchestrator.isRecallSectionEnabled to isolate sections.\n this.resolveSectionEnabled =\n options.resolveSectionEnabled ??\n ((id, def) => this.isRecallSectionEnabled(id, def));\n }\n\n getRecallSectionEntry(\n sectionId: string,\n ): RecallSectionConfig | undefined {\n const pipeline = Array.isArray(this.getConfig().recallPipeline)\n ? this.getConfig().recallPipeline\n : [];\n return pipeline.find((entry) => entry.id === sectionId);\n }\n\n 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 isSpecializedRecallSectionEnabled(\n sectionId: string,\n topLevelEnabled: boolean,\n ): boolean {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return topLevelEnabled;\n return entry.enabled === true || (topLevelEnabled && entry.enabled !== false);\n }\n\n 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 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 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.resolveSectionEnabled(sectionId, true)) 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 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 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 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 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 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.getConfig().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.getConfig().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 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.getConfig().recallPipeline)\n ? this.getConfig().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 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.getConfig().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 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 * QMD result resolver — extracted from the orchestrator (issue #1526 seam 11).\n *\n * Owns the subsystem that resolves a QMD search-result path back to the\n * concrete `MemoryFile` (and its owning namespace/storage). Three concerns\n * live here:\n *\n * - `readQmdResultMemory` — resolve a result path to a `MemoryFile`,\n * handling cold-tier collections, namespace-prefixed collections, and\n * absolute vs relative paths.\n * - `resolveColdQmdResultForRecall` — wrap a result with its owner\n * namespace so the recall pipeline can scope-filter candidates.\n * - `storageForAbsoluteQmdResultPath` — find the `StorageManager` whose\n * directory tree contains an absolute result path.\n *\n * Behavior-preserving move from orchestrator.ts — no logic changes. The\n * orchestrator constructs one instance and keeps thin delegating methods so\n * existing call sites (recallInternal, applyColdFallbackPipeline,\n * loadSearchResultMemoryMap, suggestLinksForMemory, and the\n * RecallRerankCoordinator callback) continue to work.\n *\n * Config, the storage router, and the orchestrator's namespace-resolution\n * helpers are accessed through getter callbacks (not captured at\n * construction) so that post-construction reassignment of the\n * orchestrator's live fields is honored. This mirrors the\n * RecallRerankCoordinator / ConversationIndexCoordinator accessor pattern.\n */\n\nimport path from \"node:path\";\nimport { log } from \"../logger.js\";\nimport { isPathInsideStorageRoot } from \"../storage-paths.js\";\nimport { namespaceIdentityFromToken } from \"../namespaces/identity.js\";\nimport { resolveNamespaceCapabilities } from \"../capabilities.js\";\nimport { SecureStoreLockedError } from \"../secure-store/index.js\";\nimport type { PluginConfig, QmdSearchResult, MemoryFile } from \"../types.js\";\nimport type { StorageManager } from \"../index.js\";\n\n/**\n * Split a relative QMD result path into its collection prefix and the\n * remainder. Returns `null` for absolute paths, date-only prefixes, or\n * paths with no collection separator.\n */\nexport function qmdCollectionPathParts(resultPath: string): {\n collection: string;\n relativePath: string;\n} | null {\n if (!resultPath || path.isAbsolute(resultPath)) return null;\n const normalized = resultPath.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\");\n const slashIndex = normalized.indexOf(\"/\");\n if (slashIndex <= 0 || slashIndex >= normalized.length - 1) return null;\n const collection = normalized.slice(0, slashIndex);\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(collection)) return null;\n return {\n collection,\n relativePath: normalized.slice(slashIndex + 1),\n };\n}\n\n/**\n * Build the set of on-disk candidate paths to probe for a QMD result,\n * constrained to the storage root so a result path can never escape the\n * namespace directory.\n */\nexport function qmdResultPathCandidates(\n storageDir: string,\n resultPath: string,\n): string[] {\n const candidates = new Set<string>();\n const storageRoot = path.resolve(storageDir);\n const addCandidate = (candidate: string) => {\n const resolved = path.resolve(candidate);\n if (isPathInsideStorageRoot(storageRoot, resolved)) {\n candidates.add(resolved);\n }\n };\n const addRelativeCandidates = (relativePath: string) => {\n const normalized = relativePath.replace(/\\\\/g, \"/\").replace(/^\\/+/, \"\");\n if (!normalized) return;\n addCandidate(path.join(storageRoot, normalized));\n if (/^\\d{4}-\\d{2}-\\d{2}\\//.test(normalized)) {\n addCandidate(path.join(storageRoot, \"facts\", normalized));\n }\n };\n\n if (path.isAbsolute(resultPath)) {\n addCandidate(resultPath);\n } else {\n addRelativeCandidates(resultPath);\n }\n\n return [...candidates];\n}\n\n/**\n * Extract a non-empty `dir` from a storage, returning `null` when the\n * property is absent or not a non-empty string at runtime. Proxy-backed\n * fake storages used in recall paths may not provide a real `dir`, so\n * every caller must handle the null case (skip or fall back to a direct\n * `readMemoryByPath`).\n */\nfunction storageDirOrNull(storage: StorageManager): string | null {\n const dir = storage.dir;\n return typeof dir === \"string\" && dir.length > 0 ? dir : null;\n}\n\n/**\n * Coordinator for resolving QMD search-result paths to concrete memory\n * files and their owning namespace/storage.\n */\nexport class QmdResultResolver {\n private readonly getConfig: () => PluginConfig;\n private readonly storageFor: (namespace: string) => Promise<StorageManager>;\n private readonly storageDirNamespace: (storageDir: string) => string;\n private readonly qmdCollectionNamespaceFromPrefix: (\n collectionPrefix: string,\n ) => string | null;\n private readonly namespaceFromPath: (p: string) => string;\n\n constructor(options: {\n getConfig: () => PluginConfig;\n storageFor: (namespace: string) => Promise<StorageManager>;\n storageDirNamespace: (storageDir: string) => string;\n qmdCollectionNamespaceFromPrefix: (\n collectionPrefix: string,\n ) => string | null;\n namespaceFromPath: (p: string) => string;\n }) {\n this.getConfig = options.getConfig;\n this.storageFor = options.storageFor;\n this.storageDirNamespace = options.storageDirNamespace;\n this.qmdCollectionNamespaceFromPrefix =\n options.qmdCollectionNamespaceFromPrefix;\n this.namespaceFromPath = options.namespaceFromPath;\n }\n\n async readQmdResultMemory(\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<MemoryFile | null> {\n const parts = qmdCollectionPathParts(resultPath);\n const fallbackStorageDir = storageDirOrNull(fallbackStorage);\n const config = this.getConfig();\n const coldCollection = config.qmdColdCollection ?? \"openclaw-engram-cold\";\n if (parts && parts.collection === coldCollection) {\n const storages: StorageManager[] = [];\n const seenStorageDirs = new Set<string>();\n const addStorage = (storage: StorageManager): void => {\n const storageDir = storageDirOrNull(storage);\n const storageKey = storageDir\n ? path.resolve(storageDir)\n : `storage-without-dir-${storages.length}`;\n if (seenStorageDirs.has(storageKey)) return;\n seenStorageDirs.add(storageKey);\n storages.push(storage);\n };\n\n const fallbackNamespace =\n fallbackStorageDir !== null\n ? this.storageDirNamespace(fallbackStorageDir)\n : config.defaultNamespace;\n if (\n recallNamespaces.length === 0 ||\n !resolveNamespaceCapabilities(config).namespaces ||\n recallNamespaces.includes(fallbackNamespace)\n ) {\n addStorage(fallbackStorage);\n }\n\n if (recallNamespaces.length > 0) {\n for (const namespace of recallNamespaces) {\n try {\n addStorage(await this.storageFor(namespace));\n } catch (err) {\n log.debug(\"qmd cold result namespace storage lookup skipped\", {\n path: resultPath,\n namespace,\n error: (err as Error).message,\n });\n }\n }\n }\n\n for (const storage of storages) {\n const storageDir = storageDirOrNull(storage);\n if (!storageDir) {\n const memory = await storage.readMemoryByPath(resultPath);\n if (memory) return memory;\n continue;\n }\n try {\n const coldRoot = path.join(storageDir, \"cold\");\n for (const candidate of qmdResultPathCandidates(\n coldRoot,\n parts.relativePath,\n )) {\n const memory = await storage.readMemoryByPath(candidate);\n if (memory) return memory;\n }\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n log.debug(\"qmd cold result path lookup failed open\", {\n path: resultPath,\n collection: coldCollection,\n error: (err as Error).message,\n });\n }\n }\n return null;\n }\n const collectionNamespace = parts\n ? this.qmdCollectionNamespaceFromPrefix(parts.collection)\n : null;\n\n if (parts && collectionNamespace) {\n try {\n const collectionStorage = await this.storageFor(collectionNamespace);\n for (const candidate of qmdResultPathCandidates(\n collectionStorage.dir,\n parts.relativePath,\n )) {\n const memory = await collectionStorage.readMemoryByPath(candidate);\n if (memory) return memory;\n }\n return null;\n } catch (err) {\n if (err instanceof SecureStoreLockedError) throw err;\n log.debug(\"qmd result namespace path lookup failed open\", {\n path: resultPath,\n namespace: collectionNamespace,\n error: (err as Error).message,\n });\n return null;\n }\n }\n\n if (path.isAbsolute(resultPath)) {\n if (!fallbackStorageDir) {\n return await fallbackStorage.readMemoryByPath(resultPath);\n }\n const ownerStorage = await this.storageForAbsoluteQmdResultPath(\n resultPath,\n fallbackStorage,\n recallNamespaces,\n );\n if (!ownerStorage) return null;\n for (const candidate of qmdResultPathCandidates(\n ownerStorage.dir,\n resultPath,\n )) {\n const memory = await ownerStorage.storage.readMemoryByPath(candidate);\n if (memory) return memory;\n }\n return null;\n }\n\n if (!fallbackStorageDir) {\n return await fallbackStorage.readMemoryByPath(resultPath);\n }\n for (const candidate of qmdResultPathCandidates(\n fallbackStorageDir,\n resultPath,\n )) {\n const memory = await fallbackStorage.readMemoryByPath(candidate);\n if (memory) return memory;\n }\n return null;\n }\n\n async resolveColdQmdResultForRecall(\n result: QmdSearchResult,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<{ namespace: string; result: QmdSearchResult } | null> {\n const memory = await this.readQmdResultMemory(\n result.path,\n fallbackStorage,\n recallNamespaces,\n );\n if (!memory) return null;\n\n let ownerNamespace: string | null = null;\n if (path.isAbsolute(memory.path)) {\n const ownerStorage = await this.storageForAbsoluteQmdResultPath(\n memory.path,\n fallbackStorage,\n recallNamespaces,\n );\n ownerNamespace = ownerStorage?.namespace ?? null;\n if (!ownerNamespace && resolveNamespaceCapabilities(this.getConfig()).namespaces) return null;\n }\n ownerNamespace ??= this.namespaceFromPath(memory.path);\n if (\n recallNamespaces.length > 0 &&\n !recallNamespaces.includes(ownerNamespace)\n ) {\n return null;\n }\n\n return {\n namespace: ownerNamespace,\n result: {\n ...result,\n docid: result.docid || memory.frontmatter.id,\n path: memory.path,\n snippet: result.snippet || memory.content.slice(0, 400),\n },\n };\n }\n\n async storageForAbsoluteQmdResultPath(\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[] = [],\n ): Promise<{ storage: StorageManager; dir: string; namespace: string } | null> {\n const resolvedPath = path.resolve(resultPath);\n const config = this.getConfig();\n const memoryRoot = path.resolve(config.memoryDir);\n const namespacesRoot = path.join(memoryRoot, \"namespaces\");\n const fallbackStorageDir = storageDirOrNull(fallbackStorage);\n const matches: Array<{ storage: StorageManager; dir: string; namespace: string }> = [];\n const seenDirs = new Set<string>();\n\n const maybeAddStorage = (storage: StorageManager, namespace: string) => {\n const storageDir = storageDirOrNull(storage);\n if (!storageDir) return;\n const candidateRoot = path.resolve(storageDir);\n if (seenDirs.has(candidateRoot)) return;\n if (!isPathInsideStorageRoot(candidateRoot, resolvedPath)) return;\n if (\n candidateRoot === memoryRoot &&\n isPathInsideStorageRoot(namespacesRoot, resolvedPath)\n ) {\n return;\n }\n seenDirs.add(candidateRoot);\n matches.push({ storage, dir: candidateRoot, namespace });\n };\n\n const fallbackNamespace =\n fallbackStorageDir !== null\n ? this.storageDirNamespace(fallbackStorageDir)\n : config.defaultNamespace;\n maybeAddStorage(fallbackStorage, fallbackNamespace);\n\n const candidateNamespaces = new Set<string>();\n candidateNamespaces.add(config.defaultNamespace);\n candidateNamespaces.add(config.sharedNamespace);\n for (const ns of recallNamespaces) {\n candidateNamespaces.add(ns);\n }\n if (isPathInsideStorageRoot(namespacesRoot, resolvedPath)) {\n const relativeToNamespaces = path.relative(namespacesRoot, resolvedPath);\n const [namespaceSegment] = relativeToNamespaces.split(/[\\\\/]/);\n if (namespaceSegment) {\n candidateNamespaces.add(\n namespaceIdentityFromToken(namespaceSegment) ?? namespaceSegment,\n );\n }\n }\n for (const policy of config.namespacePolicies ?? []) {\n candidateNamespaces.add(policy.name);\n }\n\n for (const ns of candidateNamespaces) {\n if (!ns) continue;\n try {\n maybeAddStorage(await this.storageFor(ns), ns);\n } catch {\n continue;\n }\n }\n\n matches.sort((a, b) => b.dir.length - a.dir.length);\n return matches[0] ?? null;\n }\n}\n","/**\n * Contradiction-linking coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the write-path semantic-analysis subsystem: contradiction detection\n * (QMD similarity search + LLM verification), deferred contradiction\n * auto-resolve (#1645 — retires superseded memories only after the new write's\n * tombstone status is known), and memory link suggestion. Behavior-preserving\n * move from orchestrator.ts — no logic changes; the orchestrator constructs one\n * instance and keeps thin delegating methods so existing call sites (writeMemory\n * fact-write branches) continue to work.\n *\n * Config, storage, search, namespace resolution, and the extraction engine are\n * accessed through getter callbacks (not captured at construction) so that\n * post-construction reassignment of the orchestrator's live fields is honored.\n * This mirrors the RecallRerankCoordinator / ConversationIndexCoordinator\n * accessor pattern.\n */\n\nimport type {\n MemoryLink,\n PluginConfig,\n QmdSearchResult,\n} from \"../types.js\";\n// StorageManager type comes from the package barrel (type-only) so this\n// module does not add a direct storage.ts import (ratchet #1533).\nimport type { StorageManager } from \"../index.js\";\nimport type { ExtractionEngine } from \"../extraction.js\";\nimport { log } from \"../logger.js\";\nimport { resolveIndexingCapabilities } from \"../capabilities.js\";\nimport { deindexMemory } from \"../temporal-index.js\";\n\n/** Result type of {@link ContradictionLinkingCoordinator.checkForContradiction}. */\nexport interface ContradictionResult {\n supersededId: string;\n confidence: number;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n}\n\n/**\n * Subset of {@link ContradictionResult} used by\n * {@link ContradictionLinkingCoordinator.applyDeferredContradictionResolve}.\n * The deferred resolve runs AFTER writeMemory and only needs the supersede\n * target fields (not confidence, which the caller already consumed).\n */\nexport interface ContradictionResolveTarget {\n supersededId: string;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n}\n\n/**\n * Coordinator for the contradiction-detection + memory-linking subsystem.\n *\n * The three methods mirror the orchestrator's former private methods\n * `checkForContradiction`, `applyDeferredContradictionResolve`, and\n * `suggestLinksForMemory` byte-for-byte in logic.\n */\nexport class ContradictionLinkingCoordinator {\n private readonly getConfig: () => PluginConfig;\n private readonly isSearchAvailable: () => boolean;\n private readonly searchAcrossNamespaces: (options: {\n query: string;\n namespaces?: string[];\n maxResults?: number;\n mode?: \"search\" | \"hybrid\" | \"bm25\" | \"vector\";\n }) => Promise<QmdSearchResult[]>;\n private readonly extractMemoryIdsFromResults: (\n results: QmdSearchResult[],\n ) => string[];\n private readonly namespaceFromPath: (p: string) => string;\n private readonly storageForNamespace: (\n namespace: string,\n ) => Promise<StorageManager>;\n private readonly getExtraction: () => ExtractionEngine;\n\n constructor(options: {\n getConfig: () => PluginConfig;\n isSearchAvailable: () => boolean;\n searchAcrossNamespaces: (options: {\n query: string;\n namespaces?: string[];\n maxResults?: number;\n mode?: \"search\" | \"hybrid\" | \"bm25\" | \"vector\";\n }) => Promise<QmdSearchResult[]>;\n extractMemoryIdsFromResults: (results: QmdSearchResult[]) => string[];\n namespaceFromPath: (p: string) => string;\n storageForNamespace: (namespace: string) => Promise<StorageManager>;\n getExtraction: () => ExtractionEngine;\n }) {\n this.getConfig = options.getConfig;\n this.isSearchAvailable = options.isSearchAvailable;\n this.searchAcrossNamespaces = options.searchAcrossNamespaces;\n this.extractMemoryIdsFromResults = options.extractMemoryIdsFromResults;\n this.namespaceFromPath = options.namespaceFromPath;\n this.storageForNamespace = options.storageForNamespace;\n this.getExtraction = options.getExtraction;\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 async checkForContradiction(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<ContradictionResult | null> {\n if (!this.isSearchAvailable()) return null;\n\n const config = this.getConfig();\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 < 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 = await this.storageForNamespace(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 extraction = this.getExtraction();\n const verification = await 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 >= 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, the caller retires the old memory AFTER the new write lands\n // and its tombstone status is known (#1645: defer auto-resolve until\n // tombstone status is known — a tombstone-blocked new write must not\n // retire the only active copy, leaving neither memory active). When\n // disabled, the old memory stays active for manual review. The\n // contradiction info is returned in both cases so the caller can apply\n // the deferred retire post-write.\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${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 * #1645: Complete the deferred contradiction auto-resolve after writeMemory\n * returns and the new write's tombstone status is known. Retires the old\n * memory + deindexes it ONLY when the new write is genuinely active (not\n * tombstone-blocked / pending_review). A blocked write must not retire the\n * only active copy — deferring here closes the \"contradictionAutoResolve\n * supersedes before tombstone status is known\" defect class.\n */\n async applyDeferredContradictionResolve(\n contradiction: ContradictionResolveTarget | null | undefined,\n storage: StorageManager,\n newMemoryId: string,\n postWriteGuard: boolean,\n ): Promise<void> {\n const config = this.getConfig();\n // #1645 yG2: clear the pre-write `supersedes` link from a blocked row so\n // it doesn't claim to supersede a still-active memory (best-effort).\n if (postWriteGuard && contradiction && config.contradictionAutoResolve) {\n try {\n const blockedRow = await storage.getMemoryById(newMemoryId);\n if (blockedRow?.frontmatter?.supersedes) {\n await storage.writeMemoryFrontmatter(blockedRow, { supersedes: undefined });\n }\n } catch (err) {\n log.warn(\n `contradiction auto-resolve supersedes clear failed for blocked ${newMemoryId}: ${err}`,\n );\n }\n }\n if (\n !contradiction ||\n !config.contradictionAutoResolve ||\n postWriteGuard\n ) {\n return;\n }\n try {\n await storage.supersedeMemory(\n contradiction.supersededId,\n newMemoryId,\n contradiction.reason,\n );\n if (\n resolveIndexingCapabilities(config).queryAwareIndexing &&\n contradiction.supersededPath\n ) {\n deindexMemory(\n config.memoryDir,\n contradiction.supersededPath,\n contradiction.supersededCreated,\n contradiction.supersededTags,\n );\n }\n } catch (err) {\n log.warn(\n `contradiction auto-resolve supersede failed for ${contradiction.supersededId}: ${err}`,\n );\n }\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 async suggestLinksForMemory(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<MemoryLink[]> {\n if (!this.isSearchAvailable()) 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 = await this.storageForNamespace(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 extraction = this.getExtraction();\n const suggestions = await 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","/**\n * Extraction-run coordinator — extracted from the orchestrator\n * (issue #1526, seam 15).\n *\n * Owns the buffer→extract→persist pipeline orchestration:\n * - `runExtraction` — the main extraction pipeline coordinator\n * (normalize → threshold gate → namespace resolve → dedupe\n * fingerprint → extract → validate → persist → post-write hooks)\n * - dedupe support: `shouldQueueExtraction`,\n * `buildExtractionFingerprint`, `normalizeExtractionFingerprintTurns`\n * - `recordProcessedExtractionFingerprint` — meta recording\n *\n * The orchestrator constructs one instance and delegates the extraction\n * run to it. `persistExtraction`, `maybeCapturePassiveCorrections`, and\n * all post-write side-effect helpers arrive as injectable delegates so\n * the orchestrator keeps ownership of cross-subsystem routing and the\n * behavior-critical chokepoints it hosts.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps thin delegating methods so existing call sites\n * and tests that exercise the public API continue to work.\n */\n\nimport { createHash } from \"node:crypto\";\nimport type { StorageManager } from \"../index.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport type { ExtractionEngine } from \"../extraction.js\";\nimport type { SmartBuffer } from \"../buffer.js\";\nimport type { ThreadingManager } from \"../threading.js\";\nimport type { BoxBuilder } from \"../boxes.js\";\nimport {\n resolvePrincipal,\n defaultNamespaceForPrincipal,\n} from \"../namespaces/principal.js\";\nimport {\n resolveScopeProfilePlan,\n type ResolvedScopeProfilePlan,\n} from \"../namespaces/scope-profiles.js\";\nimport { resolveCodingNamespaceOverlay } from \"../coding/coding-namespace.js\";\nimport type { CodingContext } from \"../types.js\";\nimport {\n resolvePresentationCapabilities,\n resolveMemoryLifecycleCapabilities,\n type GraphConstructionCapabilitySet,\n type MemoryLifecycleCapabilitySet,\n} from \"../capabilities.js\";\nimport { parseFlexibleIsoTimestamp } from \"../utils/iso-timestamp.js\";\nimport { log } from \"../logger.js\";\nimport type {\n PluginConfig,\n BufferTurn,\n ExtractionResult,\n} from \"../types.js\";\nimport type { TierMigrationCycleSummary } from \"../recall-state.js\";\n\nexport interface ExtractionRunResult {\n status: \"completed\" | \"skipped\";\n reason?: string;\n persistedCount: number;\n durableOutputCount: number;\n postPersistMetadataFailed?: boolean;\n}\n\n/** Dependencies injected by the orchestrator. All stable references or\n * live accessors — lazy getters for anything tests reassign\n * post-construction (buffer, extraction, storageRouter, threading). */\nexport interface ExtractionRunCoordinatorDeps {\n config: PluginConfig;\n getBuffer: () => SmartBuffer;\n getExtraction: () => ExtractionEngine;\n getStorageRouter: () => NamespaceStorageRouter;\n getThreading: () => ThreadingManager;\n\n persistExtraction: (\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: { sessionKey?: string; principal?: string; validAt?: string },\n baseNamespace?: string,\n scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,\n sourceText?: string,\n graphCaps?: GraphConstructionCapabilitySet,\n lifecycleCaps?: MemoryLifecycleCapabilitySet,\n ) => Promise<string[]>;\n\n maybeCapturePassiveCorrections: (\n turns: readonly BufferTurn[],\n opts: {\n sessionKey: string;\n principal?: string;\n namespace: string;\n bufferKey: string;\n isLiveSession: boolean;\n },\n ) => Promise<void>;\n\n resolveSelfNamespace: (sessionKey?: string) => string;\n getCodingContextForSession: (sessionKey: string) => CodingContext | null;\n applyCodingNamespaceOverlay: (sessionKey: string, namespace: string) => string;\n boxBuilderFor: (storage: StorageManager) => BoxBuilder;\n appendPersistedThreadEpisodes: (\n threadId: string,\n ids: string[],\n ) => Promise<void>;\n maybeScheduleConsolidation: (nonZero: boolean) => void;\n requestQmdMaintenance: () => void;\n 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 getLastPersistExtractionDeferredCount: () => number;\n recordProcessedExtractionFingerprint: (\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>,\n ) => Promise<void>;\n}\n\n// Recall/extraction abort helpers live in orchestrator-helpers.ts since\n// #1526 seam 25; this file previously carried duplicate copies\n// (AGENTS.md rule 8 — no duplicated helpers).\nimport { raceRecallAbort, throwIfRecallAborted } from \"./orchestrator-helpers.js\";\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\n/**\n * Coordinates the extraction run pipeline. Holds the dedupe fingerprint\n * cache (`recentExtractionFingerprints`) and delegates all side effects\n * to injected orchestrator methods.\n */\nexport class ExtractionRunCoordinator {\n private readonly recentExtractionFingerprints = new Map<string, number>();\n\n constructor(\n private readonly deps: ExtractionRunCoordinatorDeps,\n ) {}\n\n private get config(): PluginConfig {\n return this.deps.config;\n }\n\n // -------------------------------------------------------------------------\n // Source-valid-at helpers (moved from orchestrator.ts module scope)\n // -------------------------------------------------------------------------\n\n private latestSourceValidAtFromTurns(turns: readonly BufferTurn[]): string | undefined {\n let latestMs: number | null = null;\n for (const turn of turns) {\n if (turn.extractionContextOnly === true) continue;\n if (typeof turn.sourceValidAt !== \"string\") continue;\n const parsed = parseFlexibleIsoTimestamp(turn.sourceValidAt.trim());\n if (parsed === null) continue;\n if (latestMs === null || parsed > latestMs) {\n latestMs = parsed;\n }\n }\n return latestMs === null ? undefined : new Date(latestMs).toISOString();\n }\n\n\n // -------------------------------------------------------------------------\n // Extraction dedupe fingerprint helpers\n // -------------------------------------------------------------------------\n\n 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\n 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\n\n shouldQueueExtraction(\n turns: BufferTurn[],\n options: { commit?: boolean; bufferKey?: string } = {},\n ): boolean {\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.config);\n if (!lifecycleCaps.extractionDedupe) 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 // -------------------------------------------------------------------------\n // Processed-fingerprint recording\n // -------------------------------------------------------------------------\n\n 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\n // -------------------------------------------------------------------------\n // Main extraction pipeline\n // -------------------------------------------------------------------------\n\n async runExtraction(\n turns: BufferTurn[],\n options: {\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n skipUserTurnThreshold?: boolean;\n deadlineMs?: number;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n failOnExtractionFailure?: boolean;\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 * Pin the provenance principal instead of deriving it from\n * `resolvePrincipal(sessionKey)` (#1495 thread 1). When set, this is the\n * identity an access surface already authenticated; used so observed-turn\n * provenance is correct even though `turn.sessionKey` is the ORIGINAL\n * (un-prefixed) key and storage is pinned via `writeNamespaceOverride`.\n */\n principalOverride?: string;\n } = {},\n ): Promise<ExtractionRunResult> {\n log.debug(`running extraction on ${turns.length} turns`);\n const clearBufferAfterExtraction =\n options.clearBufferAfterExtraction ?? true;\n const skipCharThreshold = options.skipCharThreshold ?? false;\n const skipUserTurnThreshold = options.skipUserTurnThreshold ?? 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.deps.getBuffer().clearAfterExtraction(bufferKey, turns);\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 status: \"skipped\",\n reason: \"cron_session\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\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 const targetTurns = normalizedTurns.filter(\n (turn) => turn.extractionContextOnly !== true,\n );\n if (targetTurns.length === 0) {\n log.debug(\"skipping extraction: no non-context turns after normalization\");\n // Context-only turns may still contain corrections (review: \"context-only\n // turns skip capture\"). Scan normalizedTurns before clearing the buffer.\n if (normalizedTurns.length > 0) {\n await this.deps.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], { sessionKey, principal: resolvePrincipal(sessionKey, this.config), namespace: this.deps.resolveSelfNamespace(sessionKey), bufferKey, isLiveSession: clearBufferAfterExtraction });\n }\n await clearBuffer();\n return { status: \"skipped\", reason: \"empty_normalized_turns\", persistedCount: 0, durableOutputCount: 0 };\n }\n const sourceValidAt = this.latestSourceValidAtFromTurns(targetTurns);\n throwIfDeadlineExceeded(\"before_extract\");\n throwIfAborted(\"before_extract\");\n\n const userTurns = targetTurns.filter((t) => t.role === \"user\");\n const totalChars = targetTurns.reduce(\n (sum, t) => sum + t.content.length,\n 0,\n );\n const belowCharThreshold = totalChars < this.config.extractionMinChars;\n const belowUserTurnThreshold =\n !skipUserTurnThreshold &&\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 // Passive correction capture runs even when extraction is skipped for\n // being below the char/user-turn threshold (review: \"skipped extraction\n // skips capture\"). A short correction like \"stop using Vim\" is under\n // extractionMinChars but is exactly the high-value case this feature\n // exists for. The write namespace resolves through the SAME scope-profile\n // plan as the full extraction path so corrections target the active\n // profile's write layer, not just resolveSelfNamespace (review:\n // \"below-threshold wrong namespace\"). The ACL in passiveCorrectionService\n // authorizes the actual plan/apply.\n {\n const capturePrincipal =\n typeof options.principalOverride === \"string\" && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const captureWO = typeof options.writeNamespaceOverride === \"string\" && options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride : undefined;\n const captureCodingCtx = sessionKey ? this.deps.getCodingContextForSession(sessionKey) : null;\n const captureCodingOv = resolveCodingNamespaceOverlay(captureCodingCtx, this.config.codingMode, this.config.defaultNamespace);\n const captureScopePlan = resolveScopeProfilePlan({ config: this.config, principal: capturePrincipal, codingContext: captureCodingCtx, codingOverlay: captureCodingOv });\n const captureNamespace = captureWO ?? captureScopePlan?.writeNamespace ?? this.deps.resolveSelfNamespace(sessionKey);\n await this.deps.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], {\n sessionKey, principal: capturePrincipal, namespace: captureNamespace, bufferKey, isLiveSession: clearBufferAfterExtraction,\n });\n }\n return {\n status: \"skipped\",\n reason: \"below_threshold\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n\n // Provenance principal honours the access-surface override (#1495 thread 1,\n // mirroring the recall path's `principalOverride`, issue #570 PR 4). Access\n // surfaces that authenticated the caller at the transport layer pass their\n // resolved principal so provenance uses the SAME identity the surface\n // authorized, instead of `resolvePrincipal(sessionKey)` — which on a\n // namespace-prefixed key would collapse to `default`. The ORIGINAL,\n // un-prefixed session key still drives threading.\n const principal =\n typeof options.principalOverride === \"string\" &&\n options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n // Write path — explicit callers still win. Otherwise, an active hosted\n // scope profile owns the extraction write target so hook-captured turns land\n // in the same layer that profile recall searches. Without a profile, preserve\n // the existing coding-agent overlay behavior (issue #569).\n const explicitWriteNamespace =\n typeof options.writeNamespaceOverride === \"string\" &&\n options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : undefined;\n const codingContextForWrite = sessionKey\n ? this.deps.getCodingContextForSession(sessionKey)\n : null;\n const codingOverlayForWrite = resolveCodingNamespaceOverlay(\n codingContextForWrite,\n this.config.codingMode,\n this.config.defaultNamespace,\n );\n const scopeProfileGatePlan = resolveScopeProfilePlan({\n config: this.config,\n principal,\n codingContext: codingContextForWrite,\n codingOverlay: codingOverlayForWrite,\n });\n const scopeProfileWritePlan = explicitWriteNamespace ? null : scopeProfileGatePlan;\n if (scopeProfileWritePlan) {\n const selectedLayer = scopeProfileWritePlan.layers.find(\n (layer) => layer.id === scopeProfileWritePlan.writeLayer,\n );\n const writeNamespaceReadable = scopeProfileWritePlan.readNamespaces.includes(\n scopeProfileWritePlan.writeNamespace,\n );\n if (!selectedLayer?.writable || !writeNamespaceReadable) {\n log.warn(\n `runExtraction: skipping scope profile ${scopeProfileWritePlan.profileId} because write layer ${scopeProfileWritePlan.writeLayer} is not writable inside the profile read stack`,\n );\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"scope_profile_no_writable_layer\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n }\n const selfNamespace =\n explicitWriteNamespace ??\n scopeProfileWritePlan?.writeNamespace ??\n this.deps.applyCodingNamespaceOverlay(\n sessionKey,\n defaultNamespaceForPrincipal(principal, this.config),\n );\n const storage = await this.deps.getStorageRouter().storageFor(selfNamespace);\n const shouldPersistProcessedFingerprint = targetTurns.some(\n (turn) => turn.persistProcessedFingerprint === true,\n );\n const extractionFingerprint = this.buildExtractionFingerprint(\n targetTurns,\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 status: \"skipped\",\n reason: \"processed_fingerprint\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\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.deps.getExtraction().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. Explicit\n // fail-closed callers, such as flush-plan import, must not observe\n // malformed extractor output as a successful skip.\n if (!result) {\n log.warn(\"runExtraction: extraction returned null/undefined\");\n if (options.failOnExtractionFailure) {\n throw new Error(\"extraction failed: invalid_extraction_result\");\n }\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"invalid_extraction_result\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n const invalidExtractionResultFields = [\n [\"facts\", result.facts],\n [\"entities\", result.entities],\n [\"questions\", result.questions],\n [\"profileUpdates\", result.profileUpdates],\n ]\n .filter(([, value]) => !Array.isArray(value))\n .map(([field]) => field);\n if (invalidExtractionResultFields.length > 0) {\n log.warn(\n \"runExtraction: extraction returned invalid collection fields\",\n {\n invalidFields: invalidExtractionResultFields,\n resultKeys:\n typeof result === \"object\" && result !== null\n ? Object.keys(result)\n : [],\n },\n );\n if (options.failOnExtractionFailure) {\n throw new Error(\"extraction failed: invalid_extraction_result\");\n }\n await clearBuffer();\n return {\n status: \"skipped\",\n reason: \"invalid_extraction_result\",\n persistedCount: 0,\n durableOutputCount: 0,\n };\n }\n const extractionFailure =\n typeof result.extractionFailure === \"string\" &&\n result.extractionFailure.trim().length > 0\n ? result.extractionFailure\n : undefined;\n if (options.failOnExtractionFailure && extractionFailure) {\n throw new Error(`extraction failed: ${extractionFailure}`);\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 if (extractionFailure) {\n log.warn(\n \"runExtraction: extraction reported failure with no durable outputs; not marking fingerprint processed\",\n { extractionFailure },\n );\n }\n if (\n extractionFingerprint &&\n shouldPersistProcessedFingerprint &&\n !extractionFailure\n ) {\n meta ??= await storage.loadMeta();\n await this.deps.recordProcessedExtractionFingerprint(\n storage,\n extractionFingerprint,\n meta,\n );\n meta.extractionCount += 1;\n meta.lastExtractionAt = new Date().toISOString();\n await storage.saveMeta(meta);\n }\n // Correction-only turns that meet char/user-turn thresholds but yield\n // zero facts still need passive capture (review: \"empty extraction skips\n // capture\"). selfNamespace/principal already resolved above.\n await this.deps.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], { sessionKey, principal, namespace: selfNamespace, bufferKey, isLiveSession: clearBufferAfterExtraction });\n await clearBuffer();\n return { status: \"skipped\", reason: \"empty_extraction_result\", persistedCount: 0, durableOutputCount: 0 };\n }\n\n let threadIdForExtraction: string | null = null;\n if (resolvePresentationCapabilities(this.config).threading && turns.length > 0) {\n const lastTurn = turns[turns.length - 1];\n try {\n threadIdForExtraction = await this.deps.getThreading().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.deps.persistExtraction(\n result,\n storage,\n threadIdForExtraction,\n { sessionKey, principal, validAt: sourceValidAt },\n // Pass the KNOWN base namespace (NHIdx) so the catalog write touch records the\n // real namespace rather than a guess decoded from the storage dir.\n selfNamespace,\n scopeProfileGatePlan,\n // Verbatim source turns for the faithfulness gate (#1576) so it can\n // locate a quote per fact when #1575 spans are absent.\n normalizedTurns.map((t) => t.content).join(\"\\n\\n\"),\n );\n let postPersistMetadataFailed = false;\n meta ??= await storage.loadMeta();\n if (extractionFingerprint && shouldPersistProcessedFingerprint) {\n try {\n await this.deps.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 postPersistMetadataFailed = true;\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 try {\n await storage.saveMeta(meta);\n } catch (error) {\n log.warn(\n \"runExtraction: failed to save extraction metadata after durable persistence; continuing with buffer clear\",\n error,\n );\n postPersistMetadataFailed = true;\n }\n\n const durableOutputCount =\n result.facts.length +\n result.entities.length +\n result.questions.length +\n result.profileUpdates.length;\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.deps.getLastPersistExtractionDeferredCount();\n if (deferredCount > 0 && normalizedTurns.length > 0) {\n await this.deps.getBuffer().retainDeferredTurns(\n bufferKey,\n normalizedTurns as BufferTurn[],\n 10,\n );\n } else {\n await this.deps.getBuffer().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 // Passive correction capture (issue #1581) — detect corrections expressed\n // passively in the extracted turns and route to the Correction Contract.\n // Runs AFTER persistence + buffer clear so a capture failure never blocks\n // the extraction return. `clearBufferAfterExtraction` gates live-session\n // auto-apply (replay/import → queue-only).\n await this.deps.maybeCapturePassiveCorrections(normalizedTurns as BufferTurn[], {\n sessionKey,\n principal,\n namespace: selfNamespace,\n bufferKey,\n isLiveSession: clearBufferAfterExtraction,\n });\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 (resolvePresentationCapabilities(this.config).memoryBoxes && 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.deps.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. The helper excludes pending_review ids (#1635).\n if (\n resolvePresentationCapabilities(this.config).threading &&\n threadIdForExtraction &&\n persistedIds.length > 0\n ) {\n await this.deps.appendPersistedThreadEpisodes(\n threadIdForExtraction,\n persistedIds,\n );\n }\n\n // Thread title update for the already-established thread context.\n if (resolvePresentationCapabilities(this.config).threading && threadIdForExtraction) {\n const conversationContent = turns.map((t) => t.content).join(\" \");\n try {\n await this.deps.getThreading().updateThreadTitle(\n threadIdForExtraction,\n conversationContent,\n );\n } catch (err) {\n log.warn(\n \"[threading] updateThreadTitle failed after persistence (non-fatal)\",\n err,\n );\n }\n }\n\n // Check if consolidation is needed (debounced + non-zero gated).\n const nonZeroExtraction = durableOutputCount > 0;\n try {\n // The increment of nonZeroExtractionsSinceConsolidation moved into\n // the scheduler with the rest of the cadence state (issue #1526 PR1).\n this.deps.maybeScheduleConsolidation(nonZeroExtraction);\n } catch (err) {\n log.warn(\n \"runExtraction: consolidation scheduling failed after persistence (non-fatal)\",\n err,\n );\n }\n\n try {\n this.deps.requestQmdMaintenance();\n } catch (err) {\n log.warn(\n \"runExtraction: QMD maintenance scheduling failed after persistence (non-fatal)\",\n err,\n );\n }\n\n try {\n await this.deps.runTierMigrationCycle(storage, \"extraction\");\n } catch (err) {\n log.warn(\n \"runExtraction: tier migration failed after persistence (non-fatal)\",\n err,\n );\n }\n\n return {\n status: \"completed\",\n persistedCount: persistedIds.length,\n durableOutputCount,\n postPersistMetadataFailed,\n };\n }\n}\n\n","/**\n * Orchestrator module-level helpers — relocated from orchestrator.ts\n * (issue #1526, seam 25).\n *\n * Pure functions, types, and constants that previously lived at module\n * level in orchestrator.ts: recall-mode planning, recall snapshots and\n * parsers, abort/race helpers, artifact recall limits, replay\n * source-time slicing, day-summary date utilities, and QMD startup\n * checks. orchestrator.ts re-exports the previously-public names so\n * every existing importer (coordinators, tests, root shims) keeps\n * working unchanged.\n *\n * Behavior-preserving move — no logic changes.\n */\n\nimport { createHash } from \"node:crypto\";\nimport os from \"node:os\";\nimport path from \"node:path\";\nimport { abortError as sharedAbortError, throwIfAborted as sharedThrowIfAborted } from \"../abort-error.js\";\nimport type { CapabilitySet } from \"../capabilities.js\";\nimport { buildCompressionGuidelinesMarkdown as buildCompressionGuidelinesMarkdownV2 } from \"../compression-optimizer.js\";\nimport { FallbackLlmClient } from \"../fallback-llm.js\";\nimport { hasBroadGraphIntent, planRecallMode } from \"../intent.js\";\nimport { resolveLifecycleState } from \"../lifecycle.js\";\nimport { log } from \"../logger.js\";\nimport type { GraphRecallRankedResult, GraphRecallShadowComparison } from \"./graph-recall-coordinator.js\";\nimport { parseQmdExplain } from \"../qmd.js\";\nimport type { GraphRecallExpandedEntry } from \"../recall-state.js\";\nimport type { RecallXrayServedBy } from \"../recall-xray.js\";\nimport { type BufferTurn, type MemoryActionEvent, type MemoryFile, type MemoryFrontmatter, type MemoryIntent, type PluginConfig, type QmdSearchResult, type RecallPlanMode, confidenceTier } from \"../types.js\";\nimport { categoryDirName } from \"../utils/category-dir.js\";\nimport { parseFlexibleIsoTimestamp } from \"../utils/iso-timestamp.js\";\n\nexport interface BulkImportBatchIngestResult {\n attemptedTurnCount: number;\n extractionCount: number;\n persistedCount: number;\n durableOutputCount: number;\n skippedCount: number;\n failedCount: number;\n postPersistMetadataFailureCount: number;\n processedTurnCount: number;\n}\n\nexport class BulkImportBatchPartialFailureError extends Error {\n readonly partialResult: BulkImportBatchIngestResult;\n\n readonly originalError: unknown;\n\n constructor(\n message: string,\n partialResult: BulkImportBatchIngestResult,\n originalError: unknown,\n ) {\n super(message);\n this.name = \"BulkImportBatchPartialFailureError\";\n this.partialResult = partialResult;\n this.originalError = originalError;\n }\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 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 * Where `plannedMode` came from (issue #1367 / Option C). `\"heuristic\"` for\n * the regex planner; `\"llm\"` when the LLM planner classified it; and\n * `\"heuristic-fallback\"` when the LLM was enabled but errored/timed out and we\n * fell back. Absent on the synchronous heuristic-only path.\n */\n plannerSource?: \"heuristic\" | \"llm\" | \"heuristic-fallback\";\n /** Short rationale from the planner (for telemetry / x-ray). */\n plannerReason?: string;\n /** Wall-clock spent in the LLM planner call, when one was made. */\n plannerLatencyMs?: number;\n /** True when the LLM planner was enabled but fell back to the heuristic. */\n plannerFallbackUsed?: boolean;\n /** Model that served the LLM classification, when one was used. */\n plannerModelUsed?: string;\n /**\n * The regex-heuristic baseline mode, captured whenever the LLM planner ran\n * (any source). Lets operators compare planned-vs-heuristic during rollout —\n * distinct from `plannedMode`, which on the LLM path is the LLM's choice.\n */\n plannerHeuristicMode?: RecallPlanMode;\n /**\n * In shadow mode, the mode the LLM *would* have chosen (recorded for\n * comparison) while `effectiveMode` stays on the heuristic decision.\n */\n shadowLlmMode?: RecallPlanMode;\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 */\nexport function 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 * User-aware context scopes active for this recall. Used by X-ray\n * provenance safety checks so boundary-scoped memories are evaluated\n * against the caller's real context.\n */\n currentContextScopes?: readonly unknown[];\n}\n\nexport type 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.\nexport const abortRecallError = sharedAbortError;\n\nexport function throwIfRecallAborted(\n signal?: AbortSignal,\n message = \"recall aborted\",\n): void {\n sharedThrowIfAborted(signal, message);\n}\n\nexport async 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. */\nexport const COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour\n\nexport const DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS = 10_000;\n\nexport type DaySummaryGatherOptions = {\n timeZone?: string;\n now?: Date;\n};\n\nexport function normalizeIanaTimeZone(value: unknown): string | undefined {\n if (typeof value !== \"string\") return undefined;\n const trimmed = value.trim();\n if (!trimmed) return undefined;\n try {\n Intl.DateTimeFormat(undefined, { timeZone: trimmed });\n return trimmed;\n } catch {\n return undefined;\n }\n}\n\nexport function formatDateInTimeZone(date: Date, timeZone: string): string {\n const parts = new Intl.DateTimeFormat(\"en-US\", {\n timeZone,\n year: \"numeric\",\n month: \"2-digit\",\n day: \"2-digit\",\n }).formatToParts(date);\n const get = (type: string): string => parts.find((part) => part.type === type)?.value ?? \"\";\n return `${get(\"year\")}-${get(\"month\")}-${get(\"day\")}`;\n}\n\nexport function utcDateKey(date: Date): string {\n return date.toISOString().slice(0, 10);\n}\n\nexport function utcDateKeysAround(date: Date): string[] {\n const dayMs = 86_400_000;\n const keys = [\n utcDateKey(new Date(date.getTime() - dayMs)),\n utcDateKey(date),\n utcDateKey(new Date(date.getTime() + dayMs)),\n ];\n return keys.filter((value, index, array) => array.indexOf(value) === index);\n}\n\nexport function utcDateKeysForLocalDay(date: Date, timeZone: string): string[] {\n const targetLocalDate = formatDateInTimeZone(date, timeZone);\n const keys = new Set<string>();\n const hourMs = 3_600_000;\n const scanStart = date.getTime() - 48 * hourMs;\n const scanEnd = date.getTime() + 48 * hourMs;\n for (let ms = scanStart; ms <= scanEnd; ms += hourMs) {\n const candidate = new Date(ms);\n if (formatDateInTimeZone(candidate, timeZone) === targetLocalDate) {\n keys.add(utcDateKey(candidate));\n }\n }\n return keys.size > 0 ? [...keys].sort() : utcDateKeysAround(date);\n}\n\nexport function parseFiniteDate(value: unknown): Date | null {\n if (typeof value !== \"string\" || value.trim().length === 0) return null;\n const parsed = new Date(value);\n return Number.isFinite(parsed.getTime()) ? parsed : null;\n}\n\nexport function filterHourlySummaryMarkdownForLocalDay(\n raw: string,\n utcDate: string,\n timeZone: string,\n targetLocalDate: string,\n): string | null {\n const hourHeaderPattern = /^## ([01]\\d|2[0-3]):00[ \\t]*$/gm;\n const matches = Array.from(raw.matchAll(hourHeaderPattern));\n if (matches.length === 0) return null;\n\n const firstSectionStart = matches[0]?.index ?? 0;\n const preamble = raw.slice(0, firstSectionStart).trim();\n const sections: string[] = [];\n for (let index = 0; index < matches.length; index += 1) {\n const match = matches[index];\n const hour = match[1];\n if (!hour) continue;\n const sectionTimestamp = parseFiniteDate(`${utcDate}T${hour}:00:00.000Z`);\n if (\n !sectionTimestamp ||\n formatDateInTimeZone(sectionTimestamp, timeZone) !== targetLocalDate\n ) {\n continue;\n }\n const sectionStart = match.index ?? 0;\n const sectionEnd = matches[index + 1]?.index ?? raw.length;\n const section = raw.slice(sectionStart, sectionEnd).trim();\n if (section.length > 0) sections.push(section);\n }\n\n if (sections.length === 0) return null;\n return [preamble, ...sections]\n .filter((section) => section.length > 0)\n .join(\"\\n\\n\");\n}\n\nexport type SearchCollectionState = \"present\" | \"missing\" | \"unknown\" | \"skipped\";\n\nexport function qmdStartupCollectionCheckTimeoutMs(): number {\n const raw =\n process.env.REMNIC_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS ??\n process.env.ENGRAM_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;\n if (raw === undefined) return DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;\n const parsed = Number(raw);\n return Number.isFinite(parsed) && parsed >= 1_000\n ? Math.floor(parsed)\n : DEFAULT_QMD_STARTUP_COLLECTION_CHECK_TIMEOUT_MS;\n}\n\nexport async function qmdStartupCollectionCheckWithTimeout(\n promise: Promise<SearchCollectionState>,\n controller: AbortController,\n label: string,\n): Promise<SearchCollectionState> {\n const timeoutMs = qmdStartupCollectionCheckTimeoutMs();\n let timer: NodeJS.Timeout | undefined;\n let settled = false;\n\n const timeoutPromise = new Promise<SearchCollectionState>((resolve) => {\n timer = setTimeout(() => {\n if (settled) return;\n controller.abort();\n log.warn(\n `QMD startup collection check for ${label} timed out after ${timeoutMs}ms; keeping search enabled fail-open`,\n );\n resolve(\"unknown\");\n }, timeoutMs);\n timer.unref?.();\n });\n\n const checkedPromise = promise\n .catch((err): SearchCollectionState => {\n log.warn(\n `QMD startup collection check for ${label} failed; keeping search enabled fail-open: ${err}`,\n );\n return \"unknown\";\n })\n .finally(() => {\n settled = true;\n if (timer) clearTimeout(timer);\n });\n\n return await Promise.race([checkedPromise, timeoutPromise]);\n}\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 sourceValidAtMs(turn: BufferTurn): number | null {\n if (typeof turn.sourceValidAt !== \"string\") return null;\n return parseFlexibleIsoTimestamp(turn.sourceValidAt.trim());\n}\n\nexport const SOURCE_VALID_AT_CONTEXT_TURNS = 2;\n\nexport function sourceValidAtSliceKey(turn: BufferTurn, index: number): string {\n const validAtMs = sourceValidAtMs(turn);\n return validAtMs === null ? `unknown:${index}` : String(validAtMs);\n}\n\nexport function asExtractionContextTurn(turn: BufferTurn): BufferTurn {\n return { ...turn, extractionContextOnly: true };\n}\n\nexport function asExtractionTargetTurn(turn: BufferTurn): BufferTurn {\n const { extractionContextOnly: _contextOnly, ...targetTurn } = turn;\n return targetTurn;\n}\n\nexport function sourceValidAtContextTurns(\n turns: readonly BufferTurn[],\n targetStart: number,\n targetEnd: number,\n targetValidAtMs: number | null,\n): BufferTurn[] {\n if (targetValidAtMs === null) return [];\n return turns\n .flatMap((turn, index) => {\n if (index >= targetStart && index < targetEnd) return [];\n const contextValidAtMs = sourceValidAtMs(turn);\n if (contextValidAtMs === null || contextValidAtMs > targetValidAtMs) {\n return [];\n }\n return [{ turn, index, validAtMs: contextValidAtMs }];\n })\n .sort((a, b) => {\n if (a.validAtMs < b.validAtMs) return -1;\n if (a.validAtMs > b.validAtMs) return 1;\n if (a.index === b.index) return 0;\n return a.index < b.index ? -1 : 1;\n })\n .slice(-SOURCE_VALID_AT_CONTEXT_TURNS)\n .map(({ turn }) => asExtractionContextTurn(turn));\n}\n\nexport function targetSourceValidAtSortMs(turns: readonly BufferTurn[]): number {\n let latestMs: number | null = null;\n for (const turn of turns) {\n if (turn.extractionContextOnly === true) continue;\n const validAtMs = sourceValidAtMs(turn);\n if (validAtMs === null) continue;\n if (latestMs === null || validAtMs > latestMs) {\n latestMs = validAtMs;\n }\n }\n return latestMs ?? Number.POSITIVE_INFINITY;\n}\n\nexport function sortSourceValidAtSlicesChronologically(\n slices: BufferTurn[][],\n): BufferTurn[][] {\n return slices\n .map((turns, order) => ({\n turns,\n order,\n targetValidAtMs: targetSourceValidAtSortMs(turns),\n }))\n .sort((a, b) => {\n if (a.targetValidAtMs < b.targetValidAtMs) return -1;\n if (a.targetValidAtMs > b.targetValidAtMs) return 1;\n if (a.order === b.order) return 0;\n return a.order < b.order ? -1 : 1;\n })\n .map((slice) => slice.turns);\n}\n\nexport function splitTurnsBySourceValidAt(\n turns: readonly BufferTurn[],\n options: { includeContext?: boolean } = {},\n): BufferTurn[][] {\n if (turns.length === 0) return [];\n if (!turns.some((turn) => sourceValidAtMs(turn) !== null)) {\n return [[...turns]];\n }\n\n const slices: BufferTurn[][] = [];\n let start = 0;\n while (start < turns.length) {\n const targetValidAtMs = sourceValidAtMs(turns[start]);\n const activeKey = sourceValidAtSliceKey(turns[start], start);\n let end = start + 1;\n while (\n end < turns.length &&\n sourceValidAtSliceKey(turns[end], end) === activeKey\n ) {\n end += 1;\n }\n\n const contextTurns =\n options.includeContext === false\n ? []\n : sourceValidAtContextTurns(turns, start, end, targetValidAtMs);\n slices.push([\n ...contextTurns,\n ...turns.slice(start, end).map(asExtractionTargetTurn),\n ]);\n start = end;\n }\n return sortSourceValidAtSlicesChronologically(slices);\n}\n\nexport function isArtifactMemoryPath(filePath: string): boolean {\n return /(?:^|[\\\\/])artifacts(?:[\\\\/]|$)/i.test(filePath);\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 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\nexport function applyQueryAwareCandidateFilter(\n candidates: QmdSearchResult[],\n candidatePaths: Set<string> | null,\n): QmdSearchResult[] {\n if (!candidatePaths) return candidates;\n if (candidatePaths.size === 0) return [];\n const filtered = candidates.filter((candidate) =>\n candidatePaths.has(candidate.path),\n );\n return filtered.length > 0 ? filtered : candidates;\n}\n\nexport function 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\nexport function 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 interface RecallModeGraphOptions {\n plannerEnabled: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n graphExpandedIntentEnabled?: boolean;\n prompt: string;\n}\n\n/**\n * Apply the graph-mode overlay + gating to a planner-produced mode.\n *\n * Shared by the heuristic ({@link resolveRecallModeDecision}) and LLM\n * ({@link resolveRecallModeDecisionAsync}) paths so graph promotion and the\n * \"graph disabled → fall back to full\" gating behave identically regardless of\n * which planner produced `plannedModeRaw` (gotcha #39).\n */\nexport function finalizeRecallModeDecision(\n plannedModeRaw: RecallPlanMode,\n options: RecallModeGraphOptions,\n): RecallModeDecision {\n let plannedMode: RecallPlanMode = plannedModeRaw;\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 resolveRecallModeDecision(options: RecallModeGraphOptions): RecallModeDecision {\n const plannedMode: RecallPlanMode = options.plannerEnabled\n ? planRecallMode(options.prompt)\n : \"full\";\n return finalizeRecallModeDecision(plannedMode, options);\n}\n\n/**\n * Async recall-mode decision with optional LLM-based planning (issue #1367 /\n * Option C). Falls back to the heuristic decision when the LLM planner is\n * disabled, in shadow mode, or unavailable/failed — so this is always safe to\n * await on the recall hot path. Provider-agnostic: the LLM call routes through\n * the gateway/fallback chain.\n *\n * `recallPlannerEnabled === false` keeps the legacy \"always full\" behavior and\n * skips the LLM entirely (the planner as a whole is off).\n */\nexport async function resolveRecallModeDecisionAsync(\n options: RecallModeGraphOptions & {\n config: PluginConfig;\n /**\n * Recall-operation capability gates (issue #1523). REQUIRED: the recall\n * orchestrator always passes a resolved set — the LLM planner gate reads\n * `caps.recallPlannerLlm`, never re-derives from config.\n */\n caps: CapabilitySet;\n hints?: string[];\n llm?: FallbackLlmClient;\n signal?: AbortSignal;\n },\n): Promise<RecallModeDecision> {\n const heuristicDecision = resolveRecallModeDecision(options);\n\n // Planner globally off, or LLM planning not opted into → heuristic only.\n // Read the resolved capability (issue #1523) — never re-derive from config.\n const plannerLlmEnabled = options.caps.recallPlannerLlm;\n if (!options.plannerEnabled || !plannerLlmEnabled) {\n return heuristicDecision;\n }\n\n const { planRecallModeLLM } = await import(\"../recall-planner-llm.js\");\n const planned = await planRecallModeLLM(\n options.prompt,\n options.hints,\n options.config,\n options.caps,\n options.llm,\n options.signal,\n );\n\n // Shadow mode: record what the LLM would have chosen but keep the heuristic\n // effective decision (safe rollout / comparison — gotcha #30).\n if (options.config.recallPlannerShadowMode) {\n return {\n ...heuristicDecision,\n plannerSource: planned.source,\n plannerReason: `shadow:${planned.reason}`,\n plannerLatencyMs: planned.latencyMs,\n plannerFallbackUsed: planned.fallbackUsed,\n plannerModelUsed: planned.modelUsed,\n plannerHeuristicMode: planned.heuristicMode,\n shadowLlmMode: planned.mode,\n };\n }\n\n const llmDecision = finalizeRecallModeDecision(planned.mode, options);\n return {\n ...llmDecision,\n plannerSource: planned.source,\n plannerReason: planned.reason,\n plannerLatencyMs: planned.latencyMs,\n plannerFallbackUsed: planned.fallbackUsed,\n plannerModelUsed: planned.modelUsed,\n plannerHeuristicMode: planned.heuristicMode,\n };\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 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\nexport function 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\nexport function 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\nexport function 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\nexport function 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 // #1635 (defensive): skip pending_review ids from legacy episode sets.\n const pendingReviewIds = new Set<string>(\n (options.allMemsForGraph ?? [])\n .filter((m) => m.frontmatter.status === \"pending_review\" && m.frontmatter.id)\n .map((m) => m.frontmatter.id as string),\n );\n\n return options.threadEpisodeIds\n .filter((id) => id !== options.currentMemoryId)\n .filter((id) => !pendingReviewIds.has(id))\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. Routing goes through\n // the shared categoryDirName() chokepoint (utils/category-dir.ts) so\n // every category — decisions/, preferences/, reasoning-traces/, ... —\n // resolves to the same dir the writer used; otherwise graph edges point\n // at the wrong subtree and graph expansion silently drops those nodes\n // when readMemoryByPath cannot resolve them (issue #564 PR 3 / #1546).\n const subtree = categoryDirName(options.category);\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","/**\n * Consolidation-run coordinator — extracted from the orchestrator\n * (issue #1526, seam 17).\n *\n * Owns the full consolidation maintenance pass:\n * - `run()` — the main consolidation cycle (LLM merge/invalidate/update\n * → entity-file merge → commitment cleanup → TTL cleanup → lifecycle\n * policy → compression guideline learning → tier migration → fact\n * archival → semantic consolidation → identity consolidation → profile\n * consolidation → summarization → topic extraction → TMT rebuild)\n * - `recordScheduledDreamsPhaseRun` — dream-phase ledger recording\n * - `runFactArchival` / `runSummarization` / `runTopicExtraction` —\n * thin delegates to LifecyclePolicyCoordinator\n * - `runCompressionGuidelineLearningPass` — thin delegate to\n * CompressionGuidelineCoordinator\n *\n * The orchestrator constructs one instance and delegates the consolidation\n * pass to it. Everything that must stay orchestrator-owned (access tracking,\n * embedding index, entity synthesis, tier migration, semantic consolidation,\n * identity consolidation, recall section config, fast LLM) arrives as\n * injectable delegates.\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating method so existing call sites\n * (runConsolidationNow, maintenance scheduler) and tests continue to work.\n */\n\nimport path from \"node:path\";\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport { log } from \"../logger.js\";\nimport { applyCommitmentLedgerLifecycle } from \"../commitment-ledger.js\";\nimport { recordDreamsPhaseRun } from \"../maintenance/dreams-ledger.js\";\nimport { clearIndexes, deindexMemory, indexMemoriesBatch, indexesExist } from \"../temporal-index.js\";\nimport { isActiveMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport {\n resolveConsolidationCapabilities,\n resolveCreationMemoryCapabilities,\n resolveIndexingCapabilities,\n resolveMemoryLifecycleCapabilities,\n resolvePipelineProcessingCapabilities,\n resolvePresentationCapabilities,\n resolveRecallEnhancementCapabilities,\n type MemoryLifecycleCapabilitySet,\n} from \"../capabilities.js\";\nimport type { LifecyclePolicyCoordinator } from \"./lifecycle-policy-coordinator.js\";\nimport type { CompressionGuidelineCoordinator } from \"./compression-guideline-coordinator.js\";\nimport type { SemanticConsolidationCoordinator } from \"./semantic-consolidation-coordinator.js\";\nimport type { EntitySynthesisCoordinator } from \"./entity-synthesis-coordinator.js\";\nimport type { RecallSectionCoordinator } from \"./recall-section-coordinator.js\";\nimport type { TierMigrationCoordinator } from \"./tier-migration-coordinator.js\";\nimport type { StorageManager } from \"../index.js\";\nimport type { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport type { ExtractionEngine } from \"../extraction.js\";\nimport type { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport type { TmtBuilder } from \"../tmt.js\";\nimport type {\n ConsolidationObservation,\n MemoryFile,\n PluginConfig,\n RecallSectionConfig,\n} from \"../types.js\";\n\n/** Dependencies injected by the orchestrator. Stable references or live\n * accessors — lazy getters for mutable fields tests reassign\n * post-construction (storage, extraction, storageRouter). */\nexport interface ConsolidationRunCoordinatorDeps {\n config: PluginConfig;\n getStorage: () => StorageManager;\n getStorageRouter: () => NamespaceStorageRouter;\n getExtraction: () => ExtractionEngine;\n embeddingFallback: EmbeddingFallback;\n tmtBuilder: TmtBuilder;\n consolidationObservers: Set<\n (observation: ConsolidationObservation) => Promise<void> | void\n >;\n getAccessTrackingBuffer: () => Map<\n string,\n { count: number; lastAccessed: string }\n >;\n\n lifecyclePolicyCoordinator: LifecyclePolicyCoordinator;\n compressionGuidelineCoordinator: CompressionGuidelineCoordinator;\n semanticConsolidationCoordinator: SemanticConsolidationCoordinator;\n entitySynthesisCoordinator: EntitySynthesisCoordinator;\n recallSectionCoordinator: RecallSectionCoordinator;\n tierMigrationCoordinator: TierMigrationCoordinator;\n\n flushAccessTracking: () => Promise<void>;\n indexPersistedMemory: (storage: StorageManager, memoryId: string) => Promise<void>;\n autoConsolidateIdentity: () => Promise<void>;\n fastChatCompletion: (\n messages: Array<{ role: string; content: string }>,\n options: {\n temperature?: number;\n maxTokens?: number;\n timeoutMs?: number;\n operation?: string;\n priority?: \"background\" | \"recall-critical\";\n },\n ) => Promise<{ content: string } | null>;\n}\n\nexport class ConsolidationRunCoordinator {\n constructor(private readonly deps: ConsolidationRunCoordinatorDeps) {}\n\n async run(): Promise<{\n memoriesProcessed: number;\n merged: number;\n invalidated: number;\n }> {\n const config = this.deps.config;\n const storage = this.deps.getStorage();\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(config);\n log.info(\"running consolidation pass\");\n let merged = 0;\n let invalidated = 0;\n // Tracks whether any consolidation memory-item action (UPDATE / MERGE /\n // INVALIDATE) durably rewrote memory state. A consolidation pass that only\n // mutates memory items (no profile/entity updates) still changes the default\n // namespace's data, so its catalog `lastWriteAt` must refresh too (NIBOi).\n let memoryItemMutated = false;\n\n // Flush access tracking buffer first\n if (this.deps.getAccessTrackingBuffer().size > 0) {\n await this.deps.flushAccessTracking();\n }\n\n let allMemories = await 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 storage.readProfile();\n const result = await this.deps.getExtraction().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 = resolveIndexingCapabilities(config).queryAwareIndexing\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 = resolveIndexingCapabilities(config).queryAwareIndexing\n ? (memoryLookup?.get(item.existingId) ?? null)\n : null;\n if (await storage.invalidateMemory(item.existingId)) {\n invalidated += 1;\n memoryItemMutated = true;\n await this.deps.embeddingFallback.removeFromIndex(item.existingId);\n if (toInvalidate?.path && toInvalidate.frontmatter?.created) {\n deindexMemory(\n 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 storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n lineage: [item.existingId],\n },\n );\n memoryItemMutated = true;\n await this.deps.indexPersistedMemory(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 storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n supersedes: item.mergeWith,\n lineage: [item.existingId, item.mergeWith],\n },\n );\n memoryItemMutated = true;\n await this.deps.indexPersistedMemory(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 = resolveIndexingCapabilities(config).queryAwareIndexing\n ? (memoryLookup?.get(item.mergeWith) ?? null)\n : null;\n if (await storage.invalidateMemory(item.mergeWith)) {\n invalidated += 1;\n merged += 1;\n await this.deps.embeddingFallback.removeFromIndex(item.mergeWith);\n if (\n toMergeInvalidate?.path &&\n toMergeInvalidate.frontmatter?.created\n ) {\n deindexMemory(\n 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 storage.appendToProfile(result.profileUpdates);\n }\n\n for (const entity of result.entityUpdates) {\n const safeFacts = Array.isArray(entity.facts)\n ? entity.facts.filter((f): f is string => typeof f === \"string\")\n : [];\n await storage.writeEntity(entity.name, entity.type, safeFacts, {\n source: \"consolidation\",\n structuredSections: Array.isArray(entity.structuredSections)\n ? entity.structuredSections\n : undefined,\n });\n }\n\n // Catalog write touch accounting (issue #1499 sweep): consolidation persists\n // durable mutations directly to the default-namespace storage, bypassing\n // the extraction write path. We do NOT touch here — later maintenance steps in\n // this same function (entity-file merges, expired-commitment / TTL cleanup,\n // fact archival) can ALSO mutate the namespace on a run with no LLM outputs\n // (NIjwl). So we accumulate every durable mutation into `memoryItemMutated` and\n // record ONE consolidated touch AFTER all mutation-producing steps complete,\n // just before returning (rule #25: touch after the write commits). LLM\n // profile/entity updates and memory-item actions (UPDATE / MERGE / INVALIDATE)\n // count here (NIBOi).\n if (result.profileUpdates.length > 0 || result.entityUpdates.length > 0) {\n memoryItemMutated = true;\n }\n\n // Merge fragmented entity files\n const entitiesMerged = await storage.mergeFragmentedEntities();\n if (entitiesMerged > 0) {\n memoryItemMutated = true;\n log.info(`merged ${entitiesMerged} fragmented entity files`);\n }\n\n if (resolvePresentationCapabilities(config).entitySummary) {\n try {\n const synthesized = await this.deps.entitySynthesisCoordinator.processQueue(\n config.defaultNamespace,\n 5,\n );\n if (synthesized > 0) {\n // Entity synthesis rewrites entity files — a durable namespace mutation,\n // so record it for the catalog touch even when it is the only change in\n // the pass (codex). Otherwise lastWriteAt goes stale.\n memoryItemMutated = true;\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 storage.cleanExpiredCommitments(\n config.commitmentDecayDays,\n );\n if (deletedCommitments.length > 0) {\n memoryItemMutated = true;\n log.info(`cleaned ${deletedCommitments.length} expired commitments`);\n if (resolveIndexingCapabilities(config).queryAwareIndexing) {\n for (const m of deletedCommitments) {\n deindexMemory(\n config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n }\n }\n\n if (\n resolveCreationMemoryCapabilities(config).creationMemory &&\n resolveCreationMemoryCapabilities(config).commitmentLedger &&\n resolveCreationMemoryCapabilities(config).commitmentLifecycle\n ) {\n try {\n const lifecycle = await applyCommitmentLedgerLifecycle({\n memoryDir: config.memoryDir,\n commitmentLedgerDir: config.commitmentLedgerDir,\n enabled: true,\n decayDays: config.commitmentDecayDays,\n });\n if (\n lifecycle.transitionedToExpired.length > 0 ||\n lifecycle.deletedResolved.length > 0\n ) {\n memoryItemMutated = true;\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 storage.cleanExpiredTTL();\n if (deletedTTL.length > 0) {\n memoryItemMutated = true;\n log.info(`cleaned ${deletedTTL.length} TTL-expired memories`);\n if (resolveIndexingCapabilities(config).queryAwareIndexing) {\n for (const m of deletedTTL) {\n deindexMemory(\n 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 (lifecycleCaps.lifecyclePolicy) {\n try {\n const lightSleepStartedAt = new Date().toISOString();\n const lifecycleCorpus = await storage.readAllMemories();\n // Lifecycle frontmatter writes count as durable mutations for the catalog\n // touch below (codex NR-tS), even when no other consolidation step set\n // memoryItemMutated.\n if ((await this.deps.lifecyclePolicyCoordinator.runLifecyclePolicyPass(lifecycleCorpus, storage)) > 0) {\n memoryItemMutated = true;\n }\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.deps.compressionGuidelineCoordinator.runCompressionGuidelineLearningPass();\n\n try {\n const deepSleepStartedAt = new Date().toISOString();\n // Tier migrations move/rewrite memory files; count them as durable\n // mutations for the catalog touch below (codex NThSW).\n const tierMigration = await this.deps.tierMigrationCoordinator.runCycle(storage, \"maintenance\");\n if (tierMigration.migrated > 0) memoryItemMutated = true;\n allMemories = await storage.readAllMemories();\n\n // Fact archival pass (v6.0) — move old, low-importance, rarely-accessed facts to archive/\n if (resolveRecallEnhancementCapabilities(config).factArchival) {\n const archived = await this.deps.lifecyclePolicyCoordinator.runFactArchival(allMemories);\n if (archived > 0) {\n memoryItemMutated = true;\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 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 (resolveConsolidationCapabilities(config).semanticConsolidation) {\n try {\n const stateFilePath = path.join(\n 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 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.deps.semanticConsolidationCoordinator.runSemanticConsolidation();\n let remItemsProcessed = allMemories.length;\n try {\n allMemories = await 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(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 (resolveRecallEnhancementCapabilities(config).identity) {\n await this.deps.autoConsolidateIdentity();\n }\n\n // Auto-consolidate profile.md if it exceeds max lines\n const profileSection = this.deps.recallSectionCoordinator.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 storage.profileNeedsConsolidation(\n profileConsolidationTriggerLines,\n )\n ) {\n log.info(\"profile.md exceeds max lines — running smart consolidation\");\n const currentProfile = await storage.readProfile();\n if (currentProfile) {\n const profileResult = await this.deps.getExtraction().consolidateProfile(\n currentProfile,\n profileConsolidationTargetLines,\n );\n if (profileResult) {\n await storage.writeProfile(profileResult.consolidatedProfile);\n // Profile consolidation rewrites profile.md — a durable namespace\n // mutation; record it for the catalog touch even when it is the only\n // change in the pass (codex). Otherwise lastWriteAt goes stale.\n memoryItemMutated = true;\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 (resolvePipelineProcessingCapabilities(config).summarization) {\n await this.deps.lifecyclePolicyCoordinator.runSummarization(allMemories);\n }\n\n // Topic Extraction (Phase 4B)\n if (resolvePipelineProcessingCapabilities(config).topicExtraction) {\n await this.deps.lifecyclePolicyCoordinator.runTopicExtraction(allMemories);\n }\n\n const meta = await storage.loadMeta();\n meta.lastConsolidationAt = new Date().toISOString();\n await storage.saveMeta(meta);\n\n // Temporal Memory Tree (v8.2) — rebuild nodes from all memories, fail-open\n if (lifecycleCaps.temporalMemoryTree) {\n try {\n const tmtEntries = allMemories\n .filter(\n (m) =>\n m.frontmatter.status !== \"superseded\" && m.frontmatter.status !== \"archived\" &&\n m.frontmatter.status !== \"forgotten\" && m.frontmatter.status !== \"pending_review\", // #1576: unfaithful queue items must not feed TMT clusters\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.deps.tmtBuilder.maybeRebuildNodes(\n tmtEntries,\n async (texts, level) => {\n const prompt = `You are a memory archivist. Summarize the following ${level}-level memories into 3\\u20135 sentences, preserving key facts, decisions, and preferences.\\n\\n${texts.map((t, i) => `[${i + 1}] ${t}`).join(\"\\n\\n\")}`;\n const response = await this.deps.fastChatCompletion(\n [\n {\n role: \"system\",\n content:\n \"Respond with a 3\\u20135 sentence narrative summary. No JSON, just plain prose.\",\n },\n { role: \"user\", content: prompt },\n ],\n {\n temperature: 0.3,\n maxTokens: 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.deps.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.deps.consolidationObservers) {\n try {\n await observer(observation);\n } catch (err) {\n log.warn(`consolidation observer failed (ignored): ${err}`);\n }\n }\n }\n\n // Consolidated catalog write touch — belt-and-suspenders for cleanup-only\n // passes that mutate the store via delete-only paths (entity merges, TTL\n // cleanup) without triggering the storage chokepoint's post-write hook.\n // Gated on memoryItemMutated (set by every durable mutation including cleanup-only passes)\n // Best-effort and failure-tolerant.\n if (memoryItemMutated) {\n this.deps.getStorageRouter().recordWrite(config.defaultNamespace, storage.dir);\n }\n\n log.info(\"consolidation complete\");\n return { memoriesProcessed: allMemories.length, merged, invalidated };\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 await recordDreamsPhaseRun({\n memoryDir: this.deps.getStorage().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}\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 must throw when the embedding backend\n * is unavailable or the provider call fails, and return an empty array only\n * when a reachable backend successfully reports no hits. The decision function\n * fail-opens on thrown lookup errors while preserving a distinct\n * \"backend_unavailable\" reason for telemetry.\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\nconst DEFAULT_SEMANTIC_THRESHOLD = 0.92;\nconst DEFAULT_SEMANTIC_CANDIDATES = 5;\n\nfunction normalizeSemanticThreshold(value: number): number {\n return Number.isFinite(value)\n ? Math.min(1, Math.max(0, value))\n : DEFAULT_SEMANTIC_THRESHOLD;\n}\n\nfunction normalizeSemanticCandidates(value: number): number {\n if (!Number.isFinite(value) || value < 0) {\n return DEFAULT_SEMANTIC_CANDIDATES;\n }\n const normalized = Math.floor(value);\n return value > 0 && normalized === 0 ? 1 : normalized;\n}\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 const threshold = normalizeSemanticThreshold(options.threshold);\n const candidates = normalizeSemanticCandidates(options.candidates);\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 (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 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 (\n !hit ||\n typeof hit.id !== \"string\" ||\n hit.id.trim().length === 0 ||\n typeof hit.score !== \"number\" ||\n !Number.isFinite(hit.score)\n ) {\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 >= 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 * Extraction-persist coordinator — extracted from the orchestrator\n * (issue #1526, seam 16).\n *\n * Owns the `persistExtraction` pipeline: the ~2.5k-LOC method that turns\n * an ExtractionResult into durable memory writes. Hosts:\n * - pre-judge multi-namespace redaction gate\n * - extraction-judge gating\n * - scope routing\n * - tombstone postWriteGuard\n * - dedup + bitemporal backfill (3 paths)\n * - contradiction auto-resolve deferral\n * - promotion paths\n * - post-persist content-hash indexing\n * - catalog write-recording\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating method so existing call sites and\n * tests continue to work.\n */\n\nimport path from \"node:path\";\nimport {\n StorageManager,\n ContentHashIndex,\n normalizeAttributePairs,\n} from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport { chunkContent, type ChunkingConfig } from \"../chunking.js\";\nimport { semanticChunkContent, type SemanticChunkResult } from \"../semantic-chunking.js\";\nimport { isAboveImportanceThreshold, scoreImportance } from \"../importance.js\";\nimport { sanitizeMemoryContent } from \"../sanitize.js\";\nimport {\n resolveGraphConstructionCapabilities,\n resolveMemoryLifecycleCapabilities,\n resolvePipelineProcessingCapabilities,\n resolvePresentationCapabilities,\n resolveNamespaceCapabilities,\n resolveRecallEnhancementCapabilities,\n resolveConversationContextCapabilities,\n type GraphConstructionCapabilitySet,\n type MemoryLifecycleCapabilitySet,\n} from \"../capabilities.js\";\nimport {\n applyTemporalSupersession,\n normalizeSupersessionKey,\n} from \"../temporal-supersession.js\";\nimport { pickFactEventTimeAnchor, resolveFactEventTime } from \"../event-time.js\";\nimport {\n judgeFactDurability,\n getVerdictKind,\n validateProcedureExtraction,\n type JudgeVerdict,\n type JudgeCandidate,\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 {\n applyFaithfulnessVerdict,\n runFaithfulnessGateBatch,\n type FaithfulnessGateCounters,\n} from \"../extraction-faithfulness.js\";\nimport {\n contentMatchesRedactionRules,\n loadRedactionRules,\n type CompiledRedactionRule,\n} from \"../extraction-redaction-rules.js\";\nimport {\n attachCitation,\n type CitationContext,\n hasCitationForTemplate,\n stripCitationForTemplate,\n} from \"../source-attribution.js\";\nimport { classifyMemoryKind } from \"../himem.js\";\nimport {\n buildBehaviorSignalsForMemory,\n dedupeBehaviorSignalsByMemoryAndHash,\n} from \"../behavior-signals.js\";\nimport { buildProcedurePersistBody } from \"../procedural/procedure-types.js\";\nimport { LocalLlmClient } from \"../local-llm.js\";\nimport {\n FallbackLlmClient,\n fallbackLlmRuntimeContextFromConfig,\n} from \"../fallback-llm.js\";\nimport { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport { decideSemanticDedup, type SemanticDedupDecision, type SemanticDedupHit } from \"../dedup/semantic.js\";\nimport { selectRouteRule, type RouteRule, type RoutingEngineOptions } from \"../routing/engine.js\";\nimport { ThreadingManager } from \"../threading.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport type { SearchBackend } from \"../search/port.js\";\nimport { inferIntentFromText } from \"../intent.js\";\nimport type {\n BehaviorSignalEvent,\n ExtractionResult,\n MemoryFile,\n MemoryFrontmatter,\n MemoryLink,\n PluginConfig,\n ProvenanceSource,\n} from \"../types.js\";\nimport { confidenceTier } from \"../types.js\";\nimport type { ResolvedScopeProfilePlan } from \"../namespaces/scope-profiles.js\";\nimport {\n buildMemoryPathById,\n appendMemoryToGraphContext,\n resolvePersistedMemoryRelativePath,\n} from \"../orchestrator.js\";\n\nexport interface ExtractionPersistDeps {\n config: PluginConfig;\n getStorageRouter: () => NamespaceStorageRouter;\n getThreading: () => ThreadingManager;\n getLocalLlm: () => LocalLlmClient;\n getQmd: () => SearchBackend;\n getJudgeVerdictCache: () => Map<string, JudgeVerdict>;\n getJudgeDeferCounts: () => Map<string, number>;\n getFaithfulnessCounters: () => FaithfulnessGateCounters;\n getEmbeddingFallback: () => EmbeddingFallback;\n setLastPersistExtractionDeferredCount: (value: number) => void;\n setLastPersistExtractionPendingReviewIds: (ids: string[]) => void;\n addContentHashDedup: (targetStorage: StorageManager, content: string) => Promise<void>;\n hasContentHashDedup: (targetStorage: StorageManager, content: string) => Promise<boolean>;\n backfillTemporalBoundsOnDedupHit: (\n targetStorage: StorageManager,\n dedupContent: string,\n bounds: {\n invalidAt?: string;\n validFrom?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n },\n entityRef?: string,\n ) => Promise<void>;\n saveContentHashIndexes: () => Promise<void>;\n artifactTypeForCategory: (\n category: string,\n ) =>\n | \"decision\"\n | \"constraint\"\n | \"todo\"\n | \"definition\"\n | \"commitment\"\n | \"correction\"\n | \"fact\";\n loadRoutingRules: () => Promise<RouteRule[]>;\n routeEngineOptions: () => RoutingEngineOptions;\n semanticDedupLookup: (\n content: string,\n limit: number,\n targetStorage: StorageManager,\n ) => Promise<SemanticDedupHit[]>;\n 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 applyDeferredContradictionResolve: (\n contradiction: {\n supersededId: string;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n } | null | undefined,\n storage: StorageManager,\n newMemoryId: string,\n postWriteGuard: boolean,\n ) => Promise<void>;\n suggestLinksForMemory: (\n content: string,\n category: string,\n namespaceScope: string,\n ) => Promise<MemoryLink[]>;\n storageDirNamespace: (storageDir: string) => string;\n indexPersistedMemory: (storage: StorageManager, memoryId: string) => Promise<void>;\n buildGraphEdge: (\n storage: StorageManager,\n memoryRelPath: string,\n entityRef: string | undefined,\n memoryId: string,\n factContent: string,\n allMemsForGraph: MemoryFile[] | null | undefined,\n memoryPathById: Map<string, string>,\n threadIdForEdge: string | undefined,\n threadEpisodeIdsForGraph: string[] | undefined,\n fallbackCausalPredecessor: string | undefined,\n graphCaps?: GraphConstructionCapabilitySet,\n ) => Promise<void>;\n updateTemporalTagIndexes: (\n storage: StorageManager,\n persistedIds: string[],\n ) => Promise<void>;\n}\n\nexport class ExtractionPersistCoordinator {\n constructor(\n private readonly deps: ExtractionPersistDeps,\n ) {}\n\n private get config(): PluginConfig {\n return this.deps.config;\n }\n\n async persistExtraction(\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: { sessionKey?: string; principal?: string; validAt?: string },\n baseNamespace?: string,\n scopeProfileWritePlan?: ResolvedScopeProfilePlan | null,\n /** Verbatim source turn text the facts were extracted from (faithfulness gate #1576). */\n sourceText?: string,\n graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.deps.config),\n lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.deps.config),\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 = resolvePipelineProcessingCapabilities(this.deps.config).inlineSourceAttribution === true;\n const citationTemplate = this.deps.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 supersessionOrderingAt = (validAt?: string): string =>\n validAt && validAt.length > 0 ? validAt : new Date().toISOString();\n // #1635: pending_review persisted ids, excluded from the thread episode set below.\n const pendingReviewPersistedIds: 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: {\n includeReturnedIds?: boolean;\n /** #1635: keep this id out of the persisted thread episode set. */\n pendingReview?: boolean;\n } = {},\n ): void => {\n if (options.includeReturnedIds !== false) {\n persistedIds.push(id);\n }\n if (options.pendingReview) {\n pendingReviewPersistedIds.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 // #1669: per-namespace redaction-rule cache for this persist pass. A\n // `never_store` / redaction_rule correction persists patterns under each\n // namespace's state/corrections/redaction-rules/ dir; we consult them\n // before a fact reaches the storage write chokepoint so matching content\n // is withheld entirely rather than landing as pending_review. Cached per\n // dir so a multi-fact batch over one namespace reads the dir once.\n let redactionGatedCount = 0;\n const redactionRulesByDir = new Map<string, CompiledRedactionRule[]>();\n const redactionRulesFor = async (...dirs: string[]): Promise<CompiledRedactionRule[]> => {\n const out: CompiledRedactionRule[] = [];\n for (const d of dirs) {\n let r = redactionRulesByDir.get(d);\n if (!r) { r = await loadRedactionRules(d); redactionRulesByDir.set(d, r); }\n out.push(...r);\n }\n return out;\n };\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 sharedProfileLayer = scopeProfileWritePlan?.layers.find(\n (layer) =>\n layer.id === \"serverShared\" &&\n layer.namespace === this.deps.config.sharedNamespace,\n );\n const sharedPromotionTarget = scopeProfileWritePlan?.promotionTargets.find(\n (target) =>\n target.target === \"serverShared\" &&\n target.namespace === this.deps.config.sharedNamespace,\n );\n const profileAllowsSharedWrites =\n !scopeProfileWritePlan ||\n Boolean(\n scopeProfileWritePlan.profile.readOrder.includes(\"serverShared\") &&\n scopeProfileWritePlan.readNamespaces.includes(this.deps.config.sharedNamespace) &&\n sharedProfileLayer?.readable &&\n sharedProfileLayer.writable &&\n sharedPromotionTarget?.authorized,\n );\n // #1713: hoist namespaces-enabled once for the scope-routing mirrors\n // (pre-judge + write-loop) so no new scattered config.*Enabled read is\n // introduced (ratchet scatteredConfigFlagReads; see #1523).\n const namespacesEnabled = resolveNamespaceCapabilities(this.deps.config).namespaces;\n const profileAutoPromotionAllows = (\n category: string,\n confidence: number,\n ): boolean => {\n if (!scopeProfileWritePlan) return false;\n const actualTier = confidenceTier(confidence);\n const actualRank = confidenceTierOrder.indexOf(actualTier);\n if (actualRank === -1) return false;\n const autoPromote = scopeProfileWritePlan.profile.autoPromote;\n if (!autoPromote.enabled) return false;\n if (!autoPromote.categories.includes(category as any)) return false;\n const minimumRank = confidenceTierOrder.indexOf(autoPromote.minConfidenceTier);\n return minimumRank !== -1 && actualRank <= minimumRank;\n };\n const sharedAutoPromotionAllows = (\n category: string,\n confidence: number,\n ): boolean => {\n if (!scopeProfileWritePlan) {\n const actualTier = confidenceTier(confidence);\n const actualRank = confidenceTierOrder.indexOf(actualTier);\n if (actualRank === -1) return false;\n if (!resolveRecallEnhancementCapabilities(this.deps.config).autoPromoteToShared) return false;\n if (!this.deps.config.autoPromoteToSharedCategories.includes(category as any))\n return false;\n const minimumRank = confidenceTierOrder.indexOf(\n this.deps.config.autoPromoteMinConfidenceTier,\n );\n return minimumRank !== -1 && actualRank <= minimumRank;\n }\n return (\n scopeProfileWritePlan.profile.autoPromote.targets.includes(\"serverShared\") &&\n profileAutoPromotionAllows(category, confidence)\n );\n };\n const shouldPromoteToShared = (\n targetStorage: StorageManager,\n category: string,\n confidence: number,\n ): boolean => {\n if (\n !resolveNamespaceCapabilities(this.deps.config).namespaces ||\n !profileAllowsSharedWrites ||\n !sharedAutoPromotionAllows(category, confidence)\n )\n return false;\n if (\n this.deps.storageDirNamespace(targetStorage.dir) ===\n this.deps.config.sharedNamespace\n )\n return false;\n return true;\n };\n const promoteMemoryToProfileTargets = 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 validAt?: string;\n // #1578 — bi-temporal bounds + ingestion provenance forwarded to profile-\n // target copies (same defect class as shared promotion; cursor bugbot).\n invalidAt?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n source: string;\n sources?: ProvenanceSource[];\n provenance?: \"verified\" | \"unverified\" | \"none\";\n }): Promise<void> => {\n if (\n !scopeProfileWritePlan ||\n !profileAutoPromotionAllows(options.category, options.confidence)\n )\n return;\n const autoTargets = new Set(scopeProfileWritePlan.profile.autoPromote.targets);\n const targets = scopeProfileWritePlan.promotionTargets.filter(\n (target) =>\n target.target !== \"serverShared\" &&\n autoTargets.has(target.target) &&\n target.authorized &&\n target.namespace,\n );\n if (targets.length === 0) return;\n const rawContent =\n citationEnabled && 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 for (const target of targets) {\n if (!target.namespace) continue;\n try {\n const targetStorage = await this.deps.getStorageRouter().storageFor(target.namespace);\n if (targetStorage.dir === options.sourceStorage.dir) continue;\n if (\n options.category === \"fact\" &&\n (await targetStorage.hasFactContentHash(dedupContent))\n ) {\n // #1671 — backfill bi-temporal bounds the existing promoted copy\n // lacks (re-extraction with a now-resolved invalidAt). Best-effort,\n // fail-open; the helper gates on invalidAt to avoid I/O when no\n // end bound is present.\n if (options.invalidAt || options.validAt) {\n await this.deps.backfillTemporalBoundsOnDedupHit(\n targetStorage,\n dedupContent,\n {\n invalidAt: options.invalidAt,\n // #1707 thread 2 — carry the corrected start bound.\n validFrom: options.validAt,\n ...(options.observedAt ? { observedAt: options.observedAt } : {}),\n ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),\n },\n options.entityRef,\n );\n }\n continue;\n }\n const targetPromotion = await targetStorage.writeMemory(\n options.category as any,\n citedContent,\n {\n confidence: options.confidence,\n tags: [...options.tags, `${target.target}-promotion`],\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n source: `${options.source}-${target.target}-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 validAt: options.validAt,\n // #1578 — forward bi-temporal bounds + ingestion provenance.\n ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),\n ...(options.observedAt ? { observedAt: options.observedAt } : {}),\n ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),\n contentHashSource: options.category === \"fact\" ? dedupContent : rawContent,\n ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),\n ...(options.provenance ? { provenance: options.provenance } : {}),\n },\n );\n const promotedId = targetPromotion.id;\n // #1645: if the TARGET namespace's own tombstone blocked this promotion,\n // the row lands pending_review — do NOT supersede active target memories.\n if (\n !targetPromotion.tombstoneBlocked &&\n lifecycleCaps.temporalSupersession &&\n options.category === \"fact\" &&\n options.entityRef &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ) {\n try {\n await applyTemporalSupersession({\n storage: targetStorage,\n newMemoryId: promotedId,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: supersessionOrderingAt(options.validAt),\n enabled: !(options.eventTimeSource === \"extracted\" && !options.validAt),\n });\n } catch (profileSupersessionErr) {\n log.warn(\n `persistExtraction: ${target.target} promotion temporal supersession failed open for promoted ${promotedId}: ${profileSupersessionErr}`,\n );\n }\n }\n // #1645 TV6: a tombstone-blocked promotion is pending_review (no\n // active copy) — skip catalog/index/behavior like postWriteGuard.\n if (!targetPromotion.tombstoneBlocked) {\n trackPersistedId(targetStorage, promotedId, { includeReturnedIds: false });\n await this.deps.indexPersistedMemory(targetStorage, promotedId);\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId: promotedId,\n category: options.category as any,\n content: options.content,\n namespace: target.namespace,\n confidence: options.confidence,\n source: \"extraction\",\n }),\n );\n }\n } catch (err) {\n log.warn(\n `persistExtraction: ${target.target} promotion failed open for ${options.sourceMemoryId}: ${err}`,\n );\n }\n }\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 validAt?: string;\n // #1578 — bi-temporal bounds + ingestion provenance forwarded to the\n // shared-namespace copy so shared recall honours the same invalid_at\n // window as the source fact (cursor bugbot).\n invalidAt?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n source: string;\n /** Claim-level provenance spans (issue #1575 PR 2). */\n sources?: ProvenanceSource[];\n provenance?: \"verified\" | \"unverified\" | \"none\";\n }): Promise<void> => {\n await promoteMemoryToProfileTargets(options);\n if (\n !shouldPromoteToShared(\n options.sourceStorage,\n options.category,\n options.confidence,\n )\n )\n return;\n try {\n const sharedStorage = await this.deps.getStorageRouter().storageFor(\n this.deps.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 // #1671 — backfill bi-temporal bounds onto the existing shared copy\n // before the supersession short-circuit. Covers all return paths below\n // (supersession-hit, catch-skip, and the no-supersession short-circuit)\n // in one shot. Best-effort / fail-open; the helper gates on invalidAt.\n if (options.invalidAt || options.validAt) {\n await this.deps.backfillTemporalBoundsOnDedupHit(\n sharedStorage,\n dedupContent,\n {\n invalidAt: options.invalidAt,\n // #1707 thread 2 — carry the corrected start bound.\n validFrom: options.validAt,\n ...(options.observedAt ? { observedAt: options.observedAt } : {}),\n ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),\n },\n options.entityRef,\n );\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 lifecycleCaps.temporalSupersession &&\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 // incoming event's time, not the existing fact's persisted\n // `created`. For source-dated replay/import, this is the\n // source valid_at; otherwise it is the current wall-clock. The\n // matching fact may be an old shared copy whose `created`\n // 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` as the ordering anchor instead of the old fact's\n // timestamp, ensuring supersession fires correctly even when\n // the matching fact predates conflicting candidates.\n const hashDedupSupersession = await applyTemporalSupersession({\n storage: sharedStorage,\n newMemoryId: hashDedupMatchingFact.frontmatter.id,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: supersessionOrderingAt(options.validAt),\n enabled: !(options.eventTimeSource === \"extracted\" && !options.validAt),\n useCallerTimestamp: true,\n });\n // Catalog touch (issue #1499 — codex P2 NElSf): this dedup branch\n // returns WITHOUT the post-write catalog touch (now at the storage chokepoint #1522),\n // but `applyTemporalSupersession` mutated the shared namespace\n // (it rewrote frontmatter to retire stale shared facts). When any\n // ids were actually superseded, the shared namespace changed, so we\n // must record the write — otherwise the shared record's\n // `lastWriteAt` stays stale and `writtenSince` maintenance / QMD\n // fanout skips the namespace after a supersession-only update.\n // Best-effort and failure-tolerant (the storage chokepoint swallows\n // errors); only touch when work happened to avoid spurious writes.\n if (hashDedupSupersession.supersededIds.length > 0) {\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 sharedPromotion = 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 validAt: options.validAt,\n // #1578 — forward bi-temporal bounds + ingestion provenance.\n ...(options.invalidAt ? { invalidAt: options.invalidAt } : {}),\n ...(options.observedAt ? { observedAt: options.observedAt } : {}),\n ...(options.eventTimeSource ? { eventTimeSource: options.eventTimeSource } : {}),\n contentHashSource: options.category === \"fact\" ? dedupContent : rawContent,\n // Claim-level provenance spans (issue #1575 PR 2).\n ...(options.sources && options.sources.length > 0 ? { sources: options.sources } : {}),\n ...(options.provenance ? { provenance: options.provenance } : {}),\n },\n );\n const promotedId = sharedPromotion.id;\n // #1645: if the shared namespace's own tombstone blocked this promotion,\n // leave the row pending_review but do NOT supersede active shared memories.\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 !sharedPromotion.tombstoneBlocked &&\n lifecycleCaps.temporalSupersession &&\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: supersessionOrderingAt(options.validAt),\n enabled: !(options.eventTimeSource === \"extracted\" && !options.validAt),\n });\n } catch (sharedSupersessionErr) {\n log.warn(\n `persistExtraction: shared-namespace temporal supersession failed open for promoted ${promotedId}: ${sharedSupersessionErr}`,\n );\n }\n }\n // Catalog touch (issue #1499, Issue B + ordering sweep): a shared-\n // namespace promotion is the ONLY write the shared namespace receives on\n // this path, so without this the shared record's lastWriteAt stays stale\n // and `writtenSince` filters / maintenance fanout skip it. Record AFTER\n // the promoted write and the shared temporal-supersession attempt so the\n // catalog timestamp never precedes a later durable frontmatter mutation in\n // the same promotion pass. The hot-path source-namespace touch uses a\n // different storage dir, so this does not double-count the source.\n // Best-effort and failure-tolerant — it must never crash the promotion.\n // #1645 TV6: same guard as the profile-target promotion above.\n if (!sharedPromotion.tombstoneBlocked) {\n trackPersistedId(sharedStorage, promotedId, {\n includeReturnedIds: false,\n });\n await this.deps.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.deps.config.sharedNamespace,\n confidence: options.confidence,\n source: \"extraction\",\n }),\n );\n }\n } catch (err) {\n log.warn(\n `persistExtraction: shared promotion failed open for ${options.sourceMemoryId}: ${err}`,\n );\n }\n };\n // #1707 thread 1 — backfill temporal bounds onto promotion copies when the\n // SOURCE-namespace dedup short-circuit fires. That branch patches the\n // source copy then `continue`s before the promotion dedup paths run, so\n // promoted shared/profile copies written before the source fact carried\n // resolved bounds stay stale (cross-namespace recall surfaces an expired\n // fact). This mirrors the promotion-target resolution used by the two\n // promote closures above and calls the same fail-open helper against each\n // target storage. Backfill-only: never writes a new promoted copy.\n const backfillTemporalBoundsOnPromotionCopies = async (args: {\n sourceStorage: StorageManager;\n content: string;\n category: string;\n confidence: number;\n entityRef?: string;\n structuredAttributes?: Record<string, string>;\n bounds: {\n invalidAt?: string;\n validFrom?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n };\n }): Promise<void> => {\n // Mirror the helper's I/O gate: only resolve promotion targets when\n // there is an end bound OR an EXTRACTED start bound. An \"assumed\"\n // validFrom is just the ingestion anchor (no recall effect), so\n // skipping it avoids resolving target storages on every bi-temporal\n // duplicate (review cursor PRRT_OvHk).\n const hasExtractedStart =\n args.bounds.validFrom !== undefined &&\n args.bounds.eventTimeSource === \"extracted\";\n if (!args.bounds.invalidAt && !hasExtractedStart) return;\n // Build the same dedupContent the promotion functions hash on so the\n // content-hash lookup in the helper matches what was stored.\n const rawContent =\n citationEnabled && hasCitationForTemplate(args.content, citationTemplate)\n ? stripCitationForTemplate(args.content, citationTemplate)\n : args.content;\n const sanitizedBase = sanitizeMemoryContent(rawContent);\n const dedupContent =\n args.category === \"fact\" &&\n args.structuredAttributes &&\n Object.keys(args.structuredAttributes).length > 0\n ? `${sanitizedBase.text}\\n[Attributes: ${normalizeAttributePairs(args.structuredAttributes)}]`\n : sanitizedBase.text;\n // Profile targets. NOTE: we do NOT gate on profileAutoPromotionAllows —\n // a promoted profile copy may exist from an EARLIER extraction with\n // higher confidence or older auto-promote settings, so the current\n // duplicate's confidence must not skip backfilling an already-existing\n // promoted copy (review codex PRRT_Ov7LKF). The helper no-ops when no\n // matching copy is found, so resolving all configured auto-promote\n // targets is safe.\n if (scopeProfileWritePlan) {\n const autoTargets = new Set(\n scopeProfileWritePlan.profile.autoPromote.targets,\n );\n const profileTargets = scopeProfileWritePlan.promotionTargets.filter(\n (target) =>\n target.target !== \"serverShared\" &&\n autoTargets.has(target.target) &&\n target.authorized &&\n target.namespace,\n );\n for (const target of profileTargets) {\n if (!target.namespace) continue;\n try {\n const targetStorage = await this.deps.getStorageRouter().storageFor(\n target.namespace,\n );\n if (targetStorage.dir === args.sourceStorage.dir) continue;\n await this.deps.backfillTemporalBoundsOnDedupHit(\n targetStorage,\n dedupContent,\n args.bounds,\n args.entityRef,\n );\n } catch (err) {\n log.warn(\n `bitemporal-backfill: profile-target backfill failed open for ${target.target}: ${err}`,\n );\n }\n }\n }\n // Shared target. A shared copy may exist from an earlier extraction\n // regardless of the current confidence, so do not gate on\n // shouldPromoteToShared (review codex PRRT_Ov7LKF) — BUT still respect\n // shared-write AUTHORIZATION: a scoped profile that does not authorize\n // serverShared writes must not have its shared namespace backfilled\n // (review codex PRRT_Ov7dHR). profileAllowsSharedWrites is true for the\n // legacy no-scope case and encodes the readable/writable/authorized\n // checks under a scope profile.\n if (profileAllowsSharedWrites) {\n try {\n const sharedStorage = await this.deps.getStorageRouter().storageFor(\n this.deps.config.sharedNamespace,\n );\n if (sharedStorage.dir !== args.sourceStorage.dir) {\n await this.deps.backfillTemporalBoundsOnDedupHit(\n sharedStorage,\n dedupContent,\n args.bounds,\n args.entityRef,\n );\n }\n } catch (err) {\n log.warn(\n `bitemporal-backfill: shared-target backfill failed open: ${err}`,\n );\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.deps.config.chunkingTargetTokens,\n minTokens: this.deps.config.chunkingMinTokens,\n overlapSentences: this.deps.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.deps.config.extractionMaxFactsPerRun);\n const entities = rawEntities.slice(\n 0,\n this.deps.config.extractionMaxEntitiesPerRun,\n );\n const questions = rawQuestions.slice(\n 0,\n this.deps.config.extractionMaxQuestionsPerRun,\n );\n const profileUpdates = rawProfileUpdates.slice(\n 0,\n this.deps.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 (graphCaps.multiGraphMemory) {\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 (graphCaps.multiGraphMemory && threadIdForExtraction) {\n try {\n const thread = await this.deps.getThreading().loadThread(threadIdForExtraction);\n threadEpisodeIdsForGraph = thread?.episodeIds\n ? [...thread.episodeIds]\n : [];\n } catch {\n /* fail-open */\n }\n }\n const routeRules = await this.deps.loadRoutingRules();\n const routeOptions = this.deps.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 // #1713 Item 1: collect routed target namespaces so the pre-judge redaction\n // filter can consult rules from cross-namespace targets, not just the source.\n // #1713 P2 (cursor): track per-fact routed namespace for per-fact pre-judge rules\n const preRoutedNamespaceByFact: 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 if (selected?.target.namespace) {\n preRoutedNamespaceByFact[fi] = selected.target.namespace;\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.deps.setLastPersistExtractionDeferredCount(0);\n if (lifecycleCaps.extractionJudge) {\n // #1669 P1 + #1713 Item 1: pre-filter redacted facts from judge candidates\n // so never-store content is not persisted as judge training data.\n // Consult source + shared + routed target namespace rules so a\n // never-store pattern registered under a cross-namespace target is\n // caught at the batch pre-filter point, not just at the persist gate.\n let preJudgeRedactionRules: CompiledRedactionRule[] = [];\n try {\n // #1713: base rules are source-only. Per-fact routed target rules\n // (including shared when a fact is routed there) are checked in the\n // fact loop, matching the write-time gate's per-fact scoping exactly.\n preJudgeRedactionRules = await redactionRulesFor(storage.dir);\n } catch { /* fail open */ }\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.deps.config.extractionMinImportanceLevel,\n )\n ) {\n continue;\n }\n // #1713 P2 (cursor): per-fact rules — load this fact's routed target\n // namespace rules FIRST, then check. This catches target-only rules\n // even when the base (source+shared) rules are empty (threads acc58c42\n // + PBJEe/PBKAj).\n let factRedactionRules = preJudgeRedactionRules;\n let factNs = preRoutedNamespaceByFact[fi];\n // #1713 (codex PRRT_kwDORJXyws6PBj5X): scope classification can route\n // a scope=global fact to the shared namespace independent of routing\n // rules. If so, the pre-judge filter must consult the shared\n // namespace's rules too, or a never-store pattern under shared is\n // missed at pre-judge and only caught at the write gate — letting the\n // content reach the extraction judge/training path. Mirror the write\n // loop's scope-routing conditions exactly.\n if (\n !factNs &&\n lifecycleCaps.extractionScopeClassification &&\n namespacesEnabled &&\n f.scope === \"global\" &&\n profileAllowsSharedWrites &&\n this.deps.storageDirNamespace(storage.dir) !== this.deps.config.sharedNamespace\n ) {\n factNs = this.deps.config.sharedNamespace;\n }\n if (factNs) {\n try {\n const factDir = (await this.deps.getStorageRouter().storageFor(factNs)).dir;\n if (factDir !== storage.dir) {\n const targetRules = await redactionRulesFor(factDir);\n if (targetRules.length) factRedactionRules = [...preJudgeRedactionRules, ...targetRules];\n }\n } catch { /* fail open */ }\n }\n if (factRedactionRules.length > 0) {\n const rc = f.content + (f.structuredAttributes ? \" \" + JSON.stringify(f.structuredAttributes) : \"\")\n + (f.procedureSteps ? \" \" + f.procedureSteps.map((s) => `${s.intent} ${s.expectedOutcome ?? \"\"} ${s.toolCall ? `${s.toolCall.kind} ${s.toolCall.signature}` : \"\"}`.trim()).join(\" \") : \"\");\n if (contentMatchesRedactionRules(rc, factRedactionRules)) 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: lifecycleCaps.extractionJudgeTelemetry,\n memoryDir: this.deps.config.memoryDir,\n };\n const judgeTrainingOpts = {\n enabled: this.deps.config.collectJudgeTrainingPairs === true,\n ...(this.deps.config.judgeTrainingDir\n ? { directory: this.deps.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.deps.config,\n this.deps.getLocalLlm(),\n new FallbackLlmClient(\n this.deps.config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(this.deps.config),\n ),\n this.deps.getJudgeVerdictCache(),\n this.deps.getJudgeDeferCounts(),\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.deps.setLastPersistExtractionDeferredCount(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 // Faithfulness gate (issue #1576). Entailment-verification of extracted\n // facts against their verified source spans from #1575. Placement: after\n // parse + provenance validation, BEFORE persist/index (rule 44). The\n // substantive batch logic lives in the pure module; this is thin\n // delegation (ground rule 4). off → null map (byte-identical pre-feature\n // pipeline, rule 39); shadow → record only; enforce → pending_review.\n const faithfulnessMode = this.deps.config.extractionFaithfulnessGate;\n const faithfulnessResultsByFactIndex =\n faithfulnessMode === \"shadow\" || faithfulnessMode === \"enforce\"\n ? await runFaithfulnessGateBatch(\n facts,\n faithfulnessMode,\n this.deps.config,\n this.deps.getLocalLlm(),\n new FallbackLlmClient(\n this.deps.config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(this.deps.config),\n ),\n this.deps.getFaithfulnessCounters(),\n sourceText,\n )\n : null;\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 // #1670 — anchor each fact's event-time to its SOURCE TURN timestamp,\n // not the batch-wide latest. When a buffered conversation spans a date\n // boundary, a relative expression (\"yesterday\") on an early-turn fact\n // must resolve against that early turn's date. Prefer the fact's\n // explicit sourceTurnTimestamp, then the earliest provenance span's\n // observedAt, then fall back to the batch anchor (legacy extractors).\n const factAnchor = pickFactEventTimeAnchor(fact, sourceContext?.validAt);\n const biTemporal = this.deps.config.temporalBiTemporal && factAnchor ? resolveFactEventTime(fact.eventTime, factAnchor) : undefined;\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 const sourceStorageDir = storage.dir; // #1669 thread #2: pre-routing source ns for redaction gate\n // Track the KNOWN target namespace NAME alongside targetStorage (round 6,\n // codex P2 — NCQI0). Re-deriving it from `targetStorage.dir` mangles a raw\n // namespace literally named like a canonical token (e.g. `ns-616c706861`\n // served from its legacy raw dir decodes to `alpha`). We seed it from the\n // EXPLICIT base namespace the caller used to obtain `storage` (NHIdx, codex\n // P2) — `selfNamespace`/`writeNamespaceOverride` — so the catalog write touch\n // records the real namespace, not a guess decoded from the directory. We only\n // fall back to decoding the dir when no base namespace was passed (legacy\n // callers). The EXPLICIT routed name (below) still overrides this verbatim.\n let targetNamespaceName =\n baseNamespace && baseNamespace.length > 0\n ? baseNamespace\n : this.deps.storageDirNamespace(targetStorage.dir);\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.deps.getStorageRouter().storageFor(\n selected.target.namespace,\n );\n targetNamespaceName = selected.target.namespace;\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 lifecycleCaps.extractionScopeClassification &&\n namespacesEnabled &&\n fact.scope === \"global\" &&\n !routedNamespaceExplicit\n ) {\n const currentNs = this.deps.storageDirNamespace(targetStorage.dir);\n if (currentNs !== this.deps.config.sharedNamespace && profileAllowsSharedWrites) {\n try {\n targetStorage = await this.deps.getStorageRouter().storageFor(\n this.deps.config.sharedNamespace,\n );\n targetNamespaceName = this.deps.config.sharedNamespace;\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 } else if (currentNs !== this.deps.config.sharedNamespace) {\n log.debug(\n `scope-routing: skipped shared namespace for global fact because active scope profile ${scopeProfileWritePlan?.profileId ?? \"none\"} does not authorize serverShared writes`,\n );\n }\n }\n // #1669 redaction-rule gate: consult BOTH source and target namespace\n // rules before any write. A never-store pattern registered under the\n // source namespace must survive scope-routing to a different target\n // (review thread #2). Fails open on read error.\n try {\n const redactionRules = await redactionRulesFor(sourceStorageDir, targetStorage.dir);\n const redactionCandidate = fact.content\n + (fact.structuredAttributes ? \" \" + JSON.stringify(fact.structuredAttributes) : \"\")\n + (fact.procedureSteps ? \" \" + fact.procedureSteps.map((s) => `${s.intent} ${s.expectedOutcome ?? \"\"} ${s.toolCall ? `${s.toolCall.kind} ${s.toolCall.signature}` : \"\"}`.trim()).join(\" \") : \"\");\n if (redactionRules.length > 0 && contentMatchesRedactionRules(redactionCandidate, redactionRules)) {\n redactionGatedCount++;\n log.debug(`extraction: redaction-rule withheld fact #${redactionGatedCount} in ${targetStorage.dir}`);\n continue;\n }\n } catch (redactionErr) {\n log.warn(`extraction: redaction-rule gate failed open: ${redactionErr}`);\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 // Importance is scored before the dedup short-circuit so #1671 backfill\n // can gate on it (cursor PRRT_OvKnS): a low-value duplicate that the\n // importance write-gate (#372) or the judge pre-filter would drop must\n // not expire an active fact.\n const importance = scoreImportance(\n fact.content,\n writeCategory,\n fact.tags,\n );\n let exactDuplicate = false;\n try {\n exactDuplicate = await this.deps.hasContentHashDedup(\n targetStorage,\n contentHashDedupKey,\n );\n } catch (err) {\n log.warn(\n `content-hash dedup lookup failed for storage ${targetStorage.dir}; writing fact fail-open: ${err}`,\n );\n }\n if (exactDuplicate) {\n // #1671 — before short-circuiting, backfill bi-temporal bounds\n // onto the existing source-namespace copy if it lacks bounds the\n // incoming fact now carries (re-extraction with a resolved invalidAt).\n // Skip when the fact would be rejected/deferred/pending by downstream\n // gates — a non-durable candidate must not expire an active fact\n // (chatgpt-codex P1: faithfulness, requireSpans, extraction judge).\n // #1671 + #1707: backfill bi-temporal bounds onto the existing\n // source-namespace copy if it lacks bounds the incoming fact now\n // carries (re-extraction with a resolved bound). #1707 thread 3:\n // gate on writeCategory === \"fact\" — the helper only matches facts,\n // so a non-fact duplicate must not reach the fact-only scan.\n // #1707 thread 2: also fire when only a corrected start bound\n // (validFrom) is present, not just an end bound (validUntil). The\n // downstream-gate skip still applies — a non-durable candidate must\n // not expire an active fact (chatgpt-codex P1).\n if (\n biTemporal &&\n writeCategory === \"fact\" &&\n (biTemporal.validUntil || biTemporal.validFrom)\n ) {\n const fr = faithfulnessResultsByFactIndex?.get(factLoopIndex);\n const faithfulnessWouldPending =\n faithfulnessMode === \"enforce\" &&\n fr?.ok === true &&\n (fr.verdict === \"unsupported\" || fr.verdict === \"contradicted\");\n const requireSpansWouldPending =\n this.deps.config.provenance?.requireSpans === true &&\n fact.requireSpansPending === true;\n const judgeVerdict = judgeVerdictsByFactIndex?.get(factLoopIndex);\n const judgeWouldGate =\n !this.deps.config.extractionJudgeShadow &&\n judgeVerdict !== undefined &&\n !judgeVerdict.durable;\n // Importance gate (cursor PRRT_OvKnS): below-threshold duplicates\n // would never persist (#372) and carry no judge verdict (the\n // pre-filter skips them), so they must not expire an active fact.\n if (\n isAboveImportanceThreshold(importance.level, this.deps.config.extractionMinImportanceLevel) &&\n !faithfulnessWouldPending &&\n !requireSpansWouldPending &&\n !judgeWouldGate\n ) {\n await this.deps.backfillTemporalBoundsOnDedupHit(\n targetStorage,\n contentHashDedupKey,\n {\n invalidAt: biTemporal.validUntil,\n // #1707 thread 2 — carry the corrected start bound too.\n validFrom: biTemporal.validFrom,\n observedAt: biTemporal.observedAt,\n eventTimeSource: biTemporal.eventTimeSource,\n },\n fact.entityRef,\n );\n // #1707 thread 1 — the source branch short-circuits (`continue`\n // below) before the promotion dedup paths run, so promoted\n // shared/profile copies written before the source fact carried\n // resolved bounds stay stale and cross-namespace recall surfaces\n // an expired fact. Backfill the promotion targets too (fail-open,\n // backfill-only — never writes a new promoted copy).\n await backfillTemporalBoundsOnPromotionCopies({\n sourceStorage: targetStorage,\n content: fact.content,\n category: writeCategory,\n confidence: fact.confidence,\n entityRef: fact.entityRef,\n structuredAttributes: fact.structuredAttributes,\n bounds: {\n invalidAt: biTemporal.validUntil,\n validFrom: biTemporal.validFrom,\n observedAt: biTemporal.observedAt,\n eventTimeSource: biTemporal.eventTimeSource,\n },\n });\n }\n }\n log.debug(\n `dedup: skipping duplicate fact \"${fact.content.slice(0, 60)}…\" in storage ${targetStorage.dir}`,\n );\n dedupedCount++;\n continue;\n }\n\n if (writeCategory === \"procedure\" && this.deps.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.deps.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.deps.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.deps.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 // Faithfulness gate verdict application (issue #1576). Look up the\n // pre-computed verdict for this fact and translate it to frontmatter +\n // an optional enforce-mode pending_review status. Logic lives in the\n // pure module; this is thin read-through (ground rule 4).\n const { faithfulness: faithfulnessFm, enforceStatus: faithfulnessGateStatus } =\n applyFaithfulnessVerdict(\n faithfulnessResultsByFactIndex,\n factLoopIndex,\n faithfulnessMode,\n fact.content,\n this.deps.getFaithfulnessCounters(),\n );\n\n // requireSpans enforcement (issue #1575 PR 2): when an operator opts\n // into provenance.requireSpans, a fact whose quote could not be located\n // in any source turn (carried as the transient requireSpansPending\n // signal from the extraction validator) routes to pending_review — the\n // same review queue an unsupported faithfulness verdict uses. This is\n // the persist-path wiring ProvenanceConfig.requireSpans documents.\n // Faithfulness takes precedence when it already routed the fact; both\n // gates agree on pending_review so the merge is a simple coalesce\n // (chatgpt-codex-connector thread 4xB).\n const requireSpansPendingStatus =\n this.deps.config.provenance?.requireSpans === true &&\n fact.requireSpansPending === true\n ? (\"pending_review\" as const)\n : undefined;\n const faithfulnessEnforceStatus = faithfulnessGateStatus ?? requireSpansPendingStatus;\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 (resolvePipelineProcessingCapabilities(this.deps.config).semanticDedup) {\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.deps.semanticDedupLookup(content, limit, lookupStorage),\n {\n enabled: true,\n threshold: this.deps.config.semanticDedupThreshold,\n candidates: this.deps.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 = resolveConversationContextCapabilities(this.deps.config).intentRouting\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 // #1645: hoist the contradiction result so the deferred auto-resolve\n // (post-write, gated on tombstone status) can read its fields.\n let contradiction: {\n supersededId: string;\n confidence: number;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n } | null | undefined;\n\n // Faithfulness gate (#1576, chatgpt P2): skip contradiction detection\n // for a pending_review fact — an unfaithful extraction in the review queue\n // must not trigger auto-resolve and retire an existing active memory.\n if (\n resolveRecallEnhancementCapabilities(this.deps.config).contradictionDetection &&\n this.deps.getQmd().isAvailable() &&\n faithfulnessEnforceStatus !== \"pending_review\"\n ) {\n const targetNamespace = this.deps.storageDirNamespace(targetStorage.dir);\n contradiction = await this.deps.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.deps.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 // #1645: deindex + supersede are deferred to after writeMemory so the\n // caller can gate them on the new write's tombstone status. A\n // tombstone-blocked write (pending_review) must not deindex or retire\n // the existing active memory — see the post-write guard below.\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 // Faithfulness gate (#1576, cursor High): a pending_review fact must\n // bypass the semantic-dedup skip so it reaches the review queue — the\n // gate's contract is \"persists with status: pending_review, never\n // silently dropped\" (issue #1576).\n if (\n pendingSemanticSkip &&\n !contradictionDetected &&\n !isCorrection &&\n faithfulnessEnforceStatus !== \"pending_review\"\n ) {\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 (resolvePipelineProcessingCapabilities(this.deps.config).chunking && writeCategory !== \"procedure\") {\n let chunkResult: { chunked: boolean; chunks: { content: string; index: number; tokenCount: number }[] };\n\n if (resolvePipelineProcessingCapabilities(this.deps.config).semanticChunking) {\n try {\n const embedFn = this.deps.getEmbeddingFallback().embedTexts.bind(this.deps.getEmbeddingFallback());\n const semanticResult: SemanticChunkResult = await semanticChunkContent(\n fact.content,\n embedFn,\n this.deps.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.deps.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 = resolvePresentationCapabilities(this.deps.config).episodeNoteMode\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 // 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 parentWrite = 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 validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,\n ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),\n contentHashSource: rawChunkedContent,\n // Faithfulness gate (issue #1576).\n ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),\n ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),\n // Claim-level provenance spans (issue #1575 PR 2).\n ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),\n ...(fact.provenance ? { provenance: fact.provenance } : {}),\n },\n );\n const parentId = parentWrite.id;\n // #1645: surface the tombstone block and gate active post-write paths\n // (chunks, supersession, shared promotion, graph/artifact) like #1576.\n const tombstoneBlocked = parentWrite.tombstoneBlocked;\n const postWriteGuard =\n faithfulnessEnforceStatus === \"pending_review\" || tombstoneBlocked;\n // #1645: defer contradiction auto-resolve until tombstone status is\n // known (see applyDeferredContradictionResolve).\n await this.deps.applyDeferredContradictionResolve(\n contradiction,\n targetStorage,\n parentId,\n postWriteGuard,\n );\n try {\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 validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,\n // #1578: propagate end bound + provenance to chunks (cursor bugbot).\n ...(biTemporal\n ? {\n observedAt: biTemporal.observedAt,\n eventTimeSource: biTemporal.eventTimeSource,\n ...(biTemporal.validUntil\n ? { invalidAt: biTemporal.validUntil }\n : {}),\n }\n : {}),\n // Faithfulness gate (issue #1576): propagate the parent\n // fact's verdict + enforce status so a pending_review fact\n // is not indexed as active through its chunks (chatgpt P2).\n ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),\n // #1645 (OchiE): inherit pending_review + blockedBy so no chunk lands active.\n ...(postWriteGuard\n ? { status: \"pending_review\" as const }\n : (faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {})),\n ...(tombstoneBlocked && parentWrite.blockedBy\n ? { blockedBy: parentWrite.blockedBy }\n : {}),\n // Claim-level provenance (issue #1575 PR 2): mirror the\n // parent's spans onto each chunk so a chunk surfaced\n // independently (memory_get/x-ray on a chunk ID) preserves\n // the verified span (chatgpt-codex-connector thread Ocvmo).\n ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),\n ...(fact.provenance ? { provenance: fact.provenance } : {}),\n },\n );\n }\n } finally {\n // The parent memory is durable once writeMemory returns `parentId`.\n // Touch immediately around the chunk-write loop so a later chunk\n // failure still surfaces the partially durable parent/chunk files to\n // catalog-driven `writtenSince` maintenance. The final touch below\n // still refreshes `lastWriteAt` after later durable writes on success.\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 pendingReview: postWriteGuard,\n });\n // #1576 (cursor Medium): keep pending_review ids out of threadEpisodeIdsForGraph — else later active facts build thread-predecessor edges to an unfaithful memory.\n if (\n !postWriteGuard &&\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(parentId)\n ) {\n threadEpisodeIdsForGraph.push(parentId);\n }\n // #1645: same gate as the non-chunked path — a blocked chunked parent\n // must not enter the embedding-fallback index (resurrection).\n if (!postWriteGuard) {\n await this.deps.indexPersistedMemory(targetStorage, parentId);\n }\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 // Faithfulness gate (#1576, cursor High): skip supersession for a\n // pending_review fact — an unfaithful extraction in the review queue\n // must NOT retire older active memories.\n if (!postWriteGuard) {\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: supersessionOrderingAt(biTemporal?.validFrom ?? sourceContext?.validAt),\n // #1578 r3: an extracted end-only bound (validFrom absent) is\n // historical, not a new authoritative state — never let it\n // supersede a later active fact (codex P1 on :15534).\n enabled: lifecycleCaps.temporalSupersession &&\n !(biTemporal && !biTemporal.validFrom),\n });\n } catch (err) {\n log.warn(`temporal-supersession (chunked): unexpected error: ${err}`);\n }\n }\n // Faithfulness gate (#1576, chatgpt P2): do not promote a\n // pending_review fact to shared/profile — it must enter the review\n // queue without active copies that bypass the gate.\n if (!postWriteGuard) 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 validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,\n ...(biTemporal\n ? {\n observedAt: biTemporal.observedAt,\n eventTimeSource: biTemporal.eventTimeSource,\n ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}),\n }\n : {}),\n source: extractionWriteSource,\n ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),\n ...(fact.provenance ? { provenance: fact.provenance } : {}),\n });\n // Register chunked content in the target storage 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.\n try {\n const canonicalChunkedContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n // #1645: do NOT register a tombstone-blocked fact's content in the\n // dedup index — writeMemory already skipped it (rule 44). Re-adding\n // would let the next extraction dedup-skip the tombstone chokepoint\n // and silently ban the retired content (no pending_review row).\n if (!tombstoneBlocked) {\n await this.deps.addContentHashDedup(targetStorage, canonicalChunkedContent);\n }\n } catch (err) {\n log.warn(\n `content-hash dedup registration failed for chunked memory ${parentId}: ${err}`,\n );\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 // #1645: chunks inherit pending_review under postWriteGuard — don't\n // index them into the embedding fallback (resurrection).\n if (!postWriteGuard) {\n await this.deps.indexPersistedMemory(targetStorage, chunkId);\n }\n }\n try {\n if (\n resolvePresentationCapabilities(this.deps.config).verbatimArtifacts &&\n this.deps.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.deps.config.verbatimArtifactsMinConfidence &&\n !postWriteGuard\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.deps.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. #1576: skip pending_review.\n if (graphCaps.multiGraphMemory && !postWriteGuard) {\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.deps.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 graphCaps,\n );\n graphContext.previousPersistedRelPath = parentRelPath;\n } catch {\n /* fail-open */\n }\n }\n } finally {\n // Catalog touch (issue #1499): refresh AFTER later chunked\n // source-namespace durable mutations — temporal supersession, shared\n // promotion, optional artifact writes, and graph-edge writes — so\n // `lastWriteAt` cannot precede later file changes on successful\n // completion. Use the KNOWN routed name, not a dir-decoded guess.\n }\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId: parentId,\n category: writeCategory,\n content: fact.content,\n namespace: this.deps.storageDirNamespace(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 (resolveRecallEnhancementCapabilities(this.deps.config).memoryLinking && this.deps.getQmd().isAvailable()) {\n const targetNamespace = this.deps.storageDirNamespace(targetStorage.dir);\n const suggestedLinks = await this.deps.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 : resolvePresentationCapabilities(this.deps.config).episodeNoteMode\n ? classifyMemoryKind(fact.content, fact.tags ?? [], writeCategory)\n : undefined;\n\n // Normal write (no chunking)\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 // 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 factWrite = 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 validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,\n ...(biTemporal ? { observedAt: biTemporal.observedAt, eventTimeSource: biTemporal.eventTimeSource, ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}) } : {}),\n contentHashSource: writeCategory === \"fact\" ? fact.content : undefined,\n // Faithfulness gate (issue #1576).\n ...(faithfulnessFm ? { faithfulness: faithfulnessFm } : {}),\n ...(faithfulnessEnforceStatus ? { status: faithfulnessEnforceStatus } : {}),\n // Claim-level provenance spans (issue #1575 PR 2). Carry verified\n // sources + the coarse strength tag from the extraction validator\n // through to frontmatter so they survive end-to-end.\n ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),\n ...(fact.provenance ? { provenance: fact.provenance } : {}),\n },\n );\n const memoryId = factWrite.id;\n // #1645: surface the tombstone block; gate active post-write paths like #1576\n // so a blocked fact creates no active shared copy / supersession / graph entry.\n const tombstoneBlocked = factWrite.tombstoneBlocked;\n const postWriteGuard =\n faithfulnessEnforceStatus === \"pending_review\" || tombstoneBlocked;\n // #1645: defer contradiction auto-resolve until tombstone status is\n // known (see applyDeferredContradictionResolve).\n await this.deps.applyDeferredContradictionResolve(\n contradiction,\n targetStorage,\n memoryId,\n postWriteGuard,\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. Faithfulness gate (#1576, cursor\n // High): skip for a pending_review fact — an unfaithful extraction in\n // the review queue must NOT retire older active memories.\n if (!postWriteGuard) {\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: supersessionOrderingAt(biTemporal?.validFrom ?? sourceContext?.validAt),\n enabled: lifecycleCaps.temporalSupersession &&\n !(biTemporal && !biTemporal.validFrom),\n });\n } catch (err) {\n log.warn(`temporal-supersession: unexpected error: ${err}`);\n }\n }\n try {\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId,\n category: writeCategory,\n content: fact.content,\n namespace: this.deps.storageDirNamespace(targetStorage.dir),\n confidence: fact.confidence,\n source: \"extraction\",\n }),\n );\n trackPersistedId(targetStorage, memoryId, {\n pendingReview: postWriteGuard,\n });\n if (\n !postWriteGuard &&\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(memoryId)\n ) {\n threadEpisodeIdsForGraph.push(memoryId);\n }\n // #1645: a tombstone-blocked / pending_review fact must NOT enter the\n // embedding-fallback index — otherwise embedding recall surfaces the\n // pending_review row (resurrection). Gate on postWriteGuard like the\n // surrounding supersession / promotion / graph paths.\n if (!postWriteGuard) {\n await this.deps.indexPersistedMemory(targetStorage, memoryId);\n }\n // Faithfulness gate (#1576, chatgpt P2): skip promotion for a\n // pending_review fact so no active shared/profile copy bypasses the gate.\n if (!postWriteGuard) 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 validAt: biTemporal ? biTemporal.validFrom : sourceContext?.validAt,\n ...(biTemporal\n ? {\n observedAt: biTemporal.observedAt,\n eventTimeSource: biTemporal.eventTimeSource,\n ...(biTemporal.validUntil ? { invalidAt: biTemporal.validUntil } : {}),\n }\n : {}),\n source: extractionWriteSource,\n ...(fact.sources && fact.sources.length > 0 ? { sources: fact.sources } : {}),\n ...(fact.provenance ? { provenance: fact.provenance } : {}),\n });\n // v8.2: graph edge building (fail-open). #1576: skip pending_review facts.\n if (graphCaps.multiGraphMemory && !postWriteGuard) {\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.deps.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 graphCaps,\n );\n graphContext.previousPersistedRelPath = memoryRelPath;\n } catch {\n /* fail-open */\n }\n }\n if (\n resolvePresentationCapabilities(this.deps.config).verbatimArtifacts &&\n this.deps.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.deps.config.verbatimArtifactsMinConfidence &&\n !postWriteGuard\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.deps.artifactTypeForCategory(writeCategory),\n sourceMemoryId: memoryId,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n });\n }\n // Register in the target storage content-hash index after successful\n // write. Thread 3 fix: canonicalize by stripping any pre-existing\n // citation so the stored hash matches what the dedup check computes.\n try {\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 // #1645: do NOT register a tombstone-blocked fact's content in the dedup\n // index (rule 44 defeat) — see chunked path comment.\n if (!tombstoneBlocked) {\n await this.deps.addContentHashDedup(targetStorage, hashRegisterKey);\n }\n } catch (err) {\n log.warn(\n `content-hash dedup registration failed for memory ${memoryId}: ${err}`,\n );\n }\n } finally {\n // Catalog touch (issue #1499): record AFTER every synchronous\n // source-namespace mutation in the non-chunked path: writeMemory,\n // temporal supersession, graph edges, and optional verbatim artifacts.\n // The `finally` preserves the write touch when post-write indexing or\n // promotion fails after the canonical memory is already durable. Use the\n // KNOWN routed name, not a dir-decoded guess (NCQI0).\n }\n }\n\n // Tracks whether THIS extraction persisted any durable, non-fact output to the\n // BASE namespace's storage (entity / relationship / profile / question). The\n // per-fact catalog touch (storage chokepoint #1522) only fires inside the fact write loop, so a\n // fact-less extraction that still persists durable data must record exactly one\n // base-namespace catalog touch after all writes complete (NHZEZ, codex P2).\n let durableNonFactWritten = false;\n let durableNonFactTouchRecorded = false;\n const touchBaseNonFactNamespace = () => {\n const baseTouchNamespace =\n baseNamespace && baseNamespace.length > 0\n ? baseNamespace\n : this.deps.storageDirNamespace(storage.dir);\n };\n const recordDurableNonFactWrite = () => {\n durableNonFactWritten = true;\n if (durableNonFactTouchRecorded) return;\n durableNonFactTouchRecorded = true;\n touchBaseNonFactNamespace();\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 timestamp: sourceContext?.validAt,\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) {\n trackPersistedId(storage, id);\n recordDurableNonFactWrite();\n }\n } catch (err) {\n log.warn(`persistExtraction: entity write failed: ${err}`);\n }\n }\n\n // Persist entity relationships (v7.0)\n if (\n resolveRecallEnhancementCapabilities(this.deps.config).entityRelationships &&\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 recordDurableNonFactWrite();\n await storage.addEntityRelationship(rel.target, {\n target: rel.source,\n label: `${rel.label} (reverse)`,\n });\n recordDurableNonFactWrite();\n } catch (err) {\n log.debug(`relationship persist failed: ${err}`);\n }\n }\n }\n\n // Persist entity activity (v7.0)\n if (resolveRecallEnhancementCapabilities(this.deps.config).entityActivityLog) {\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 = storage.normalizeEntityName(name, type);\n await storage.addEntityActivity(\n normalized,\n { date: today, note: \"Mentioned in conversation\" },\n this.deps.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 recordDurableNonFactWrite();\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) {\n trackPersistedId(storage, id);\n recordDurableNonFactWrite();\n }\n }\n\n // Persist identity reflection. This writes durable namespace-local state, so\n // an identity-ONLY extraction (no facts/entities/profile/questions) still\n // counts as a durable non-fact write for the catalog touch below (NIIly).\n // Only count it when the write actually succeeds (best-effort write); the\n // touch is recorded AFTER this so a rolled-back/failed write never touches.\n if (resolveRecallEnhancementCapabilities(this.deps.config).identity && result.identityReflection) {\n try {\n await storage.appendIdentityReflection(result.identityReflection);\n recordDurableNonFactWrite();\n } catch (err) {\n log.debug(`identity reflection write failed: ${err}`);\n }\n }\n\n // Catalog touch for durable NON-FACT outputs (NHZEZ / NIIly, codex P2). The\n // per-fact catalog touch (storage chokepoint #1522) above only fires inside the fact write loop, so\n // an extraction that persists ONLY entities, relationships, profile updates,\n // questions, or an identity reflection (no facts) would record durable data to\n // the BASE namespace's storage without ever touching the catalog — leaving that\n // namespace's `lastWriteAt` stale so `listNamespaces({writtenSince})` /\n // write-recency QMD maintenance miss the write. All of these are written to the\n // BASE `storage` (not the per-fact routed `targetStorage`), so we record ONE\n // base-namespace touch here, AFTER every non-fact write completes. Use the\n // KNOWN base namespace name, not a dir-decoded guess (NCQI0). One touch per\n // namespace per extraction — `markWrite` is idempotent, so if the fact path\n // already touched the base namespace this only refreshes `lastWriteAt`.\n // Best-effort and failure-tolerant (storage chokepoint #1522 swallows errors).\n if (durableNonFactWritten) {\n touchBaseNonFactNamespace();\n }\n\n // Save any content-hash indexes touched during the batch.\n await this.deps.saveContentHashIndexes().catch((err) =>\n 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 const redactionSuffix =\n redactionGatedCount > 0 ? ` (${redactionGatedCount} redacted)` : \"\";\n log.info(\n `persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount - redactionGatedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}${redactionSuffix}, ${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.deps.updateTemporalTagIndexes(storage, []);\n return;\n }\n for (const entry of persistedIdsByStorage.values()) {\n await this.deps.updateTemporalTagIndexes(entry.storage, entry.ids);\n }\n })().catch((err) =>\n log.debug(`temporal-index update error (non-fatal): ${err}`),\n );\n\n // #1635: surface pending_review ids so the thread episode set excludes them.\n this.deps.setLastPersistExtractionPendingReviewIds(pendingReviewPersistedIds);\n // Return the persisted fact IDs for threading\n return persistedIds;\n }\n}\n","/**\n * Recall-internal coordinator — extracted from the orchestrator\n * (issue #1526, seam 18).\n *\n * Owns the `recallInternal` pipeline: the ~5k-LOC method that turns a\n * prompt into the injected memory-context string. Hosts the full recall\n * assembly flow:\n * - intent planning + recall-mode gating\n * - QMD tier search with artifact top-up and cold-fallback pipeline\n * - specialized recall sections (entity, explicit-cue, targeted-fact,\n * response-guidance, event-order, conversation, compression guidelines)\n * - graph expansion, trust scoring, rerank, MMR diversification\n * - budget accounting, X-ray capture, and last-recall snapshots\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps a thin delegating method so existing call sites and\n * tests continue to work. Every gate the moved code consults flows back\n * through RecallInternalDeps into the orchestrator's own (overridable)\n * members, so test seams like `recallAssemblyClockMs` keep working.\n */\n\nimport { createHash } from \"node:crypto\";\nimport { readFile, stat, unlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { BoxBuilder, type BoxFrontmatter } from \"../boxes.js\";\nimport { type CapabilitySet, type GraphConstructionCapabilitySet, type MemoryLifecycleCapabilitySet, resolveCapabilities, resolveCompressionCapabilities, resolveConsolidationCapabilities, resolveConversationContextCapabilities, resolveCreationMemoryCapabilities, resolveGraphConstructionCapabilities, resolveIdentityContinuityCapabilities, resolveIndexingCapabilities, resolveMemoryLifecycleCapabilities, resolveNamespaceCapabilities, resolveObjectiveStateCapabilities, resolvePipelineProcessingCapabilities, resolvePresentationCapabilities, resolveQmdCapabilities, resolveRecallAuxiliaryCapabilities, resolveRecallEnhancementCapabilities, resolveSecurityCapabilities } from \"../capabilities.js\";\nimport { type CausalTrajectorySearchResult, searchCausalTrajectories } from \"../causal-trajectory.js\";\nimport { CompoundingEngine } from \"../compounding/engine.js\";\nimport { buildEntityRecallSection, entityRecentTranscriptLookbackHours, readRecentEntityTranscriptEntries } from \"../entity-retrieval.js\";\nimport type { EvalShadowRecallRecord } from \"../evals.js\";\nimport { buildEventOrderRecallSection, shouldRecallEventOrderEvidence } from \"../event-order-recall.js\";\nimport { buildExplicitCueRecallSection } from \"../explicit-cue-recall.js\";\nimport { buildFocusedListRecallSection, shouldRecallFocusedListEvidence } from \"../focused-list-recall.js\";\nimport { type HarmonicRetrievalResult, searchHarmonicRetrieval } from \"../harmonic-retrieval.js\";\nimport { StorageManager } from \"../index.js\";\nimport { inferIntentFromText, planRecallMode } from \"../intent.js\";\nimport { LcmEngine } from \"../lcm/index.js\";\nimport { log } from \"../logger.js\";\nimport { buildRetrievedMemoryProvenance } from \"../memory-provenance.js\";\nimport { NamespaceCatalog } from \"../namespaces/catalog.js\";\nimport { canReadNamespace, resolvePrincipal } from \"../namespaces/principal.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { collectNativeKnowledgeChunks, formatNativeKnowledgeSection, searchNativeKnowledge } from \"../native-knowledge.js\";\nimport { type ObjectiveStateSearchResult, objectiveStateStoreOverrideForNamespace, searchObjectiveStateSnapshots } from \"../objective-state.js\";\nimport { type GraphRecallRankedResult, type GraphRecallShadowComparison, mergeGraphExpandedResults } from \"./graph-recall-coordinator.js\";\nimport { buildProcedureRecallSection } from \"../procedural/procedure-recall.js\";\nimport { ProfilingCollector } from \"../profiling.js\";\nimport { buildQmdRecallCacheKey, getCachedQmdRecall, setCachedQmdRecall } from \"../qmd-recall-cache.js\";\nimport { MEMORY_ID_PATTERN } from \"../recall-handles.js\";\nimport { createRecallSectionMetricRecorder } from \"../recall-qos.js\";\nimport { buildRecallQueryPolicy } from \"../recall-query-policy.js\";\nimport { type GraphRecallExpandedEntry, type LastRecallBudgetSummary, type LastRecallSnapshot, LastRecallStore, RecallHandleHistoryStore } from \"../recall-state.js\";\nimport { type RecallFilterTrace, type RecallXrayResult, type RecallXrayScoreDecomposition, type RecallXraySnapshot, buildXraySnapshot } from \"../recall-xray.js\";\nimport { findUnresolvedEntityRefs } from \"../reconstruct.js\";\nimport { RerankCache, rerankLocalOrNoop } from \"../rerank.js\";\nimport { buildResponseGuidanceRecallSection, shouldRecallResponseGuidance } from \"../response-guidance-recall.js\";\nimport { type ParallelSearchResult, mergeWithAgentResults, runDirectAgent, runTemporalAgent, shouldRunAgent } from \"../retrieval-agents.js\";\nimport { resolveScopePlan } from \"../scopes/scope-plan.js\";\nimport type { SearchBackend, SearchDegradation, SearchQueryOptions } from \"../search/port.js\";\nimport { type VerifiedSemanticRuleResult, compareVerifiedSemanticRuleResults, searchVerifiedSemanticRules } from \"../semantic-rule-verifier.js\";\nimport { SharedContextManager } from \"../shared-context/manager.js\";\nimport { isDisagreementPrompt } from \"../signal.js\";\nimport { HourlySummarizer } from \"../summarizer.js\";\nimport { buildTargetedFactRecallSection, shouldRecallTargetedFactEvidence } from \"../targeted-fact-recall.js\";\nimport { shouldFilterSupersededFromRecall } from \"../temporal-supersession.js\";\nimport { isValidAsOf } from \"../temporal-validity.js\";\nimport { TmtBuilder } from \"../tmt.js\";\nimport { TranscriptManager } from \"../transcript.js\";\nimport { type TrustStageResultItem, projectTrustForXray } from \"../trust-score-stage.js\";\nimport { type TrustZoneSearchResult, searchTrustZoneRecords } from \"../trust-zones.js\";\nimport type { CodingContext, EngramTraceEvent, IdentityInjectionMode, MemoryFile, MemoryIntent, PluginConfig, QmdSearchResult, RecallPlanMode, RecallSectionConfig } from \"../types.js\";\nimport { type VerifiedEpisodeResult, compareVerifiedEpisodeResults, searchVerifiedEpisodes } from \"../verified-recall.js\";\nimport { type WorkProductLedgerSearchResult, searchWorkProductLedgerEntries } from \"../work-product-ledger.js\";\nimport {\n applyQueryAwareCandidateFilter,\n filterRecallCandidates,\n mapRecallSourceToXrayServedBy,\n COMPACTION_SIGNAL_MAX_AGE_MS,\n computeArtifactRecallLimit,\n computeQmdHybridFetchLimit,\n defaultWorkspaceDir,\n isArtifactMemoryPath,\n raceRecallAbort,\n resolveRecallModeDecision,\n resolveRecallModeDecisionAsync,\n sanitizeSessionKeyForFilename,\n summarizeGraphShadowComparison,\n throwIfRecallAborted,\n type GraphRecallSnapshot,\n type IntentDebugSnapshot,\n type QmdRecallSnapshot,\n type QueryAwarePrefilter,\n type RecallInvocationOptions,\n} from \"../orchestrator.js\";\n\nexport interface RecallInternalDeps {\n readonly _recallWorkspaceOverrides: Map<string, string>;\n appendRecallSection(\n sectionBuckets: Map<string, string[]>,\n sectionId: string,\n content: string,\n ): boolean;\n applyColdFallbackPipeline(options: {\n prompt: string;\n recallNamespaces: string[];\n recallResultLimit: number;\n recallMode: RecallPlanMode;\n /**\n * Recall-operation capability gates resolved once at recall entry (#1523).\n * OPTIONAL and additive: the recall pipeline threads a resolved set, but\n * callers that omit it (e.g. direct unit-test invocations) get an\n * equivalent config-derived set — behavior-preserving.\n */\n caps?: CapabilitySet;\n /** Graph-construction gates resolved at recall entry (#1566 Cluster A). */\n graphCaps?: GraphConstructionCapabilitySet;\n queryAwarePrefilter?: QueryAwarePrefilter;\n abortSignal?: AbortSignal;\n /** Backend degradation observer — cold-tier QMD must report like hot (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\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 /**\n * Issue #1577 — out-parameter that receives the TrustScore stage's\n * per-path trust map (admitted + quarantined) when the cold path runs\n * trust scoring. Mirrors the xrayPoolSizeSink pattern so recallInternal\n can propagate trust data for epistemic rendering and X-ray visibility\n without changing the cold pipeline's return type.\n */\n trustByPathSink?: { trustByPath: Map<string, TrustStageResultItem> | null };\n deadlineAtMs?: number | null;\n /** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */\n includeLowConfidence?: boolean;\n }): Promise<QmdSearchResult[]>;\n applyTrustScoreToBranch(\n results: QmdSearchResult[],\n namespaces: string[],\n caps: CapabilitySet,\n label: string,\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }>;\n 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 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 boxBuilderFor(storage: StorageManager): BoxBuilder;\n buildCompressionGuidelineRecallSection(): Promise<string | null>;\n buildConfiguredQmdSearchOptions(\n queryText: string,\n ): SearchQueryOptions | undefined;\n buildGraphRecallRankedResults(\n results: QmdSearchResult[],\n sourceLabelResolver: (path: string) => string[],\n limit?: number,\n ): GraphRecallRankedResult[];\n 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 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 buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter>;\n 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 readonly compounding?: CompoundingEngine;\n readonly config: PluginConfig;\n currentPolicyVersion(): string;\n diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n caps?: CapabilitySet,\n ): QmdSearchResult[];\n effectiveCronRecallInstructionHeavyTokenCap(): number;\n emitTrace(event: EngramTraceEvent): void;\n expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n deadlineAtMs?: number | null;\n includeLowConfidence?: boolean;\n }): Promise<{\n merged: QmdSearchResult[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n seedResults: QmdSearchResult[];\n }>;\n extractMemoryIdsFromResults(results: QmdSearchResult[]): string[];\n readonly 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 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 /** Backend degradation observer, threaded into every QMD call (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]>;\n filterSearchResultsForRecall(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n dropUnresolved?: boolean;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{ results: QmdSearchResult[]; memoryByPath: Map<string, MemoryFile> }>;\n formatCausalTrajectoryResults(\n results: CausalTrajectorySearchResult[],\n ): string;\n formatConversationRecallSection(\n results: Array<{ path: string; snippet: string; score: number }>,\n maxChars: number,\n ): string | null;\n formatHarmonicRetrievalResults(\n results: HarmonicRetrievalResult[],\n ): string;\n formatObjectiveStateResults(\n results: ObjectiveStateSearchResult[],\n ): string;\n formatQmdResults(\n title: string,\n results: QmdSearchResult[],\n sessionKey?: string,\n trustByPath?: Map<string, TrustStageResultItem> | null,\n ): string;\n formatTrustZoneResults(results: TrustZoneSearchResult[]): string;\n formatVerifiedEpisodeResults(\n results: VerifiedEpisodeResult[],\n ): string;\n formatVerifiedSemanticRuleResults(\n results: VerifiedSemanticRuleResult[],\n ): string;\n formatWorkProductResults(\n results: WorkProductLedgerSearchResult[],\n ): string;\n getCodingContextForSession(sessionKey: string | undefined): CodingContext | null;\n getPeerIdForSession(sessionKey: string | undefined): string | null;\n getRecallBudgetChars(override?: number): number;\n getRecallSectionEntry(\n sectionId: string,\n ): RecallSectionConfig | undefined;\n getRecallSectionMaxChars(\n sectionId: string,\n ): number | null | undefined;\n getRecallSectionNumber(\n sectionId: string,\n key: keyof RecallSectionConfig,\n ): number | undefined;\n getStorage(namespace?: string): Promise<StorageManager>;\n readonly handleHistory: RecallHandleHistoryStore;\n isRecallSectionEnabled(\n sectionId: string,\n defaultEnabled?: boolean,\n ): boolean;\n isSpecializedRecallSectionEnabled(\n sectionId: string,\n topLevelEnabled: boolean,\n ): boolean;\n lastQmdReprobeAtMs: number;\n readonly lastRecall: LastRecallStore;\n lastXraySnapshot: RecallXraySnapshot | null;\n readonly lcmEngine: LcmEngine | null;\n readonly namespaceCatalog: NamespaceCatalog;\n namespaceFromPath(p: string): string;\n readonly profiler: ProfilingCollector;\n 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 /**\n * Issue #1577 — per-recall trust map. When present, quarantined items\n * are filtered from injection on EVERY recall path (hot QMD, embedding\n * fallback, cold archive, recent) so a faithfulness-contradicted memory\n * cannot sneak in via a branch that bypasses trust scoring (review:\n * fallback paths bypass trust). The map is also threaded to\n * formatQmdResults for the epistemic hedge.\n */\n trustByPath?: Map<string, TrustStageResultItem> | null;\n }): void;\n readonly qmd: SearchBackend;\n queueEvalShadowRecall(\n record: Omit<EvalShadowRecallRecord, \"schemaVersion\">,\n ): void;\n readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]>;\n recallArtifactsAcrossNamespaces(\n prompt: string,\n recallNamespaces: string[],\n targetCount: number,\n ): Promise<MemoryFile[]>;\n recallAssemblyClockMs(): number;\n 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 recordLastIntentSnapshot(options: {\n storage: StorageManager;\n snapshot: IntentDebugSnapshot;\n }): Promise<void>;\n recordLastIntentSnapshotForNamespace(options: {\n namespace: string;\n snapshot: IntentDebugSnapshot;\n }): Promise<void>;\n recordLastQmdRecallSnapshot(options: {\n storage: StorageManager;\n snapshot: QmdRecallSnapshot;\n }): Promise<void>;\n readonly rerankCache: RerankCache;\n searchConversationRecallResults(\n retrievalQuery: string,\n topK: number,\n ): Promise<Array<{ path: string; snippet: string; score: number }>>;\n searchEmbeddingFallback(\n query: string,\n limit: number,\n ): Promise<QmdSearchResult[]>;\n readonly sharedContext?: SharedContextManager;\n readonly storage: StorageManager;\n readonly storageRouter: NamespaceStorageRouter;\n readonly summarizer: HourlySummarizer;\n readonly tmtBuilder: TmtBuilder;\n readonly transcript: TranscriptManager;\n truncateArtifactForRecall(text: string, maxChars?: number): string;\n truncateRecallSectionToBudget(\n content: string,\n maxChars: number,\n ): string;\n}\n\nexport class RecallInternalCoordinator {\n constructor(\n private readonly deps: RecallInternalDeps,\n ) {}\n\n async recallInternal(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n caps: CapabilitySet = resolveCapabilities(this.deps.config),\n graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.deps.config),\n lifecycleCaps: MemoryLifecycleCapabilitySet = resolveMemoryLifecycleCapabilities(this.deps.config),\n ): Promise<string> {\n const recallStart = Date.now();\n // Backend degradations observed by this recall's QMD searches (#1536):\n // collected via the execution-options observer and attached to the\n // LastRecallSnapshot after it is recorded, so surfaces can distinguish\n // \"no matches\" from \"backend could not answer\" (CLAUDE.md rule 34).\n const backendDegradations: SearchDegradation[] = [];\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.deps.profiler.startTrace(\"recall\", sessionKey, {\n qmdEnabled: resolveQmdCapabilities(this.deps.config).qmd,\n rerankEnabled: caps.rerank,\n parallelRetrieval: caps.parallelRetrieval,\n });\n this.deps.profiler.startSpan(\"planning\", profileTraceId);\n let profileTraceClosed = false;\n const closeProfileTrace = () => {\n if (profileTraceClosed) return;\n profileTraceClosed = true;\n this.deps.profiler.endTrace(profileTraceId); // persists to JSONL file\n };\n const recallSectionDeadlineMs = this.deps.config.recallCoreDeadlineMs ?? 75_000;\n const enrichmentSectionDeadlineMs =\n this.deps.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 // The effective LCM read session_id SET is computed below from\n // `recallNamespaces` (the SAME read-authorized namespace set normal QMD/file\n // recall searches, incl. coding `readFallbacks`). See the\n // `lcmReadSessionIds` derivation after `recallNamespaces` is built.\n const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: resolveRecallAuxiliaryCapabilities(this.deps.config).cronRecallPolicy,\n cronRecallNormalizedQueryMaxChars:\n this.deps.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.deps.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.deps.config.cronConversationRecallMode,\n });\n const retrievalQuery = queryPolicy.retrievalQuery || prompt;\n const retrievalQueryHash = createHash(\"sha256\")\n .update(retrievalQuery)\n .digest(\"hex\");\n const policyVersion = this.deps.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 // Issue #1577 — per-recall trust map (admitted + quarantined items).\n // A LOCAL, not instance state, so concurrent recalls on the same\n // orchestrator cannot race on it (review: shared-trust-map concurrency).\n // Populated by applyTrustScoreRerank on whichever recall path runs;\n // consumed by formatQmdResults (epistemic hedge), publishRecallResults\n // (quarantine filtering on ALL paths), and the X-ray capture (trust\n // projection + quarantined-item visibility — rule 34).\n let recallTrustByPath: Map<string, TrustStageResultItem> | null = null;\n // Issue #1577 — sink for the cold-fallback pipeline's trust map. The cold\n // pipeline scores internally (applyColdFallbackPipeline) and writes its\n // per-path trust map here; each cold caller reads it back into\n // recallTrustByPath so cold/embedding/recent paths feed the same X-ray +\n // epistemic-rendering + publisher-quarantine consumers the hot path uses\n // (rule 41: the feature gate applies across ALL parallel recall paths).\n const trustByPathSink: { trustByPath: Map<string, TrustStageResultItem> | null } = {\n trustByPath: null,\n };\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 recallModeDecisionOptions = {\n plannerEnabled: caps.recallPlanner,\n graphRecallEnabled: caps.graphRecall,\n multiGraphMemoryEnabled: graphCaps.multiGraphMemory,\n graphExpandedIntentEnabled: caps.graphExpandedIntent,\n prompt,\n };\n // Issue #1547 — let the heuristic decide no_recall BEFORE the planner/non-planner fork so it fires with planner on OR off.\n const requestedMode: RecallPlanMode | undefined = options.mode ?? (planRecallMode(prompt) === \"no_recall\" ? \"no_recall\" : undefined);\n // planner entirely — the decision is overridden anyway. Otherwise consult\n // the LLM planner when opted in (issue #1367 / Option C); it falls back to\n // the heuristic on disable / shadow / timeout / error.\n const recallDecision =\n requestedMode !== undefined\n ? resolveRecallModeDecision(recallModeDecisionOptions)\n : await resolveRecallModeDecisionAsync({\n ...recallModeDecisionOptions,\n config: this.deps.config,\n caps,\n signal: options.abortSignal,\n });\n if (\n resolveRecallEnhancementCapabilities(this.deps.config).recallPlannerTelemetry &&\n recallDecision.plannerSource &&\n recallDecision.plannerSource !== \"heuristic\"\n ) {\n log.debug(\n `[recall-planner] mode=${recallDecision.shadowLlmMode ?? recallDecision.effectiveMode} ` +\n `source=${recallDecision.plannerSource} ` +\n `planned=${recallDecision.plannedMode} ` +\n `heuristic=${recallDecision.plannerHeuristicMode ?? recallDecision.plannedMode} ` +\n `model=${recallDecision.plannerModelUsed ?? \"n/a\"} ` +\n `latencyMs=${recallDecision.plannerLatencyMs ?? 0} ` +\n `fallback=${recallDecision.plannerFallbackUsed ?? false}` +\n (recallDecision.shadowLlmMode ? \" (shadow)\" : \"\"),\n );\n }\n this.deps.profiler.endSpan(\"planning\", profileTraceId);\n const recallMode: RecallPlanMode =\n requestedMode ?? recallDecision.effectiveMode;\n const queryIntent = inferIntentFromText(retrievalQuery);\n const qmdSearchOptions =\n this.deps.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.deps.config.qmdMaxResults,\n this.deps.config.recallPlannerMaxQmdResultsMinimal,\n ),\n )\n : this.deps.config.qmdMaxResults;\n const policyMinimalLimit = Math.max(\n 0,\n Math.min(\n this.deps.config.qmdMaxResults,\n this.deps.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.deps.isRecallSectionEnabled(\"memories\");\n const memorySectionMaxResults = this.deps.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 = resolvePresentationCapabilities(this.deps.config).verbatimArtifacts\n ? Math.max(12, this.deps.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 resolvePresentationCapabilities(this.deps.config).verbatimArtifacts,\n this.deps.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.deps.config);\n const namespacesEnabled = resolveNamespaceCapabilities(this.deps.config).namespaces;\n if (namespacesEnabled && !principal) {\n throw new Error(\"authentication required: namespaces are enabled and no principal was supplied\");\n }\n const namespaceOverride = options.namespace?.trim() || undefined;\n if (\n namespaceOverride &&\n !canReadNamespace(principal, namespaceOverride, this.deps.config)\n ) {\n throw new Error(\n `namespace override is not readable: ${namespaceOverride}`,\n );\n }\n // Resolve every namespace-bearing field through ONE ScopePlan (#1521): the\n // read set, the LCM read keys, the coding overlay, and the scope-profile plan\n // all come from a single pure resolver that delegates to the same helpers\n // the inline code used. Parity snapshots in scope-plan.test.ts pin the\n // outputs so this migration cannot change behavior.\n //\n // Catalog read touch (issue #1499) is recorded LATER — after the Phase 1\n // abort gate — so it fires only when retrieval actually runs, not for\n // aborted / short-circuited recalls.\n const scopePlan = resolveScopePlan({\n config: this.deps.config,\n sessionKey,\n namespace: options.namespace,\n principalOverride:\n typeof options.principalOverride === \"string\"\n && options.principalOverride.length > 0\n ? options.principalOverride\n : undefined,\n codingContext: sessionKey\n ? this.deps.getCodingContextForSession(sessionKey)\n : null,\n namespacesEnabled,\n });\n const {\n readNamespaces: recallNamespaces,\n baseNamespace: selfNamespace,\n scopeProfilePlan,\n lcmReadSessionIds,\n } = scopePlan;\n // Query an LCM-backed read across the ordered read key set and return the\n // FIRST non-empty result (#1505 fallback-namespace unification). The primary\n // overlay key is tried first; if a branch-scoped session has no rows under its\n // branch key, the project / root fallback keys are tried in order.\n //\n // #1505 codex P2 (\"Merge LCM fallback reads instead of short-circuiting\"): the\n // query-SCORED sections (explicit-cue, targeted-facts, focused-list,\n // response-guidance, event-order, structured message-parts) no longer use this\n // helper — they MERGE candidates across EVERY authorized key under their single\n // budget (a weak primary-key hit must not mask stronger fallback evidence; the\n // section builders take `sessionIds`, structured-parts merges inline below).\n // This first-non-empty helper now serves ONLY the compressed-history section,\n // which is a per-session HOLISTIC DAG narrative with no per-item id to merge or\n // dedupe on — see its call site for the rationale.\n //\n // When the set is a single key (single-user / no-overlay / explicit-namespace),\n // this is exactly one call — unchanged. `lcmSessionId` is `string | undefined`:\n // a legacy SESSIONLESS recall yields the single `undefined` key so the read\n // runs ONE archive-wide read with no `session_id` filter (pre-#1505 behavior).\n // Hosted scope profiles are stricter: without a session key there is no\n // namespace-scoped LCM key to query, so the key set stays empty and LCM cannot\n // bypass the profile read stack via an archive-wide read. NEVER the literal\n // \"default\" session id (codex P2).\n const firstNonEmptyLcmRead = async <T>(\n read: (lcmSessionId: string | undefined) => Promise<T>,\n isEmpty: (value: T) => boolean,\n empty: T,\n ): Promise<T> => {\n for (const lcmSessionId of lcmReadSessionIds) {\n const value = await read(lcmSessionId);\n if (!isEmpty(value)) return value;\n }\n return empty;\n };\n const qmdAvailable = this.deps.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: caps.recallPlanner,\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: caps.graphRecall,\n multiGraphMemoryEnabled: graphCaps.multiGraphMemory,\n },\n });\n\n if (recallMode === \"no_recall\") {\n const intentSnapshot = buildIntentDebugSnapshot();\n await this.deps.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.deps._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.deps.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.deps.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.deps.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.deps.buildLastRecallBudgetSummary({\n requestedTopK,\n recallResultLimit,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n }),\n latencyMs: Date.now() - recallStart,\n resultPaths: [],\n policyVersion,\n appendImpression: this.deps.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.deps.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.deps.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: resolveQmdCapabilities(this.deps.config).qmd,\n qmdAvailable: this.deps.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 profileStorageNamespaces = scopeProfilePlan ? recallNamespaces : [selfNamespace];\n const profileStorages = await Promise.all(\n profileStorageNamespaces.map((namespace) => this.deps.storageRouter.storageFor(namespace)),\n );\n const emptyProfileStorage = new Proxy(\n { dir: path.join(this.deps.config.memoryDir, \".empty-scope-profile\") } as any,\n {\n get(target, prop: string | symbol) {\n if (prop in target) return target[prop];\n if (prop === \"readProfile\") return async () => \"\";\n if (\n prop === \"readQuestions\" ||\n prop === \"listEntityNames\" ||\n prop === \"readContinuityIncidents\"\n )\n return async () => [];\n if (\n prop === \"readIdentityAnchor\" ||\n prop === \"readIdentityImprovementLoops\"\n )\n return async () => \"\";\n if (prop === \"readEntity\" || prop === \"readMemoryByPath\")\n return async () => null;\n return async () => [];\n },\n },\n );\n const profileStorage =\n profileStorages.length <= 1\n ? profileStorages[0] ?? emptyProfileStorage\n : new Proxy(profileStorages[0] as any, {\n get(target, prop: string | symbol) {\n if (prop === \"readProfile\") {\n return async () => {\n for (const storage of profileStorages) {\n const profile = await storage.readProfile();\n if (profile.trim().length > 0) return profile;\n }\n return \"\";\n };\n }\n if (prop === \"readQuestions\") {\n return async (...args: any[]) => {\n const merged: any[] = [];\n const seen = new Set<string>();\n const priorityOf = (question: any): number => {\n const priority = Number(question?.priority ?? 0);\n return Number.isFinite(priority) ? priority : 0;\n };\n for (const storage of profileStorages) {\n const questions = await (storage.readQuestions as any)(...args);\n for (const question of questions) {\n const key = typeof question === \"string\" ? question : JSON.stringify(question);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(question);\n }\n }\n return merged.sort(\n (left, right) =>\n priorityOf(right) - priorityOf(left) ||\n String(left?.id ?? \"\").localeCompare(String(right?.id ?? \"\")),\n );\n };\n }\n if (prop === \"readIdentityAnchor\") {\n return async () => {\n for (const storage of profileStorages) {\n const anchor = (await storage.readIdentityAnchor()) ?? \"\";\n if (anchor.trim().length > 0) return anchor;\n }\n return \"\";\n };\n }\n if (prop === \"readIdentityImprovementLoops\") {\n return async () => {\n const sections: string[] = [];\n const seen = new Set<string>();\n for (const storage of profileStorages) {\n const loops = ((await storage.readIdentityImprovementLoops()) ?? \"\").trim();\n if (!loops || seen.has(loops)) continue;\n seen.add(loops);\n sections.push(loops);\n }\n return sections.join(\"\\n\\n\");\n };\n }\n if (prop === \"readContinuityIncidents\") {\n return async (...args: any[]) => {\n const limit = typeof args[0] === \"number\" && Number.isFinite(args[0]) ? Math.max(0, args[0]) : undefined;\n const incidents: any[] = [];\n const seen = new Set<string>();\n const incidentTime = (incident: any): number => {\n const raw = incident?.updatedAt ?? incident?.openedAt ?? incident?.createdAt;\n const parsed = typeof raw === \"string\" ? Date.parse(raw) : Number.NaN;\n return Number.isFinite(parsed) ? parsed : 0;\n };\n for (const storage of profileStorages) {\n for (const incident of await (storage.readContinuityIncidents as any)(...args)) {\n const key = JSON.stringify(incident);\n if (seen.has(key)) continue;\n seen.add(key);\n incidents.push(incident);\n }\n }\n incidents.sort(\n (left, right) =>\n incidentTime(right) - incidentTime(left) ||\n String(left?.id ?? \"\").localeCompare(String(right?.id ?? \"\")),\n );\n return limit === undefined ? incidents : incidents.slice(0, limit);\n };\n }\n if (prop === \"listEntityNames\") {\n return async (...args: any[]) => {\n const names = new Set<string>();\n for (const storage of profileStorages) {\n for (const name of await (storage.listEntityNames as any)(...args)) names.add(name);\n }\n return [...names];\n };\n }\n if (prop === \"readEntity\" || prop === \"readMemoryByPath\") {\n return async (...args: any[]) => {\n for (const storage of profileStorages) {\n const value = await (storage as any)[prop](...args);\n if (value) return value;\n }\n return null;\n };\n }\n if (prop === \"readAllMemories\") {\n return async (...args: any[]) => {\n const memories: any[] = [];\n const seen = new Set<string>();\n for (const storage of profileStorages) {\n for (const memory of await (storage.readAllMemories as any)(...args)) {\n const key = String(memory?.path ?? memory?.frontmatter?.id ?? JSON.stringify(memory));\n if (seen.has(key)) continue;\n seen.add(key);\n memories.push(memory);\n }\n }\n return memories;\n };\n }\n return target[prop];\n },\n });\n const profileStorageDirs = Array.from(\n new Set(profileStorages.map((storage) => storage.dir).filter((dir): dir is string => typeof dir === \"string\" && dir.length > 0)),\n );\n\n // --- Phase 1: Launch ALL independent data fetches in parallel ---\n throwIfRecallAborted(options.abortSignal);\n\n // Catalog read touch (issue #1499): record reads against the recalled\n // namespaces HERE — after the abort gate, immediately before retrieval\n // actually runs — so `lastReadAt` reflects a real read, not a recall that was\n // aborted/errored/short-circuited before reaching this point (round 3/4/6,\n // codex/cursor — no_recall, zero-limit, aborted, and pre-read-error cases).\n // `no_recall` already returned earlier, so it cannot reach here. Best-effort\n // and failure-tolerant.\n if (\n this.deps.namespaceCatalog.enabled &&\n recallResultLimit > 0 &&\n !options.abortSignal?.aborted\n ) {\n for (const ns of recallNamespaces) this.deps.storageRouter.recordRead(ns);\n }\n\n // 0. Shared context (v4.0, optional)\n const sharedContextPromise = (async (): Promise<string | null> => {\n if (\n !this.deps.isRecallSectionEnabled(\n \"shared-context\",\n resolveConversationContextCapabilities(this.deps.config).sharedContext === true,\n )\n )\n return null;\n if (!this.deps.sharedContext) return null;\n if (\n scopeProfilePlan &&\n !(\n scopeProfilePlan.profile.readOrder.includes(\"serverShared\") &&\n scopeProfilePlan.readNamespaces.includes(this.deps.config.sharedNamespace)\n )\n )\n return null;\n const t0 = Date.now();\n const [priorities, roundtable, crossSignals] = await Promise.all([\n this.deps.sharedContext.readPriorities(),\n this.deps.sharedContext.readLatestRoundtable(),\n this.deps.sharedContext.readLatestCrossSignals(),\n ]);\n const max = Math.max(500, this.deps.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.deps.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 (!resolveRecallEnhancementCapabilities(this.deps.config).peerProfileRecall) return null;\n if (this.deps.config.peerProfileRecallMaxFields <= 0) return null;\n const peerId = this.deps.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.deps.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.deps.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.deps.isRecallSectionEnabled(\n \"identity-continuity\",\n resolveIdentityContinuityCapabilities(this.deps.config).identityContinuity === true,\n )\n )\n return null;\n const t0 = Date.now();\n const section = await this.deps.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.deps.isRecallSectionEnabled(\n \"entity-retrieval\",\n resolveRecallAuxiliaryCapabilities(this.deps.config).entityRetrieval,\n )\n )\n return null;\n if (!resolveRecallAuxiliaryCapabilities(this.deps.config).entityRetrieval) return null;\n const maxChars =\n this.deps.getRecallSectionMaxChars(\"entity-retrieval\") ??\n this.deps.config.entityRetrievalMaxChars;\n const maxHints =\n this.deps.getRecallSectionNumber(\"entity-retrieval\", \"maxHints\") ??\n this.deps.config.entityRetrievalMaxHints;\n const maxSupportingFacts =\n this.deps.getRecallSectionNumber(\"entity-retrieval\", \"maxSupportingFacts\") ??\n this.deps.config.entityRetrievalMaxSupportingFacts;\n const maxRelatedEntities =\n this.deps.getRecallSectionNumber(\"entity-retrieval\", \"maxRelatedEntities\") ??\n this.deps.config.entityRetrievalMaxRelatedEntities;\n const recentTurns =\n this.deps.getRecallSectionNumber(\"entity-retrieval\", \"recentTurns\") ??\n this.deps.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.deps.transcript.readRecent(\n entityRecentTranscriptLookbackHours,\n sessionKey,\n ),\n recentTurns,\n )\n : [];\n const section = await buildEntityRecallSection({\n config: this.deps.config,\n storage: profileStorage,\n namespaceStorage: (namespace) => this.deps.getStorage(namespace),\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.deps.isRecallSectionEnabled(\n \"knowledge-index\",\n resolveRecallAuxiliaryCapabilities(this.deps.config).knowledgeIndex,\n )\n )\n return null;\n if (!resolveRecallAuxiliaryCapabilities(this.deps.config).knowledgeIndex) return null;\n const t0 = Date.now();\n try {\n const knowledgeIndexMaxChars =\n this.deps.getRecallSectionNumber(\"knowledge-index\", \"maxChars\") ??\n this.deps.config.knowledgeIndexMaxChars;\n const knowledgeIndexMaxEntities =\n this.deps.getRecallSectionNumber(\"knowledge-index\", \"maxEntities\") ??\n this.deps.config.knowledgeIndexMaxEntities;\n const knowledgeIndexOptions = {\n maxEntities: knowledgeIndexMaxEntities,\n maxChars: knowledgeIndexMaxChars,\n };\n const ki = scopeProfilePlan\n ? await (async () => {\n const perLayerOptions = {\n ...knowledgeIndexOptions,\n maxEntities: Number.MAX_SAFE_INTEGER,\n maxChars: Number.MAX_SAFE_INTEGER,\n };\n const results = await Promise.all(\n profileStorages.map((storage) =>\n storage.buildKnowledgeIndex(this.deps.config, perLayerOptions),\n ),\n );\n const sections = results\n .map((result) => result.result.trim())\n .filter((section) => section.length > 0);\n const maxRows = Math.max(0, Math.floor(knowledgeIndexMaxEntities));\n const rows: string[] = [];\n let header: string[] | null = null;\n for (const section of sections) {\n const lines = section\n .split(\"\\n\")\n .map((line) => line.trimEnd())\n .filter((line) => line.length > 0);\n const tableHeaderIndex = lines.findIndex((line) =>\n line.startsWith(\"| Entity |\"),\n );\n if (tableHeaderIndex === -1) continue;\n header ??= lines.slice(0, tableHeaderIndex + 2);\n for (const row of lines.slice(tableHeaderIndex + 2)) {\n if (!row.startsWith(\"|\")) continue;\n if (rows.length >= maxRows) break;\n rows.push(row);\n }\n if (rows.length >= maxRows) break;\n }\n const merged =\n header && rows.length > 0\n ? `${header.join(\"\\n\")}\\n${rows.join(\"\\n\")}\\n`\n : \"\";\n return {\n result: this.deps.truncateRecallSectionToBudget(\n merged,\n knowledgeIndexMaxChars,\n ),\n cached: results.every((result) => result.cached),\n };\n })()\n : await this.deps.storage.buildKnowledgeIndex(this.deps.config, knowledgeIndexOptions);\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.deps.isRecallSectionEnabled(\n \"verbatim-artifacts\",\n resolvePresentationCapabilities(this.deps.config).verbatimArtifacts === true,\n )\n )\n return [];\n if (!resolvePresentationCapabilities(this.deps.config).verbatimArtifacts) return [];\n const t0 = Date.now();\n const targetCount = computeArtifactRecallLimit(\n recallMode,\n recallResultLimit,\n this.deps.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.deps.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 !resolveObjectiveStateCapabilities(this.deps.config).objectiveStateMemory ||\n !resolveObjectiveStateCapabilities(this.deps.config).objectiveStateRecall ||\n !this.deps.isRecallSectionEnabled(\n \"objective-state\",\n resolveObjectiveStateCapabilities(this.deps.config).objectiveStateRecall === 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.deps.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 objectiveStateSearches = await Promise.all(\n recallNamespaces.map(async (namespace) => {\n const storage = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.getStorage(namespace)\n : null;\n return searchObjectiveStateSnapshots({\n memoryDir: resolveNamespaceCapabilities(this.deps.config).namespaces\n ? storage!.dir\n : this.deps.config.memoryDir,\n objectiveStateStoreDir: objectiveStateStoreOverrideForNamespace({\n memoryDir: this.deps.config.memoryDir,\n configuredStoreDir: this.deps.config.objectiveStateStoreDir,\n namespacesEnabled: resolveNamespaceCapabilities(this.deps.config).namespaces,\n namespace,\n }),\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n }),\n );\n const results = objectiveStateSearches\n .flat()\n .sort((left, right) => {\n if (right.score !== left.score) return right.score - left.score;\n return right.snapshot.recordedAt.localeCompare(left.snapshot.recordedAt);\n })\n .slice(0, maxResults);\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.deps.formatObjectiveStateResults(results)\n : null;\n })();\n\n const causalTrajectoryPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !resolveRecallEnhancementCapabilities(this.deps.config).causalTrajectoryMemory ||\n !resolveRecallEnhancementCapabilities(this.deps.config).causalTrajectoryRecall ||\n !this.deps.isRecallSectionEnabled(\n \"causal-trajectories\",\n resolveRecallEnhancementCapabilities(this.deps.config).causalTrajectoryRecall === 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.deps.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.deps.config.memoryDir,\n causalTrajectoryStoreDir: this.deps.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.deps.formatCausalTrajectoryResults(results)\n : null;\n })();\n\n const cmcRetrievalPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !resolveRecallEnhancementCapabilities(this.deps.config).cmcRetrieval ||\n !this.deps.isRecallSectionEnabled(\n \"cmc-causal-chains\",\n resolveRecallEnhancementCapabilities(this.deps.config).cmcRetrieval === 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.deps.config.memoryDir,\n causalTrajectoryStoreDir: this.deps.config.causalTrajectoryStoreDir,\n query: retrievalQuery,\n sessionKey,\n config: {\n maxDepth: this.deps.config.cmcRetrievalMaxDepth,\n maxChars: this.deps.config.cmcRetrievalMaxChars,\n counterfactualBoost: this.deps.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 !resolveConsolidationCapabilities(this.deps.config).calibration ||\n !this.deps.isRecallSectionEnabled(\n \"calibration-rules\",\n resolveConsolidationCapabilities(this.deps.config).calibration === 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.deps.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.deps.config.calibrationMaxRulesPerRecall),\n retrievalQuery,\n this.deps.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 !resolveSecurityCapabilities(this.deps.config).trustZones ||\n !resolveSecurityCapabilities(this.deps.config).trustZoneRecall ||\n !this.deps.isRecallSectionEnabled(\n \"trust-zones\",\n resolveSecurityCapabilities(this.deps.config).trustZoneRecall === 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.deps.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.deps.config.memoryDir,\n trustZoneStoreDir: this.deps.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.deps.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 !caps.harmonicRetrieval ||\n !this.deps.isRecallSectionEnabled(\n \"harmonic-retrieval\",\n caps.harmonicRetrieval,\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.deps.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 harmonicSearchDirs = scopeProfilePlan ? profileStorageDirs : [this.deps.config.memoryDir];\n const harmonicResultsByDir = await Promise.all(\n harmonicSearchDirs.map((memoryDir) =>\n searchHarmonicRetrieval({\n memoryDir,\n abstractionNodeStoreDir: scopeProfilePlan ? undefined : this.deps.config.abstractionNodeStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n anchorsEnabled: resolveConsolidationCapabilities(this.deps.config).abstractionAnchors,\n abortSignal: harmonicRetrievalAbort.signal,\n }),\n ),\n );\n const harmonicByNodeId = new Map<string, HarmonicRetrievalResult>();\n for (const result of harmonicResultsByDir.flat()) {\n const existing = harmonicByNodeId.get(result.node.nodeId);\n if (!existing || result.score > existing.score) {\n harmonicByNodeId.set(result.node.nodeId, result);\n }\n }\n const results = [...harmonicByNodeId.values()]\n .sort(\n (left, right) =>\n right.score - left.score ||\n right.anchorScore - left.anchorScore ||\n right.node.recordedAt.localeCompare(left.node.recordedAt) ||\n left.node.nodeId.localeCompare(right.node.nodeId),\n )\n .slice(0, maxResults);\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.deps.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 !resolveRecallAuxiliaryCapabilities(this.deps.config).verifiedRecall ||\n !this.deps.isRecallSectionEnabled(\n \"verified-episodes\",\n resolveRecallAuxiliaryCapabilities(this.deps.config).verifiedRecall === 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.deps.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 Promise.all(\n profileStorageDirs.map((memoryDir) =>\n searchVerifiedEpisodes({\n memoryDir,\n query: retrievalQuery,\n maxResults,\n boxRecallDays: this.deps.config.boxRecallDays,\n }).catch((err) => {\n log.debug(`verified recall directory scan failed: ${err}`);\n return [] as VerifiedEpisodeResult[];\n }),\n ),\n ).then((groups) => {\n const merged: VerifiedEpisodeResult[] = [];\n const seen = new Set<string>();\n for (const result of groups.flat()) {\n const key = result.box.id || JSON.stringify(result);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n }\n return merged.sort(compareVerifiedEpisodeResults).slice(0, maxResults);\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.deps.formatVerifiedEpisodeResults(results)\n : null;\n })();\n\n const verifiedRulesPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !resolveRecallAuxiliaryCapabilities(this.deps.config).semanticRuleVerification ||\n !this.deps.isRecallSectionEnabled(\n \"verified-rules\",\n resolveRecallAuxiliaryCapabilities(this.deps.config).semanticRuleVerification === 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.deps.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 Promise.all(\n profileStorageDirs.map((memoryDir) =>\n searchVerifiedSemanticRules({\n memoryDir,\n query: retrievalQuery,\n maxResults,\n }).catch((err) => {\n log.debug(`verified rules directory scan failed: ${err}`);\n return [] as VerifiedSemanticRuleResult[];\n }),\n ),\n ).then((groups) => {\n const merged: VerifiedSemanticRuleResult[] = [];\n const seen = new Set<string>();\n for (const result of groups.flat()) {\n const key = result.rule.frontmatter.id || result.rule.path || JSON.stringify(result);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n }\n return merged.sort(compareVerifiedSemanticRuleResults).slice(0, 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.deps.formatVerifiedSemanticRuleResults(results)\n : null;\n })();\n\n const workProductsPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !resolveCreationMemoryCapabilities(this.deps.config).creationMemory ||\n !resolveRecallAuxiliaryCapabilities(this.deps.config).workProductRecall ||\n !this.deps.isRecallSectionEnabled(\n \"work-products\",\n resolveRecallAuxiliaryCapabilities(this.deps.config).workProductRecall === 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.deps.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 workProductSearchDirs = scopeProfilePlan ? profileStorageDirs : [this.deps.config.memoryDir];\n const workProductResultsByDir = await Promise.all(\n workProductSearchDirs.map((memoryDir) =>\n searchWorkProductLedgerEntries({\n memoryDir,\n workProductLedgerDir: scopeProfilePlan ? undefined : this.deps.config.workProductLedgerDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n }),\n ),\n );\n const workProductByEntryId = new Map<string, WorkProductLedgerSearchResult>();\n for (const result of workProductResultsByDir.flat()) {\n const existing = workProductByEntryId.get(result.entry.entryId);\n if (!existing || result.score > existing.score) {\n workProductByEntryId.set(result.entry.entryId, result);\n }\n }\n const results = [...workProductByEntryId.values()]\n .sort(\n (left, right) =>\n right.score - left.score ||\n right.entry.recordedAt.localeCompare(left.entry.recordedAt) ||\n left.entry.entryId.localeCompare(right.entry.entryId),\n )\n .slice(0, maxResults);\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.deps.formatWorkProductResults(results) : null;\n })();\n\n const queryAwarePrefilterPromise =\n (async (): Promise<QueryAwarePrefilter> => {\n const t0 = Date.now();\n if (!resolveIndexingCapabilities(this.deps.config).queryAwareIndexing || !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.deps.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 /**\n * Degradations observed while producing this phase result (#1536).\n * Cached WITH the result so cache hits replay them — a served-from-\n * cache partial result must still explain why it is partial (codex\n * round-4 review on #1544).\n */\n degradations?: SearchDegradation[];\n } | null;\n\n const qmdEnrichmentAbort = createEnrichmentAbortHandle(options.abortSignal);\n const qmdPromise = observeEnrichmentPromise(\n (async (): Promise<QmdPhaseResult> => {\n const t0 = Date.now();\n // Degradation accounting for this phase (#1536): everything pushed\n // after this mark belongs to this phase and is cached with its\n // result; cache hits and stale fallbacks replay stored degradations\n // so served-from-cache results still explain their gaps, and every\n // path that skips QMD entirely reports backend_unavailable.\n const phaseDegradationsStart = backendDegradations.length;\n const replayCachedDegradations = (value: {\n degradations?: SearchDegradation[];\n }) => {\n for (const degradation of value.degradations ?? []) {\n backendDegradations.push(degradation);\n }\n };\n const reportRecallQmdUnavailable = (detail: string) => {\n backendDegradations.push({\n backend: \"qmd\",\n code: \"backend_unavailable\",\n detail,\n });\n };\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.deps.config.memoryDir,\n searchOptions: qmdSearchOptions,\n searchStrategy: this.deps.config.qmdSearchStrategy,\n subprocessStrategy: this.deps.config.qmdSubprocessStrategy,\n });\n const cachedQmd = getCachedQmdRecall<Exclude<QmdPhaseResult, null>>(\n qmdCacheKey,\n {\n freshTtlMs: this.deps.config.qmdRecallCacheTtlMs ?? 60_000,\n staleTtlMs: this.deps.config.qmdRecallCacheStaleTtlMs ?? 10 * 60_000,\n },\n );\n const staleQmdFallback =\n cachedQmd?.source === \"stale\" ? cachedQmd : null;\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const queryAwarePrefilterIsEmpty =\n queryAwarePrefilter.candidatePaths?.size === 0;\n const emptyQueryAwareQmdResult: Exclude<QmdPhaseResult, null> = {\n memoryResultsLists: [[]],\n globalResults: [],\n preAugmentTopScore: 0,\n maxSpecializedScore: 0,\n };\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 replayCachedDegradations(cachedQmd.value);\n if (queryAwarePrefilterIsEmpty) {\n return emptyQueryAwareQmdResult;\n }\n return cachedQmd.value;\n }\n\n if (!this.deps.qmd.isAvailable()) {\n const now = Date.now();\n const QMD_REPROBE_COOLDOWN_MS = 60_000;\n if (\n this.deps.lastQmdReprobeAtMs &&\n now - this.deps.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 reportRecallQmdUnavailable(\"served stale recall cache (reprobe cooldown)\");\n replayCachedDegradations(staleQmdFallback.value);\n if (queryAwarePrefilterIsEmpty) {\n return emptyQueryAwareQmdResult;\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 reportRecallQmdUnavailable(\"recall skipped QMD (reprobe cooldown)\");\n return null;\n }\n this.deps.lastQmdReprobeAtMs = now;\n const reprobed = await this.deps.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 reportRecallQmdUnavailable(\"served stale recall cache (reprobe failed)\");\n replayCachedDegradations(staleQmdFallback.value);\n if (queryAwarePrefilterIsEmpty) {\n return emptyQueryAwareQmdResult;\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.deps.qmd.debugStatus()}`,\n );\n reportRecallQmdUnavailable(\"recall skipped QMD (reprobe failed)\");\n return null;\n }\n log.info(`QMD re-probe succeeded: ${this.deps.qmd.debugStatus()}`);\n }\n\n const maxPerAgent = this.deps.config.parallelMaxResultsPerAgent;\n const specializedAgentPromise: Promise<\n [ParallelSearchResult[], ParallelSearchResult[]]\n > | null =\n !queryAwarePrefilterIsEmpty &&\n caps.parallelRetrieval && maxPerAgent > 0\n ? Promise.all([\n shouldRunAgent(\"direct\", retrievalQuery, 0)\n ? Promise.all(\n profileStorageDirs.map((memoryDir) =>\n runDirectAgent(\n retrievalQuery,\n memoryDir,\n maxPerAgent,\n ).catch((err) => {\n log.debug(`DirectAgent pre-start failed: ${err}`);\n return [] as ParallelSearchResult[];\n }),\n ),\n ).then((groups) => {\n const merged: ParallelSearchResult[] = [];\n const seen = new Set<string>();\n for (const result of groups.flat()) {\n const key = (result as any).path ?? JSON.stringify(result);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n }\n return merged\n .sort((a, b) => b.score - a.score)\n .slice(0, maxPerAgent);\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n shouldRunAgent(\"temporal\", retrievalQuery, 0)\n ? Promise.all(\n profileStorageDirs.map((memoryDir) =>\n runTemporalAgent(\n retrievalQuery,\n memoryDir,\n maxPerAgent,\n queryAwarePrefilter.candidatePaths,\n ).catch((err) => {\n log.debug(`TemporalAgent pre-start failed for ${memoryDir}: ${err}`);\n return [] as ParallelSearchResult[];\n }),\n ),\n ).then((groups) => {\n const merged: ParallelSearchResult[] = [];\n const seen = new Set<string>();\n for (const result of groups.flat()) {\n const key = (result as any).path ?? JSON.stringify(result);\n if (seen.has(key)) continue;\n seen.add(key);\n merged.push(result);\n }\n return merged\n .sort((a, b) => b.score - a.score)\n .slice(0, maxPerAgent);\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n ])\n : null;\n\n try {\n const filteredResults =\n await this.deps.fetchQmdMemoryResultsWithArtifactTopUp(\n retrievalQuery,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n {\n namespacesEnabled: resolveNamespaceCapabilities(this.deps.config).namespaces,\n recallNamespaces,\n resolveNamespace: (p) => this.deps.namespaceFromPath(p),\n queryAwarePrefilter,\n searchOptions: qmdSearchOptions,\n abortSignal: qmdEnrichmentAbort.signal,\n onDegradation: (degradation) => {\n backendDegradations.push(degradation);\n },\n onDebugSnapshot: async (snapshot) => {\n await this.deps.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 (caps.parallelRetrieval && specializedAgentPromise) {\n try {\n const [directResults, temporalResults] =\n await specializedAgentPromise;\n if (filteredResults.length > 0) {\n const w = this.deps.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.deps.config.parallelMaxResultsPerAgent * 2;\n augmentedResults = await mergeWithAgentResults(\n filteredResults,\n directResults,\n temporalResults,\n this.deps.config.parallelAgentWeights,\n qmdFetchLimit + lifecycleHeadroom,\n this.deps.config.memoryDir,\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 phaseDegradations = backendDegradations.slice(\n phaseDegradationsStart,\n );\n const result = {\n memoryResultsLists: [augmentedResults],\n globalResults: [],\n preAugmentTopScore,\n maxSpecializedScore,\n ...(phaseDegradations.length > 0\n ? { degradations: phaseDegradations }\n : {}),\n };\n if (\n augmentedResults.length > 0 ||\n result.globalResults.length > 0\n ) {\n setCachedQmdRecall(qmdCacheKey, result, {\n maxEntries: this.deps.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 reportRecallQmdUnavailable(\"served stale recall cache (qmd phase error)\");\n replayCachedDegradations(staleQmdFallback.value);\n if (queryAwarePrefilterIsEmpty) {\n return emptyQueryAwareQmdResult;\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 () => {\n // The enrichment budget abandoned the hot QMD phase mid-flight\n // (#1536, codex round-7 on #1544): QmdClient treats this abort as\n // caller cancellation and never reports, so report the abandonment\n // deterministically here — the exact mirror of the cold-tier\n // deadline gate. Guarded: a CALLER abort also routes through this\n // cancel callback, and an aborted recall is not a backend\n // degradation (no snapshot is recorded for it anyway).\n if (!options.abortSignal?.aborted) {\n backendDegradations.push({\n backend: \"qmd\",\n code: \"deadline_exceeded\",\n detail: \"hot qmd enrichment abandoned (enrichment deadline)\",\n });\n }\n qmdEnrichmentAbort.cancel();\n },\n );\n\n const transcriptPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !resolvePresentationCapabilities(this.deps.config).transcript ||\n !this.deps.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.deps.getRecallSectionNumber(\"transcript\", \"maxTokens\") ??\n this.deps.config.maxTranscriptTokens;\n const transcriptMaxTurns =\n this.deps.getRecallSectionNumber(\"transcript\", \"maxTurns\") ??\n this.deps.config.maxTranscriptTurns;\n const transcriptLookbackHours =\n this.deps.getRecallSectionNumber(\"transcript\", \"lookbackHours\") ??\n this.deps.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 (resolvePipelineProcessingCapabilities(this.deps.config).checkpoint) {\n const checkpoint = await this.deps.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.deps.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.deps.transcript.clearCheckpoint();\n }\n }\n }\n\n if (!checkpointInjected) {\n const entries = await this.deps.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.deps.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.deps._recallWorkspaceOverrides.get(effectiveSessionKey);\n this.deps._recallWorkspaceOverrides.delete(effectiveSessionKey);\n\n if (!resolveRecallAuxiliaryCapabilities(this.deps.config).compactionReset) return null;\n\n const workspaceDir =\n compactionWorkspaceDir ||\n this.deps.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 !resolvePipelineProcessingCapabilities(this.deps.config).hourlySummaries ||\n !sessionKey ||\n !this.deps.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.deps.getRecallSectionNumber(\"summaries\", \"lookbackHours\") ??\n this.deps.config.summaryRecallHours;\n const summariesMaxCount =\n this.deps.getRecallSectionNumber(\"summaries\", \"maxCount\") ??\n this.deps.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.deps.summarizer.readRecent(\n sessionKey,\n summariesLookbackHours,\n );\n const cappedSummaries = summaries.slice(0, summariesMaxCount);\n const section =\n cappedSummaries.length > 0\n ? this.deps.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.deps.config.nativeKnowledge?.enabled ||\n !this.deps.isRecallSectionEnabled(\n \"native-knowledge\",\n this.deps.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.deps.config.nativeKnowledge.maxResults === 0 ||\n this.deps.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.deps.config.workspaceDir,\n memoryDir: this.deps.config.memoryDir,\n config: this.deps.config.nativeKnowledge,\n recallNamespaces: resolveNamespaceCapabilities(this.deps.config).namespaces\n ? recallNamespaces\n : undefined,\n defaultNamespace: this.deps.config.defaultNamespace,\n abortSignal: nativeKnowledgeAbort.signal,\n }).catch(() => []);\n const results = searchNativeKnowledge({\n query: retrievalQuery,\n chunks,\n maxResults:\n this.deps.getRecallSectionNumber(\"native-knowledge\", \"maxResults\") ??\n this.deps.config.nativeKnowledge.maxResults,\n });\n const section = formatNativeKnowledgeSection({\n results,\n maxChars:\n this.deps.getRecallSectionNumber(\"native-knowledge\", \"maxChars\") ??\n this.deps.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 !resolveIndexingCapabilities(this.deps.config).conversationIndex ||\n queryPolicy.skipConversationRecall ||\n !this.deps.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.deps.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.deps.getRecallSectionNumber(\"conversation-recall\", \"timeoutMs\") ??\n this.deps.config.conversationRecallTimeoutMs,\n );\n const topK = Math.max(\n 1,\n topKOverride ?? this.deps.config.conversationRecallTopK,\n );\n const maxChars = Math.max(\n 400,\n this.deps.getRecallSectionNumber(\"conversation-recall\", \"maxChars\") ??\n this.deps.config.conversationRecallMaxChars,\n );\n\n const results = (await Promise.race([\n this.deps.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.deps.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.deps.config.procedural?.enabled !== true) return null;\n if (!this.deps.isRecallSectionEnabled(\"procedure-recall\", true)) return null;\n try {\n return await buildProcedureRecallSection(\n profileStorage,\n retrievalQuery,\n this.deps.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.deps.compounding ||\n !resolveRecallEnhancementCapabilities(this.deps.config).compoundingInject ||\n !this.deps.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.deps.getRecallSectionNumber(\"compounding\", \"maxPatterns\") ?? 40;\n const maxRubrics =\n this.deps.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.deps.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 = observeEnrichmentPromise(\n this.deps.isRecallSectionEnabled(\n \"memory-boxes\",\n resolvePresentationCapabilities(this.deps.config).memoryBoxes === true,\n ) &&\n resolvePresentationCapabilities(this.deps.config).memoryBoxes &&\n this.deps.config.boxRecallDays > 0\n ? Promise.all(\n profileStorages.map((storage) =>\n this.deps.boxBuilderFor(storage)\n .readRecentBoxes(this.deps.config.boxRecallDays)\n .catch(() => [] as BoxFrontmatter[]),\n ),\n ).then((groups) => {\n const boxes: BoxFrontmatter[] = [];\n const seen = new Set<string>();\n for (const box of groups.flat()) {\n const key = JSON.stringify(box);\n if (seen.has(key)) continue;\n seen.add(key);\n boxes.push(box);\n }\n return boxes.sort((a, b) => {\n const aTime = Date.parse(a.sealedAt ?? \"\");\n const bTime = Date.parse(b.sealedAt ?? \"\");\n const aRank = Number.isFinite(aTime) ? aTime : 0;\n const bRank = Number.isFinite(bTime) ? bTime : 0;\n return bRank - aRank;\n });\n })\n : Promise.resolve([] as BoxFrontmatter[]),\n );\n\n // --- Wait for core sections first, then bounded enrichment ---\n this.deps.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.deps.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 ? this.deps.recallAssemblyClockMs() + 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 - this.deps.recallAssemblyClockMs());\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 const remainingEnrichmentAssemblyMs = (): number | null =>\n enrichmentAssemblyDeadlineAtMs === null\n ? null\n : Math.max(0, enrichmentAssemblyDeadlineAtMs - this.deps.recallAssemblyClockMs());\n\n const awaitAssemblyStep = async <T>(\n name: string,\n task: () => Promise<T>,\n fallback: T,\n ): Promise<T> => {\n if (options.abortSignal?.aborted) {\n log.debug(\n `recall phase-1 assembly [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return fallback;\n }\n\n const timeoutMs = remainingEnrichmentAssemblyMs();\n if (timeoutMs === 0) {\n log.debug(\n `recall phase-1 assembly [${name}]: skipped after shared ${enrichmentSectionDeadlineMs}ms budget expired ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n return fallback;\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n try {\n const result = await (timeoutMs !== null\n ? Promise.race<T | { status: \"timed_out\" }>([\n task(),\n new Promise<{ status: \"timed_out\" }>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve({ status: \"timed_out\" }),\n timeoutMs,\n );\n }),\n ])\n : task());\n if (timeoutHandle) clearTimeout(timeoutHandle);\n if (\n typeof result === \"object\" &&\n result !== null &&\n \"status\" in result &&\n (result as { status?: unknown }).status === \"timed_out\"\n ) {\n log.debug(\n `recall phase-1 assembly [${name}]: timed out within shared ${enrichmentSectionDeadlineMs}ms budget ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n return fallback;\n }\n return result as T;\n } catch (err) {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n log.warn(\n `recall phase-1 assembly [${name}] failed open: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n return fallback;\n }\n };\n\n // --- Phase 2: Assemble sections in correct order ---\n this.deps.profiler.startSpan(\"assembly\", profileTraceId);\n\n // 0. Shared context\n if (sharedCtx)\n this.deps.appendRecallSection(sectionBuckets, \"shared-context\", sharedCtx);\n\n // 0a. Explicit cue evidence\n const explicitCueMaxChars =\n this.deps.getRecallSectionMaxChars(\"explicit-cue\") ??\n this.deps.config.explicitCueRecallMaxChars;\n if (\n resolveRecallEnhancementCapabilities(this.deps.config).explicitCueRecall &&\n this.deps.isRecallSectionEnabled(\"explicit-cue\") &&\n explicitCueMaxChars !== 0 &&\n this.deps.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n try {\n const explicitCueSection = await buildExplicitCueRecallSection({\n engine: this.deps.lcmEngine,\n // #1495 thread 3 + #1505 fallback unification: read across the ordered\n // LCM read key set (primary overlay → coding fallbacks) so a\n // branch-scoped session finds its own explicit-cue evidence even when\n // archived at project/root scope (rule 39). #1505 codex P2: the builder\n // MERGES candidates across every key under its single budget instead of\n // short-circuiting on the first non-empty key.\n sessionIds: lcmReadSessionIds,\n query: retrievalQuery,\n maxChars: explicitCueMaxChars,\n maxReferences:\n this.deps.getRecallSectionNumber(\"explicit-cue\", \"maxResults\") ??\n this.deps.config.explicitCueRecallMaxReferences,\n });\n if (explicitCueSection) {\n this.deps.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 // 0b. Targeted factual evidence. This is query-triggered and lossless:\n // it uses the LCM archive to recover exact numeric facts that broad\n // compressed-history or search sections can crowd out.\n const targetedFactMaxChars =\n this.deps.getRecallSectionMaxChars(\"targeted-facts\") ??\n this.deps.config.targetedFactRecallMaxChars;\n if (\n this.deps.isSpecializedRecallSectionEnabled(\n \"targeted-facts\",\n resolveRecallEnhancementCapabilities(this.deps.config).targetedFactRecall,\n ) &&\n targetedFactMaxChars !== 0 &&\n this.deps.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\" &&\n shouldRecallTargetedFactEvidence(retrievalQuery)\n ) {\n try {\n const targetedFactSection = await buildTargetedFactRecallSection({\n engine: this.deps.lcmEngine,\n // #1495 + #1505 fallback unification: read across the ordered LCM read\n // key set so a branch-scoped session finds its own targeted-fact\n // evidence even when archived at project/root scope. #1505 codex P2: the\n // builder MERGES candidates across every key under its single budget.\n sessionIds: lcmReadSessionIds,\n query: retrievalQuery,\n maxChars: targetedFactMaxChars,\n maxSearchResults:\n this.deps.getRecallSectionNumber(\"targeted-facts\", \"maxResults\") ??\n this.deps.config.targetedFactRecallMaxResults,\n maxScanWindowTurns:\n this.deps.getRecallSectionNumber(\"targeted-facts\", \"maxTurns\") ??\n this.deps.config.targetedFactRecallScanWindowTurns,\n maxScanWindowTokens:\n this.deps.getRecallSectionNumber(\"targeted-facts\", \"maxTokens\") ??\n this.deps.config.targetedFactRecallScanWindowTokens,\n });\n if (targetedFactSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"targeted-facts\",\n targetedFactSection,\n );\n }\n } catch (err) {\n log.debug(`Targeted fact recall assembly error: ${err}`);\n }\n }\n\n // 0c. Focused list/count evidence. This recovers user-specific list\n // candidates and countable facts that are easy to bury in broad search\n // results, while staying gated to explicit list/count/recommendation\n // prompts.\n const focusedListMaxChars =\n this.deps.getRecallSectionMaxChars(\"focused-list\") ??\n this.deps.config.focusedListRecallMaxChars;\n if (\n this.deps.isSpecializedRecallSectionEnabled(\n \"focused-list\",\n resolveRecallEnhancementCapabilities(this.deps.config).focusedListRecall,\n ) &&\n focusedListMaxChars !== 0 &&\n this.deps.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\" &&\n shouldRecallFocusedListEvidence(retrievalQuery)\n ) {\n try {\n const focusedListSection = await buildFocusedListRecallSection({\n engine: this.deps.lcmEngine,\n // #1495 thread 3 + #1505 fallback unification: read across the ordered\n // LCM read key set so a branch-scoped session reads its own\n // focused-list/count evidence even at project/root scope (rule 39).\n // #1505 codex P2: the builder MERGES candidates across every key under\n // its single budget.\n sessionIds: lcmReadSessionIds,\n query: retrievalQuery,\n maxChars: focusedListMaxChars,\n maxSearchResults:\n this.deps.getRecallSectionNumber(\"focused-list\", \"maxResults\") ??\n this.deps.config.focusedListRecallMaxResults,\n maxScanWindowTurns:\n this.deps.getRecallSectionNumber(\"focused-list\", \"maxTurns\") ??\n this.deps.config.focusedListRecallScanWindowTurns,\n maxScanWindowTokens:\n this.deps.getRecallSectionNumber(\"focused-list\", \"maxTokens\") ??\n this.deps.config.focusedListRecallScanWindowTokens,\n });\n if (focusedListSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"focused-list\",\n focusedListSection,\n );\n }\n } catch (err) {\n log.debug(`Focused list recall assembly error: ${err}`);\n }\n }\n\n // 0d. Response guidance evidence. This recovers durable user\n // instructions and preferences that affect how an answer should be shaped\n // for the current query, such as requested date formats, tool/version\n // details, or preferred editing workflows.\n const responseGuidanceMaxChars =\n this.deps.getRecallSectionMaxChars(\"response-guidance\") ??\n this.deps.config.responseGuidanceRecallMaxChars;\n const responseGuidanceEntry = this.deps.getRecallSectionEntry(\"response-guidance\");\n const responseGuidanceMatchesQuery = shouldRecallResponseGuidance(retrievalQuery);\n const responseGuidanceForcedByPipeline =\n responseGuidanceEntry?.forceGeneric === true && !responseGuidanceMatchesQuery;\n if (\n this.deps.isSpecializedRecallSectionEnabled(\n \"response-guidance\",\n resolveRecallEnhancementCapabilities(this.deps.config).responseGuidanceRecall,\n ) &&\n responseGuidanceMaxChars !== 0 &&\n this.deps.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\" &&\n (responseGuidanceMatchesQuery || responseGuidanceForcedByPipeline)\n ) {\n try {\n const responseGuidanceSection = await buildResponseGuidanceRecallSection({\n engine: this.deps.lcmEngine,\n // #1495 thread 3 + #1505 fallback unification: read across the ordered\n // LCM read key set so a branch-scoped session reads its own\n // response-guidance evidence even at project/root scope (rule 39).\n // #1505 codex P2: the builder MERGES candidates across every key under\n // its single budget.\n sessionIds: lcmReadSessionIds,\n query: retrievalQuery,\n maxChars: responseGuidanceMaxChars,\n maxSearchResults:\n this.deps.getRecallSectionNumber(\"response-guidance\", \"maxResults\") ??\n this.deps.config.responseGuidanceRecallMaxResults,\n maxScanWindowTurns:\n this.deps.getRecallSectionNumber(\"response-guidance\", \"maxTurns\") ??\n this.deps.config.responseGuidanceRecallScanWindowTurns,\n maxScanWindowTokens:\n this.deps.getRecallSectionNumber(\"response-guidance\", \"maxTokens\") ??\n this.deps.config.responseGuidanceRecallScanWindowTokens,\n forceGeneric: responseGuidanceForcedByPipeline,\n });\n if (responseGuidanceSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"response-guidance\",\n responseGuidanceSection,\n );\n }\n } catch (err) {\n log.debug(`Response guidance recall assembly error: ${err}`);\n }\n }\n\n // 0e. Chronological event-order evidence. This recovers ordered user\n // turns for prompts asking how topics unfolded across a conversation.\n const eventOrderMaxChars =\n this.deps.getRecallSectionMaxChars(\"event-order\") ??\n this.deps.config.eventOrderRecallMaxChars;\n if (\n this.deps.isSpecializedRecallSectionEnabled(\n \"event-order\",\n resolveRecallEnhancementCapabilities(this.deps.config).eventOrderRecall,\n ) &&\n eventOrderMaxChars !== 0 &&\n this.deps.lcmEngine?.enabled &&\n (recallMode as RecallPlanMode) !== \"no_recall\" &&\n shouldRecallEventOrderEvidence(retrievalQuery)\n ) {\n try {\n // #1495 thread 3 + #1505 fallback unification: read across the ordered LCM\n // read key set so a branch-scoped session reads its own chronological\n // event-order evidence even at project/root scope. UNLIKE the relevance-\n // ranked sections, event-order must NOT merge across keys: `turn_index` is\n // LOCAL to each LCM `session_id` (`observe` numbers turns per session via\n // `getMaxTurnIndex`), so interleaving two keys and sorting by `turn_index`\n // would place an older project-scope turn after a newer branch-scope turn\n // and misstate the chronology (#1505 codex P2). Like compressed-history,\n // event-order is an inherently per-session ORDERED artifact, so it takes\n // the highest-priority authorized key (primary overlay → project/root)\n // that actually has chronological evidence — each key's timeline is\n // internally consistent.\n const eventOrderSection = await firstNonEmptyLcmRead(\n (lcmSessionId) =>\n buildEventOrderRecallSection({\n engine: this.deps.lcmEngine,\n sessionId: lcmSessionId,\n query: retrievalQuery,\n maxChars: eventOrderMaxChars,\n maxItems:\n this.deps.getRecallSectionNumber(\"event-order\", \"maxResults\") ??\n this.deps.config.eventOrderRecallMaxResults,\n maxScanWindowTurns:\n this.deps.getRecallSectionNumber(\"event-order\", \"maxTurns\") ??\n this.deps.config.eventOrderRecallScanWindowTurns,\n maxScanWindowTokens:\n this.deps.getRecallSectionNumber(\"event-order\", \"maxTokens\") ??\n this.deps.config.eventOrderRecallScanWindowTokens,\n }),\n (s) => !s,\n \"\",\n );\n if (eventOrderSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"event-order\",\n eventOrderSection,\n );\n }\n } catch (err) {\n log.debug(`Event order recall assembly error: ${err}`);\n }\n }\n\n // 1. Profile\n if (profile)\n this.deps.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.deps.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.deps.appendRecallSection(\n sectionBuckets,\n \"calibration-rules\",\n calibrationSection,\n );\n }\n\n if (procedureRecallSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"procedure-recall\",\n procedureRecallSection,\n );\n }\n\n // 1a. Identity continuity\n if (identityContinuity) {\n this.deps.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.deps.appendRecallSection(\n sectionBuckets,\n \"entity-retrieval\",\n entityRetrievalSection,\n );\n }\n\n // 1b. Knowledge Index\n if (kiResult?.result) {\n this.deps.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.deps.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.deps.truncateArtifactForRecall(a.content)}\" (${created})`;\n });\n this.deps.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 awaitEnrichmentSection(\n \"memory-boxes\",\n recentBoxesPromise,\n );\n if (recentBoxes && 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.deps.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.deps.isRecallSectionEnabled(\n \"temporal-memory-tree\",\n lifecycleCaps.temporalMemoryTree,\n ) &&\n lifecycleCaps.temporalMemoryTree &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n const tmtNode = await this.deps.tmtBuilder.getMostRelevantNode();\n if (tmtNode) {\n const levelLabel =\n tmtNode.level.charAt(0).toUpperCase() + tmtNode.level.slice(1);\n this.deps.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.deps.lcmEngine?.enabled &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n try {\n // #1495 + #1505 fallback unification: read across the ordered LCM read\n // key set so a branch-scoped session reads its own structured\n // message-part evidence even when archived at project/root scope.\n // #1505 codex P2: structured matches are query-SCORED evidence, so MERGE\n // across EVERY key (primary overlay → project/root fallbacks) instead of\n // short-circuiting on the first non-empty key — a weak branch-key hit must\n // not mask stronger project-fallback parts. Keys are queried in priority\n // order; dedupe by session_id+turn_index+part_id keeps the primary key's\n // row on collision. `formatStructuredRecall` applies the single budget\n // below. A sessionless key (`undefined`) normalizes to \"\" → no matches\n // (structured parts are inherently per-session; pre-#1505 behavior, codex\n // P2).\n // FAULT ISOLATION (allSettled, not all): the pre-#1505 first-non-empty read\n // short-circuited, so a fallback key was often never queried and its latent\n // search failure never surfaced. Querying every key eagerly must NOT let one\n // key's failure (e.g. a SqliteError from a corrupt/locked fallback index)\n // reject the batch and discard the OTHER keys' parts — or, since this and\n // the compressed-history read below share one try block, silently drop the\n // compressed-history section a healthy primary key would still produce. So\n // read each key independently and keep the fulfilled batches.\n const structuredSettled = await Promise.allSettled(\n lcmReadSessionIds.map((lcmSessionId) =>\n this.deps.lcmEngine!.searchStructuredParts(lcmSessionId ?? \"\", retrievalQuery),\n ),\n );\n for (const settled of structuredSettled) {\n if (settled.status === \"rejected\") {\n log.debug(\n `LCM structured-parts read failed for one key: ${settled.reason}`,\n );\n }\n }\n const seenStructuredParts = new Set<string>();\n const structuredMatches = structuredSettled\n .flatMap((settled) => (settled.status === \"fulfilled\" ? settled.value : []))\n .filter((match) => {\n const key = `${match.session_id} ${match.turn_index} ${match.part_id}`;\n if (seenStructuredParts.has(key)) return false;\n seenStructuredParts.add(key);\n return true;\n })\n // Restore the archive's per-key ordering (score DESC, then turn DESC)\n // across the MERGED set so the strongest parts win the shared budget in\n // `formatStructuredRecall` — otherwise weak primary-key parts could crowd\n // out stronger fallback parts. Stable sort: a single key is already in\n // this order, so it stays byte-for-byte the pre-#1505 behavior.\n // `?? 0` is defensive: `LcmStructuredRecallMatch.score` is always a\n // number here, but a bare `b.score - a.score` would yield NaN (falsy)\n // for any future unscored match and silently fall through to turn order.\n .sort(\n (a, b) =>\n (b.score ?? 0) - (a.score ?? 0) || b.turn_index - a.turn_index,\n );\n const structuredSection = this.deps.lcmEngine.formatStructuredRecall(\n structuredMatches,\n Math.ceil(this.deps.config.recallBudgetChars * 0.08),\n );\n if (structuredSection) {\n const structuredAppended = this.deps.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 // #1495 + #1505 fallback unification: read across the ordered LCM read key\n // set so a branch-scoped session reads its own compressed-history evidence\n // even at project/root scope. UNLIKE the query-scored sections above, the\n // compressed history is a per-session HOLISTIC DAG narrative, not a set of\n // independently-rankable evidence items — concatenating two sessions'\n // summaries would double-count the conversation and blow the budget, and\n // there is no per-item id to dedupe on. So this section deliberately keeps\n // first-non-empty semantics (#1505 codex P2 scope: \"merge the query-matched\n // sections\"): the highest-priority authorized key (primary overlay →\n // project/root) that actually has a compressed history wins. A sessionless\n // key (`undefined`) normalizes to empty → no section (pre-#1505 behavior).\n const lcmSection = await firstNonEmptyLcmRead(\n (lcmSessionId) =>\n this.deps.lcmEngine!.assembleRecall(\n lcmSessionId ?? \"\",\n this.deps.config.recallBudgetChars,\n ),\n (s) => !s,\n \"\",\n );\n if (lcmSection) {\n this.deps.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.deps.appendRecallSection(\n sectionBuckets,\n \"objective-state\",\n objectiveStateSection,\n );\n }\n\n if (causalTrajectorySection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"causal-trajectories\",\n causalTrajectorySection,\n );\n }\n\n if (cmcCausalChainsSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"cmc-causal-chains\",\n cmcCausalChainsSection,\n );\n }\n\n if (trustZoneSection) {\n this.deps.appendRecallSection(sectionBuckets, \"trust-zones\", trustZoneSection);\n }\n\n const harmonicRetrievalSection = await awaitEnrichmentSection(\n \"harmonic\",\n harmonicRetrievalPromise,\n );\n if (harmonicRetrievalSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"harmonic-retrieval\",\n harmonicRetrievalSection,\n );\n }\n\n if (verifiedRecallSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"verified-episodes\",\n verifiedRecallSection,\n );\n }\n\n if (verifiedRulesSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"verified-rules\",\n verifiedRulesSection,\n );\n }\n\n if (workProductsSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"work-products\",\n workProductsSection,\n );\n }\n\n // 2. QMD results — post-process and format\n const qmdWasSettledBeforeAssemblyWait =\n qmdPromise.getSettledOutcome() !== undefined;\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 (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n memoryResults = memoryResults.filter((r) =>\n recallNamespaces.includes(this.deps.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 graphCaps.multiGraphMemory &&\n caps.graphAssistInFullMode &&\n recallMode === \"full\" &&\n memoryResults.length >=\n Math.max(1, this.deps.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n recallMode === \"graph_mode\" || isFullModeGraphAssist;\n const graphShadowEvalEnabled =\n isFullModeGraphAssist &&\n resolveRecallEnhancementCapabilities(this.deps.config).graphAssistShadowEval === 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 graphExpansion = await awaitAssemblyStep(\n \"graph-expansion\",\n () =>\n this.deps.expandResultsViaGraph({\n memoryResults,\n recallNamespaces,\n recallResultLimit,\n deadlineAtMs: enrichmentAssemblyDeadlineAtMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n }),\n null as Awaited<ReturnType<typeof this.deps.expandResultsViaGraph>> | null,\n );\n if (!graphExpansion) {\n graphSnapshotStatus = \"aborted\";\n graphDecisionStatus = \"aborted\";\n graphDecisionReason = options.abortSignal?.aborted\n ? \"graph expansion skipped because recall assembly was aborted\"\n : \"graph expansion skipped because shared post-retrieval assembly budget expired\";\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = baselineMemoryResults\n .slice(0, Math.max(1, recallResultLimit))\n .map((result) => result.path);\n graphSnapshotSeedResults = this.deps.buildGraphRecallRankedResults(\n baselineMemoryResults,\n () => [\"baseline\"],\n );\n graphSnapshotExpandedPaths = [];\n graphExpandedResultPaths.clear();\n memoryResults = baselineMemoryResults;\n } else {\n const {\n merged,\n seedPaths,\n expandedPaths,\n seedResults = baselineMemoryResults,\n } = graphExpansion;\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.deps.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 }\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.deps.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 mandatory recall safety filters before deadline-bound scoring\n // enrichment. If scoring times out, we must fall back to this filtered\n // list rather than raw QMD hits; boostSearchResults also removes\n // forgotten, lifecycle-filtered, superseded/as_of-invalid, and\n // dream/procedural memories.\n const qmdBoostInput = await this.deps.filterSearchResultsForRecall(\n memoryResults,\n undefined,\n {\n asOfMs,\n // If QMD had already settled before the ordered assembly reached it,\n // do not let unrelated slow enrichment turn those known results into\n // unchecked misses. QMD that only settles during its own wait remains\n // bounded by the shared post-retrieval assembly deadline.\n deadlineAtMs: qmdWasSettledBeforeAssemblyWait\n ? null\n : enrichmentAssemblyDeadlineAtMs,\n abortSignal: options.abortSignal,\n dropUnresolved: true,\n recallNamespaces,\n },\n );\n\n // Apply recency and access count boosting\n memoryResults = await awaitAssemblyStep(\n \"qmd-boost\",\n () =>\n this.deps.boostSearchResults(\n qmdBoostInput.results,\n recallNamespaces,\n retrievalQuery,\n qmdBoostInput.memoryByPath,\n { asOfMs },\n ),\n qmdBoostInput.results,\n );\n\n // Optional LLM reranking (default off). Fail-open if rerank fails/slow.\n if (caps.rerank && this.deps.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: retrievalQuery,\n candidates: memoryResults\n .slice(0, this.deps.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.deps.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.deps.config.rerankTimeoutMs,\n maxCandidates: this.deps.config.rerankMaxCandidates,\n cache: this.deps.rerankCache,\n cacheEnabled: caps.rerankCache,\n cacheTtlMs: this.deps.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 (caps.rerank && this.deps.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Trust-reweighting stage. TrustScore (issue #1577) SUBSUMES the Memory\n // Worth multiplier — exactly one runs (rule 39; the double-multiplier\n // test in trust-score-stage.test.ts pins it structurally). Applied on\n // EVERY recall path via applyTrustScoreToBranch so the gate is consistent\n // (rule 41 parity). Fail-open on lookup errors so recall never breaks.\n {\n const trustOutcome = await this.deps.applyTrustScoreToBranch(\n memoryResults,\n recallNamespaces,\n caps,\n \"hot-qmd\",\n );\n memoryResults = trustOutcome.results;\n recallTrustByPath = trustOutcome.trustByPath;\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 (caps.recallConfidenceGate && effectiveGateScore > 0) {\n if (effectiveGateScore < this.deps.config.recallConfidenceGateThreshold) {\n log.debug(\n `recall: confidence gate rejected ${memoryResults.length} results (effective score ${effectiveGateScore.toFixed(3)} below ${this.deps.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.deps.diversifyAndLimitRecallResults(\n \"memories\",\n memoryResults,\n recallResultLimit,\n retrievalQuery,\n caps,\n );\n\n // E-Mem-inspired memory reconstruction: fill gaps for referenced entities\n if (resolveRecallEnhancementCapabilities(this.deps.config).memoryReconstruction && 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.deps.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.deps.buildGraphRecallRankedResults(\n memoryResults,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_qmd\";\n recalledMemoryCount = memoryResults.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.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 if (queryAwarePrefilter.candidatePaths?.size !== 0) {\n let scoped = await awaitAssemblyStep(\n \"embedding-fallback\",\n async () => {\n const embeddingResults = await this.deps.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: resolveNamespaceCapabilities(this.deps.config).namespaces,\n recallNamespaces,\n resolveNamespace: (p) => this.deps.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.deps.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 return this.deps.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n caps,\n );\n },\n [] as QmdSearchResult[],\n );\n // Issue #1577 — apply TrustScore on the embedding-fallback path so the\n // feature gate is consistent across ALL recall paths (rule 41 parity).\n {\n const trustOutcome = await this.deps.applyTrustScoreToBranch(\n scoped,\n recallNamespaces,\n caps,\n \"embedding-fallback\",\n );\n scoped = trustOutcome.results;\n recallTrustByPath = trustOutcome.trustByPath;\n }\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.deps.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.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.deps.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n caps,\n graphCaps,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n onDegradation: (degradation) => {\n backendDegradations.push(degradation);\n },\n xrayPoolSizeSink: xrayColdPoolSink,\n trustByPathSink,\n deadlineAtMs: enrichmentAssemblyDeadlineAtMs,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n // Issue #1577 — read the cold pipeline's trust map back so cold\n // results feed X-ray + epistemic rendering + publisher quarantine\n // filtering (rule 41 parity; review: the sink was never read back).\n recallTrustByPath = trustByPathSink.trustByPath;\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.deps.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n }\n }\n }\n\n if (globalResults.length > 0) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"workspace-context\",\n this.deps.formatQmdResults(\"Workspace Context\", globalResults, sessionKey, recallTrustByPath),\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.deps.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.deps.qmd.isAvailable()) {\n // Fallback: embeddings first, then recency-only.\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n if (queryAwarePrefilter.candidatePaths?.size !== 0) {\n let scoped = await awaitAssemblyStep(\n \"embedding-fallback\",\n async () => {\n const embeddingResults = await this.deps.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: resolveNamespaceCapabilities(this.deps.config).namespaces,\n recallNamespaces,\n resolveNamespace: (p) => this.deps.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.deps.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 return this.deps.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n caps,\n );\n },\n [] as QmdSearchResult[],\n );\n // Issue #1577 — apply TrustScore on the embedding-fallback path so the\n // feature gate is consistent across ALL recall paths (rule 41 parity).\n {\n const trustOutcome = await this.deps.applyTrustScoreToBranch(\n scoped,\n recallNamespaces,\n caps,\n \"embedding-fallback\",\n );\n scoped = trustOutcome.results;\n recallTrustByPath = trustOutcome.trustByPath;\n }\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.deps.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.extractMemoryIdsFromResults(scoped);\n recalledMemoryPaths = scoped\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = scoped;\n impressionRecorded = true;\n } else {\n const memories = await awaitAssemblyStep(\n \"recent-memory-read\",\n () => this.deps.readAllMemoriesForNamespaces(recallNamespaces),\n [] as MemoryFile[],\n );\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: lifecycleCaps.temporalSupersession,\n includeInRecall: this.deps.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.deps.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n caps,\n graphCaps,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n onDegradation: (degradation) => {\n backendDegradations.push(degradation);\n },\n xrayPoolSizeSink: xrayColdPoolSink,\n trustByPathSink,\n deadlineAtMs: enrichmentAssemblyDeadlineAtMs,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n // Issue #1577 — read the cold pipeline's trust map back (rule 41).\n recallTrustByPath = trustByPathSink.trustByPath;\n if (longTerm.length > 0) {\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n } else {\n let recent = await awaitAssemblyStep(\n \"recent-memory-scan\",\n async () => {\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.deps.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 return this.deps.diversifyAndLimitRecallResults(\n \"memories\",\n boostedRecent,\n recallResultLimit,\n retrievalQuery,\n caps,\n );\n },\n [] as QmdSearchResult[],\n );\n // Issue #1577 — apply TrustScore on the recent-scan path so the\n // feature gate is consistent across ALL recall paths (rule 41).\n {\n const trustOutcome = await this.deps.applyTrustScoreToBranch(\n recent,\n recallNamespaces,\n caps,\n \"recent-scan\",\n );\n recent = trustOutcome.results;\n recallTrustByPath = trustOutcome.trustByPath;\n }\n\n if (recent.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.deps.buildGraphRecallRankedResults(\n recent,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"recent_scan\";\n recalledMemoryCount = recent.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.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.deps.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n caps,\n graphCaps,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n onDegradation: (degradation) => {\n backendDegradations.push(degradation);\n },\n xrayPoolSizeSink: xrayColdPoolSink,\n trustByPathSink,\n deadlineAtMs: enrichmentAssemblyDeadlineAtMs,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n // Issue #1577 — read the cold pipeline's trust map back (rule 41).\n recallTrustByPath = trustByPathSink.trustByPath;\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults =\n this.deps.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.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.deps.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n caps,\n graphCaps,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n onDegradation: (degradation) => {\n backendDegradations.push(degradation);\n },\n xrayPoolSizeSink: xrayColdPoolSink,\n trustByPathSink,\n deadlineAtMs: enrichmentAssemblyDeadlineAtMs,\n asOfMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n // Issue #1577 — read the cold pipeline's trust map back (rule 41).\n recallTrustByPath = trustByPathSink.trustByPath;\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.deps.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.deps.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 trustByPath: recallTrustByPath,\n });\n recalledMemoryIds = this.deps.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n xrayRecalledResults = longTerm;\n impressionRecorded = true;\n }\n }\n }\n }\n\n if (isDisagreementPrompt(prompt)) {\n this.deps.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.deps.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.deps.recordLastIntentSnapshot({\n storage: profileStorage,\n snapshot: buildIntentDebugSnapshot(),\n });\n\n // 2.5. Compression guideline recall section (v8.11 Task 5)\n if (\n this.deps.isRecallSectionEnabled(\n \"compression-guidelines\",\n resolveCompressionCapabilities(this.deps.config).compressionGuidelineLearning === true,\n )\n ) {\n const compressionGuidelineSection =\n await this.deps.buildCompressionGuidelineRecallSection();\n if (compressionGuidelineSection) {\n this.deps.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.deps.appendRecallSection(sectionBuckets, \"transcript\", transcriptSection);\n }\n // Compaction reset context — independent section so it works even when transcript is disabled.\n if (compactionSection) {\n this.deps.appendRecallSection(\n sectionBuckets,\n \"compaction-reset\",\n compactionSection,\n );\n }\n if (summariesSection) {\n this.deps.appendRecallSection(sectionBuckets, \"summaries\", summariesSection);\n }\n if (conversationRecallSection) {\n this.deps.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.deps.appendRecallSection(\n sectionBuckets,\n \"compounding\",\n compoundingSection,\n );\n }\n\n // 5. Inject most relevant question (if enabled) (existing)\n if (\n this.deps.config.injectQuestions &&\n this.deps.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.deps.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.deps.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.deps.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.deps.collectLastRecallSources(\n sectionBuckets,\n recallSource,\n );\n const budgetsApplied = this.deps.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 const resultNamespace = this.deps.namespaceFromPath(recalledPath);\n let provenance: RecallXrayResult[\"provenance\"] | undefined;\n let sourceSpan: RecallXrayResult[\"sourceSpan\"] | undefined;\n try {\n const resultStorage =\n await this.deps.storageRouter.storageFor(resultNamespace);\n const memory = await resultStorage.readMemoryByPath(recalledPath);\n if (memory) {\n provenance = buildRetrievedMemoryProvenance(memory, {\n namespace: resultNamespace,\n retrievalReason: `served-by=${servedBy}`,\n currentContextScopes: options.currentContextScopes,\n });\n // Claim-level provenance span (#1575 PR 3): surface the first\n // source excerpt so the X-ray shows the literal utterance this\n // fact derives from. Thin read from already-loaded frontmatter.\n const fm = memory.frontmatter;\n if (fm.sources && fm.sources.length > 0) {\n sourceSpan = {\n quote: fm.sources[0]!.quote,\n observedAt: fm.sources[0]!.observedAt,\n provenance: fm.provenance ?? \"none\",\n };\n }\n }\n } catch {\n // X-ray capture is best-effort; missing provenance must not\n // perturb recall or suppress the surfaced result.\n }\n const trustItem = recallTrustByPath?.get(recalledPath);\n results.push({\n memoryId: derivedId,\n path: recalledPath,\n servedBy,\n scoreDecomposition,\n admittedBy: [],\n ...(provenance ? { provenance } : {}),\n ...(sourceSpan ? { sourceSpan } : {}),\n // Issue #1577 — per-result trust projection for X-ray visibility.\n ...(trustItem ? { trust: projectTrustForXray(trustItem) } : {}),\n });\n }\n // Issue #1577 — surface quarantined items in X-ray with their exclusion\n // reason so operators see WHY a memory was dropped (rule 34 — exclusion\n // must never look like \"no result\"). These are NOT in recalledMemoryPaths\n // (they were excluded from injection) but ARE in the trust map.\n if (recallTrustByPath) {\n for (const [qPath, qItem] of recallTrustByPath) {\n if (!qItem.quarantined || recalledMemoryPaths.includes(qPath)) continue;\n const qId = idFromPath(qPath);\n if (!qId) continue;\n results.push({\n memoryId: qId,\n path: qPath,\n servedBy,\n scoreDecomposition: { final: 0 },\n admittedBy: [],\n rejectedBy: \"trust-score:quarantine\",\n trust: projectTrustForXray(qItem),\n });\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.deps.lastXraySnapshot = buildXraySnapshot({\n query: retrievalQuery,\n tierExplain: null,\n results: [...results, ...lcmStructuredXrayResults],\n filters,\n budget: {\n chars: this.deps.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.deps.lastRecall\n .record({\n sessionKey,\n query: retrievalQuery,\n memoryIds: recalledMemoryIds,\n namespace: selfNamespace,\n recallNamespaces,\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.deps.config.recordEmptyRecallImpressions,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n // Included at record time so the published snapshot is born\n // annotated — a post-record annotation leaves a window where\n // readers see the snapshot without degradations, and a concurrent\n // same-session recall could drop them entirely (codex + cursor\n // reviews on #1544).\n backendDegradations:\n backendDegradations.length > 0 ? backendDegradations : undefined,\n })\n .catch((err) => log.debug(`last recall record failed: ${err}`));\n // Issue #1582 — record the admitted memory-id set for handle resolution.\n // Only when handles are enabled: if injection is off, no handle is ever\n // rendered, so there is nothing to resolve and we skip the write.\n if (this.deps.config.recallMemoryHandles && recalledMemoryIds.length > 0) {\n // Only handle-eligible ids aid resolution; filter out non-memory .md\n // basenames (entity reconstructions) so the resolver never records a\n // citation target that cannot be loaded.\n const handleEligibleIds = recalledMemoryIds.filter((id) =>\n MEMORY_ID_PATTERN.test(id),\n );\n if (handleEligibleIds.length > 0) {\n this.deps.handleHistory\n .record(sessionKey, handleEligibleIds)\n .catch((err) => log.debug(`handle history record failed: ${err}`));\n }\n }\n }\n if (sessionKey) {\n this.deps.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.deps.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: resolveQmdCapabilities(this.deps.config).qmd,\n qmdAvailable: this.deps.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.deps.config.traceRecallContent && context.length > 0\n ? context\n : undefined,\n });\n\n return context;\n } finally {\n closeProfileTrace();\n }\n }\n}\n","/**\n * Graph-recall coordinator — extracted from the orchestrator (issue #1526).\n *\n * Owns the graph-expansion subsystem in recall: spreading-activation\n * traversal from seed memories, seed-path resolution relative to\n * per-namespace storage, and the last-graph-recall snapshot persistence.\n * Behavior-preserving move from orchestrator.ts — no logic changes; the\n * orchestrator constructs one instance and keeps thin delegating methods so\n * existing call sites (recallInternal, cold-fallback pipeline) continue to\n * work.\n *\n * Config, storage, graph index, namespace resolution, and QMD result\n * resolution are accessed through getter callbacks (not captured at\n * construction) so that post-construction reassignment of the orchestrator's\n * live fields is honored. This mirrors the RecallRerankCoordinator /\n * ContradictionLinkingCoordinator accessor pattern.\n */\n\nimport type {\n MemoryFile,\n MemoryIntent,\n PluginConfig,\n QmdSearchResult,\n RecallPlanMode,\n} from \"../types.js\";\nimport type { StorageManager } from \"../index.js\";\nimport type { GraphIndex } from \"../graph.js\";\nimport type { GraphRecallExpandedEntry } from \"../recall-state.js\";\nimport { clampGraphRecallExpandedEntries } from \"../recall-state.js\";\nimport { qmdCollectionPathParts } from \"./qmd-result-resolver.js\";\nimport { log } from \"../logger.js\";\nimport { createHash } from \"node:crypto\";\nimport { mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\n// ---------------------------------------------------------------------------\n// Types (moved from orchestrator.ts; re-exported by the orchestrator barrel)\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\n// ---------------------------------------------------------------------------\n// Utility functions (moved from orchestrator.ts; re-exported for callers)\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\n// ---------------------------------------------------------------------------\n// Coordinator\n// ---------------------------------------------------------------------------\n\nexport class GraphRecallCoordinator {\n private readonly getConfig: () => PluginConfig;\n private readonly getStorage: () => StorageManager;\n private readonly storageFor: (namespace: string) => Promise<StorageManager>;\n private readonly graphIndexFor: (storage: StorageManager) => GraphIndex;\n private readonly namespaceFromPath: (p: string) => string;\n private readonly resolveColdQmdResultForRecall: (\n result: QmdSearchResult,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<{ namespace: string; result: QmdSearchResult } | null>;\n private readonly storageForAbsoluteQmdResultPath: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<{ storage: StorageManager; dir: string; namespace: string } | null>;\n private readonly readQmdResultMemory: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<MemoryFile | null>;\n\n constructor(options: {\n getConfig: () => PluginConfig;\n getStorage: () => StorageManager;\n storageFor: (namespace: string) => Promise<StorageManager>;\n graphIndexFor: (storage: StorageManager) => GraphIndex;\n namespaceFromPath: (p: string) => string;\n resolveColdQmdResultForRecall: (\n result: QmdSearchResult,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<{ namespace: string; result: QmdSearchResult } | null>;\n storageForAbsoluteQmdResultPath: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<{ storage: StorageManager; dir: string; namespace: string } | null>;\n readQmdResultMemory: (\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces: readonly string[],\n ) => Promise<MemoryFile | null>;\n }) {\n this.getConfig = options.getConfig;\n this.getStorage = options.getStorage;\n this.storageFor = options.storageFor;\n this.graphIndexFor = options.graphIndexFor;\n this.namespaceFromPath = options.namespaceFromPath;\n this.resolveColdQmdResultForRecall = options.resolveColdQmdResultForRecall;\n this.storageForAbsoluteQmdResultPath = options.storageForAbsoluteQmdResultPath;\n this.readQmdResultMemory = options.readQmdResultMemory;\n }\n\n async expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n deadlineAtMs?: number | null;\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 config = this.getConfig();\n const deadlineExpired = (): boolean =>\n typeof options.deadlineAtMs === \"number\" &&\n Date.now() >= options.deadlineAtMs;\n const byNamespace = new Map<string, QmdSearchResult[]>();\n const addResultForNamespace = (\n namespace: string,\n result: QmdSearchResult,\n ): void => {\n const existing = byNamespace.get(namespace);\n if (existing) {\n existing.push(result);\n } else {\n byNamespace.set(namespace, [result]);\n }\n };\n const resolvedAmbiguousSeeds = new Map<\n string,\n { namespace: string; result: QmdSearchResult } | null\n >();\n const resolveAmbiguousSeedOwner = async (\n result: QmdSearchResult,\n parts: { collection: string; relativePath: string } | null,\n ): Promise<{ namespace: string; result: QmdSearchResult } | null> => {\n const cached = resolvedAmbiguousSeeds.get(result.path);\n if (cached !== undefined) return cached;\n if (deadlineExpired()) {\n resolvedAmbiguousSeeds.set(result.path, null);\n return null;\n }\n\n let resolvedPath = result.path;\n let resolvedResult = result;\n if (parts) {\n const resolvedCold = await this.resolveColdQmdResultForRecall(\n result,\n this.getStorage(),\n options.recallNamespaces,\n );\n if (!resolvedCold || deadlineExpired()) {\n resolvedAmbiguousSeeds.set(result.path, null);\n return null;\n }\n resolvedPath = resolvedCold.result.path;\n resolvedResult = resolvedCold.result;\n }\n\n if (!path.isAbsolute(resolvedPath)) {\n resolvedAmbiguousSeeds.set(result.path, null);\n return null;\n }\n const ownerStorage = await this.storageForAbsoluteQmdResultPath(\n resolvedPath,\n this.getStorage(),\n options.recallNamespaces,\n );\n const ownerNamespace = ownerStorage?.namespace ?? null;\n const resolved =\n ownerNamespace && options.recallNamespaces.includes(ownerNamespace)\n ? { namespace: ownerNamespace, result: resolvedResult }\n : null;\n resolvedAmbiguousSeeds.set(result.path, resolved);\n return resolved;\n };\n const coldCollection = config.qmdColdCollection ?? \"openclaw-engram-cold\";\n for (const result of options.memoryResults) {\n if (deadlineExpired()) break;\n const parts = qmdCollectionPathParts(result.path);\n if (parts?.collection === coldCollection) {\n const resolved = await resolveAmbiguousSeedOwner(result, parts);\n if (resolved) {\n addResultForNamespace(resolved.namespace, resolved.result);\n }\n continue;\n }\n if (path.isAbsolute(result.path)) {\n const resolved = await resolveAmbiguousSeedOwner(result, null);\n if (resolved) {\n addResultForNamespace(resolved.namespace, resolved.result);\n }\n continue;\n }\n const ns = this.namespaceFromPath(result.path);\n if (!options.recallNamespaces.includes(ns)) continue;\n addResultForNamespace(ns, result);\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 if (deadlineExpired()) break;\n const storage = await this.storageFor(namespace);\n const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);\n seedResults.push(...seedCandidates);\n const seedRelativePaths =\n typeof options.deadlineAtMs === \"number\"\n ? await this.graphSeedPathsWithinDeadline(\n storage,\n seedCandidates,\n options.deadlineAtMs,\n [namespace],\n )\n : (\n await Promise.all(\n seedCandidates.map((result) =>\n this.graphSeedPathRelativeToStorage(storage, result, [\n namespace,\n ]),\n ),\n )\n ).filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n );\n if (deadlineExpired()) break;\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 config.maxGraphTraversalSteps,\n {\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n ...(typeof options.deadlineAtMs === \"number\"\n ? { deadlineAtMs: options.deadlineAtMs }\n : {}),\n },\n );\n if (expanded.length === 0) continue;\n if (deadlineExpired()) break;\n\n for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {\n if (deadlineExpired()) break;\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 (deadlineExpired()) break;\n if (!memory) continue;\n if (/(?:^|[\\\\/])artifacts(?:[\\\\/]|$)/i.test(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: config.graphExpansionActivationWeight,\n blendMin: config.graphExpansionBlendMin,\n blendMax: 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 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 graphSeedPathRelativeToStorage(\n storage: StorageManager,\n result: QmdSearchResult,\n recallNamespaces: readonly string[] = [],\n ): Promise<string | null> {\n const parts = qmdCollectionPathParts(result.path);\n if (parts) {\n const memory = await this.readQmdResultMemory(\n result.path,\n storage,\n recallNamespaces,\n );\n return memory\n ? graphPathRelativeToStorage(storage.dir, memory.path)\n : null;\n }\n return graphPathRelativeToStorage(storage.dir, result.path);\n }\n\n private async graphSeedPathsWithinDeadline(\n storage: StorageManager,\n results: QmdSearchResult[],\n deadlineAtMs: number,\n recallNamespaces: readonly string[] = [],\n ): Promise<string[]> {\n const resolved: string[] = [];\n for (const result of results) {\n if (Date.now() >= deadlineAtMs) break;\n const seedPath = await this.graphSeedPathRelativeToStorage(\n storage,\n result,\n recallNamespaces,\n );\n if (Date.now() >= deadlineAtMs) break;\n if (seedPath) resolved.push(seedPath);\n }\n return resolved;\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","/**\n * Recall search-pipeline coordinator — extracted from the orchestrator\n * (issue #1526, seam 19).\n *\n * Owns the QMD search post-processing helpers that feed recall assembly:\n * - query-aware prefiltering and artifact top-up fetch\n * - embedding/archive/cold-collection fallback pipelines\n * - recall-safety filtering and memory-map loading\n * - result boosting (recency, access, importance, relevance)\n *\n * Behavior-preserving move from orchestrator.ts. No logic changes — the\n * orchestrator keeps thin delegating methods (the private API callers and\n * tests keep working), and every member the moved code consults flows back\n * through RecallSearchPipelineDeps into the orchestrator's own overridable\n * members, so instance-level test stubs keep taking effect (the same\n * late-binding rule as seam 18).\n */\n\nimport { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport { type CapabilitySet, type GraphConstructionCapabilitySet, resolveCapabilities, resolveConversationContextCapabilities, resolveGraphConstructionCapabilities, resolveIndexingCapabilities, resolveMemoryLifecycleCapabilities, resolveNamespaceCapabilities, resolvePipelineProcessingCapabilities, resolveQmdCapabilities, resolveRecallEnhancementCapabilities } from \"../capabilities.js\";\nimport { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport { StorageManager } from \"../index.js\";\nimport { inferIntentFromText, intentCompatibilityScore } from \"../intent.js\";\nimport { log } from \"../logger.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { NegativeExampleStore } from \"../negative.js\";\nimport { qmdCollectionPathParts } from \"./qmd-result-resolver.js\";\nimport type { GraphRecallExpandedEntry } from \"../recall-state.js\";\nimport { getDefaultArchiveScoring, memoryFileToScoreItem } from \"../recall/archive-scoring.js\";\nimport { RelevanceStore } from \"../relevance.js\";\nimport { RerankCache, rerankLocalOrNoop } from \"../rerank.js\";\nimport type { SearchBackend, SearchDegradation, SearchExecutionOptions, SearchQueryOptions } from \"../search/port.js\";\nimport { SecureStoreLockedError } from \"../secure-store/index.js\";\nimport { isPathInsideStorageRoot } from \"../storage-paths.js\";\nimport { extractTagsFromPrompt, isTemporalQuery, queryByDateRangeAsync, queryByTagsAsync, recencyWindowFromPrompt, resolvePromptTagPrefilterAsync } from \"../temporal-index.js\";\nimport { shouldFilterSupersededFromRecall } from \"../temporal-supersession.js\";\nimport { isValidAsOf, isValidityExpiredNow } from \"../temporal-validity.js\";\nimport type { TrustStageResultItem } from \"../trust-score-stage.js\";\nimport type { MemoryFile, PluginConfig, QmdSearchResult, RecallPlanMode } from \"../types.js\";\nimport { type UtilityRuntimeValues, applyUtilityRankingRuntimeDelta } from \"../utility-runtime.js\";\nimport {\n computeArtifactCandidateFetchLimit,\n lifecycleRecallScoreAdjustment,\n shouldFilterLifecycleRecallCandidate,\n computeQmdHybridFetchLimit,\n filterRecallCandidates,\n isArtifactMemoryPath,\n throwIfRecallAborted,\n tokenizeRecallQuery,\n type QmdRecallSnapshot,\n type QueryAwarePrefilter,\n} from \"../orchestrator.js\";\n\nexport interface RecallSearchPipelineDeps {\n applyMemoryWorthRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<QmdSearchResult[]>;\n applyTrustScoreRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<{\n results: QmdSearchResult[];\n trustByPath: Map<string, TrustStageResultItem> | null;\n }>;\n 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 buildConfiguredQmdSearchOptions(\n queryText: string,\n ): SearchQueryOptions | undefined;\n buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter>;\n readonly config: PluginConfig;\n diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n caps?: CapabilitySet,\n ): QmdSearchResult[];\n effectiveRecencyWeight(): number;\n readonly embeddingFallback: EmbeddingFallback;\n expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n deadlineAtMs?: number | null;\n includeLowConfidence?: boolean;\n }): Promise<{\n merged: QmdSearchResult[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n seedResults: QmdSearchResult[];\n }>;\n readonly 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 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 /** Backend degradation observer, threaded into every QMD call (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]>;\n filterSearchResultsByRecallSafety(\n results: QmdSearchResult[],\n memoryByPath: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n blockedPaths?: Set<string>;\n },\n ): QmdSearchResult[];\n filterSearchResultsForRecall(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n dropUnresolved?: boolean;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{ results: QmdSearchResult[]; memoryByPath: Map<string, MemoryFile> }>;\n loadSearchResultMemoryMap(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{\n memoryByPath: Map<string, MemoryFile>;\n checkedPaths: Set<string>;\n unreadablePaths: Set<string>;\n completed: boolean;\n }>;\n namespaceFromPath(p: string): string;\n readonly negatives: NegativeExampleStore;\n readonly qmd: SearchBackend;\n readArchivedMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]>;\n readQmdResultMemory(\n resultPath: string,\n fallbackStorage: StorageManager,\n recallNamespaces?: readonly string[],\n ): Promise<MemoryFile | null>;\n readonly relevance: RelevanceStore;\n readonly rerankCache: RerankCache;\n resolveArtifactSourceStatuses(\n storage: StorageManager,\n sourceIds: string[],\n ): Promise<Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">>;\n resolveColdQmdResultForRecall(\n result: QmdSearchResult,\n fallbackStorage: StorageManager,\n recallNamespaces?: readonly string[],\n ): Promise<{ namespace: string; result: QmdSearchResult } | null>;\n scopeQueryAwarePaths(\n paths: Set<string> | null,\n recallNamespaces: string[],\n ): Set<string> | null;\n 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 searchLongTermArchiveFallback(\n prompt: string,\n recallNamespaces: string[],\n limit: number,\n queryAwarePrefilter?: QueryAwarePrefilter,\n abortSignal?: AbortSignal,\n ): Promise<QmdSearchResult[]>;\n searchScopedMemoryCandidates(\n candidatePaths: Set<string>,\n query: string,\n limit: number,\n options?: {\n allowArchived?: boolean;\n },\n ): Promise<QmdSearchResult[]>;\n readonly storage: StorageManager;\n readonly storageRouter: NamespaceStorageRouter;\n readonly utilityRuntimeValues: UtilityRuntimeValues | null;\n}\n\nexport class RecallSearchPipelineCoordinator {\n constructor(\n private readonly deps: RecallSearchPipelineDeps,\n ) {}\n\n async fetchActiveArtifactsForNamespace(\n namespace: string,\n prompt: string,\n targetCount: number,\n ): Promise<MemoryFile[]> {\n const storage = await this.deps.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.deps.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 async buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter> {\n if (!resolveIndexingCapabilities(this.deps.config).queryAwareIndexing || !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.deps.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n resolvePromptTagPrefilterAsync(this.deps.config.memoryDir, prompt).catch(\n () => ({\n matchedTags: extractTagsFromPrompt(prompt),\n expandedTags: extractTagsFromPrompt(prompt),\n paths: null,\n }),\n ),\n ]);\n\n const temporalCandidates = this.deps.scopeQueryAwarePaths(\n rawTemporal,\n recallNamespaces,\n );\n const tagCandidates = this.deps.scopeQueryAwarePaths(\n tagSignals.paths,\n recallNamespaces,\n );\n const maxCandidates = this.deps.config.queryAwareIndexingMaxCandidates;\n\n let candidatePaths: Set<string> | null = null;\n let combination: QueryAwarePrefilter[\"combination\"] = \"none\";\n let filteredToFullSearch = false;\n\n if (\n tagSignals.matchedTags.length > 0 &&\n tagCandidates !== null &&\n tagCandidates.size === 0\n ) {\n candidatePaths = tagCandidates;\n combination = \"tag\";\n } else if (temporalCandidates !== null && tagCandidates !== null) {\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 !== null) {\n candidatePaths = temporalCandidates;\n combination = \"temporal\";\n } else if (tagCandidates !== null) {\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 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 /** Backend degradation observer, threaded into every QMD call (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]> {\n throwIfRecallAborted(options.abortSignal);\n const queryAwarePrefilter =\n options.queryAwarePrefilter ??\n (await this.deps.buildQueryAwarePrefilter(prompt, options.recallNamespaces));\n const scopedSeedResults = queryAwarePrefilter.candidatePaths?.size\n ? await this.deps.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.deps.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.deps.config.searchBackend ?? \"qmd\") === \"qmd\";\n const resolvedSearchOptions = (() => {\n const resolver = (\n this.deps.qmd as {\n resolveSupportedSearchOptions?: (\n options?: SearchQueryOptions,\n ) => SearchQueryOptions | undefined;\n }\n ).resolveSupportedSearchOptions;\n if (typeof resolver === \"function\") {\n return resolver.call(this.deps.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 if (queryAwarePrefilter.candidatePaths?.size === 0) {\n await emitDebugSnapshot([], fetchLimit);\n return [];\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.deps.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n {\n signal: options.abortSignal,\n onDegradation: options.onDegradation,\n },\n )\n : await this.deps.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n { onDegradation: options.onDegradation },\n )\n : await this.deps.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"search\",\n searchOptions: primarySearchOptions,\n execution: {\n signal: options.abortSignal,\n onDegradation: options.onDegradation,\n },\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 if (this.deps.config.qmdSearchStrategy === \"lex\") {\n // BM25-only strategy: a hybrid top-up runs vectorSearch (see\n // QmdClient.hybridSearch), which would reintroduce the vector path the\n // operator opted out of. Keep \"lex\" BM25-only end-to-end so the gate is\n // uniform across primary + top-up (gotcha #39). Issue #1335 (codex review #1422).\n lastHybridTopUpSkippedReason = \"lex_strategy\";\n } else {\n const hybridResults = options.collection\n ? await this.deps.qmd.hybridSearch(\n prompt,\n options.collection,\n fetchLimit,\n {\n signal: options.abortSignal,\n onDegradation: options.onDegradation,\n },\n )\n : await this.deps.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"hybrid\",\n execution: {\n signal: options.abortSignal,\n onDegradation: options.onDegradation,\n },\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 async searchEmbeddingFallback(\n query: string,\n limit: number,\n ): Promise<QmdSearchResult[]> {\n if (!resolveMemoryLifecycleCapabilities(this.deps.config).embeddingFallback) return [];\n if (!(await this.deps.embeddingFallback.isAvailable())) return [];\n const hits = await this.deps.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.deps.config.memoryDir, hit.path);\n const memory = await this.deps.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 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 if (queryAwarePrefilter?.candidatePaths?.size === 0) return [];\n\n const scopedSeedResults = queryAwarePrefilter?.candidatePaths?.size\n ? await this.deps.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.deps.readArchivedMemoriesForNamespaces(recallNamespaces);\n if (archivedMemories.length === 0) return scopedSeedResults;\n\n // Issue #1674: off-load the CPU-bound archive-scoring loop to a\n // worker_threads pool so concurrent recall requests run on separate\n // cores instead of serializing on the main JS thread. The pure scoring\n // function is identical to the old inline loop — only the execution\n // context changed. Aborts are checked at the boundaries (before submit\n // and after result); the worker's work is bounded by the file count.\n throwIfRecallAborted(abortSignal);\n const scoring = getDefaultArchiveScoring();\n const scoredResults = await scoring.score(archivedMemories.map(memoryFileToScoreItem), tokens, abortSignal);\n throwIfRecallAborted(abortSignal);\n const scored: QmdSearchResult[] = scoredResults.map((r) => ({\n docid: r.docid,\n path: r.path,\n score: r.score,\n snippet: r.snippet,\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 async applyColdFallbackPipeline(options: {\n prompt: string;\n recallNamespaces: string[];\n recallResultLimit: number;\n recallMode: RecallPlanMode;\n /**\n * Recall-operation capability gates resolved once at recall entry (#1523).\n * OPTIONAL and additive: the recall pipeline threads a resolved set, but\n * callers that omit it (e.g. direct unit-test invocations) get an\n * equivalent config-derived set — behavior-preserving.\n */\n caps?: CapabilitySet;\n /** Graph-construction gates resolved at recall entry (#1566 Cluster A). */\n graphCaps?: GraphConstructionCapabilitySet;\n queryAwarePrefilter?: QueryAwarePrefilter;\n abortSignal?: AbortSignal;\n /** Backend degradation observer — cold-tier QMD must report like hot (#1536). */\n onDegradation?: (degradation: SearchDegradation) => void;\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 /**\n * Issue #1577 — out-parameter that receives the TrustScore stage's\n * per-path trust map (admitted + quarantined) when the cold path runs\n * trust scoring. Mirrors the xrayPoolSizeSink pattern so recallInternal\n can propagate trust data for epistemic rendering and X-ray visibility\n without changing the cold pipeline's return type.\n */\n trustByPathSink?: { trustByPath: Map<string, TrustStageResultItem> | null };\n deadlineAtMs?: number | null;\n /** Issue #681 — when true, bypass graphTraversalConfidenceFloor. */\n includeLowConfidence?: boolean;\n }): Promise<QmdSearchResult[]> {\n // Prefer the threaded set; fall back to a config-derived set so direct\n // callers (unit tests) behave identically to the recall pipeline (#1523).\n const caps = options.caps ?? resolveCapabilities(this.deps.config);\n const graphCaps = options.graphCaps ?? resolveGraphConstructionCapabilities(this.deps.config);\n if (options.queryAwarePrefilter?.candidatePaths?.size === 0) {\n if (options.xrayPoolSizeSink) options.xrayPoolSizeSink.size = 0;\n return [];\n }\n const deadlineRemainingMs = (): number | null =>\n typeof options.deadlineAtMs === \"number\"\n ? Math.max(0, options.deadlineAtMs - Date.now())\n : null;\n const runColdStepWithinDeadline = async <T>(\n label: string,\n fallback: T,\n task: () => Promise<T>,\n // Invoked when the deadline abandons this step (before it started or\n // while it runs), so callers can report the abandonment and gate off\n // late observer callbacks (#1536, cursor round-6 on #1544).\n onDeadline?: () => void,\n ): Promise<T> => {\n throwIfRecallAborted(options.abortSignal);\n const remainingMs = deadlineRemainingMs();\n if (remainingMs === 0) {\n try {\n onDeadline?.();\n } catch {\n // Observers must never break recall.\n }\n log.debug(`cold-tier recall ${label} skipped: shared assembly deadline expired`);\n return fallback;\n }\n if (remainingMs === null) return task();\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n let timedOut = false;\n const taskPromise = task().catch((err) => {\n if (timedOut) {\n log.debug(`cold-tier recall ${label} failed after deadline: ${err}`);\n return fallback;\n }\n throw err;\n });\n\n try {\n return await Promise.race<T>([\n taskPromise,\n new Promise<T>((resolve) => {\n timeoutHandle = setTimeout(() => {\n timedOut = true;\n try {\n onDeadline?.();\n } catch {\n // Observers must never break recall.\n }\n log.debug(\n `cold-tier recall ${label} skipped: shared assembly deadline expired`,\n );\n resolve(fallback);\n }, remainingMs);\n }),\n ]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n };\n\n const coldQmdEnabled = resolveQmdCapabilities(this.deps.config).qmdColdTier === true;\n const coldCollection =\n this.deps.config.qmdColdCollection ?? \"openclaw-engram-cold\";\n const coldMaxResults =\n this.deps.config.qmdColdMaxResults ?? this.deps.config.qmdMaxResults;\n\n let longTerm: QmdSearchResult[] = [];\n if (coldQmdEnabled && this.deps.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 // Deadline-gated observer (#1536, cursor round-6 on #1544): when the\n // shared assembly deadline abandons this lookup, the still-running\n // fetch's LATE reports must not land after the recall snapshot has\n // been recorded — gate them off and report the abandonment itself\n // deterministically at resolution time instead.\n let coldQmdObserverActive = true;\n const reportColdQmdDeadline = () => {\n coldQmdObserverActive = false;\n try {\n options.onDegradation?.({\n backend: \"qmd\",\n code: \"deadline_exceeded\",\n detail: \"cold-tier qmd lookup abandoned (assembly deadline)\",\n });\n } catch {\n // Observers must never break recall.\n }\n };\n longTerm = await runColdStepWithinDeadline(\n \"qmd lookup\",\n [],\n () =>\n this.deps.fetchQmdMemoryResultsWithArtifactTopUp(\n options.prompt,\n coldFetchLimit,\n coldHybridLimit,\n {\n namespacesEnabled: resolveNamespaceCapabilities(this.deps.config).namespaces,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: (p) => this.deps.namespaceFromPath(p),\n collection: coldCollection,\n queryAwarePrefilter: options.queryAwarePrefilter,\n searchOptions: this.deps.buildConfiguredQmdSearchOptions(options.prompt),\n abortSignal: options.abortSignal,\n onDegradation: (degradation) => {\n if (coldQmdObserverActive) {\n options.onDegradation?.(degradation);\n }\n },\n },\n ),\n reportColdQmdDeadline,\n );\n // Normal completion also closes the gate: a deadline that fires\n // after this await has nothing left to suppress, and a fetch that\n // limps home later cannot mutate a recorded recall's collector.\n coldQmdObserverActive = false;\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 // Deadline-aware abort: terminate the scoring worker when the shared\n // assembly deadline wins, not just when the caller aborts (#1674).\n const da = new AbortController();\n if (options.abortSignal?.aborted) da.abort();\n else options.abortSignal?.addEventListener(\"abort\", () => da.abort(), { once: true });\n longTerm = await runColdStepWithinDeadline(\n \"archive scan\", [],\n () => this.deps.searchLongTermArchiveFallback(\n options.prompt, options.recallNamespaces, options.recallResultLimit,\n options.queryAwarePrefilter, da.signal),\n () => da.abort(),\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 (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n const recallRoots: string[] = [];\n const seenRecallRoots = new Set<string>();\n for (const namespace of options.recallNamespaces) {\n try {\n const storage = await this.deps.storageRouter.storageFor(namespace);\n const storageDir =\n typeof (storage as { dir?: unknown }).dir === \"string\" &&\n (storage as { dir?: string }).dir\n ? (storage as { dir: string }).dir\n : null;\n if (!storageDir) continue;\n const recallRoot = path.resolve(storageDir);\n if (seenRecallRoots.has(recallRoot)) continue;\n seenRecallRoots.add(recallRoot);\n recallRoots.push(recallRoot);\n } catch (err) {\n log.debug(\"cold-tier recall namespace root lookup skipped\", {\n namespace,\n error: (err as Error).message,\n });\n }\n }\n const scopedResults: QmdSearchResult[] = [];\n for (const result of results) {\n if (options.abortSignal?.aborted || deadlineRemainingMs() === 0) break;\n const parts = qmdCollectionPathParts(result.path);\n if (parts?.collection === coldCollection) {\n const resolvedCold = await this.deps.resolveColdQmdResultForRecall(\n result,\n this.deps.storage,\n options.recallNamespaces,\n );\n if (resolvedCold) scopedResults.push(resolvedCold.result);\n continue;\n }\n if (path.isAbsolute(result.path)) {\n const resolvedPath = path.resolve(result.path);\n if (\n recallRoots.some((recallRoot) =>\n isPathInsideStorageRoot(recallRoot, resolvedPath),\n )\n ) {\n scopedResults.push(result);\n }\n continue;\n }\n if (options.recallNamespaces.includes(this.deps.namespaceFromPath(result.path))) {\n scopedResults.push(result);\n }\n }\n results = scopedResults;\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 resolveQmdCapabilities(this.deps.config).qmdTierParityGraph &&\n graphCaps.multiGraphMemory &&\n caps.graphAssistInFullMode &&\n options.recallMode === \"full\" &&\n results.length >= Math.max(1, this.deps.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n resolveQmdCapabilities(this.deps.config).qmdTierParityGraph &&\n (options.recallMode === \"graph_mode\" || isFullModeGraphAssist);\n\n if (shouldRunGraphExpansion) {\n const { merged } = await this.deps.expandResultsViaGraph({\n memoryResults: results,\n recallNamespaces: options.recallNamespaces,\n recallResultLimit: options.recallResultLimit,\n deadlineAtMs: options.deadlineAtMs,\n ...(options.includeLowConfidence === true ? { includeLowConfidence: true } : {}),\n });\n results = merged;\n }\n\n const boostInput = await this.deps.filterSearchResultsForRecall(\n results,\n undefined,\n {\n allowLifecycleFiltered: true,\n asOfMs: options.asOfMs,\n deadlineAtMs: options.deadlineAtMs,\n abortSignal: options.abortSignal,\n dropUnresolved: true,\n recallNamespaces: options.recallNamespaces,\n },\n );\n results = boostInput.results;\n const boostTimeoutMs =\n typeof options.deadlineAtMs === \"number\"\n ? Math.max(0, options.deadlineAtMs - Date.now())\n : null;\n if (boostTimeoutMs !== 0) {\n let timeoutHandle: NodeJS.Timeout | undefined;\n try {\n const boosted = await (boostTimeoutMs !== null\n ? Promise.race<QmdSearchResult[] | { status: \"timed_out\" }>([\n this.deps.boostSearchResults(\n boostInput.results,\n options.recallNamespaces,\n options.prompt,\n boostInput.memoryByPath,\n { allowLifecycleFiltered: true, asOfMs: options.asOfMs },\n ),\n new Promise<{ status: \"timed_out\" }>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve({ status: \"timed_out\" }),\n boostTimeoutMs,\n );\n }),\n ])\n : this.deps.boostSearchResults(\n boostInput.results,\n options.recallNamespaces,\n options.prompt,\n boostInput.memoryByPath,\n { allowLifecycleFiltered: true, asOfMs: options.asOfMs },\n ));\n if (\n typeof boosted === \"object\" &&\n boosted !== null &&\n \"status\" in boosted &&\n boosted.status === \"timed_out\"\n ) {\n log.debug(\"cold-tier recall boost skipped: shared assembly deadline expired\");\n } else if (Array.isArray(boosted)) {\n results = boosted;\n } else {\n results = boostInput.results;\n }\n } catch (err) {\n log.debug(`cold-tier recall boost failed open: ${err}`);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n } else {\n log.debug(\"cold-tier recall boost skipped: shared assembly deadline already expired\");\n }\n\n if (caps.rerank && this.deps.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: options.prompt,\n candidates: results\n .slice(0, this.deps.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.deps.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.deps.config.rerankTimeoutMs,\n maxCandidates: this.deps.config.rerankMaxCandidates,\n cache: this.deps.rerankCache,\n cacheEnabled: caps.rerankCache,\n cacheTtlMs: this.deps.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 (caps.rerank && this.deps.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Trust-reweighting — must fire on the cold fallback path too, or the\n // feature flag produces divergent behavior by retrieval path (rule 39).\n // TrustScore subsumes the Memory Worth multiplier; run exactly one.\n // Fail-open on lookup errors.\n if (caps.recallTrustScore && results.length > 0) {\n try {\n const trustOutcome = await this.deps.applyTrustScoreRerank(results, options.recallNamespaces);\n results = trustOutcome.results;\n if (options.trustByPathSink) options.trustByPathSink.trustByPath = trustOutcome.trustByPath;\n } catch (err) {\n log.debug(\"trust-score stage (cold) failed open\", {\n error: (err as Error).message,\n });\n }\n } else if (caps.recallMemoryWorthFilter && results.length > 0) {\n try {\n results = await this.deps.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.deps.diversifyAndLimitRecallResults(\n \"memories\",\n results,\n options.recallResultLimit,\n options.prompt,\n caps,\n );\n }\n\n async loadSearchResultMemoryMap(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{\n memoryByPath: Map<string, MemoryFile>;\n checkedPaths: Set<string>;\n unreadablePaths: Set<string>;\n completed: boolean;\n }> {\n const memoryByPath: Map<string, MemoryFile> = preloadedMemoryMap\n ? new Map(preloadedMemoryMap)\n : new Map();\n const checkedPaths = new Set<string>();\n const unreadablePaths = new Set<string>();\n\n const markChecked = (result: QmdSearchResult): void => {\n if (result.path) checkedPaths.add(result.path);\n };\n const markUnreadable = (result: QmdSearchResult, err: unknown): void => {\n if (!result.path) return;\n checkedPaths.add(result.path);\n unreadablePaths.add(result.path);\n log.warn(\"recall safety filter dropped unreadable secure-store candidate\", {\n path: result.path,\n error: (err as Error).message,\n });\n };\n const deadlineExpired = (): boolean =>\n typeof options?.deadlineAtMs === \"number\" &&\n Date.now() >= options.deadlineAtMs;\n\n if (options?.deadlineAtMs == null) {\n const batchSize = options?.abortSignal ? 16 : results.length;\n for (let offset = 0; offset < results.length; offset += batchSize) {\n if (options?.abortSignal?.aborted) {\n return {\n memoryByPath,\n checkedPaths,\n unreadablePaths,\n completed: false,\n };\n }\n await Promise.all(\n results.slice(offset, offset + batchSize).map(async (r) => {\n if (!r.path) return;\n if (memoryByPath.has(r.path)) {\n markChecked(r);\n return;\n }\n try {\n const mem = await this.deps.readQmdResultMemory(\n r.path,\n this.deps.storage,\n options?.recallNamespaces,\n );\n markChecked(r);\n if (mem) memoryByPath.set(r.path, mem);\n } catch (err) {\n if (err instanceof SecureStoreLockedError) {\n markUnreadable(r, err);\n return;\n }\n throw err;\n }\n }),\n );\n }\n\n return { memoryByPath, checkedPaths, unreadablePaths, completed: true };\n }\n\n for (const result of results) {\n if (!result.path) continue;\n if (memoryByPath.has(result.path)) {\n markChecked(result);\n continue;\n }\n if (options?.abortSignal?.aborted || deadlineExpired()) {\n return { memoryByPath, checkedPaths, unreadablePaths, completed: false };\n }\n try {\n const mem = await this.deps.readQmdResultMemory(\n result.path,\n this.deps.storage,\n options?.recallNamespaces,\n );\n markChecked(result);\n if (mem) memoryByPath.set(result.path, mem);\n } catch (err) {\n if (err instanceof SecureStoreLockedError) {\n markUnreadable(result, err);\n continue;\n }\n throw err;\n }\n }\n\n return { memoryByPath, checkedPaths, unreadablePaths, completed: true };\n }\n\n filterSearchResultsByRecallSafety(\n results: QmdSearchResult[],\n memoryByPath: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n blockedPaths?: Set<string>;\n },\n ): QmdSearchResult[] {\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.deps.config);\n let lifecycleFilteredCount = 0;\n let temporalSupersededFilteredCount = 0;\n let biTemporalExpiredFilteredCount = 0;\n let dedicatedSurfaceFilteredCount = 0;\n let forgottenFilteredCount = 0;\n let blockedPathFilteredCount = 0;\n const filtered: QmdSearchResult[] = [];\n for (const r of results) {\n if (r.path && options?.blockedPaths?.has(r.path)) {\n blockedPathFilteredCount += 1;\n continue;\n }\n const memory = memoryByPath.get(r.path);\n if (memory) {\n // Review-lifecycle statuses never enter active recall injection\n // (forgotten, pending_review, rejected, quarantined). Superseded and\n // archived have dedicated filters below. #1576: the faithfulness gate\n // routes unsupported/contradicted facts to pending_review — they must\n // not leak back via the QMD/embedding path. chatgpt P2.\n const recallStatus = memory.frontmatter.status;\n if (\n recallStatus === \"forgotten\" ||\n recallStatus === \"pending_review\" ||\n recallStatus === \"rejected\" ||\n recallStatus === \"quarantined\"\n ) {\n forgottenFilteredCount += 1;\n continue;\n }\n\n if (\n options?.allowLifecycleFiltered !== true &&\n shouldFilterLifecycleRecallCandidate(memory.frontmatter, {\n lifecyclePolicyEnabled: lifecycleCaps.lifecyclePolicy,\n lifecycleFilterStaleEnabled:\n lifecycleCaps.lifecycleFilterStale,\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: lifecycleCaps.temporalSupersession,\n includeInRecall: this.deps.config.temporalSupersessionIncludeInRecall,\n })\n ) {\n temporalSupersededFilteredCount += 1;\n continue;\n }\n // Bi-temporal INJECTION filter (issue #1578): when the master gate\n // is on and the caller did NOT pin `as_of`, drop facts whose event-\n // time interval has ended before now. This lives ONLY in the recall\n // injection path (filterSearchResultsByRecallSafety) — explicit\n // search (access-service.memorySearch → searchAcrossNamespaces /\n // qmd.search) never routes through here, so expired-validity facts\n // remain findable by memory_search and `as_of` queries (escape\n // hatch: the as_of branch above also admits historically-valid\n // records). Gated off entirely when `temporalExpiredInInjection` is\n // set. Status-orthogonal: an `active` fact can be validity-expired;\n // a `superseded` one may still be within its window.\n if (\n !asOfActive &&\n this.deps.config.temporalBiTemporal &&\n !this.deps.config.temporalExpiredInInjection &&\n isValidityExpiredNow(memory.frontmatter, Date.now())\n ) {\n biTemporalExpiredFilteredCount += 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 filtered.push(r);\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 (biTemporalExpiredFilteredCount > 0) {\n log.debug(\n `bi-temporal validity filter removed ${biTemporalExpiredFilteredCount} expired-validity candidates from injection (temporal.biTemporal on)`,\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 if (blockedPathFilteredCount > 0) {\n log.debug(\n `unreadable-path filter removed ${blockedPathFilteredCount} candidates from recall`,\n );\n }\n return filtered;\n }\n\n async filterSearchResultsForRecall(\n results: QmdSearchResult[],\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n asOfMs?: number;\n deadlineAtMs?: number | null;\n abortSignal?: AbortSignal;\n dropUnresolved?: boolean;\n recallNamespaces?: readonly string[];\n },\n ): Promise<{ results: QmdSearchResult[]; memoryByPath: Map<string, MemoryFile> }> {\n if (results.length === 0) {\n return {\n results,\n memoryByPath: preloadedMemoryMap ? new Map(preloadedMemoryMap) : new Map(),\n };\n }\n const loaded = await this.deps.loadSearchResultMemoryMap(\n results,\n preloadedMemoryMap,\n options,\n );\n const candidateResults = loaded.completed\n ? results\n : results.filter((result) => !result.path || loaded.checkedPaths.has(result.path));\n if (!loaded.completed) {\n log.debug(\n `recall safety filter stopped before validating all candidates (${candidateResults.length}/${results.length} eligible)`,\n );\n }\n const blockedPaths = new Set(loaded.unreadablePaths);\n if (options?.dropUnresolved === true) {\n for (const resultPath of loaded.checkedPaths) {\n if (!loaded.memoryByPath.has(resultPath)) {\n blockedPaths.add(resultPath);\n }\n }\n }\n return {\n results: this.deps.filterSearchResultsByRecallSafety(\n candidateResults,\n loaded.memoryByPath,\n { ...options, blockedPaths },\n ),\n memoryByPath: loaded.memoryByPath,\n };\n }\n\n /**\n * Apply recency, access count, and importance boosting to QMD search results.\n * Returns re-ranked results.\n */\n 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 const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.deps.config);\n if (results.length === 0) return results;\n\n const safety = await this.deps.filterSearchResultsForRecall(\n results,\n preloadedMemoryMap,\n { ...options, recallNamespaces: _recallNamespaces },\n );\n const safeResults = safety.results;\n const memoryByPath = safety.memoryByPath;\n if (safeResults.length === 0) return safeResults;\n\n const now = Date.now();\n\n // Determine temporal/tag query params before index I/O (pure computation).\n const resultPaths = new Set(\n safeResults.map((r) => r.path).filter(Boolean) as string[],\n );\n let temporalFromDate: string | null = null;\n let promptTags: string[] = [];\n if (resolveIndexingCapabilities(this.deps.config).queryAwareIndexing && prompt) {\n if (isTemporalQuery(prompt)) {\n temporalFromDate = recencyWindowFromPrompt(prompt, now);\n }\n promptTags = extractTagsFromPrompt(prompt);\n }\n\n const [rawTemporal, rawTags] = await Promise.all([\n temporalFromDate !== null\n ? queryByDateRangeAsync(this.deps.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n promptTags.length > 0\n ? queryByTagsAsync(this.deps.config.memoryDir, promptTags)\n : Promise.resolve<Set<string> | null>(null),\n ]);\n\n const queryIntent =\n resolveConversationContextCapabilities(this.deps.config).intentRouting && 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 (resolveIndexingCapabilities(this.deps.config).queryAwareIndexing && prompt) {\n const maxCandidates = this.deps.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;\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 const boosted: QmdSearchResult[] = [];\n const recencyWeight = this.deps.effectiveRecencyWeight();\n for (const r of safeResults) {\n const memory = memoryByPath.get(r.path);\n let score = r.score;\n\n if (memory) {\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.deps.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.deps.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.deps.utilityRuntimeValues,\n importanceBoost >= 0 ? \"boost\" : \"suppress\",\n );\n }\n\n // Feedback bias (v2.2): apply small user-provided up/down vote adjustments.\n if (resolveRecallEnhancementCapabilities(this.deps.config).feedback) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const feedbackDelta = this.deps.relevance.adjustment(memoryId);\n score += applyUtilityRankingRuntimeDelta(\n feedbackDelta,\n this.deps.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 (resolvePipelineProcessingCapabilities(this.deps.config).negativeExamples) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const negativePenalty = this.deps.negatives.penalty(memoryId, {\n perHit: this.deps.config.negativeExamplesPenaltyPerHit,\n cap: this.deps.config.negativeExamplesPenaltyCap,\n });\n score -= applyUtilityRankingRuntimeDelta(\n negativePenalty,\n this.deps.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.deps.config.intentRoutingBoost,\n this.deps.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 (resolveIndexingCapabilities(this.deps.config).queryAwareIndexing && r.path) {\n if (temporalCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.08,\n this.deps.utilityRuntimeValues,\n \"boost\",\n );\n }\n if (tagCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.06,\n this.deps.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: lifecycleCaps.lifecyclePolicy,\n },\n );\n score += applyUtilityRankingRuntimeDelta(\n lifecycleDelta,\n this.deps.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 resolveRecallEnhancementCapabilities(this.deps.config).reinforcementRecallBoost &&\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.deps.config.reinforcementRecallBoostWeight,\n this.deps.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\n // Re-sort by boosted score\n return boosted.sort((a, b) => b.score - a.score);\n }\n}\n","// ---------------------------------------------------------------------------\n// Off-thread archive scoring for the cold-fallback recall path (issue #1674).\n//\n// `searchLongTermArchiveFallback` (orchestrator.ts) falls back to scanning\n// EVERY archived memory file when hybrid/vector search returns zero hits.\n// The scoring loop — for each memory × for each token, `haystack.includes(token)`\n// — is fully synchronous, unbounded, and CPU-bound. Under concurrent recall\n// load this monopolized the JS main thread: N concurrent recalls serialized\n// on one core and each blew past the client-side timeout even though total\n// CPU work would have finished comfortably if parallelized.\n//\n// This module extracts the scoring loop into a pure function and provides two\n// strategies:\n//\n// 1. `SyncArchiveScoring` — runs the pure function on the calling thread\n// (the OLD behavior; preserved for prove-fail\n// tests and as the graceful fallback).\n// 2. `OffThreadArchiveScoring` — dispatches the pure function to a\n// `worker_threads` pool so concurrent recalls\n// run on separate cores instead of serializing\n// on the main thread. Falls back to sync if\n// workers cannot be created.\n//\n// Both strategies share the identical `scoreArchiveMemories` pure function,\n// so the scoring semantics are byte-identical regardless of which path runs.\n// ---------------------------------------------------------------------------\n\nimport os from \"node:os\";\nimport { Worker } from \"node:worker_threads\";\nimport { log } from \"../logger.js\";\nimport type { MemoryFile } from \"../types.js\";\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Wire types — plain-serializable shapes that cross the worker boundary via\n// structured clone. Only the fields the scoring loop reads are included.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/** Minimal serializable projection of {@link MemoryFile} for scoring. */\nexport interface ArchiveScoreItem {\n id: string;\n path: string;\n content: string;\n category: string;\n tags: string[];\n}\n\n/** Scoring output — maps 1:1 to the relevant QmdSearchResult fields. */\nexport interface ArchiveScoreResult {\n docid: string;\n path: string;\n score: number;\n snippet: string;\n}\n\n/** Worker request envelope. */\ninterface ScoreTask {\n items: ArchiveScoreItem[];\n tokens: string[];\n}\n\n/** Worker reply envelope. */\ntype ScoreReply = { ok: true; results: ArchiveScoreResult[] } | { ok: false; error: string };\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Pure scoring function — shared by both strategies and by the inline worker.\n// Extracted verbatim from the original inline loop in\n// `searchLongTermArchiveFallback` so behavior is identical.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Score archived memories against query tokens using substring overlap.\n *\n * For each memory, builds a lowercase haystack from `[content, category, ...tags]`,\n * counts how many distinct tokens appear in it, and scores by `hits / tokens.length`.\n * Memories with zero hits are dropped. Snippets are the first 400 chars of content\n * with newlines collapsed to spaces — matching the original orchestrator behavior.\n *\n * This function is intentionally synchronous and CPU-bound; that is precisely\n * why the off-thread strategy exists.\n */\nexport function scoreArchiveMemories(\n items: ReadonlyArray<ArchiveScoreItem>,\n tokens: ReadonlyArray<string>\n): ArchiveScoreResult[] {\n if (items.length === 0 || tokens.length === 0) return [];\n\n const scored: ArchiveScoreResult[] = [];\n for (const item of items) {\n const haystack = [item.content, item.category, ...item.tags].join(\" \").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 scored.push({\n docid: item.id,\n path: item.path,\n score: hits / tokens.length,\n snippet: item.content.slice(0, 400).replace(/\\n/g, \" \"),\n });\n }\n return scored;\n}\n\n/**\n * Project a {@link MemoryFile} into the minimal serializable shape the scoring\n * function consumes. Called on the main thread BEFORE dispatching to a worker\n * so the heavy `MemoryFrontmatter` (dozens of optional fields, nested objects)\n * never crosses the worker boundary.\n */\nexport function memoryFileToScoreItem(memory: MemoryFile): ArchiveScoreItem {\n return {\n id: memory.frontmatter.id,\n path: memory.path,\n content: memory.content,\n category: memory.frontmatter.category,\n tags: memory.frontmatter.tags ?? [],\n };\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Strategy interface\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Pluggable scoring backend. The orchestrator holds one instance and calls\n * `score()` from the cold-fallback path. The default is off-thread; tests and\n * restricted environments can swap in the sync strategy.\n */\nexport interface ArchiveScoringStrategy {\n score(\n items: ReadonlyArray<ArchiveScoreItem>,\n tokens: ReadonlyArray<string>,\n abortSignal?: AbortSignal\n ): Promise<ArchiveScoreResult[]>;\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// 1. SyncArchiveScoring — the OLD serialized behavior, preserved for fallback\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Runs the scoring loop synchronously on the calling thread.\n *\n * This is the exact behavior that caused issue #1674: the synchronous loop\n * blocks the event loop for its entire duration, so concurrent recall\n * requests serialize behind each other. It is retained as the graceful\n * fallback when worker_threads are unavailable, and as the prove-fail\n * baseline in regression tests.\n */\nexport class SyncArchiveScoring implements ArchiveScoringStrategy {\n async score(\n items: ReadonlyArray<ArchiveScoreItem>,\n tokens: ReadonlyArray<string>,\n abortSignal?: AbortSignal\n ): Promise<ArchiveScoreResult[]> {\n if (items.length === 0 || tokens.length === 0) return [];\n if (abortSignal?.aborted) return [];\n // Process in chunks so an abort during a large archive scan is observed\n // without burning the full synchronous CPU pass (#1674 review: sync\n // fallback should check mid-scoring abort, like the old inline loop).\n const CHUNK = 500;\n if (items.length <= CHUNK) return scoreArchiveMemories(items, tokens);\n const results: ArchiveScoreResult[] = [];\n for (let i = 0; i < items.length; i += CHUNK) {\n if (abortSignal?.aborted) return [];\n const scored = scoreArchiveMemories(items.slice(i, i + CHUNK), tokens);\n for (const r of scored) results.push(r);\n }\n return results;\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Inline worker code (eval mode) — eliminates file-resolution / build-config\n// issues entirely. The worker is self-contained CJS (no imports), so it runs\n// identically under tsx, compiled dist, and published npm packages.\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Inline worker source. Runs via `new Worker(code, { eval: true })`.\n *\n * MUST stay byte-identical to {@link scoreArchiveMemories} above. The\n * regression test \"worker scoring matches canonical scoreArchiveMemories\"\n * asserts this equivalence at runtime.\n */\nconst WORKER_SOURCE = String.raw`\nconst { parentPort } = require('node:worker_threads');\n\nfunction scoreArchiveMemories(items, tokens) {\n if (items.length === 0 || tokens.length === 0) return [];\n var scored = [];\n for (var i = 0; i < items.length; i++) {\n var item = items[i];\n var haystack = [item.content, item.category].concat(item.tags || []).join(' ').toLowerCase();\n var hits = 0;\n for (var j = 0; j < tokens.length; j++) {\n if (haystack.indexOf(tokens[j]) !== -1) hits++;\n }\n if (hits === 0) continue;\n scored.push({\n docid: item.id,\n path: item.path,\n score: hits / tokens.length,\n snippet: item.content.slice(0, 400).replace(/\\n/g, ' '),\n });\n }\n return scored;\n}\n\nif (parentPort) {\n parentPort.on('message', function(task) {\n try {\n var results = scoreArchiveMemories(task.items, task.tokens);\n parentPort.postMessage({ ok: true, results: results });\n } catch (err) {\n parentPort.postMessage({ ok: false, error: err && err.message ? err.message : String(err) });\n }\n });\n}\n`;\n\n// ─────────────────────────────────────────────────────────────────────────────\n// 2. OffThreadArchiveScoring — worker pool for genuine multi-core parallelism\n// ─────────────────────────────────────────────────────────────────────────────\n\n/**\n * Default worker pool size. Uses `availableParallelism()` (Node 19.4+) minus\n * one so the main thread always has a dedicated core for I/O dispatch. Capped\n * at 8 to bound memory overhead (each worker has its own V8 heap).\n */\nfunction defaultPoolSize(): number {\n const cpus = typeof os.availableParallelism === \"function\" ? os.availableParallelism() : os.cpus().length;\n return Math.max(1, Math.min(Math.max(1, cpus - 1), 8));\n}\n\n/**\n * Safety-net timeout for a single dispatch. The cold-fallback pipeline already\n * has its own deadline mechanism (runColdStepWithinDeadline); this is a\n * last-resort guard so a hung worker never blocks recall indefinitely.\n * Generously large to avoid interfering with large corpora (issue #1674\n * reported scans up to ~70s on large archives).\n */\nconst DISPATCH_TIMEOUT_MS = 120_000;\n\n/** Lazy worker pool. Workers are created on first use and recycled. */\nclass ArchiveScoringWorkerPool {\n private readonly targetSize: number;\n private workers: Worker[] = [];\n private idle: Worker[] = [];\n private waiters: Array<{ resolve: (worker: Worker) => void; reject: (err: Error) => void }> = [];\n private terminated = false;\n\n constructor(size: number = defaultPoolSize()) {\n this.targetSize = Math.max(1, size);\n }\n\n async run(task: ScoreTask, abortSignal?: AbortSignal): Promise<ArchiveScoreResult[]> {\n if (this.terminated) throw new Error(\"archive-scoring pool terminated\");\n const worker = await this.acquire(abortSignal);\n // If the caller already aborted before dispatch, return the worker to idle\n // instead of retiring it — it was never posted to (#1674).\n if (abortSignal?.aborted) {\n this.release(worker);\n return [];\n }\n let abandoned = false;\n try {\n return await this.dispatch(worker, task, abortSignal, () => {\n abandoned = true;\n });\n } finally {\n if (abandoned) this.retireWorker(worker);\n else this.release(worker);\n }\n }\n\n async terminate(): Promise<void> {\n if (this.terminated) return;\n this.terminated = true;\n // Reject all queued waiters so they don't hang indefinitely (#1674).\n const queued = this.waiters;\n this.waiters = [];\n for (const w of queued) w.reject(new Error(\"archive-scoring pool terminated\"));\n const all = [...this.workers];\n this.workers = [];\n this.idle = [];\n await Promise.allSettled(all.map((w) => w.terminate()));\n }\n\n private async acquire(abortSignal?: AbortSignal): Promise<Worker> {\n const idle = this.idle.pop();\n if (idle) return idle;\n if (this.workers.length < this.targetSize) return this.spawn();\n // Park until a worker is released. If the caller aborts (or the pool\n // terminates) while queued, reject so the recall falls back to sync\n // instead of consuming a worker for a request that already timed out.\n return new Promise<Worker>((resolve, reject) => {\n const entry = { resolve, reject };\n this.waiters.push(entry);\n if (!abortSignal) return;\n const onAbort = () => {\n const idx = this.waiters.indexOf(entry);\n if (idx !== -1) this.waiters.splice(idx, 1);\n reject(new Error(\"archive-scoring acquire aborted\"));\n };\n if (abortSignal.aborted) { onAbort(); return; }\n abortSignal.addEventListener(\"abort\", onAbort, { once: true });\n });\n }\n\n private release(worker: Worker): void {\n const next = this.waiters.shift();\n if (next) {\n next.resolve(worker);\n } else if (!this.terminated) {\n this.idle.push(worker);\n } else {\n void worker.terminate();\n }\n }\n\n /** Terminate a worker that may still be busy, then spawn a replacement\n * if a waiter is queued. */\n private retireWorker(worker: Worker): void {\n const idx = this.workers.indexOf(worker);\n if (idx !== -1) this.workers.splice(idx, 1);\n void worker.terminate();\n const next = this.waiters.shift();\n if (next) next.resolve(this.spawn());\n }\n\n private spawn(): Worker {\n const worker = new Worker(WORKER_SOURCE, { eval: true });\n // Unref so idle workers never keep the event loop alive (#1674).\n worker.unref();\n this.workers.push(worker);\n return worker;\n }\n\n private dispatch(\n worker: Worker,\n task: ScoreTask,\n abortSignal: AbortSignal | undefined,\n onAbandon: () => void\n ): Promise<ArchiveScoreResult[]> {\n return new Promise<ArchiveScoreResult[]>((resolve, reject) => {\n let settled = false;\n const timer = setTimeout(() => {\n if (settled) return;\n settled = true;\n cleanup();\n onAbandon();\n log.debug(`archive-scoring dispatch timed out after ${DISPATCH_TIMEOUT_MS}ms — falling back to sync`);\n reject(new Error(`archive-scoring dispatch timed out after ${DISPATCH_TIMEOUT_MS}ms`));\n }, DISPATCH_TIMEOUT_MS);\n\n const onMessage = (reply: ScoreReply) => {\n if (settled) return;\n settled = true;\n cleanup();\n if (reply.ok) resolve(reply.results);\n else reject(new Error(reply.error));\n };\n const onError = (err: Error) => {\n if (settled) return;\n settled = true;\n cleanup();\n onAbandon();\n reject(err);\n };\n // worker.terminate() ends via 'exit', not 'error' — listen so in-flight\n // dispatches during pool shutdown reject immediately instead of hanging\n // until the 120s timeout (#1674).\n const onExit = (code: number) => {\n if (settled) return;\n settled = true;\n cleanup();\n onAbandon();\n reject(new Error(`archive-scoring worker exited with code ${code}`));\n };\n const onAbort = () => {\n if (settled) return;\n settled = true;\n cleanup();\n onAbandon();\n resolve([]);\n };\n\n const cleanup = () => {\n clearTimeout(timer);\n worker.off(\"message\", onMessage);\n worker.off(\"error\", onError);\n worker.off(\"exit\", onExit);\n abortSignal?.removeEventListener(\"abort\", onAbort);\n };\n\n worker.on(\"message\", onMessage);\n worker.on(\"error\", onError);\n worker.on(\"exit\", onExit);\n abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n worker.postMessage(task);\n });\n }\n}\n\n/**\n * Off-thread scoring via a `worker_threads` pool.\n *\n * Concurrent `score()` calls are dispatched to separate workers, giving\n * genuine multi-core parallelism: K concurrent recalls run on K cores\n * instead of serializing on the main JS thread. If the pool cannot be\n * created (e.g. restricted runtime), it transparently falls back to\n * {@link SyncArchiveScoring} so recall never breaks.\n */\nexport class OffThreadArchiveScoring implements ArchiveScoringStrategy {\n private pool: ArchiveScoringWorkerPool | null = null;\n private poolFailed = false;\n private readonly syncFallback = new SyncArchiveScoring();\n\n constructor(poolSize?: number) {\n if (poolSize !== undefined) {\n this.pool = new ArchiveScoringWorkerPool(poolSize);\n }\n }\n\n async score(\n items: ReadonlyArray<ArchiveScoreItem>,\n tokens: ReadonlyArray<string>,\n abortSignal?: AbortSignal\n ): Promise<ArchiveScoreResult[]> {\n if (items.length === 0 || tokens.length === 0) return [];\n if (abortSignal?.aborted) return [];\n\n // Lazy pool init — workers are only created when the cold-fallback path\n // is first hit, so hot-path recall pays zero overhead.\n if (this.pool === null && !this.poolFailed) {\n try {\n this.pool = new ArchiveScoringWorkerPool();\n } catch (err) {\n this.poolFailed = true;\n log.debug(`archive-scoring: worker pool unavailable, using sync fallback — ${(err as Error).message}`);\n }\n }\n\n if (this.pool !== null) {\n const dispatchStart = Date.now();\n try {\n const task: ScoreTask = {\n items: items as ArchiveScoreItem[],\n tokens: tokens as string[],\n };\n const results = await this.pool.run(task, abortSignal);\n if (abortSignal?.aborted) return [];\n return results;\n } catch (err) {\n // Timeout or worker error — fall back to sync scoring so recall\n // quality is never silently dropped. An already-aborted signal\n // short-circuits first. If the dispatch consumed most of the timeout\n // budget (genuine timeout, not a fast error), skip the sync rescore —\n // the recall deadline has very likely expired by then (#1674).\n if (abortSignal?.aborted) return [];\n if (Date.now() - dispatchStart > DISPATCH_TIMEOUT_MS * 0.5) return [];\n log.debug(`archive-scoring: worker dispatch failed, using sync fallback — ${(err as Error).message}`);\n }\n }\n\n return this.syncFallback.score(items, tokens, abortSignal);\n }\n\n /** @internal — terminate the underlying pool (tests / shutdown). */\n async terminate(): Promise<void> {\n if (this.pool !== null) {\n await this.pool.terminate();\n this.pool = null;\n }\n }\n}\n\n// ─────────────────────────────────────────────────────────────────────────────\n// Factory + process-wide default\n// ─────────────────────────────────────────────────────────────────────────────\n\nlet defaultStrategy: ArchiveScoringStrategy | null = null;\n\n/**\n * Process-wide default archive-scoring strategy. Lazily creates an\n * {@link OffThreadArchiveScoring} on first use. All orchestrator instances\n * share one pool — a single daemon serves all concurrent sessions, so one\n * shared pool is the correct sizing unit.\n */\nexport function getDefaultArchiveScoring(): ArchiveScoringStrategy {\n if (defaultStrategy === null) {\n defaultStrategy = new OffThreadArchiveScoring();\n }\n return defaultStrategy;\n}\n\n/**\n * Dispose the process-wide default archive-scoring strategy, terminating any\n * worker threads. Called from `Orchestrator.destroy()` so worker threads don't\n * outlive the orchestrator (#1674). The strategy is lazily recreated on the\n * next cold-fallback recall, so this is safe to call from tests that create\n * and destroy orchestrator instances.\n */\nexport async function disposeDefaultArchiveScoring(): Promise<void> {\n if (defaultStrategy !== null) {\n const strategy = defaultStrategy;\n defaultStrategy = null;\n if (strategy instanceof OffThreadArchiveScoring) {\n await strategy.terminate();\n }\n }\n}\n\n/**\n * Create a fresh strategy instance (for tests that need isolation or\n * explicit control over pool size / sync vs off-thread).\n */\nexport function createArchiveScoring(opts?: {\n poolSize?: number;\n sync?: boolean;\n}): ArchiveScoringStrategy {\n if (opts?.sync) return new SyncArchiveScoring();\n return new OffThreadArchiveScoring(opts?.poolSize);\n}\n","/**\n * Turn-ingestion coordinator — extracted from the orchestrator\n * (issue #1526, seam 20).\n *\n * Owns the buffer-side entry points that feed the extraction pipeline:\n * - processTurn (per-turn buffering + trigger-mode flush decisions)\n * - observeSessionHeartbeat (heartbeat-driven extraction observer)\n * - queueBufferedExtraction (dedupe-gated extraction queueing)\n * - ingestReplayBatch / ingestBulkImportBatch (batch ingestion)\n * - maybeCapturePassiveCorrections (passive correction capture)\n *\n * Behavior-preserving move from orchestrator.ts. The orchestrator keeps\n * thin delegating methods; every member the moved code consults flows\n * back through TurnIngestionDeps live accessors/arrows so prototype-call\n * tests (Orchestrator.prototype.processTurn.call(fake, …)) and instance\n * stubs keep working (same late-binding rule as seams 18/19).\n */\n\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { SmartBuffer } from \"../buffer.js\";\nimport type { ImportTurn } from \"../bulk-import/types.js\";\nimport { resolvePipelineProcessingCapabilities, resolveRecallAuxiliaryCapabilities } from \"../capabilities.js\";\nimport type { CorrectionService } from \"../correction/correction-service.js\";\nimport { type PassiveCaptureConfig, capturePassiveCorrections } from \"../correction/passive-capture.js\";\nimport { detectPassiveCorrections } from \"../correction/passive-correction-detector.js\";\nimport { shouldSkipImplicitExtraction } from \"../explicit-capture.js\";\nimport { StorageManager } from \"../index.js\";\nimport { LcmEngine } from \"../lcm/index.js\";\nimport { log } from \"../logger.js\";\nimport { ExtractionQueueCoordinator } from \"./extraction-queue-coordinator.js\";\nimport { ExtractionRunCoordinator, type ExtractionRunResult } from \"./extraction-run.js\";\nimport { stripHandles } from \"../recall-handles.js\";\nimport { type ReplayTurn, normalizeReplaySessionKey } from \"../replay/types.js\";\nimport { SessionObserverState } from \"../session-observer-state.js\";\nimport { CODEX_THREAD_KEY_PREFIX } from \"../thread-key.js\";\nimport { TranscriptManager } from \"../transcript.js\";\nimport type { BufferTurn, PluginConfig } from \"../types.js\";\nimport {\n BulkImportBatchPartialFailureError,\n splitTurnsBySourceValidAt,\n targetSourceValidAtSortMs,\n type BulkImportBatchIngestResult,\n} from \"../orchestrator.js\";\n\nexport interface TurnIngestionDeps {\n readonly buffer: SmartBuffer;\n bulkImportWriteNamespace(): string;\n readonly config: PluginConfig;\n readonly extractionQueueCoordinator: ExtractionQueueCoordinator;\n getStorage(namespace?: string): Promise<StorageManager>;\n readonly heartbeatObserverChains: Map<string, Promise<void>>;\n readonly lcmEngine: LcmEngine | null;\n readonly passiveCorrectionDedup: Set<string>;\n passiveCorrectionService(): CorrectionService;\n readonly passiveCorrectionTelemetry: {\n detected: number;\n queued: number;\n autoApplied: number;\n suppressedReasonCounts: Record<string, number>;\n };\n queueBufferedExtraction(\n turnsToExtract: BufferTurn[],\n reason: \"trigger_mode\" | \"heartbeat_observer\",\n options?: {\n skipDedupeCheck?: boolean;\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n skipUserTurnThreshold?: boolean;\n extractionDeadlineMs?: number;\n failOnExtractionFailure?: boolean;\n onTaskSettled?: (\n error?: unknown,\n result?: ExtractionRunResult,\n ) => 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 * Pin the provenance principal (#1495 thread 1). Forwarded to\n * `runExtraction` so access `observe` can record provenance under the\n * authenticated principal instead of `resolvePrincipal(sessionKey)`.\n */\n principalOverride?: string;\n },\n ): Promise<void>;\n resolveMemoryIdOrHandle(ref: string, sessionKey?: string): string;\n runExtraction(\n ...args: Parameters<ExtractionRunCoordinator[\"runExtraction\"]>\n ): Promise<ExtractionRunResult>;\n readonly sessionObserver: SessionObserverState;\n shouldQueueExtraction(\n turns: BufferTurn[],\n options?: { commit?: boolean; bufferKey?: string },\n ): boolean;\n readonly transcript: TranscriptManager;\n}\n\nexport class TurnIngestionCoordinator {\n constructor(\n private readonly deps: TurnIngestionDeps,\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.deps.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 captureTimestamp = new Date().toISOString();\n // Issue #1582 hygiene §2 — strip any echoed `[m:xxxx]` handle before the\n // turn enters the extraction buffer so handles never become memory content\n // or get QMD-indexed (rule 23). Gated on the feature flag: when handles are\n // off none are ever injected, so there is nothing to strip and the buffer\n // stays byte-identical to the pre-#1582 path.\n const bufferedContent = this.deps.config.recallMemoryHandles\n ? stripHandles(content)\n : content;\n const turn: BufferTurn = {\n role,\n content: bufferedContent,\n timestamp: captureTimestamp,\n // #1578: anchor live-capture turns to wall-clock when bi-temporal is on;\n // replay/import turns carry sourceValidAt explicitly (codex P1).\n ...(this.deps.config.temporalBiTemporal\n ? { sourceValidAt: captureTimestamp }\n : {}),\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 outcome =\n typeof this.deps.buffer.addTurnWithOutcome === \"function\"\n ? await this.deps.buffer.addTurnWithOutcome(bufferKey, turn)\n : { decision: await this.deps.buffer.addTurn(bufferKey, turn) };\n\n if (outcome.decision === \"keep_buffering\") return;\n await this.deps.queueBufferedExtraction(\n outcome.extractionTurns ?? this.deps.buffer.getTurns(bufferKey),\n \"trigger_mode\",\n { bufferKey },\n );\n }\n\n async ingestReplayBatch(\n turns: ReplayTurn[],\n options: {\n deadlineMs?: number;\n archiveLcm?: boolean;\n abortSignal?: AbortSignal;\n /**\n * Pin extraction writes to this namespace instead of deriving one from\n * `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))` + the\n * coding overlay (#1495). The access `observe` surface resolves a single\n * effective scope plan and passes its `writeNamespace` here so the\n * extracted memories land in the SAME namespace as LCM archival,\n * objective-state snapshots, and project-scoped recall — without relying\n * on re-deriving the namespace from a namespace-prefixed session key.\n * Same hook bulk-import uses (#460).\n */\n writeNamespaceOverride?: string;\n /**\n * Pin the provenance PRINCIPAL instead of deriving it from\n * `resolvePrincipal(turn.sessionKey)` (#1495 thread 1). The access\n * `observe` surface authenticates the caller at the transport layer and\n * passes its resolved principal here so extracted-memory provenance uses\n * the SAME identity the surface authorized — independent of storage\n * routing (`writeNamespaceOverride`) and of whatever `resolvePrincipal`\n * would parse from the raw session key. Mirrors the recall path's\n * `principalOverride` (issue #570 PR 4).\n */\n principalOverride?: string;\n } = {},\n ): Promise<void> {\n if (!Array.isArray(turns) || turns.length === 0) return;\n if (options.abortSignal?.aborted) {\n throw options.abortSignal.reason instanceof Error\n ? options.abortSignal.reason\n : new Error(\"ingestReplayBatch aborted\");\n }\n if (shouldSkipImplicitExtraction(this.deps.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 sourceValidAt: turn.sourceValidAt,\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 replaySlices: Array<{\n bufferKey: string;\n order: number;\n targetValidAtMs: number;\n turns: BufferTurn[];\n }> = [];\n for (const [key, sessionTurns] of bySession.entries()) {\n if (sessionTurns.length === 0) continue;\n if (options.abortSignal?.aborted) {\n throw options.abortSignal.reason instanceof Error\n ? options.abortSignal.reason\n : new Error(\"ingestReplayBatch aborted\");\n }\n if (options.archiveLcm !== false && this.deps.lcmEngine?.enabled) {\n await this.deps.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 for (const sessionSlice of splitTurnsBySourceValidAt(sessionTurns)) {\n replaySlices.push({\n bufferKey: key,\n order: replaySlices.length,\n targetValidAtMs: targetSourceValidAtSortMs(sessionSlice),\n turns: sessionSlice,\n });\n }\n }\n\n const replayTasks = replaySlices\n .sort((a, b) => {\n if (a.targetValidAtMs < b.targetValidAtMs) return -1;\n if (a.targetValidAtMs > b.targetValidAtMs) return 1;\n if (a.order === b.order) return 0;\n return a.order < b.order ? -1 : 1;\n })\n .map(\n ({ bufferKey, turns: sessionSlice }) =>\n new Promise<void>((resolve, reject) => {\n void this.deps.queueBufferedExtraction(sessionSlice, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n skipUserTurnThreshold: true,\n bufferKey,\n extractionDeadlineMs: options.deadlineMs,\n abortSignal: options.abortSignal,\n writeNamespaceOverride: options.writeNamespaceOverride,\n principalOverride: options.principalOverride,\n onTaskSettled: (err) => (err ? reject(err) : resolve()),\n }).catch(reject);\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 * 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.deps.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 failOnExtractionFailure?: boolean;\n includeSourceValidAtContext?: boolean;\n } = {},\n ): Promise<BulkImportBatchIngestResult> {\n if (!Array.isArray(turns) || turns.length === 0) {\n return {\n attemptedTurnCount: 0,\n extractionCount: 0,\n persistedCount: 0,\n durableOutputCount: 0,\n skippedCount: 0,\n failedCount: 0,\n postPersistMetadataFailureCount: 0,\n processedTurnCount: 0,\n };\n }\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 shouldUseStableBatchKey = turns.some(\n (turn) =>\n turn.persistProcessedFingerprint === true ||\n (typeof turn.turnFingerprint === \"string\" &&\n turn.turnFingerprint.length > 0),\n );\n const stableBatchFingerprint = shouldUseStableBatchKey\n ? createHash(\"sha256\")\n .update(\n turns\n .map((turn) =>\n [\n turn.role,\n typeof turn.turnFingerprint === \"string\" &&\n turn.turnFingerprint.length > 0\n ? turn.turnFingerprint\n : turn.content.replace(/\\s+/g, \" \").trim(),\n ].join(\":\"),\n )\n .join(\"\\n\"),\n )\n .digest(\"hex\")\n .slice(0, 32)\n : undefined;\n const sessionKey = stableBatchFingerprint\n ? `bulk-import:batch:${stableBatchFingerprint}`\n : `bulk-import:batch:${Date.now().toString(36)}-${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 sourceValidAt: turn.timestamp,\n sessionKey,\n parts: turn.parts,\n rawContent: turn.rawContent,\n sourceFormat: turn.sourceFormat,\n importProvenance: turn.importProvenance,\n turnFingerprint: turn.turnFingerprint,\n persistProcessedFingerprint: turn.persistProcessedFingerprint === true,\n });\n }\n if (sessionTurns.length === 0) {\n return {\n attemptedTurnCount: 0,\n extractionCount: 0,\n persistedCount: 0,\n durableOutputCount: 0,\n skippedCount: 0,\n failedCount: 0,\n postPersistMetadataFailureCount: 0,\n processedTurnCount: 0,\n };\n }\n\n if (this.deps.lcmEngine?.enabled) {\n await this.deps.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 const sessionSlices = splitTurnsBySourceValidAt(sessionTurns, {\n includeContext: options.includeSourceValidAtContext !== false,\n });\n const results: ExtractionRunResult[] = [];\n let processedTurnCount = 0;\n let firstRejected: unknown;\n for (const sessionSlice of sessionSlices) {\n try {\n const result = await new Promise<ExtractionRunResult>(\n (resolve, reject) => {\n void this.deps.queueBufferedExtraction(sessionSlice, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n skipUserTurnThreshold: true,\n bufferKey: sessionKey,\n extractionDeadlineMs: options.deadlineMs,\n failOnExtractionFailure: options.failOnExtractionFailure === true,\n writeNamespaceOverride: this.deps.bulkImportWriteNamespace(),\n onTaskSettled: (err, result) =>\n err\n ? reject(err)\n : resolve(\n result ?? {\n status: \"skipped\",\n reason: \"missing_extraction_result\",\n persistedCount: 0,\n durableOutputCount: 0,\n },\n ),\n }).catch(reject);\n },\n );\n results.push(result);\n processedTurnCount += sessionSlice.filter(\n (turn) => turn.extractionContextOnly !== true,\n ).length;\n } catch (err) {\n firstRejected = err;\n break;\n }\n }\n const rejectedCount = firstRejected ? 1 : 0;\n const ingestResult: BulkImportBatchIngestResult = {\n attemptedTurnCount: sessionTurns.length,\n extractionCount: results.length,\n persistedCount: results.reduce(\n (sum, result) => sum + result.persistedCount,\n 0,\n ),\n durableOutputCount: results.reduce(\n (sum, result) => sum + result.durableOutputCount,\n 0,\n ),\n skippedCount: results.filter((result) => result.status === \"skipped\").length,\n failedCount: rejectedCount,\n postPersistMetadataFailureCount: results.filter(\n (result) => result.postPersistMetadataFailed === true,\n ).length,\n processedTurnCount:\n rejectedCount === 0 ? sessionTurns.length : processedTurnCount,\n };\n if (firstRejected) {\n if (processedTurnCount > 0) {\n throw new BulkImportBatchPartialFailureError(\n \"bulk import failed after partial processing\",\n ingestResult,\n firstRejected,\n );\n }\n throw firstRejected;\n }\n return ingestResult;\n }\n\n async observeSessionHeartbeat(\n sessionKey: string,\n options: { bufferKey?: string } = {},\n ): Promise<void> {\n if (resolvePipelineProcessingCapabilities(this.deps.config).sessionObserver !== 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.deps.heartbeatObserverChains.get(sessionKey) ?? Promise.resolve();\n const next = previous\n .catch(() => undefined)\n .then(async () => {\n const turns = this.deps.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.deps.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.deps.transcript.estimateSessionFootprint(sessionKey);\n const decision = await this.deps.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.deps.queueBufferedExtraction(turns, \"heartbeat_observer\", {\n bufferKey,\n });\n });\n\n this.deps.heartbeatObserverChains.set(sessionKey, next);\n try {\n await next;\n } finally {\n if (this.deps.heartbeatObserverChains.get(sessionKey) === next) {\n this.deps.heartbeatObserverChains.delete(sessionKey);\n }\n }\n }\n\n async queueBufferedExtraction(\n turnsToExtract: BufferTurn[],\n reason: \"trigger_mode\" | \"heartbeat_observer\",\n options: {\n skipDedupeCheck?: boolean;\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n skipUserTurnThreshold?: boolean;\n extractionDeadlineMs?: number;\n failOnExtractionFailure?: boolean;\n onTaskSettled?: (\n error?: unknown,\n result?: ExtractionRunResult,\n ) => 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 * Pin the provenance principal (#1495 thread 1). Forwarded to\n * `runExtraction` so access `observe` can record provenance under the\n * authenticated principal instead of `resolvePrincipal(sessionKey)`.\n */\n principalOverride?: string;\n } = {},\n ): Promise<void> {\n const bufferKey = options.bufferKey ?? turnsToExtract[0]?.sessionKey ?? \"default\";\n if (\n !options.skipDedupeCheck &&\n !this.deps.shouldQueueExtraction(turnsToExtract, { bufferKey })\n ) {\n log.debug(`extraction dedupe skip: preserving buffer (${reason})`);\n options.onTaskSettled?.(undefined, {\n status: \"skipped\",\n reason: \"dedupe\",\n persistedCount: 0,\n durableOutputCount: 0,\n });\n return;\n }\n\n const extractionDeadlineMs =\n typeof options.extractionDeadlineMs === \"number\" &&\n Number.isFinite(options.extractionDeadlineMs)\n ? options.extractionDeadlineMs\n : undefined;\n let timeout: ReturnType<typeof setTimeout> | undefined;\n let settled = false;\n const clearQueueWaitTimer = (): void => {\n if (timeout) {\n clearTimeout(timeout);\n timeout = undefined;\n }\n };\n const settleTask = (\n error?: unknown,\n result?: ExtractionRunResult,\n ): boolean => {\n if (settled) return false;\n settled = true;\n clearQueueWaitTimer();\n options.onTaskSettled?.(error, result);\n return true;\n };\n\n if (typeof extractionDeadlineMs === \"number\") {\n const remainingMs = extractionDeadlineMs - Date.now();\n if (remainingMs <= 0) {\n settleTask(new Error(\"replay extraction deadline exceeded (queue_wait)\"));\n return;\n }\n timeout = setTimeout(() => {\n settleTask(new Error(\"replay extraction deadline exceeded (queue_wait)\"));\n }, remainingMs);\n }\n\n this.deps.extractionQueueCoordinator.enqueue(async () => {\n if (settled) return;\n if (\n typeof extractionDeadlineMs === \"number\" &&\n extractionDeadlineMs <= Date.now()\n ) {\n settleTask(new Error(\"replay extraction deadline exceeded (queue_wait)\"));\n return;\n }\n clearQueueWaitTimer();\n try {\n const result = await this.deps.runExtraction(turnsToExtract, {\n clearBufferAfterExtraction:\n options.clearBufferAfterExtraction ?? true,\n skipCharThreshold: options.skipCharThreshold ?? false,\n skipUserTurnThreshold: options.skipUserTurnThreshold ?? false,\n deadlineMs: extractionDeadlineMs,\n bufferKey,\n abortSignal: options.abortSignal,\n failOnExtractionFailure: options.failOnExtractionFailure === true,\n writeNamespaceOverride: options.writeNamespaceOverride,\n principalOverride: options.principalOverride,\n });\n settleTask(undefined, result);\n } catch (err) {\n if (settleTask(err)) {\n throw err;\n }\n }\n });\n\n log.debug(`queued extraction from ${reason}`);\n }\n\n /**\n * Passive correction capture (issue #1581) — detects corrections expressed\n * passively in conversation turns and routes them to the Correction Contract\n * (#1580). Called from `runExtraction` after persistence completes.\n *\n * Thin wiring: delegates ALL correction logic to the detector + capture\n * modules + the CorrectionService. This method only checks gates, calls the\n * detector, and routes results. Fail-open: capture errors never block the\n * extraction return path.\n */\n async maybeCapturePassiveCorrections(\n turns: readonly BufferTurn[],\n opts: {\n sessionKey: string;\n principal?: string;\n namespace: string;\n bufferKey: string;\n isLiveSession: boolean;\n },\n ): Promise<void> {\n const mode = this.deps.config.correctionCaptureMode;\n if (mode === \"off\") return;\n if (!resolveRecallAuxiliaryCapabilities(this.deps.config).correction) return;\n\n try {\n const corrections = detectPassiveCorrections(\n turns.map((t) => ({ role: t.role, content: t.content })),\n );\n if (corrections.length === 0) return;\n\n // Replay/import: force queue-only mode even if config says auto.\n const effectiveMode = opts.isLiveSession ? mode : \"queue\";\n const captureConfig: PassiveCaptureConfig = {\n mode: effectiveMode,\n confidenceFloor: this.deps.config.correctionCaptureConfidenceFloor,\n autoApplyMaxAffected: this.deps.config.correctionCaptureAutoApplyMaxAffected,\n };\n\n const service = this.deps.passiveCorrectionService();\n const result = await capturePassiveCorrections(\n corrections,\n {\n correctionEnabled: resolveRecallAuxiliaryCapabilities(this.deps.config).correction,\n isLiveSession: opts.isLiveSession,\n bufferKey: opts.bufferKey,\n sessionKey: opts.sessionKey,\n principal: opts.principal,\n namespace: opts.namespace,\n },\n captureConfig,\n {\n planCorrection: (req) => service.plan(req),\n applyCorrection: (planId, applyOpts) => service.apply(planId, applyOpts),\n storageDir: async (ns) => (await this.deps.getStorage(ns)).dir,\n // Resolve `[m:xxxx]` handles to concrete memory ids via the single\n // shared helper (#1582). Returns null on miss/ambiguity so the\n // capture loop drops the handle and the planner falls back to text\n // search (review: \"memory handles not resolved\").\n resolveHandle: (ref, sessionKey) => {\n try {\n return this.deps.resolveMemoryIdOrHandle(ref, sessionKey);\n } catch {\n return null;\n }\n },\n },\n this.deps.passiveCorrectionDedup,\n );\n\n // Accumulate telemetry\n this.deps.passiveCorrectionTelemetry.detected += result.telemetry.detected;\n this.deps.passiveCorrectionTelemetry.queued += result.telemetry.queued;\n this.deps.passiveCorrectionTelemetry.autoApplied += result.telemetry.autoApplied;\n for (const [reason, count] of Object.entries(result.telemetry.suppressedReasons)) {\n this.deps.passiveCorrectionTelemetry.suppressedReasonCounts[reason] =\n (this.deps.passiveCorrectionTelemetry.suppressedReasonCounts[reason] ?? 0) + count;\n }\n } catch (err) {\n // Fail-open: passive capture never blocks extraction.\n log.debug(\n `passive-correction: capture failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n}\n","/**\n * Recall-introspection coordinator — extracted from the orchestrator\n * (issue #1526, seam 21).\n *\n * Owns the recall observability surfaces:\n * - last-intent / last-graph-recall / last-QMD-recall snapshot\n * recording, reading, and explain rendering\n * - console faithfulness distribution\n * - background direct-answer tier annotation (observation mode, #518)\n *\n * Behavior-preserving move from orchestrator.ts. The orchestrator keeps\n * thin delegating methods; all member access flows back through\n * RecallIntrospectionDeps live accessors/arrows (late-binding rule,\n * seams 18–20).\n */\n\nimport { mkdir, readFile, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { type CapabilitySet, resolveRecallAuxiliaryCapabilities } from \"../capabilities.js\";\nimport { type DirectAnswerSources, tryDirectAnswer } from \"../direct-answer-wiring.js\";\nimport type { FaithfulnessGateCounters } from \"../extraction-faithfulness.js\";\nimport { StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { GraphRecallCoordinator, type GraphRecallRankedResult, type GraphRecallShadowComparison } from \"./graph-recall-coordinator.js\";\nimport { buildRecallQueryPolicy } from \"../recall-query-policy.js\";\nimport { type GraphRecallExpandedEntry, LastRecallStore, clampGraphRecallExpandedEntries } from \"../recall-state.js\";\nimport { resolveScopePlan } from \"../scopes/scope-plan.js\";\nimport { DEFAULT_TAXONOMY } from \"../taxonomy/index.js\";\nimport { listTrustZoneRecords } from \"../trust-zones.js\";\nimport type { CodingContext, MemoryFile, MemoryIntent, PluginConfig, RecallPlanMode, RecallTierExplain } from \"../types.js\";\nimport {\n parseGraphRecallRankedResults,\n parseMemoryIntentSnapshot,\n parseQmdRecallResults,\n type GraphRecallSnapshot,\n type IntentDebugSnapshot,\n type QmdRecallSnapshot,\n} from \"../orchestrator.js\";\n\nexport interface RecallIntrospectionDeps {\n annotateDirectAnswerTier(\n prompt: string,\n sessionKey: string,\n namespaces: string[],\n expectedIdentity:\n | { writeNonce?: string; traceId?: string; recordedAt?: string }\n | undefined,\n caps: CapabilitySet,\n _parentAbortSignal?: AbortSignal,\n ): Promise<void>;\n readonly config: PluginConfig;\n directAnswerObservationChain: Promise<void>;\n effectiveCronRecallInstructionHeavyTokenCap(): number;\n readonly faithfulnessCounters: FaithfulnessGateCounters;\n getCodingContextForSession(sessionKey: string | undefined): CodingContext | null;\n getLastGraphRecallSnapshot(\n namespace?: string,\n ): Promise<GraphRecallSnapshot | null>;\n getLastIntentSnapshot(\n namespace?: string,\n ): Promise<IntentDebugSnapshot | null>;\n getLastQmdRecallSnapshot(\n namespace?: string,\n ): Promise<QmdRecallSnapshot | null>;\n getStorage(namespace?: string): Promise<StorageManager>;\n readonly graphRecallCoordinator: GraphRecallCoordinator;\n readonly lastRecall: LastRecallStore;\n resolveStateDirForNamespace(\n namespace: string,\n ): Promise<string>;\n readonly storageRouter: NamespaceStorageRouter;\n}\n\nexport class RecallIntrospectionCoordinator {\n constructor(\n private readonly deps: RecallIntrospectionDeps,\n ) {}\n\n /**\n * Faithfulness gate verdict distribution (issue #1576). Consumed by the\n * console-state aggregator so `remnic doctor` can render how the gate is\n * performing. Returns a fresh object so callers cannot mutate the\n * internal counters. Returns `undefined` when the gate is off so the\n * console-state snapshot omits the faithfulness block entirely (cursor\n * review: an all-zero block would otherwise always be truthy and leak\n * into snapshots that document it as absent-when-off).\n */\n getConsoleFaithfulnessDistribution(): FaithfulnessGateCounters | undefined {\n if (this.deps.config.extractionFaithfulnessGate === \"off\") return undefined;\n return { ...this.deps.faithfulnessCounters };\n }\n\n async getLastGraphRecallSnapshot(\n namespace?: string,\n ): Promise<GraphRecallSnapshot | null> {\n const storage = await this.deps.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.deps.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.deps.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.deps.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.deps.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.deps.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 /**\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.deps.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 enqueueDirectAnswerObservation(\n prompt: string,\n sessionKey: string,\n namespaceOverride: string | undefined,\n principalOverride: string | undefined,\n caps: CapabilitySet,\n namespacesEnabled: boolean,\n ): void {\n const expectedSnapshot = this.deps.lastRecall.get(sessionKey);\n if (expectedSnapshot === null) return;\n if (expectedSnapshot.plannerMode === \"no_recall\") return;\n\n // Resolve the observation namespace set through the SAME ScopePlan resolver\n // the main recall path uses (#1521). The observe path does NOT throw on an\n // unreadable override (it falls through to the coding/legacy branches), so\n // we skip the readability gate the recall path enforces.\n const observationScopePlan = resolveScopePlan({\n config: this.deps.config,\n sessionKey,\n namespace: namespaceOverride,\n principalOverride,\n codingContext: sessionKey\n ? this.deps.getCodingContextForSession(sessionKey)\n : null,\n namespacesEnabled,\n });\n const observationNamespaces = observationScopePlan.readNamespaces;\n const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: resolveRecallAuxiliaryCapabilities(this.deps.config).cronRecallPolicy,\n cronRecallNormalizedQueryMaxChars:\n this.deps.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.deps.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.deps.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.deps.directAnswerObservationChain;\n this.deps.directAnswerObservationChain = previous\n .catch(() => undefined)\n .then(async () => {\n try {\n await this.deps.annotateDirectAnswerTier(\n observationQuery,\n sessionKey,\n observationNamespaces,\n expectedIdentity,\n caps,\n undefined,\n );\n } catch (err) {\n log.debug(`direct-answer observation chain error: ${err}`);\n }\n });\n }\n\n async annotateDirectAnswerTier(\n prompt: string,\n sessionKey: string,\n namespaces: string[],\n expectedIdentity:\n | { writeNonce?: string; traceId?: string; recordedAt?: string }\n | undefined,\n caps: CapabilitySet,\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.deps.storageRouter.storageFor>>\n >();\n\n for (const ns of namespaces) {\n const storage = await this.deps.storageRouter.storageFor(ns);\n scopedStorages.set(ns, storage);\n const trustZones = await listTrustZoneRecords({\n memoryDir: storage.dir,\n trustZoneStoreDir: this.deps.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.deps.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.deps.config,\n enabled: caps.recallDirectAnswer,\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.deps.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 // Issue #1526 (seam 14): graph-recall snapshot moved to\n // GraphRecallCoordinator. Thin delegation keeps the private API stable.\n 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 return this.deps.graphRecallCoordinator.recordLastGraphRecallSnapshot(options);\n }\n\n 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 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 async recordLastIntentSnapshotForNamespace(options: {\n namespace: string;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n try {\n const stateDir = await this.deps.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","/**\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-]*$/;\nconst VALID_MEMORY_CATEGORIES = new Set([\n \"fact\",\n \"preference\",\n \"correction\",\n \"entity\",\n \"decision\",\n \"relationship\",\n \"principle\",\n \"commitment\",\n \"moment\",\n \"skill\",\n \"rule\",\n \"procedure\",\n \"reasoning_trace\",\n]);\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 for (const [index, rule] of cat.filingRules.entries()) {\n if (typeof rule !== \"string\" || rule.trim().length === 0) {\n throw new Error(\n `Taxonomy category \"${cat.id}\" filingRules[${index}] must be a non-empty string`,\n );\n }\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 for (const [index, memoryCategory] of cat.memoryCategories.entries()) {\n if (typeof memoryCategory !== \"string\" || memoryCategory.trim().length === 0) {\n throw new Error(\n `Taxonomy category \"${cat.id}\" memoryCategories[${index}] must be a non-empty string`,\n );\n }\n if (!VALID_MEMORY_CATEGORIES.has(memoryCategory)) {\n throw new Error(\n `Taxonomy category \"${cat.id}\" memoryCategories[${index}] is unknown: \"${memoryCategory}\"`,\n );\n }\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 if (typeof obj.version !== \"number\") {\n throw new Error(\"taxonomy.json version must be a number\");\n }\n if (!Array.isArray(obj.categories)) {\n throw new Error(\"taxonomy.json categories must be an array\");\n }\n\n const userVersion = obj.version;\n const userCategories = obj.categories as TaxonomyCategory[];\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","/**\n * Orchestrator-init coordinator — extracted from the orchestrator\n * (issue #1526, seam 22).\n *\n * Owns the startup lifecycle:\n * - initialize(): directory/storage/alias/policy bring-up and the\n * init gate that recall() awaits\n * - deferredInitialize(): background QMD probe, warmup, caches, cron\n * wiring, and the deferredReady gate\n * - startupSearchSync(): the initial search-index reconciliation\n *\n * Behavior-preserving move from orchestrator.ts. The async init ORDERING\n * is part of the gateway_start contract — the move keeps every await in\n * place and mutates the orchestrator's own gate fields (initPromise,\n * deferredReady, resolveDeferredReady, deferredInitAbort,\n * deferredSyncSucceeded, …) through live get/set accessors, so\n * stop/start reuse of one Orchestrator instance behaves identically.\n */\n\nimport { readdir, stat, unlink } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { SmartBuffer } from \"../buffer.js\";\nimport { resolveIndexingCapabilities, resolveLocalLlmCapabilities, resolveMemoryLifecycleCapabilities, resolveNamespaceCapabilities, resolveQmdCapabilities, resolveRecallAuxiliaryCapabilities, resolveUtilityLearningCapabilities } from \"../capabilities.js\";\nimport { CompoundingEngine } from \"../compounding/engine.js\";\nimport type { ConversationIndexBackend } from \"../conversation-index/backend.js\";\nimport type { CorrectionService } from \"../correction/correction-service.js\";\nimport { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport { ContentHashIndex, StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport { migrateFromEngram } from \"../migrate/from-engram.js\";\nimport { NamespaceCatalog } from \"../namespaces/catalog.js\";\nimport { NamespaceSearchRouter } from \"../namespaces/search.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { NegativeExampleStore } from \"../negative.js\";\nimport { MaintenanceScheduler } from \"./maintenance.js\";\nimport { PolicyRuntimeManager, type RuntimePolicyValues } from \"../policy-runtime.js\";\nimport { LastRecallStore, RecallHandleHistoryStore, TierMigrationStatusStore } from \"../recall-state.js\";\nimport { RelevanceStore } from \"../relevance.js\";\nimport { NoopSearchBackend } from \"../search/noop-backend.js\";\nimport type { SearchBackend } from \"../search/port.js\";\nimport { SessionObserverState } from \"../session-observer-state.js\";\nimport { SharedContextManager } from \"../shared-context/manager.js\";\nimport { HourlySummarizer } from \"../summarizer.js\";\nimport { TranscriptManager } from \"../transcript.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { type UtilityRuntimeValues, loadUtilityRuntimeValues } from \"../utility-runtime.js\";\nimport { WearablesService } from \"../wearables/service.js\";\nimport {\n COMPACTION_SIGNAL_MAX_AGE_MS,\n defaultWorkspaceDir,\n qmdStartupCollectionCheckWithTimeout,\n} from \"../orchestrator.js\";\n\nexport interface OrchestratorInitDeps {\n readonly buffer: SmartBuffer;\n readonly compounding?: CompoundingEngine;\n readonly config: PluginConfig;\n configuredNamespaceList(): string[];\n contentHashIndex: ContentHashIndex | null;\n readonly conversationIndexBackend?: ConversationIndexBackend;\n deferredInitAbort: AbortController | null;\n deferredInitialize(signal: AbortSignal): Promise<void>;\n deferredReady: Promise<void>;\n deferredSyncSucceeded: boolean;\n disposeSearchBackendIfNeeded(): Promise<void>;\n readonly embeddingFallback: EmbeddingFallback;\n getWearablesService(): WearablesService;\n readonly handleHistory: RecallHandleHistoryStore;\n readonly lastRecall: LastRecallStore;\n maintenanceNamespaces(\n jobName?: string,\n budgetMode?: \"cycle\" | \"unbounded\",\n ): Promise<string[]>;\n readonly maintenanceScheduler: MaintenanceScheduler;\n readonly namespaceCatalog: NamespaceCatalog;\n readonly namespaceSearchRouter: NamespaceSearchRouter;\n readonly negatives: NegativeExampleStore;\n passiveCorrectionService(): CorrectionService;\n readonly policyRuntime: PolicyRuntimeManager;\n qmd: SearchBackend;\n readonly relevance: RelevanceStore;\n resolveDeferredReady: (() => void) | null;\n resolveInit: (() => void) | null;\n runtimePolicyValues: RuntimePolicyValues | null;\n readonly sessionObserver: SessionObserverState;\n readonly sharedContext?: SharedContextManager;\n readonly storage: StorageManager;\n readonly storageRouter: NamespaceStorageRouter;\n readonly summarizer: HourlySummarizer;\n readonly tierMigrationStatus: TierMigrationStatusStore;\n readonly transcript: TranscriptManager;\n utilityRuntimeValues: UtilityRuntimeValues | null;\n validateLocalLlmModel(): Promise<void>;\n wearablesAutoSyncHandle: { stop(): Promise<void> } | null;\n}\n\nexport class OrchestratorInitCoordinator {\n constructor(\n private readonly deps: OrchestratorInitDeps,\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.deps.deferredReady = new Promise<void>((resolve) => {\n this.deps.resolveDeferredReady = resolve;\n });\n\n try {\n await migrateFromEngram({\n quiet: true,\n logger: (message) => log.info(message),\n });\n await this.deps.storage.ensureDirectories();\n await this.deps.storage.loadAliases();\n if (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n const namespaces = new Set<string>([\n this.deps.config.defaultNamespace,\n this.deps.config.sharedNamespace,\n ...this.deps.config.namespacePolicies.map((p) => p.name),\n ]);\n for (const ns of namespaces) {\n const sm = await this.deps.storageRouter.storageFor(ns);\n await sm.ensureDirectories();\n await sm.loadAliases().catch(() => undefined);\n }\n // Explicitly seed the catalog with all configured namespaces at startup\n // (round 6, cursor Medium — NBLlR). The storageFor loop above fires the\n // router's onResolve hook, but a warm router cache (reused instance\n // across stop/start) can skip onResolve, leaving policy namespaces absent\n // from the live catalog until an operator runs `rebuild --apply`. This\n // call is cheap, idempotent, and best-effort: a catalog failure must\n // never break initialization (rule #13, #40).\n await this.deps.namespaceCatalog.registerConfiguredNamespaces().catch(() => undefined);\n }\n // #1713 Item 2: recover stale `applying` correction plans left behind\n // by a process that died mid-apply. Best-effort — a failure here must\n // never block initialization (rule 13). Runs for every configured\n // namespace since correction plans can exist in any of them.\n try {\n // #1713 Item 2 + P2 (cursor): sweep ALL known namespaces — configured\n // + catalog-discovered — so stale applying plans in derived namespaces\n // (coding-scoped, session-derived) are also recovered.\n const correctionNamespaces = new Set(this.deps.configuredNamespaceList());\n if (this.deps.namespaceCatalog.enabled) {\n try {\n for (const rec of await this.deps.namespaceCatalog.listNamespaces()) {\n correctionNamespaces.add(rec.namespace);\n }\n } catch { /* best-effort */ }\n }\n const recovered = await this.deps.passiveCorrectionService().recoverStaleApplyingPlans(\n [...correctionNamespaces],\n );\n if (recovered > 0) {\n log.info(`correction: recovered ${recovered} stale applying plan(s) on startup`);\n }\n } catch (staleErr) {\n log.debug(`correction: stale-plan recovery skipped: ${staleErr instanceof Error ? staleErr.message : String(staleErr)}`);\n }\n await this.deps.relevance.load();\n await this.deps.negatives.load();\n await this.deps.lastRecall.load();\n await this.deps.handleHistory.load();\n await this.deps.tierMigrationStatus.load();\n await this.deps.sessionObserver.load();\n this.deps.runtimePolicyValues = await this.deps.policyRuntime.loadRuntimeValues();\n this.deps.utilityRuntimeValues = await loadUtilityRuntimeValues({\n memoryDir: this.deps.config.memoryDir,\n memoryUtilityLearningEnabled: resolveUtilityLearningCapabilities(this.deps.config).memoryUtilityLearning,\n promotionByOutcomeEnabled: resolveUtilityLearningCapabilities(this.deps.config).promotionByOutcome,\n });\n\n // Initialize content-hash dedup index\n if (resolveRecallAuxiliaryCapabilities(this.deps.config).factDeduplication) {\n this.deps.contentHashIndex = this.deps.storage.createContentHashIndex();\n await this.deps.contentHashIndex.load();\n log.info(\n `content-hash dedup: loaded ${this.deps.contentHashIndex.size} hashes`,\n );\n }\n await this.deps.transcript.initialize();\n await this.deps.summarizer.initialize();\n if (this.deps.sharedContext) {\n await this.deps.sharedContext.ensureStructure();\n }\n if (this.deps.compounding) {\n await this.deps.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.deps.buffer.load();\n } catch (bufErr) {\n log.error(\n `buffer.load() failed (init gate will still open): ${bufErr}`,\n );\n this.deps.buffer.resetToEmpty();\n }\n if (resolveRecallAuxiliaryCapabilities(this.deps.config).compactionReset) {\n try {\n const wsDir = this.deps.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.deps.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.deps.qmd.probe();\n if (available) {\n log.info(`Search backend: available ${this.deps.qmd.debugStatus()}`);\n // Ensure collections at startup for the catalog-union namespace set, not\n // just the configured set (issue #1499 sweep, same class as NHZEV): a\n // dynamic namespace that exists only in the persisted catalog must have\n // its QMD collection checked/ensured on boot so recall against it works\n // after a restart. `registerConfiguredNamespaces()` already seeded the\n // catalog above, so `maintenanceNamespaces()` is readable here; it falls\n // back to the configured set on any catalog read failure.\n const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.maintenanceNamespaces()\n : [this.deps.config.defaultNamespace];\n const states = await Promise.all(\n namespaces.map(async (namespace) => {\n const collectionCheckAbort = new AbortController();\n const state = await qmdStartupCollectionCheckWithTimeout(\n resolveNamespaceCapabilities(this.deps.config).namespaces\n ? this.deps.namespaceSearchRouter.ensureNamespaceCollection(\n namespace,\n { signal: collectionCheckAbort.signal },\n )\n : this.deps.qmd.ensureCollection(\n this.deps.config.memoryDir,\n this.deps.config.qmdCollection,\n { signal: collectionCheckAbort.signal },\n ),\n collectionCheckAbort,\n namespace,\n );\n return { namespace, state };\n }),\n );\n const defaultState =\n states.find(\n (entry) => entry.namespace === this.deps.config.defaultNamespace,\n )?.state ?? \"unknown\";\n if (defaultState === \"missing\") {\n await this.deps.disposeSearchBackendIfNeeded();\n this.deps.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.deps.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.deps.qmd instanceof NoopSearchBackend) {\n log.debug(`Search backend: noop (search intentionally disabled)`);\n } else {\n log.warn(`Search backend: not available ${this.deps.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.deps.resolveInit) {\n this.deps.resolveInit();\n this.deps.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.deps.qmd is finalized.\n //\n // Capture the resolver by value so a concurrent re-initialize() cannot\n // overwrite this.deps.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.deps.resolveDeferredReady;\n this.deps.resolveDeferredReady = null;\n this.deps.deferredInitAbort = new AbortController();\n this.deps.deferredInitialize(this.deps.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.deps.resolveInit) {\n this.deps.resolveInit();\n this.deps.resolveInit = null;\n }\n if (this.deps.resolveDeferredReady) {\n this.deps.resolveDeferredReady();\n this.deps.resolveDeferredReady = null;\n }\n throw err;\n }\n }\n\n async deferredInitialize(signal: AbortSignal): Promise<void> {\n const lifecycleCaps = resolveMemoryLifecycleCapabilities(this.deps.config);\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.deps.qmd.isAvailable() && resolveQmdCapabilities(this.deps.config).qmdMaintenance) {\n try {\n log.info(\"QMD startup sync: updating index to match current disk state\");\n if (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n // Cover cataloged dynamic namespaces at startup too (NHZEV, codex P2):\n // a dynamic namespace written before a daemon restart must be synced on\n // boot, not only by the debounced runQmdMaintenance() path. Same union +\n // catalog-read-failure fallback as runQmdMaintenance.\n await this.deps.namespaceSearchRouter.updateNamespaces(\n await this.deps.maintenanceNamespaces(),\n { signal },\n );\n } else {\n await this.deps.qmd.update({ signal });\n }\n log.info(\"QMD startup sync: complete\");\n this.deps.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.deps.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.deps.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.deps.qmd.isAvailable()) {\n const warmupNs = this.deps.config.defaultNamespace;\n log.info(\"QMD warmup: pre-loading models with a test search\");\n warmupPromises.push(\n this.deps.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 (resolveMemoryLifecycleCapabilities(this.deps.config).embeddingFallback) {\n warmupPromises.push(\n this.deps.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 (resolveRecallAuxiliaryCapabilities(this.deps.config).knowledgeIndex) {\n cacheWarmups.push(\n (async () => {\n try {\n const t0 = Date.now();\n await this.deps.storage.buildKnowledgeIndex(this.deps.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.deps.storage.readAllMemories().then(() => {}).catch(() => {}));\n cacheWarmups.push(this.deps.storage.readAllEntityFiles().then(() => {}).catch(() => {}));\n await Promise.all(cacheWarmups);\n if (signal.aborted) return;\n\n if (resolveIndexingCapabilities(this.deps.config).conversationIndex && this.deps.conversationIndexBackend) {\n try {\n const init = await this.deps.conversationIndexBackend.initialize();\n if (!init.enabled) {\n this.deps.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.deps.config.conversationIndexEnabled = false;\n }\n }\n\n if (signal.aborted) return;\n\n if (resolveLocalLlmCapabilities(this.deps.config).localLlm) {\n try {\n await this.deps.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 // Auto-register every cron job in one pass. Each registration is gated\n // by its config flag inside the scheduler and individually non-fatal\n // (issue #1526 PR1 — moved to MaintenanceScheduler).\n await this.deps.maintenanceScheduler.autoRegisterCrons(signal);\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 (lifecycleCaps.lifecyclePolicy && resolveQmdCapabilities(this.deps.config).qmdTierMigration) {\n try {\n const { runFirstStartMigration } = await import(\"../maintenance/first-start-migration.js\"\n );\n const result = await runFirstStartMigration({\n storage: this.deps.storage,\n config: this.deps.config,\n qmd: this.deps.qmd,\n hotCollection: this.deps.config.qmdCollection,\n coldCollection: this.deps.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 // Wearables auto-sync: in-process periodic transcript refresh for\n // long-lived hosts (default on). Today's transcript keeps growing\n // while the wearable records; a once-per-local-day deep pass picks\n // up late uploads and provider re-processing. Static config gate —\n // sources can't appear at runtime, so checking once here is safe.\n // The timer is unref'd, so one-shot CLI runs exit naturally without\n // ever ticking; idempotent across stop/start cycles via the handle\n // guard. Non-fatal: a failure to start must not break init.\n if (signal.aborted) return;\n if (\n !this.deps.wearablesAutoSyncHandle &&\n this.deps.config.wearables.enabled &&\n this.deps.config.wearables.autoSyncEnabled &&\n Object.values(this.deps.config.wearables.sources).some((source) => source.enabled)\n ) {\n try {\n const { startWearablesAutoSync } = await import(\"../wearables/auto-sync.js\");\n // Re-check after the await: destroy() may have aborted while\n // the import was in flight, having found no handle to stop —\n // starting now would leave a live interval on a destroyed\n // orchestrator (Cursor review on PR #1464). Handle creation\n // below is synchronous, so no further window exists.\n if (signal.aborted) return;\n this.deps.wearablesAutoSyncHandle = startWearablesAutoSync(\n {\n intervalMinutes: this.deps.config.wearables.autoSyncIntervalMinutes,\n days: this.deps.config.wearables.autoSyncDays,\n deepDays: this.deps.config.wearables.autoSyncDeepDays,\n ...(this.deps.config.wearables.timezone !== undefined\n ? { timezone: this.deps.config.wearables.timezone }\n : {}),\n },\n {\n sync: (options) => this.deps.getWearablesService().sync(options),\n log: {\n info: (message) => log.info(message),\n warn: (message) => log.warn(message),\n },\n },\n );\n log.info(\n `wearables auto-sync started: every ${this.deps.config.wearables.autoSyncIntervalMinutes}m over ${this.deps.config.wearables.autoSyncDays}d (deep ${this.deps.config.wearables.autoSyncDeepDays}d daily)`,\n );\n } catch (err) {\n const { displayErrorDetail } = await import(\"../runtime/better-sqlite.js\");\n log.warn(\n `wearables auto-sync failed to start (non-fatal): ${displayErrorDetail(err)}`,\n );\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.deps.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.deps.qmd.debugStatus()}`);\n\n // Clear namespace router cache so re-probe picks up newly available backends\n if (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n this.deps.namespaceSearchRouter.clearCache();\n }\n\n // Ensure collections — namespace-aware when enabled.\n // Use the catalog-union namespace set (issue #1499 sweep, same class as\n // NHZEV): this is the QMD startup-recovery sync that ensures collections AND\n // runs `updateNamespaces(...)` below over the SAME `namespaces` set. A dynamic\n // namespace that exists only in the persisted catalog must be ensured and\n // re-synced here too, otherwise after a backend-was-unavailable-at-boot\n // recovery its collection stays stale. Falls back to the configured set on any\n // catalog read failure.\n const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.maintenanceNamespaces()\n : [this.deps.config.defaultNamespace];\n\n const states = await Promise.all(\n namespaces.map(async (namespace) => ({\n namespace,\n state: resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.namespaceSearchRouter.ensureNamespaceCollection(namespace, { signal })\n : await this.deps.qmd.ensureCollection(this.deps.config.memoryDir, this.deps.config.qmdCollection, { signal }),\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.deps.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.deps.qmd before the reassignment) would observe\n // isAvailable()===true against a backend with a missing collection.\n if (\"available\" in this.deps.qmd) {\n (this.deps.qmd as any).available = false;\n }\n await this.deps.disposeSearchBackendIfNeeded();\n this.deps.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 (resolveQmdCapabilities(this.deps.config).qmdMaintenance) {\n try {\n const failTsBefore = \"lastUpdateFailedAtMs\" in this.deps.qmd\n ? (this.deps.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const hasRunTs = \"lastUpdateRanAtMs\" in this.deps.qmd;\n if (\"resetUpdateThrottles\" in this.deps.qmd) {\n (this.deps.qmd as any).resetUpdateThrottles();\n }\n log.info(\"startupSearchSync: updating index to match current disk state\");\n let namespacesUpdated = 0;\n if (resolveNamespaceCapabilities(this.deps.config).namespaces) {\n namespacesUpdated = await this.deps.namespaceSearchRouter.updateNamespaces(\n namespaces,\n { signal },\n );\n } else {\n await this.deps.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.deps.qmd\n ? (this.deps.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const runTsAfter = hasRunTs\n ? (this.deps.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 (resolveNamespaceCapabilities(this.deps.config).namespaces) {\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.deps.qmd.search(\"warmup\", this.deps.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 * Persistence-index coordinator — extracted from the orchestrator\n * (issue #1526, seam 23).\n *\n * Owns the post-persist bookkeeping that extraction-persist and\n * consolidation delegate back through the orchestrator:\n * - content-hash dedup index add/has/remove/save\n * - temporal-bounds backfill on dedup hits (bitemporal, #1578)\n * - temporal tag index updates and persisted-memory indexing\n * - graph edge construction for newly persisted memories\n * - semantic dedup candidate lookup\n *\n * Behavior-preserving move from orchestrator.ts (late-binding deps rule,\n * seams 18–22).\n */\n\nimport path from \"node:path\";\nimport { type GraphConstructionCapabilitySet, resolveCapabilities, resolveGraphConstructionCapabilities, resolveIndexingCapabilities, resolveMemoryLifecycleCapabilities, resolveNamespaceCapabilities } from \"../capabilities.js\";\nimport type { SemanticDedupHit } from \"../dedup/semantic.js\";\nimport { EmbeddingFallback } from \"../embedding-fallback.js\";\nimport { GraphIndex } from \"../graph.js\";\nimport { ContentHashIndex, StorageManager } from \"../index.js\";\nimport { log } from \"../logger.js\";\nimport { isActiveMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { stripCitationForTemplate } from \"../source-attribution.js\";\nimport { clearIndexes, indexMemoriesBatch, indexesExist } from \"../temporal-index.js\";\nimport { normalizeSupersessionKey } from \"../temporal-supersession.js\";\nimport type { MemoryFile, MemoryFrontmatter, PluginConfig } from \"../types.js\";\nimport {\n resolveRecentThreadMemoryPaths,\n} from \"../orchestrator.js\";\n\nexport interface PersistenceIndexDeps {\n readonly config: PluginConfig;\n readonly contentHashIndex: ContentHashIndex | null;\n contentHashIndexForStorage(\n targetStorage: StorageManager,\n ): Promise<ContentHashIndex | null>;\n readonly contentHashIndexesByStorageDir: Map<string, ContentHashIndex>;\n readonly embeddingFallback: EmbeddingFallback;\n graphIndexFor(storage: StorageManager): GraphIndex;\n readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]>;\n semanticDedupScopeFor(targetStorage: StorageManager): {\n pathPrefix?: string;\n pathExcludePrefixes?: readonly string[];\n };\n}\n\nexport class PersistenceIndexCoordinator {\n constructor(\n private readonly deps: PersistenceIndexDeps,\n ) {}\n\n async hasContentHashDedup(\n targetStorage: StorageManager,\n content: string,\n ): Promise<boolean> {\n const index = await this.deps.contentHashIndexForStorage(targetStorage);\n return index ? index.has(content) : false;\n }\n\n async addContentHashDedup(\n targetStorage: StorageManager,\n content: string,\n ): Promise<void> {\n const index = await this.deps.contentHashIndexForStorage(targetStorage);\n if (!index) return;\n index.add(content);\n }\n\n async removeContentHashForMemory(\n targetStorage: StorageManager,\n memory: MemoryFile,\n context: string,\n ): Promise<void> {\n const index = await this.deps.contentHashIndexForStorage(targetStorage);\n if (!index) return;\n\n if (memory.frontmatter.contentHash) {\n index.removeByHash(memory.frontmatter.contentHash);\n return;\n }\n\n log.warn(\n `[${context}] removing hash for legacy memory ${memory.frontmatter.id ?? \"(unknown)\"} via content fallback - no contentHash in frontmatter`,\n );\n index.remove(memory.content);\n }\n\n /**\n * Issue #1671 — backfill bi-temporal bounds onto an existing promoted/deduped\n * copy that was written BEFORE the source fact carried a resolved\n * `invalid_at`/`observedAt`/`eventTimeSource`.\n *\n * On re-extraction/backfill, a fact may now carry a resolved end bound (e.g.\n * \"until June 2025\") that the existing copy lacks because it was promoted\n * before bi-temporal wiring existed. Without this backfill, recall keeps\n * surfacing an expired fact even though the source copy now expires correctly.\n *\n * Finds the active fact in `targetStorage` matching `dedupContent`, then\n * patches the temporal frontmatter the existing copy is missing. Best-effort\n * / fail-open — any I/O error is logged and swallowed so the dedup\n * short-circuit is never blocked by a backfill failure.\n *\n * Matching: the stored `frontmatter.contentHash` is compared against\n * `ContentHashIndex.computeHash(dedupContent)` first (the exact hash the\n * content-hash index uses), then falls back to stripping citations and\n * comparing normalized bodies. This handles inline-attribution deployments\n * where the persisted body carries a citation marker the dedup key does not.\n *\n * I/O gate: only triggers when `invalidAt` is present (the end bound that\n * actually changes recall behavior by expiring the fact). `observedAt` and\n * `eventTimeSource` alone don'\\''t expire a fact, so backfilling them without\n * an end bound would cause a full readAllMemories scan on every dedup hit\n * under biTemporal for no recall benefit.\n *\n * Only patches fields the existing copy LACKS — never overwrites a bound the\n * copy already carries.\n */\n async backfillTemporalBoundsOnDedupHit(\n targetStorage: StorageManager,\n dedupContent: string,\n bounds: {\n invalidAt?: string;\n // #1707 thread 2 — per-fact start bound (valid_at). Carried so a\n // re-extracted duplicate whose event time yields only a start bound\n // (\"since 2024\", \"yesterday\", an absolute date) gets the corrected\n // per-fact anchoring onto the existing copy.\n validFrom?: string;\n observedAt?: string;\n eventTimeSource?: \"extracted\" | \"assumed\";\n },\n entityRef?: string,\n ): Promise<void> {\n // I/O gate: scan when there is a recall-relevant bound to backfill —\n // either an end bound (invalidAt, which expires the fact) or a corrected\n // EXTRACTED start bound. A start bound only changes recall when it is\n // extracted (the as-of filter excludes facts whose valid_at is after the\n // as-of instant); an \"assumed\" validFrom is just the ingestion anchor\n // (resolveFactEventTime sets one for every fact), so scanning on it would\n // run a full readAllMemories on every bi-temporal dedup hit for no benefit\n // (review cursor PRRT_OvHk / codex PRRT_OvHxVH). observedAt and\n // eventTimeSource alone never change recall.\n const hasExtractedStart =\n bounds.validFrom !== undefined && bounds.eventTimeSource === \"extracted\";\n if (!bounds.invalidAt && !hasExtractedStart) return;\n try {\n const incomingHash = ContentHashIndex.computeHash(dedupContent);\n const normalizedIncoming = ContentHashIndex.normalizeContent(dedupContent);\n // Normalize the entity for same-entity scoping when provided — two\n // entities can share identical fact text, and patching a different\n // entity'\\''s fact would corrupt its temporal bounds (cursor review).\n const incomingEntityNorm = entityRef\n ? normalizeSupersessionKey(entityRef)\n : undefined;\n const all = await targetStorage.readAllMemories();\n const existing = all.find((m) => {\n if (m.frontmatter.category !== \"fact\") return false;\n if ((m.frontmatter.status ?? \"active\") !== \"active\") return false;\n // Same-entity guard: reject only when the stored fact carries a\n // DIFFERENT entity (two entities can share identical fact text, so\n // patching the other entity's copy would corrupt its bounds — codex\n // P2 PRRT_OvB4A). Legacy facts written before entity linkage (no\n // entityRef) have no entity to conflict with, so they stay eligible\n // for backfill (cursor PRRT_OvKnV: the guard must NOT silently\n // no-op for older promoted copies that predate entity linkage).\n if (\n incomingEntityNorm &&\n m.frontmatter.entityRef &&\n normalizeSupersessionKey(m.frontmatter.entityRef) !== incomingEntityNorm\n ) {\n return false;\n }\n // Prefer the stored contentHash (what the hash index actually keys\n // on) — it is computed from contentHashSource (the raw/enriched\n // body before citation), matching the dedupContent the caller passes.\n if (m.frontmatter.contentHash) {\n return m.frontmatter.contentHash === incomingHash;\n }\n // Legacy facts without a stored hash: strip citations then compare\n // normalized bodies so inline-attribution markers don'\\''t prevent\n // a match.\n return (\n ContentHashIndex.normalizeContent(\n stripCitationForTemplate(m.content ?? \"\", this.deps.config.inlineSourceAttributionFormat),\n ) === normalizedIncoming\n );\n });\n if (!existing) return;\n // Build a patch containing ONLY the fields the existing copy lacks.\n const patch: Partial<MemoryFrontmatter> = {};\n const fm = existing.frontmatter;\n if (bounds.invalidAt && (!fm.invalid_at || fm.invalid_at.length === 0)) {\n patch.invalid_at = bounds.invalidAt;\n }\n if (bounds.observedAt && (!fm.observedAt || fm.observedAt.length === 0)) {\n patch.observedAt = bounds.observedAt;\n }\n if (\n bounds.eventTimeSource &&\n (!fm.eventTimeSource || fm.eventTimeSource.length === 0)\n ) {\n patch.eventTimeSource = bounds.eventTimeSource;\n }\n // #1707 thread 2 — per-fact-anchored start bound. A re-extracted\n // duplicate whose event time resolves a real start bound must carry\n // that anchor onto the existing copy so as-of recall uses the corrected\n // valid_at instead of a stale batch-anchored value. Only an EXTRACTED\n // bound corrects; an \"assumed\" bound is just the ingestion anchor.\n //\n // No-clobber via equality, not provenance inference: exact-content dedup\n // re-extracts the SAME event-time expression, which #1670 per-fact\n // anchoring resolves deterministically to the same validFrom — so for\n // stable content the incoming validFrom EQUALS the copy's valid_at and\n // we skip the redundant write (the only no-clobber that holds without a\n // fragile provenance heuristic — review codex PRRT_Ov7LKC). When they\n // differ (a prior batch/assumed anchor, end-only assumed start, or a\n // non-deterministic re-resolution), the extracted validFrom is the\n // authoritative correction and overwrites. The eventTimeSource upgrade\n // below records that the start is now extracted-anchored.\n if (\n bounds.validFrom &&\n bounds.eventTimeSource === \"extracted\" &&\n fm.valid_at !== bounds.validFrom\n ) {\n patch.valid_at = bounds.validFrom;\n // Mark the copy extracted-anchored in the SAME patch so its provenance\n // reflects the correction (review cursor PRRT_OvHM / codex PRRT_OvHxVD):\n // without this, a copy upgraded from \"assumed\" would keep \"assumed\"\n // provenance while carrying an extracted start. (The earlier\n // eventTimeSource block only fills an EMPTY source.)\n if (fm.eventTimeSource !== \"extracted\") {\n patch.eventTimeSource = \"extracted\";\n }\n }\n if (Object.keys(patch).length === 0) return;\n const ok = await targetStorage.writeMemoryFrontmatter(existing, patch);\n if (ok) {\n log.debug(\n `bitemporal-backfill: patched ${Object.keys(patch).join(\",\")} onto existing fact ${fm.id ?? \"(unknown)\"} in ${targetStorage.dir}`,\n );\n }\n } catch (err) {\n log.warn(\n `bitemporal-backfill: failed open for ${targetStorage.dir}: ${err}`,\n );\n }\n }\n\n async saveContentHashIndexes(): Promise<void> {\n const indexes = new Set<ContentHashIndex>();\n if (this.deps.contentHashIndex) indexes.add(this.deps.contentHashIndex);\n for (const index of this.deps.contentHashIndexesByStorageDir.values()) {\n indexes.add(index);\n }\n for (const index of indexes) {\n await index.save();\n }\n }\n\n async indexPersistedMemory(\n storage: StorageManager,\n memoryId: string,\n ): Promise<void> {\n if (!resolveMemoryLifecycleCapabilities(this.deps.config).embeddingFallback) return;\n if (!(await this.deps.embeddingFallback.isAvailable())) return;\n const memory = await storage.getMemoryById(memoryId);\n if (!memory) return;\n await this.deps.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 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 graphCaps: GraphConstructionCapabilitySet = resolveGraphConstructionCapabilities(this.deps.config),\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 graphCaps.graphWriteSessionAdjacency &&\n fallbackCausalPredecessor &&\n fallbackCausalPredecessor !== memoryRelPath\n ) {\n recentInThread.push(fallbackCausalPredecessor);\n }\n const causalPredecessor =\n recentInThread[recentInThread.length - 1] ?? fallbackCausalPredecessor;\n await this.deps.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 graphCapsOverride: {\n entityGraph: graphCaps.entityGraph,\n timeGraph: graphCaps.timeGraph,\n causalGraph: graphCaps.causalGraph,\n multiGraphMemory: graphCaps.multiGraphMemory,\n },\n });\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 async updateTemporalTagIndexes(\n storage: StorageManager,\n persistedIds: string[],\n ): Promise<void> {\n const caps = resolveCapabilities(this.deps.config); // #1566 Cluster C\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 !resolveIndexingCapabilities(this.deps.config).queryAwareIndexing &&\n !caps.parallelRetrieval\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.deps.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 && resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.readAllMemoriesForNamespaces(\n Array.from(\n new Set<string>([\n this.deps.config.defaultNamespace,\n this.deps.config.sharedNamespace,\n ...this.deps.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.deps.config.memoryDir);\n if (entries.length > 0) {\n indexMemoriesBatch(this.deps.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.deps.config.memoryDir, entries);\n }\n } catch (err) {\n log.debug(`temporal-index update failed (non-fatal): ${err}`);\n }\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 (!resolveMemoryLifecycleCapabilities(this.deps.config).embeddingFallback) {\n throw new Error(\"semantic dedup: embedding backend not configured\");\n }\n if (!(await this.deps.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.deps.semanticDedupScopeFor(targetStorage);\n const hits = await this.deps.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 * Workspace-ops coordinator — extracted from the orchestrator\n * (issue #1526, seam 24).\n *\n * Owns the periodic workspace/operations surfaces:\n * - day-summary fact gathering (gatherTodayFacts)\n * - memory-action policy preview (previewMemoryActionEvent)\n * - file hygiene runs and identity auto-consolidation\n * - wearables service construction\n * - local-LLM model validation\n * - pattern-reinforcement runs and their namespace fanout\n * - access-tracking flush\n *\n * Behavior-preserving move from orchestrator.ts (late-binding deps rule,\n * seams 18–23).\n */\n\nimport { lstat, mkdir, readFile, readdir, realpath, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolveCompressionCapabilities, resolveConsolidationCapabilities, resolveNamespaceCapabilities } from \"../capabilities.js\";\nimport { formatDaySummaryMemories } from \"../day-summary.js\";\nimport { type JudgeVerdict, judgeFactDurability } from \"../extraction-judge.js\";\nimport { ExtractionEngine } from \"../extraction.js\";\nimport { FallbackLlmClient, fallbackLlmRuntimeContextFromConfig } from \"../fallback-llm.js\";\nimport { lintWorkspaceFiles, rotateMarkdownFileToArchive } from \"../hygiene.js\";\nimport { StorageManager } from \"../index.js\";\nimport { LocalLlmClient } from \"../local-llm.js\";\nimport { log } from \"../logger.js\";\nimport type { NamespaceMaintenanceFanoutRunnerContext } from \"../maintenance/namespace-maintenance-fanout.js\";\nimport type { NamespaceMaintenanceSummary } from \"../maintenance/namespace-planner.js\";\nimport { type PatternReinforcementResult, runPatternReinforcement } from \"../maintenance/pattern-reinforcement.js\";\nimport { evaluateMemoryActionPolicy } from \"../memory-action-policy.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { parseMemoryActionEligibilityContext } from \"../schemas.js\";\nimport type { SearchBackend } from \"../search/port.js\";\nimport { type AccessTrackingEntry, type MemoryActionEvent, type MemoryFile, type PluginConfig, confidenceTier } from \"../types.js\";\nimport { RECALL_FALLBACK_DIRS } from \"../utils/category-dir.js\";\nimport { assertPathInsideRoot } from \"../utils/path-containment.js\";\nimport { WearablesService } from \"../wearables/service.js\";\nimport {\n Orchestrator,\n filterHourlySummaryMarkdownForLocalDay,\n formatDateInTimeZone,\n normalizeIanaTimeZone,\n parseFiniteDate,\n utcDateKeysForLocalDay,\n type DaySummaryGatherOptions,\n} from \"../orchestrator.js\";\n\nexport interface WorkspaceOpsDeps {\n readonly accessTrackingBuffer: Map<string, { count: number; lastAccessed: string }>;\n bulkImportWriteNamespace(): string;\n readonly config: PluginConfig;\n readonly extraction: ExtractionEngine;\n getStorage(namespace?: string): Promise<StorageManager>;\n getStorageForNamespace(namespace?: string): Promise<StorageManager>;\n readonly judgeDeferCounts: Map<string, number>;\n readonly judgeVerdictCache: Map<string, JudgeVerdict>;\n lastFileHygieneRunAtMs: number;\n readonly lastPatternReinforcementAtByNs: Map<string, number>;\n readonly localLlm: LocalLlmClient;\n maintenanceNamespaces(\n jobName?: string,\n budgetMode?: \"cycle\" | \"unbounded\",\n ): Promise<string[]>;\n namespaceFromPath(p: string): string;\n readonly qmd: SearchBackend;\n readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]>;\n runNamespaceMaintenanceFanoutForJob(\n jobName: string,\n runner: (ctx: NamespaceMaintenanceFanoutRunnerContext) => Promise<{ itemCount?: number } | undefined>,\n options?: { enabled?: boolean },\n ): Promise<NamespaceMaintenanceSummary>;\n 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 readonly storage: StorageManager;\n readonly storageRouter: NamespaceStorageRouter;\n wearablesServiceInstance: WearablesService | null;\n}\n\nexport class WorkspaceOpsCoordinator {\n constructor(\n private readonly deps: WorkspaceOpsDeps,\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 (!resolveConsolidationCapabilities(this.deps.config).patternReinforcement) {\n return { ran: false, skippedReason: \"disabled\", namespace: cadenceKey };\n }\n const cadence = this.deps.config.patternReinforcementCadenceMs;\n const lastAt = this.deps.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.deps.getStorage(options.namespace)\n : this.deps.storage;\n const result = await runPatternReinforcement(storage, {\n categories: this.deps.config.patternReinforcementCategories,\n minCount: this.deps.config.patternReinforcementMinCount,\n });\n this.deps.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 /**\n * Fan out pattern reinforcement across all maintained namespaces (issue #1500).\n * Delegates per-namespace execution to {@link runPatternReinforcement} while\n * the planner handles discovery, budgeting, locking, and status recording.\n * When namespaces are disabled, runs once against default storage.\n */\n async runPatternReinforcementFanout(options: {\n force?: boolean;\n } = {}): Promise<NamespaceMaintenanceSummary> {\n return this.deps.runNamespaceMaintenanceFanoutForJob(\n \"pattern-reinforcement\",\n async (ctx) => {\n const result = await this.deps.runPatternReinforcement({\n namespace: ctx.candidate.namespace,\n force: options.force,\n });\n // runPatternReinforcement has its own per-namespace cadence gate\n // (lastPatternReinforcementAtByNs). When it throttles (ran:false),\n // signal skip so the planner records state:\"skipped\" and does NOT\n // touch lastMaintenanceAt — otherwise a throttled namespace would\n // look maintained while pattern reinforcement never ran (#1500\n // review: cadence-skip accuracy).\n if (!result.ran) {\n return {\n skipped: true,\n skipReason: result.skippedReason ?? \"throttled\",\n };\n }\n return result.result\n ? { itemCount: result.result.clustersFound }\n : { itemCount: 0 };\n },\n { enabled: resolveConsolidationCapabilities(this.deps.config).patternReinforcement },\n );\n }\n\n async maybeRunFileHygiene(): Promise<void> {\n const hygiene = this.deps.config.fileHygiene;\n if (!hygiene?.enabled) return;\n\n const now = Date.now();\n if (now - this.deps.lastFileHygieneRunAtMs < hygiene.runMinIntervalMs) return;\n this.deps.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.deps.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.deps.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.deps.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.deps.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 /**\n * Read today's facts and hourly summaries from storage, returning them\n * as a formatted string suitable for generateDaySummary().\n */\n async gatherTodayFacts(\n namespace?: string,\n options: DaySummaryGatherOptions = {},\n ): Promise<string> {\n const ns =\n namespace && namespace.length > 0\n ? namespace\n : this.deps.config.defaultNamespace;\n const storage = await this.deps.storageRouter.storageFor(ns);\n const configuredTimeZone = normalizeIanaTimeZone(options.timeZone)\n ?? normalizeIanaTimeZone(this.deps.config.daySummaryTimezone);\n const timeZone =\n configuredTimeZone ?? Intl.DateTimeFormat().resolvedOptions().timeZone;\n const now = options.now instanceof Date && Number.isFinite(options.now.getTime())\n ? options.now\n : new Date();\n const targetLocalDate = formatDateInTimeZone(now, timeZone);\n // Facts are stored under UTC date directories, while the summary target is\n // a local calendar day. Scan the UTC-date envelope that overlaps the local\n // day, then filter parseable fact timestamps to that configured local day.\n const datesToScan = utcDateKeysForLocalDay(now, timeZone);\n const MAX_CHARS = 100_000;\n\n // --- Read memory files from each category dir × date directory ---\n // Iterate every recall category dir (RECALL_FALLBACK_DIRS — single source\n // of truth) so the day summary includes decisions/, moments/, ... not just\n // facts/ (#1546). corrections/ is flat, so corrections/<date>/ never exists\n // and is skipped by the ENOENT guard — preserving the prior exclusion. The\n // per-file created→local-day filter below is unchanged.\n //\n // Symlink/containment hardening (mirrors scanDir / the CLI walker): the\n // gathered contents feed the day-summary LLM input, so a symlinked category\n // dir (decisions/ → outside memoryDir) must not be followed and leak files.\n // Resolve the store root once; skip symlinked / out-of-root dirs and\n // entries; skip the scan gracefully if the root can't be resolved.\n const facts: MemoryFile[] = [];\n let memoryRootReal: string | null = null;\n try {\n memoryRootReal = await realpath(storage.dir);\n } catch {\n memoryRootReal = null;\n }\n for (const categoryDir of RECALL_FALLBACK_DIRS) {\n if (memoryRootReal === null) break;\n for (const date of datesToScan) {\n const dateDir = path.join(storage.dir, categoryDir, date);\n try {\n const dirStat = await lstat(dateDir);\n if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) continue;\n assertPathInsideRoot(memoryRootReal, await realpath(dateDir), dateDir);\n const entries = await readdir(dateDir, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.isSymbolicLink()) continue;\n if (!entry.name.endsWith(\".md\")) continue;\n const fullPath = path.join(dateDir, entry.name);\n try {\n assertPathInsideRoot(memoryRootReal, await realpath(fullPath), fullPath);\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 const created = fm.created || \"unknown\";\n const createdAt = parseFiniteDate(created);\n if (\n createdAt &&\n formatDateInTimeZone(createdAt, timeZone) !== targetLocalDate\n ) {\n continue;\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,\n updated: fm.updated || created,\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 // Absent dir (ENOENT), symlinked/out-of-root dir, or containment\n // violation — skip this category/date without aborting the summary.\n }\n }\n }\n\n // Sort facts by created timestamp (most recent last) so truncation keeps newest\n facts.sort((a, b) => {\n if (a.frontmatter.created === b.frontmatter.created) return 0;\n return 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 const filtered = filterHourlySummaryMarkdownForLocalDay(\n raw,\n date,\n timeZone,\n targetLocalDate,\n );\n if (filtered) {\n hourlySummaries.push(filtered);\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 for ${targetLocalDate} (${timeZone}, ${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.deps.config.defaultNamespace;\n const eligibility = parseMemoryActionEligibilityContext(\n event.policyEligibility,\n );\n const policy = evaluateMemoryActionPolicy({\n action: event.action,\n eligibility,\n options: {\n actionsEnabled: resolveCompressionCapabilities(this.deps.config).contextCompressionActions,\n maxCompressionTokensPerHour: this.deps.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 /**\n * Validate local LLM model availability and context window compatibility.\n * Warns the user if there's a mismatch.\n */\n async validateLocalLlmModel(): Promise<void> {\n log.debug(\"Local LLM: validating model configuration\");\n try {\n const modelInfo = await this.deps.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.deps.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.deps.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 /**\n * Lazily-constructed wearables service (Limitless / Bee / Omi\n * transcript ingestion). All wearables surfaces — CLI, MCP tools,\n * HTTP routes — share this one instance so sync state, search, and\n * memory writes stay consistent. Writes are pinned to the same\n * deterministic namespace bulk-import uses.\n */\n getWearablesService(): WearablesService {\n if (!this.deps.wearablesServiceInstance) {\n this.deps.wearablesServiceInstance = new WearablesService({\n config: this.deps.config.wearables,\n getStorage: async () =>\n await this.deps.getStorageForNamespace(this.deps.bulkImportWriteNamespace()),\n extract: (turns) => this.deps.extraction.extract(turns),\n // Smart memoryMode runs candidates through the SAME extraction\n // judge (cache + defer counters included) the live extraction\n // pipeline uses, so wearable facts get identical LLM-as-judge\n // durability gating.\n judgeFacts: (candidates) =>\n judgeFactDurability(\n candidates,\n this.deps.config,\n this.deps.localLlm,\n new FallbackLlmClient(\n this.deps.config.gatewayConfig,\n fallbackLlmRuntimeContextFromConfig(this.deps.config),\n ),\n this.deps.judgeVerdictCache,\n this.deps.judgeDeferCounts,\n ),\n searchBackend: {\n search: async (query, maxResults) => {\n if (!this.deps.qmd.isAvailable()) return null;\n try {\n const results = await this.deps.qmd.search(query, undefined, maxResults);\n return results.map((result) => ({\n path: result.path,\n score: result.score,\n preview: result.snippet,\n }));\n } catch {\n // Backend hiccup → tell the service \"unavailable\" so it\n // runs its bounded scan fallback instead of returning a\n // silent empty result (CLAUDE.md rule 34).\n return null;\n }\n },\n },\n reindexSearch: async () => {\n await this.deps.qmd.update();\n },\n });\n }\n return this.deps.wearablesServiceInstance;\n }\n\n async autoConsolidateIdentity(): Promise<void> {\n // Fan out over the catalog-union namespace set (issue #1499 sweep): a dynamic\n // namespace that accumulated IDENTITY.md reflections must also be eligible for\n // auto-consolidation, otherwise its identity file grows unbounded and is never\n // consolidated. Falls back to the configured set on any catalog read failure.\n const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? await this.deps.maintenanceNamespaces()\n : [this.deps.config.defaultNamespace];\n\n for (const namespace of namespaces) {\n const storage = await this.deps.storageRouter.storageFor(namespace);\n const identityNamespace =\n resolveNamespaceCapabilities(this.deps.config).namespaces &&\n namespace !== this.deps.config.defaultNamespace\n ? namespace\n : undefined;\n const reflectionsContent =\n (await storage.readIdentityReflections()) ?? \"\";\n\n const existingIdentity = await storage.readIdentity(\n this.deps.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.deps.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.deps.config.workspaceDir,\n newContent,\n identityNamespace,\n );\n await storage.writeIdentityReflections(\"\");\n // NRcCL (codex P2): record a per-namespace catalog write for THIS namespace\n // after the identity files are updated. This fan-out can mutate a dynamic\n // namespace via `writeIdentity`/`writeIdentityReflections`, but the\n // consolidation pass's only consolidated touch covers `this.deps.storage` (the\n // default) and only fires when `memoryItemMutated` was set by OTHER work — so\n // a namespace whose sole mutation in the pass is identity consolidation would\n // otherwise keep a stale `lastWriteAt`, making `listNamespaces({ writtenSince })`\n // and catalog-recency consumers miss the write. Best-effort and\n // failure-tolerant (the storage chokepoint (#1522) swallows errors, never crashing the\n // consolidation; gotcha #13, rule #40). No double-count with the consolidated\n // touch above: that one is gated on `memoryItemMutated` (which identity\n // consolidation does not set), and `markWrite` is idempotent regardless.\n log.info(\n `IDENTITY(${namespace}) consolidated: ${identityContent.length} → ${newContent.length} chars, ${result.learnedPatterns.length} patterns`,\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.deps.accessTrackingBuffer.size === 0) return;\n\n // Build entries from buffer, merging with existing counts\n const entries: AccessTrackingEntry[] = [];\n const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? Array.from(\n new Set<string>([\n this.deps.config.defaultNamespace,\n this.deps.config.sharedNamespace,\n ...this.deps.config.namespacePolicies.map((p) => p.name),\n ]),\n )\n : [this.deps.config.defaultNamespace];\n const memories = await this.deps.readAllMemoriesForNamespaces(namespaces);\n const memoryMap = new Map(memories.map((m) => [m.frontmatter.id, m]));\n\n for (const [memoryId, update] of this.deps.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.deps.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.deps.storageRouter.storageFor(ns);\n await sm.flushAccessTracking(list);\n }\n this.deps.accessTrackingBuffer.clear();\n log.debug(`flushed ${entries.length} access tracking entries`);\n }\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 { buildRetiredFactTombstoneInputs, type TombstoneReason, type TombstoneCreatedBy } from \"../lifecycle/tombstones.js\";\nimport { supersessionKeysForFact } from \"../temporal-supersession.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 * Best-effort tombstone append for retired duplicates (issue #1579 thread\n * Oblq9). Optional so unit-test stubs need not implement it; the production\n * StorageManager satisfies it via its appendTombstone chokepoint.\n */\n appendTombstone?(input: {\n reason: TombstoneReason;\n createdBy: TombstoneCreatedBy;\n sourceMemoryId: string;\n contentHash?: string;\n rawContent: string;\n entityRef?: string;\n supersessionKey?: string;\n createdAt: string;\n }): Promise<string | null>;\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 // Issue #1579 thread Oblq9 / Ocn0C / OcoPs: emit a tombstone so the\n // retired duplicate cannot resurrect through re-extraction / import.\n // Pattern reinforcement retires via writeMemoryFrontmatter which\n // bypasses the writeMemory chokepoint; without this emit, the same\n // content re-extracted before a manual rebuild would be stored active.\n // Threads Ocn0C/OcoPs: emit one tombstone PER derived supersession key\n // via buildRetiredFactTombstoneInputs (same helper as supersedeMemory +\n // forgetMemory), not a single entityRef-only record — a paraphrased\n // re-extraction with the same entity/attribute can only be caught by\n // the keyed tier. Best-effort (the interface method is optional; a\n // failure must not fail the reinforcement job).\n if (storage.appendTombstone) {\n for (const input of buildRetiredFactTombstoneInputs(\n {\n id: dup.frontmatter.id,\n content: dup.content,\n contentHash: dup.frontmatter.contentHash,\n entityRef: dup.frontmatter.entityRef,\n structuredAttributes: dup.frontmatter.structuredAttributes,\n },\n { reason: \"supersession\", createdBy: \"supersession\", createdAt: nowIso, supersessionKeysForFact },\n )) {\n try {\n await storage.appendTombstone(input);\n } catch {\n // Best-effort: a tombstone append failure must not fail the\n // reinforcement job (gotcha #13 / rule 34 spirit).\n }\n }\n }\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 * Wearable connector registry.\n *\n * Concrete connectors live in optional à-la-carte packages and register\n * a factory here (directly, or via the built-in loader below which\n * dynamic-imports the known packages with computed specifiers so\n * bundlers and the dts resolver never require them at build time).\n */\n\nimport { log } from \"../logger.js\";\nimport type {\n WearableSourceConnector,\n WearableSourceSettings,\n} from \"./types.js\";\n\nexport interface WearableConnectorFactoryOptions {\n settings: WearableSourceSettings;\n /** IANA timezone transcripts are bucketed in. */\n timezone: string;\n}\n\nexport type WearableConnectorFactory = (\n options: WearableConnectorFactoryOptions,\n) => WearableSourceConnector;\n\nexport interface WearableConnectorRegistration {\n id: string;\n displayName: string;\n factory: WearableConnectorFactory;\n}\n\nconst registrations = new Map<string, WearableConnectorRegistration>();\n\nexport function registerWearableConnector(\n registration: WearableConnectorRegistration,\n): void {\n if (!registration || typeof registration !== \"object\") {\n throw new Error(\"wearable connector registration must be an object\");\n }\n if (\n typeof registration.id !== \"string\" ||\n registration.id.trim().length === 0\n ) {\n throw new Error(\"wearable connector id must be a non-empty string\");\n }\n if (typeof registration.factory !== \"function\") {\n throw new Error(\n `wearable connector '${registration.id}' must provide a factory function`,\n );\n }\n const key = registration.id.trim();\n if (registrations.has(key)) {\n throw new Error(`wearable connector '${key}' is already registered`);\n }\n registrations.set(key, { ...registration, id: key });\n}\n\nexport function getWearableConnector(\n id: string,\n): WearableConnectorRegistration | undefined {\n if (typeof id !== \"string\") return undefined;\n const key = id.trim();\n if (key.length === 0) return undefined;\n return registrations.get(key);\n}\n\nexport function listWearableConnectors(): string[] {\n return [...registrations.keys()];\n}\n\n/** Test-only: reset the registry between cases. */\nexport function clearWearableConnectors(): void {\n registrations.clear();\n}\n\n/**\n * Built-in connector packages, tried in order. Each entry is loaded via\n * a computed-specifier dynamic import (see optional-bench.ts in\n * @remnic/cli for the canonical à-la-carte pattern); a missing package\n * is silently skipped, any other load error is logged once and skipped\n * so one broken connector never takes down the others.\n */\nconst BUILT_IN_CONNECTOR_PACKAGES: Array<{ id: string; suffix: string }> = [\n { id: \"limitless\", suffix: \"connector-limitless\" },\n { id: \"bee\", suffix: \"connector-bee\" },\n { id: \"omi\", suffix: \"connector-omi\" },\n];\n\nconst loadFailuresWarned = new Set<string>();\n\nexport async function ensureBuiltInWearableConnectors(): Promise<void> {\n for (const entry of BUILT_IN_CONNECTOR_PACKAGES) {\n if (registrations.has(entry.id)) continue;\n const specifier = \"@remnic/\" + entry.suffix;\n let mod: { wearableConnectorRegistration?: WearableConnectorRegistration };\n try {\n mod = (await import(specifier)) as {\n wearableConnectorRegistration?: WearableConnectorRegistration;\n };\n } catch (err) {\n if (isModuleNotFound(err, specifier)) continue;\n if (!loadFailuresWarned.has(specifier)) {\n loadFailuresWarned.add(specifier);\n log.warn(\n `wearables: failed to load optional connector package ${specifier}: ${\n err instanceof Error ? err.message : String(err)\n }`,\n );\n }\n continue;\n }\n const registration = mod.wearableConnectorRegistration;\n if (!registration) continue;\n try {\n registerWearableConnector(registration);\n } catch {\n // Already registered by a direct import — fine.\n }\n }\n}\n\nfunction isModuleNotFound(err: unknown, specifier: string): boolean {\n if (!err || typeof err !== \"object\") return false;\n const code = (err as { code?: unknown }).code;\n if (code !== \"ERR_MODULE_NOT_FOUND\" && code !== \"MODULE_NOT_FOUND\") {\n return false;\n }\n const message = (err as { message?: unknown }).message;\n // Only treat the failure as \"optional package absent\" when the error\n // names the specifier we asked for — a transitive resolution failure\n // inside an installed connector is a broken install worth surfacing.\n return typeof message === \"string\" && message.includes(specifier);\n}\n","/**\n * WearablesService — the single implementation behind every wearables\n * access surface (CLI, MCP tools, HTTP routes). Surfaces stay thin and\n * delegate here; formatting differences live with the surface, behavior\n * lives here (same renderer-sharing rule as recall explain/xray).\n */\n\nimport {\n correctionsFilePath,\n loadCorrectionsFile,\n saveCorrectionsFile,\n compileCorrectionRule,\n} from \"./corrections.js\";\nimport { describeErrorForOperator, WearablesInputError } from \"./errors.js\";\nimport { inferMemoryStatus } from \"../memory-lifecycle-ledger-utils.js\";\nimport { isValidTranscriptDate, parseDayTranscript } from \"./day-store.js\";\nimport { stripAttributesSuffix } from \"../storage.js\";\nimport type { MemoryFrontmatter } from \"../types.js\";\nimport type { WearableMemoryGenDeps } from \"./memory-gen.js\";\nimport { WEARABLE_SOURCE_PREFIX, wearableSourceLabel } from \"./memory-gen.js\";\nimport {\n defaultTimezone,\n syncWearableSource,\n type WearableSyncOptions,\n} from \"./pipeline.js\";\nimport {\n ensureBuiltInWearableConnectors,\n getWearableConnector,\n listWearableConnectors,\n} from \"./registry.js\";\nimport {\n loadSpeakerRegistry,\n saveSpeakerRegistry,\n speakerRegistryKey,\n type SpeakerRegistry,\n} from \"./speakers.js\";\nimport { loadSyncState } from \"./sync-state.js\";\nimport type {\n WearableCorrectionRule,\n WearableDayTranscript,\n WearableSourceSettings,\n WearableSourceStatus,\n WearableSyncSummary,\n WearablesConfig,\n} from \"./types.js\";\n\n/** Storage capabilities the service needs (satisfied by StorageManager). */\nexport interface WearableStorageIo {\n readonly dir: string;\n writeWearableDayTranscript(\n sourceId: string,\n date: string,\n serialized: string,\n ): Promise<void>;\n readWearableDayTranscript(\n sourceId: string,\n date: string,\n ): Promise<string | null>;\n listWearableTranscriptDays(\n sourceId?: string,\n ): Promise<Array<{ source: string; date: string }>>;\n readAllMemories(): Promise<\n Array<{\n path: string;\n frontmatter: {\n id: string;\n source: string;\n created: string;\n tags: string[];\n status?: string;\n /** Archival timestamp — rows with this set are not support. */\n archivedAt?: string;\n structuredAttributes?: Record<string, string>;\n };\n content: string;\n }>\n >;\n writeMemory: WearableMemoryGenDeps[\"writer\"][\"writeMemory\"];\n hasFactContentHash(content: string): Promise<boolean>;\n findWearableMemoryByContent(\n content: string,\n ): Promise<{ id: string; status: string | undefined } | null>;\n promoteWearableMemory(\n id: string,\n attributeUpdates: Record<string, string>,\n confidence?: number,\n ): Promise<boolean>;\n demoteWearableMemory(\n id: string,\n attributeUpdates: Record<string, string>,\n ): Promise<boolean>;\n}\n\nexport interface WearableSearchBackend {\n /** Full-text search over the memory dir; null when unavailable. */\n search(\n query: string,\n maxResults: number,\n ): Promise<Array<{ path: string; score: number; preview: string }> | null>;\n}\n\nexport interface WearablesServiceDeps {\n config: WearablesConfig;\n getStorage(): Promise<WearableStorageIo>;\n /** Extraction hook; null when no engine is available. */\n extract: WearableMemoryGenDeps[\"extract\"] | null;\n /**\n * LLM-as-judge hook for smart memoryMode (the orchestrator wires the\n * existing extraction judge here). Absent degrades smart mode to\n * confidence x sourceTrust + corroboration scoring.\n */\n judgeFacts?: WearableMemoryGenDeps[\"judgeFacts\"];\n /** Search backend (QMD); null disables indexed search. */\n searchBackend: WearableSearchBackend | null;\n /** Fired after transcript writes so the search index refreshes. */\n reindexSearch?: () => Promise<void>;\n}\n\nexport interface WearableTranscriptSearchResult {\n source: string;\n date: string;\n score: number;\n snippet: string;\n /** \"indexed\" (QMD) or \"scan\" (substring fallback). */\n backend: \"indexed\" | \"scan\";\n}\n\nexport interface WearableMemorySearchResult {\n id: string;\n source: string;\n date?: string;\n conversationId?: string;\n status?: string;\n content: string;\n created: string;\n}\n\nexport interface WearableDayTranscriptView {\n source: string;\n date: string;\n meta: WearableDayTranscript[\"meta\"] | null;\n body: string;\n /** Other sources that also recorded during this day (overlap hint). */\n overlapsWith: string[];\n}\n\n/**\n * Build the memory writer used by wearable syncs. The storage fact\n * hash index only covers category \"fact\", so dedup for the other\n * categories wearables write (moment digests, decisions, preferences,\n * commitments) additionally scans existing wearable-tagged memories for\n * an exact content match — without this, a forced or retried day\n * re-writes identical digests and candidates (Codex P2 on PR #1458).\n * The scan is bounded to wearable-sourced memories and sits on the\n * cached readAllMemories() path.\n */\nexport function createWearableMemoryWriter(\n storage: WearableStorageIo,\n): WearableMemoryGenDeps[\"writer\"] {\n return {\n writeMemory: storage.writeMemory.bind(storage),\n findWearableMemoryByContent: async (content: string) =>\n (await storage.findWearableMemoryByContent(content)) as\n | { id: string; status: import(\"../types.js\").MemoryStatus | undefined }\n | null,\n promoteWearableMemory: storage.promoteWearableMemory.bind(storage),\n demoteWearableMemory: storage.demoteWearableMemory.bind(storage),\n hasFactContentHash: async (content: string) => {\n if (await storage.hasFactContentHash(content)) return true;\n // Compare with the \"[Attributes: ...]\" enrichment suffix removed\n // on BOTH sides — stored wearable bodies carry it, callers pass\n // raw fact text. Without the strip, digest/candidate dedup never\n // matched attribute-bearing memories.\n const needle = stripAttributesSuffix(content);\n const memories = await storage.readAllMemories();\n return memories.some(\n (memory) =>\n typeof memory.frontmatter.source === \"string\" &&\n memory.frontmatter.source.startsWith(`${WEARABLE_SOURCE_PREFIX}:`) &&\n stripAttributesSuffix(memory.content) === needle,\n );\n },\n };\n}\n\n/** Mirrors the storage-layer guard so surface inputs fail as 400s. */\nconst SOURCE_ID_PATTERN = /^[a-z][a-z0-9-]{0,63}$/;\n\nfunction assertValidSourceId(source: string): void {\n if (!SOURCE_ID_PATTERN.test(source)) {\n throw new WearablesInputError(\n `invalid source id '${source}' — expected lowercase letters, digits, and dashes`,\n );\n }\n}\n\nconst TRANSCRIPT_SEARCH_DEFAULT_LIMIT = 10;\nconst TRANSCRIPT_SEARCH_MAX_LIMIT = 50;\nconst MEMORY_LIST_DEFAULT_LIMIT = 50;\nconst MEMORY_LIST_MAX_LIMIT = 200;\n\nexport class WearablesService {\n constructor(private readonly deps: WearablesServiceDeps) {}\n\n get enabled(): boolean {\n return this.deps.config.enabled;\n }\n\n private assertEnabled(): void {\n if (!this.deps.config.enabled) {\n throw new WearablesInputError(\n \"wearables are not enabled — set `wearables.enabled: true` (and configure at least one source) in the plugin config\",\n );\n }\n }\n\n private timezone(): string {\n return this.deps.config.timezone ?? defaultTimezone();\n }\n\n private enabledSources(): Array<[string, WearableSourceSettings]> {\n return Object.entries(this.deps.config.sources).filter(\n ([, settings]) => settings.enabled,\n );\n }\n\n /** Status for every configured source (and connector availability). */\n async status(): Promise<{\n enabled: boolean;\n timezone: string;\n sources: WearableSourceStatus[];\n connectorsInstalled: string[];\n }> {\n await ensureBuiltInWearableConnectors();\n const storage = await this.deps.getStorage();\n const syncState = await loadSyncState(storage.dir);\n const sources: WearableSourceStatus[] = [];\n for (const [sourceId, settings] of Object.entries(this.deps.config.sources)) {\n const registration = getWearableConnector(sourceId);\n const days = await storage.listWearableTranscriptDays(sourceId).catch(() => []);\n const state = syncState.sources[sourceId];\n sources.push({\n source: sourceId,\n displayName: registration?.displayName ?? sourceId,\n enabled: settings.enabled,\n connectorInstalled: registration !== undefined,\n memoryMode: settings.memoryMode,\n lastSyncAt: state?.lastSyncAt ?? null,\n lastDateSynced: state?.lastDateSynced ?? null,\n transcriptDays: days.length,\n });\n }\n return {\n enabled: this.deps.config.enabled,\n timezone: this.timezone(),\n sources,\n connectorsInstalled: listWearableConnectors(),\n };\n }\n\n /** Run a sync for one source or all enabled sources. */\n async sync(\n options: WearableSyncOptions & { source?: string },\n ): Promise<WearableSyncSummary[]> {\n this.assertEnabled();\n await ensureBuiltInWearableConnectors();\n const storage = await this.deps.getStorage();\n\n let targets: Array<[string, WearableSourceSettings]>;\n if (options.source !== undefined) {\n assertValidSourceId(options.source);\n const settings = this.deps.config.sources[options.source];\n if (!settings) {\n throw new WearablesInputError(\n `unknown wearable source '${options.source}' — configured sources: ${\n Object.keys(this.deps.config.sources).join(\", \") || \"(none)\"\n }`,\n );\n }\n if (!settings.enabled) {\n throw new WearablesInputError(\n `wearable source '${options.source}' is configured but disabled — set wearables.sources.${options.source}.enabled: true`,\n );\n }\n targets = [[options.source, settings]];\n } else {\n targets = this.enabledSources();\n if (targets.length === 0) {\n throw new WearablesInputError(\n \"no wearable sources are enabled — configure wearables.sources.<id>.enabled: true\",\n );\n }\n }\n\n const memoryGen: WearableMemoryGenDeps | null = this.deps.extract\n ? {\n extract: this.deps.extract,\n writer: createWearableMemoryWriter(storage),\n ...(this.deps.judgeFacts !== undefined\n ? { judgeFacts: this.deps.judgeFacts }\n : {}),\n }\n : null;\n\n const summaries: WearableSyncSummary[] = [];\n for (const [sourceId, settings] of targets) {\n const registration = getWearableConnector(sourceId);\n if (!registration) {\n throw new WearablesInputError(\n `wearable source '${sourceId}' is enabled but its connector package is not installed.\\n` +\n `Install it alongside Remnic:\\n npm install @remnic/connector-${sourceId}`,\n );\n }\n const connector = registration.factory({\n settings,\n timezone: this.timezone(),\n });\n const summary = await syncWearableSource(\n connector,\n settings,\n this.deps.config,\n options,\n {\n memoryDir: storage.dir,\n readDayContentHash: async (source, date) => {\n const raw = await storage.readWearableDayTranscript(source, date);\n if (raw === null) return null;\n return parseDayTranscript(raw)?.meta.contentHash ?? null;\n },\n writeDayTranscript: (source, date, serialized) =>\n storage.writeWearableDayTranscript(source, date, serialized),\n afterWrites: this.deps.reindexSearch,\n memoryGen,\n // Cross-device corroboration evidence (smart mode): other\n // sources' stored transcripts for the same day...\n readOtherSourceDayBodies: async (date, excludeSource) => {\n const bodies = new Map<string, string>();\n const days = await storage.listWearableTranscriptDays();\n for (const entry of days) {\n if (entry.date !== date || entry.source === excludeSource) continue;\n if (bodies.size >= 4) break;\n const raw = await storage.readWearableDayTranscript(entry.source, entry.date);\n if (raw === null) continue;\n bodies.set(entry.source, parseDayTranscript(raw)?.body ?? raw);\n }\n return bodies;\n },\n // ...and existing memories for the support boost. Status\n // resolves through the canonical inferMemoryStatus so rows\n // archived via `archivedAt` (or an archive/ path) without an\n // explicit status never count. Explicit allow-list: active\n // rows AND pending_review rows — a borderline fact observed\n // again on a later day is repetition signal and the support\n // boost is how it earns promotion. Rejected/quarantined/\n // superseded/archived/forgotten rows never count (CLAUDE.md\n // rule 53). Bodies feed token matching with the\n // \"[Attributes: ...]\" enrichment suffix stripped — attribute\n // metadata must never grant corroboration.\n listSupportMemories: async () => {\n const memories = await storage.readAllMemories();\n const support: Array<{ id: string; content: string }> = [];\n for (const memory of memories) {\n // WearableStorageIo narrows MemoryFrontmatter for\n // testability; production hands us the real thing.\n const status = inferMemoryStatus(\n memory.frontmatter as MemoryFrontmatter,\n memory.path,\n );\n if (status !== \"active\" && status !== \"pending_review\") {\n continue;\n }\n support.push({\n id: memory.frontmatter.id,\n content: stripAttributesSuffix(memory.content),\n });\n }\n return support;\n },\n },\n );\n summaries.push(summary);\n }\n return summaries;\n }\n\n /** Verify connectivity/credentials for one source. */\n async checkAuth(sourceId: string): Promise<{ ok: boolean; detail?: string }> {\n this.assertEnabled();\n await ensureBuiltInWearableConnectors();\n assertValidSourceId(sourceId);\n const settings = this.deps.config.sources[sourceId];\n if (!settings) {\n throw new WearablesInputError(`unknown wearable source '${sourceId}'`);\n }\n const registration = getWearableConnector(sourceId);\n if (!registration) {\n return {\n ok: false,\n detail: `connector package @remnic/connector-${sourceId} is not installed`,\n };\n }\n const connector = registration.factory({\n settings,\n timezone: this.timezone(),\n });\n try {\n // Connector detail strings are authored guidance (plus\n // name+errno network summaries) — safe to pass through verbatim.\n return await connector.verifyAuth();\n } catch (err) {\n return {\n ok: false,\n detail: describeErrorForOperator(err),\n };\n }\n }\n\n /**\n * Full transcript(s) for a day. Without `source`, returns every\n * source that recorded that day, annotated with overlap hints.\n */\n async dayTranscript(\n date: string,\n sourceId?: string,\n ): Promise<WearableDayTranscriptView[]> {\n if (!isValidTranscriptDate(date)) {\n throw new WearablesInputError(`invalid date '${date}' — expected YYYY-MM-DD`);\n }\n if (sourceId !== undefined) assertValidSourceId(sourceId);\n const storage = await this.deps.getStorage();\n const targets =\n sourceId !== undefined\n ? [sourceId]\n : (await storage.listWearableTranscriptDays())\n .filter((entry) => entry.date === date)\n .map((entry) => entry.source);\n const views: WearableDayTranscriptView[] = [];\n for (const source of [...new Set(targets)]) {\n const raw = await storage.readWearableDayTranscript(source, date);\n if (raw === null) continue;\n const parsed = parseDayTranscript(raw);\n views.push({\n source,\n date,\n meta: parsed?.meta ?? null,\n body: parsed?.body ?? raw,\n overlapsWith: [],\n });\n }\n for (const view of views) {\n view.overlapsWith = views\n .map((other) => other.source)\n .filter((other) => other !== view.source);\n }\n return views;\n }\n\n /** List days that have stored transcripts. */\n async listDays(\n sourceId?: string,\n ): Promise<Array<{ source: string; date: string }>> {\n if (sourceId !== undefined) assertValidSourceId(sourceId);\n const storage = await this.deps.getStorage();\n return storage.listWearableTranscriptDays(sourceId);\n }\n\n /**\n * Search stored transcripts. Uses the indexed backend when available\n * and falls back to a bounded substring scan otherwise — the two\n * paths are distinguishable in the result (`backend`) so callers can\n * tell \"no hits\" from \"weaker search ran\".\n */\n async searchTranscripts(\n query: string,\n options: {\n source?: string;\n from?: string;\n to?: string;\n limit?: number;\n } = {},\n ): Promise<WearableTranscriptSearchResult[]> {\n const trimmed = query.trim();\n if (trimmed.length === 0) {\n throw new WearablesInputError(\"transcript search requires a non-empty query\");\n }\n if (options.source !== undefined) assertValidSourceId(options.source);\n for (const [name, value] of [\n [\"from\", options.from],\n [\"to\", options.to],\n ] as const) {\n if (value !== undefined && !isValidTranscriptDate(value)) {\n throw new WearablesInputError(`invalid ${name} date '${value}' — expected YYYY-MM-DD`);\n }\n }\n const limit = clampLimit(\n options.limit,\n TRANSCRIPT_SEARCH_DEFAULT_LIMIT,\n TRANSCRIPT_SEARCH_MAX_LIMIT,\n \"limit\",\n );\n\n const matchesScope = (source: string, date: string): boolean => {\n if (options.source !== undefined && source !== options.source) return false;\n if (options.from !== undefined && date < options.from) return false;\n // Half-open scan semantics aren't meaningful for whole-day files;\n // `to` is inclusive of the named day.\n if (options.to !== undefined && date > options.to) return false;\n return true;\n };\n\n if (this.deps.searchBackend) {\n const hits = await this.deps.searchBackend.search(trimmed, limit * 5);\n if (hits !== null) {\n const results: WearableTranscriptSearchResult[] = [];\n for (const hit of hits) {\n const located = locateTranscriptPath(hit.path);\n if (!located) continue;\n if (!matchesScope(located.source, located.date)) continue;\n results.push({\n source: located.source,\n date: located.date,\n score: hit.score,\n snippet: hit.preview,\n backend: \"indexed\",\n });\n if (results.length >= limit) break;\n }\n // The index spans the whole memory dir, so ordinary memory\n // files can crowd transcripts out of the top hits entirely.\n // Zero in-scope hits therefore doesn't mean \"no transcript\n // matches\" — fall through to the bounded scan in that case\n // (Codex P2 on PR #1458). Partial result sets stay indexed-only\n // so the two backends never interleave in one response.\n if (results.length > 0) {\n return results;\n }\n }\n }\n\n // Fallback scan: newest days first, bounded, case-insensitive.\n const storage = await this.deps.getStorage();\n const days = await storage.listWearableTranscriptDays(options.source);\n const needle = trimmed.toLowerCase();\n const results: WearableTranscriptSearchResult[] = [];\n for (const { source, date } of days) {\n if (!matchesScope(source, date)) continue;\n const raw = await storage.readWearableDayTranscript(source, date);\n if (raw === null) continue;\n const body = parseDayTranscript(raw)?.body ?? raw;\n const lower = body.toLowerCase();\n const index = lower.indexOf(needle);\n if (index === -1) continue;\n results.push({\n source,\n date,\n score: 0,\n snippet: extractSnippet(body, index, needle.length),\n backend: \"scan\",\n });\n if (results.length >= limit) break;\n }\n return results;\n }\n\n /**\n * Memories created from wearable transcripts, filterable by source\n * and/or day. Includes pending_review candidates — the whole point of\n * review mode is seeing what's queued.\n */\n async transcriptMemories(\n options: {\n source?: string;\n date?: string;\n limit?: number;\n } = {},\n ): Promise<WearableMemorySearchResult[]> {\n if (options.date !== undefined && !isValidTranscriptDate(options.date)) {\n throw new WearablesInputError(`invalid date '${options.date}' — expected YYYY-MM-DD`);\n }\n if (options.source !== undefined) assertValidSourceId(options.source);\n const limit = clampLimit(\n options.limit,\n MEMORY_LIST_DEFAULT_LIMIT,\n MEMORY_LIST_MAX_LIMIT,\n \"limit\",\n );\n const storage = await this.deps.getStorage();\n const memories = await storage.readAllMemories();\n const results: WearableMemorySearchResult[] = [];\n for (const memory of memories) {\n const source = memory.frontmatter.source;\n if (typeof source !== \"string\" || !source.startsWith(`${WEARABLE_SOURCE_PREFIX}:`)) {\n continue;\n }\n const attrs = memory.frontmatter.structuredAttributes ?? {};\n const sourceId = attrs.wearableSource;\n if (options.source !== undefined) {\n if (\n sourceId !== options.source &&\n source !== wearableSourceLabel(options.source) &&\n source !== `${wearableSourceLabel(options.source)}:native`\n ) {\n continue;\n }\n }\n if (options.date !== undefined && attrs.wearableDate !== options.date) {\n continue;\n }\n results.push({\n id: memory.frontmatter.id,\n source: sourceId ?? source,\n date: attrs.wearableDate,\n conversationId: attrs.wearableConversationId,\n status: memory.frontmatter.status,\n content: memory.content,\n created: memory.frontmatter.created,\n });\n }\n results.sort((a, b) => {\n if (a.created > b.created) return -1;\n if (a.created < b.created) return 1;\n if (a.id < b.id) return -1;\n if (a.id > b.id) return 1;\n return 0;\n });\n return results.slice(0, limit);\n }\n\n // -- speakers -------------------------------------------------------------\n\n async listSpeakers(): Promise<SpeakerRegistry> {\n const storage = await this.deps.getStorage();\n return loadSpeakerRegistry(storage.dir);\n }\n\n async setSpeaker(\n sourceId: string,\n speakerKey: string,\n name: string,\n opts: { isSelf?: boolean } = {},\n ): Promise<SpeakerRegistry> {\n if (typeof name !== \"string\" || name.trim().length === 0) {\n throw new WearablesInputError(\"speaker name must be a non-empty string\");\n }\n if (typeof speakerKey !== \"string\" || speakerKey.trim().length === 0) {\n throw new WearablesInputError(\"speaker key must be a non-empty string\");\n }\n const storage = await this.deps.getStorage();\n const registry = await loadSpeakerRegistry(storage.dir);\n registry.speakers[speakerRegistryKey(sourceId, speakerKey.trim())] = {\n name: name.trim(),\n ...(opts.isSelf === true ? { isSelf: true } : {}),\n updatedAt: new Date().toISOString(),\n };\n await saveSpeakerRegistry(storage.dir, registry);\n return registry;\n }\n\n async setSelfName(name: string): Promise<SpeakerRegistry> {\n if (typeof name !== \"string\" || name.trim().length === 0) {\n throw new WearablesInputError(\"self name must be a non-empty string\");\n }\n const storage = await this.deps.getStorage();\n const registry = await loadSpeakerRegistry(storage.dir);\n registry.selfName = name.trim();\n await saveSpeakerRegistry(storage.dir, registry);\n return registry;\n }\n\n async removeSpeaker(\n sourceId: string,\n speakerKey: string,\n ): Promise<SpeakerRegistry> {\n const storage = await this.deps.getStorage();\n const registry = await loadSpeakerRegistry(storage.dir);\n const key = speakerRegistryKey(sourceId, speakerKey.trim());\n if (!(key in registry.speakers)) {\n throw new WearablesInputError(`no speaker override stored for '${key}'`);\n }\n delete registry.speakers[key];\n await saveSpeakerRegistry(storage.dir, registry);\n return registry;\n }\n\n // -- corrections ----------------------------------------------------------\n\n async listCorrections(): Promise<{\n fromConfig: WearableCorrectionRule[];\n fromState: WearableCorrectionRule[];\n stateFilePath: string;\n }> {\n const storage = await this.deps.getStorage();\n return {\n fromConfig: this.deps.config.corrections,\n fromState: await loadCorrectionsFile(storage.dir),\n stateFilePath: correctionsFilePath(storage.dir),\n };\n }\n\n async addCorrection(rule: WearableCorrectionRule): Promise<void> {\n // Validate before persisting so a bad rule fails the command, not\n // the next sync.\n compileCorrectionRule(rule, \"correction\");\n const storage = await this.deps.getStorage();\n const rules = await loadCorrectionsFile(storage.dir);\n const duplicate = rules.some(\n (existing) =>\n existing.match === rule.match &&\n existing.replace === rule.replace &&\n (existing.regex === true) === (rule.regex === true),\n );\n if (duplicate) {\n throw new WearablesInputError(\n `an identical correction rule already exists (match: ${JSON.stringify(rule.match)})`,\n );\n }\n rules.push(rule);\n await saveCorrectionsFile(storage.dir, rules);\n }\n\n async removeCorrection(index: number): Promise<WearableCorrectionRule> {\n if (!Number.isInteger(index) || index < 0) {\n throw new WearablesInputError(`invalid correction index '${index}'`);\n }\n const storage = await this.deps.getStorage();\n const rules = await loadCorrectionsFile(storage.dir);\n if (index >= rules.length) {\n throw new WearablesInputError(\n `correction index ${index} is out of range (have ${rules.length} state rule${rules.length === 1 ? \"\" : \"s\"})`,\n );\n }\n const [removed] = rules.splice(index, 1);\n await saveCorrectionsFile(storage.dir, rules);\n return removed;\n }\n}\n\nfunction clampLimit(\n value: number | undefined,\n fallback: number,\n max: number,\n label: string,\n): number {\n if (value === undefined) return fallback;\n if (!Number.isFinite(value) || !Number.isInteger(value) || value < 1 || value > max) {\n throw new WearablesInputError(\n `invalid ${label} '${value}' — expected an integer between 1 and ${max}`,\n );\n }\n return value;\n}\n\n/** Map an indexed-search hit path back to (source, date), or null. */\nexport function locateTranscriptPath(\n hitPath: string,\n): { source: string; date: string } | null {\n const normalized = hitPath.replace(/\\\\/g, \"/\");\n const match = normalized.match(\n /(?:^|\\/)wearables\\/([a-z][a-z0-9-]{0,63})\\/(\\d{4}-\\d{2}-\\d{2})\\.md$/,\n );\n if (!match) return null;\n if (!isValidTranscriptDate(match[2])) return null;\n return { source: match[1], date: match[2] };\n}\n\nfunction extractSnippet(body: string, index: number, matchLength: number): string {\n const start = Math.max(0, index - 80);\n const end = Math.min(body.length, index + matchLength + 80);\n const prefix = start > 0 ? \"…\" : \"\";\n const suffix = end < body.length ? \"…\" : \"\";\n return `${prefix}${body.slice(start, end).replace(/\\s+/g, \" \").trim()}${suffix}`;\n}\n","/**\n * Namespace read-fanout coordinator — extracted from the orchestrator\n * (issue #1526, seam 26).\n *\n * Owns namespace-scoped READ fanout (never namespace RESOLUTION — the\n * ScopePlan resolver from #1521 stays the single authority for that):\n * - storage-dir hint loading from the catalog\n * - cross-namespace search and memory/archive reads\n * - scoped memory candidate search and artifact recall fanout\n * - artifact source status resolution (with per-storage cache)\n * - path→namespace and storage-dir→namespace mapping helpers\n *\n * Behavior-preserving move from orchestrator.ts (late-binding deps rule,\n * seams 18–25).\n */\n\nimport { existsSync, readFileSync } from \"node:fs\";\nimport { stat } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { resolveNamespaceCapabilities } from \"../capabilities.js\";\nimport { StorageManager } from \"../index.js\";\nimport { NamespaceCatalog } from \"../namespaces/catalog.js\";\nimport { namespaceIdentityFromToken, namespaceIdentityToken, normalizeNamespaceIdentity } from \"../namespaces/identity.js\";\nimport { NamespaceSearchRouter } from \"../namespaces/search.js\";\nimport { NamespaceStorageRouter } from \"../namespaces/storage.js\";\nimport { mergeArtifactRecallCandidates, tokenizeRecallQuery } from \"./orchestrator-helpers.js\";\nimport { qmdCollectionPathParts } from \"./qmd-result-resolver.js\";\nimport { resolveNamespaceFromStorageDir } from \"../scopes/scope-plan.js\";\nimport type { SearchBackend, SearchExecutionOptions, SearchQueryOptions } from \"../search/port.js\";\nimport type { MemoryFile, PluginConfig, QmdSearchResult } from \"../types.js\";\nimport {\n Orchestrator,\n} from \"../orchestrator.js\";\n\nexport interface NamespaceReadFanoutDeps {\n readonly artifactSourceStatusCache: WeakMap<StorageManager, { loadedAtMs: number; statusVersion: number; statuses: Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\"> }>;\n readonly config: PluginConfig;\n configuredNamespaceList(): string[];\n fetchActiveArtifactsForNamespace(\n namespace: string,\n prompt: string,\n targetCount: number,\n ): Promise<MemoryFile[]>;\n loadNamespaceStorageDirHintsFromCatalog(): void;\n readonly namespaceCatalog: NamespaceCatalog;\n namespaceFromPath(p: string): string;\n readonly namespaceSearchRouter: NamespaceSearchRouter;\n namespaceStorageDirHintOwnershipRank(\n record: { namespace: string },\n resolvedStorageDir: string,\n configured: Set<string>,\n ): number;\n readonly namespaceStorageDirHints: Map<string, Set<string>>;\n namespaceStorageDirHintsLoaded: boolean;\n preferNamespaceStorageDirHintOwner(\n current: { namespace: string; identityToken: string; storageDir: string },\n candidate: { namespace: string; identityToken: string; storageDir: string },\n resolvedStorageDir: string,\n configured: Set<string>,\n ): { namespace: string; identityToken: string; storageDir: string };\n readonly qmd: SearchBackend;\n qmdCollectionNamespaceFromPrefix(collectionPrefix: string): string | null;\n rememberNamespaceStorageDirHint(namespace: string, storageDir?: string): void;\n storageDirMatchesNamespaceHint(namespace: string, storageDir: string): boolean;\n readonly storageRouter: NamespaceStorageRouter;\n}\n\nexport class NamespaceReadFanoutCoordinator {\n constructor(\n private readonly deps: NamespaceReadFanoutDeps,\n ) {}\n\n preferNamespaceStorageDirHintOwner(\n current: { namespace: string; identityToken: string; storageDir: string },\n candidate: { namespace: string; identityToken: string; storageDir: string },\n resolvedStorageDir: string,\n configured: Set<string>,\n ): { namespace: string; identityToken: string; storageDir: string } {\n const currentRank = this.deps.namespaceStorageDirHintOwnershipRank(\n current,\n resolvedStorageDir,\n configured,\n );\n const candidateRank = this.deps.namespaceStorageDirHintOwnershipRank(\n candidate,\n resolvedStorageDir,\n configured,\n );\n if (candidateRank < currentRank) return candidate;\n if (candidateRank > currentRank) return current;\n\n const byName = candidate.namespace.localeCompare(current.namespace);\n if (byName < 0) return candidate;\n if (byName > 0) return current;\n return candidate.identityToken.localeCompare(current.identityToken) < 0\n ? candidate\n : current;\n }\n\n loadNamespaceStorageDirHintsFromCatalog(): void {\n if (this.deps.namespaceStorageDirHintsLoaded || !this.deps.namespaceCatalog.enabled) return;\n this.deps.namespaceStorageDirHintsLoaded = true;\n const catalogPath = path.join(this.deps.config.memoryDir, \"state\", \"namespaces.jsonl\");\n if (!existsSync(catalogPath)) return;\n\n let body: string;\n try {\n body = readFileSync(catalogPath, \"utf8\");\n } catch {\n return;\n }\n\n const compactedByNamespace = new Map<\n string,\n { namespace: string; identityToken: string; storageDir: string }\n >();\n for (const line of body.split(/\\r?\\n/)) {\n const trimmed = line.trim();\n if (!trimmed) continue;\n try {\n const parsed = JSON.parse(trimmed) as unknown;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) continue;\n const record = parsed as Record<string, unknown>;\n if (\n typeof record.namespace !== \"string\" ||\n typeof record.storageDir !== \"string\" ||\n typeof record.identityToken !== \"string\"\n ) {\n continue;\n }\n const namespace = normalizeNamespaceIdentity(record.namespace);\n if (!namespace || record.identityToken !== namespaceIdentityToken(namespace)) continue;\n compactedByNamespace.set(namespace, {\n namespace,\n identityToken: record.identityToken,\n storageDir: record.storageDir,\n });\n } catch {\n // Catalog hints are best-effort. The catalog reader still owns full recovery.\n }\n }\n\n const configured = new Set(\n this.deps.configuredNamespaceList().map((namespace) => normalizeNamespaceIdentity(namespace)),\n );\n const preferredByStorageDir = new Map<\n string,\n { namespace: string; identityToken: string; storageDir: string }\n >();\n for (const record of compactedByNamespace.values()) {\n if (!this.deps.storageDirMatchesNamespaceHint(record.namespace, record.storageDir)) {\n continue;\n }\n const resolvedStorageDir = path.resolve(record.storageDir);\n const current = preferredByStorageDir.get(resolvedStorageDir);\n preferredByStorageDir.set(\n resolvedStorageDir,\n current\n ? this.deps.preferNamespaceStorageDirHintOwner(\n current,\n record,\n resolvedStorageDir,\n configured,\n )\n : record,\n );\n }\n for (const record of preferredByStorageDir.values()) {\n this.deps.rememberNamespaceStorageDirHint(record.namespace, record.storageDir);\n }\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 if (\n resolveNamespaceCapabilities(this.deps.config).namespaces &&\n options.namespaces !== undefined &&\n options.namespaces.length === 0\n ) {\n return [];\n }\n const namespaces = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? Array.from(\n new Set(\n (options.namespaces?.length\n ? options.namespaces\n : this.deps.configuredNamespaceList()\n )\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n )\n : [this.deps.config.defaultNamespace];\n\n if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {\n switch (options.mode) {\n case \"hybrid\":\n return await this.deps.qmd.hybridSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"bm25\":\n return await this.deps.qmd.bm25Search(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"vector\":\n return await this.deps.qmd.vectorSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n default:\n return await this.deps.qmd.search(\n options.query,\n undefined,\n options.maxResults,\n options.searchOptions,\n options.execution,\n );\n }\n }\n\n return await this.deps.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 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.deps.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.deps.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 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.deps.fetchActiveArtifactsForNamespace(namespace, prompt, targetCount),\n ),\n );\n\n return mergeArtifactRecallCandidates(filteredByNamespace, targetCount);\n }\n\n 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 = resolveNamespaceCapabilities(this.deps.config).namespaces\n ? this.deps.namespaceFromPath(memoryPath)\n : this.deps.config.defaultNamespace;\n const storage = await this.deps.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 async resolveStateDirForNamespace(\n namespace: string,\n ): Promise<string> {\n if (!resolveNamespaceCapabilities(this.deps.config).namespaces) {\n return path.join(this.deps.config.memoryDir, \"state\");\n }\n if (namespace !== this.deps.config.defaultNamespace) {\n return path.join(this.deps.config.memoryDir, \"namespaces\", namespace, \"state\");\n }\n const candidate = path.join(\n this.deps.config.memoryDir,\n \"namespaces\",\n this.deps.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.deps.config.memoryDir, \"state\");\n }\n\n namespaceFromPath(p: string): string {\n if (!resolveNamespaceCapabilities(this.deps.config).namespaces) return this.deps.config.defaultNamespace;\n const parts = qmdCollectionPathParts(p);\n const collectionNamespace = parts\n ? this.deps.qmdCollectionNamespaceFromPrefix(parts.collection)\n : null;\n if (collectionNamespace) return collectionNamespace;\n const m = p.match(/[\\\\/]+namespaces[\\\\/]+([^\\\\/]+)(?:[\\\\/]|$)/);\n if (!m?.[1]) return this.deps.config.defaultNamespace;\n return namespaceIdentityFromToken(m[1]) ?? m[1];\n }\n\n storageDirNamespace(storageDir: string): string {\n // #1521: delegates to the scope-module resolver. The inline dir→namespace\n // derivation (token round-trip guard, catalog hints) is retired so the\n // adHocNamespaceResolutions ratchet no longer counts this site. Hints are\n // loaded lazily via the callback (only after early returns, matching the\n // original behavior — codex P2).\n return resolveNamespaceFromStorageDir(storageDir, {\n config: this.deps.config,\n configuredNamespaces: this.deps.configuredNamespaceList(),\n hints: this.deps.namespaceStorageDirHints,\n loadHints: () => this.deps.loadNamespaceStorageDirHintsFromCatalog(),\n });\n }\n\n 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.deps.storageRouter.storageFor(ns);\n return sm.readAllMemories();\n }),\n );\n return lists.flat();\n }\n\n 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.deps.storageRouter.storageFor(ns);\n return sm.readArchivedMemories();\n }),\n );\n return lists.flat();\n }\n}\n","/**\n * Live self-deps factory (issue #1526 seam 27).\n *\n * Every coordinator extracted from the orchestrator (seams 4–26) takes a\n * deps bundle whose property names MATCH the orchestrator's own member\n * names, wired as live accessors / late-binding arrows so instance-level\n * test stubs and subclass overrides keep taking effect. Those hand-written\n * wiring blocks were ~100 lines each and pure repetition. This factory\n * replaces them with a Proxy that preserves the exact semantics:\n *\n * - property GET reads `self[prop]` live on every access (late binding —\n * an instance stub installed after coordinator creation is observed);\n * - method properties are bound to `self` at access time, so `this`\n * inside the orchestrator method stays the orchestrator;\n * - property SET writes through to `self` (gate fields like\n * `deferredReady` / `lastXraySnapshot` stay on the orchestrator);\n * - getters on `self` (e.g. `fastLlmForRerank`) are invoked live.\n *\n * The `as unknown as T` cast is deliberate: the deps interfaces reference\n * the orchestrator's PRIVATE members, which TypeScript cannot verify\n * structurally from outside the class. The interfaces remain fully\n * enforced on the coordinator side. Per-access `bind` costs nanoseconds\n * and allocates one closure per property access — negligible against the\n * I/O-bound work every coordinator method performs.\n */\nexport function selfDeps<T extends object>(self: object): T {\n const source = self as Record<PropertyKey, unknown>;\n return new Proxy(Object.create(null) as object, {\n get(_target, prop) {\n const value = source[prop as string];\n return typeof value === \"function\"\n ? (value as (...args: unknown[]) => unknown).bind(self)\n : value;\n },\n set(_target, prop, value) {\n // Fail fast on writes to properties the orchestrator does not\n // declare (Kilo review on PR #1801): returning false makes the\n // assignment throw a TypeError in strict mode, matching the\n // error-safety of the hand-written accessor blocks this factory\n // replaced. Legitimate gate-field writes (deferredReady,\n // lastXraySnapshot, …) all target existing members.\n if (!((prop as string) in source)) return false;\n source[prop as string] = value;\n return true;\n },\n has(_target, prop) {\n return (prop as string) in source;\n },\n }) as unknown as T;\n}\n","/**\n * Diff-aware review-context packer (issue #569 PR 4).\n *\n * When an agent is asked \"review this PR\" / \"what changed in this diff\" /\n * \"look at this diff\", the prompt that reaches recall is short and generic\n * — the real signal is the diff itself. This module:\n *\n * 1. Detects review-intent prompts via `isReviewPrompt`.\n * 2. Extracts the touched file list from a unified diff via\n * `parseTouchedFiles`.\n * 3. Re-ranks a set of candidate memories so that memories whose\n * `entityRefs` mention a touched path float to the top. The boost is\n * additive and bounded so it doesn't obliterate the original ranking —\n * it's a bias, not a filter.\n *\n * Pure — no orchestrator, no storage. Callers inject the candidate memories\n * they already have from their normal recall pipeline. This keeps the\n * module easy to test and integrates cleanly with the existing tiered-recall\n * code in `orchestrator.ts` (the tier itself can be wired later; the pure\n * surface is what PRs 5/6/7 will call).\n */\n\nimport type {\n StructuralContextDegradation,\n StructuralContextProvider,\n} from \"./structural-context.js\";\n\n// ──────────────────────────────────────────────────────────────────────────\n// Public types\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * A memory candidate as fed into review-context ranking. The shape is a\n * deliberate subset of the core `MemorySummary` / recall result — only the\n * fields we actually need — so this module stays decoupled from the rest of\n * the codebase and can be reused by CLI tools, bench fixtures, etc.\n */\nexport interface ReviewCandidate {\n /** Opaque identifier. Echoed unchanged in the output. */\n id: string;\n /**\n * Pre-review relevance score from the upstream recall pipeline. Higher is\n * better. `0` is treated as \"no prior signal\" and gets the full review\n * boost when a path match is found.\n */\n score: number;\n /**\n * References the memory mentions (file paths, entity names, etc.). Used\n * to decide whether any touched file appears in the memory's scope.\n *\n * Accepts `undefined`/missing so callers can pass sparse records from\n * legacy storage without pre-filling.\n */\n entityRefs?: string[];\n}\n\nexport interface ReviewContext {\n /**\n * Normalized file paths touched by the diff. Each entry is forward-slashed\n * and relative to the repo root when possible.\n */\n touchedFiles: string[];\n /**\n * Candidates re-sorted so memories whose `entityRefs` mention a touched\n * path are boosted. Shape matches the input `ReviewCandidate[]` — the\n * boost is recorded on each entry as `boost` for observability.\n */\n rankedRecall: Array<ReviewCandidate & { boost: number }>;\n /**\n * Structural-context provider degradation observed while expanding the\n * diff to touched symbols (issue #1548 Track A PR 5, #1536 pattern).\n * Present only when a provider was consulted AND it failed — a silent\n * provider failure must never look like \"no structural matches\"\n * (CLAUDE.md rule 34). Undefined when no provider was consulted (the\n * pure {@link packReviewContext} path) or when the provider succeeded.\n */\n structuralDegradation?: StructuralContextDegradation;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Review-prompt heuristic\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Keyword list from the #569 design doc, plus obvious paraphrases. All\n * matching is case-insensitive and whole-word (so `reviewer` doesn't trigger\n * on `review` alone).\n */\nconst REVIEW_KEYWORD_PATTERNS: RegExp[] = [\n /\\breview\\b/i,\n /\\bdiff\\b/i,\n /\\bwhat changed\\b/i,\n /\\blook at this pr\\b/i,\n /\\bwhat('?s|\\s+is)\\s+in\\s+this\\s+(pr|patch|diff|change)\\b/i,\n /\\bcode review\\b/i,\n];\n\n/**\n * `true` when the prompt looks like a review / diff-explanation request.\n *\n * Empty / non-string input → `false` (the caller shouldn't branch on an\n * invalid prompt).\n */\nexport function isReviewPrompt(prompt: string | null | undefined): boolean {\n if (typeof prompt !== \"string\") return false;\n const trimmed = prompt.trim();\n if (!trimmed) return false;\n return REVIEW_KEYWORD_PATTERNS.some((re) => re.test(trimmed));\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Unified-diff parser — extract touched files\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Parse a unified diff and return the set of files touched. Accepts both the\n * `diff --git` form (`diff --git a/foo b/bar`) and the `--- / +++` form\n * (`--- a/foo\\n+++ b/bar`). Returns deduplicated, repo-root-relative paths\n * (with the conventional `a/` / `b/` prefixes stripped).\n *\n * Path entries of `/dev/null` (used in adds/deletes) are excluded.\n */\nexport function parseTouchedFiles(diff: string | null | undefined): string[] {\n if (typeof diff !== \"string\" || !diff.trim()) return [];\n const touched = new Set<string>();\n const lines = diff.split(/\\r?\\n/);\n\n for (const line of lines) {\n // `diff --git a/foo/bar.ts b/foo/bar.ts`\n //\n // Paths may be quoted by git when they contain spaces or non-ASCII\n // characters, e.g. `diff --git \"a/src/my file.ts\" \"b/src/my file.ts\"`.\n // The two paths are always separated by whitespace at the top level, but\n // whitespace INSIDE quoted paths must NOT split the tokens. Parse the\n // two paths with an explicit tokenizer instead of a `\\S+`-based regex\n // (which would shatter `\"a/my file.ts\"` into `\"a/my` / `file.ts\"`).\n const gitPrefix = line.match(/^diff --git\\s+/);\n if (gitPrefix) {\n const rest = line.slice(gitPrefix[0].length);\n const paths = splitDiffGitPaths(rest);\n if (paths) {\n for (const raw of paths) {\n const stripped = stripDiffPathPrefix(raw);\n if (stripped && stripped !== \"/dev/null\") touched.add(stripped);\n }\n }\n continue;\n }\n // `--- a/foo/bar.ts` or `+++ b/foo/bar.ts` — or quoted:\n // `--- \"a/foo bar.ts\"` / `+++ \"b/foo bar.ts\"` when git emits C-quoted\n // paths for whitespace or non-ASCII filenames.\n //\n // Matched with an anchored prefix and an explicit tokenizer for the\n // tail so quoted paths containing whitespace are not split on the\n // first internal space. The previous `\\S+` form silently dropped\n // everything after the first whitespace in a quoted path.\n const headerPrefix = line.match(/^(?:---|\\+\\+\\+)[ \\t]+/);\n if (headerPrefix) {\n // Linear trailing space/tab trim instead of /[ \\t]+$/, whose anchored\n // quantifier backtracks polynomially on a long diff line (CodeQL\n // js/polynomial-redos).\n const sliced = line.slice(headerPrefix[0].length);\n let tailEnd = sliced.length;\n while (tailEnd > 0 && (sliced[tailEnd - 1] === \" \" || sliced[tailEnd - 1] === \"\\t\")) tailEnd--;\n const tail = sliced.slice(0, tailEnd);\n const raw = extractSingleDiffPathToken(tail);\n if (raw) {\n const stripped = stripDiffPathPrefix(raw);\n if (stripped && stripped !== \"/dev/null\") touched.add(stripped);\n }\n }\n }\n\n return Array.from(touched).sort();\n}\n\n/**\n * Extract the single path token from the tail of a `---` / `+++` header\n * line. Returns `null` when the tail is empty or malformed (e.g. an\n * unterminated quoted path). The whole tail is consumed — trailing\n * timestamps from non-git diff frontends (`--- a/foo\t2023-01-01`) fall\n * into a leading-token extraction like the quoted-form case.\n */\nfunction extractSingleDiffPathToken(tail: string): string | null {\n if (tail.length === 0) return null;\n if (tail[0] === '\"') {\n let j = 1;\n while (j < tail.length) {\n if (tail[j] === \"\\\\\" && j + 1 < tail.length) {\n j += 2;\n continue;\n }\n if (tail[j] === '\"') break;\n j += 1;\n }\n if (j >= tail.length) return null; // unterminated quoted path\n return tail.slice(0, j + 1);\n }\n // Unquoted: consume up to the first tab or whitespace-run, so standard\n // `--- a/foo\t<timestamp>` lines surface just `a/foo`. For ordinary\n // git-style output the tail has no whitespace at all.\n let j = 0;\n while (j < tail.length && tail[j] !== \" \" && tail[j] !== \"\\t\") j += 1;\n return tail.slice(0, j);\n}\n\n/**\n * Split the `a-path b-path` portion of a `diff --git` line into exactly two\n * path tokens, respecting git's quoting convention. Returns `null` when the\n * input cannot be parsed into exactly two tokens.\n */\nfunction splitDiffGitPaths(rest: string): [string, string] | null {\n const tokens: string[] = [];\n let i = 0;\n while (i < rest.length && tokens.length < 2) {\n // Skip leading whitespace between tokens.\n while (i < rest.length && (rest[i] === \" \" || rest[i] === \"\\t\")) i += 1;\n if (i >= rest.length) break;\n if (rest[i] === '\"') {\n // Quoted path: consume up to the matching unescaped `\"`. Git escapes\n // inner quotes as `\\\"`, so we respect backslash escaping.\n let j = i + 1;\n while (j < rest.length) {\n if (rest[j] === \"\\\\\" && j + 1 < rest.length) {\n j += 2;\n continue;\n }\n if (rest[j] === '\"') break;\n j += 1;\n }\n if (j >= rest.length) return null; // unterminated quoted path\n tokens.push(rest.slice(i, j + 1));\n i = j + 1;\n } else {\n // Unquoted path: run of non-whitespace.\n let j = i;\n while (j < rest.length && rest[j] !== \" \" && rest[j] !== \"\\t\") j += 1;\n tokens.push(rest.slice(i, j));\n i = j;\n }\n }\n if (tokens.length !== 2) return null;\n return [tokens[0]!, tokens[1]!];\n}\n\nfunction stripDiffPathPrefix(raw: string): string {\n // Git conventionally prefixes paths with `a/` or `b/` in diffs, and\n // quotes the whole path (including the prefix) when it contains spaces or\n // non-ASCII bytes. Quote-stripping must therefore happen BEFORE the\n // prefix check — otherwise `\"a/path with spaces.ts\"` still starts with\n // `\"a` and the prefix is never recognized.\n let s = raw;\n if (s.length >= 2 && s[0] === '\"' && s[s.length - 1] === '\"') {\n const decoded = decodeGitCQuotedPath(s.slice(1, -1));\n if (decoded === null) {\n return raw;\n }\n s = decoded;\n }\n // Normalize Windows-style backslashes. Must happen AFTER quote stripping\n // so that C-quote escape pairs are decoded before path separators are\n // normalized.\n s = s.replace(/\\\\/g, \"/\");\n if (s.startsWith(\"a/\") || s.startsWith(\"b/\")) s = s.slice(2);\n return s;\n}\n\nfunction decodeGitCQuotedPath(value: string): string | null {\n const bytes: number[] = [];\n const encoder = new TextEncoder();\n const appendText = (text: string) => {\n bytes.push(...encoder.encode(text));\n };\n\n for (let index = 0; index < value.length; index += 1) {\n const char = value[index]!;\n if (char !== \"\\\\\") {\n appendText(char);\n continue;\n }\n\n if (index + 1 >= value.length) {\n appendText(\"\\\\\");\n continue;\n }\n\n const next = value[index + 1]!;\n if (next >= \"0\" && next <= \"7\") {\n let octal = next;\n let cursor = index + 2;\n while (cursor < value.length && octal.length < 3) {\n const digit = value[cursor]!;\n if (digit < \"0\" || digit > \"7\") break;\n octal += digit;\n cursor += 1;\n }\n bytes.push(Number.parseInt(octal, 8));\n index = cursor - 1;\n continue;\n }\n\n const escaped = cEscapeValue(next);\n if (escaped !== null) {\n appendText(escaped);\n index += 1;\n continue;\n }\n\n appendText(`\\\\${next}`);\n index += 1;\n }\n\n try {\n return new TextDecoder(\"utf-8\", { fatal: true }).decode(Uint8Array.from(bytes));\n } catch {\n return null;\n }\n}\n\nfunction cEscapeValue(value: string): string | null {\n switch (value) {\n case \"n\":\n return \"\\n\";\n case \"t\":\n return \"\\t\";\n case \"r\":\n return \"\\r\";\n case \"b\":\n return \"\\b\";\n case \"f\":\n return \"\\f\";\n case \"\\\\\":\n case '\"':\n return value;\n default:\n return null;\n }\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Ranking\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Additive boost per matching touched-file. Tuned so that a single exact\n * match is enough to float a `score=0` candidate above a `score=0.4`\n * unmatched peer, but not so large it buries multi-signal results. `0.5`\n * per match, capped at `1.0` so three matches don't eclipse strong recall.\n */\nconst BOOST_PER_MATCH = 0.5;\nconst MAX_BOOST = 1.0;\n\n/**\n * Count how many touched files appear in a memory's entityRefs. Matches are\n * literal substring matches on either direction — either the ref contains\n * the path, or the path contains the ref — so both\n * - `\"src/foo.ts\"` refs matching a touched `\"src/foo.ts\"`, and\n * - `\"foo.ts\"` refs matching a touched `\"src/foo.ts\"`\n * succeed.\n */\nfunction countPathHits(entityRefs: string[] | undefined, touchedFiles: string[]): number {\n if (!entityRefs || entityRefs.length === 0) return 0;\n if (touchedFiles.length === 0) return 0;\n let hits = 0;\n for (const ref of entityRefs) {\n if (typeof ref !== \"string\" || !ref) continue;\n const lowered = ref.toLowerCase();\n for (const file of touchedFiles) {\n const flower = file.toLowerCase();\n if (lowered === flower) {\n hits += 1;\n break;\n }\n if (lowered.includes(flower) || flower.includes(lowered)) {\n hits += 1;\n break;\n }\n }\n }\n return hits;\n}\n\n/**\n * Build a review-context ranking for a set of candidate memories.\n *\n * Contract:\n * - `touchedFiles` is the parsed diff file list.\n * - `candidates` is passed through unchanged when no boost applies.\n * - When a boost applies, the result is sorted by `(score + boost)` desc,\n * with a stable secondary sort on the original `id` for determinism\n * (CLAUDE.md #19 — comparators must return 0 for equal items).\n */\nexport function rankReviewCandidates(\n candidates: ReviewCandidate[],\n touchedFiles: string[],\n): Array<ReviewCandidate & { boost: number }> {\n const annotated: Array<ReviewCandidate & { boost: number }> = candidates.map((c) => {\n const hits = countPathHits(c.entityRefs, touchedFiles);\n const boost = Math.min(MAX_BOOST, hits * BOOST_PER_MATCH);\n return { ...c, boost };\n });\n\n annotated.sort((a, b) => {\n const adjA = a.score + a.boost;\n const adjB = b.score + b.boost;\n if (adjA !== adjB) return adjB - adjA;\n // Stable secondary sort for deterministic ordering on ties.\n if (a.id < b.id) return -1;\n if (a.id > b.id) return 1;\n return 0;\n });\n\n return annotated;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Packer entry point\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface PackReviewContextInput {\n /** Unified diff, as produced by `git diff`. */\n diff: string | null | undefined;\n /** Candidate memories from the upstream recall pipeline. */\n candidates: ReviewCandidate[];\n}\n\n/**\n * Top-level entry point used by the orchestrator (and CLI / bench) when a\n * review-intent prompt is detected.\n *\n * Parses the diff, re-ranks the candidates, and returns both artefacts so\n * the caller can surface `touchedFiles` as context and `rankedRecall` as\n * the recall result.\n */\nexport function packReviewContext(input: PackReviewContextInput): ReviewContext {\n const touchedFiles = parseTouchedFiles(input.diff);\n const rankedRecall = rankReviewCandidates(input.candidates, touchedFiles);\n return { touchedFiles, rankedRecall };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Structural-context enhancement (issue #1548 Track A PR 5)\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Input for the structural-context-aware review-context packer. The pure\n * {@link packReviewContext} stays unchanged (gate-off parity); this async\n * variant consults a {@link StructuralContextProvider} to expand the diff's\n * touched FILE paths into touched SYMBOL names, widening the match set so\n * memories that mention a changed symbol — not just the file path — float\n * up. The gate (`structuralProvider !== \"none\"`) is checked ONCE by the\n * caller, never inside this function (rule 39).\n */\nexport interface PackReviewContextStructuralInput extends PackReviewContextInput {\n /** A probed structural-context provider. Never undefined here. */\n provider: StructuralContextProvider;\n /** Cancellation forwarded to the provider subprocess (rule 40). */\n signal?: AbortSignal;\n}\n\n/**\n * Structural-context-aware packer.\n *\n * Contract (issue #1548 Track A PR 5, prove-fail-before characterization):\n * - Provider returns symbols (`ok: true`) → symbol names are ADDED to the\n * match set alongside touched files; memories mentioning a symbol get the\n * same bounded additive boost as a file-path match.\n * - Provider fails (`ok: false`, any code) → ranking falls back to\n * FILE-PATH-ONLY boosting, BYTE-IDENTICAL to {@link packReviewContext}\n * (the match set is exactly the touched files), AND `structuralDegradation`\n * is populated so xray/doctor can surface the failure (rule 34).\n *\n * The underlying ranker ({@link rankReviewCandidates}) is reused unchanged,\n * so the deterministic ordering, boost cap, and tie-break are identical to\n * the pure path.\n */\nexport async function packReviewContextStructural(\n input: PackReviewContextStructuralInput,\n): Promise<ReviewContext> {\n const touchedFiles = parseTouchedFiles(input.diff);\n const diffString = typeof input.diff === \"string\" ? input.diff : \"\";\n const result = await input.provider.symbolsForDiff(diffString, {\n signal: input.signal,\n });\n\n let matchTerms: string[] = touchedFiles;\n let structuralDegradation: StructuralContextDegradation | undefined;\n\n if (result.ok) {\n const symbolNames = result.symbols.map((sym) => sym.symbol);\n matchTerms = symbolNames.length > 0 ? [...touchedFiles, ...symbolNames] : touchedFiles;\n } else {\n // Fallback: file-path-only ranking, identical to the pure packer. The\n // degradation is surfaced so the failure is never silent (rule 34).\n structuralDegradation = {\n backend: \"structural-context\",\n code: result.code,\n detail: result.detail,\n };\n }\n\n const rankedRecall = rankReviewCandidates(input.candidates, matchTerms);\n return { touchedFiles, rankedRecall, structuralDegradation };\n}\n","/**\n * Structural-context provider port (issue #1548 Track A PR 5).\n *\n * The architectural boundary between Track A (durable coding-memory\n * features) and Track B (the native @remnic/coding-graph engine). A\n * structural-context provider expands a unified diff into the SYMBOLS it\n * touches (and optionally yields architecture hints), so review-intent\n * recall can boost memories that mention those symbols — not just the\n * bare file paths that `review-context.ts` already boosts on.\n *\n * Three providers satisfy this port, selected by\n * `codingKnowledge.structuralProvider`:\n *\n * - `\"none\"` — no provider consulted (default; review-context stays\n * file-path-only, byte-identical to pre-feature — rule 39).\n * - `\"subprocess\"` — an external binary shelled out via `execFile` with an\n * argv ARRAY (never a shell string — rule 10). The\n * built-in adapter lives in `structural-subprocess-provider.ts`;\n * codebase-memory-mcp's CLI mode is the canonical target,\n * but the provider is command-agnostic.\n * - `\"native\"` — the in-family @remnic/coding-graph engine, adapted to\n * this port by a future PR (#1551/#1554). Only the enum\n * value and this doc note land in this PR — no engine\n * code. codebase-memory-mcp remains a supported\n * subprocess provider through this same port regardless.\n *\n * Every result is a tagged outcome shaped like #1536's `SearchDegradation`\n * (CLAUDE.md rule 34 — a degraded/absent provider must NEVER masquerade as\n * \"no structural matches\"):\n * - `{ ok: true, symbols }` on success\n * - `{ ok: false, code }` on every failure (distinct codes per mode)\n *\n * No module-level mutable state (rule 11): the registry is keyed per\n * orchestrator/service instance via a `Symbol.for(...)` slot on\n * `globalThis`, mirroring `host-embedding-provider.ts`.\n */\nimport type { CodingKnowledgeConfig, PluginConfig } from \"../types.js\";\n\n// ──────────────────────────────────────────────────────────────────────────\n// Tagged-outcome types (rule 34 — #1536 pattern; rule 18 — object-not-null)\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Distinct failure codes for the structural-context port. Every code is\n * load-bearing: callers (review-context, `remnic doctor`, xray) switch on\n * `code` to distinguish \"binary not installed\" from \"timed out\" from\n * \"protocol violation\" so a silent provider failure can never look like an\n * empty-but-healthy result.\n */\nexport type StructuralContextErrorCode =\n /** Probe failed: binary missing / not executable, or native package absent. */\n | \"provider_unavailable\"\n /** The provider exceeded its deadline. */\n | \"provider_timeout\"\n /** Output was present but not a valid JSON object/array (rule 18). */\n | \"provider_malformed\"\n /** Provider ran but returned an explicit error or threw. */\n | \"provider_error\";\n\n/**\n * A single symbol touched by a diff. The `symbol` name is the load-bearing\n * field — it is what review-context adds to its match set. `path`/`kind`\n * are informational and surface in xray when present.\n */\nexport interface StructuralSymbol {\n /** Qualified or bare symbol name, e.g. `\"AuthService.login\"` or `\"login\"`. */\n readonly symbol: string;\n /** Source file the symbol lives in (forward-slashed, repo-relative when possible). */\n readonly path?: string;\n /** Coarse kind if the provider knows it (`function`/`method`/`class`/...). */\n readonly kind?: string;\n}\n\nexport interface SymbolsForDiffOk {\n readonly ok: true;\n readonly symbols: StructuralSymbol[];\n /** Provider-reported latency in ms, when available. */\n readonly latencyMs?: number;\n}\n\nexport interface SymbolsForDiffErr {\n readonly ok: false;\n readonly code: StructuralContextErrorCode;\n readonly detail?: string;\n}\n\nexport type SymbolsForDiffResult = SymbolsForDiffOk | SymbolsForDiffErr;\n\nexport interface ArchitectureHintsOk {\n readonly ok: true;\n readonly hints: string[];\n}\nexport interface ArchitectureHintsErr {\n readonly ok: false;\n readonly code: StructuralContextErrorCode;\n readonly detail?: string;\n}\nexport type ArchitectureHintsResult = ArchitectureHintsOk | ArchitectureHintsErr;\n\n/**\n * The port contract. Both the built-in subprocess adapter\n * (`structural-subprocess-provider.ts`) and the future native engine\n * adapter (#1551) implement this. Registry callers retrieve an instance by\n * scope; never construct one inline at a call site.\n */\nexport interface StructuralContextProvider {\n /** Stable identifier for registry logging / `remnic doctor`. */\n readonly id: string;\n /**\n * Probe availability. Resolves to a tagged result so a missing binary\n * (subprocess) or absent package (native) is surfaced, never thrown\n * (rule 34). Implementations SHOULD cache the outcome per instance\n * (rule 11).\n */\n probe(): Promise<{ available: boolean; detail?: string }>;\n /**\n * Expand a unified diff to the symbols it touches. NEVER throws — every\n * failure path returns a tagged `{ ok: false, code }`. The optional\n * `signal` lets the caller cancel an in-flight subprocess (rule 40).\n */\n symbolsForDiff(\n diff: string,\n options?: { signal?: AbortSignal },\n ): Promise<SymbolsForDiffResult>;\n /**\n * Optional architecture hints for a repo root. Used by the architecture\n * card composition (#1548 Track A PR 3 + #1554). Implementations MAY omit\n * this; callers MUST handle its absence.\n */\n architectureHints?(\n root: string,\n options?: { signal?: AbortSignal },\n ): Promise<ArchitectureHintsResult>;\n /** Release any resources the provider holds (subprocess handles, etc.). */\n close?(): Promise<void> | void;\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Degradation (shaped like SearchDegradation from search/port.ts — #1536)\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Backend tag is a literal so consumers can switch on it programmatically\n * alongside `SearchDegradation` (`backend: \"qmd\"`). `detail` is optional\n * and never load-bearing — `code` is the signal.\n */\nexport interface StructuralContextDegradation {\n readonly backend: \"structural-context\";\n readonly code: StructuralContextErrorCode;\n readonly detail?: string;\n}\n\n/**\n * Coerce a {@link SymbolsForDiffErr} into the degradation record consumers\n * attach to recall snapshots / xray. Centralised so the `{ backend: ... }`\n * tag is set in one place (rule 22 spirit).\n */\nexport function toStructuralContextDegradation(\n err: SymbolsForDiffErr,\n): StructuralContextDegradation {\n return { backend: \"structural-context\", code: err.code, detail: err.detail };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Registry — instance-scoped via Symbol (rule 11; mirrors host-embedding)\n// ──────────────────────────────────────────────────────────────────────────\n\nconst STRUCTURAL_PROVIDERS_KEY = Symbol.for(\n \"remnic.structuralContextProviders\",\n);\n\nfunction providerMap(): Map<string, StructuralContextProvider> {\n const store = globalThis as Record<PropertyKey, unknown>;\n const existing = store[STRUCTURAL_PROVIDERS_KEY];\n if (existing instanceof Map) {\n return existing as Map<string, StructuralContextProvider>;\n }\n const created = new Map<string, StructuralContextProvider>();\n store[STRUCTURAL_PROVIDERS_KEY] = created;\n return created;\n}\n\nfunction normalizeScope(scope: string): string {\n const normalized = typeof scope === \"string\" ? scope.trim() : \"\";\n return normalized || \"default\";\n}\n\n/**\n * Register a provider for a scope (typically an orchestrator `serviceId`).\n * Overwriting a previous registration closes the old provider. Returns an\n * unregister function — callers SHOULD invoke it on service teardown so a\n * hot-reloaded host does not leak subprocess handles.\n */\nexport function registerStructuralContextProvider(\n scope: string,\n provider: StructuralContextProvider,\n): () => void {\n const key = normalizeScope(scope);\n const providers = providerMap();\n const previous = providers.get(key);\n if (previous && previous !== provider) {\n void previous.close?.();\n }\n providers.set(key, provider);\n return () => {\n const current = providerMap();\n if (current.get(key) === provider) {\n current.delete(key);\n void provider.close?.();\n }\n };\n}\n\n/** Look up the provider registered for a scope, if any. */\nexport function getStructuralContextProvider(\n scope: string,\n): StructuralContextProvider | undefined {\n return providerMap().get(normalizeScope(scope));\n}\n\n/** Test-only: clear every registered provider. */\nexport function clearStructuralContextProvidersForTest(): void {\n providerMap().clear();\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Gate predicate — rule 39: ONE predicate, checked identically on every path\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * The single gate every review-context consumer consults before consulting a\n * provider. Returns `true` iff the master `codingKnowledge.enabled` switch is\n * on AND `structuralProvider` is not `\"none\"`. When this returns `false`,\n * review-context runs its pure file-path-only ranker — byte-identical to\n * pre-feature behaviour on every path.\n */\nexport function structuralProviderActive(config: PluginConfig): boolean {\n const ck = config.codingKnowledge;\n if (ck === undefined || ck === null) return false;\n return ck.enabled === true && ck.structuralProvider !== \"none\";\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Doctor / xray status — pure config-only summariser + renderer\n// (the live PROBE lives in structural-subprocess-provider.ts so this module\n// stays free of subprocess / optional-package imports)\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Config-only structural provider status. `remnic doctor` and xray render\n * this; an async sibling in `structural-subprocess-provider.ts` augments it\n * with a live `probed` field.\n */\nexport interface StructuralProviderStatus {\n readonly active: boolean;\n readonly mode: CodingKnowledgeConfig[\"structuralProvider\"];\n /** Command path when mode is `\"subprocess\"` and a command is configured. */\n readonly command?: string;\n /** Provider id when one is registered for the scope. */\n readonly providerId?: string;\n /** Live probe outcome — set only by the async doctor probe. */\n probed?: { available: boolean; detail?: string };\n}\n\n/**\n * Summarise the structural provider status from config ALONE (no probe, no\n * I/O). Pure — safe to call from any context, including the recall hot path\n * for xray labels.\n */\nexport function describeStructuralProviderStatus(\n config: PluginConfig,\n scope?: string,\n): StructuralProviderStatus {\n const ck = config.codingKnowledge;\n const mode: CodingKnowledgeConfig[\"structuralProvider\"] =\n ck?.structuralProvider ?? \"none\";\n const active = structuralProviderActive(config);\n const provider =\n scope !== undefined ? getStructuralContextProvider(scope) : undefined;\n return {\n active,\n mode,\n command:\n mode === \"subprocess\" && ck?.structuralProviderCommand\n ? ck.structuralProviderCommand\n : undefined,\n providerId: provider?.id,\n };\n}\n\n/**\n * Render a single human-readable line for `remnic doctor`. Pure.\n *\n * `structural-context provider: none (inactive — review-context stays file-path-only)`\n * `structural-context provider: subprocess, command=/usr/local/bin/cbm, probed=available`\n * `structural-context provider: subprocess, command=/usr/local/bin/cbm, probed=unavailable (binary not found)`\n */\nexport function renderStructuralProviderStatusLine(\n status: StructuralProviderStatus,\n): string {\n if (!status.active) {\n return `structural-context provider: ${status.mode} (inactive — review-context stays file-path-only)`;\n }\n const parts = [`structural-context provider: ${status.mode}`];\n if (status.command) parts.push(`command=${status.command}`);\n if (status.providerId) parts.push(`registered=${status.providerId}`);\n if (status.probed) {\n parts.push(\n status.probed.available\n ? \"probed=available\"\n : `probed=unavailable${status.probed.detail ? ` (${status.probed.detail})` : \"\"}`,\n );\n }\n return parts.join(\", \");\n}\n","/**\n * Built-in subprocess structural-context provider + doctor probe\n * (issue #1548 Track A PR 5).\n *\n * Shells out to a configured external binary via `execFile` with an argv\n * ARRAY (never a shell string — rule 10). codebase-memory-mcp's CLI mode is\n * the canonical target, but the provider is command-agnostic: any binary\n * that accepts `<symbols-subcommand> <json-arg>` and emits a JSON object\n * `{ symbols: [{ symbol, path?, kind? }] }` satisfies it.\n *\n * Probe is cached once per instance (rule 11). Every failure path is a\n * tagged outcome — `provider_unavailable` / `provider_timeout` /\n * `provider_malformed` / `provider_error` — never a throw (rule 34).\n *\n * The async {@link probeStructuralProviderForDoctor} constructs a one-shot\n * provider from config so `remnic doctor` can render\n * \"configured / probed / last error code\" without a registered instance.\n */\nimport { execFile } from \"node:child_process\";\nimport { promisify } from \"node:util\";\nimport { accessSync, constants, statSync } from \"node:fs\";\n\nimport type { PluginConfig } from \"../types.js\";\nimport { expandTildePath } from \"../utils/path.js\";\nimport { isCodingGraphInstalled } from \"./optional-coding-graph.js\";\nimport {\n describeStructuralProviderStatus,\n type ArchitectureHintsResult,\n type StructuralContextProvider,\n type StructuralProviderStatus,\n type StructuralContextErrorCode,\n type StructuralSymbol,\n type SymbolsForDiffResult,\n} from \"./structural-context.js\";\n\nconst execFileAsync = promisify(execFile);\n\n/** Injectable spawn shape so tests substitute a stub (rule 33). */\nexport type StructuralSpawnFn = (\n command: string,\n argv: readonly string[],\n options: { timeout: number; signal?: AbortSignal },\n) => Promise<{ stdout: string; stderr: string }>;\n\nexport interface SubprocessProviderOptions {\n /** Absolute path to the binary (rule 24 — statSync at probe time). */\n readonly command: string;\n /**\n * Extra argv appended after the symbols-for-diff subcommand\n * (rule 10 — array, never a shell string).\n */\n readonly args?: readonly string[];\n /** Per-call deadline in ms. Default 5000. */\n readonly timeoutMs?: number;\n /**\n * Subcommand the provider invokes for symbol expansion.\n * Default `\"symbols-for-diff\"`.\n */\n readonly symbolsSubcommand?: string;\n /** Test seam — defaults to promisified `execFile`. */\n readonly spawn?: StructuralSpawnFn;\n}\n\ninterface ProbeState {\n readonly available: boolean;\n readonly detail?: string;\n}\n\nconst DEFAULT_TIMEOUT_MS = 5000;\nconst DEFAULT_SYMBOLS_SUBCOMMAND = \"symbols-for-diff\";\n\n/**\n * Construct a structural-context provider backed by an external subprocess.\n * The instance is self-contained: callers register it via\n * `registerStructuralContextProvider(scope, provider)` and dispose via the\n * returned unregister handle.\n */\nexport function createSubprocessStructuralProvider(\n options: SubprocessProviderOptions,\n): StructuralContextProvider {\n // Rule 17 — expand a leading ~ so a home-relative binary path\n // (e.g. ~/bin/cbm) resolves instead of degrading to unavailable.\n // Mirrors the codegraph-runtime.ts precedent for operator paths.\n const command = expandTildePath(options.command.trim());\n const extraArgs = options.args ?? [];\n const timeoutMs = options.timeoutMs ?? DEFAULT_TIMEOUT_MS;\n const symbolsSubcommand = options.symbolsSubcommand ?? DEFAULT_SYMBOLS_SUBCOMMAND;\n const spawn: StructuralSpawnFn = options.spawn ?? defaultSpawn;\n\n let probeState: ProbeState | null = null;\n const id = `subprocess(${command})`;\n\n async function ensureProbe(): Promise<ProbeState> {\n if (probeState !== null) return probeState;\n if (!command) {\n probeState = { available: false, detail: \"structuralProviderCommand is empty\" };\n return probeState;\n }\n // Rule 24 — file existence check at probe time. An operator pointing at\n // a missing/renamed binary gets a DISTINCT `provider_unavailable` code,\n // never a silent empty result.\n let statOk = false;\n let notExecutable = false;\n try {\n statOk = statSync(command).isFile();\n } catch {\n statOk = false;\n }\n // P2 hardening: a non-executable regular file would report available\n // here but fail later with EACCES/provider_error. On POSIX, enforce\n // executable access so `remnic doctor` surfaces the real state. Windows\n // has no reliable exec bit (Node X_OK is always true there), so the\n // check is POSIX-only.\n if (statOk && process.platform !== \"win32\") {\n try {\n accessSync(command, constants.X_OK);\n } catch {\n notExecutable = true;\n }\n }\n probeState = !statOk\n ? { available: false, detail: `binary not found: ${command}` }\n : notExecutable\n ? { available: false, detail: `binary not executable: ${command}` }\n : { available: true };\n return probeState;\n }\n\n return {\n id,\n async probe() {\n return ensureProbe();\n },\n async symbolsForDiff(\n diff: string,\n callOpts,\n ): Promise<SymbolsForDiffResult> {\n const probe = await ensureProbe();\n if (!probe.available) {\n return { ok: false, code: \"provider_unavailable\", detail: probe.detail };\n }\n // Rule 10 — argv array; the diff is carried as a JSON argument so the\n // binary never sees a shell and never re-interpolates paths.\n const payload = JSON.stringify({ diff });\n const argv = [symbolsSubcommand, payload, ...extraArgs];\n try {\n const { stdout } = await spawn(command, argv, {\n timeout: timeoutMs,\n signal: callOpts?.signal,\n });\n return parseSymbolJson(stdout);\n } catch (err) {\n return classifySpawnError(err);\n }\n },\n async architectureHints(\n root: string,\n callOpts,\n ): Promise<ArchitectureHintsResult> {\n const probe = await ensureProbe();\n if (!probe.available) {\n return { ok: false, code: \"provider_unavailable\", detail: probe.detail };\n }\n const argv = [\"architecture-hints\", root, ...extraArgs];\n try {\n const { stdout } = await spawn(command, argv, {\n timeout: timeoutMs,\n signal: callOpts?.signal,\n });\n return parseHintsJson(stdout);\n } catch (err) {\n return classifySpawnError(err);\n }\n },\n close() {\n probeState = null;\n },\n };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// JSON validation — rule 18 (object-not-null), rule 51 (shape), rule 34\n// ──────────────────────────────────────────────────────────────────────────\n\nfunction parseSymbolJson(stdout: string): SymbolsForDiffResult {\n let value: unknown;\n try {\n value = JSON.parse(stdout);\n } catch {\n return {\n ok: false,\n code: \"provider_malformed\",\n detail: \"stdout was not valid JSON\",\n };\n }\n if (value === null || typeof value !== \"object\" || Array.isArray(value)) {\n return {\n ok: false,\n code: \"provider_malformed\",\n detail: \"provider output was not a JSON object\",\n };\n }\n const obj = value as Record<string, unknown>;\n const symbolsRaw = obj.symbols;\n if (!Array.isArray(symbolsRaw)) {\n return {\n ok: false,\n code: \"provider_malformed\",\n detail: \"provider output .symbols is not an array\",\n };\n }\n const symbols: StructuralSymbol[] = [];\n for (const entry of symbolsRaw) {\n const item = readStructuralSymbol(entry);\n if (item !== null) symbols.push(item);\n }\n return { ok: true, symbols };\n}\n\nfunction parseHintsJson(stdout: string): ArchitectureHintsResult {\n let value: unknown;\n try {\n value = JSON.parse(stdout);\n } catch {\n return {\n ok: false,\n code: \"provider_malformed\",\n detail: \"stdout was not valid JSON\",\n };\n }\n if (!Array.isArray(value)) {\n return {\n ok: false,\n code: \"provider_malformed\",\n detail: \"provider hints output was not a JSON array\",\n };\n }\n const hints = value.filter((h): h is string => typeof h === \"string\" && h.length > 0);\n return { ok: true, hints };\n}\n\nfunction readStructuralSymbol(entry: unknown): StructuralSymbol | null {\n if (entry === null || typeof entry !== \"object\" || Array.isArray(entry)) {\n return null;\n }\n const rec = entry as Record<string, unknown>;\n const symbol = typeof rec.symbol === \"string\" ? rec.symbol.trim() : \"\";\n if (!symbol) return null;\n const path = typeof rec.path === \"string\" && rec.path.length > 0 ? rec.path : undefined;\n const kind = typeof rec.kind === \"string\" && rec.kind.length > 0 ? rec.kind : undefined;\n const item: StructuralSymbol =\n path !== undefined && kind !== undefined\n ? { symbol, path, kind }\n : path !== undefined\n ? { symbol, path }\n : kind !== undefined\n ? { symbol, kind }\n : { symbol };\n return item;\n}\n\ntype StructuralContextError = {\n readonly ok: false;\n readonly code: StructuralContextErrorCode;\n readonly detail?: string;\n};\n\nfunction classifySpawnError(err: unknown): StructuralContextError {\n const message = err instanceof Error ? err.message : String(err);\n // Node sets the child's `.killed` flag and surfaces an ETIMEDOUT-style\n // message when `timeout` elapses; the regex keeps this robust to Node\n // version wording differences.\n if (/timeout|timed out|ETIMEDOUT/i.test(message)) {\n return { ok: false, code: \"provider_timeout\", detail: message };\n }\n return { ok: false, code: \"provider_error\", detail: message };\n}\n\nfunction defaultSpawn(\n command: string,\n argv: readonly string[],\n options: { timeout: number; signal?: AbortSignal },\n): Promise<{ stdout: string; stderr: string }> {\n return execFileAsync(command, [...argv], {\n timeout: options.timeout,\n signal: options.signal,\n maxBuffer: 4 * 1024 * 1024,\n });\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Doctor probe — construct a one-shot provider from config and probe it\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Augment the pure {@link describeStructuralProviderStatus} with a LIVE probe\n * so `remnic doctor` can render \"configured / probed / last error code\".\n *\n * - `\"none\"` → inactive (no probe).\n * - `\"subprocess\"` → builds a throwaway provider from\n * `structuralProviderCommand`, probes it, disposes it.\n * - `\"native\"` → asks `isCodingGraphInstalled()` whether the optional\n * @remnic/coding-graph peer is present (the adapter that\n * turns the engine into a provider lands in #1551).\n *\n * Never throws — a probe failure populates `probed.available = false`.\n */\nexport async function probeStructuralProviderForDoctor(\n config: PluginConfig,\n): Promise<StructuralProviderStatus> {\n const status = describeStructuralProviderStatus(config);\n if (!status.active) return status;\n\n const ck = config.codingKnowledge;\n if (ck.structuralProvider === \"subprocess\") {\n if (!ck.structuralProviderCommand) {\n return {\n ...status,\n probed: { available: false, detail: \"structuralProviderCommand is empty\" },\n };\n }\n const provider = createSubprocessStructuralProvider({\n command: ck.structuralProviderCommand,\n });\n try {\n const probed = await safeProbe(provider);\n return { ...status, probed };\n } finally {\n void provider.close?.();\n }\n }\n\n if (ck.structuralProvider === \"native\") {\n const installed = await isCodingGraphInstalled().catch(() => false);\n return {\n ...status,\n probed: {\n available: installed,\n detail: installed ? undefined : \"@remnic/coding-graph not installed\",\n },\n };\n }\n\n return status;\n}\n\nasync function safeProbe(\n provider: StructuralContextProvider,\n): Promise<{ available: boolean; detail?: string }> {\n try {\n return await provider.probe();\n } catch (err) {\n return { available: false, detail: err instanceof Error ? err.message : String(err) };\n }\n}\n","/**\n * Binary file lifecycle management types.\n *\n * Defines the configuration, manifest, and record structures for the\n * three-stage binary lifecycle pipeline: mirror, redirect, clean.\n */\n\nexport interface BinaryLifecycleConfig {\n /** Master toggle. Default: false. */\n enabled: boolean;\n /** Days after mirror before local copy is eligible for cleanup. Default: 7. */\n gracePeriodDays: number;\n /** Files larger than this are skipped during scan. Default: 50 MB. */\n maxBinarySizeBytes: number;\n /** Glob patterns for binary file types to manage. */\n scanPatterns: string[];\n /** Backend configuration for binary storage. */\n backend: BinaryStorageBackendConfig;\n}\n\nexport interface BinaryStorageBackendConfig {\n /** Backend type. \"filesystem\" copies to a local directory. \"none\" is a no-op (dry-run/testing). */\n type: \"filesystem\" | \"s3\" | \"none\";\n /** Destination directory for the filesystem backend. */\n basePath?: string;\n /** S3 bucket name (future). */\n s3Bucket?: string;\n /** S3 region (future). */\n s3Region?: string;\n /** S3 key prefix (future). */\n s3Prefix?: string;\n}\n\nexport type BinaryAssetStatus =\n | \"pending\"\n | \"mirrored\"\n | \"redirected\"\n | \"cleaned\"\n | \"error\";\n\nexport interface BinaryAssetRecord {\n /** Relative path from memoryDir to the original file. */\n originalPath: string;\n /** Path (or URL) in the backend storage. */\n mirroredPath: string;\n /** Optional user-resolvable target to write into markdown links. */\n redirectPath?: string;\n /** SHA-256 hex digest of file content. */\n contentHash: string;\n /** File size in bytes. */\n sizeBytes: number;\n /** MIME type (e.g. \"image/png\"). */\n mimeType: string;\n /** ISO 8601 timestamp when the file was mirrored. */\n mirroredAt: string;\n /** ISO 8601 timestamp when markdown references were rewritten. */\n redirectedAt?: string;\n /** ISO 8601 timestamp when the local copy was deleted. */\n cleanedAt?: string;\n /** Current lifecycle status. */\n status: BinaryAssetStatus;\n}\n\nexport interface BinaryLifecycleManifest {\n version: 1;\n assets: BinaryAssetRecord[];\n lastScanAt?: string;\n}\n\nexport interface PipelineResult {\n scanned: number;\n mirrored: number;\n redirected: number;\n cleaned: number;\n errors: string[];\n dryRun: boolean;\n}\n\nexport const DEFAULT_SCAN_PATTERNS = [\n \"*.png\",\n \"*.jpg\",\n \"*.jpeg\",\n \"*.gif\",\n \"*.pdf\",\n \"*.mp3\",\n \"*.mp4\",\n \"*.wav\",\n];\n\nexport const DEFAULT_MAX_BINARY_SIZE_BYTES = 50 * 1024 * 1024; // 50 MB\nexport const DEFAULT_GRACE_PERIOD_DAYS = 7;\n","/**\n * Binary storage backend interface and implementations.\n *\n * Backends handle the actual persistence of binary files to an external\n * location. The pipeline calls upload/exists/delete through this interface\n * so swapping storage providers requires no pipeline changes.\n */\n\nimport type { Stats } from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { BinaryStorageBackendConfig } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Interface\n// ---------------------------------------------------------------------------\n\nexport interface BinaryStorageBackend {\n /** Discriminator for the backend type. */\n readonly type: string;\n /**\n * Upload a local file to the backend.\n * @returns The backend path or URL where the file was stored.\n */\n upload(localPath: string, remotePath: string): Promise<string>;\n /** Check whether a remote path already exists in the backend. */\n exists(remotePath: string): Promise<boolean>;\n /** Delete a file from the backend. */\n delete(remotePath: string): Promise<void>;\n /** Return the user-resolvable markdown target for a stored backend path. */\n getRedirectTarget?(remotePath: string): string;\n}\n\n// ---------------------------------------------------------------------------\n// Filesystem backend\n// ---------------------------------------------------------------------------\n\nexport class FilesystemBackend implements BinaryStorageBackend {\n readonly type = \"filesystem\";\n private readonly basePath: string;\n\n constructor(basePath: string) {\n if (!basePath || basePath.trim().length === 0) {\n throw new Error(\"FilesystemBackend requires a non-empty basePath\");\n }\n this.basePath = path.resolve(basePath);\n }\n\n private resolveRemotePath(remotePath: string): string {\n const resolved = path.isAbsolute(remotePath)\n ? path.resolve(remotePath)\n : path.resolve(this.basePath, remotePath);\n const relative = path.relative(this.basePath, resolved);\n if (relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);\n }\n return resolved;\n }\n\n private isInsideBase(candidate: string, realBase: string): boolean {\n const relative = path.relative(realBase, candidate);\n return relative === \"\" || (relative !== \"..\" && !relative.startsWith(`..${path.sep}`) && !path.isAbsolute(relative));\n }\n\n private async realBasePathIfExists(): Promise<string | null> {\n try {\n const stat = await fsp.lstat(this.basePath);\n if (stat.isSymbolicLink()) {\n throw new Error(`FilesystemBackend basePath must not be a symlink: ${this.basePath}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`FilesystemBackend basePath must be a directory: ${this.basePath}`);\n }\n return await fsp.realpath(this.basePath);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw err;\n }\n }\n\n private async ensureBaseDirectory(): Promise<string> {\n await fsp.mkdir(this.basePath, { recursive: true });\n const realBase = await this.realBasePathIfExists();\n if (realBase === null) {\n throw new Error(`FilesystemBackend failed to create basePath: ${this.basePath}`);\n }\n return realBase;\n }\n\n private async ensureSafeParentDirectory(dest: string): Promise<string> {\n const realBase = await this.ensureBaseDirectory();\n const destDir = path.dirname(dest);\n const relativeDir = path.relative(this.basePath, destDir);\n const segments = relativeDir === \"\" ? [] : relativeDir.split(path.sep);\n let current = this.basePath;\n\n for (const segment of segments) {\n if (segment === \".\" || segment === \"\") continue;\n current = path.join(current, segment);\n try {\n const stat = await fsp.lstat(current);\n if (stat.isSymbolicLink()) {\n throw new Error(`FilesystemBackend remotePath traverses symlink: ${current}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`FilesystemBackend remotePath parent is not a directory: ${current}`);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n await fsp.mkdir(current);\n }\n }\n\n const realParent = await fsp.realpath(destDir);\n if (!this.isInsideBase(realParent, realBase)) {\n throw new Error(`FilesystemBackend remotePath parent escapes basePath: ${dest}`);\n }\n return realBase;\n }\n\n private async resolveExistingRemotePath(remotePath: string): Promise<string | null> {\n const dest = this.resolveRemotePath(remotePath);\n const realBase = await this.realBasePathIfExists();\n if (realBase === null) {\n return null;\n }\n\n const destDir = path.dirname(dest);\n const relativeDir = path.relative(this.basePath, destDir);\n const segments = relativeDir === \"\" ? [] : relativeDir.split(path.sep);\n let current = this.basePath;\n for (const segment of segments) {\n if (segment === \".\" || segment === \"\") continue;\n current = path.join(current, segment);\n let stat: Stats;\n try {\n stat = await fsp.lstat(current);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw err;\n }\n if (stat.isSymbolicLink()) {\n throw new Error(`FilesystemBackend remotePath traverses symlink: ${current}`);\n }\n if (!stat.isDirectory()) {\n return null;\n }\n }\n\n const realParent = await fsp.realpath(destDir).catch((err: NodeJS.ErrnoException) => {\n if (err.code === \"ENOENT\") return null;\n throw err;\n });\n if (realParent === null) {\n return null;\n }\n if (!this.isInsideBase(realParent, realBase)) {\n throw new Error(`FilesystemBackend remotePath parent escapes basePath: ${JSON.stringify(remotePath)}`);\n }\n\n try {\n const stat = await fsp.lstat(dest);\n if (stat.isSymbolicLink()) {\n throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);\n }\n if (!stat.isFile()) {\n return null;\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return null;\n }\n throw err;\n }\n\n const realDest = await fsp.realpath(dest);\n if (!this.isInsideBase(realDest, realBase)) {\n throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);\n }\n return dest;\n }\n\n async upload(localPath: string, remotePath: string): Promise<string> {\n if (path.isAbsolute(remotePath)) {\n throw new Error(`FilesystemBackend upload remotePath must be relative: ${JSON.stringify(remotePath)}`);\n }\n const dest = this.resolveRemotePath(remotePath);\n const realBase = await this.ensureSafeParentDirectory(dest);\n try {\n const stat = await fsp.lstat(dest);\n if (stat.isSymbolicLink()) {\n throw new Error(`FilesystemBackend remotePath points to symlink: ${dest}`);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw err;\n }\n }\n await fsp.copyFile(localPath, dest);\n const realDest = await fsp.realpath(dest);\n if (!this.isInsideBase(realDest, realBase)) {\n throw new Error(`FilesystemBackend remotePath escapes basePath: ${JSON.stringify(remotePath)}`);\n }\n return remotePath;\n }\n\n async exists(remotePath: string): Promise<boolean> {\n const dest = await this.resolveExistingRemotePath(remotePath);\n return dest !== null;\n }\n\n async delete(remotePath: string): Promise<void> {\n const dest = await this.resolveExistingRemotePath(remotePath);\n if (dest === null) {\n return;\n }\n try {\n await fsp.unlink(dest);\n } catch (err: unknown) {\n // Ignore ENOENT (already deleted); rethrow everything else.\n if ((err as NodeJS.ErrnoException).code !== \"ENOENT\") throw err;\n }\n }\n\n getRedirectTarget(remotePath: string): string {\n return this.resolveRemotePath(remotePath);\n }\n}\n\n// ---------------------------------------------------------------------------\n// None backend (no-op, for dry-run / testing)\n// ---------------------------------------------------------------------------\n\nexport class NoneBackend implements BinaryStorageBackend {\n readonly type = \"none\";\n\n async upload(_localPath: string, remotePath: string): Promise<string> {\n return remotePath;\n }\n\n async exists(_remotePath: string): Promise<boolean> {\n return false;\n }\n\n async delete(_remotePath: string): Promise<void> {\n // intentional no-op\n }\n}\n\n// ---------------------------------------------------------------------------\n// Factory\n// ---------------------------------------------------------------------------\n\nexport function createBackend(cfg: BinaryStorageBackendConfig): BinaryStorageBackend {\n switch (cfg.type) {\n case \"filesystem\": {\n if (!cfg.basePath) {\n throw new Error(\n \"BinaryStorageBackendConfig.basePath is required when type is \\\"filesystem\\\"\",\n );\n }\n return new FilesystemBackend(cfg.basePath);\n }\n case \"s3\":\n throw new Error(\"S3 binary storage backend is not yet implemented\");\n case \"none\":\n return new NoneBackend();\n default:\n throw new Error(`Unknown binary storage backend type: ${String((cfg as { type: string }).type)}`);\n }\n}\n","/**\n * Binary file scanner.\n *\n * Recursively walks the memory directory, matches files against configured\n * glob patterns, skips files already tracked in the manifest, and respects\n * the max-size limit.\n */\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type { BinaryLifecycleConfig, BinaryLifecycleManifest } from \"./types.js\";\n\n/**\n * Test whether a filename matches any of the provided glob patterns.\n * Supports simple `*.ext` patterns (the default scan patterns).\n * For more complex globs a proper library should be used; this covers\n * the 95% case without adding a dependency.\n */\nexport function matchesPatterns(filename: string, patterns: string[]): boolean {\n const lower = filename.toLowerCase();\n for (const pattern of patterns) {\n // Simple *.ext matching\n if (pattern.startsWith(\"*.\")) {\n const ext = pattern.slice(1).toLowerCase(); // e.g. \".png\"\n if (lower.endsWith(ext)) return true;\n } else if (lower === pattern.toLowerCase()) {\n return true;\n }\n }\n return false;\n}\n\n/**\n * Scan memoryDir recursively for binary files matching the configured patterns.\n * Returns relative paths (relative to memoryDir) for files not yet tracked.\n */\nexport async function scanForBinaries(\n memoryDir: string,\n config: BinaryLifecycleConfig,\n manifest: BinaryLifecycleManifest,\n): Promise<string[]> {\n const tracked = new Map(manifest.assets.map((a) => [a.originalPath, a]));\n const results: string[] = [];\n\n async function walk(dir: string): Promise<void> {\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = await fsp.readdir(dir, { withFileTypes: true });\n } catch {\n return; // skip unreadable directories\n }\n\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n // Normalize to POSIX separators so redirect matching works on Windows\n // (markdown links always use forward slashes).\n const relativePath = path.relative(memoryDir, fullPath).split(path.sep).join(\"/\");\n\n if (entry.isDirectory()) {\n // Skip the manifest directory itself and hidden dirs starting with .\n if (entry.name === \".binary-lifecycle\") continue;\n await walk(fullPath);\n continue;\n }\n\n if (!entry.isFile()) continue;\n\n // Check pattern match\n if (!matchesPatterns(entry.name, config.scanPatterns)) continue;\n\n // Check file size\n try {\n const stat = await fsp.stat(fullPath);\n if (stat.size > config.maxBinarySizeBytes) continue;\n if (stat.size === 0) continue; // skip empty files\n const existing = tracked.get(relativePath);\n if (existing) {\n if (existing.sizeBytes !== stat.size) {\n results.push(relativePath);\n continue;\n }\n const contentHash = await hashFile(fullPath);\n if (existing.contentHash !== contentHash) {\n results.push(relativePath);\n }\n continue;\n }\n } catch {\n continue; // stat failure, skip\n }\n\n results.push(relativePath);\n }\n }\n\n await walk(memoryDir);\n return results;\n}\n\nasync function hashFile(filePath: string): Promise<string> {\n const content = await fsp.readFile(filePath);\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n","/**\n * Binary lifecycle manifest — read/write operations.\n *\n * The manifest lives at `${memoryDir}/.binary-lifecycle/manifest.json`.\n * Writes use the atomic temp-then-rename pattern (CLAUDE.md #54).\n */\n\nimport fs from \"node:fs\";\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type { BinaryLifecycleManifest } from \"./types.js\";\n\nconst MANIFEST_DIR = \".binary-lifecycle\";\nconst MANIFEST_FILE = \"manifest.json\";\n\nexport function manifestDir(memoryDir: string): string {\n return path.join(memoryDir, MANIFEST_DIR);\n}\n\nexport function manifestPath(memoryDir: string): string {\n return path.join(memoryDir, MANIFEST_DIR, MANIFEST_FILE);\n}\n\n/**\n * Read the manifest from disk. Returns a fresh empty manifest if the file\n * does not exist. Existing invalid manifests fail closed so the pipeline does\n * not overwrite state needed for safe cleanup.\n */\nexport async function readManifest(memoryDir: string): Promise<BinaryLifecycleManifest> {\n const filePath = manifestPath(memoryDir);\n let raw: string;\n try {\n raw = await fsp.readFile(filePath, \"utf-8\");\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return emptyManifest();\n }\n throw new Error(`Failed to read binary lifecycle manifest at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n let parsed: unknown;\n try {\n parsed = JSON.parse(raw);\n } catch (err) {\n throw new Error(`Invalid binary lifecycle manifest JSON at ${filePath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n\n // CLAUDE.md #18: validate the parsed result is a non-null object.\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(`Invalid binary lifecycle manifest shape at ${filePath}: expected object`);\n }\n const obj = parsed as Record<string, unknown>;\n if (obj.version !== 1 || !Array.isArray(obj.assets)) {\n throw new Error(`Invalid binary lifecycle manifest shape at ${filePath}: expected version 1 with assets array`);\n }\n return parsed as BinaryLifecycleManifest;\n}\n\n/**\n * Write the manifest atomically: write to a temp file, then rename.\n * CLAUDE.md #54: never delete before write. Write temp first, rename atomically.\n */\nexport async function writeManifest(\n memoryDir: string,\n manifest: BinaryLifecycleManifest,\n): Promise<void> {\n const dir = manifestDir(memoryDir);\n await fsp.mkdir(dir, { recursive: true });\n const dest = manifestPath(memoryDir);\n const tmpSuffix = crypto.randomBytes(8).toString(\"hex\");\n const tmpPath = `${dest}.${tmpSuffix}.tmp`;\n // Sort keys for deterministic output (CLAUDE.md #38).\n const content = JSON.stringify(manifest, null, 2) + \"\\n\";\n await fsp.writeFile(tmpPath, content, \"utf-8\");\n try {\n await fsp.rename(tmpPath, dest);\n } catch (renameErr) {\n // Clean up temp on rename failure (cross-device edge case).\n try {\n await fsp.unlink(tmpPath);\n } catch {\n // ignore cleanup failure\n }\n throw renameErr;\n }\n}\n\nexport function emptyManifest(): BinaryLifecycleManifest {\n return { version: 1, assets: [] };\n}\n","/**\n * Binary lifecycle pipeline — mirror, redirect, clean.\n *\n * Three-stage pipeline:\n * 1. Mirror: upload binary to backend, record in manifest\n * 2. Redirect: scan markdown for inline refs, replace with redirect path\n * 3. Clean: after grace period, delete local copy\n */\n\nimport fsp from \"node:fs/promises\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport type {\n BinaryAssetRecord,\n BinaryLifecycleConfig,\n PipelineResult,\n} from \"./types.js\";\nimport type { BinaryStorageBackend } from \"./backend.js\";\nimport { readManifest, writeManifest } from \"./manifest.js\";\nimport { scanForBinaries } from \"./scanner.js\";\n\n/** Minimal logger interface so we don't depend on the full logger module. */\ninterface PipelineLogger {\n info(msg: string): void;\n warn(msg: string): void;\n error(msg: string): void;\n}\n\ntype ReadMarkdownFile = (filePath: string) => Promise<string>;\ntype WriteMarkdownFile = (filePath: string, content: string) => Promise<void>;\n\ninterface PipelineOptions {\n dryRun?: boolean;\n /** Force-clean all files past grace period, ignoring redirect status. */\n forceClean?: boolean;\n /** Test hook for deterministic markdown read failures. */\n readMarkdownFile?: ReadMarkdownFile;\n /** Test hook for deterministic markdown write failures. */\n writeMarkdownFile?: WriteMarkdownFile;\n}\n\n// ---------------------------------------------------------------------------\n// Helpers\n// ---------------------------------------------------------------------------\n\nasync function hashFile(filePath: string): Promise<string> {\n const content = await fsp.readFile(filePath);\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\");\n}\n\nfunction guessMimeType(ext: string): string {\n const map: Record<string, string> = {\n \".png\": \"image/png\",\n \".jpg\": \"image/jpeg\",\n \".jpeg\": \"image/jpeg\",\n \".gif\": \"image/gif\",\n \".pdf\": \"application/pdf\",\n \".mp3\": \"audio/mpeg\",\n \".mp4\": \"video/mp4\",\n \".wav\": \"audio/wav\",\n };\n return map[ext.toLowerCase()] ?? \"application/octet-stream\";\n}\n\n/**\n * Escape special regex characters in a string.\n * CLAUDE.md #46: always escapeRegex on user-derived parts.\n */\nfunction escapeRegex(s: string): string {\n return s.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\n\nfunction resolveManifestAssetPath(memoryDir: string, originalPath: string): string | null {\n if (\n originalPath.length === 0 ||\n originalPath.includes(\"\\0\") ||\n originalPath.includes(\"\\\\\") ||\n path.isAbsolute(originalPath) ||\n path.win32.isAbsolute(originalPath)\n ) {\n return null;\n }\n\n const memoryRoot = path.resolve(memoryDir);\n const fullPath = path.resolve(memoryRoot, originalPath);\n const relative = path.relative(memoryRoot, fullPath);\n if (relative === \"\" || relative === \"..\" || relative.startsWith(`..${path.sep}`) || path.isAbsolute(relative)) {\n return null;\n }\n\n return fullPath;\n}\n\nfunction validateBinaryLifecycleConfig(config: BinaryLifecycleConfig): void {\n if (\n typeof config.gracePeriodDays !== \"number\" ||\n !Number.isFinite(config.gracePeriodDays) ||\n !Number.isInteger(config.gracePeriodDays) ||\n config.gracePeriodDays < 0\n ) {\n throw new Error(\"binary lifecycle gracePeriodDays must be a finite non-negative integer\");\n }\n}\n\nfunction remotePathForAsset(backend: BinaryStorageBackend, relPath: string): string {\n const normalized = relPath.split(path.sep).join(\"/\");\n if (backend.type === \"filesystem\") {\n return `.binary-lifecycle/mirrors/${normalized}`;\n }\n return normalized;\n}\n\nfunction markdownTargetForAsset(asset: BinaryAssetRecord): string {\n return asset.redirectPath ?? asset.mirroredPath;\n}\n\n// ---------------------------------------------------------------------------\n// Pipeline stages\n// ---------------------------------------------------------------------------\n\nasync function stageMirror(\n memoryDir: string,\n newPaths: string[],\n backend: BinaryStorageBackend,\n assets: BinaryAssetRecord[],\n log: PipelineLogger,\n dryRun: boolean,\n): Promise<{ mirrored: number; errors: string[] }> {\n let mirrored = 0;\n const errors: string[] = [];\n\n for (const relPath of newPaths) {\n const fullPath = path.join(memoryDir, relPath);\n try {\n const stat = await fsp.stat(fullPath);\n const contentHash = await hashFile(fullPath);\n const ext = path.extname(relPath);\n const mimeType = guessMimeType(ext);\n const remotePath = remotePathForAsset(backend, relPath);\n\n let backendLocation = remotePath;\n if (!dryRun) {\n backendLocation = await backend.upload(fullPath, remotePath);\n }\n const redirectPath = backend.getRedirectTarget?.(backendLocation);\n\n const record: BinaryAssetRecord = {\n originalPath: relPath,\n mirroredPath: backendLocation,\n ...(redirectPath ? { redirectPath } : {}),\n contentHash,\n sizeBytes: stat.size,\n mimeType,\n mirroredAt: new Date().toISOString(),\n status: \"mirrored\",\n };\n\n if (!dryRun) {\n const existingIndex = assets.findIndex((asset) => asset.originalPath === relPath);\n if (existingIndex >= 0) {\n assets.splice(existingIndex, 1);\n }\n assets.push(record);\n }\n mirrored++;\n log.info(`[binary-lifecycle] mirrored: ${relPath} (${stat.size} bytes)${dryRun ? \" [dry-run]\" : \"\"}`);\n } catch (err) {\n const msg = `mirror failed for ${relPath}: ${err instanceof Error ? err.message : String(err)}`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n }\n\n return { mirrored, errors };\n}\n\nasync function stageRedirect(\n memoryDir: string,\n assets: BinaryAssetRecord[],\n log: PipelineLogger,\n dryRun: boolean,\n readMarkdownFile: ReadMarkdownFile,\n writeMarkdownFile: WriteMarkdownFile,\n): Promise<{ redirected: number; errors: string[] }> {\n let redirected = 0;\n const errors: string[] = [];\n\n // Redirect mirrored assets and retry prior redirect errors. Clean-stage errors\n // remain safe because the redirect path validation below will keep rejecting\n // invalid manifest records.\n const candidates = assets.filter((a) => a.status === \"mirrored\" || a.status === \"error\");\n if (candidates.length === 0) return { redirected, errors };\n\n // Find all markdown files in memoryDir (recursive).\n const mdFiles = await findMarkdownFiles(memoryDir);\n\n for (const asset of candidates) {\n const assetAbsolute = resolveManifestAssetPath(memoryDir, asset.originalPath);\n if (assetAbsolute === null) {\n const msg = `redirect blocked for ${asset.originalPath}: manifest path is outside memoryDir`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n if (!dryRun) {\n asset.status = \"error\";\n }\n continue;\n }\n\n const updates: Array<{ mdPath: string; content: string }> = [];\n let scanFailCount = 0;\n for (const mdPath of mdFiles) {\n try {\n const content = await readMarkdownFile(mdPath);\n\n const pattern = markdownReferencePattern(asset, assetAbsolute, mdPath);\n\n if (!pattern.test(content)) continue;\n\n // Reset lastIndex after test().\n pattern.lastIndex = 0;\n const updated = content.replace(pattern, (_match, open, _target, close) => {\n return `${open as string}${markdownTargetForAsset(asset)}${close as string}`;\n });\n updates.push({ mdPath, content: updated });\n } catch (err) {\n scanFailCount++;\n const msg = `redirect scan failed for ${mdPath}: ${err instanceof Error ? err.message : String(err)}`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n }\n\n if (scanFailCount > 0) {\n if (!dryRun) {\n asset.status = \"error\";\n }\n log.warn(\n `[binary-lifecycle] redirect blocked for ${asset.originalPath}: ` +\n `${scanFailCount} markdown scan failure(s)` +\n `${dryRun ? \"\" : \" — status set to error\"}`,\n );\n continue;\n }\n\n if (updates.length === 0) {\n if (asset.status === \"error\") {\n const verifyResult = await countRemainingLocalReferences(\n memoryDir,\n asset,\n assetAbsolute,\n mdFiles,\n readMarkdownFile,\n );\n if (verifyResult.errors.length > 0 || verifyResult.remaining > 0) {\n if (!dryRun) {\n asset.status = \"error\";\n }\n for (const msg of verifyResult.errors) {\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n if (verifyResult.remaining > 0) {\n const msg = `redirect verification failed for ${asset.originalPath}: ${verifyResult.remaining} local reference(s) remain`;\n log.warn(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n continue;\n }\n\n if (asset.redirectedAt === undefined) {\n if (!dryRun) {\n asset.status = \"mirrored\";\n }\n log.info(`[binary-lifecycle] preserved mirrored asset without redirected marker: ${asset.originalPath}${dryRun ? \" [dry-run]\" : \"\"}`);\n continue;\n }\n\n if (!Number.isFinite(new Date(asset.mirroredAt).getTime())) {\n const msg = `redirect blocked for ${asset.originalPath}: manifest mirroredAt is invalid`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n if (!dryRun) {\n asset.status = \"error\";\n }\n continue;\n }\n\n if (!dryRun) {\n asset.status = \"redirected\";\n asset.redirectedAt = new Date().toISOString();\n }\n redirected++;\n log.info(`[binary-lifecycle] redirected: ${asset.originalPath}${dryRun ? \" [dry-run]\" : \"\"}`);\n }\n continue;\n }\n\n if (dryRun) {\n redirected++;\n log.info(`[binary-lifecycle] redirected: ${asset.originalPath} [dry-run]`);\n continue;\n }\n\n let writeFailCount = 0;\n for (const update of updates) {\n try {\n await writeMarkdownFile(update.mdPath, update.content);\n } catch (err) {\n writeFailCount++;\n const msg = `redirect write failed for ${update.mdPath}: ${err instanceof Error ? err.message : String(err)}`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n }\n\n if (writeFailCount > 0) {\n if (!dryRun) {\n asset.status = \"error\";\n }\n log.warn(\n `[binary-lifecycle] redirect write failure for ${asset.originalPath}: ` +\n `${writeFailCount} write failure(s) — status set to error`,\n );\n continue;\n }\n\n const redirectedAt = new Date().toISOString();\n asset.redirectedAt = redirectedAt;\n\n const verifyResult = await countRemainingLocalReferences(\n memoryDir,\n asset,\n assetAbsolute,\n mdFiles,\n readMarkdownFile,\n );\n if (verifyResult.errors.length > 0 || verifyResult.remaining > 0) {\n asset.status = \"error\";\n for (const msg of verifyResult.errors) {\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n if (verifyResult.remaining > 0) {\n const msg = `redirect verification failed for ${asset.originalPath}: ${verifyResult.remaining} local reference(s) remain`;\n log.warn(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n continue;\n }\n asset.status = \"redirected\";\n asset.redirectedAt = redirectedAt;\n redirected++;\n log.info(`[binary-lifecycle] redirected: ${asset.originalPath}`);\n }\n\n return { redirected, errors };\n}\n\nasync function countRemainingLocalReferences(\n memoryDir: string,\n asset: BinaryAssetRecord,\n assetAbsolute: string,\n mdFiles: string[],\n readMarkdownFile: ReadMarkdownFile,\n): Promise<{ remaining: number; errors: string[] }> {\n let remaining = 0;\n const errors: string[] = [];\n\n for (const mdPath of mdFiles) {\n try {\n const content = await readMarkdownFile(mdPath);\n const pattern = markdownReferencePattern(asset, assetAbsolute, mdPath);\n if (pattern.test(content)) {\n remaining++;\n }\n } catch (err) {\n errors.push(`redirect verification failed for ${mdPath}: ${err instanceof Error ? err.message : String(err)}`);\n }\n }\n\n return { remaining, errors };\n}\n\nfunction markdownReferencePattern(\n asset: BinaryAssetRecord,\n assetAbsolute: string,\n mdPath: string,\n): RegExp {\n const mdDir = path.dirname(mdPath);\n const candidates = new Set<string>();\n const addCandidate = (candidate: string): void => {\n const normalized = candidate.split(path.sep).join(\"/\");\n if (normalized.length === 0) return;\n candidates.add(normalized);\n const isParentTraversal = normalized === \"..\" || normalized.startsWith(\"../\");\n if (!normalized.startsWith(\"./\") && !normalized.startsWith(\"/\") && !isParentTraversal) {\n candidates.add(`./${normalized}`);\n }\n };\n\n // Markdown links may be file-relative to the note or memory-root-relative in\n // Remnic notes. Match both forms so verification cannot miss a live local ref.\n addCandidate(path.relative(mdDir, assetAbsolute));\n const originalPath = asset.originalPath.split(path.sep).join(\"/\");\n const originalAsFileRelative = path.resolve(mdDir, ...originalPath.split(\"/\"));\n if (path.resolve(originalAsFileRelative) === path.resolve(assetAbsolute)) {\n addCandidate(originalPath);\n }\n addCandidate(`/${originalPath}`);\n\n const alternatives = [...candidates]\n .sort((a, b) => b.length - a.length)\n .map(escapeRegex)\n .join(\"|\");\n\n return new RegExp(`(!?\\\\[[^\\\\]]*\\\\]\\\\()(${alternatives})(\\\\))`, \"g\");\n}\n\nasync function stageClean(\n memoryDir: string,\n assets: BinaryAssetRecord[],\n backend: BinaryStorageBackend,\n gracePeriodDays: number,\n log: PipelineLogger,\n dryRun: boolean,\n forceClean: boolean,\n): Promise<{ cleaned: number; errors: string[] }> {\n let cleaned = 0;\n const errors: string[] = [];\n const now = Date.now();\n const graceMs = gracePeriodDays * 24 * 60 * 60 * 1000;\n\n // Clean only assets that have been redirected (markdown refs already rewritten).\n // Mirrored-only assets must NOT be cleaned — their markdown refs still point\n // to the local file, so deletion would break links.\n const candidates = assets.filter(\n (a) => a.status === \"redirected\",\n );\n\n for (const asset of candidates) {\n const mirroredMs = new Date(asset.mirroredAt).getTime();\n if (!Number.isFinite(mirroredMs)) {\n const msg = `clean blocked for ${asset.originalPath}: manifest mirroredAt is invalid`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n if (!dryRun) {\n asset.status = \"error\";\n }\n continue;\n }\n const ageMs = now - mirroredMs;\n\n if (!forceClean && ageMs < graceMs) {\n // Not yet past grace period.\n continue;\n }\n\n const fullPath = resolveManifestAssetPath(memoryDir, asset.originalPath);\n if (fullPath === null) {\n const msg = `clean blocked for ${asset.originalPath}: manifest path is outside memoryDir`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n if (!dryRun) {\n asset.status = \"error\";\n }\n continue;\n }\n\n let remoteExists: boolean;\n try {\n remoteExists = await backend.exists(asset.mirroredPath);\n } catch (err) {\n const msg = `clean blocked for ${asset.originalPath}: failed to verify mirrored copy: ${err instanceof Error ? err.message : String(err)}`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n continue;\n }\n\n if (!remoteExists) {\n const msg = `clean blocked for ${asset.originalPath}: mirrored copy is missing`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n continue;\n }\n\n try {\n const currentHash = await hashFile(fullPath);\n if (currentHash !== asset.contentHash) {\n const msg = `clean blocked for ${asset.originalPath}: local content hash does not match manifest`;\n log.warn(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n continue;\n }\n if (!dryRun) {\n await fsp.unlink(fullPath);\n asset.status = \"cleaned\";\n asset.cleanedAt = new Date().toISOString();\n }\n cleaned++;\n log.info(`[binary-lifecycle] cleaned: ${asset.originalPath}${dryRun ? \" [dry-run]\" : \"\"}`);\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n // Already gone — mark as cleaned.\n if (!dryRun) {\n asset.status = \"cleaned\";\n asset.cleanedAt = new Date().toISOString();\n cleaned++;\n }\n } else {\n const msg = `clean failed for ${asset.originalPath}: ${err instanceof Error ? err.message : String(err)}`;\n log.error(`[binary-lifecycle] ${msg}`);\n errors.push(msg);\n }\n }\n }\n\n return { cleaned, errors };\n}\n\n// ---------------------------------------------------------------------------\n// Markdown file discovery\n// ---------------------------------------------------------------------------\n\nasync function findMarkdownFiles(dir: string): Promise<string[]> {\n const results: string[] = [];\n\n async function walk(current: string): Promise<void> {\n let entries: import(\"node:fs\").Dirent[];\n try {\n entries = await fsp.readdir(current, { withFileTypes: true });\n } catch {\n return;\n }\n for (const entry of entries) {\n const full = path.join(current, entry.name);\n if (entry.isDirectory()) {\n if (entry.name === \".binary-lifecycle\") continue;\n await walk(full);\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n results.push(full);\n }\n }\n }\n\n await walk(dir);\n return results;\n}\n\n// ---------------------------------------------------------------------------\n// Main pipeline entry point\n// ---------------------------------------------------------------------------\n\n/**\n * Run the binary lifecycle pipeline: scan, mirror, redirect, clean.\n */\nexport async function runBinaryLifecyclePipeline(\n memoryDir: string,\n config: BinaryLifecycleConfig,\n backend: BinaryStorageBackend,\n log: PipelineLogger,\n opts?: PipelineOptions,\n): Promise<PipelineResult> {\n validateBinaryLifecycleConfig(config);\n\n const dryRun = opts?.dryRun ?? false;\n const forceClean = opts?.forceClean ?? false;\n\n if (config.enabled === false) {\n return {\n scanned: 0,\n mirrored: 0,\n redirected: 0,\n cleaned: 0,\n errors: [],\n dryRun,\n };\n }\n\n const manifest = await readManifest(memoryDir);\n\n // Stage 0: Scan\n const newPaths = await scanForBinaries(memoryDir, config, manifest);\n const scanned = newPaths.length;\n\n // Stage 1: Mirror\n const mirrorResult = await stageMirror(\n memoryDir,\n newPaths,\n backend,\n manifest.assets,\n log,\n dryRun,\n );\n\n // Stage 2: Redirect\n const redirectResult = await stageRedirect(\n memoryDir,\n manifest.assets,\n log,\n dryRun,\n opts?.readMarkdownFile ?? ((filePath: string) => fsp.readFile(filePath, \"utf-8\")),\n opts?.writeMarkdownFile ?? ((filePath: string, content: string) => fsp.writeFile(filePath, content, \"utf-8\")),\n );\n\n // Stage 3: Clean\n const cleanResult = await stageClean(\n memoryDir,\n manifest.assets,\n backend,\n config.gracePeriodDays,\n log,\n dryRun,\n forceClean,\n );\n\n // Persist manifest (unless dry-run).\n manifest.lastScanAt = new Date().toISOString();\n if (!dryRun) {\n await writeManifest(memoryDir, manifest);\n }\n\n const allErrors = [\n ...mirrorResult.errors,\n ...redirectResult.errors,\n ...cleanResult.errors,\n ];\n\n return {\n scanned,\n mirrored: mirrorResult.mirrored,\n redirected: redirectResult.redirected,\n cleaned: cleanResult.cleaned,\n errors: allErrors,\n dryRun,\n };\n}\n","/**\n * @remnic/core — Workspace Tree Projection\n *\n * Generates a human-readable `.engram/context-tree/` from canonical memory.\n * Each node is a `.md` file with rich metadata, * (provenance, trust, confidence, source anchors).\n * Manual edits are preserved in fenced blocks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_KEYS } from \"../utils/category-dir.js\";\n\nconst VALID_PROJECTION_CATEGORIES = new Set(ALL_CATEGORY_KEYS);\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface TreeNode {\n /** Relative path from context-tree root, e.g. \"entities/claude.md\" */\n path: string;\n /** Category from canonical memory */\n category: string;\n /** Human-readable title */\n title: string;\n /** File content (rendered markdown) */\n content: string;\n /** Source memory IDs that contributed to this node */\n sourceAnchors: string[];\n /** Confidence (0-1) */\n confidence: number;\n /** Trust zone classification */\n confidenceTier: string;\n /** When this node was generated */\n generatedAt: string;\n /** Provenance chain */\n provenance: ProvenanceEntry[];\n}\n\nexport interface ProvenanceEntry {\n memoryId: string;\n source: string;\n extracted: string;\n}\n\nexport interface GenerateOptions {\n /** Memory root directory (e.g. ~/.openclaw/workspace/memory/local) */\n memoryDir: string;\n /** Output directory (e.g. .engram/context-tree) */\n outputDir: string;\n /** Categories to include (default: all) */\n categories?: string[];\n /** Whether to include entity graph */\n includeEntities?: boolean;\n /** Whether to include orphaned questions */\n includeQuestions?: boolean;\n /** Max nodes per category (default: unlimited) */\n maxPerCategory?: number;\n /** Whether to watch for changes and regenerate incrementally */\n watch?: boolean;\n}\n\nexport interface GenerateResult {\n nodesGenerated: number;\n nodesSkipped: number;\n categories: Record<string, number>;\n durationMs: number;\n outputDir: string;\n}\n\n// ── Generation ──────────────────────────────────────────────────────────────\n\n/**\n * Generate a context tree from canonical memory.\n *\n * Reads memory `.md` files from the source directory, * and projects them into a clean, * human-readable tree structure at `outputDir`.\n */\nexport async function generateContextTree(options: GenerateOptions): Promise<GenerateResult> {\n const startTime = Date.now();\n const {\n memoryDir,\n outputDir,\n categories: filterCategories,\n includeEntities = true,\n includeQuestions = true,\n maxPerCategory = Infinity,\n } = options;\n\n let nodesGenerated = 0;\n let nodesSkipped = 0;\n const categoryCounts: Record<string, number> = {};\n const resolvedMemoryDir = path.resolve(memoryDir);\n const resolvedOutputDir = path.resolve(outputDir);\n const requestedCategories = validateProjectionCategories(filterCategories);\n const realMemoryDir = assertSafeMemoryRoot(resolvedMemoryDir);\n\n // Ensure output directory exists\n assertNotSymlink(resolvedOutputDir, \"context tree outputDir\");\n fs.mkdirSync(resolvedOutputDir, { recursive: true });\n const realOutputDir = fs.realpathSync(resolvedOutputDir);\n\n // Process each category (exclude 'question' — handled by separate includeQuestions pass)\n const allCategories = (requestedCategories ?? ALL_CATEGORY_KEYS)\n .filter((c) => c !== \"question\");\n\n for (const category of allCategories) {\n const categoryDir = getCategoryDir(memoryDir, category);\n if (!fs.existsSync(categoryDir)) continue;\n assertSafeInputRoot(realMemoryDir, categoryDir, `${category} memory category`);\n\n categoryCounts[category] = 0;\n const files = walkR(categoryDir, realMemoryDir);\n let count = 0;\n\n for (const filePath of files) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, category, fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n // Write node to output\n const outputPath = resolveContainedOutputPath(realOutputDir, node.path);\n writeProjectedContent(realOutputDir, outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[category] = (categoryCounts[category] ?? 0) + 1;\n count++;\n }\n }\n\n // Process entities\n if (includeEntities) {\n const entitiesDir = path.join(memoryDir, \"entities\");\n if (fs.existsSync(entitiesDir)) {\n assertSafeInputRoot(realMemoryDir, entitiesDir, \"entities root\");\n categoryCounts[\"entity\"] = 0;\n const entityFiles = walkR(entitiesDir, realMemoryDir);\n let count = 0;\n\n for (const filePath of entityFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fileName = path.basename(filePath, \".md\");\n const node = projectEntityNode(fileName, content);\n\n const outputPath = resolveContainedOutputPath(realOutputDir, \"entities\", `${fileName}.md`);\n writeProjectedContent(realOutputDir, outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"entity\"] = (categoryCounts[\"entity\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Process questions\n const shouldIncludeQuestions =\n includeQuestions &&\n (requestedCategories === undefined || requestedCategories.includes(\"question\"));\n if (shouldIncludeQuestions) {\n const questionsDir = path.join(memoryDir, \"questions\");\n if (fs.existsSync(questionsDir)) {\n assertSafeInputRoot(realMemoryDir, questionsDir, \"questions root\");\n categoryCounts[\"question\"] = 0;\n const qFiles = walkR(questionsDir, realMemoryDir);\n let count = 0;\n\n for (const filePath of qFiles) {\n if (count >= maxPerCategory) {\n nodesSkipped++;\n continue;\n }\n\n const content = fs.readFileSync(filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) {\n nodesSkipped++;\n continue;\n }\n\n const node = projectNode(filePath, \"question\", fm, content);\n if (!node) {\n nodesSkipped++;\n continue;\n }\n\n const outputPath = resolveContainedOutputPath(realOutputDir, node.path);\n writeProjectedContent(realOutputDir, outputPath, node.content);\n\n nodesGenerated++;\n categoryCounts[\"question\"] = (categoryCounts[\"question\"] ?? 0) + 1;\n count++;\n }\n }\n }\n\n // Write index\n const index = generateIndex(categoryCounts, resolvedOutputDir);\n writeProjectedContent(realOutputDir, resolveContainedOutputPath(realOutputDir, \"INDEX.md\"), index);\n\n return {\n nodesGenerated,\n nodesSkipped,\n categories: categoryCounts,\n durationMs: Date.now() - startTime,\n outputDir,\n };\n}\n\n// ── Helpers ──────────────────────────────────────────────────────────────────\n\nfunction isPathInside(root: string, candidate: string): boolean {\n const relative = path.relative(root, candidate);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction assertNotSymlink(targetPath: string, label: string): void {\n try {\n if (fs.lstatSync(targetPath).isSymbolicLink()) {\n throw new Error(`${label} must not be a symlink: ${targetPath}`);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") return;\n throw err;\n }\n}\n\nfunction assertSafeMemoryRoot(targetPath: string): string {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink()) {\n throw new Error(`memoryDir must not be a symlink: ${targetPath}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`memoryDir must be a directory: ${targetPath}`);\n }\n return fs.realpathSync(targetPath);\n}\n\nfunction assertSafeInputRoot(realMemoryDir: string, targetPath: string, label: string): void {\n const stat = fs.lstatSync(targetPath);\n if (stat.isSymbolicLink()) {\n throw new Error(`${label} must not be a symlink: ${targetPath}`);\n }\n if (!stat.isDirectory()) {\n throw new Error(`${label} must be a directory: ${targetPath}`);\n }\n const realTarget = fs.realpathSync(targetPath);\n if (!isPathInside(realMemoryDir, realTarget)) {\n throw new Error(`${label} escapes memoryDir: ${targetPath}`);\n }\n}\n\nfunction assertSafeOutputTarget(realOutputDir: string, outputPath: string): void {\n let current = realOutputDir;\n const relative = path.relative(realOutputDir, outputPath);\n if (relative.startsWith(\"..\") || path.isAbsolute(relative)) {\n throw new Error(`context tree output path escapes outputDir: ${outputPath}`);\n }\n for (const segment of relative.split(path.sep).filter(Boolean)) {\n current = path.join(current, segment);\n try {\n const stat = fs.lstatSync(current);\n if (stat.isSymbolicLink()) {\n throw new Error(`context tree output path contains symlink: ${current}`);\n }\n } catch (err) {\n if ((err as NodeJS.ErrnoException).code === \"ENOENT\") {\n break;\n }\n throw err;\n }\n }\n}\n\nfunction validateProjectionCategories(categories: string[] | undefined): string[] | undefined {\n if (categories === undefined) {\n return undefined;\n }\n const validated: string[] = [];\n for (const category of categories) {\n if (typeof category !== \"string\" || !VALID_PROJECTION_CATEGORIES.has(category)) {\n throw new Error(`invalid context tree category: ${String(category)}`);\n }\n if (!validated.includes(category)) {\n validated.push(category);\n }\n }\n return validated;\n}\n\nfunction resolveContainedOutputPath(outputRoot: string, ...segments: string[]): string {\n const resolved = path.resolve(outputRoot, ...segments);\n const relative = path.relative(outputRoot, resolved);\n if (relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative))) {\n return resolved;\n }\n throw new Error(`context tree output path escapes outputDir: ${segments.join(\"/\")}`);\n}\n\nfunction writeProjectedContent(realOutputDir: string, outputPath: string, generatedContent: string): void {\n assertSafeOutputTarget(realOutputDir, outputPath);\n fs.mkdirSync(path.dirname(outputPath), { recursive: true });\n const realParent = fs.realpathSync(path.dirname(outputPath));\n if (!isPathInside(realOutputDir, realParent)) {\n throw new Error(`context tree output path escapes outputDir: ${outputPath}`);\n }\n const existingContent = fs.existsSync(outputPath)\n ? fs.readFileSync(outputPath, \"utf8\")\n : \"\";\n fs.writeFileSync(\n outputPath,\n preserveManualFencedBlocks(generatedContent, existingContent),\n );\n}\n\nfunction preserveManualFencedBlocks(\n generatedContent: string,\n existingContent: string,\n): string {\n const manualBlocks = extractManualFencedBlocks(existingContent)\n .filter((block) => !generatedContent.includes(block));\n if (manualBlocks.length === 0) {\n return generatedContent;\n }\n return `${generatedContent.trimEnd()}\\n\\n## Manual Edits\\n\\n${manualBlocks.join(\"\\n\\n\")}\\n`;\n}\n\nfunction extractManualFencedBlocks(content: string): string[] {\n const blocks: string[] = [];\n const seen = new Set<string>();\n const fencePattern = /(?:^|\\n)([`~]{3,})[^\\n]*\\bmanual\\b[^\\n]*\\n[\\s\\S]*?\\n\\1[ \\t]*(?=\\n|$)/gi;\n for (const match of content.matchAll(fencePattern)) {\n const block = match[0].trim();\n if (!seen.has(block)) {\n seen.add(block);\n blocks.push(block);\n }\n }\n return blocks;\n}\n\nfunction walkR(dir: string, realMemoryDir: string): string[] {\n const results: string[] = [];\n function walk(directory: string): void {\n for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {\n const fullPath = path.join(directory, entry.name);\n if (entry.isSymbolicLink()) {\n throw new Error(`context tree input path contains symlink: ${fullPath}`);\n }\n if (entry.isDirectory()) {\n const realDir = fs.realpathSync(fullPath);\n if (!isPathInside(realMemoryDir, realDir)) {\n throw new Error(`context tree input path escapes memoryDir: ${fullPath}`);\n }\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n const realFile = fs.realpathSync(fullPath);\n if (!isPathInside(realMemoryDir, realFile)) {\n throw new Error(`context tree input path escapes memoryDir: ${fullPath}`);\n }\n results.push(fullPath);\n }\n }\n }\n walk(dir);\n return results;\n}\n\ninterface Frontmatter {\n id: string;\n category: string;\n created: string;\n updated: string;\n confidence: number;\n confidenceTier: string;\n tags: string[];\n source: string;\n entityRef?: string;\n lifecycleState?: string;\n}\n\nfunction parseFrontmatter(content: string): Frontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fmText = match[1];\n const fm: Record<string, unknown> = {};\n for (const line of fmText.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n if (key === \"tags\") {\n try {\n fm[key] = JSON.parse(value) as string[];\n } catch {\n fm[key] = [] as string[];\n }\n } else if (key === \"confidence\") {\n const parsed = parseFloat(value);\n fm[key] = Number.isFinite(parsed) ? parsed : 0;\n } else {\n fm[key] = value;\n }\n }\n return fm as unknown as Frontmatter;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction projectNode(\n filePath: string,\n category: string,\n fm: Frontmatter,\n rawContent: string,\n): TreeNode | null {\n const body = extractBody(rawContent);\n const fileName = path.basename(filePath, \".md\");\n const dateDir = path.basename(path.dirname(filePath));\n\n // Build relative path: category/date/file or just category/file\n let relPath: string;\n if (/^\\d{4}-\\d{2}-\\d{2}$/.test(dateDir)) {\n relPath = path.join(category, dateDir, `${fileName}.md`);\n } else {\n relPath = path.join(category, `${fileName}.md`);\n }\n\n const generatedAt = new Date().toISOString();\n\n const md = `# ${fm.id}\n\n> **Category:** ${fm.category}\n> **Created:** ${fm.created}\n> **Updated:** ${fm.updated ?? fm.created}\n> **Confidence:** ${fm.confidence} (${fm.confidenceTier}${fm.lifecycleState ? `, ${fm.lifecycleState}` : \"\"})\n${fm.tags?.length ? `\\n> **Tags:** ${fm.tags.join(\", \")}` : \"\"}\n${fm.entityRef ? `\\n> **Entity:** ${fm.entityRef}` : \"\"}\n> **Source:** ${fm.source ?? \"unknown\"}\n> **Projected:** ${generatedAt}\n\n---\n\n${body}\n`;\n\n return {\n path: relPath,\n category,\n title: fm.id,\n content: md,\n sourceAnchors: [fm.id],\n confidence: fm.confidence ?? 0,\n confidenceTier: fm.confidenceTier ?? \"unknown\",\n generatedAt,\n provenance: [{\n memoryId: fm.id,\n source: fm.source ?? \"unknown\",\n extracted: fm.created,\n }],\n };\n}\n\nfunction projectEntityNode(fileName: string, content: string): TreeNode {\n const generatedAt = new Date().toISOString();\n\n const md = `> **Projected:** ${generatedAt}\n> **Source:** canonical\n\n---\n\n${content}\n`;\n\n return {\n path: path.join(\"entities\", `${fileName}.md`),\n category: \"entity\",\n title: fileName,\n content: md,\n sourceAnchors: [fileName],\n confidence: 1,\n confidenceTier: \"explicit\",\n generatedAt,\n provenance: [{\n memoryId: fileName,\n source: \"canonical\",\n extracted: generatedAt,\n }],\n };\n}\n\nfunction generateIndex(\n categoryCounts: Record<string, number>,\n outputDir: string,\n): string {\n const lines = [\n \"# Context Tree Index\",\n \"\",\n `Generated: ${new Date().toISOString()}`,\n \"\",\n \"## Summary\",\n \"\",\n `| Category | Count |`,\n `|----------|-------|`,\n ];\n\n let total = 0;\n for (const [cat, count] of Object.entries(categoryCounts).sort()) {\n lines.push(`| ${cat} | ${count} |`);\n total += count;\n }\n\n lines.push(\"\");\n lines.push(`**Total:** ${total} nodes`);\n lines.push(\"\");\n lines.push(\"## Structure\");\n lines.push(\"\");\n lines.push(\"```\");\n lines.push(\"context-tree/\");\n lines.push(\"├── entities/ # Entity knowledge graph\");\n lines.push(\"├── fact/ # Factual memories (date-partitioned)\");\n lines.push(\"├── correction/ # Correction memories\");\n lines.push(\"├── decision/ # Decisions\");\n lines.push(\"├── moment/ # Notable moments\");\n lines.push(\"├── preference/ # Preferences\");\n lines.push(\"├── principle/ # Principles\");\n lines.push(\"├── question/ # Open questions\");\n lines.push(\"└── INDEX.md # This file\");\n lines.push(\"```\");\n\n return lines.join(\"\\n\") + \"\\n\";\n}\n","/**\n * @remnic/core — Onboarding\n *\n * Detects project language, shape, and documentation to produce\n * an onboarding plan for memory ingestion.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface OnboardOptions {\n /** Directory to scan (defaults to cwd) */\n directory?: string;\n /** Max depth to walk (default: 6) */\n maxDepth?: number;\n /** Directories to skip */\n excludeDirs?: string[];\n}\n\nexport interface LanguageInfo {\n /** Language name (e.g. \"TypeScript\", \"Python\") */\n language: string;\n /** Confidence in detection (0-1) */\n confidence: number;\n /** Evidence (e.g. [\"package.json\", \"tsconfig.json\", \"*.ts files\"]) */\n evidence: string[];\n}\n\nexport interface DocFile {\n /** Absolute path */\n path: string;\n /** Relative path from project root */\n relativePath: string;\n /** Estimated type */\n kind: \"readme\" | \"changelog\" | \"contributing\" | \"license\" | \"config\" | \"docs\" | \"other\";\n /** File size in bytes */\n size: number;\n}\n\nexport type ProjectShape = \"app\" | \"library\" | \"monorepo\" | \"workspace\" | \"script\" | \"unknown\";\n\nexport interface OnboardResult {\n /** Project root */\n directory: string;\n /** Detected languages (sorted by confidence) */\n languages: LanguageInfo[];\n /** Detected project shape */\n shape: ProjectShape;\n /** Shape evidence */\n shapeEvidence: string[];\n /** Discovered documentation files */\n docs: DocFile[];\n /** Total files scanned */\n totalFiles: number;\n /** Duration in ms */\n durationMs: number;\n /** Suggested ingestion plan */\n plan: IngestionPlan;\n}\n\nexport interface IngestionPlan {\n /** Priority files to ingest first */\n priorityFiles: DocFile[];\n /** Estimated total files to ingest */\n estimatedFiles: number;\n /** Recommended categories */\n categories: string[];\n /** Suggested memory namespace */\n suggestedNamespace: string;\n}\n\n// ── Language detection rules ─────────────────────────────────────────────────\n\ninterface LanguageRule {\n language: string;\n extensions: string[];\n manifests: string[];\n configFiles: string[];\n}\n\nconst LANGUAGE_RULES: LanguageRule[] = [\n {\n language: \"TypeScript\",\n extensions: [\".ts\", \".tsx\"],\n manifests: [],\n configFiles: [\"tsconfig.json\", \"tsup.config.ts\"],\n },\n {\n language: \"JavaScript\",\n extensions: [\".js\", \".jsx\", \".mjs\", \".cjs\"],\n manifests: [],\n configFiles: [\".eslintrc\", \".prettierrc\"],\n },\n {\n language: \"Python\",\n extensions: [\".py\", \".pyi\"],\n manifests: [\"pyproject.toml\", \"setup.py\", \"setup.cfg\", \"requirements.txt\"],\n configFiles: [\"mypy.ini\", \".flake8\", \"tox.ini\"],\n },\n {\n language: \"Go\",\n extensions: [\".go\"],\n manifests: [\"go.mod\", \"go.sum\"],\n configFiles: [],\n },\n {\n language: \"Rust\",\n extensions: [\".rs\"],\n manifests: [\"Cargo.toml\"],\n configFiles: [],\n },\n {\n language: \"Ruby\",\n extensions: [\".rb\"],\n manifests: [\"Gemfile\", \"*.gemspec\"],\n configFiles: [\".rubocop.yml\"],\n },\n {\n language: \"PHP\",\n extensions: [\".php\"],\n manifests: [\"composer.json\"],\n configFiles: [\"phpcs.xml\"],\n },\n {\n language: \"Java\",\n extensions: [\".java\", \".kt\"],\n manifests: [\"pom.xml\", \"build.gradle\", \"build.gradle.kts\"],\n configFiles: [],\n },\n {\n language: \"Swift\",\n extensions: [\".swift\"],\n manifests: [\"Package.swift\", \"Podfile\"],\n configFiles: [],\n },\n {\n language: \"C#\",\n extensions: [\".cs\"],\n manifests: [\"*.csproj\", \"*.sln\"],\n configFiles: [],\n },\n {\n language: \"Shell\",\n extensions: [\".sh\", \".bash\", \".zsh\"],\n manifests: [],\n configFiles: [],\n },\n {\n language: \"Dart\",\n extensions: [\".dart\"],\n manifests: [\"pubspec.yaml\"],\n configFiles: [],\n },\n {\n language: \"Elixir\",\n extensions: [\".ex\", \".exs\"],\n manifests: [\"mix.exs\"],\n configFiles: [],\n },\n];\n\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"vendor\",\n \"__pycache__\",\n \".venv\",\n \"venv\",\n \"dist\",\n \"build\",\n \".next\",\n \".nuxt\",\n \"target\",\n \"coverage\",\n \".engram\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function onboard(options: OnboardOptions): OnboardResult {\n const startTime = Date.now();\n const {\n maxDepth = 6,\n excludeDirs = [],\n } = options;\n const directory = path.resolve(options.directory ?? process.cwd());\n let rootStat: fs.Stats;\n try {\n rootStat = fs.statSync(directory);\n } catch (err) {\n throw new Error(`Cannot scan onboarding directory ${directory}: ${err instanceof Error ? err.message : String(err)}`);\n }\n if (!rootStat.isDirectory()) {\n throw new Error(`Cannot scan onboarding directory ${directory}: not a directory`);\n }\n\n const exclude = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n\n // Collect all files\n const files = walkDir(directory, exclude, maxDepth);\n\n // Detect languages\n const languages = detectLanguages(files, directory);\n\n // Detect shape\n const { shape, evidence: shapeEvidence } = detectShape(files, directory);\n\n // Discover docs\n const docs = discoverDocs(files, directory);\n\n // Build plan\n const plan = buildPlan(languages, shape, docs, directory);\n\n return {\n directory,\n languages,\n shape,\n shapeEvidence,\n docs,\n totalFiles: files.length,\n durationMs: Date.now() - startTime,\n plan,\n };\n}\n\n// ── Walk directory ───────────────────────────────────────────────────────────\n\nfunction walkDir(\n root: string,\n exclude: Set<string>,\n maxDepth: number,\n): string[] {\n const results: string[] = [];\n\n function walk(dir: string, depth: number): void {\n if (depth > maxDepth) return;\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch (err) {\n if (depth === 0) {\n throw new Error(`Cannot scan onboarding directory ${root}: ${err instanceof Error ? err.message : String(err)}`);\n }\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath, depth + 1);\n } else if (entry.isFile()) {\n results.push(fullPath);\n }\n }\n }\n\n walk(root, 0);\n return results;\n}\n\n// ── Language detection ───────────────────────────────────────────────────────\n\nfunction detectLanguages(files: string[], root: string): LanguageInfo[] {\n const results: LanguageInfo[] = [];\n\n // Count extensions\n const extCounts = new Map<string, number>();\n for (const f of files) {\n const ext = path.extname(f).toLowerCase();\n if (ext) extCounts.set(ext, (extCounts.get(ext) ?? 0) + 1);\n }\n\n // Check manifests at root level\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n for (const rule of LANGUAGE_RULES) {\n const evidence: string[] = [];\n let score = 0;\n\n // Extension matches\n let extMatch = 0;\n for (const ext of rule.extensions) {\n const count = extCounts.get(ext) ?? 0;\n if (count > 0) {\n extMatch += count;\n evidence.push(`${ext} files (${count})`);\n }\n }\n score += Math.min(extMatch * 0.05, 0.5);\n\n // Manifest matches\n for (const manifest of rule.manifests) {\n if (manifest.includes(\"*\")) {\n // Glob pattern — e.g. \"*.gemspec\" matches files ending with \".gemspec\"\n const suffix = manifest.replaceAll(/\\*/g, \"\");\n if ([...rootFiles].some((f) => f.endsWith(suffix))) {\n score += 0.2;\n evidence.push(manifest);\n }\n } else if (rootFiles.has(manifest)) {\n score += 0.2;\n evidence.push(manifest);\n }\n }\n\n // Config matches\n for (const cfg of rule.configFiles) {\n if (rootFiles.has(cfg)) {\n score += 0.1;\n evidence.push(cfg);\n }\n }\n\n if (score > 0) {\n results.push({\n language: rule.language,\n confidence: Math.min(score, 1),\n evidence,\n });\n }\n }\n\n return results.sort((a, b) => b.confidence - a.confidence);\n}\n\n// ── Shape detection ──────────────────────────────────────────────────────────\n\nfunction detectShape(\n files: string[],\n root: string,\n): { shape: ProjectShape; evidence: string[] } {\n const rootFiles = new Set(\n files\n .filter((f) => path.dirname(f) === root)\n .map((f) => path.basename(f)),\n );\n\n const rootDirs = new Set<string>();\n try {\n for (const entry of fs.readdirSync(root, { withFileTypes: true })) {\n if (entry.isDirectory()) rootDirs.add(entry.name);\n }\n } catch {\n // ignore\n }\n\n const evidence: string[] = [];\n\n // Monorepo: workspace packages/ or libs/ dirs + root package.json with workspaces\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.workspaces) {\n evidence.push(\"package.json has workspaces\");\n return { shape: \"monorepo\", evidence };\n }\n }\n\n if (rootDirs.has(\"packages\") || rootDirs.has(\"libs\")) {\n evidence.push(\"has packages/ or libs/ directory\");\n return { shape: \"monorepo\", evidence };\n }\n\n // Workspace: pnpm-workspace.yaml, Cargo workspace, go.work\n if (rootFiles.has(\"pnpm-workspace.yaml\") || rootFiles.has(\"go.work\")) {\n evidence.push(\"workspace manifest found\");\n return { shape: \"workspace\", evidence };\n }\n\n const cargoToml = readTomlWorkspace(path.join(root, \"Cargo.toml\"));\n if (cargoToml) {\n evidence.push(\"Cargo.toml has workspace\");\n return { shape: \"workspace\", evidence };\n }\n\n // Library: has lib/ or src/index.*, exports in package.json\n if (rootFiles.has(\"package.json\")) {\n const pkg = readJsonSafe(path.join(root, \"package.json\"));\n if (pkg?.exports || pkg?.main) {\n // If it also has \"bin\", it's more of an app\n if (pkg?.bin) {\n evidence.push(\"package.json has bin\");\n return { shape: \"app\", evidence };\n }\n evidence.push(\"package.json has exports/main\");\n return { shape: \"library\", evidence };\n }\n }\n\n // Check for app indicators\n if (\n rootFiles.has(\"Dockerfile\") ||\n rootFiles.has(\"docker-compose.yml\") ||\n rootFiles.has(\"docker-compose.yaml\") ||\n rootDirs.has(\"app\") ||\n rootDirs.has(\"src\") && rootDirs.has(\"public\")\n ) {\n evidence.push(\"app-like structure detected\");\n return { shape: \"app\", evidence };\n }\n\n // Script: few files, no package manifest\n if (files.length <= 5 && !rootFiles.has(\"package.json\") && !rootFiles.has(\"pyproject.toml\")) {\n evidence.push(\"few files, no manifest\");\n return { shape: \"script\", evidence };\n }\n\n return { shape: \"unknown\", evidence: [\"no strong shape signal\"] };\n}\n\n// ── Doc discovery ────────────────────────────────────────────────────────────\n\nfunction discoverDocs(files: string[], root: string): DocFile[] {\n const docs: DocFile[] = [];\n const docPatterns: Array<{ pattern: RegExp; kind: DocFile[\"kind\"] }> = [\n { pattern: /^readme(\\.\\w+)?$/i, kind: \"readme\" },\n { pattern: /^changelog(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^changes(\\.\\w+)?$/i, kind: \"changelog\" },\n { pattern: /^contributing(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^code[_-]of[_-]conduct(\\.\\w+)?$/i, kind: \"contributing\" },\n { pattern: /^license(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^copying(\\.\\w+)?$/i, kind: \"license\" },\n { pattern: /^\\.env\\.example$/i, kind: \"config\" },\n { pattern: /^\\.editorconfig$/i, kind: \"config\" },\n ];\n\n for (const filePath of files) {\n const basename = path.basename(filePath).toLowerCase();\n const relPath = path.relative(root, filePath);\n let kind: DocFile[\"kind\"] | undefined;\n\n // Check against patterns\n for (const { pattern, kind: k } of docPatterns) {\n if (pattern.test(basename)) {\n kind = k;\n break;\n }\n }\n\n // Check docs/ directories\n if (!kind && isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n\n // Check markdown files at root or in docs/\n if (!kind && (basename.endsWith(\".md\") || basename.endsWith(\".mdx\"))) {\n if (path.dirname(relPath) === \".\" || isUnderDocsDir(relPath)) {\n kind = \"docs\";\n }\n }\n\n if (kind) {\n let size = 0;\n try {\n size = fs.statSync(filePath).size;\n } catch {\n // ignore\n }\n docs.push({\n path: filePath,\n relativePath: relPath,\n kind,\n size,\n });\n }\n }\n\n return docs;\n}\n\nfunction isUnderDocsDir(relPath: string): boolean {\n const parts = relPath.split(path.sep);\n return parts[0] === \"docs\" || parts[0] === \"doc\" || parts[0] === \"documentation\";\n}\n\n// ── Plan generation ──────────────────────────────────────────────────────────\n\nfunction buildPlan(\n languages: LanguageInfo[],\n shape: ProjectShape,\n docs: DocFile[],\n _root: string,\n): IngestionPlan {\n // Priority: README, CONTRIBUTING, then other docs\n const priorityOrder: Record<DocFile[\"kind\"], number> = {\n readme: 0,\n contributing: 1,\n changelog: 2,\n license: 3,\n docs: 4,\n config: 5,\n other: 6,\n };\n\n const priorityFiles = [...docs]\n .filter((d) => d.size > 0)\n .sort((a, b) => priorityOrder[a.kind] - priorityOrder[b.kind]);\n\n // Recommended categories based on project shape\n const categories: string[] = [\"fact\", \"preference\", \"decision\", \"principle\"];\n if (shape === \"monorepo\" || shape === \"workspace\") {\n categories.push(\"entity\");\n }\n\n // Namespace suggestion from primary language\n const suggestedNamespace = languages.length > 0\n ? languages[0].language.toLowerCase()\n : \"project\";\n\n return {\n priorityFiles,\n estimatedFiles: docs.filter((d) => d.size > 0).length,\n categories,\n suggestedNamespace,\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction readJsonSafe(filePath: string): Record<string, unknown> | null {\n try {\n return JSON.parse(fs.readFileSync(filePath, \"utf8\"));\n } catch {\n return null;\n }\n}\n\nfunction readTomlWorkspace(filePath: string): boolean {\n try {\n const content = fs.readFileSync(filePath, \"utf8\");\n return content.includes(\"[workspace]\");\n } catch {\n return false;\n }\n}\n","/**\n * @remnic/core — Curation\n *\n * Deliberate ingestion of files into memory with provenance tracking.\n * Supports statement-level extraction, dedup, and contradiction checks.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface CurateOptions {\n /** File or directory path to curate */\n targetPath: string;\n /** Memory root directory for writing */\n memoryDir: string;\n /** Source label (e.g. \"manual\", \"docs\", \"onboarding\") */\n source?: string;\n /** Category override (default: auto-detect) */\n category?: string;\n /** Confidence to assign (default: 0.9 for curated items) */\n confidence?: number;\n /** Entity reference to attach */\n entityRef?: string;\n /** Tags to add */\n tags?: string[];\n /** Whether to perform dedup check against existing memories */\n checkDuplicates?: boolean;\n /** Whether to detect contradictions */\n checkContradictions?: boolean;\n /** Whether to write files (default: true). False = dry run */\n write?: boolean;\n}\n\nexport interface CuratedStatement {\n /** Unique ID for this statement */\n id: string;\n /** The extracted statement text */\n content: string;\n /** Category */\n category: string;\n /** Confidence */\n confidence: number;\n /** Provenance info */\n provenance: StatementProvenance;\n /** Hash of content for dedup */\n contentHash: string;\n /** Tags */\n tags: string[];\n /** Entity reference */\n entityRef?: string;\n}\n\nexport interface StatementProvenance {\n /** Source file path */\n sourcePath: string;\n /** Relative path from project root */\n relativePath: string;\n /** Source label */\n source: string;\n /** Line number if extractable (0 = unknown) */\n lineNumber: number;\n /** Timestamp of ingestion */\n ingestedAt: string;\n /** Hash of the source file for diff tracking */\n sourceFileHash: string;\n}\n\nexport interface CurateResult {\n /** Statements extracted */\n statements: CuratedStatement[];\n /** Files processed */\n filesProcessed: number;\n /** Files skipped (empty, binary, etc.) */\n filesSkipped: number;\n /** Duplicate statements found (if checkDuplicates) */\n duplicates: DuplicateResult[];\n /** Contradictions found (if checkContradictions) */\n contradictions: ContradictionResult[];\n /** Memory files written */\n written: string[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicateResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Existing memory ID that matches */\n existingId: string;\n /** Similarity score (0-1) */\n similarity: number;\n /** Recommended action */\n action: \"skip\" | \"merge\" | \"keep\";\n}\n\nexport interface ContradictionResult {\n /** New statement */\n newStatement: CuratedStatement;\n /** Conflicting memory ID */\n conflictingId: string;\n /** The conflicting content */\n conflictingContent: string;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n}\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport async function curate(options: CurateOptions): Promise<CurateResult> {\n const startTime = Date.now();\n const {\n targetPath,\n memoryDir,\n source = \"curation\",\n category: categoryOverride,\n confidence = 0.9,\n entityRef,\n tags = [],\n checkDuplicates = true,\n checkContradictions = false,\n write = true,\n } = options;\n\n const statements: CuratedStatement[] = [];\n const written: string[] = [];\n const duplicates: DuplicateResult[] = [];\n const contradictions: ContradictionResult[] = [];\n let filesProcessed = 0;\n let filesSkipped = 0;\n\n // Determine targets\n const targets = resolveTargets(targetPath);\n const provenanceRoot = resolveProvenanceRoot(targetPath);\n\n // Load existing memories for dedup/contradiction checks\n const existingMemories = checkDuplicates || checkContradictions\n ? loadExistingMemories(memoryDir)\n : new Map();\n\n // Process each file\n for (const filePath of targets) {\n const content = readFileSafe(filePath);\n if (!content) {\n filesSkipped++;\n continue;\n }\n\n if (isBinary(content)) {\n filesSkipped++;\n continue;\n }\n\n filesProcessed++;\n\n const sourceFileHash = hashContent(content);\n const fileStatements = extractStatements(\n content,\n filePath,\n provenanceRoot,\n source,\n sourceFileHash,\n categoryOverride,\n confidence,\n entityRef,\n tags,\n );\n\n for (const stmt of fileStatements) {\n // Dedup check\n if (checkDuplicates) {\n const dup = findDuplicate(stmt, existingMemories);\n if (dup) {\n duplicates.push(dup);\n if (dup.action === \"skip\") continue;\n }\n }\n\n // Contradiction check\n if (checkContradictions) {\n const contra = findContradiction(stmt, existingMemories);\n if (contra) {\n contradictions.push(contra);\n }\n }\n\n statements.push(stmt);\n\n // Write to memory\n if (write) {\n const writtenPath = writeStatement(stmt, memoryDir);\n written.push(writtenPath);\n existingMemories.set(stmt.contentHash, {\n id: stmt.id,\n content: stmt.content,\n category: stmt.category,\n });\n }\n }\n }\n\n return {\n statements,\n filesProcessed,\n filesSkipped,\n duplicates,\n contradictions,\n written,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Target resolution ────────────────────────────────────────────────────────\n\nfunction resolveTargets(targetPath: string): string[] {\n const stat = fs.statSync(targetPath);\n if (stat.isFile()) return [targetPath];\n\n // Directory — walk for .md, .txt, .mdx\n const results: string[] = [];\n const extensions = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\n\n function walk(dir: string): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n if (entry.name !== \"node_modules\" && entry.name !== \".git\") {\n walk(fullPath);\n }\n } else if (extensions.has(path.extname(entry.name).toLowerCase())) {\n results.push(fullPath);\n }\n }\n }\n\n walk(targetPath);\n return results;\n}\n\nfunction resolveProvenanceRoot(targetPath: string): string {\n const resolvedTarget = path.resolve(targetPath);\n const stat = fs.statSync(resolvedTarget);\n return stat.isFile() ? path.dirname(resolvedTarget) : resolvedTarget;\n}\n\n// ── Statement extraction ─────────────────────────────────────────────────────\n\nfunction extractStatements(\n content: string,\n filePath: string,\n projectRoot: string,\n source: string,\n sourceFileHash: string,\n categoryOverride: string | undefined,\n confidence: number,\n entityRef: string | undefined,\n tags: string[],\n): CuratedStatement[] {\n const relativePath = path.relative(projectRoot, path.resolve(filePath)) || path.basename(filePath);\n const statements: CuratedStatement[] = [];\n const now = new Date().toISOString();\n\n // Split content into paragraphs/lines and extract meaningful statements\n const paragraphs = content\n .split(/\\n{2,}/)\n .map((p) => p.trim())\n .filter((p) => p.length > 20 && p.length < 2000);\n\n // Also extract list items\n const listItems = content\n .split(\"\\n\")\n .filter((l) => /^\\s*[-*]\\s+/.test(l))\n .map((l) => l.replace(/^\\s*[-*]\\s+/, \"\").trim())\n .filter((l) => l.length > 10 && l.length < 500);\n\n const allItems = [...paragraphs, ...listItems];\n\n // Deduplicate within file\n const seen = new Set<string>();\n for (const item of allItems) {\n const hash = hashContent(item.toLowerCase());\n if (seen.has(hash)) continue;\n seen.add(hash);\n\n const id = generateId();\n const category = categoryOverride ?? detectCategory(item);\n\n statements.push({\n id,\n content: item,\n category,\n confidence,\n provenance: {\n sourcePath: filePath,\n relativePath,\n source,\n lineNumber: 0,\n ingestedAt: now,\n sourceFileHash,\n },\n contentHash: hash,\n tags: [...tags],\n entityRef,\n });\n }\n\n return statements;\n}\n\n// ── Category detection ───────────────────────────────────────────────────────\n\nfunction detectCategory(text: string): string {\n const lower = text.toLowerCase();\n\n if (/^(always|never|must|should|don't|avoid|ensure)/.test(lower)) return \"principle\";\n if (/^(we|team|project)\\s+(decided|chose|will|use)/.test(lower)) return \"decision\";\n if (/^(i|we)\\s+(prefer|like|want|hate|dislike)/.test(lower)) return \"preference\";\n if (/fix|bug|issue|broken|error/i.test(lower)) return \"correction\";\n if (/\\?.+$/.test(lower.trim())) return \"question\";\n\n return \"fact\";\n}\n\n// ── Dedup ────────────────────────────────────────────────────────────────────\n\ninterface ExistingMemory {\n id: string;\n content: string;\n category: string;\n}\n\nfunction findDuplicate(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): DuplicateResult | null {\n const stmtLower = stmt.content.toLowerCase();\n\n // Exact hash match\n const exactMatch = existing.get(stmt.contentHash);\n if (exactMatch) {\n return {\n newStatement: stmt,\n existingId: exactMatch.id,\n similarity: 1,\n action: \"skip\",\n };\n }\n\n // Fuzzy match — check substring containment\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n if (memLower.length > 50 && stmtLower.length > 50) {\n // Check if one contains the other\n if (memLower.includes(stmtLower.slice(0, 40)) || stmtLower.includes(memLower.slice(0, 40))) {\n return {\n newStatement: stmt,\n existingId: mem.id,\n similarity: 0.85,\n action: \"skip\",\n };\n }\n }\n }\n\n return null;\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nfunction findContradiction(\n stmt: CuratedStatement,\n existing: Map<string, ExistingMemory>,\n): ContradictionResult | null {\n const negationPatterns = [\n /\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/i,\n ];\n\n const hasNegation = negationPatterns.some((p) => p.test(stmt.content));\n if (!hasNegation) return null;\n\n // Strip negation and look for positive version\n const stripped = stmt.content\n .toLowerCase()\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|never|no)\\b/gi, \"\")\n .trim();\n\n if (stripped.length < 20) return null;\n\n for (const [_, mem] of existing) {\n const memLower = mem.content.toLowerCase();\n // If an existing memory affirms what this statement negates\n if (memLower.includes(stripped.slice(0, Math.min(30, stripped.length)))) {\n return {\n newStatement: stmt,\n conflictingId: mem.id,\n conflictingContent: mem.content,\n severity: \"high\",\n };\n }\n }\n\n return null;\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadExistingMemories(memoryDir: string): Map<string, ExistingMemory> {\n const result = new Map<string, ExistingMemory>();\n if (!fs.existsSync(memoryDir)) return result;\n\n // Walk all known category dirs for existing memories\n const dirs = ALL_CATEGORY_DIRS;\n for (const dir of dirs) {\n const fullDir = path.join(memoryDir, dir);\n if (!fs.existsSync(fullDir)) continue;\n\n walkFiles(fullDir, (filePath) => {\n const content = readFileSafe(filePath);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n const hash = hashContent(body.toLowerCase());\n result.set(hash, {\n id: fm.id,\n content: body,\n category: fm.category ?? dir.slice(0, -1),\n });\n });\n }\n\n return result;\n}\n\n// ── Writing ──────────────────────────────────────────────────────────────────\n\nfunction writeStatement(stmt: CuratedStatement, memoryDir: string): string {\n const now = new Date();\n const dateDir = now.toISOString().split(\"T\")[0];\n const categoryDir = getCategoryDir(memoryDir, stmt.category);\n\n const dir = path.join(categoryDir, dateDir);\n fs.mkdirSync(dir, { recursive: true });\n\n const fileName = `${stmt.category}-${Date.now()}-${stmt.id.slice(0, 8)}.md`;\n const filePath = path.join(dir, fileName);\n\n const frontmatter = [\n \"---\",\n `id: ${stmt.id}`,\n `category: ${stmt.category}`,\n `created: ${stmt.provenance.ingestedAt}`,\n `updated: ${stmt.provenance.ingestedAt}`,\n `confidence: ${stmt.confidence}`,\n `confidenceTier: ${tierFromConfidence(stmt.confidence)}`,\n `source: ${stmt.provenance.source}`,\n `tags: ${JSON.stringify(stmt.tags)}`,\n stmt.entityRef ? `entityRef: ${stmt.entityRef}` : null,\n `provenanceFile: ${stmt.provenance.relativePath}`,\n `provenanceHash: ${stmt.provenance.sourceFileHash}`,\n \"---\",\n ]\n .filter(Boolean)\n .join(\"\\n\");\n\n const body = `${frontmatter}\\n\\n${stmt.content}\\n`;\n\n fs.writeFileSync(filePath, body);\n return filePath;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction generateId(): string {\n return crypto.randomUUID();\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction tierFromConfidence(confidence: number): string {\n if (confidence >= 0.95) return \"explicit\";\n if (confidence >= 0.8) return \"high\";\n if (confidence >= 0.5) return \"medium\";\n return \"low\";\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction isBinary(content: string): boolean {\n // Simple heuristic: if content has null bytes, it's binary\n for (let i = 0; i < Math.min(content.length, 8000); i++) {\n if (content.charCodeAt(i) === 0) return true;\n }\n return false;\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n category?: string;\n [key: string]: unknown;\n}\n\nfunction parseFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n (fm as Record<string, unknown>)[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkFiles(dir: string, callback: (filePath: string) => void): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walkFiles(fullPath, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Dedup & Contradiction Detection\n *\n * Statement-level deduplication and contradiction detection\n * against existing memories. Can be used standalone or via curation.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\nimport { ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface MemoryEntry {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** File path (if known) */\n filePath?: string;\n}\n\nexport interface DedupOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Similarity threshold for fuzzy matching (0-1, default: 0.85) */\n threshold?: number;\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface DedupResult {\n /** Total memories scanned */\n scanned: number;\n /** Duplicate pairs found */\n duplicates: DuplicatePair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface DuplicatePair {\n /** First memory */\n left: MemoryEntry;\n /** Second memory */\n right: MemoryEntry;\n /** Similarity score */\n similarity: number;\n /** Recommended action */\n action: \"merge\" | \"keep_left\" | \"keep_right\";\n}\n\nexport interface ContradictionOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Categories to scan (default: all) */\n categories?: string[];\n /** Max memories to load (default: 10000) */\n maxLoad?: number;\n}\n\nexport interface ContradictionResult {\n /** Total memories scanned */\n scanned: number;\n /** Contradictions found */\n contradictions: ContradictionPair[];\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ContradictionPair {\n /** First statement */\n left: MemoryEntry;\n /** Contradicting statement */\n right: MemoryEntry;\n /** Severity */\n severity: \"high\" | \"medium\" | \"low\";\n /** Reason */\n reason: string;\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\nconst DEFAULT_DEDUP_THRESHOLD = 0.85;\nconst DEFAULT_MAX_LOAD = 10000;\n\nfunction normalizeThreshold(value: number | undefined, defaultValue: number): number {\n return typeof value === \"number\" &&\n Number.isFinite(value) &&\n value >= 0 &&\n value <= 1\n ? value\n : defaultValue;\n}\n\nfunction normalizeMaxLoad(value: number | undefined, defaultValue: number): number {\n return typeof value === \"number\" &&\n Number.isInteger(value) &&\n value >= 0\n ? value\n : defaultValue;\n}\n\nexport function findDuplicates(options: DedupOptions): DedupResult {\n const startTime = Date.now();\n const { memoryDir } = options;\n const threshold = normalizeThreshold(options.threshold, DEFAULT_DEDUP_THRESHOLD);\n const maxLoad = normalizeMaxLoad(options.maxLoad, DEFAULT_MAX_LOAD);\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const duplicates: DuplicatePair[] = [];\n\n // Compare all pairs (O(n^2) but bounded by maxLoad)\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const sim = computeSimilarity(memories[i].content, memories[j].content);\n if (sim >= threshold) {\n duplicates.push({\n left: memories[i],\n right: memories[j],\n similarity: sim,\n action: sim >= 0.98 ? \"merge\" : sim >= 0.9 ? \"keep_right\" : \"keep_left\",\n });\n }\n }\n }\n\n return {\n scanned: memories.length,\n duplicates,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function findContradictions(options: ContradictionOptions): ContradictionResult {\n const startTime = Date.now();\n const { memoryDir } = options;\n const maxLoad = normalizeMaxLoad(options.maxLoad, DEFAULT_MAX_LOAD);\n\n const memories = loadMemories(memoryDir, options.categories, maxLoad);\n const contradictions: ContradictionPair[] = [];\n\n for (let i = 0; i < memories.length; i++) {\n for (let j = i + 1; j < memories.length; j++) {\n const contra = detectContradiction(memories[i], memories[j]);\n if (contra) {\n contradictions.push(contra);\n }\n }\n }\n\n return {\n scanned: memories.length,\n contradictions,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Similarity computation ───────────────────────────────────────────────────\n\nfunction computeSimilarity(a: string, b: string): number {\n // Normalize\n const normA = normalize(a);\n const normB = normalize(b);\n\n // Exact match\n if (normA === normB) return 1;\n\n // Hash-based exact match\n if (hashContent(normA) === hashContent(normB)) return 0.99;\n\n // Substring containment\n if (normA.length > 50 && normB.length > 50) {\n if (normA.includes(normB.slice(0, 40)) || normB.includes(normA.slice(0, 40))) {\n return 0.9;\n }\n }\n\n // Word overlap (Jaccard)\n const wordsA = new Set(normA.split(/\\s+/));\n const wordsB = new Set(normB.split(/\\s+/));\n const intersection = new Set([...wordsA].filter((w) => wordsB.has(w)));\n const union = new Set([...wordsA, ...wordsB]);\n\n if (union.size === 0) return 0;\n return intersection.size / union.size;\n}\n\nfunction normalize(text: string): string {\n return text\n .toLowerCase()\n .replace(/[^\\w\\s']/g, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Contradiction detection ──────────────────────────────────────────────────\n\nconst NEGATION_WORDS = new Set([\n \"not\", \"don't\", \"doesn't\", \"isn't\", \"aren't\", \"won't\", \"can't\", \"cannot\",\n \"never\", \"no\", \"none\", \"neither\", \"nor\", \"nothing\", \"nowhere\",\n]);\n\nfunction detectContradiction(\n a: MemoryEntry,\n b: MemoryEntry,\n): ContradictionPair | null {\n const normA = normalize(a.content);\n const normB = normalize(b.content);\n\n // Check if one has negation and the other doesn't\n const aHasNegation = containsNegation(normA);\n const bHasNegation = containsNegation(normB);\n\n if (aHasNegation === bHasNegation) return null;\n\n // Strip negation and compare core content\n const strippedA = stripNegation(normA);\n const strippedB = stripNegation(normB);\n\n const sim = computeSimilarity(strippedA, strippedB);\n if (sim < 0.7) return null;\n\n // Check for opposite quantifiers\n const oppQuantifiers = [\n [\"always\", \"never\"],\n [\"all\", \"none\"],\n [\"every\", \"no\"],\n [\"must\", \"must not\"],\n [\"should\", \"should not\"],\n [\"can\", \"cannot\"],\n ];\n\n for (const [pos, neg] of oppQuantifiers) {\n if (\n (a.content.toLowerCase().includes(pos) && b.content.toLowerCase().includes(neg)) ||\n (a.content.toLowerCase().includes(neg) && b.content.toLowerCase().includes(pos))\n ) {\n return {\n left: a,\n right: b,\n severity: \"high\",\n reason: `Opposite quantifiers: \"${pos}\" vs \"${neg}\"`,\n };\n }\n }\n\n return {\n left: a,\n right: b,\n severity: sim >= 0.85 ? \"high\" : \"medium\",\n reason: \"Negated version of similar content\",\n };\n}\n\nfunction containsNegation(text: string): boolean {\n const words = text.split(/\\s+/);\n return words.some((w) => NEGATION_WORDS.has(w));\n}\n\nfunction stripNegation(text: string): string {\n return text\n .replace(/\\b(not|don't|doesn't|isn't|aren't|won't|can't|cannot|never|no|none|neither|nor|nothing|nowhere)\\b/gi, \"\")\n .replace(/\\s+/g, \" \")\n .trim();\n}\n\n// ── Memory loading ───────────────────────────────────────────────────────────\n\nfunction loadMemories(\n memoryDir: string,\n categories?: string[],\n maxLoad = 10000,\n): MemoryEntry[] {\n const result: MemoryEntry[] = [];\n const allCategories = categories ?? ALL_CATEGORY_DIRS;\n if (!fs.existsSync(memoryDir)) return result;\n const memoryRootReal = fs.realpathSync(memoryDir);\n\n for (const category of allCategories) {\n if (result.length >= maxLoad) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir)) continue;\n const categoryStat = fs.lstatSync(dir);\n if (categoryStat.isSymbolicLink()) {\n throw new Error(`Refusing to scan symlinked memory category directory: ${dir}`);\n }\n if (!categoryStat.isDirectory()) continue;\n const categoryRootReal = fs.realpathSync(dir);\n assertPathInsideRoot(memoryRootReal, categoryRootReal, dir);\n\n walkMdFiles(dir, memoryRootReal, categoryRootReal, (filePath) => {\n if (result.length >= maxLoad) return;\n\n const content = readFileSafe(filePath, memoryRootReal, categoryRootReal);\n if (!content) return;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id || !body) return;\n\n result.push({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n filePath,\n });\n });\n }\n\n return result;\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction readFileSafe(\n filePath: string,\n memoryRootReal: string,\n categoryRootReal: string,\n): string | null {\n try {\n const fileStat = fs.lstatSync(filePath);\n if (fileStat.isSymbolicLink()) {\n throw new Error(`Refusing to read symlinked memory file: ${filePath}`);\n }\n const fileReal = fs.realpathSync(filePath);\n assertPathInsideRoot(memoryRootReal, fileReal, filePath);\n assertPathInsideRoot(categoryRootReal, fileReal, filePath);\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction assertPathInsideRoot(rootReal: string, targetReal: string, sourcePath: string): void {\n const rel = path.relative(rootReal, targetReal);\n if (rel === \"\" || (!rel.startsWith(\"..\") && !path.isAbsolute(rel))) {\n return;\n }\n throw new Error(`Refusing to scan memory path outside root: ${sourcePath}`);\n}\n\nfunction walkMdFiles(\n dir: string,\n memoryRootReal: string,\n categoryRootReal: string,\n callback: (filePath: string) => void,\n): void {\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n const entryStat = fs.lstatSync(fullPath);\n if (entryStat.isSymbolicLink()) {\n throw new Error(`Refusing to scan symlinked memory path: ${fullPath}`);\n }\n const entryReal = fs.realpathSync(fullPath);\n assertPathInsideRoot(memoryRootReal, entryReal, fullPath);\n assertPathInsideRoot(categoryRootReal, entryReal, fullPath);\n if (entryStat.isDirectory()) {\n walkMdFiles(fullPath, memoryRootReal, categoryRootReal, callback);\n } else if (entry.name.endsWith(\".md\")) {\n callback(fullPath);\n }\n }\n}\n","/**\n * @remnic/core — Review Inbox\n *\n * Manages low-confidence memories and suggestions pending review.\n * Integrates with the existing review-queue system.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { getCategoryDir, ALL_CATEGORY_DIRS } from \"../utils/category-dir.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface ReviewItem {\n /** Memory ID */\n id: string;\n /** Content text */\n content: string;\n /** Category */\n category: string;\n /** Confidence score (0-1) */\n confidence: number;\n /** Confidence tier */\n confidenceTier: string;\n /** Source */\n source: string;\n /** File path if available */\n filePath?: string;\n /** Created date */\n created: string;\n /** Reason it's in review */\n reviewReason: \"low_confidence\" | \"suggestion\" | \"contradiction\" | \"duplicate\" | \"tombstone_blocked\";\n /** Additional context */\n context?: string;\n}\n\nexport type ReviewAction = \"approve\" | \"dismiss\" | \"flag\";\n\nexport interface ReviewResult {\n /** Item acted upon */\n itemId: string;\n /** Action taken */\n action: ReviewAction;\n /** Updated file path (if modified) */\n updatedPath?: string;\n /** Status message */\n message: string;\n /** Tombstone id cleared by an approve action (for the caller to revoke). */\n clearedTombstoneId?: string;\n}\n\nexport interface ReviewListResult {\n /** Items pending review */\n items: ReviewItem[];\n /** Total count */\n total: number;\n /** Duration in ms */\n durationMs: number;\n}\n\nexport interface ReviewOptions {\n /** Memory root directory */\n memoryDir: string;\n /** Filter by reason */\n reason?: ReviewItem[\"reviewReason\"];\n /** Max items to return (default: 50) */\n limit?: number;\n /** Include items with confidence below this threshold (default: 0.7) */\n confidenceThreshold?: number;\n}\n\nexport interface ReviewActionOptions {\n /** Match the threshold used when listing review items (default: 0.7) */\n confidenceThreshold?: number;\n /**\n * Revocation hook (issue #1579). When approving a memory whose frontmatter\n * carries `blockedBy: <tombstoneId>`, the hook fires so the caller (CLI /\n * orchestrator) can append a `kind: \"revocation\"` tombstone entry —\n * re-allowing the content. Fire-and-forget: a revocation failure MUST NOT\n * fail the approval (gotcha #13). The hook receives the tombstone id and\n * the memory id.\n */\n onApproveBlockedMemory?: (tombstoneId: string, memoryId: string) => void | Promise<void>;\n}\n\ninterface ReviewFileMatch {\n filePath: string;\n location: \"queue\" | \"category\";\n}\n\nconst DEFAULT_CONFIDENCE_THRESHOLD = 0.7;\n\nfunction realMemoryRoot(memoryDir: string): string | null {\n try {\n const stat = fs.lstatSync(memoryDir);\n if (!stat.isDirectory() || stat.isSymbolicLink()) return null;\n return fs.realpathSync(memoryDir);\n } catch {\n return null;\n }\n}\n\nfunction isPathInside(rootReal: string, candidateReal: string): boolean {\n const relative = path.relative(rootReal, candidateReal);\n return relative === \"\" || (!!relative && !relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\nfunction isSafeDirectory(rootReal: string, dir: string): boolean {\n try {\n const stat = fs.lstatSync(dir);\n if (!stat.isDirectory() || stat.isSymbolicLink()) return false;\n return isPathInside(rootReal, fs.realpathSync(dir));\n } catch {\n return false;\n }\n}\n\nfunction ensureSafeDirectory(rootReal: string, dir: string): void {\n if (fs.existsSync(dir)) {\n if (!isSafeDirectory(rootReal, dir)) {\n throw new Error(`Refusing to write through unsafe review path: ${dir}`);\n }\n return;\n }\n fs.mkdirSync(dir, { recursive: true });\n if (!isSafeDirectory(rootReal, dir)) {\n throw new Error(`Refusing to write through unsafe review path: ${dir}`);\n }\n}\n\n// ── Main functions ───────────────────────────────────────────────────────────\n\n/**\n * List items pending review.\n */\nexport function listReviewItems(options: ReviewOptions): ReviewListResult {\n const startTime = Date.now();\n const {\n memoryDir,\n reason: filterReason,\n limit = 50,\n confidenceThreshold = DEFAULT_CONFIDENCE_THRESHOLD,\n } = options;\n const maxItems = Math.max(0, limit);\n const rootReal = realMemoryRoot(memoryDir);\n if (!rootReal || maxItems === 0) {\n return { items: [], total: 0, durationMs: Date.now() - startTime };\n }\n\n const items: ReviewItem[] = [];\n const isLimitReached = (): boolean => items.length >= maxItems;\n const addItem = (item: ReviewItem): void => {\n if (isLimitReached()) return;\n if (filterReason && item.reviewReason !== filterReason) return;\n items.push(item);\n };\n\n // Check suggestions directory\n const suggestionsDir = path.join(memoryDir, \"suggestions\");\n if (!isLimitReached() && fs.existsSync(suggestionsDir) && isSafeDirectory(rootReal, suggestionsDir)) {\n walkMd(rootReal, suggestionsDir, (filePath, content) => {\n if (isLimitReached()) return true;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return false;\n\n addItem({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"suggestion\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: \"suggestion\",\n });\n return isLimitReached();\n });\n }\n\n // Check review directory\n const reviewDir = path.join(memoryDir, \"review\");\n if (!isLimitReached() && fs.existsSync(reviewDir) && isSafeDirectory(rootReal, reviewDir)) {\n walkMd(rootReal, reviewDir, (filePath, content) => {\n if (isLimitReached()) return true;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return false;\n\n addItem({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? \"review\",\n confidence: parseConfidence(fm.confidence, 0.5),\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: (fm.reviewReason as ReviewItem[\"reviewReason\"]) ?? \"low_confidence\",\n context: fm.context as string | undefined,\n });\n return isLimitReached();\n });\n }\n\n // Scan all categories for low-confidence items\n const categories = ALL_CATEGORY_DIRS;\n for (const category of categories) {\n if (isLimitReached()) break;\n\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;\n\n walkMd(rootReal, dir, (filePath, content) => {\n if (isLimitReached()) return true;\n\n const fm = parseFrontmatter(content);\n const body = extractBody(content);\n if (!fm?.id) return false;\n\n const confidence = parseConfidence(fm.confidence, 1);\n if (confidence >= confidenceThreshold && !(typeof fm.blockedBy === \"string\" && fm.blockedBy.length > 0)) return false;\n if (parseBoolean(fm.reviewDismissed)) return false;\n\n // Skip if already in items\n if (items.some((i) => i.id === fm.id)) return false;\n\n addItem({\n id: fm.id as string,\n content: body,\n category: (fm.category as string) ?? category.slice(0, -1),\n confidence,\n confidenceTier: (fm.confidenceTier as string) ?? \"low\",\n source: (fm.source as string) ?? \"unknown\",\n filePath,\n created: (fm.created as string) ?? new Date().toISOString(),\n reviewReason: (typeof fm.blockedBy === \"string\" && fm.blockedBy.length > 0) ? \"tombstone_blocked\" : \"low_confidence\",\n });\n return isLimitReached();\n });\n }\n\n return {\n items,\n total: items.length,\n durationMs: Date.now() - startTime,\n };\n}\n\n/**\n * Perform a review action on an item.\n */\nexport function performReview(\n memoryDir: string,\n itemId: string,\n action: ReviewAction,\n options: ReviewActionOptions = {},\n): ReviewResult {\n switch (action) {\n case \"approve\":\n return approveItem(memoryDir, itemId, options);\n case \"dismiss\":\n return dismissItem(memoryDir, itemId, options);\n case \"flag\":\n return flagItem(memoryDir, itemId, options);\n }\n}\n\n// ── Actions ──────────────────────────────────────────────────────────────────\n\nfunction approveItem(\n memoryDir: string,\n itemId: string,\n options: ReviewActionOptions,\n): ReviewResult {\n const rootReal = realMemoryRoot(memoryDir);\n if (!rootReal) return { itemId, action: \"approve\", message: \"Item not found\" };\n const found = findReviewFileById(memoryDir, itemId, options);\n if (!found) {\n return { itemId, action: \"approve\", message: \"Item not found\" };\n }\n\n const content = fs.readFileSync(found.filePath, \"utf8\");\n const fm = parseFrontmatter(content);\n if (!fm) return { itemId, action: \"approve\", message: \"Could not parse frontmatter\" };\n\n // Issue #1579 — when approving a tombstone-blocked memory, fire the\n // revocation hook so the content is re-allowed (append-only log: a\n // `kind: \"revocation\"` entry supersedes the tombstone at lookup). Clear\n // blockedBy/tombstoneBlockTier on the promoted memory so it is fully\n // active. Fire-and-forget: a hook failure never fails the approval.\n const blockedBy = typeof fm.blockedBy === \"string\" ? fm.blockedBy : null;\n if (blockedBy && options.onApproveBlockedMemory) {\n try {\n const maybe = options.onApproveBlockedMemory(blockedBy, itemId);\n if (maybe && typeof (maybe as Promise<void>).then === \"function\") {\n void (maybe as Promise<void>).catch(() => undefined);\n }\n } catch {\n /* fire-and-forget — never fail the approval (gotcha #13) */\n }\n }\n\n const updatedContent = updateFrontmatterFields(content, {\n confidence: \"0.9\",\n confidenceTier: \"high\",\n reviewDismissed: null,\n // Clear the tombstone-block markers so the promoted memory is active.\n // Clear the tombstone-block markers AND restore active status so the\n // promoted memory is fully active in recall + provenance (issue #1579\n // review: leaving status: pending_review kept it invisible to recall).\n ...(blockedBy ? { blockedBy: null, tombstoneBlockTier: null, status: \"active\" } : {}),\n });\n\n if (found.location === \"category\") {\n fs.writeFileSync(found.filePath, updatedContent, \"utf8\");\n return {\n itemId,\n action: \"approve\",\n updatedPath: found.filePath,\n message: \"Approved low-confidence memory in place with confidence 0.9\",\n ...(blockedBy ? { clearedTombstoneId: blockedBy } : {}),\n };\n }\n\n // Promote queued suggestions/review items to their category directory.\n const category = (fm.category as string) ?? \"fact\";\n const targetDir = getCategoryDir(memoryDir, category);\n const dateDir = new Date().toISOString().split(\"T\")[0];\n ensureSafeDirectory(rootReal, targetDir);\n const outputPath = path.join(targetDir, dateDir, path.basename(found.filePath));\n\n ensureSafeDirectory(rootReal, path.dirname(outputPath));\n const promotedPath = writeFileWithoutClobber(outputPath, updatedContent, itemId);\n\n // Remove from review\n fs.unlinkSync(found.filePath);\n\n return {\n itemId,\n action: \"approve\",\n updatedPath: promotedPath,\n message: `Promoted to ${category} with confidence 0.9`,\n ...(blockedBy ? { clearedTombstoneId: blockedBy } : {}),\n };\n}\n\nfunction dismissItem(\n memoryDir: string,\n itemId: string,\n options: ReviewActionOptions,\n): ReviewResult {\n const found = findReviewFileById(memoryDir, itemId, options);\n if (!found) {\n return { itemId, action: \"dismiss\", message: \"Item not found\" };\n }\n\n if (found.location === \"queue\") {\n fs.unlinkSync(found.filePath);\n return { itemId, action: \"dismiss\", message: \"Dismissed and removed\" };\n }\n\n const content = fs.readFileSync(found.filePath, \"utf8\");\n fs.writeFileSync(\n found.filePath,\n updateFrontmatterFields(content, {\n reviewDismissed: \"true\",\n reviewDismissedAt: new Date().toISOString(),\n }),\n \"utf8\",\n );\n return {\n itemId,\n action: \"dismiss\",\n updatedPath: found.filePath,\n message: \"Dismissed low-confidence memory in place\",\n };\n}\n\nfunction flagItem(\n memoryDir: string,\n itemId: string,\n options: ReviewActionOptions,\n): ReviewResult {\n const found = findReviewFileById(memoryDir, itemId, options);\n if (!found) {\n return { itemId, action: \"flag\", message: \"Item not found\" };\n }\n\n const content = fs.readFileSync(found.filePath, \"utf8\");\n const fixed = updateFrontmatterFields(content, {\n flagged: \"true\",\n flaggedAt: new Date().toISOString(),\n });\n fs.writeFileSync(found.filePath, fixed);\n return {\n itemId,\n action: \"flag\",\n updatedPath: found.filePath,\n message: \"Flagged for further review\",\n };\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction findReviewFileById(\n memoryDir: string,\n id: string,\n options: ReviewActionOptions = {},\n): ReviewFileMatch | null {\n const rootReal = realMemoryRoot(memoryDir);\n if (!rootReal) return null;\n for (const loc of [\"suggestions\", \"review\"]) {\n const dir = path.join(memoryDir, loc);\n if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;\n\n const found = findFileById(rootReal, dir, id);\n if (found) return { filePath: found, location: \"queue\" };\n }\n\n for (const category of ALL_CATEGORY_DIRS) {\n const dir = path.join(memoryDir, category);\n if (!fs.existsSync(dir) || !isSafeDirectory(rootReal, dir)) continue;\n\n const found = findFileById(rootReal, dir, id, (fm) => isLowConfidenceReviewCandidate(fm, options));\n if (found) return { filePath: found, location: \"category\" };\n }\n\n return null;\n}\n\nfunction findFileById(\n rootReal: string,\n dir: string,\n id: string,\n include?: (frontmatter: Record<string, unknown>) => boolean,\n): string | null {\n const files = walkMdPaths(rootReal, dir);\n for (const filePath of files) {\n const content = readFileSafe(filePath);\n if (!content) continue;\n const fm = parseFrontmatter(content);\n if (fm?.id === id && (!include || include(fm))) return filePath;\n }\n return null;\n}\n\nfunction isLowConfidenceReviewCandidate(\n fm: Record<string, unknown>,\n options: ReviewActionOptions,\n): boolean {\n const threshold = options.confidenceThreshold ?? DEFAULT_CONFIDENCE_THRESHOLD;\n // Issue #1579: tombstone-blocked facts are ALWAYS review candidates,\n // regardless of confidence. The block sets status: pending_review +\n // blockedBy; these must be visible in the review queue so an operator\n // can approve (revoke the tombstone) or dismiss them. Without this, a\n // high-confidence blocked fact is visible on disk but absent from the\n // review UI — a silent drop, which violates the non-resurrection design\n // (rule 34: visible, not silent).\n if (typeof fm.blockedBy === \"string\" && fm.blockedBy.length > 0) {\n return !parseBoolean(fm.reviewDismissed);\n }\n return (\n parseConfidence(fm.confidence, 1) < threshold &&\n !parseBoolean(fm.reviewDismissed)\n );\n}\n\nfunction parseBoolean(value: unknown): boolean {\n if (typeof value === \"boolean\") return value;\n if (typeof value !== \"string\") return false;\n const normalized = value.trim().toLowerCase();\n return normalized === \"true\" || normalized === \"1\" || normalized === \"yes\";\n}\n\nfunction parseConfidence(value: unknown, fallback: number): number {\n if (typeof value === \"number\") return Number.isFinite(value) ? value : fallback;\n if (typeof value === \"string\") {\n const n = parseFloat(value);\n return Number.isFinite(n) ? n : fallback;\n }\n return fallback;\n}\n\nfunction updateFrontmatterFields(\n content: string,\n fields: Record<string, string | null>,\n): string {\n const match = content.match(/^(---\\n)([\\s\\S]*?)(\\n---(?:\\n|$))/);\n if (!match) return content;\n\n const seen = new Set<string>();\n const lines = match[2].split(\"\\n\");\n const nextLines: string[] = [];\n for (const line of lines) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) {\n nextLines.push(line);\n continue;\n }\n const key = line.slice(0, colonIdx).trim();\n if (!Object.prototype.hasOwnProperty.call(fields, key)) {\n nextLines.push(line);\n continue;\n }\n seen.add(key);\n const value = fields[key];\n if (value !== null) {\n nextLines.push(`${key}: ${value}`);\n }\n }\n\n for (const [key, value] of Object.entries(fields)) {\n if (value !== null && !seen.has(key)) {\n nextLines.push(`${key}: ${value}`);\n }\n }\n\n return `${match[1]}${nextLines.join(\"\\n\")}${match[3]}${content.slice(match[0].length)}`;\n}\n\nfunction readFileSafe(filePath: string): string | null {\n try {\n return fs.readFileSync(filePath, \"utf8\");\n } catch {\n return null;\n }\n}\n\nfunction writeFileWithoutClobber(basePath: string, content: string, discriminator: string): string {\n const parsed = path.parse(basePath);\n const safeDiscriminator = sanitizeFilePart(discriminator);\n\n for (let attempt = 0; attempt < 1000; attempt++) {\n const candidate = attempt === 0\n ? basePath\n : path.join(\n parsed.dir,\n `${parsed.name}-${safeDiscriminator}${attempt === 1 ? \"\" : `-${attempt}`}${parsed.ext || \".md\"}`,\n );\n\n try {\n fs.writeFileSync(candidate, content, { encoding: \"utf8\", flag: \"wx\" });\n return candidate;\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"EEXIST\") continue;\n throw error;\n }\n }\n\n throw new Error(`Could not find a free review promotion path for ${basePath}`);\n}\n\nfunction sanitizeFilePart(value: string): string {\n const chars: string[] = [];\n let previousWasDash = false;\n\n for (const char of value) {\n const next = isSafeFilePartChar(char) ? char : \"-\";\n if (next === \"-\" && previousWasDash) continue;\n chars.push(next);\n previousWasDash = next === \"-\";\n if (chars.length >= 64) break;\n }\n\n let start = 0;\n let end = chars.length;\n while (start < end && chars[start] === \"-\") start++;\n while (end > start && chars[end - 1] === \"-\") end--;\n\n const sanitized = chars.slice(start, end).join(\"\");\n return sanitized || \"review-item\";\n}\n\nfunction isSafeFilePartChar(value: string): boolean {\n if (value.length !== 1) return false;\n const code = value.charCodeAt(0);\n return (\n (code >= 48 && code <= 57) ||\n (code >= 65 && code <= 90) ||\n (code >= 97 && code <= 122) ||\n value === \".\" ||\n value === \"_\" ||\n value === \"-\"\n );\n}\n\nfunction parseFrontmatter(content: string): Record<string, unknown> | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: Record<string, unknown> = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n\nfunction extractBody(content: string): string {\n const match = content.match(/^---\\n[\\s\\S]*?\\n---\\n([\\s\\S]*)/);\n return match ? match[1].trim() : content.trim();\n}\n\nfunction walkMd(rootReal: string, dir: string, callback: (filePath: string, content: string) => boolean | void): boolean {\n if (!isSafeDirectory(rootReal, dir)) return false;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isSymbolicLink()) continue;\n if (entry.isDirectory()) {\n if (walkMd(rootReal, fullPath, callback)) return true;\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n const content = readFileSafe(fullPath);\n if (content && callback(fullPath, content) === true) return true;\n }\n }\n return false;\n}\n\nfunction walkMdPaths(rootReal: string, dir: string): string[] {\n const results: string[] = [];\n if (!isSafeDirectory(rootReal, dir)) return results;\n for (const entry of fs.readdirSync(dir, { withFileTypes: true })) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isSymbolicLink()) continue;\n if (entry.isDirectory()) {\n results.push(...walkMdPaths(rootReal, fullPath));\n } else if (entry.isFile() && entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n return results;\n}\n","/**\n * @remnic/core — Diff-Aware Sync\n *\n * Watches source files for changes and triggers re-ingestion\n * only for changed content. Uses file hashing to detect changes.\n */\n\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport crypto from \"node:crypto\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport interface SyncOptions {\n /** Source directory to watch */\n sourceDir: string;\n /** Memory root directory */\n memoryDir: string;\n /** State file path (stores hashes). Default: memoryDir/.sync-state.json */\n stateFile?: string;\n /** File extensions to watch (default: .md, .txt, .mdx) */\n extensions?: string[];\n /** Directories to exclude */\n excludeDirs?: string[];\n /** Poll interval for watchForChanges. Default: 5000ms */\n pollIntervalMs?: number;\n /** Whether to actually write changes (default: true) */\n dryRun?: boolean;\n}\n\nexport interface SyncResult {\n /** Files scanned */\n scanned: number;\n /** Files changed since last sync */\n changed: FileChange[];\n /** Files unchanged */\n unchanged: number;\n /** Files deleted since last sync */\n deleted: string[];\n /** Files newly added */\n added: string[];\n /** Duration in ms */\n durationMs: number;\n /** State file path */\n stateFile: string;\n}\n\nexport interface FileChange {\n /** Absolute file path */\n filePath: string;\n /** Relative path from source root */\n relativePath: string;\n /** Change type */\n type: \"added\" | \"modified\" | \"deleted\";\n /** Current content hash */\n currentHash: string;\n /** Previous content hash (if modified) */\n previousHash?: string;\n /** File size in bytes */\n size: number;\n}\n\nexport interface SyncState {\n /** Map of relative path → content hash */\n fileHashes: Record<string, string>;\n /** Last sync timestamp */\n lastSyncAt: string;\n /** Version of state format */\n version: number;\n}\n\n// ── Constants ────────────────────────────────────────────────────────────────\n\nconst DEFAULT_EXTENSIONS = new Set([\".md\", \".txt\", \".mdx\", \".rst\"]);\nconst DEFAULT_EXCLUDE = new Set([\n \"node_modules\",\n \".git\",\n \"dist\",\n \"build\",\n \".engram\",\n \"coverage\",\n]);\n\n// ── Main function ────────────────────────────────────────────────────────────\n\nexport function syncChanges(options: SyncOptions): SyncResult {\n const startTime = Date.now();\n const {\n sourceDir,\n memoryDir,\n extensions = [...DEFAULT_EXTENSIONS],\n excludeDirs = [],\n dryRun = false,\n } = options;\n\n const extSet = new Set(extensions);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...excludeDirs]);\n const stateFilePath = options.stateFile ?? path.join(memoryDir, \".sync-state.json\");\n\n // Load previous state\n const prevState = loadState(stateFilePath);\n\n // Scan current files\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n\n // Compute diffs\n const changes = computeDiff(currentFiles, prevState.fileHashes, sourceDir);\n\n const added = changes.filter((c) => c.type === \"added\").map((c) => c.relativePath);\n const modified = changes.filter((c) => c.type === \"modified\");\n const deleted = changes\n .filter((c) => c.type === \"deleted\")\n .map((c) => c.relativePath);\n\n // Update state (even in dry run, we want to show what would change)\n if (!dryRun) {\n const newState: SyncState = {\n fileHashes: {},\n lastSyncAt: new Date().toISOString(),\n version: 1,\n };\n\n // Build new state from current files\n for (const [relPath, hash] of Object.entries(currentFiles)) {\n newState.fileHashes[relPath] = hash;\n }\n\n // Write state\n fs.mkdirSync(path.dirname(stateFilePath), { recursive: true });\n fs.writeFileSync(stateFilePath, JSON.stringify(newState, null, 2));\n }\n\n return {\n scanned: Object.keys(currentFiles).length,\n changed: changes,\n unchanged:\n Object.keys(currentFiles).length - changes.filter((c) => c.type !== \"deleted\").length,\n deleted,\n added,\n durationMs: Date.now() - startTime,\n stateFile: stateFilePath,\n };\n}\n\n/**\n * Watch for changes and call callback on file changes.\n * Returns a stop function.\n */\nexport function watchForChanges(\n options: SyncOptions,\n onChange: (changes: FileChange[]) => void | Promise<void>,\n): { stop: () => void } {\n const { sourceDir, extensions, excludeDirs } = options;\n const extSet = new Set(extensions ?? DEFAULT_EXTENSIONS);\n const excludeSet = new Set([...DEFAULT_EXCLUDE, ...(excludeDirs ?? [])]);\n const pollIntervalMs =\n typeof options.pollIntervalMs === \"number\" &&\n Number.isFinite(options.pollIntervalMs) &&\n options.pollIntervalMs > 0\n ? options.pollIntervalMs\n : 5000;\n\n let lastHashes: Record<string, string> = {};\n let pollInFlight = false;\n\n // Initial scan\n const currentFiles = scanFiles(sourceDir, extSet, excludeSet);\n lastHashes = { ...currentFiles };\n\n // Poll interval (FSWatcher doesn't reliably work for all platforms)\n const poll = async (): Promise<void> => {\n if (pollInFlight) return;\n pollInFlight = true;\n try {\n const nowFiles = scanFiles(sourceDir, extSet, excludeSet);\n const changes = computeDiff(nowFiles, lastHashes, sourceDir);\n\n if (changes.length > 0) {\n await onChange(changes);\n // Update hashes\n for (const change of changes) {\n if (change.type === \"deleted\") {\n delete lastHashes[change.relativePath];\n } else {\n lastHashes[change.relativePath] = change.currentHash;\n }\n }\n }\n } catch {\n // Leave lastHashes unchanged so the next poll retries the same diff.\n } finally {\n pollInFlight = false;\n }\n };\n const interval = setInterval(() => {\n void poll();\n }, pollIntervalMs);\n\n return {\n stop: () => clearInterval(interval),\n };\n}\n\n// ── File scanning ────────────────────────────────────────────────────────────\n\nfunction scanFiles(\n root: string,\n extensions: Set<string>,\n exclude: Set<string>,\n): Record<string, string> {\n const result: Record<string, string> = {};\n\n function walk(dir: string, isRoot = false): void {\n let entries: fs.Dirent[];\n try {\n entries = fs.readdirSync(dir, { withFileTypes: true });\n } catch (err) {\n if (isRoot) {\n throw new Error(\n `sync scan failed for ${dir}: ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n return;\n }\n\n for (const entry of entries) {\n if (exclude.has(entry.name)) continue;\n\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.isFile()) {\n const ext = path.extname(entry.name).toLowerCase();\n if (!extensions.has(ext)) continue;\n\n const relPath = path.relative(root, fullPath);\n try {\n const content = fs.readFileSync(fullPath, \"utf8\");\n result[relPath] = hashContent(content);\n } catch {\n // Can't read — skip\n }\n }\n }\n }\n\n walk(root, true);\n return result;\n}\n\n// ── Diff computation ─────────────────────────────────────────────────────────\n\nfunction computeDiff(\n current: Record<string, string>,\n previous: Record<string, string>,\n sourceDir: string,\n): FileChange[] {\n const changes: FileChange[] = [];\n\n // Find added and modified\n for (const [relPath, hash] of Object.entries(current)) {\n const fullPath = path.join(sourceDir, relPath);\n\n if (!(relPath in previous)) {\n // Added\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"added\",\n currentHash: hash,\n size,\n });\n } else if (previous[relPath] !== hash) {\n // Modified\n let size = 0;\n try {\n size = fs.statSync(fullPath).size;\n } catch {\n // ignore\n }\n changes.push({\n filePath: fullPath,\n relativePath: relPath,\n type: \"modified\",\n currentHash: hash,\n previousHash: previous[relPath],\n size,\n });\n }\n }\n\n // Find deleted\n for (const relPath of Object.keys(previous)) {\n if (!(relPath in current)) {\n changes.push({\n filePath: path.join(sourceDir, relPath),\n relativePath: relPath,\n type: \"deleted\",\n currentHash: \"\",\n size: 0,\n });\n }\n }\n\n return changes;\n}\n\n// ── State management ─────────────────────────────────────────────────────────\n\nfunction loadState(stateFilePath: string): SyncState {\n try {\n const raw = fs.readFileSync(stateFilePath, \"utf8\");\n return JSON.parse(raw);\n } catch {\n return {\n fileHashes: {},\n lastSyncAt: new Date(0).toISOString(),\n version: 1,\n };\n }\n}\n\n// ── Helpers ───────────────────────────────────────────────────────────────────\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n","/**\n * @remnic/core — Spaces + Collaboration\n *\n * First-class memory spaces (personal, project, team) with merge/conflict\n * flows, promotion workflow, and audit trail.\n *\n * Each space is an isolated memory directory. Spaces can share memories\n * through push/pull and promotion workflows.\n */\n\nimport { spawnSync } from \"node:child_process\";\nimport crypto from \"node:crypto\";\nimport fs from \"node:fs\";\nimport path from \"node:path\";\nimport { readEnvVar, resolveHomeDir } from \"../runtime/env.js\";\n\n// ── Types ────────────────────────────────────────────────────────────────────\n\nexport type SpaceKind = \"personal\" | \"project\" | \"team\";\n\nexport interface Space {\n /** Unique space ID */\n id: string;\n /** Human-readable name */\n name: string;\n /** Space type */\n kind: SpaceKind;\n /** Description */\n description?: string;\n /** Memory directory path (absolute) */\n memoryDir: string;\n /** Created at */\n createdAt: string;\n /** Updated at */\n updatedAt: string;\n /** Owner */\n owner?: string;\n /** Members (for team spaces) */\n members?: string[];\n /** Parent space (for promotion) */\n parentSpaceId?: string;\n}\n\nexport interface SpaceManifest {\n /** Current active space ID */\n activeSpaceId: string;\n /** All spaces */\n spaces: Space[];\n /** Manifest version */\n version: number;\n /** Last updated */\n updatedAt?: string;\n}\n\nexport interface SpaceSwitchResult {\n previousSpaceId: string;\n currentSpaceId: string;\n message: string;\n}\n\nexport interface SpacePushResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPushed: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpacePullResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPulled: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface SpaceShareResult {\n spaceId: string;\n sharedWith: string[];\n message: string;\n}\n\nexport interface SpacePromoteResult {\n sourceSpaceId: string;\n targetSpaceId: string;\n memoriesPromoted: number;\n conflicts: ConflictEntry[];\n durationMs: number;\n}\n\nexport interface ConflictEntry {\n /** Memory ID */\n memoryId: string;\n /** Source file path */\n sourcePath: string;\n /** Target file path */\n targetPath: string;\n /** Conflict type */\n conflictType: \"content_mismatch\" | \"metadata_mismatch\" | \"both\";\n /** Source content hash */\n sourceHash: string;\n /** Target content hash */\n targetHash: string;\n}\n\nexport interface MergeResult {\n merged: number;\n conflicts: ConflictEntry[];\n skipped: number;\n durationMs: number;\n}\n\nexport interface AuditEntry {\n id: string;\n timestamp: string;\n action: string;\n sourceSpaceId: string;\n targetSpaceId?: string;\n actor?: string;\n details: string;\n memoryIds?: string[];\n}\n\n// ── Manifest management ─────────────────────────────────────────────────────\n\nconst MANIFEST_VERSION = 1;\nconst MANIFEST_LOCK_STALE_MS = 30_000;\nconst MANIFEST_LOCK_TIMEOUT_MS = MANIFEST_LOCK_STALE_MS + 10_000;\nconst MANIFEST_LOCK_SLEEP_MS = 20;\n\nfunction normalizeSpaceMemoryDir(memoryDir: string): string {\n return path.resolve(memoryDir);\n}\n\nexport function getSpacesDir(baseDir?: string): string {\n const homeDir = baseDir ?? resolveHomeDir();\n return path.join(homeDir, \".config\", \"engram\", \"spaces\");\n}\n\nexport function getManifestPath(baseDir?: string): string {\n return path.join(getSpacesDir(baseDir), \"manifest.json\");\n}\n\nexport function loadManifest(baseDir?: string, memoryDirOverride?: string): SpaceManifest {\n if (fs.existsSync(getManifestPath(baseDir))) {\n try {\n return readManifestUnlocked(baseDir, memoryDirOverride, { bootstrapIfMissing: false });\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n }\n\n return updateManifest(baseDir, (manifest) => manifest, memoryDirOverride);\n}\n\nexport function saveManifest(manifest: SpaceManifest, baseDir?: string): void {\n withManifestLock(baseDir, () => {\n saveManifestUnlocked(manifest, baseDir);\n });\n}\n\nexport function updateManifest<T>(\n baseDir: string | undefined,\n updater: (manifest: SpaceManifest) => T,\n memoryDirOverride?: string\n): T {\n return withManifestLock(baseDir, () => {\n const manifest = readManifestUnlocked(baseDir, memoryDirOverride);\n const result = updater(manifest);\n saveManifestUnlocked(manifest, baseDir);\n return result;\n });\n}\n\nfunction readManifestUnlocked(\n baseDir?: string,\n memoryDirOverride?: string,\n options: { bootstrapIfMissing?: boolean } = {}\n): SpaceManifest {\n const manifestPath = getManifestPath(baseDir);\n\n if (!fs.existsSync(manifestPath)) {\n if (options.bootstrapIfMissing === false) {\n const error = new Error(`Spaces manifest not found: ${manifestPath}`) as NodeJS.ErrnoException;\n error.code = \"ENOENT\";\n throw error;\n }\n const personalSpace = createPersonalSpace(baseDir, memoryDirOverride);\n return {\n activeSpaceId: personalSpace.id,\n spaces: [personalSpace],\n version: MANIFEST_VERSION,\n };\n }\n\n const raw = JSON.parse(fs.readFileSync(manifestPath, \"utf8\"));\n return raw as SpaceManifest;\n}\n\nfunction saveManifestUnlocked(manifest: SpaceManifest, baseDir?: string): void {\n const manifestPath = getManifestPath(baseDir);\n const manifestDir = path.dirname(manifestPath);\n fs.mkdirSync(manifestDir, { recursive: true });\n const tempPath = path.join(manifestDir, `.manifest.${process.pid}.${Date.now()}.${crypto.randomUUID()}.tmp`);\n try {\n fs.writeFileSync(tempPath, `${JSON.stringify(manifest, null, 2)}\\n`, { flag: \"wx\" });\n fs.renameSync(tempPath, manifestPath);\n } catch (error) {\n try {\n fs.rmSync(tempPath, { force: true });\n } catch {\n // Ignore cleanup failures; surface the original write/rename error.\n }\n throw error;\n }\n}\n\nfunction withManifestLock<T>(baseDir: string | undefined, operation: () => T): T {\n const lockDir = `${getManifestPath(baseDir)}.lock`;\n fs.mkdirSync(path.dirname(lockDir), { recursive: true });\n const lockOwner = acquireManifestLock(lockDir);\n try {\n return operation();\n } finally {\n releaseManifestLock(lockDir, lockOwner);\n }\n}\n\nfunction acquireManifestLock(lockDir: string): string {\n const deadline = Date.now() + MANIFEST_LOCK_TIMEOUT_MS;\n const owner = createManifestLockOwner();\n const reclaimDir = getManifestLockReclaimDir(lockDir);\n while (true) {\n if (fs.existsSync(reclaimDir)) {\n removeStaleManifestReclaimLock(reclaimDir);\n }\n if (fs.existsSync(reclaimDir)) {\n if (Date.now() >= deadline) {\n throw new Error(`Timed out waiting for spaces manifest reclaim lock: ${reclaimDir}`);\n }\n sleepSync(MANIFEST_LOCK_SLEEP_MS);\n continue;\n }\n\n try {\n fs.mkdirSync(lockDir, { recursive: false });\n try {\n fs.writeFileSync(path.join(lockDir, \"owner\"), `${owner}\\n`, { flag: \"wx\" });\n } catch (error) {\n fs.rmSync(lockDir, { recursive: true, force: true });\n throw error;\n }\n if (fs.existsSync(reclaimDir)) {\n releaseManifestLock(lockDir, owner);\n if (Date.now() >= deadline) {\n throw new Error(`Timed out waiting for spaces manifest reclaim lock: ${reclaimDir}`);\n }\n sleepSync(MANIFEST_LOCK_SLEEP_MS);\n continue;\n }\n return owner;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n\n removeStaleManifestLock(lockDir);\n if (Date.now() >= deadline) {\n throw new Error(`Timed out waiting for spaces manifest lock: ${lockDir}`);\n }\n sleepSync(MANIFEST_LOCK_SLEEP_MS);\n }\n }\n}\n\nfunction releaseManifestLock(lockDir: string, owner: string): void {\n try {\n const ownerPath = path.join(lockDir, \"owner\");\n if (fs.readFileSync(ownerPath, \"utf8\").trim() === owner) {\n fs.rmSync(lockDir, { recursive: true, force: true });\n }\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n }\n}\n\nfunction removeStaleManifestLock(lockDir: string): void {\n const reclaimDir = getManifestLockReclaimDir(lockDir);\n const reclaimOwner = createManifestLockOwner();\n try {\n fs.mkdirSync(reclaimDir, { recursive: false });\n try {\n fs.writeFileSync(path.join(reclaimDir, \"owner\"), `${reclaimOwner}\\n`, { flag: \"wx\" });\n } catch (error) {\n fs.rmSync(reclaimDir, { recursive: true, force: true });\n throw error;\n }\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"EEXIST\") {\n return;\n }\n throw error;\n }\n\n try {\n const snapshot = readManifestLockSnapshot(lockDir);\n if (!snapshot || Date.now() - snapshot.mtimeMs <= MANIFEST_LOCK_STALE_MS) {\n return;\n }\n\n if (isManifestLockOwnerActive(snapshot.owner)) {\n return;\n }\n\n const tombstoneDir = `${lockDir}.stale.${process.pid}.${crypto.randomUUID()}`;\n try {\n fs.renameSync(lockDir, tombstoneDir);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n return;\n }\n fs.rmSync(tombstoneDir, { recursive: true, force: true });\n } finally {\n fs.rmSync(reclaimDir, { recursive: true, force: true });\n }\n}\n\nfunction getManifestLockReclaimDir(lockDir: string): string {\n return `${lockDir}.reclaim`;\n}\n\nfunction createManifestLockOwner(): string {\n return JSON.stringify({\n pid: process.pid,\n startKey: readProcessStartKey(process.pid),\n token: crypto.randomUUID(),\n });\n}\n\nfunction removeStaleManifestReclaimLock(reclaimDir: string): void {\n const snapshot = readManifestLockSnapshot(reclaimDir);\n if (!snapshot || Date.now() - snapshot.mtimeMs <= MANIFEST_LOCK_STALE_MS) {\n return;\n }\n\n if (isManifestLockOwnerActive(snapshot.owner)) {\n return;\n }\n\n const tombstoneDir = `${reclaimDir}.stale.${process.pid}.${crypto.randomUUID()}`;\n try {\n fs.renameSync(reclaimDir, tombstoneDir);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code !== \"ENOENT\") {\n throw error;\n }\n return;\n }\n fs.rmSync(tombstoneDir, { recursive: true, force: true });\n}\n\nfunction readManifestLockSnapshot(lockDir: string): { mtimeMs: number; owner?: string } | undefined {\n let stat: fs.Stats;\n try {\n stat = fs.statSync(lockDir);\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return undefined;\n }\n throw error;\n }\n\n try {\n const owner = fs.readFileSync(path.join(lockDir, \"owner\"), \"utf8\").trim();\n return { mtimeMs: stat.mtimeMs, owner };\n } catch (error) {\n if ((error as NodeJS.ErrnoException).code === \"ENOENT\") {\n return { mtimeMs: stat.mtimeMs };\n }\n throw error;\n }\n}\n\nfunction isManifestLockOwnerActive(owner: string | undefined): boolean {\n if (!owner) {\n return false;\n }\n\n const parsed = parseManifestLockOwner(owner);\n if (!parsed) {\n return false;\n }\n\n const currentStartKey = readProcessStartKey(parsed.pid);\n if (currentStartKey && parsed.startKey) {\n return currentStartKey === parsed.startKey;\n }\n\n return isProcessAlive(parsed.pid);\n}\n\nfunction parseManifestLockOwner(owner: string): { pid: number; startKey?: string } | undefined {\n try {\n const parsed = JSON.parse(owner) as { pid?: unknown; startKey?: unknown };\n const pid = typeof parsed.pid === \"number\" ? parsed.pid : Number.NaN;\n if (Number.isInteger(pid) && pid > 0) {\n return {\n pid,\n startKey: typeof parsed.startKey === \"string\" && parsed.startKey.length > 0 ? parsed.startKey : undefined,\n };\n }\n } catch {\n // Fall through to legacy owner format.\n }\n\n const legacyPid = Number(owner.split(\":\", 1)[0]);\n return Number.isInteger(legacyPid) && legacyPid > 0 ? { pid: legacyPid } : undefined;\n}\n\nfunction readProcessStartKey(pid: number): string | undefined {\n if (!Number.isInteger(pid) || pid <= 0) {\n return undefined;\n }\n\n const result = spawnSync(\"ps\", [\"-p\", String(pid), \"-o\", \"lstart=\"], {\n encoding: \"utf8\",\n stdio: [\"ignore\", \"pipe\", \"ignore\"],\n });\n if (result.error || result.status !== 0 || typeof result.stdout !== \"string\") {\n return undefined;\n }\n const startKey = result.stdout.trim().replace(/\\s+/g, \" \");\n return startKey.length > 0 ? startKey : undefined;\n}\n\nfunction isProcessAlive(pid: number): boolean {\n if (pid === process.pid) {\n return true;\n }\n\n try {\n process.kill(pid, 0);\n return true;\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code === \"ESRCH\") {\n return false;\n }\n return true;\n }\n}\n\nfunction sleepSync(ms: number): void {\n Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, ms);\n}\n\nfunction createPersonalSpace(baseDir?: string, memoryDirOverride?: string): Space {\n const homeDir = baseDir ?? resolveHomeDir();\n // Priority: override > REMNIC_MEMORY_DIR > ENGRAM_MEMORY_DIR > existing standalone dir > existing OpenClaw dir > new standalone dir\n const standalonePath = path.join(homeDir, \".engram\", \"memory\");\n const openclawPath = path.join(homeDir, \".openclaw\", \"workspace\", \"memory\", \"local\");\n const memoryDir =\n memoryDirOverride ??\n readEnvVar(\"REMNIC_MEMORY_DIR\") ??\n readEnvVar(\"ENGRAM_MEMORY_DIR\") ??\n (fs.existsSync(standalonePath) ? standalonePath : fs.existsSync(openclawPath) ? openclawPath : standalonePath);\n const normalizedMemoryDir = normalizeSpaceMemoryDir(memoryDir);\n const now = new Date().toISOString();\n\n return {\n id: \"personal\",\n name: \"Personal\",\n kind: \"personal\",\n description: \"Default personal memory space\",\n memoryDir: normalizedMemoryDir,\n createdAt: now,\n updatedAt: now,\n owner: readEnvVar(\"USER\"),\n };\n}\n\n// ── Space CRUD ──────────────────────────────────────────────────────────────\n\nexport function listSpaces(baseDir?: string): Space[] {\n const manifest = loadManifest(baseDir);\n return manifest.spaces;\n}\n\nexport function getActiveSpace(baseDir?: string): Space {\n const manifest = loadManifest(baseDir);\n const space = manifest.spaces.find((s) => s.id === manifest.activeSpaceId);\n if (!space) throw new Error(`Active space ${manifest.activeSpaceId} not found`);\n return space;\n}\n\nexport function createSpace(options: {\n name: string;\n kind: SpaceKind;\n description?: string;\n memoryDir?: string;\n parentSpaceId?: string;\n baseDir?: string;\n}): Space {\n const id = options.name\n .toLowerCase()\n .replace(/[^a-z0-9-]/g, \"-\")\n .replace(/-+/g, \"-\");\n const now = new Date().toISOString();\n const memoryDir = normalizeSpaceMemoryDir(\n options.memoryDir ?? path.join(getSpacesDir(options.baseDir), id, \"memory\")\n );\n\n const space = updateManifest(options.baseDir, (manifest) => {\n if (manifest.spaces.some((s) => s.id === id)) {\n throw new Error(`Space \"${id}\" already exists`);\n }\n\n // Validate parent space exists\n if (options.parentSpaceId && !manifest.spaces.some((s) => s.id === options.parentSpaceId)) {\n throw new Error(`Parent space \"${options.parentSpaceId}\" not found`);\n }\n\n const created: Space = {\n id,\n name: options.name,\n kind: options.kind,\n description: options.description,\n memoryDir,\n createdAt: now,\n updatedAt: now,\n owner: readEnvVar(\"USER\"),\n parentSpaceId: options.parentSpaceId,\n };\n\n // Ensure memory directory exists before publishing the manifest entry.\n fs.mkdirSync(memoryDir, { recursive: true });\n\n manifest.spaces.push(created);\n manifest.updatedAt = now;\n return created;\n });\n\n // Audit\n appendAudit(\n {\n action: \"space.create\",\n sourceSpaceId: id,\n details: `Created ${options.kind} space \"${options.name}\"`,\n },\n options.baseDir\n );\n\n return space;\n}\n\nexport function deleteSpace(spaceId: string, baseDir?: string): void {\n if (spaceId === \"personal\") {\n throw new Error(\"Cannot delete the personal space\");\n }\n\n updateManifest(baseDir, (manifest) => {\n const idx = manifest.spaces.findIndex((s) => s.id === spaceId);\n if (idx === -1) throw new Error(`Space \"${spaceId}\" not found`);\n\n // If deleting active space, switch to personal\n if (manifest.activeSpaceId === spaceId) {\n manifest.activeSpaceId = \"personal\";\n }\n\n // Clear parentSpaceId references from children\n for (const space of manifest.spaces) {\n if (space.parentSpaceId === spaceId) {\n space.parentSpaceId = undefined;\n }\n }\n\n manifest.spaces.splice(idx, 1);\n });\n\n appendAudit(\n {\n action: \"space.delete\",\n sourceSpaceId: spaceId,\n details: `Deleted space \"${spaceId}\"`,\n },\n baseDir\n );\n}\n\n// ── Switch ───────────────────────────────────────────────────────────────────\n\nexport function switchSpace(spaceId: string, baseDir?: string): SpaceSwitchResult {\n const { previousId, spaceName } = updateManifest(baseDir, (manifest) => {\n const space = manifest.spaces.find((s) => s.id === spaceId);\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n const previousId = manifest.activeSpaceId;\n manifest.activeSpaceId = spaceId;\n return { previousId, spaceName: space.name };\n });\n\n appendAudit(\n {\n action: \"space.switch\",\n sourceSpaceId: previousId,\n targetSpaceId: spaceId,\n details: `Switched from \"${previousId}\" to \"${spaceId}\"`,\n },\n baseDir\n );\n\n return {\n previousSpaceId: previousId,\n currentSpaceId: spaceId,\n message: `Switched to \"${spaceName}\"`,\n };\n}\n\n// ── Push / Pull ─────────────────────────────────────────────────────────────\n\nexport function pushToSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string }\n): SpacePushResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit(\n {\n action: \"space.push\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pushed ${result.merged} memories, ${result.conflicts.length} conflicts`,\n },\n options?.baseDir\n );\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPushed: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\nexport function pullFromSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; baseDir?: string }\n): SpacePullResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.force,\n });\n\n appendAudit(\n {\n action: \"space.pull\",\n sourceSpaceId,\n targetSpaceId,\n details: `Pulled ${result.merged} memories, ${result.conflicts.length} conflicts`,\n },\n options?.baseDir\n );\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPulled: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Share ────────────────────────────────────────────────────────────────────\n\nexport function shareSpace(spaceId: string, members: string[], baseDir?: string): SpaceShareResult {\n const spaceName = updateManifest(baseDir, (manifest) => {\n const space = manifest.spaces.find((s) => s.id === spaceId);\n if (!space) throw new Error(`Space \"${spaceId}\" not found`);\n if (space.kind === \"personal\") throw new Error(\"Cannot share personal space\");\n\n space.members = [...new Set([...(space.members ?? []), ...members])];\n space.updatedAt = new Date().toISOString();\n return space.name;\n });\n\n appendAudit(\n {\n action: \"space.share\",\n sourceSpaceId: spaceId,\n details: `Shared with: ${members.join(\", \")}`,\n },\n baseDir\n );\n\n return {\n spaceId,\n sharedWith: members,\n message: `Shared \"${spaceName}\" with ${members.length} member(s)`,\n };\n}\n\n// ── Promote ──────────────────────────────────────────────────────────────────\n\nexport function promoteSpace(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { memoryIds?: string[]; force?: boolean; forceOverwrite?: boolean; baseDir?: string }\n): SpacePromoteResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n // Promotion requires parent-child relationship or explicit force\n if (source.parentSpaceId !== targetSpaceId && target.parentSpaceId !== sourceSpaceId) {\n if (!options?.force) {\n throw new Error(\"Spaces must have a parent-child relationship for promotion. Use --force to override.\");\n }\n }\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n filterIds: options?.memoryIds,\n force: options?.forceOverwrite !== undefined ? options.forceOverwrite : (options?.force ?? false),\n });\n\n appendAudit(\n {\n action: \"space.promote\",\n sourceSpaceId,\n targetSpaceId,\n details: `Promoted ${result.merged} memories from \"${source.name}\" to \"${target.name}\"`,\n },\n options?.baseDir\n );\n\n return {\n sourceSpaceId,\n targetSpaceId,\n memoriesPromoted: result.merged,\n conflicts: result.conflicts,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Merge ────────────────────────────────────────────────────────────────────\n\nexport function mergeSpaces(\n sourceSpaceId: string,\n targetSpaceId: string,\n options?: { force?: boolean; baseDir?: string }\n): MergeResult {\n const startTime = Date.now();\n const manifest = loadManifest(options?.baseDir);\n\n const source = manifest.spaces.find((s) => s.id === sourceSpaceId);\n const target = manifest.spaces.find((s) => s.id === targetSpaceId);\n\n if (!source) throw new Error(`Source space \"${sourceSpaceId}\" not found`);\n if (!target) throw new Error(`Target space \"${targetSpaceId}\" not found`);\n\n const result = copyMemories(source.memoryDir, target.memoryDir, {\n force: options?.force,\n });\n\n appendAudit(\n {\n action: \"space.merge\",\n sourceSpaceId,\n targetSpaceId,\n details: `Merged: ${result.merged} merged, ${result.conflicts.length} conflicts, ${result.skipped} skipped`,\n },\n options?.baseDir\n );\n\n return {\n ...result,\n durationMs: Date.now() - startTime,\n };\n}\n\n// ── Audit trail ─────────────────────────────────────────────────────────────\n\nexport function getAuditLog(baseDir?: string): AuditEntry[] {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n if (!fs.existsSync(auditPath)) return [];\n\n const lines = fs.readFileSync(auditPath, \"utf8\").trim().split(\"\\n\");\n return lines.filter((l) => l.trim()).map((l) => JSON.parse(l) as AuditEntry);\n}\n\nfunction appendAudit(entry: Omit<AuditEntry, \"id\" | \"timestamp\">, baseDir?: string): void {\n const auditPath = path.join(getSpacesDir(baseDir), \"audit.jsonl\");\n fs.mkdirSync(path.dirname(auditPath), { recursive: true });\n\n const full: AuditEntry = {\n id: crypto.randomUUID(),\n timestamp: new Date().toISOString(),\n ...entry,\n };\n\n fs.appendFileSync(auditPath, `${JSON.stringify(full)}\\n`);\n}\n\n// ── Internal helpers ─────────────────────────────────────────────────────────\n\ninterface CopyOptions {\n filterIds?: string[];\n force?: boolean;\n}\n\nfunction copyMemories(\n sourceDir: string,\n targetDir: string,\n options?: CopyOptions\n): { merged: number; conflicts: ConflictEntry[]; skipped: number } {\n let merged = 0;\n const conflicts: ConflictEntry[] = [];\n let skipped = 0;\n\n if (!fs.existsSync(sourceDir)) {\n return { merged: 0, conflicts: [], skipped: 0 };\n }\n\n const sourceRoot = fs.realpathSync(sourceDir);\n fs.mkdirSync(targetDir, { recursive: true });\n const targetRoot = fs.realpathSync(targetDir);\n\n const sourceFiles = walkMd(sourceRoot);\n for (const sourcePath of sourceFiles) {\n const sourceRealPath = safeRealpath(sourcePath);\n if (!sourceRealPath || !isPathInsideRoot(sourceRealPath, sourceRoot)) {\n skipped++;\n continue;\n }\n const sourceStat = safeLstat(sourcePath);\n if (!sourceStat?.isFile()) {\n skipped++;\n continue;\n }\n const content = fs.readFileSync(sourcePath, \"utf8\");\n const relativePath = path.relative(sourceRoot, sourceRealPath);\n const targetPath = path.resolve(targetRoot, relativePath);\n if (!isPathInsideRoot(targetPath, targetRoot)) {\n skipped++;\n continue;\n }\n\n const sourceHash = hashContent(content);\n\n // Filter by IDs if specified\n if (options?.filterIds?.length) {\n const fm = parseSimpleFrontmatter(content);\n if (!fm?.id || !options.filterIds.includes(fm.id)) {\n skipped++;\n continue;\n }\n }\n\n // Check for conflict\n if (fs.existsSync(targetPath)) {\n const targetStat = safeLstat(targetPath);\n if (!targetStat?.isFile() || targetStat.isSymbolicLink()) {\n skipped++;\n continue;\n }\n const targetRealPath = safeRealpath(targetPath);\n if (!targetRealPath || !isPathInsideRoot(targetRealPath, targetRoot)) {\n skipped++;\n continue;\n }\n }\n\n if (fs.existsSync(targetPath) && !options?.force) {\n const targetContent = fs.readFileSync(targetPath, \"utf8\");\n const targetHash = hashContent(targetContent);\n\n if (sourceHash !== targetHash) {\n conflicts.push({\n memoryId: parseSimpleFrontmatter(content)?.id ?? relativePath,\n sourcePath,\n targetPath,\n conflictType: \"content_mismatch\",\n sourceHash,\n targetHash,\n });\n continue;\n }\n\n // Same content — skip\n skipped++;\n continue;\n }\n\n // Copy file\n fs.mkdirSync(path.dirname(targetPath), { recursive: true });\n const targetParentRealPath = safeRealpath(path.dirname(targetPath));\n if (!targetParentRealPath || !isPathInsideRoot(targetParentRealPath, targetRoot)) {\n skipped++;\n continue;\n }\n fs.writeFileSync(targetPath, content);\n merged++;\n }\n\n return { merged, conflicts, skipped };\n}\n\nfunction hashContent(content: string): string {\n return crypto.createHash(\"sha256\").update(content).digest(\"hex\").slice(0, 16);\n}\n\nfunction walkMd(dir: string): string[] {\n const results: string[] = [];\n\n function walk(d: string): void {\n for (const entry of fs.readdirSync(d, { withFileTypes: true })) {\n const fullPath = path.join(d, entry.name);\n if (entry.isSymbolicLink()) {\n continue;\n }\n if (entry.isDirectory()) {\n walk(fullPath);\n } else if (entry.name.endsWith(\".md\")) {\n results.push(fullPath);\n }\n }\n }\n\n walk(dir);\n return results;\n}\n\nfunction safeLstat(filePath: string): fs.Stats | null {\n try {\n return fs.lstatSync(filePath);\n } catch {\n return null;\n }\n}\n\nfunction safeRealpath(filePath: string): string | null {\n try {\n return fs.realpathSync(filePath);\n } catch {\n return null;\n }\n}\n\nfunction isPathInsideRoot(candidatePath: string, rootPath: string): boolean {\n const relative = path.relative(rootPath, candidatePath);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\ninterface SimpleFrontmatter {\n id?: string;\n [key: string]: string | undefined;\n}\n\nfunction parseSimpleFrontmatter(content: string): SimpleFrontmatter | null {\n const match = content.match(/^---\\n([\\s\\S]*?)\\n---/);\n if (!match) return null;\n\n const fm: SimpleFrontmatter = {};\n for (const line of match[1].split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n const key = line.slice(0, colonIdx).trim();\n const value = line.slice(colonIdx + 1).trim();\n fm[key] = value;\n }\n return fm;\n}\n","/**\n * @remnic/core — Shared Instruction Blocks\n *\n * Reusable markdown fragments that every host-specific publisher can\n * compose into its instructions.md file. Keeping them here avoids\n * per-host copy-paste drift.\n */\n\n/**\n * Describes the Remnic memory types a host agent may encounter.\n */\nexport const REMNIC_SEMANTIC_OVERVIEW = `\\\n## Remnic Memory Types\n\nRemnic stores memories as plain Markdown files with YAML front-matter.\nEach memory has a **type** that describes its semantic role:\n\n| Type | Description |\n|------|-------------|\n| \\`fact\\` | An objective piece of knowledge the user confirmed or that was extracted from a session. |\n| \\`preference\\` | A stated or inferred user preference (e.g. coding style, tool choice). |\n| \\`decision\\` | An explicit decision or trade-off the user made. |\n| \\`entity\\` | A named thing the user cares about (project, service, person, API). |\n| \\`skill\\` | A reusable workflow or procedure documented for future sessions. |\n| \\`correction\\` | A fix or amendment to a previously stored memory. |\n| \\`question\\` | An open question or uncertainty flagged for future resolution. |\n| \\`observation\\` | A pattern noticed across sessions (e.g. \"user always runs tests before commits\"). |\n| \\`summary\\` | A condensed roll-up of recent sessions or a topic area. |\n\nWhen reading Remnic content, the front-matter \\`type\\` field tells you what\nkind of knowledge you are looking at and how much weight to give it.\n`;\n\n/**\n * Explains the oai-mem-citation block format hosts should use when\n * referencing Remnic-sourced content.\n */\nexport const REMNIC_CITATION_FORMAT = `\\\n## Citing Remnic Memories\n\nWhen a piece of your output draws on a Remnic file, cite it using the\nmemory citation block format so the user can trace the source:\n\n\\`\\`\\`\n<oai-mem-citation path=\"<path-relative-to-remnic-memory-base>\" />\n\\`\\`\\`\n\nThe path must be **relative to the Remnic memory base** (the directory\nnamed \\`memories/\\` under \\`<remnic-home>\\`), not absolute. Examples:\n\n- \\`<oai-mem-citation path=\"default/MEMORY.md\" />\\`\n- \\`<oai-mem-citation path=\"my-project/skills/deploy/SKILL.md\" />\\`\n- \\`<oai-mem-citation path=\"shared/memory_summary.md\" />\\`\n\nCite each distinct source once near the fact it supports. Do not invent\ncitations for files you have not actually read.\n`;\n\n/**\n * Table of MCP tools the Remnic daemon exposes. Hosts that can reach\n * the MCP server should prefer these over raw file reads.\n *\n * Tool names use the canonical `remnic.*` prefix. Legacy `engram.*`\n * aliases are also accepted by the server for backward compatibility.\n */\nexport const REMNIC_MCP_TOOL_INVENTORY = `\\\n## Remnic MCP Tools\n\nWhen the Remnic MCP server is reachable, the following tools are\navailable. Prefer MCP tools over direct file reads when the host\nsupports MCP connections.\n\n| Tool | Purpose |\n|------|---------|\n| \\`remnic.recall\\` | Retrieve contextually relevant memories for the current session. |\n| \\`remnic.recall_explain\\` | Like recall, but includes an explanation of why each memory was selected. |\n| \\`remnic.memory_store\\` | Persist a new memory (fact, preference, decision, etc.). |\n| \\`remnic.memory_get\\` | Fetch a specific memory by ID. |\n| \\`remnic.memory_search\\` | Full-text + semantic search across all memories. |\n| \\`remnic.memory_timeline\\` | Retrieve memories in chronological order within a time range. |\n| \\`remnic.observe\\` | Record an observation from the current conversation turn. |\n| \\`remnic.entity_get\\` | Look up a named entity and its relationships. |\n| \\`remnic.memory_entities_list\\` | List all known entities. |\n| \\`remnic.memory_profile\\` | Retrieve the user profile summary. |\n| \\`remnic.day_summary\\` | Generate a summary of memories from a specific day. |\n| \\`remnic.briefing\\` | Generate a structured briefing for an upcoming session. |\n| \\`remnic.memory_feedback\\` | Submit feedback on a recalled memory (useful, outdated, wrong). |\n| \\`remnic.memory_promote\\` | Promote a memory to a higher confidence tier. |\n| \\`remnic.context_checkpoint\\` | Save a conversation checkpoint for continuity. |\n| \\`remnic.suggestion_submit\\` | Submit a suggestion for a new memory to the review queue. |\n| \\`remnic.review_queue_list\\` | List pending suggestions in the review queue. |\n| \\`remnic.work_task\\` | Create or update a work task. |\n| \\`remnic.work_project\\` | Create or update a work project. |\n| \\`remnic.work_board\\` | View the work board. |\n\nLegacy \\`engram.*\\` prefixed names are accepted as aliases for all tools.\n`;\n\n/**\n * Decision rules for when a host agent should use MCP recall vs\n * reading Remnic files directly from disk.\n */\nexport const REMNIC_RECALL_DECISION_RULES = `\\\n## When to Use Recall vs Direct Read\n\n### Use \\`remnic.recall\\` (MCP) when:\n\n- The Remnic MCP server is reachable (the host has an active MCP\n connection to the Remnic daemon).\n- You want contextually relevant memories ranked by the recall planner\n (semantic search + reranking + importance scoring).\n- You need memories across multiple namespaces or topics.\n- The conversation benefits from Remnic's intent detection and\n adaptive recall depth.\n\n### Use direct file reads when:\n\n- You are in a sandboxed environment with no network or MCP access\n (e.g. Codex phase-2 consolidation).\n- You need a specific file you already know the path to.\n- The MCP server is unavailable or unhealthy.\n- You are operating on the raw memory files for maintenance or\n migration purposes.\n\n### General guidance:\n\n- Prefer MCP tools when available — they provide ranked, deduplicated,\n and context-aware results.\n- Fall back to file reads gracefully — never block on a failed MCP call\n when the data is also on disk.\n- Never write directly to the Remnic memory directory unless you are an\n authorized extraction or consolidation process.\n`;\n","/**\n * @remnic/core — Codex Memory Extension Publisher\n *\n * Writes Remnic instructions into ~/.codex/memories_extensions/remnic/\n * so the Codex agent can discover and use Remnic memories during its\n * consolidation phase.\n */\n\nimport fs from \"node:fs\";\nimport os from \"node:os\";\nimport path from \"node:path\";\n\nimport type {\n MemoryExtensionPublisher,\n PublishContext,\n PublishResult,\n PublisherCapabilities,\n} from \"./types.js\";\n\nimport {\n REMNIC_SEMANTIC_OVERVIEW,\n REMNIC_CITATION_FORMAT,\n REMNIC_MCP_TOOL_INVENTORY,\n REMNIC_RECALL_DECISION_RULES,\n} from \"./shared-instructions.js\";\nimport { readEnvVar, resolveHomeDir } from \"../runtime/env.js\";\n\n/** Folder name Remnic installs its extension under inside memories_extensions/. */\nconst REMNIC_EXTENSION_DIR_NAME = \"remnic\";\n\nfunction resolveEnvHome(env?: NodeJS.ProcessEnv): string {\n if (env === undefined) return resolveHomeDir();\n return env.HOME?.trim() || env.USERPROFILE?.trim() || os.homedir();\n}\n\nfunction expandTildeWithHome(input: string, homeDir: string): string {\n if (input === \"~\") return homeDir;\n if (input.startsWith(\"~/\") || input.startsWith(\"~\\\\\")) {\n return path.join(homeDir, input.slice(2));\n }\n return input;\n}\n\nfunction normalizeHostRoot(input: string, homeDir: string): string {\n return path.resolve(expandTildeWithHome(input.trim(), homeDir));\n}\n\n/**\n * Codex-specific publisher that knows the Codex extension layout:\n * ~/.codex/memories_extensions/remnic/instructions.md\n */\nexport class CodexMemoryExtensionPublisher implements MemoryExtensionPublisher {\n readonly hostId = \"codex\";\n\n static readonly capabilities: PublisherCapabilities = {\n isStub: false,\n instructionsMd: true,\n skillsFolder: false,\n citationFormat: true,\n readPathTemplate: true,\n };\n\n async resolveExtensionRoot(\n env?: NodeJS.ProcessEnv,\n ): Promise<string> {\n const homeDir = resolveEnvHome(env);\n const codexHomeInput = env === undefined\n ? readEnvVar(\"CODEX_HOME\")?.trim()\n : env.CODEX_HOME?.trim();\n const codexHome = codexHomeInput\n ? normalizeHostRoot(codexHomeInput, homeDir)\n : path.resolve(homeDir, \".codex\");\n return path.join(codexHome, \"memories_extensions\", REMNIC_EXTENSION_DIR_NAME);\n }\n\n async isHostAvailable(): Promise<boolean> {\n try {\n const home = readEnvVar(\"CODEX_HOME\")?.trim() ||\n path.join(resolveHomeDir(), \".codex\");\n return fs.existsSync(home);\n } catch {\n return false;\n }\n }\n\n async renderInstructions(ctx: PublishContext): Promise<string> {\n const memDir = ctx.config.memoryDir;\n const ns = ctx.config.namespace ?? \"default\";\n\n const sections: string[] = [\n `# Remnic Memory Extension for Codex\\n`,\n `This document tells you how to use Remnic as an authoritative local ` +\n `memory source. Remnic is a local-first, file-backed memory system. ` +\n `All Remnic content lives on disk as plain Markdown.\\n`,\n REMNIC_SEMANTIC_OVERVIEW,\n `## Where Remnic Content Lives\\n\\n` +\n `Memory base directory: \\`${memDir}\\`\\n\\n` +\n `Namespace: \\`${ns}\\`\\n\\n` +\n `Under the base directory, memories are organized by namespace:\\n\\n` +\n \"```\\n\" +\n `${memDir}/<namespace>/\\n` +\n ` MEMORY.md # compact top-of-mind memory\\n` +\n ` memory_summary.md # optional longer summary\\n` +\n ` skills/\\n` +\n ` <skill-name>/SKILL.md # reusable workflows\\n` +\n ` rollout_summaries/\\n` +\n ` *.md # per-session rollup notes\\n` +\n \"```\\n\",\n REMNIC_CITATION_FORMAT,\n REMNIC_MCP_TOOL_INVENTORY,\n REMNIC_RECALL_DECISION_RULES,\n `## Sandboxing Rules (Codex Phase-2)\\n\\n` +\n `When running inside the Codex phase-2 consolidation sandbox:\\n\\n` +\n `- **No network.** Do not attempt HTTP calls or MCP connections.\\n` +\n `- **No CLI invocation.** Do not shell out to \\`remnic\\` or \\`engram\\`.\\n` +\n `- **No MCP tool calls.** Use filesystem reads only.\\n` +\n `- **Local writes** are allowed only where Codex's sandbox policy permits.\\n` +\n `- **Respect missing files.** If a file does not exist, move on silently.\\n`,\n ];\n\n return sections.join(\"\\n\");\n }\n\n async publish(ctx: PublishContext): Promise<PublishResult> {\n const extensionRoot = await this.resolveExtensionRoot();\n const instructionsPath = path.join(extensionRoot, \"instructions.md\");\n const filesWritten: string[] = [];\n const skipped: string[] = [];\n\n ctx.log.info(`Publishing Codex memory extension to ${extensionRoot}`);\n\n // Ensure the extension root exists.\n fs.mkdirSync(extensionRoot, { recursive: true });\n\n // Render and write instructions.md using atomic write (temp + rename).\n // Per CLAUDE.md #54: never delete before write in file replace operations.\n const content = await this.renderInstructions(ctx);\n const tmpPath = `${instructionsPath}.tmp-${process.pid}-${Date.now()}`;\n\n try {\n fs.writeFileSync(tmpPath, content, \"utf-8\");\n fs.renameSync(tmpPath, instructionsPath);\n filesWritten.push(instructionsPath);\n ctx.log.info(`Wrote ${instructionsPath}`);\n } catch (err) {\n // Clean up temp file on failure.\n try {\n if (fs.existsSync(tmpPath)) {\n fs.unlinkSync(tmpPath);\n }\n } catch {\n // swallow cleanup error\n }\n throw err;\n }\n\n return {\n hostId: this.hostId,\n extensionRoot,\n filesWritten,\n skipped,\n };\n }\n\n async unpublish(): Promise<void> {\n const extensionRoot = await this.resolveExtensionRoot();\n if (fs.existsSync(extensionRoot)) {\n fs.rmSync(extensionRoot, { recursive: true, force: true });\n }\n }\n}\n","/**\n * @remnic/core — Claude Code Memory Extension Publisher (stub)\n *\n * Placeholder publisher for Claude Code. Claude Code does not yet\n * support a file-based memory extension directory, so all methods are\n * no-ops that return safe defaults.\n */\n\nimport type {\n MemoryExtensionPublisher,\n PublishContext,\n PublishResult,\n PublisherCapabilities,\n} from \"./types.js\";\n\nexport class ClaudeCodeMemoryExtensionPublisher implements MemoryExtensionPublisher {\n readonly hostId = \"claude-code\";\n\n static readonly capabilities: PublisherCapabilities = {\n isStub: true,\n instructionsMd: false,\n skillsFolder: false,\n citationFormat: false,\n readPathTemplate: false,\n };\n\n async resolveExtensionRoot(): Promise<string> {\n // Claude Code does not have an extension directory yet.\n return \"\";\n }\n\n async isHostAvailable(): Promise<boolean> {\n return false;\n }\n\n async renderInstructions(_ctx: PublishContext): Promise<string> {\n return \"\";\n }\n\n async publish(_ctx: PublishContext): Promise<PublishResult> {\n return {\n hostId: this.hostId,\n extensionRoot: \"\",\n filesWritten: [],\n skipped: [],\n };\n }\n\n async unpublish(): Promise<void> {\n // no-op\n }\n}\n","/**\n * @remnic/core — Hermes Memory Extension Publisher (stub)\n *\n * Placeholder publisher for Hermes. Hermes uses a daemon-based\n * transport and does not currently consume file-based memory\n * extensions, so all methods are no-ops.\n */\n\nimport type {\n MemoryExtensionPublisher,\n PublishContext,\n PublishResult,\n PublisherCapabilities,\n} from \"./types.js\";\n\nexport class HermesMemoryExtensionPublisher implements MemoryExtensionPublisher {\n readonly hostId = \"hermes\";\n\n static readonly capabilities: PublisherCapabilities = {\n isStub: true,\n instructionsMd: false,\n skillsFolder: false,\n citationFormat: false,\n readPathTemplate: false,\n };\n\n async resolveExtensionRoot(): Promise<string> {\n // Hermes does not have an extension directory.\n return \"\";\n }\n\n async isHostAvailable(): Promise<boolean> {\n return false;\n }\n\n async renderInstructions(_ctx: PublishContext): Promise<string> {\n return \"\";\n }\n\n async publish(_ctx: PublishContext): Promise<PublishResult> {\n return {\n hostId: this.hostId,\n extensionRoot: \"\",\n filesWritten: [],\n skipped: [],\n };\n }\n\n async unpublish(): Promise<void> {\n // no-op\n }\n}\n","/**\n * @remnic/core — Memory Extension Publisher Registry\n *\n * Generic registry that host adapters populate at startup via\n * `registerPublisher()`. The publisher *classes* live in core so\n * adapters can import them, but the wiring of host-specific\n * implementations into the registry happens in the host adapter\n * layer (e.g. @remnic/cli), not here. This keeps core free of\n * host-specific knowledge (CLAUDE.md gotcha #31).\n *\n * Usage (from a host adapter):\n * import { registerPublisher, CodexMemoryExtensionPublisher } from \"@remnic/core\";\n * registerPublisher(\"codex\", () => new CodexMemoryExtensionPublisher());\n */\n\nexport type {\n MemoryExtensionPublisher,\n PublishContext,\n PublishResult,\n PublisherCapabilities,\n} from \"./types.js\";\n\nexport {\n REMNIC_SEMANTIC_OVERVIEW,\n REMNIC_CITATION_FORMAT,\n REMNIC_MCP_TOOL_INVENTORY,\n REMNIC_RECALL_DECISION_RULES,\n} from \"./shared-instructions.js\";\n\nexport { CodexMemoryExtensionPublisher } from \"./codex-publisher.js\";\nexport { ClaudeCodeMemoryExtensionPublisher } from \"./claude-code-publisher.js\";\nexport { HermesMemoryExtensionPublisher } from \"./hermes-publisher.js\";\n\nimport type { MemoryExtensionPublisher } from \"./types.js\";\n\n/**\n * Factory registry keyed by host ID. Each value is a zero-argument\n * factory that returns a fresh publisher instance.\n *\n * Starts empty — host adapters populate it via registerPublisher().\n */\nexport const PUBLISHERS: Record<string, () => MemoryExtensionPublisher> = {};\n\n/**\n * Register a publisher factory for a given host ID.\n *\n * Host adapters call this at startup to wire their host-specific\n * publisher implementations into the registry. Calling with an\n * existing hostId replaces the previous factory.\n */\nexport function registerPublisher(\n hostId: string,\n factory: () => MemoryExtensionPublisher,\n): void {\n PUBLISHERS[hostId] = factory;\n}\n\n/**\n * Maps connector IDs to publisher host IDs.\n *\n * Most connector IDs match their publisher host ID exactly (e.g.\n * \"claude-code\" -> \"claude-code\", \"hermes\" -> \"hermes\").\n * This map only needs entries for connector IDs that differ from\n * their publisher host ID. Connectors without a publisher (e.g.\n * \"cursor\", \"cline\") are intentionally absent.\n */\nconst CONNECTOR_TO_HOST: Record<string, string> = {\n \"codex-cli\": \"codex\",\n};\n\n/**\n * Resolve a connector ID to its publisher host ID.\n *\n * Returns the explicit mapping if one exists, otherwise returns\n * the connector ID itself (identity mapping covers the common case\n * where connector ID === host ID).\n */\nexport function hostIdForConnector(connectorId: string): string {\n return CONNECTOR_TO_HOST[connectorId] ?? connectorId;\n}\n\n/**\n * Look up a publisher by host ID.\n * Returns undefined for unknown host IDs rather than throwing.\n */\nexport function publisherFor(hostId: string): MemoryExtensionPublisher | undefined {\n const factory = PUBLISHERS[hostId];\n return factory ? factory() : undefined;\n}\n\n/**\n * Look up a publisher by connector ID.\n *\n * Resolves the connector ID to its host ID first (e.g. \"codex-cli\" -> \"codex\"),\n * then looks up the publisher. Returns undefined if no publisher exists for\n * the resolved host ID.\n */\nexport function publisherForConnector(connectorId: string): MemoryExtensionPublisher | undefined {\n return publisherFor(hostIdForConnector(connectorId));\n}\n","import { createHash } from \"node:crypto\";\nimport { lstat, mkdir, readFile, readdir, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nimport { expandTildePath } from \"../utils/path.js\";\nimport { getLocalSessionSourceAdapter, listLocalSessionSourceAdapters } from \"./adapters.js\";\nimport { compileRedactionRules, redactSessionSummaryText } from \"./redaction.js\";\nimport type {\n CollectLocalSessionSummariesOptions,\n CompiledRedactionRule,\n LocalSessionRole,\n LocalSessionSummaryCliOptions,\n LocalSessionSummaryReport,\n LocalSessionTurn,\n RedactionConfig,\n SessionSummaryDraft,\n SessionSummaryExcerpt,\n} from \"./types.js\";\n\nexport * from \"./adapters.js\";\nexport * from \"./redaction.js\";\nexport * from \"./types.js\";\n\nconst DEFAULT_MAX_FILES = 5000;\nconst DEFAULT_MAX_SESSIONS = 500;\nconst SUPPORTED_EXTENSIONS = new Set([\".json\", \".jsonl\"]);\n\nfunction shortHash(value: string, length = 16): string {\n return createHash(\"sha256\").update(value).digest(\"hex\").slice(0, length);\n}\n\nasync function listTranscriptFiles(root: string, maxFiles: number): Promise<{ files: string[]; truncated: boolean }> {\n const out: string[] = [];\n let truncated = false;\n const entrySortKey = (entryName: string, isDirectory: boolean): string => (isDirectory ? `${entryName}${path.sep}` : entryName);\n async function visit(dir: string): Promise<void> {\n if (truncated) return;\n const entries = (await readdir(dir, { withFileTypes: true })).sort((a, b) =>\n entrySortKey(a.name, a.isDirectory()).localeCompare(entrySortKey(b.name, b.isDirectory()))\n );\n for (const entry of entries) {\n if (truncated) return;\n if (entry.name.startsWith(\".\")) continue;\n if (entry.isSymbolicLink()) continue;\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n await visit(fullPath);\n continue;\n }\n if (!entry.isFile()) continue;\n const ext = path.extname(entry.name).toLowerCase();\n if (!SUPPORTED_EXTENSIONS.has(ext)) continue;\n out.push(fullPath);\n if (out.length > maxFiles) {\n truncated = true;\n return;\n }\n }\n }\n await visit(root);\n const sorted = out.sort();\n return {\n files: sorted.slice(0, maxFiles),\n truncated,\n };\n}\n\nfunction validatePositiveInt(value: number | undefined, name: string, defaultValue: number): number {\n if (value === undefined) return defaultValue;\n if (!Number.isInteger(value) || value < 1) {\n throw new Error(`${name} must be a positive integer`);\n }\n return value;\n}\n\nfunction normalizeInputDir(inputDir: string): string {\n if (typeof inputDir !== \"string\" || inputDir.trim().length === 0) {\n throw new Error(\"inputDir must be a non-empty string\");\n }\n return path.resolve(expandTildePath(inputDir.trim()));\n}\n\nfunction initRoleCounts(): Record<LocalSessionRole, number> {\n return {\n user: 0,\n assistant: 0,\n tool: 0,\n system: 0,\n other: 0,\n };\n}\n\nfunction safeTimestampSortValue(turn: LocalSessionTurn): number {\n if (!turn.timestamp) return Number.MAX_SAFE_INTEGER;\n const millis = Date.parse(turn.timestamp);\n return Number.isFinite(millis) ? millis : Number.MAX_SAFE_INTEGER;\n}\n\nfunction earliestTurnSortValue(turns: readonly LocalSessionTurn[]): number {\n let earliest = Number.MAX_SAFE_INTEGER;\n for (const turn of turns) {\n const value = safeTimestampSortValue(turn);\n if (value < earliest) earliest = value;\n }\n return earliest;\n}\n\nfunction truncateExcerpt(text: string): string {\n const compact = text.replace(/\\s+/g, \" \").trim();\n return compact.length > 240 ? `${compact.slice(0, 237)}...` : compact;\n}\n\nfunction mergeRuleNames(target: Set<string>, names: readonly string[]): void {\n for (const name of names) target.add(name);\n}\n\nfunction buildDraft(options: {\n source: string;\n sessionKey: string;\n turns: Array<LocalSessionTurn & { fileHash: string; fileExtension: string }>;\n generatedAt: string;\n redactionRules: readonly CompiledRedactionRule[];\n includeRedactedExcerpts: boolean;\n}): SessionSummaryDraft {\n const sortedTurns = [...options.turns].sort((a, b) => safeTimestampSortValue(a) - safeTimestampSortValue(b));\n const roles = initRoleCounts();\n const fileRefs = new Map<string, string>();\n let redactionApplied = 0;\n const redactionRuleNames = new Set<string>();\n const excerpts: SessionSummaryExcerpt[] = [];\n\n for (const turn of sortedTurns) {\n roles[turn.role] += 1;\n fileRefs.set(turn.fileHash, turn.fileExtension);\n const redacted = redactSessionSummaryText(turn.content, options.redactionRules);\n redactionApplied += redacted.report.applied;\n mergeRuleNames(redactionRuleNames, redacted.report.ruleNames);\n if (options.includeRedactedExcerpts && excerpts.length < 5) {\n excerpts.push({\n role: turn.role,\n text: truncateExcerpt(redacted.text),\n ...(turn.timestamp ? { timestamp: turn.timestamp } : {}),\n });\n }\n }\n\n const firstTimestamp = sortedTurns.find((turn) => turn.timestamp)?.timestamp;\n const lastTimestamp = [...sortedTurns].reverse().find((turn) => turn.timestamp)?.timestamp;\n const sourceSessionRef = shortHash(options.sessionKey);\n const sourceFileRefs = [...fileRefs.entries()]\n .sort(([a], [b]) => a.localeCompare(b))\n .map(([hash, extension]) => ({ hash, extension }));\n const dateText = firstTimestamp && lastTimestamp ? ` from ${firstTimestamp} to ${lastTimestamp}` : \"\";\n const summary =\n `Local AI session summary: ${sortedTurns.length} turn(s)` +\n ` (${roles.user} user, ${roles.assistant} assistant, ${roles.tool} tool, ${roles.system} system, ${roles.other} other)` +\n `${dateText}. Raw transcript text, source session keys, and local file paths are not stored.`;\n\n return {\n schemaVersion: 1,\n draftId: shortHash(\n JSON.stringify({\n source: options.source,\n sourceSessionRef,\n firstTimestamp,\n lastTimestamp,\n turnCount: sortedTurns.length,\n }),\n 24\n ),\n generatedAt: options.generatedAt,\n sourceAdapter: options.source,\n sourceSessionRef,\n sourceFileCount: sourceFileRefs.length,\n sourceFileRefs,\n ...(firstTimestamp ? { firstTimestamp } : {}),\n ...(lastTimestamp ? { lastTimestamp } : {}),\n turnCount: sortedTurns.length,\n roles,\n summary,\n redaction: {\n enabled: options.redactionRules.length > 0,\n applied: redactionApplied,\n ruleNames: [...redactionRuleNames].sort(),\n },\n ...(options.includeRedactedExcerpts && excerpts.length > 0 ? { excerpts } : {}),\n metadata: {\n storesRawTranscript: false,\n storesLocalPaths: false,\n storesSourceSessionKey: false,\n },\n };\n}\n\nexport async function collectLocalSessionSummaries(\n options: CollectLocalSessionSummariesOptions\n): Promise<LocalSessionSummaryReport> {\n const inputDir = normalizeInputDir(options.inputDir);\n const inputLstat = await lstat(inputDir);\n if (inputLstat.isSymbolicLink()) {\n throw new Error(`inputDir must not be a symbolic link: ${options.inputDir}`);\n }\n const inputStat = await stat(inputDir);\n if (!inputStat.isDirectory()) {\n throw new Error(`inputDir must be a directory: ${options.inputDir}`);\n }\n\n const source = options.source?.trim() || \"generic-jsonl\";\n const adapter = getLocalSessionSourceAdapter(source);\n if (!adapter) {\n throw new Error(\n `Unknown local session source '${source}'. Valid sources: ${listLocalSessionSourceAdapters().join(\", \")}`\n );\n }\n\n const maxFiles = validatePositiveInt(options.maxFiles, \"maxFiles\", DEFAULT_MAX_FILES);\n const maxSessions = validatePositiveInt(options.maxSessions, \"maxSessions\", DEFAULT_MAX_SESSIONS);\n const redactionConfig = options.redactionConfig ?? {};\n const excerptsRequested = options.includeRedactedExcerpts === true;\n const redactionRules = compileRedactionRules({\n ...redactionConfig,\n ...(excerptsRequested ? { disableDefaults: false } : {}),\n });\n const includeRedactedExcerpts = options.includeRedactedExcerpts === true && redactionRules.length > 0;\n const listed = await listTranscriptFiles(inputDir, maxFiles);\n const files = listed.files;\n const generatedAt = (options.now ?? new Date()).toISOString();\n const warnings: LocalSessionSummaryReport[\"warnings\"] = [];\n const sessions = new Map<string, Array<LocalSessionTurn & { fileHash: string; fileExtension: string }>>();\n const seenFileHashes = new Set<string>();\n let turnsParsed = 0;\n let filesParsed = 0;\n\n if (listed.truncated) {\n warnings.push({\n code: \"session-summaries.max_files_truncated\",\n message: `Scanned the first ${maxFiles} transcript file(s); increase maxFiles to include all matching files.`,\n });\n }\n if (excerptsRequested && redactionConfig.disableDefaults === true) {\n warnings.push({\n code: \"session-summaries.default_redaction_forced_for_excerpts\",\n message: \"Default redaction rules were enabled because redacted excerpts were requested.\",\n });\n }\n if (excerptsRequested && redactionRules.length === 0) {\n warnings.push({\n code: \"session-summaries.excerpts_suppressed_no_redaction\",\n message: \"Redacted excerpts were requested, but no redaction rules are enabled; excerpts were omitted.\",\n });\n }\n\n for (const filePath of files) {\n const content = await readFile(filePath, \"utf-8\");\n const fileHash = shortHash(content, 24);\n if (seenFileHashes.has(fileHash)) {\n warnings.push({\n code: \"session-summaries.duplicate_file_skipped\",\n message: \"Skipped a duplicate transcript file with identical content.\",\n fileRef: fileHash,\n });\n continue;\n }\n seenFileHashes.add(fileHash);\n const fileExtension = path.extname(filePath).toLowerCase();\n const parsed = await adapter.parseFile(\n {\n content,\n fileName: path.basename(filePath),\n fileExtension,\n fileRef: fileHash,\n },\n { strict: options.strict }\n );\n warnings.push(...parsed.warnings);\n if (parsed.turns.length === 0) continue;\n filesParsed += 1;\n for (const turn of parsed.turns) {\n turnsParsed += 1;\n const sessionKey = turn.sessionKey?.trim() || `${adapter.id}:${fileHash}`;\n const bucket = sessions.get(sessionKey) ?? [];\n bucket.push({ ...turn, fileHash, fileExtension });\n sessions.set(sessionKey, bucket);\n }\n }\n\n const drafts: SessionSummaryDraft[] = [];\n const sessionEntries = [...sessions.entries()].sort(([aKey, a], [bKey, b]) => {\n const aFirst = earliestTurnSortValue(a);\n const bFirst = earliestTurnSortValue(b);\n return aFirst - bFirst || a[0]?.fileHash.localeCompare(b[0]?.fileHash ?? \"\") || aKey.localeCompare(bKey);\n });\n if (sessionEntries.length > maxSessions) {\n warnings.push({\n code: \"session-summaries.max_sessions_truncated\",\n message: `Summarized ${maxSessions} of ${sessionEntries.length} session(s); increase maxSessions to include all parsed sessions.`,\n });\n }\n for (const [sessionKey, turns] of sessionEntries.slice(0, maxSessions)) {\n drafts.push(\n buildDraft({\n source: adapter.id,\n sessionKey,\n turns,\n generatedAt,\n redactionRules,\n includeRedactedExcerpts,\n })\n );\n }\n drafts.sort((a, b) => (a.firstTimestamp ?? \"\").localeCompare(b.firstTimestamp ?? \"\"));\n\n return {\n generatedAt,\n source: adapter.id,\n filesScanned: files.length,\n filesParsed,\n turnsParsed,\n sessionsSummarized: drafts.length,\n warnings,\n drafts,\n wroteFiles: [],\n };\n}\n\nasync function readRedactionConfig(pathLike: string | undefined): Promise<RedactionConfig | undefined> {\n if (!pathLike) return undefined;\n const raw = await readFile(path.resolve(expandTildePath(pathLike)), \"utf-8\");\n const parsed = JSON.parse(raw) as RedactionConfig;\n if (!parsed || typeof parsed !== \"object\" || Array.isArray(parsed)) {\n throw new Error(\"redaction config must be a JSON object\");\n }\n return parsed;\n}\n\nfunction toJsonl(drafts: readonly SessionSummaryDraft[]): string {\n return `${drafts.map((draft) => JSON.stringify(draft)).join(\"\\n\")}\\n`;\n}\n\nfunction defaultDraftOutputPath(memoryDir: string, generatedAt: string): string {\n const stamp = generatedAt.replace(/[:.]/g, \"-\");\n return path.join(\n path.resolve(expandTildePath(memoryDir)),\n \"state\",\n \"session-summary-drafts\",\n `session-summaries-${stamp}.jsonl`\n );\n}\n\nasync function writeDrafts(filePath: string, drafts: readonly SessionSummaryDraft[]): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n const tempPath = `${filePath}.${process.pid}.${Date.now()}.tmp`;\n try {\n await writeFile(tempPath, toJsonl(drafts), \"utf-8\");\n await rename(tempPath, filePath);\n } catch (error) {\n await rm(tempPath, { force: true });\n throw error;\n }\n}\n\nexport async function runLocalSessionSummaryCliCommand(\n options: LocalSessionSummaryCliOptions\n): Promise<LocalSessionSummaryReport> {\n const redactionConfig = options.redactionConfig ?? (await readRedactionConfig(options.redactionConfigPath));\n const report = await collectLocalSessionSummaries({\n ...options,\n ...(redactionConfig ? { redactionConfig } : {}),\n });\n const wroteFiles: string[] = [];\n\n if (options.output) {\n const outputPath = path.resolve(expandTildePath(options.output));\n await writeDrafts(outputPath, report.drafts);\n wroteFiles.push(outputPath);\n }\n\n if (options.write === true) {\n if (!options.memoryDir || options.memoryDir.trim().length === 0) {\n throw new Error(\"memoryDir is required when write is true\");\n }\n const outputPath = defaultDraftOutputPath(options.memoryDir, report.generatedAt);\n await writeDrafts(outputPath, report.drafts);\n wroteFiles.push(outputPath);\n }\n\n const stdout = options.stdout;\n if (stdout) {\n stdout.write(`Local session summaries complete (source: ${report.source})\\n`);\n stdout.write(` Files scanned: ${report.filesScanned}\\n`);\n stdout.write(` Files parsed: ${report.filesParsed}\\n`);\n stdout.write(` Turns parsed: ${report.turnsParsed}\\n`);\n stdout.write(` Sessions summarized: ${report.sessionsSummarized}\\n`);\n stdout.write(` Draft files written: ${wroteFiles.length}\\n`);\n if (wroteFiles.length === 0) {\n stdout.write(\" (dry run - no Remnic draft files were written)\\n\");\n }\n }\n\n return { ...report, wroteFiles };\n}\n","import type { LocalSessionParsedFile, LocalSessionRole, LocalSessionSourceAdapter, LocalSessionTurn } from \"./types.js\";\n\nconst VALID_ROLES = new Set<LocalSessionRole>([\"user\", \"assistant\", \"tool\", \"system\", \"other\"]);\n\nfunction normalizeRole(value: unknown): LocalSessionRole {\n if (typeof value !== \"string\") return \"other\";\n const role = value.trim().toLowerCase();\n if (VALID_ROLES.has(role as LocalSessionRole)) {\n return role as LocalSessionRole;\n }\n if (role === \"human\") return \"user\";\n if (role === \"ai\" || role === \"model\" || role === \"bot\") return \"assistant\";\n if (role === \"function\") return \"tool\";\n return \"other\";\n}\n\nfunction normalizeTimestamp(value: unknown): string | undefined {\n if (typeof value === \"number\" && Number.isFinite(value)) {\n const millis = value > 1e12 ? value : value * 1000;\n const date = new Date(millis);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n }\n if (typeof value !== \"string\" || value.trim().length === 0) return undefined;\n const date = new Date(value);\n return Number.isFinite(date.getTime()) ? date.toISOString() : undefined;\n}\n\nfunction normalizeContent(value: unknown): string | undefined {\n if (typeof value === \"string\") {\n const trimmed = value.trim();\n return trimmed.length > 0 ? trimmed : undefined;\n }\n if (Array.isArray(value)) {\n const parts = value\n .map((part) => normalizeContent(part))\n .filter((part): part is string => typeof part === \"string\")\n .join(\"\\n\")\n .trim();\n return parts.length > 0 ? parts : undefined;\n }\n if (!value || typeof value !== \"object\") return undefined;\n const obj = value as Record<string, unknown>;\n if (firstString(obj.type) === \"tool_result\") return undefined;\n return normalizeContent(obj.text ?? obj.content ?? obj.message ?? obj.parts ?? obj.value ?? obj.input);\n}\n\nfunction firstString(...values: unknown[]): string | undefined {\n for (const value of values) {\n if (typeof value === \"string\" && value.trim().length > 0) {\n return value.trim();\n }\n if (typeof value === \"number\" && Number.isFinite(value)) {\n return String(value);\n }\n }\n return undefined;\n}\n\nfunction firstContent(...values: unknown[]): string | undefined {\n for (const value of values) {\n const content = normalizeContent(value);\n if (content) return content;\n }\n return undefined;\n}\n\nfunction objectField(value: unknown): Record<string, unknown> | undefined {\n return value && typeof value === \"object\" ? (value as Record<string, unknown>) : undefined;\n}\n\nconst SESSION_KEY_FIELDS = [\n \"sessionKey\",\n \"session_key\",\n \"sessionId\",\n \"session_id\",\n \"conversationId\",\n \"conversation_id\",\n \"threadId\",\n \"thread_id\",\n \"transcriptId\",\n \"transcript_id\",\n] as const;\n\nfunction hasUsableSessionKeyField(value: unknown): boolean {\n return (\n (typeof value === \"string\" && value.trim().length > 0) ||\n (typeof value === \"number\" && Number.isFinite(value))\n );\n}\n\nfunction inheritEnvelopeSessionFields(row: unknown, envelope: Record<string, unknown>): unknown {\n if (!row || typeof row !== \"object\" || Array.isArray(row)) return row;\n const child = row as Record<string, unknown>;\n const inherited: Record<string, unknown> = {};\n for (const key of SESSION_KEY_FIELDS) {\n if (!hasUsableSessionKeyField(child[key]) && hasUsableSessionKeyField(envelope[key])) {\n inherited[key] = envelope[key];\n }\n }\n return Object.keys(inherited).length > 0 ? { ...child, ...inherited } : row;\n}\n\nfunction codexRoleFromTypes(\n rowType: string | undefined,\n payloadType: string | undefined\n): LocalSessionRole | undefined {\n if (payloadType === \"agent_message\") return \"assistant\";\n if (payloadType === \"user_message\") return \"user\";\n if (rowType === \"event_msg\") return \"user\";\n if (rowType === \"response_item\") return \"assistant\";\n return undefined;\n}\n\nfunction sessionKeyFromRow(row: unknown): string | undefined {\n if (!row || typeof row !== \"object\") return undefined;\n const obj = row as Record<string, unknown>;\n const nestedMessage = objectField(obj.message);\n const payload = objectField(obj.payload);\n const payloadMessage = objectField(payload?.message);\n const rowType = firstString(obj.type, obj.kind, obj.event)?.toLowerCase();\n return firstString(\n obj.sessionKey,\n obj.session_key,\n obj.sessionId,\n obj.session_id,\n obj.conversationId,\n obj.conversation_id,\n obj.threadId,\n obj.thread_id,\n obj.transcriptId,\n obj.transcript_id,\n nestedMessage?.sessionKey,\n nestedMessage?.session_key,\n nestedMessage?.sessionId,\n nestedMessage?.session_id,\n nestedMessage?.conversationId,\n nestedMessage?.conversation_id,\n nestedMessage?.threadId,\n nestedMessage?.thread_id,\n nestedMessage?.transcriptId,\n nestedMessage?.transcript_id,\n rowType === \"session_meta\" ? payload?.id : undefined,\n payload?.sessionKey,\n payload?.session_key,\n payload?.sessionId,\n payload?.session_id,\n payload?.conversationId,\n payload?.conversation_id,\n payload?.threadId,\n payload?.thread_id,\n payload?.transcriptId,\n payload?.transcript_id,\n payloadMessage?.sessionKey,\n payloadMessage?.session_key,\n payloadMessage?.sessionId,\n payloadMessage?.session_id,\n payloadMessage?.conversationId,\n payloadMessage?.conversation_id,\n payloadMessage?.threadId,\n payloadMessage?.thread_id,\n payloadMessage?.transcriptId,\n payloadMessage?.transcript_id\n );\n}\n\nfunction extractRowsFromJson(value: unknown): unknown[] {\n if (Array.isArray(value)) return value;\n if (!value || typeof value !== \"object\") return [];\n const obj = value as Record<string, unknown>;\n for (const key of [\"turns\", \"messages\", \"events\", \"entries\", \"items\"]) {\n const rows = obj[key];\n if (Array.isArray(rows) && rows.length > 0) {\n return rows.map((row) => inheritEnvelopeSessionFields(row, obj));\n }\n }\n return [obj];\n}\n\nfunction parseJsonlRows(\n content: string,\n adapterId: string,\n strict: boolean | undefined,\n fileRef: string\n): { rows: unknown[]; warnings: LocalSessionParsedFile[\"warnings\"] } {\n const rows: unknown[] = [];\n const warnings: LocalSessionParsedFile[\"warnings\"] = [];\n for (const [index, line] of content.split(\"\\n\").entries()) {\n const trimmed = line.trim();\n if (trimmed.length === 0) continue;\n try {\n rows.push(JSON.parse(trimmed));\n } catch {\n const warning = {\n code: `${adapterId}.jsonl.invalid_line`,\n message: `Skipping invalid JSONL line ${index + 1} in fileRef ${fileRef}.`,\n fileRef,\n line: index + 1,\n };\n if (strict) throw new Error(warning.message);\n warnings.push(warning);\n }\n }\n return { rows, warnings };\n}\n\nfunction parseRows(\n content: string,\n extension: string,\n adapterId: string,\n strict: boolean | undefined,\n fileRef: string\n): { rows: unknown[]; warnings: LocalSessionParsedFile[\"warnings\"] } {\n if (extension === \".jsonl\") {\n return parseJsonlRows(content, adapterId, strict, fileRef);\n }\n try {\n return { rows: extractRowsFromJson(JSON.parse(content)), warnings: [] };\n } catch {\n const message = `Invalid ${adapterId} JSON in fileRef ${fileRef}; skipping file.`;\n if (strict) throw new Error(message);\n return {\n rows: [],\n warnings: [{ code: `${adapterId}.json.invalid`, message, fileRef }],\n };\n }\n}\n\nfunction turnFromRow(row: unknown, fallbackSessionKey: string): LocalSessionTurn | null {\n if (!row || typeof row !== \"object\") return null;\n const obj = row as Record<string, unknown>;\n const nestedMessage = objectField(obj.message);\n const payload = objectField(obj.payload);\n const payloadItem = objectField(payload?.item);\n const payloadMessage = objectField(payload?.message);\n const author = objectField(obj.author);\n const rowType = firstString(obj.type, obj.kind, obj.event);\n const payloadType = firstString(payload?.type, payloadItem?.type);\n const codexRole = codexRoleFromTypes(rowType, payloadType);\n\n const content = firstContent(\n obj.content,\n obj.text,\n obj.message,\n obj.body,\n obj.parts,\n obj.input,\n payload?.message,\n payload?.content,\n payload?.text,\n payload?.body,\n payload?.parts,\n payload?.input,\n payloadMessage?.content,\n payloadMessage?.text,\n payloadMessage?.parts,\n payloadMessage?.input,\n payloadItem?.content,\n payloadItem?.text,\n payloadItem?.message,\n payloadItem?.parts,\n payloadItem?.input,\n nestedMessage?.content,\n nestedMessage?.text,\n nestedMessage?.parts,\n nestedMessage?.input\n );\n if (!content) return null;\n\n const role = normalizeRole(\n obj.role ??\n obj.sender ??\n obj.actor ??\n payload?.role ??\n payload?.sender ??\n payloadMessage?.role ??\n payloadMessage?.sender ??\n payloadItem?.role ??\n nestedMessage?.role ??\n nestedMessage?.sender ??\n author?.role ??\n codexRole ??\n obj.type\n );\n\n return {\n role,\n content,\n timestamp: normalizeTimestamp(\n obj.timestamp ??\n obj.createdAt ??\n obj.created_at ??\n obj.time ??\n obj.date ??\n payload?.timestamp ??\n payload?.createdAt ??\n payload?.created_at ??\n payloadMessage?.timestamp ??\n payloadMessage?.createdAt ??\n payloadMessage?.created_at ??\n payloadItem?.timestamp ??\n payloadItem?.created_at ??\n nestedMessage?.timestamp ??\n nestedMessage?.created_at\n ),\n sessionKey: sessionKeyFromRow(row) ?? fallbackSessionKey,\n sourceId: firstString(obj.id, obj.uuid, obj.turnId, obj.turn_id, payload?.id, payloadItem?.id),\n };\n}\n\nfunction shouldSkipRowForAdapter(adapterId: string, row: unknown): boolean {\n if (adapterId !== \"codex-jsonl\" || !row || typeof row !== \"object\") return false;\n const obj = row as Record<string, unknown>;\n const payload = objectField(obj.payload);\n const rowType = firstString(obj.type, obj.kind, obj.event)?.toLowerCase();\n const payloadType = firstString(payload?.type)?.toLowerCase();\n return rowType === \"compacted\" || payloadType === \"compacted\";\n}\n\ntype CodexMirrorSurface = \"event-agent-message\" | \"response-item\";\n\nconst CODEX_MIRROR_SURFACE_PRIORITY: Record<CodexMirrorSurface, number> = {\n \"event-agent-message\": 1,\n \"response-item\": 2,\n};\n\nfunction codexMirrorSurface(row: unknown): CodexMirrorSurface | undefined {\n if (!row || typeof row !== \"object\") return undefined;\n const obj = row as Record<string, unknown>;\n const payload = objectField(obj.payload);\n const payloadItem = objectField(payload?.item);\n const rowType = firstString(obj.type, obj.kind, obj.event)?.toLowerCase();\n const payloadType = firstString(payload?.type, payloadItem?.type)?.toLowerCase();\n if (rowType === \"event_msg\" && payloadType === \"agent_message\") return \"event-agent-message\";\n if (rowType === \"response_item\") return \"response-item\";\n return undefined;\n}\n\nfunction codexMirrorKey(adapterId: string, row: unknown, turn: LocalSessionTurn): string | undefined {\n if (adapterId !== \"codex-jsonl\" || turn.role !== \"assistant\") return undefined;\n const surface = codexMirrorSurface(row);\n if (!surface) return undefined;\n const sessionKey = turn.sessionKey?.trim();\n const content = turn.content.replace(/\\s+/g, \" \").trim();\n if (!sessionKey || content.length === 0) return undefined;\n return `${sessionKey}\\0${turn.role}\\0${content}`;\n}\n\nfunction pushTurnWithCodexMirrorDedupe(\n adapterId: string,\n row: unknown,\n turn: LocalSessionTurn,\n turns: LocalSessionTurn[],\n codexMirrorTurns: Map<string, { index: number; surface: CodexMirrorSurface; rowSignal?: string }[]>\n): void {\n const key = codexMirrorKey(adapterId, row, turn);\n const surface = key ? codexMirrorSurface(row) : undefined;\n if (!key || !surface) {\n turns.push(turn);\n return;\n }\n\n const candidates = codexMirrorTurns.get(key) ?? [];\n const rowSignal = turn.sourceId ?? turn.timestamp;\n const matchingIndex = candidates.findIndex((candidate) => {\n if (candidate.surface === surface) {\n return Boolean(candidate.rowSignal && rowSignal && candidate.rowSignal === rowSignal);\n }\n return Boolean(candidate.rowSignal && rowSignal && candidate.rowSignal === rowSignal);\n });\n const existing = matchingIndex >= 0 ? candidates[matchingIndex] : undefined;\n if (existing) {\n if (CODEX_MIRROR_SURFACE_PRIORITY[surface] > CODEX_MIRROR_SURFACE_PRIORITY[existing.surface]) {\n turns[existing.index] = turn;\n candidates[matchingIndex] = { index: existing.index, surface, ...(rowSignal ? { rowSignal } : {}) };\n codexMirrorTurns.set(key, candidates);\n }\n return;\n }\n\n candidates.push({ index: turns.length, surface, ...(rowSignal ? { rowSignal } : {}) });\n codexMirrorTurns.set(key, candidates);\n turns.push(turn);\n}\n\nfunction makeJsonTranscriptAdapter(id: string): LocalSessionSourceAdapter {\n return {\n id,\n parseFile(input, options = {}) {\n const parsed = parseRows(input.content, input.fileExtension, id, options.strict, input.fileRef);\n const fallbackSessionKey = `${id}:${input.fileRef}`;\n let currentSessionKey = fallbackSessionKey;\n const turns: LocalSessionTurn[] = [];\n const codexMirrorTurns = new Map<string, { index: number; surface: CodexMirrorSurface; rowSignal?: string }[]>();\n for (const row of parsed.rows) {\n if (shouldSkipRowForAdapter(id, row)) continue;\n currentSessionKey = sessionKeyFromRow(row) ?? currentSessionKey;\n const turn = turnFromRow(row, currentSessionKey);\n if (turn) {\n currentSessionKey = turn.sessionKey ?? currentSessionKey;\n pushTurnWithCodexMirrorDedupe(id, row, turn, turns, codexMirrorTurns);\n }\n }\n return { turns, warnings: parsed.warnings };\n },\n };\n}\n\nconst BUILT_IN_ADAPTERS = new Map<string, LocalSessionSourceAdapter>();\n\nexport function registerLocalSessionSourceAdapter(adapter: LocalSessionSourceAdapter): void {\n if (!adapter || typeof adapter !== \"object\") {\n throw new Error(\"local session source adapter must be an object\");\n }\n if (typeof adapter.id !== \"string\" || adapter.id.trim().length === 0) {\n throw new Error(\"local session source adapter id must be a non-empty string\");\n }\n if (typeof adapter.parseFile !== \"function\") {\n throw new Error(`local session adapter '${adapter.id}' must define parseFile`);\n }\n const id = adapter.id.trim();\n if (BUILT_IN_ADAPTERS.has(id)) {\n throw new Error(`local session adapter '${id}' is already registered`);\n }\n BUILT_IN_ADAPTERS.set(id, adapter.id === id ? adapter : { ...adapter, id });\n}\n\nexport function getLocalSessionSourceAdapter(id: string | undefined): LocalSessionSourceAdapter | undefined {\n const key = typeof id === \"string\" && id.trim().length > 0 ? id.trim() : \"generic-jsonl\";\n return BUILT_IN_ADAPTERS.get(key);\n}\n\nexport function listLocalSessionSourceAdapters(): string[] {\n return [...BUILT_IN_ADAPTERS.keys()].sort();\n}\n\nfor (const adapterId of [\"generic-jsonl\", \"codex-jsonl\", \"claude-jsonl\"]) {\n registerLocalSessionSourceAdapter(makeJsonTranscriptAdapter(adapterId));\n}\n","import type { CompiledRedactionRule, RedactionConfig, RedactionReport } from \"./types.js\";\n\nexport const DEFAULT_REDACTION_RULES: readonly CompiledRedactionRule[] = [\n {\n name: \"secret-token\",\n pattern:\n /(?<![A-Za-z0-9_])(?:sk-[A-Za-z0-9_-]{12,}|sk-proj-[A-Za-z0-9_-]{12,}|(?:\"authorization\"|'authorization'|authorization)\\s*[:=]\\s*(?:\"[A-Za-z][A-Za-z0-9._-]*\\s+[^\"\\r\\n]*\"|'[A-Za-z][A-Za-z0-9._-]*\\s+[^'\\r\\n]*'|[A-Za-z][A-Za-z0-9._-]*\\s+(?:\"[^\"\\r\\n]*\"|'[^'\\r\\n]*'|[^\\s\"',;]+))|(?:\"(?:[A-Za-z0-9]+[_-]+)*(?:api[_-]?key|access[_-]?key|private[_-]?key|token|secret|password)\"|'(?:[A-Za-z0-9]+[_-]+)*(?:api[_-]?key|access[_-]?key|private[_-]?key|token|secret|password)'|(?:[A-Za-z0-9]+[_-]+)*(?:api[_-]?key|access[_-]?key|private[_-]?key|token|secret|password))\\s*[:=]\\s*(?:\"[^\"\\r\\n]*\"|'[^'\\r\\n]*'|[^\\s\"',;]+))/gi,\n replacement: \"[REDACTED_SECRET]\",\n },\n {\n name: \"email\",\n pattern: /\\b[A-Z0-9._%+-]+@[A-Z0-9.-]+\\.[A-Z]{2,}\\b/gi,\n replacement: \"[REDACTED_EMAIL]\",\n },\n {\n name: \"private-ip\",\n pattern:\n /\\b(?:(?:10|127)\\.(?:\\d{1,3}\\.){2}\\d{1,3}|192\\.168\\.\\d{1,3}\\.\\d{1,3}|172\\.(?:1[6-9]|2\\d|3[0-1])\\.\\d{1,3}\\.\\d{1,3})\\b/g,\n replacement: \"[REDACTED_PRIVATE_IP]\",\n },\n {\n name: \"url\",\n pattern: /\\bhttps?:\\/\\/[^\\s\"'<>)]*/gi,\n replacement: \"[REDACTED_URL]\",\n },\n {\n name: \"home-relative-posix-spaced-path\",\n pattern:\n /~\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+(?: (?!(?:before|after|then|and|or)\\b)[^/\\s\"',;<>]+)+\\.[^/\\s\"',;<>]+?(?=$|[\\s\"',;<>)]|[.,](?:\\s|$))/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"home-relative-posix-spaced-extensionless-path\",\n pattern:\n /~\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+(?: (?!(?:before|after|then|and(?=\\s+[a-z])|or(?=\\s+[a-z]))\\b)[^/\\s\"',;<>]+)+?(?=$|[\"'<>)](?!\\/)|[,;.]|\\s+(?:before|after|then|and(?=\\s+(?:[a-z]|[~/\"']|$))|or(?=\\s+(?:[a-z]|[~/\"']|$)))\\b)/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"home-relative-posix-path\",\n pattern: /~\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+?(?=$|[\\s\"',;<>)]|[.,](?:\\s|$))/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-posix-spaced-path\",\n pattern:\n /\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+(?: (?!(?:before|after|then|and|or)\\b)[^/\\s\"',;<>]+)+\\.[^/\\s\"',;<>]+?(?=$|[\\s\"',;<>)]|[.,](?:\\s|$))/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-posix-spaced-extensionless-path\",\n pattern:\n /\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+(?: (?!(?:before|after|then|and(?=\\s+[a-z])|or(?=\\s+[a-z]))\\b)[^/\\s\"',;<>]+)+?(?=$|[\"'<>)](?!\\/)|[,;.]|\\s+(?:before|after|then|and(?=\\s+(?:[a-z]|[~/\"']|$))|or(?=\\s+(?:[a-z]|[~/\"']|$)))\\b)/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-posix-path\",\n pattern: /\\/(?:[^/\\s\"',;<>]+(?: [^/\\s\"',;<>]+)*\\/)*[^/\\s\"',;<>]+?(?=$|[\\s\"',;<>)]|[.,](?:\\s|$))/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-windows-spaced-path\",\n pattern:\n /\\b[A-Za-z]:\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+(?: [^\\\\/:*?\"<>|,;\\s\\r\\n]+)+\\.[A-Za-z0-9_-]+/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-windows-spaced-extensionless-path\",\n pattern:\n /\\b[A-Za-z]:\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+(?: [^\\\\/:*?\"<>|,;\\s\\r\\n]+)+(?=$|[\"'<>)](?!\\\\)|[,;.]|\\s+(?:before|after|then|and|or)\\b)/gi,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"absolute-windows-path\",\n pattern: /\\b[A-Za-z]:\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"unc-windows-spaced-path\",\n pattern:\n /\\\\\\\\[^\\\\/:*?\"<>|,;\\s\\r\\n]+\\\\[^\\\\/:*?\"<>|,;\\r\\n]+\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+(?: [^\\\\/:*?\"<>|,;\\s\\r\\n]+)+\\.[A-Za-z0-9_-]+/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"unc-windows-spaced-extensionless-path\",\n pattern:\n /\\\\\\\\[^\\\\/:*?\"<>|,;\\s\\r\\n]+\\\\[^\\\\/:*?\"<>|,;\\r\\n]+\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+(?: [^\\\\/:*?\"<>|,;\\s\\r\\n]+)+(?=$|[\"'<>)](?!\\\\)|[,;.]|\\s+(?:before|after|then|and|or)\\b)/gi,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"unc-windows-share-root\",\n pattern: /\\\\\\\\[^\\\\/:*?\"<>|,;\\s\\r\\n]+\\\\[^\\\\/:*?\"<>|,;\\s\\r\\n]+(?=$|[\\s\"',;<>)]|[.,](?:\\s|$))/g,\n replacement: \"[REDACTED_PATH]\",\n },\n {\n name: \"unc-windows-path\",\n pattern: /\\\\\\\\[^\\\\/:*?\"<>|,;\\s\\r\\n]+\\\\[^\\\\/:*?\"<>|,;\\r\\n]+\\\\(?:[^\\\\/:*?\"<>|,;\\r\\n]+\\\\)*[^\\\\/:*?\"<>|,;\\s\\r\\n]+/g,\n replacement: \"[REDACTED_PATH]\",\n },\n];\n\nfunction cloneRedactionRule(rule: CompiledRedactionRule): CompiledRedactionRule {\n return {\n name: rule.name,\n pattern: new RegExp(rule.pattern.source, rule.pattern.flags),\n replacement: rule.replacement,\n };\n}\n\nexport function compileRedactionRules(config: RedactionConfig = {}): CompiledRedactionRule[] {\n const rules: CompiledRedactionRule[] =\n config.disableDefaults === true ? [] : DEFAULT_REDACTION_RULES.map(cloneRedactionRule);\n const customRules = config.rules ?? [];\n if (!Array.isArray(customRules)) {\n throw new Error(\"redaction rules must be an array\");\n }\n for (const rule of customRules) {\n if (!rule || typeof rule !== \"object\") {\n throw new Error(\"redaction rule must be an object\");\n }\n if (typeof rule.name !== \"string\" || rule.name.trim().length === 0) {\n throw new Error(\"redaction rule name must be a non-empty string\");\n }\n if (typeof rule.pattern !== \"string\" || rule.pattern.length === 0) {\n throw new Error(`redaction rule '${rule.name}' pattern must be non-empty`);\n }\n const flags = rule.flags ?? \"g\";\n rules.push({\n name: rule.name.trim(),\n pattern: new RegExp(rule.pattern, flags.includes(\"g\") ? flags : `${flags}g`),\n replacement: rule.replacement ?? `[REDACTED_${rule.name.trim().toUpperCase()}]`,\n });\n }\n return rules;\n}\n\nexport function redactSessionSummaryText(\n text: string,\n rules: readonly CompiledRedactionRule[]\n): { text: string; report: RedactionReport } {\n let redacted = text;\n let applied = 0;\n const ruleNames = new Set<string>();\n\n for (const rule of rules) {\n rule.pattern.lastIndex = 0;\n const matches = redacted.match(rule.pattern);\n if (!matches || matches.length === 0) continue;\n applied += matches.length;\n ruleNames.add(rule.name);\n redacted = redacted.replace(rule.pattern, rule.replacement);\n }\n\n return {\n text: redacted,\n report: {\n applied,\n ruleNames: [...ruleNames].sort(),\n },\n };\n}\n","/**\n * Capsule fork semantics — issue #676 PR 4/6.\n *\n * A fork takes an existing capsule archive, imports it into a target memory\n * root under the `fork` conflict-resolution mode (which rebases all records\n * under `forks/<capsule-id>/`), and then writes a lineage breadcrumb at\n * `<targetRoot>/forks/<forkId>/lineage.json` recording the parent capsule's\n * identity. Subsequent forks of the same parent or of a fork produce a\n * queryable chain.\n *\n * The lineage breadcrumb is a pure JSON file — no gzip, no bundle format —\n * so downstream tooling can read it with a single `readFile` + `JSON.parse`\n * without pulling in the transfer pipeline.\n */\n\nimport { lstat, mkdir, readFile, realpath, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { importCapsule, type ImportCapsuleResult } from \"./capsule-import.js\";\nimport { assertIsDirectoryNotSymlink, assertRealpathInsideRoot } from \"./fs-utils.js\";\nimport type { CapsuleParent, ExportManifestV2 } from \"./types.js\";\nimport { CAPSULE_ID_PATTERN } from \"./types.js\";\n\n// ---------------------------------------------------------------------------\n// Public types\n// ---------------------------------------------------------------------------\n\n/**\n * Options accepted by {@link forkCapsule}.\n *\n * `sourceArchive` — absolute or cwd-relative path to a `.capsule.json.gz`\n * archive produced by `exportCapsule`.\n *\n * `targetRoot` — absolute or cwd-relative path to the memory directory that\n * will receive the forked records. Must be an existing directory.\n *\n * `forkId` — user-chosen id for the fork. Validated against\n * {@link CAPSULE_ID_PATTERN}; must be unique under `<targetRoot>/forks/` (a\n * pre-existing `forks/<forkId>/` directory is rejected before any write).\n *\n * `versioning` — optional page-versioning config forwarded to\n * {@link importCapsule}. Only relevant when the target root already has files\n * that would be overwritten (fork mode is skip-on-exist by design, so this is\n * a no-op unless mode is changed in a future subclass).\n *\n * `now` — optional clock override (ms epoch) forwarded to `importCapsule` for\n * deterministic fork-id rewriting in tests.\n */\nexport interface ForkCapsuleOptions {\n sourceArchive: string;\n targetRoot: string;\n forkId: string;\n now?: number;\n}\n\n/**\n * The lineage breadcrumb written to `forks/<forkId>/lineage.json`.\n *\n * Fields are intentionally flat so the file is human-readable at a glance\n * and trivially diffable by `git diff`.\n *\n * `forkId` — the id supplied to `forkCapsule`.\n * `forkedAt` — ISO-8601 creation timestamp (UTC).\n * `parent` — structured linkage to the source capsule.\n * `importedRecords` — number of records written by the fork import.\n * `skippedRecords` — number of records skipped (target already existed).\n */\nexport interface ForkLineage {\n forkId: string;\n forkedAt: string;\n parent: CapsuleParent;\n importedRecords: number;\n skippedRecords: number;\n}\n\nexport interface ForkCapsuleResult {\n /** Absolute path to the source archive (unchanged, for chaining). */\n archivePath: string;\n /** The V2 manifest decoded from the source archive. */\n manifest: ExportManifestV2;\n /** Result of the underlying `importCapsule` call. */\n importResult: ImportCapsuleResult;\n /** The lineage breadcrumb that was written. */\n lineage: ForkLineage;\n /** Absolute path to the lineage breadcrumb file. */\n lineagePath: string;\n}\n\n// ---------------------------------------------------------------------------\n// Main function\n// ---------------------------------------------------------------------------\n\n/**\n * Fork a capsule archive into a target memory root.\n *\n * Sequence:\n * 1. Validate `forkId` against {@link CAPSULE_ID_PATTERN}.\n * 2. Resolve `targetRoot` and verify it is an existing directory (not a\n * symlink — mirrors {@link importCapsule}'s root validation).\n * 3. Reject if `forks/<forkId>/` already exists in the target root\n * (gotcha #49: deduplicate batch inputs; gotcha #25: don't destroy\n * old state).\n * 4. Import the archive in `\"fork\"` mode via {@link importCapsule}.\n * 5. Write the lineage breadcrumb at `forks/<forkId>/lineage.json`.\n * The breadcrumb dir is created by step 4 (importCapsule writes records\n * under `forks/<sourceId>/`); if `forkId !== sourceId` we may need to\n * create the fork dir ourselves. We always `mkdir -p` defensively.\n *\n * Error semantics:\n * - All validation errors throw before any filesystem write (fail-closed,\n * gotcha #25).\n * - If `importCapsule` throws after writing some records, the lineage\n * breadcrumb is NOT written (partial state is better than a false\n * \"fork complete\" marker — gotcha #12: write rollback data before\n * success markers).\n */\nexport async function forkCapsule(opts: ForkCapsuleOptions): Promise<ForkCapsuleResult> {\n // --- 1. Validate forkId ---\n validateForkId(opts.forkId);\n\n // --- 2. Validate targetRoot ---\n // Use the shared assertIsDirectoryNotSymlink helper from fs-utils.ts so\n // capsule-fork and capsule-import share the same symlink-safe validation\n // logic (Cursor medium #751 round 2: the fork's doc comment claims it\n // \"mirrors importCapsule's root validation\"; now it literally does).\n const rootAbs = path.resolve(opts.targetRoot);\n await assertIsDirectoryNotSymlink(rootAbs, \"forkCapsule\", \"targetRoot\");\n\n // --- 3. Reject duplicate forkId ---\n // Treat ANY existing filesystem entry at `forks/<forkId>` as occupied:\n // directory, regular file, or symlink. A previous version of this check\n // only rejected directories, so a stray file at the path would slip past\n // and `importCapsule` would still write under `forks/<sourceCapsule>/...`.\n // The later `mkdir`/`writeFile` for the breadcrumb would then fail,\n // leaving a partial fork import after reporting an error — violating the\n // documented \"reject before any write\" contract (Codex P2 #751 round 2).\n // `lstat` (not `stat`) is intentional so a symlink at the path is detected\n // even if its target is missing or otherwise unreadable.\n const forkDirAbs = path.join(rootAbs, \"forks\", opts.forkId);\n const forkEntryExists = await pathEntryExists(forkDirAbs);\n if (forkEntryExists) {\n throw new Error(\n `forkCapsule: fork path already exists — forkId \"${opts.forkId}\" is already in use at: ${forkDirAbs}`,\n );\n }\n\n // --- 4. Import in fork mode ---\n const archiveAbs = path.resolve(opts.sourceArchive);\n const importResult = await importCapsule({\n archivePath: archiveAbs,\n root: rootAbs,\n mode: \"fork\",\n now: opts.now,\n });\n\n const manifest = importResult.manifest;\n const sourceCapsule = manifest.capsule;\n\n // --- 5. Build lineage and write breadcrumb ---\n // The breadcrumb lives under the FORK's own directory, not the source\n // capsule's fork subtree. `forkId` may differ from `sourceCapsule.id`\n // (e.g. `forkCapsule({ forkId: \"my-fork\" })` with source `base-caps`\n // imports records under `forks/base-caps/` but the lineage breadcrumb\n // is written to `forks/my-fork/lineage.json` so a subsequent fork of\n // this fork can locate the breadcrumb by its own id).\n const forkedAt = new Date(opts.now ?? Date.now()).toISOString();\n\n const parent: CapsuleParent = {\n capsuleId: sourceCapsule.id,\n version: sourceCapsule.version,\n forkRoot: `forks/${sourceCapsule.id}`,\n };\n\n const lineage: ForkLineage = {\n forkId: opts.forkId,\n forkedAt,\n parent,\n importedRecords: importResult.imported.length,\n skippedRecords: importResult.skipped.length,\n };\n\n // Ensure the fork breadcrumb directory exists (it may not exist if forkId\n // differs from the source capsule's id, or if all records were skipped).\n const lineagePath = path.join(forkDirAbs, \"lineage.json\");\n\n // Guard lineage write against a symlinked `forks/` directory (or any\n // intermediate path component) pointing outside the memory root. If\n // `targetRoot/forks` is a symlink to `/tmp/evil`, a zero-record capsule\n // passes `importCapsule` without triggering per-record path checks and this\n // write would silently escape the root sandbox. We resolve the nearest\n // existing ancestor of `lineagePath` via `realpath` (same technique used by\n // `capsule-import` and `capsule-merge`) and verify the canonical path is\n // still inside `rootReal` before creating any directories or writing.\n //\n // Note: `rootReal` is computed from `rootAbs` here rather than reusing\n // `forkDirAbs` for the lexical check, because on macOS /tmp is a symlink\n // to /private/tmp and `path.relative(rootReal, forkDirAbs)` would produce\n // an absolute path if forkDirAbs was not also resolved. We skip the lexical\n // pre-check and rely solely on `assertRealpathInsideRoot` which handles\n // both the realpath walk and the containment check atomically.\n const rootReal = await realpath(rootAbs);\n // Symlink-safe containment check: walks the nearest existing ancestor and\n // confirms the canonical path is still inside rootReal.\n await assertRealpathInsideRoot(rootReal, lineagePath, `forks/${opts.forkId}/lineage.json`, \"forkCapsule\");\n\n await mkdir(path.dirname(lineagePath), { recursive: true });\n\n // Write breadcrumb AFTER import completes successfully — consistent with\n // gotcha #25 (don't destroy old state before new state is confirmed) and\n // gotcha #54 (write temp before rename / write before marker).\n await writeFile(lineagePath, JSON.stringify(lineage, null, 2) + \"\\n\", \"utf-8\");\n\n return {\n archivePath: archiveAbs,\n manifest,\n importResult,\n lineage,\n lineagePath,\n };\n}\n\n// ---------------------------------------------------------------------------\n// Lineage query helper\n// ---------------------------------------------------------------------------\n\n/**\n * Read the lineage breadcrumb for a given fork in a memory root.\n *\n * Returns `null` when no breadcrumb exists (the directory is not a fork, or\n * was created before PR 4/6). Never throws for a missing file — callers\n * that need to distinguish \"not a fork\" from \"corrupt breadcrumb\" should\n * handle the JSON parse error themselves.\n *\n * `forkId` is validated against {@link CAPSULE_ID_PATTERN} before being\n * joined into the breadcrumb path so a malicious value like\n * `../../../../tmp` cannot escape the `forks/` namespace and resolve to\n * unrelated files outside the configured memory root (Codex P2 #751).\n * Invalid ids return `null` (same shape as \"no breadcrumb\"); callers that\n * need to distinguish \"invalid id\" from \"absent breadcrumb\" should validate\n * upstream.\n */\nexport async function readForkLineage(\n targetRoot: string,\n forkId: string,\n): Promise<ForkLineage | null> {\n // Reject any forkId that does not satisfy the capsule-id pattern. We use\n // the same constraints as `forkCapsule` so a path traversal payload like\n // `../../etc` is rejected before any filesystem access. Returning null\n // (rather than throwing) keeps the contract symmetric with the\n // \"breadcrumb not present\" case for the common get-or-default usage.\n if (\n typeof forkId !== \"string\" ||\n forkId.length === 0 ||\n forkId.length > 64 ||\n !CAPSULE_ID_PATTERN.test(forkId)\n ) {\n return null;\n }\n const rootAbs = path.resolve(targetRoot);\n // Resolve the root via realpath up-front so the symlink-safe containment\n // check below compares against the canonical path. If realpath fails\n // (root does not exist or is unreadable) we fall back to the lexical\n // root; the read will then return null for a missing breadcrumb anyway.\n const rootReal = await realpath(rootAbs).catch(() => rootAbs);\n\n const lineagePath = path.join(rootReal, \"forks\", forkId, \"lineage.json\");\n // Defensive lexical containment check: even though CAPSULE_ID_PATTERN\n // forbids `/` and `..`, an attacker who somehow bypasses the regex would\n // still be caught here. `path.relative` returns a `..`-prefixed string\n // when the target escapes the root.\n const rel = path.relative(rootReal, lineagePath);\n if (rel.startsWith(\"..\") || path.isAbsolute(rel)) {\n return null;\n }\n\n // Symlink-safe containment check (Codex P2 #751 round 2).\n // The lexical check above cannot detect a symlinked `forks/<forkId>`\n // directory whose target is outside the memory root. We resolve the\n // nearest existing ancestor of the breadcrumb path via realpath (which\n // follows symlinks), re-append the non-existent suffix, and verify the\n // result still lives under the real root. Mirrors the\n // `assertRealpathInsideRoot` pattern used by capsule-import.ts.\n if (!(await isLineagePathContained(rootReal, lineagePath))) {\n return null;\n }\n const raw = await readFile(lineagePath, \"utf-8\").catch(() => null);\n if (raw === null) return null;\n try {\n const parsed = JSON.parse(raw);\n // Basic shape check — we do not run full zod validation here so that\n // slightly malformed breadcrumbs (e.g. missing new fields added in later\n // PRs) can still be returned rather than silently dropped.\n if (typeof parsed !== \"object\" || parsed === null || typeof parsed.forkId !== \"string\") {\n return null;\n }\n return parsed as ForkLineage;\n } catch {\n return null;\n }\n}\n\n// ---------------------------------------------------------------------------\n// Private helpers\n// ---------------------------------------------------------------------------\n\nfunction validateForkId(forkId: unknown): void {\n if (typeof forkId !== \"string\") {\n throw new Error(\"forkCapsule: forkId must be a string\");\n }\n if (forkId.length === 0) {\n throw new Error(\"forkCapsule: forkId must not be empty\");\n }\n if (forkId.length > 64) {\n throw new Error(\"forkCapsule: forkId must be 64 characters or fewer\");\n }\n if (!CAPSULE_ID_PATTERN.test(forkId)) {\n throw new Error(\n `forkCapsule: invalid forkId \"${forkId}\". Expected alphanumeric with single dashes (no leading/trailing dashes, no consecutive dashes).`,\n );\n }\n}\n\n/**\n * Return true when ANY filesystem entry exists at {@link absPath} —\n * directory, regular file, symlink (even broken), or other special file.\n * Uses `lstat` so a symlink at the path is detected regardless of whether\n * its target resolves. Used by the duplicate-forkId check so a stray file\n * cannot bypass the \"reject before any write\" guarantee (Codex P2 #751).\n */\nasync function pathEntryExists(absPath: string): Promise<boolean> {\n const st = await lstat(absPath).catch(() => null);\n return st !== null;\n}\n\n/**\n * Symlink-safe containment check for {@link readForkLineage}.\n *\n * Walks from {@link lineagePath} toward {@link rootReal} until it finds a\n * path component that exists on disk, resolves that prefix via `realpath`\n * (which follows symlinks), then re-appends the non-existent suffix and\n * verifies the resulting canonical path is still inside {@link rootReal}.\n *\n * This catches the case where any subdirectory in the path is a symlink\n * pointing outside the intended root. Returns `true` when the path is\n * safely contained, `false` otherwise.\n *\n * Mirrors the `assertRealpathInsideRoot` helper in `capsule-import.ts`.\n * Returning a boolean (rather than throwing) keeps the contract aligned\n * with `readForkLineage`'s \"return null on any safety failure\" pattern.\n */\nasync function isLineagePathContained(\n rootReal: string,\n lineagePath: string,\n): Promise<boolean> {\n let existing = lineagePath;\n const suffix: string[] = [];\n while (existing !== path.dirname(existing)) {\n const st = await lstat(existing).catch(() => null);\n if (st !== null) break;\n suffix.unshift(path.basename(existing));\n existing = path.dirname(existing);\n }\n\n // If we walked all the way to the filesystem root without finding\n // anything that exists, the path is harmless (no symlinks to follow).\n // The subsequent readFile will simply fail and return null.\n const existingReal = await realpath(existing).catch(() => existing);\n const targetReal = suffix.length > 0 ? path.join(existingReal, ...suffix) : existingReal;\n\n const rel = path.relative(rootReal, targetReal);\n if (rel === \"\") return true;\n if (rel === \"..\") return false;\n if (rel.startsWith(`..${path.sep}`)) return false;\n if (path.isAbsolute(rel)) return false;\n return true;\n}\n"],"mappings":"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","names":["path","createHash","path","path","path","path","path","path","createHash","createHash","path","path","createHash","buildCompressionGuidelinesMarkdown","createHash","throwIfAborted","options","path","mkdir","writeFile","path","mkdir","writeFile","memoryKind","tombstoneBlocked","postWriteGuard","createHash","readFile","path","createHash","mkdir","writeFile","path","createHash","path","profile","readFile","outcome","createHash","path","os","os","createHash","capped","path","createHash","createHash","result","mkdir","readFile","writeFile","path","readFile","mkdir","writeFile","path","path","readFile","mkdir","writeFile","path","readFile","mkdir","writeFile","readdir","stat","unlink","path","readdir","path","stat","unlink","path","path","mkdir","readFile","readdir","writeFile","path","results","path","readFile","writeFile","mkdir","readdir","stat","path","path","stat","path","createHash","result","j","path","path","stat","fsp","path","stat","fsp","path","crypto","fsp","path","crypto","hashFile","fsp","crypto","path","log","stat","verifyResult","path","path","stat","fs","path","fs","path","crypto","stat","fs","path","parseFrontmatter","extractBody","crypto","fs","path","crypto","hashContent","fs","path","assertPathInsideRoot","readFileSafe","parseFrontmatter","extractBody","crypto","fs","path","stat","fs","isPathInside","path","parseFrontmatter","extractBody","readFileSafe","fs","path","crypto","DEFAULT_EXCLUDE","hashContent","crypto","fs","path","path","fs","manifestPath","manifestDir","crypto","stat","previousId","walkMd","hashContent","fs","os","path","os","path","fs","createHash","lstat","mkdir","readFile","readdir","stat","writeFile","path","date","createHash","path","readdir","lstat","stat","readFile","mkdir","writeFile","lstat","mkdir","readFile","realpath","writeFile","path","path","realpath","mkdir","writeFile","readFile","lstat"]}
|