@remnic/core 1.1.2 → 1.1.4
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/abort-error.js +1 -0
- package/dist/abstraction-nodes.js +1 -0
- package/dist/access-audit.js +1 -0
- package/dist/access-cli.js +72 -47
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.d.ts +50 -5
- package/dist/access-http.js +39 -16
- package/dist/access-idempotency.js +1 -0
- package/dist/access-mcp.d.ts +10 -5
- package/dist/access-mcp.js +38 -14
- package/dist/access-schema.d.ts +133 -13
- package/dist/access-schema.js +20 -1
- package/dist/access-service-CtXFnprR.d.ts +2033 -0
- package/dist/access-service.d.ts +11 -6
- package/dist/access-service.js +40 -15
- package/dist/active-memory-bridge.js +1 -0
- package/dist/active-recall.js +1 -0
- package/dist/active-recall.js.map +1 -1
- package/dist/behavior-learner.js +1 -0
- package/dist/behavior-learner.js.map +1 -1
- package/dist/behavior-signals.js +1 -0
- package/dist/bootstrap.d.ts +6 -4
- package/dist/bootstrap.js +1 -0
- package/dist/boxes.js +1 -0
- package/dist/briefing.d.ts +9 -5
- package/dist/briefing.js +10 -7
- package/dist/buffer-surprise-report.js +1 -0
- package/dist/buffer-surprise.js +1 -0
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +1 -0
- package/dist/calibration.d.ts +8 -1
- package/dist/calibration.js +10 -2
- package/dist/calibration.js.map +1 -1
- package/dist/capsule-cli.d.ts +137 -0
- package/dist/capsule-cli.js +34 -0
- package/dist/capsule-crypto-5CYAGVC5.js +18 -0
- package/dist/capsule-export-NZQPOTQ4.js +17 -0
- package/dist/capsule-export-NZQPOTQ4.js.map +1 -0
- package/dist/capsule-import-SDCUXLEV.js +16 -0
- package/dist/capsule-import-SDCUXLEV.js.map +1 -0
- package/dist/capsule-merge-DI7PNQ2H.js +189 -0
- package/dist/capsule-merge-DI7PNQ2H.js.map +1 -0
- package/dist/causal-behavior.js +1 -0
- package/dist/causal-behavior.js.map +1 -1
- package/dist/causal-chain.js +1 -0
- package/dist/causal-consolidation.js +12 -9
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +2 -1
- package/dist/causal-retrieval.js.map +1 -1
- package/dist/causal-trajectory-graph.js +4 -1
- package/dist/causal-trajectory-graph.js.map +1 -1
- package/dist/causal-trajectory.js +2 -1
- package/dist/chunk-2LSZVONP.js +67 -0
- package/dist/chunk-2LSZVONP.js.map +1 -0
- package/dist/chunk-32KD5IHZ.js +245 -0
- package/dist/chunk-32KD5IHZ.js.map +1 -0
- package/dist/chunk-3KIS4VGT.js +228 -0
- package/dist/chunk-3KIS4VGT.js.map +1 -0
- package/dist/chunk-3LCWFNVS.js +350 -0
- package/dist/chunk-3LCWFNVS.js.map +1 -0
- package/dist/chunk-43EKP2UK.js +26 -0
- package/dist/chunk-43EKP2UK.js.map +1 -0
- package/dist/chunk-457A4P3L.js +119 -0
- package/dist/chunk-457A4P3L.js.map +1 -0
- package/dist/{chunk-TMYO7B5P.js → chunk-47WOM4YW.js} +2 -2
- package/dist/{chunk-FVA6TGI3.js → chunk-52PDY6GD.js} +42 -2
- package/dist/chunk-52PDY6GD.js.map +1 -0
- package/dist/{chunk-ULYOGL6R.js → chunk-5HRY2WRF.js} +7 -3
- package/dist/chunk-5HRY2WRF.js.map +1 -0
- package/dist/{chunk-BOUYNNYD.js → chunk-67YLUWLG.js} +32 -13
- package/dist/{chunk-BOUYNNYD.js.map → chunk-67YLUWLG.js.map} +1 -1
- package/dist/chunk-6TBWYBJ3.js +236 -0
- package/dist/chunk-6TBWYBJ3.js.map +1 -0
- package/dist/chunk-74EMIVE4.js +329 -0
- package/dist/chunk-74EMIVE4.js.map +1 -0
- package/dist/chunk-74WWN7ZW.js +82 -0
- package/dist/chunk-74WWN7ZW.js.map +1 -0
- package/dist/chunk-A6XUJE5D.js +126 -0
- package/dist/chunk-A6XUJE5D.js.map +1 -0
- package/dist/{chunk-STGWEHYR.js → chunk-AEMBDV7M.js} +1187 -62
- package/dist/chunk-AEMBDV7M.js.map +1 -0
- package/dist/{chunk-PVICZTKG.js → chunk-AGZHRWPT.js} +5 -5
- package/dist/{chunk-PVICZTKG.js.map → chunk-AGZHRWPT.js.map} +1 -1
- package/dist/chunk-AJA46VX5.js +393 -0
- package/dist/chunk-AJA46VX5.js.map +1 -0
- package/dist/chunk-ASIQZXYO.js +277 -0
- package/dist/chunk-ASIQZXYO.js.map +1 -0
- package/dist/{chunk-DG6YMRDC.js → chunk-B2TL6GA2.js} +2 -2
- package/dist/chunk-BJMBJZ2Y.js +290 -0
- package/dist/chunk-BJMBJZ2Y.js.map +1 -0
- package/dist/chunk-BT7NVCML.js +79 -0
- package/dist/chunk-BT7NVCML.js.map +1 -0
- package/dist/chunk-CK5NTM2S.js +454 -0
- package/dist/chunk-CK5NTM2S.js.map +1 -0
- package/dist/{chunk-AYXIPSZO.js → chunk-CRU27Q4J.js} +2 -2
- package/dist/{chunk-UWB5LMWY.js → chunk-CUI2STX6.js} +526 -24
- package/dist/chunk-CUI2STX6.js.map +1 -0
- package/dist/{chunk-CUPFXL3J.js → chunk-EGEPUGN4.js} +4 -4
- package/dist/chunk-EGEPUGN4.js.map +1 -0
- package/dist/{chunk-3OGMS3PE.js → chunk-F5VQOQ2E.js} +3 -2
- package/dist/chunk-F5VQOQ2E.js.map +1 -0
- package/dist/chunk-FP2373TW.js +149 -0
- package/dist/chunk-FP2373TW.js.map +1 -0
- package/dist/{chunk-RBBWYEFJ.js → chunk-G2WADRQ3.js} +1 -1
- package/dist/chunk-G7D6GZ5J.js +48 -0
- package/dist/chunk-G7D6GZ5J.js.map +1 -0
- package/dist/chunk-H7XKCNR6.js +60 -0
- package/dist/chunk-H7XKCNR6.js.map +1 -0
- package/dist/{chunk-LOIMBRDE.js → chunk-HIRKCQGF.js} +1994 -412
- package/dist/chunk-HIRKCQGF.js.map +1 -0
- package/dist/chunk-IXEJRKCZ.js +18 -0
- package/dist/chunk-IXEJRKCZ.js.map +1 -0
- package/dist/chunk-IYY4MCPG.js +275 -0
- package/dist/chunk-IYY4MCPG.js.map +1 -0
- package/dist/{chunk-BECYBZLX.js → chunk-JWSENLQI.js} +502 -22
- package/dist/chunk-JWSENLQI.js.map +1 -0
- package/dist/chunk-KNKUID7G.js +183 -0
- package/dist/chunk-KNKUID7G.js.map +1 -0
- package/dist/chunk-L2IO2QPY.js +2036 -0
- package/dist/chunk-L2IO2QPY.js.map +1 -0
- package/dist/{chunk-ZAIM4TUE.js → chunk-LW2NMHDW.js} +46 -1
- package/dist/chunk-LW2NMHDW.js.map +1 -0
- package/dist/chunk-MDYG7VI7.js +48 -0
- package/dist/chunk-MDYG7VI7.js.map +1 -0
- package/dist/{chunk-VDX363PS.js → chunk-MUELDH4F.js} +10 -3
- package/dist/chunk-MUELDH4F.js.map +1 -0
- package/dist/chunk-MXC3AP5I.js +74 -0
- package/dist/chunk-MXC3AP5I.js.map +1 -0
- package/dist/chunk-NN3TS5BM.js +147 -0
- package/dist/chunk-NN3TS5BM.js.map +1 -0
- package/dist/{chunk-3YGHKTBF.js → chunk-NZS2BLTP.js} +963 -326
- package/dist/chunk-NZS2BLTP.js.map +1 -0
- package/dist/chunk-OA3L7BFR.js +183 -0
- package/dist/chunk-OA3L7BFR.js.map +1 -0
- package/dist/chunk-OZHRDTDX.js +240 -0
- package/dist/chunk-OZHRDTDX.js.map +1 -0
- package/dist/chunk-PCUKNJAZ.js +165 -0
- package/dist/chunk-PCUKNJAZ.js.map +1 -0
- package/dist/{chunk-6PFRXT4K.js → chunk-PFV5C235.js} +11 -6
- package/dist/chunk-PFV5C235.js.map +1 -0
- package/dist/chunk-PZ5AY32C.js +10 -0
- package/dist/chunk-PZ5AY32C.js.map +1 -0
- package/dist/{chunk-Y7R2XJ5Q.js → chunk-Q7FJ5ZHM.js} +6 -2
- package/dist/chunk-Q7FJ5ZHM.js.map +1 -0
- package/dist/{chunk-WCLICCGB.js → chunk-RILIVK4O.js} +91 -4
- package/dist/chunk-RILIVK4O.js.map +1 -0
- package/dist/{chunk-C2EFFULQ.js → chunk-RK2Y4XOM.js} +163 -20
- package/dist/chunk-RK2Y4XOM.js.map +1 -0
- package/dist/{chunk-TP4FZJIZ.js → chunk-RULE4VG5.js} +5 -1
- package/dist/chunk-RULE4VG5.js.map +1 -0
- package/dist/{chunk-PVPWZSSI.js → chunk-SMA4IMHV.js} +19 -3
- package/dist/chunk-SMA4IMHV.js.map +1 -0
- package/dist/{chunk-6YJHX2DL.js → chunk-TIFRGAKO.js} +242 -22
- package/dist/chunk-TIFRGAKO.js.map +1 -0
- package/dist/chunk-TUFG6VXY.js +875 -0
- package/dist/chunk-TUFG6VXY.js.map +1 -0
- package/dist/chunk-TYEOAFH3.js +251 -0
- package/dist/chunk-TYEOAFH3.js.map +1 -0
- package/dist/chunk-UKJAGEXH.js +260 -0
- package/dist/chunk-UKJAGEXH.js.map +1 -0
- package/dist/{chunk-KVBLZUKV.js → chunk-USFPPRAF.js} +93 -3
- package/dist/chunk-USFPPRAF.js.map +1 -0
- package/dist/{chunk-NBVAS5MT.js → chunk-V7TEH5I2.js} +6 -6
- package/dist/{chunk-GA5P7RST.js → chunk-VTJVUHRK.js} +22 -36
- package/dist/chunk-VTJVUHRK.js.map +1 -0
- package/dist/{chunk-SPI27QT6.js → chunk-W7WWT4FJ.js} +9 -4
- package/dist/chunk-W7WWT4FJ.js.map +1 -0
- package/dist/chunk-WIICJPET.js +45 -0
- package/dist/chunk-WIICJPET.js.map +1 -0
- package/dist/{chunk-VBVG2M5G.js → chunk-WPGJYVUH.js} +6 -2
- package/dist/chunk-WPGJYVUH.js.map +1 -0
- package/dist/{chunk-4HQS2HPX.js → chunk-WSZIHQBK.js} +29 -9
- package/dist/{chunk-4HQS2HPX.js.map → chunk-WSZIHQBK.js.map} +1 -1
- package/dist/{chunk-NZLQTHS5.js → chunk-WW3QQF4H.js} +4 -1
- package/dist/chunk-WW3QQF4H.js.map +1 -0
- package/dist/{chunk-DIXB44VE.js → chunk-X6VBWOVZ.js} +28 -13
- package/dist/chunk-X6VBWOVZ.js.map +1 -0
- package/dist/{chunk-XXVWLXSG.js → chunk-XQ4EJLUD.js} +64 -92
- package/dist/chunk-XQ4EJLUD.js.map +1 -0
- package/dist/{chunk-OC5OXUQ4.js → chunk-XRCYKJ3V.js} +780 -17
- package/dist/chunk-XRCYKJ3V.js.map +1 -0
- package/dist/{chunk-F5VP6YCB.js → chunk-Y4A6M3B6.js} +573 -156
- package/dist/chunk-Y4A6M3B6.js.map +1 -0
- package/dist/chunk-YNJHCGDT.js +309 -0
- package/dist/chunk-YNJHCGDT.js.map +1 -0
- package/dist/{chunk-L7IXWRYE.js → chunk-ZIBOQULP.js} +22 -13
- package/dist/chunk-ZIBOQULP.js.map +1 -0
- package/dist/{chunk-W6SL7OFG.js → chunk-ZTSE2ZJ6.js} +12 -2
- package/dist/{chunk-W6SL7OFG.js.map → chunk-ZTSE2ZJ6.js.map} +1 -1
- package/dist/chunking.js +1 -0
- package/dist/cipher-GVE2GQ5H.js +28 -0
- package/dist/cipher-GVE2GQ5H.js.map +1 -0
- package/dist/citations.js +1 -0
- package/dist/{cli-BkeRaYfk.d.ts → cli-lMql2FCr.d.ts} +26 -7
- package/dist/cli.d.ts +11 -6
- package/dist/cli.js +69 -34
- package/dist/codex-thread-key.js +1 -0
- package/dist/commitment-ledger.js +1 -0
- package/dist/compression-optimizer.js +1 -0
- package/dist/config.d.ts +2 -1
- package/dist/config.js +4 -1
- package/dist/connectors-cli-DFGtY2DB.d.ts +257 -0
- package/dist/connectors-cli.d.ts +2 -0
- package/dist/connectors-cli.js +22 -0
- package/dist/connectors-cli.js.map +1 -0
- package/dist/consolidation-operator.d.ts +65 -5
- package/dist/consolidation-operator.js +6 -1
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-provenance-check.js +3 -2
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/consolidation-undo.js +1 -0
- package/dist/consolidation-undo.js.map +1 -1
- package/dist/{contradiction-review-WIUBAR52.js → contradiction-review-5LTTVDQV.js} +2 -1
- package/dist/contradiction-review-5LTTVDQV.js.map +1 -0
- package/dist/{contradiction-scan-E3GJTI4F.js → contradiction-scan-3Z6YW7YA.js} +2 -1
- package/dist/{contradiction-scan-E3GJTI4F.js.map → contradiction-scan-3Z6YW7YA.js.map} +1 -1
- package/dist/cross-namespace-budget.js +1 -0
- package/dist/cue-anchors.js +1 -0
- package/dist/dashboard-runtime.js +1 -0
- package/dist/day-summary.js +1 -0
- package/dist/delinearize.js +1 -0
- package/dist/direct-answer-wiring.js +1 -0
- package/dist/direct-answer.js +1 -0
- package/dist/dreams-ledger-LR2NBAZE.js +286 -0
- package/dist/dreams-ledger-LR2NBAZE.js.map +1 -0
- package/dist/embedding-fallback.js +1 -0
- package/dist/engine-O6YWKQM3.js +28 -0
- package/dist/engine-O6YWKQM3.js.map +1 -0
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +10 -7
- package/dist/entity-schema.js +1 -0
- package/dist/evals.js +1 -0
- package/dist/evidence-pack.d.ts +16 -0
- package/dist/evidence-pack.js +8 -0
- package/dist/evidence-pack.js.map +1 -0
- package/dist/explicit-capture.d.ts +6 -4
- package/dist/explicit-capture.js +1 -0
- package/dist/extraction-judge-telemetry.js +1 -0
- package/dist/extraction-judge-training.js +1 -0
- package/dist/extraction-judge.js +1 -0
- package/dist/extraction.js +8 -7
- package/dist/fallback-llm.js +3 -2
- package/dist/first-start-migration-4MHQEOSD.js +263 -0
- package/dist/first-start-migration-4MHQEOSD.js.map +1 -0
- package/dist/forget-PLR6J5DN.js +69 -0
- package/dist/forget-PLR6J5DN.js.map +1 -0
- package/dist/framework-CyHYDcri.d.ts +153 -0
- package/dist/fs-utils-IRVUFB6G.js +30 -0
- package/dist/fs-utils-IRVUFB6G.js.map +1 -0
- package/dist/graph-dashboard-diff.js +1 -0
- package/dist/graph-dashboard-key.js +1 -0
- package/dist/graph-dashboard-parser.js +1 -0
- package/dist/graph-edge-decay-PWB63GRE.js +207 -0
- package/dist/graph-edge-decay-PWB63GRE.js.map +1 -0
- package/dist/graph-edge-reinforcement.d.ts +81 -0
- package/dist/graph-edge-reinforcement.js +24 -0
- package/dist/graph-edge-reinforcement.js.map +1 -0
- package/dist/graph-events.d.ts +87 -0
- package/dist/graph-events.js +14 -0
- package/dist/graph-events.js.map +1 -0
- package/dist/graph-recall.js +1 -0
- package/dist/graph-retrieval.js +1 -0
- package/dist/graph-snapshot.d.ts +112 -0
- package/dist/graph-snapshot.js +19 -0
- package/dist/graph-snapshot.js.map +1 -0
- package/dist/graph.d.ts +105 -7
- package/dist/graph.js +20 -3
- package/dist/harmonic-retrieval.js +1 -0
- package/dist/himem.js +1 -0
- package/dist/hygiene.js +1 -0
- package/dist/identity-continuity.js +1 -0
- package/dist/importance.js +1 -0
- package/dist/index.d.ts +574 -13
- package/dist/index.js +337 -69
- package/dist/index.js.map +1 -1
- package/dist/intent.js +1 -0
- package/dist/json-extract.js +1 -0
- package/dist/json-store.js +1 -0
- package/dist/kdf-7S6RWKLZ.js +26 -0
- package/dist/kdf-7S6RWKLZ.js.map +1 -0
- package/dist/legacy-hook-compat.js +1 -0
- package/dist/legacy-hook-compat.js.map +1 -1
- package/dist/lifecycle.js +1 -0
- package/dist/live-connectors-runner.d.ts +48 -0
- package/dist/live-connectors-runner.js +17 -0
- package/dist/live-connectors-runner.js.map +1 -0
- package/dist/local-llm.js +1 -0
- package/dist/logger.js +1 -0
- package/dist/memory-action-policy.js +1 -0
- package/dist/memory-cache.d.ts +2 -1
- package/dist/memory-cache.js +4 -1
- package/dist/memory-governance-JZHZDOLN.js +37 -0
- package/dist/memory-governance-JZHZDOLN.js.map +1 -0
- package/dist/memory-lifecycle-ledger-utils.d.ts +2 -1
- package/dist/memory-lifecycle-ledger-utils.js +4 -1
- package/dist/memory-projection-format.js +1 -0
- package/dist/{memory-projection-store-DeSXPh1j.d.ts → memory-projection-store-CY8TU40w.d.ts} +2 -1
- package/dist/memory-projection-store.d.ts +1 -1
- package/dist/memory-projection-store.js +2 -1
- package/dist/memory-worth-bench.js +1 -0
- package/dist/memory-worth-bench.js.map +1 -1
- package/dist/memory-worth-filter.js +1 -0
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/memory-worth-outcomes.js +1 -0
- package/dist/memory-worth.js +1 -0
- package/dist/metadata-FC3XPDRQ.js +21 -0
- package/dist/metadata-FC3XPDRQ.js.map +1 -0
- package/dist/migrate-from-identity-anchor-TTEDEJGX.js +8 -0
- package/dist/migrate-from-identity-anchor-TTEDEJGX.js.map +1 -0
- package/dist/model-registry.js +1 -0
- package/dist/models-json.js +1 -0
- package/dist/native-knowledge.js +1 -0
- package/dist/negative.js +1 -0
- package/dist/objective-state-writers.js +1 -0
- package/dist/objective-state-writers.js.map +1 -1
- package/dist/objective-state.js +1 -0
- package/dist/openai-chat-compat.js +1 -0
- package/dist/operator-toolkit.d.ts +46 -2
- package/dist/operator-toolkit.js +29 -17
- package/dist/opik-exporter.js +1 -0
- package/dist/opik-exporter.js.map +1 -1
- package/dist/{orchestrator-CmJ-NTdJ.d.ts → orchestrator-ChkesB8U.d.ts} +177 -13
- package/dist/orchestrator.d.ts +6 -4
- package/dist/orchestrator.js +57 -41
- package/dist/page-versioning.js +1 -0
- package/dist/path-RMTY5Y5A.js +9 -0
- package/dist/path-RMTY5Y5A.js.map +1 -0
- package/dist/patterns-cli.d.ts +160 -0
- package/dist/patterns-cli.js +29 -0
- package/dist/patterns-cli.js.map +1 -0
- package/dist/peers-6OSQ3NK6.js +44 -0
- package/dist/peers-6OSQ3NK6.js.map +1 -0
- package/dist/plugin-id.js +1 -0
- package/dist/policy-runtime.js +1 -0
- package/dist/{port-BADbLZU5.d.ts → port-hqGnoStS.d.ts} +6 -0
- package/dist/profiling.js +1 -0
- package/dist/purge-6ATBGT77.js +205 -0
- package/dist/purge-6ATBGT77.js.map +1 -0
- package/dist/qmd-recall-cache.d.ts +1 -1
- package/dist/qmd-recall-cache.js +1 -0
- package/dist/qmd.d.ts +2 -1
- package/dist/qmd.js +4 -3
- package/dist/reasoning-trace-recall.js +1 -0
- package/dist/reasoning-trace-types.js +1 -0
- package/dist/recall-audit-anomaly.js +1 -0
- package/dist/recall-audit.js +1 -0
- package/dist/recall-disclosure-escalation.d.ts +84 -0
- package/dist/recall-disclosure-escalation.js +14 -0
- package/dist/recall-disclosure-escalation.js.map +1 -0
- package/dist/recall-explain-renderer.js +4 -1
- package/dist/recall-mmr.js +1 -0
- package/dist/recall-qos.js +1 -0
- package/dist/recall-query-policy.js +1 -0
- package/dist/recall-state.d.ts +7 -0
- package/dist/recall-state.js +2 -1
- package/dist/recall-tag-filter.d.ts +56 -0
- package/dist/recall-tag-filter.js +14 -0
- package/dist/recall-tag-filter.js.map +1 -0
- package/dist/recall-tokenization.js +1 -0
- package/dist/recall-xray-cli.d.ts +9 -2
- package/dist/recall-xray-cli.js +9 -4
- package/dist/recall-xray-renderer.js +4 -1
- package/dist/recall-xray.d.ts +116 -2
- package/dist/recall-xray.js +9 -3
- package/dist/reconstruct.js +1 -0
- package/dist/release-changelog.js +2 -0
- package/dist/release-changelog.js.map +1 -1
- package/dist/relevance.js +1 -0
- package/dist/rerank.js +1 -0
- package/dist/{resolution-QBTDHTG7.js → resolution-YGIBORXI.js} +2 -1
- package/dist/{resolution-QBTDHTG7.js.map → resolution-YGIBORXI.js.map} +1 -1
- package/dist/resolve-auth-token.d.ts +51 -0
- package/dist/resolve-auth-token.js +12 -0
- package/dist/resolve-auth-token.js.map +1 -0
- package/dist/resolve-provider-secret.d.ts +9 -1
- package/dist/resolve-provider-secret.js +4 -1
- package/dist/resume-bundles.js +4 -3
- package/dist/retrieval-agents.d.ts +1 -1
- package/dist/retrieval-agents.js +1 -0
- package/dist/retrieval-tiers.js +1 -0
- package/dist/retrieval.js +1 -0
- package/dist/sanitize.js +1 -0
- package/dist/schemas.d.ts +15 -2
- package/dist/schemas.js +2 -1
- package/dist/sdk-compat.js +1 -0
- package/dist/sdk-compat.js.map +1 -1
- package/dist/secure-store-4R2GSO7S.js +156 -0
- package/dist/secure-store-4R2GSO7S.js.map +1 -0
- package/dist/semantic-chunking.js +1 -0
- package/dist/{semantic-consolidation-CxJU6MJk.d.ts → semantic-consolidation-ByBXb-sf.d.ts} +3 -3
- package/dist/semantic-consolidation.d.ts +2 -2
- package/dist/semantic-consolidation.js +12 -7
- package/dist/semantic-rule-promotion.d.ts +1 -1
- package/dist/semantic-rule-promotion.js +10 -7
- package/dist/semantic-rule-verifier.d.ts +1 -1
- package/dist/semantic-rule-verifier.js +10 -7
- package/dist/session-integrity.js +1 -0
- package/dist/session-observer-bands.js +1 -0
- package/dist/session-observer-state.js +1 -0
- package/dist/session-toggles.js +2 -0
- package/dist/session-toggles.js.map +1 -1
- package/dist/signal.js +1 -0
- package/dist/skills-registry.js +2 -0
- package/dist/skills-registry.js.map +1 -1
- package/dist/source-attribution.js +1 -0
- package/dist/state-NCHQ4TRG.js +8 -0
- package/dist/state-NCHQ4TRG.js.map +1 -0
- package/dist/state-store-3EH7HYIN.js +16 -0
- package/dist/state-store-3EH7HYIN.js.map +1 -0
- package/dist/storage.d.ts +76 -2
- package/dist/storage.js +9 -6
- package/dist/store-contract.js +1 -0
- package/dist/summarizer.js +5 -4
- package/dist/summary-snapshot.js +1 -0
- package/dist/temporal-index.js +1 -0
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/temporal-supersession.js +2 -1
- package/dist/temporal-validity.d.ts +52 -0
- package/dist/temporal-validity.js +14 -0
- package/dist/temporal-validity.js.map +1 -0
- package/dist/threading.js +1 -0
- package/dist/tier-migration.d.ts +2 -2
- package/dist/tier-migration.js +1 -0
- package/dist/tier-routing.js +1 -0
- package/dist/tier-stats-62ZVDFKS.js +152 -0
- package/dist/tier-stats-62ZVDFKS.js.map +1 -0
- package/dist/tmt.js +1 -0
- package/dist/tokens.js +1 -0
- package/dist/topics.js +1 -0
- package/dist/trace-C5ETWBEF.js +290 -0
- package/dist/trace-C5ETWBEF.js.map +1 -0
- package/dist/transcript.js +1 -0
- package/dist/trust-zones.js +1 -0
- package/dist/tui-RI7P6PBS.js +13 -0
- package/dist/tui-RI7P6PBS.js.map +1 -0
- package/dist/types-V3FJ26TF.js +30 -0
- package/dist/types-V3FJ26TF.js.map +1 -0
- package/dist/types.d.ts +634 -9
- package/dist/types.js +10 -3
- package/dist/utility-learner.js +1 -0
- package/dist/utility-runtime.js +1 -0
- package/dist/utility-telemetry.js +1 -0
- package/dist/verified-recall.js +10 -7
- package/dist/version-utils.js +1 -0
- package/dist/whitespace.js +1 -0
- package/dist/work-product-ledger.js +1 -0
- package/package.json +7 -3
- package/scripts/ensure-better-sqlite3.mjs +124 -0
- package/dist/access-service-Br8ZydTK.d.ts +0 -827
- package/dist/chunk-3OGMS3PE.js.map +0 -1
- package/dist/chunk-3YGHKTBF.js.map +0 -1
- package/dist/chunk-6PFRXT4K.js.map +0 -1
- package/dist/chunk-6YJHX2DL.js.map +0 -1
- package/dist/chunk-BECYBZLX.js.map +0 -1
- package/dist/chunk-C2EFFULQ.js.map +0 -1
- package/dist/chunk-CUPFXL3J.js.map +0 -1
- package/dist/chunk-DIXB44VE.js.map +0 -1
- package/dist/chunk-F5VP6YCB.js.map +0 -1
- package/dist/chunk-FVA6TGI3.js.map +0 -1
- package/dist/chunk-GA5P7RST.js.map +0 -1
- package/dist/chunk-KVBLZUKV.js.map +0 -1
- package/dist/chunk-L7IXWRYE.js.map +0 -1
- package/dist/chunk-LOIMBRDE.js.map +0 -1
- package/dist/chunk-LTCGGW2D.js +0 -14
- package/dist/chunk-LTCGGW2D.js.map +0 -1
- package/dist/chunk-NZLQTHS5.js.map +0 -1
- package/dist/chunk-OC5OXUQ4.js.map +0 -1
- package/dist/chunk-PVPWZSSI.js.map +0 -1
- package/dist/chunk-SPI27QT6.js.map +0 -1
- package/dist/chunk-STGWEHYR.js.map +0 -1
- package/dist/chunk-TP4FZJIZ.js.map +0 -1
- package/dist/chunk-ULYOGL6R.js.map +0 -1
- package/dist/chunk-UWB5LMWY.js.map +0 -1
- package/dist/chunk-VBVG2M5G.js.map +0 -1
- package/dist/chunk-VDX363PS.js.map +0 -1
- package/dist/chunk-WCLICCGB.js.map +0 -1
- package/dist/chunk-X6GF3FX2.js +0 -26
- package/dist/chunk-X6GF3FX2.js.map +0 -1
- package/dist/chunk-XXVWLXSG.js.map +0 -1
- package/dist/chunk-Y7R2XJ5Q.js.map +0 -1
- package/dist/chunk-ZAIM4TUE.js.map +0 -1
- package/dist/engine-72LSIWQP.js +0 -23
- /package/dist/{contradiction-review-WIUBAR52.js.map → capsule-cli.js.map} +0 -0
- /package/dist/{engine-72LSIWQP.js.map → capsule-crypto-5CYAGVC5.js.map} +0 -0
- /package/dist/{chunk-TMYO7B5P.js.map → chunk-47WOM4YW.js.map} +0 -0
- /package/dist/{chunk-DG6YMRDC.js.map → chunk-B2TL6GA2.js.map} +0 -0
- /package/dist/{chunk-AYXIPSZO.js.map → chunk-CRU27Q4J.js.map} +0 -0
- /package/dist/{chunk-RBBWYEFJ.js.map → chunk-G2WADRQ3.js.map} +0 -0
- /package/dist/{chunk-NBVAS5MT.js.map → chunk-V7TEH5I2.js.map} +0 -0
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/orchestrator.ts","../src/migrate/from-engram.ts","../src/procedural/procedure-recall.ts","../src/maintenance/memory-governance-cron.ts","../src/dedup/semantic.ts","../src/taxonomy/default-taxonomy.ts","../src/taxonomy/resolver-doc-generator.ts","../src/taxonomy/taxonomy-loader.ts","../src/lcm/schema.ts","../src/lcm/archive.ts","../src/lcm/dag.ts","../src/lcm/summarizer.ts","../src/lcm/recall.ts","../src/lcm/queue.ts","../src/lcm/engine.ts","../src/lcm/tools.ts","../src/conversation-index/chunker.ts","../src/conversation-index/cleanup.ts","../src/coding/git-context.ts","../src/coding/coding-namespace.ts"],"sourcesContent":["import { log } from \"./logger.js\";\nimport path from \"node:path\";\nimport os from \"node:os\";\nimport { createHash, randomBytes } from \"node:crypto\";\nimport { existsSync } from \"node:fs\";\nimport {\n mkdir,\n readdir,\n readFile,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { formatDaySummaryMemories } from \"./day-summary.js\";\nimport { resolveHomeDir } from \"./runtime/env.js\";\nimport { migrateFromEngram } from \"./migrate/from-engram.js\";\nimport { SmartBuffer } from \"./buffer.js\";\nimport { chunkContent, type ChunkingConfig } from \"./chunking.js\";\nimport { semanticChunkContent, type SemanticChunkResult } from \"./semantic-chunking.js\";\nimport { ExtractionEngine } from \"./extraction.js\";\nimport { isAboveImportanceThreshold, scoreImportance } from \"./importance.js\";\nimport {\n judgeFactDurability,\n createVerdictCache,\n createDeferCountMap,\n getVerdictKind,\n validateProcedureExtraction,\n type JudgeBatchResult,\n type JudgeCandidate,\n type JudgeVerdict,\n} from \"./extraction-judge.js\";\nimport {\n EXTRACTION_JUDGE_VERDICT_CATEGORY,\n recordJudgeVerdict,\n} from \"./extraction-judge-telemetry.js\";\nimport { recordJudgeTrainingPair } from \"./extraction-judge-training.js\";\nimport { buildProcedurePersistBody } from \"./procedural/procedure-types.js\";\nimport { buildProcedureRecallSection } from \"./procedural/procedure-recall.js\";\nimport {\n attachCitation,\n type CitationContext,\n hasCitationForTemplate,\n stripCitationForTemplate,\n} from \"./source-attribution.js\";\n// stripCitation (default-format only) is intentionally NOT used on the\n// legacy archive path — replaced by skip-with-warning (Finding 2 — Urgw).\n// stripCitationForTemplate IS used for pre-tagged dedup canonicalization.\nimport { findUnresolvedEntityRefs } from \"./reconstruct.js\";\nimport type {\n SearchBackend,\n SearchExecutionOptions,\n SearchQueryOptions,\n} from \"./search/port.js\";\nimport {\n createSearchBackend,\n createConversationIndexRuntime,\n} from \"./search/factory.js\";\nimport { NoopSearchBackend } from \"./search/noop-backend.js\";\nimport {\n compareEntityTimestamps,\n StorageManager,\n ContentHashIndex,\n fingerprintEntityStructuredFacts,\n normalizeEntityName,\n normalizeAttributePairs,\n parseEntityFile,\n} from \"./storage.js\";\nimport { sanitizeMemoryContent } from \"./sanitize.js\";\nimport { ThreadingManager } from \"./threading.js\";\nimport { extractTopics } from \"./topics.js\";\nimport { TranscriptManager } from \"./transcript.js\";\nimport { HourlySummarizer } from \"./summarizer.js\";\nimport { LocalLlmClient } from \"./local-llm.js\";\nimport { FallbackLlmClient } from \"./fallback-llm.js\";\nimport {\n ensureDaySummaryCron,\n ensureNightlyGovernanceCron,\n ensureProceduralMiningCron,\n ensureContradictionScanCron,\n} from \"./maintenance/memory-governance-cron.js\";\nimport { ModelRegistry } from \"./model-registry.js\";\nimport { applyRuntimeRetrievalPolicy, expandQuery } from \"./retrieval.js\";\nimport {\n mergeWithAgentResults,\n runDirectAgent,\n runTemporalAgent,\n shouldRunAgent,\n type ParallelSearchResult,\n} from \"./retrieval-agents.js\";\nimport { RerankCache, rerankLocalOrNoop } from \"./rerank.js\";\nimport {\n applyMemoryWorthFilter,\n buildMemoryWorthCounterMap,\n type MemoryWorthCounters,\n} from \"./memory-worth-filter.js\";\nimport { reorderRecallResultsWithMmr } from \"./recall-mmr.js\";\nimport { applyReasoningTraceBoost } from \"./reasoning-trace-recall.js\";\nimport {\n applyTemporalSupersession,\n normalizeSupersessionKey,\n shouldFilterSupersededFromRecall,\n} from \"./temporal-supersession.js\";\nimport { RelevanceStore } from \"./relevance.js\";\nimport { NegativeExampleStore } from \"./negative.js\";\nimport {\n LastRecallStore,\n type LastRecallBudgetSummary,\n TierMigrationStatusStore,\n clampGraphRecallExpandedEntries,\n type GraphRecallExpandedEntry,\n type LastRecallSnapshot,\n type TierMigrationCycleSummary,\n type TierMigrationStatusSnapshot,\n} from \"./recall-state.js\";\nimport {\n buildXraySnapshot,\n type RecallFilterTrace,\n type RecallXrayResult,\n type RecallXraySnapshot,\n type RecallXrayServedBy,\n} from \"./recall-xray.js\";\nimport {\n recordEvalShadowRecall,\n type EvalShadowRecallRecord,\n} from \"./evals.js\";\nimport { SessionObserverState } from \"./session-observer-state.js\";\nimport {\n abortError as sharedAbortError,\n isAbortError,\n throwIfAborted as sharedThrowIfAborted,\n} from \"./abort-error.js\";\nimport { CODEX_THREAD_KEY_PREFIX } from \"./codex-thread-key.js\";\nimport { isDisagreementPrompt } from \"./signal.js\";\nimport { lintWorkspaceFiles, rotateMarkdownFileToArchive } from \"./hygiene.js\";\nimport { EmbeddingFallback } from \"./embedding-fallback.js\";\nimport {\n decideSemanticDedup,\n type SemanticDedupDecision,\n type SemanticDedupHit,\n} from \"./dedup/semantic.js\";\nimport { BootstrapEngine } from \"./bootstrap.js\";\nimport { parseQmdExplain } from \"./qmd.js\";\nimport {\n buildQmdRecallCacheKey,\n getCachedQmdRecall,\n setCachedQmdRecall,\n} from \"./qmd-recall-cache.js\";\nimport {\n buildEntityRecallSection,\n entityRecentTranscriptLookbackHours,\n readRecentEntityTranscriptEntries,\n} from \"./entity-retrieval.js\";\nimport {\n hasBroadGraphIntent,\n inferIntentFromText,\n intentCompatibilityScore,\n planRecallMode,\n} from \"./intent.js\";\nimport { buildRecallQueryPolicy } from \"./recall-query-policy.js\";\nimport { parseMemoryActionEligibilityContext } from \"./schemas.js\";\nimport { evaluateMemoryActionPolicy } from \"./memory-action-policy.js\";\nimport {\n buildCompressionGuidelinesMarkdown as buildCompressionGuidelinesMarkdownV2,\n computeCompressionGuidelineCandidate,\n refineCompressionGuidelineCandidateSemantically,\n renderCompressionGuidelinesMarkdown,\n} from \"./compression-optimizer.js\";\nimport { createRecallSectionMetricRecorder } from \"./recall-qos.js\";\nimport { BoxBuilder, type BoxFrontmatter } from \"./boxes.js\";\nimport { classifyMemoryKind } from \"./himem.js\";\nimport { TmtBuilder } from \"./tmt.js\";\nimport {\n decideLifecycleTransition,\n resolveLifecycleState,\n type LifecycleSignals,\n} from \"./lifecycle.js\";\nimport {\n indexMemoriesBatch,\n clearIndexes,\n indexesExist,\n deindexMemory,\n queryByDateRangeAsync,\n queryByTagsAsync,\n isTemporalQuery,\n recencyWindowFromPrompt,\n extractTagsFromPrompt,\n resolvePromptTagPrefilterAsync,\n} from \"./temporal-index.js\";\nimport { GraphIndex } from \"./graph.js\";\nimport {\n searchCausalTrajectories,\n type CausalTrajectorySearchResult,\n} from \"./causal-trajectory.js\";\nimport {\n searchObjectiveStateSnapshots,\n type ObjectiveStateSearchResult,\n} from \"./objective-state.js\";\nimport {\n listTrustZoneRecords,\n searchTrustZoneRecords,\n type TrustZoneSearchResult,\n} from \"./trust-zones.js\";\nimport { tryDirectAnswer, type DirectAnswerSources } from \"./direct-answer-wiring.js\";\nimport { DEFAULT_TAXONOMY } from \"./taxonomy/index.js\";\nimport {\n searchHarmonicRetrieval,\n type HarmonicRetrievalResult,\n} from \"./harmonic-retrieval.js\";\nimport {\n searchVerifiedEpisodes,\n type VerifiedEpisodeResult,\n} from \"./verified-recall.js\";\nimport {\n searchVerifiedSemanticRules,\n type VerifiedSemanticRuleResult,\n} from \"./semantic-rule-verifier.js\";\nimport { applyCommitmentLedgerLifecycle } from \"./commitment-ledger.js\";\nimport {\n searchWorkProductLedgerEntries,\n type WorkProductLedgerSearchResult,\n} from \"./work-product-ledger.js\";\nimport {\n collectNativeKnowledgeChunks,\n formatNativeKnowledgeSection,\n searchNativeKnowledge,\n} from \"./native-knowledge.js\";\nimport { normalizeReplaySessionKey, type ReplayTurn } from \"./replay/types.js\";\nimport type { ImportTurn } from \"./bulk-import/types.js\";\nimport {\n confidenceTier,\n type MemoryIntent,\n type MemorySummary,\n} from \"./types.js\";\nimport { LcmEngine } from \"./lcm/index.js\";\nimport { shouldSkipImplicitExtraction } from \"./explicit-capture.js\";\nimport {\n findSimilarClusters,\n buildConsolidationPrompt,\n parseConsolidationResponse,\n buildOperatorAwareConsolidationPrompt,\n parseOperatorAwareConsolidationResponse,\n chooseConsolidationOperator,\n buildExtensionsBlockForConsolidation,\n materializeAfterSemanticConsolidation,\n type SemanticConsolidationResult,\n} from \"./semantic-consolidation.js\";\nimport { chunkTranscriptEntries } from \"./conversation-index/chunker.js\";\nimport { writeConversationChunks } from \"./conversation-index/indexer.js\";\nimport { cleanupConversationChunks } from \"./conversation-index/cleanup.js\";\nimport {\n type ConversationIndexBackend,\n type ConversationIndexBackendInspection,\n type ConversationQmdRuntime,\n} from \"./conversation-index/backend.js\";\nimport { NamespaceStorageRouter } from \"./namespaces/storage.js\";\nimport {\n canReadNamespace,\n defaultNamespaceForPrincipal,\n recallNamespacesForPrincipal,\n resolvePrincipal,\n} from \"./namespaces/principal.js\";\nimport {\n combineNamespaces,\n resolveCodingNamespaceOverlay,\n} from \"./coding/coding-namespace.js\";\nimport type { CodingContext } from \"./types.js\";\nimport { NamespaceSearchRouter } from \"./namespaces/search.js\";\nimport { SharedContextManager } from \"./shared-context/manager.js\";\nimport {\n CompoundingEngine,\n defaultTierMigrationCycleBudget,\n} from \"./compounding/engine.js\";\n// IRC preference consolidation — used by eval adapter directly;\n// orchestrator integration planned for future PR.\n// import { consolidatePreferences, buildQueryAwarePreferenceSection, synthesizePreferencesFromLcm } from \"./compounding/preference-consolidator.js\";\nimport { TierMigrationExecutor } from \"./tier-migration.js\";\nimport { decideTierTransition, type MemoryTier } from \"./tier-routing.js\";\nimport {\n selectRouteRule,\n type RouteRule,\n type RoutingEngineOptions,\n} from \"./routing/engine.js\";\nimport { RoutingRulesStore } from \"./routing/store.js\";\nimport {\n PolicyRuntimeManager,\n type RuntimePolicyValues,\n} from \"./policy-runtime.js\";\nimport {\n applyUtilityPromotionRuntimePolicy,\n applyUtilityRankingRuntimeDelta,\n loadUtilityRuntimeValues,\n type UtilityRuntimeValues,\n} from \"./utility-runtime.js\";\nimport {\n buildBehaviorSignalsForMemory,\n dedupeBehaviorSignalsByMemoryAndHash,\n} from \"./behavior-signals.js\";\nimport { ProfilingCollector } from \"./profiling.js\";\nimport type {\n AccessTrackingEntry,\n BehaviorLoopPolicyState,\n BehaviorSignalEvent,\n BootstrapOptions,\n BootstrapResult,\n BufferTurn,\n ContinuityIncidentRecord,\n ConsolidationObservation,\n EngramTraceEvent,\n ExtractionResult,\n IdentityInjectionMode,\n LifecycleState,\n MemoryActionEvent,\n MemoryActionType,\n MemoryLink,\n MemoryFile,\n MemoryFrontmatter,\n DaySummaryResult,\n PluginConfig,\n QmdSearchResult,\n RecallPlanMode,\n RecallSectionConfig,\n RecallTierExplain,\n EntityStructuredSection,\n EntityTimelineEntry,\n} from \"./types.js\";\n\nexport function dedupeEntitySynthesisEvidenceEntries(\n entries: EntityTimelineEntry[],\n): EntityTimelineEntry[] {\n const dedupedEvidenceEntries: EntityTimelineEntry[] = [];\n const evidenceByFact = new Map<string, {\n newest: EntityTimelineEntry;\n oldest: EntityTimelineEntry;\n }>();\n\n for (const entry of entries) {\n const normalizedFact = entry.text.trim();\n if (!normalizedFact) continue;\n const existing = evidenceByFact.get(normalizedFact);\n if (!existing) {\n evidenceByFact.set(normalizedFact, { newest: entry, oldest: entry });\n continue;\n }\n if (compareEntityTimestamps(entry.timestamp, existing.newest.timestamp) > 0) {\n existing.newest = entry;\n }\n if (compareEntityTimestamps(entry.timestamp, existing.oldest.timestamp) < 0) {\n existing.oldest = entry;\n }\n }\n\n for (const { newest, oldest } of evidenceByFact.values()) {\n dedupedEvidenceEntries.push(newest);\n const newestKey = [\n newest.timestamp,\n newest.source ?? \"\",\n newest.sessionKey ?? \"\",\n newest.principal ?? \"\",\n newest.text,\n ].join(\"\\u0000\");\n const oldestKey = [\n oldest.timestamp,\n oldest.source ?? \"\",\n oldest.sessionKey ?? \"\",\n oldest.principal ?? \"\",\n oldest.text,\n ].join(\"\\u0000\");\n if (oldestKey !== newestKey) {\n dedupedEvidenceEntries.push(oldest);\n }\n }\n\n return dedupedEvidenceEntries;\n}\n\nfunction flattenStructuredSectionEvidence(\n sections: EntityStructuredSection[] | undefined,\n): EntityTimelineEntry[] {\n return (sections ?? []).flatMap((section) =>\n section.facts\n .map((fact) => fact.trim())\n .filter((fact) => fact.length > 0)\n .map((fact) => ({\n timestamp: \"\",\n text: fact,\n source: `section:${section.title}`,\n })),\n );\n}\n\nfunction fingerprintEntitySynthesisEvidence(entity: {\n timeline: EntityTimelineEntry[];\n structuredSections?: EntityStructuredSection[];\n}): string {\n const fingerprint = createHash(\"sha256\");\n const timelineEntries = entity.timeline\n .map((entry) => [\n entry.timestamp,\n entry.source ?? \"\",\n entry.sessionKey ?? \"\",\n entry.principal ?? \"\",\n entry.text,\n ].join(\"\\u0000\"))\n .sort();\n fingerprint.update(timelineEntries.join(\"\\u0001\"));\n fingerprint.update(\"\\u0002\");\n fingerprint.update(fingerprintEntityStructuredFacts(entity) ?? \"\");\n return fingerprint.digest(\"hex\");\n}\n\nexport interface GraphRecallSnapshot {\n recordedAt: string;\n mode: RecallPlanMode | string;\n queryHash: string;\n queryLength: number;\n namespaces: string[];\n seedCount: number;\n expandedCount: number;\n seeds: string[];\n expanded: GraphRecallExpandedEntry[];\n status?: \"completed\" | \"skipped\" | \"aborted\";\n reason?: string;\n shadowMode?: boolean;\n queryIntent?: MemoryIntent;\n seedResults?: GraphRecallRankedResult[];\n finalResults?: GraphRecallRankedResult[];\n shadowComparison?: GraphRecallShadowComparison;\n}\n\nexport interface GraphRecallRankedResult {\n path: string;\n score: number;\n docid?: string;\n sourceLabels: string[];\n}\n\nexport interface GraphRecallShadowComparison {\n baselineCount: number;\n graphCount: number;\n overlapCount: number;\n overlapRatio: number;\n averageOverlapDelta: number;\n}\n\nexport interface IntentDebugSnapshot {\n recordedAt: string;\n promptHash: string;\n promptLength: number;\n retrievalQueryHash: string;\n retrievalQueryLength: number;\n plannerEnabled: boolean;\n plannedMode: RecallPlanMode;\n effectiveMode: RecallPlanMode;\n recallResultLimit: number;\n queryIntent: MemoryIntent;\n graphExpandedIntentDetected: boolean;\n graphDecision: {\n status: \"not_requested\" | \"skipped\" | \"completed\" | \"aborted\";\n reason?: string;\n shadowMode: boolean;\n qmdAvailable: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n };\n}\n\nexport interface QmdRecallSnapshot {\n recordedAt: string;\n queryHash: string;\n queryLength: number;\n collection?: string;\n namespaces: string[];\n fetchLimit: number;\n primaryResultCount: number;\n hybridResultCount: number;\n queryAwareSeedCount: number;\n resultCount: number;\n intentHint?: string;\n explainEnabled: boolean;\n hybridTopUpUsed: boolean;\n hybridTopUpSkippedReason?: string;\n results: QmdSearchResult[];\n}\n\nexport interface RecallModeDecision {\n plannedMode: RecallPlanMode;\n effectiveMode: RecallPlanMode;\n graphExpandedIntentDetected: boolean;\n graphReason?: string;\n}\n\n/**\n * Map the orchestrator's internal `recallSource` strings to the\n * X-ray `servedBy` vocabulary (issue #570 PR 1). The X-ray tier\n * ladder intentionally flattens QMD / embedding / cold-fallback to\n * the `hybrid` tier because they all materialize through the same\n * hybrid BM25+vector pipeline from the caller's perspective. The\n * `recent_scan` path gets its own dedicated tier because it bypasses\n * the hybrid pipeline entirely. `none` is treated as `hybrid` on the\n * theory that a query that returned nothing still routed through the\n * hybrid pipeline — but callers should normally gate capture on\n * `recalledMemoryIds.length > 0`.\n */\nfunction mapRecallSourceToXrayServedBy(\n source:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\",\n): RecallXrayServedBy {\n // Exhaustive switch: every current union member is explicitly\n // listed so TypeScript surfaces a compile error if a new source is\n // added without a deliberate mapping. The `never`-typed fallthrough\n // keeps the function total at runtime — if the caller passes an\n // unexpected value that slipped past the type system (e.g. a JSON\n // deserialization), we still fall back to `hybrid`.\n switch (source) {\n case \"recent_scan\":\n return \"recent-scan\";\n case \"hot_qmd\":\n case \"hot_embedding\":\n case \"cold_fallback\":\n case \"none\":\n return \"hybrid\";\n }\n const _exhaustive: never = source;\n void _exhaustive;\n return \"hybrid\";\n}\n\nexport interface RecallInvocationOptions {\n namespace?: string;\n topK?: number;\n mode?: RecallPlanMode;\n abortSignal?: AbortSignal;\n /**\n * Capture a `RecallXraySnapshot` for this recall (issue #570). When\n * `true`, the orchestrator builds a snapshot from the data it has\n * already gathered and stashes it in memory, accessible via\n * `getLastXraySnapshot()`. When `false` or absent, nothing is\n * captured and recall behavior is unchanged (schema-only slice).\n */\n xrayCapture?: boolean;\n /**\n * Per-invocation override for `recallBudgetChars` (issue #570 PR 3/4).\n * Flows through `getRecallBudgetChars()` for this recall only — no\n * shared config mutation, so concurrent recalls on the same\n * orchestrator are not affected (CLAUDE.md rule 47: no shared\n * mutable state across async boundaries). Must be a non-negative\n * finite integer; non-conforming values are ignored and the\n * configured budget is used.\n */\n budgetCharsOverride?: number;\n /**\n * Per-invocation principal override (issue #570 PR 4). When set,\n * the orchestrator uses this principal for ACL / namespace checks\n * instead of `resolvePrincipal(sessionKey, config)`. This is the\n * escape hatch for access surfaces (HTTP / MCP) that have already\n * authenticated the caller upstream — threading an unmapped\n * principal through the session-key-based resolver would otherwise\n * collapse it to `\"default\"` and produce false denials in\n * namespace-enabled deployments (CLAUDE.md rule 42).\n */\n principalOverride?: string;\n}\n\ntype QueryAwarePrefilter = {\n candidatePaths: Set<string> | null;\n temporalFromDate: string | null;\n matchedTags: string[];\n expandedTags: string[];\n combination: \"none\" | \"temporal\" | \"tag\" | \"intersection\" | \"union\";\n filteredToFullSearch: boolean;\n};\n\n// Recall-specific abort helpers. Thin wrappers over the shared\n// `abort-error.ts` module so every abort in the codebase shares the\n// same `name === \"AbortError\"` classification contract (`isAbortError`\n// works uniformly). We keep the \"recall aborted\" default message for\n// back-compat with call-site logs; callers that pass an explicit\n// message (e.g. \"extraction aborted (before_extract)\") are unaffected.\nconst abortRecallError = sharedAbortError;\n\nfunction throwIfRecallAborted(\n signal?: AbortSignal,\n message = \"recall aborted\",\n): void {\n sharedThrowIfAborted(signal, message);\n}\n\nasync function raceRecallAbort<T>(\n promise: Promise<T>,\n signal?: AbortSignal,\n message = \"recall aborted\",\n): Promise<T> {\n throwIfRecallAborted(signal, message);\n if (!signal) return promise;\n\n let onAbort: (() => void) | null = null;\n const abortPromise = new Promise<T>((_resolve, reject) => {\n onAbort = () => reject(abortRecallError(message));\n signal.addEventListener(\"abort\", onAbort, { once: true });\n });\n\n try {\n return await Promise.race([promise, abortPromise]);\n } finally {\n if (onAbort) {\n signal.removeEventListener(\"abort\", onAbort);\n }\n }\n}\n\n/** Maximum age (ms) before a compaction-reset signal file is considered stale and removed. */\nconst COMPACTION_SIGNAL_MAX_AGE_MS = 60 * 60 * 1000; // 1 hour\n\n/** Default workspace directory when no per-agent or config workspace is available. */\nexport function defaultWorkspaceDir(): string {\n return path.join(os.homedir(), \".openclaw\", \"workspace\");\n}\n\n/**\n * Produce a collision-resistant, filesystem-safe identifier from a session key.\n *\n * Session keys follow colon-delimited forms (e.g., `agent:gpucodebot:main`).\n * A naive replace (`:` → `_`) is lossy: different keys like `agent:alpha` and\n * `agent/alpha` would collide. Instead we append a short SHA-256 hash of the\n * original key to the human-readable sanitized prefix, guaranteeing uniqueness\n * while keeping filenames debuggable.\n *\n * Format: `<sanitized>-<12-char-hex-hash>`\n * Example: `agent:gpucodebot:main` → `agent_gpucodebot_main-a1b2c3d4e5f6`\n */\nexport function sanitizeSessionKeyForFilename(sessionKey: string): string {\n const readable = sessionKey.replace(/[^a-zA-Z0-9._-]/g, \"_\");\n const hash = createHash(\"sha256\")\n .update(sessionKey)\n .digest(\"hex\")\n .slice(0, 12);\n return `${readable}-${hash}`;\n}\n\nexport function isArtifactMemoryPath(filePath: string): boolean {\n return /(?:^|[\\\\/])artifacts(?:[\\\\/]|$)/i.test(filePath);\n}\n\nexport function deriveTopicsFromExtraction(result: ExtractionResult): string[] {\n const topics = new Set<string>();\n for (const fact of result.facts ?? []) {\n for (const tag of fact.tags ?? []) {\n if (tag && tag.length >= 2) topics.add(tag.toLowerCase());\n }\n if (fact.entityRef) topics.add(fact.entityRef.toLowerCase());\n if (fact.category) topics.add(fact.category);\n }\n for (const entity of (result as any).entities ?? []) {\n if (typeof entity.name === \"string\" && entity.name.length >= 2) {\n topics.add(entity.name.toLowerCase());\n }\n }\n return [...topics].slice(0, 16);\n}\n\nexport function buildCompressionGuidelinesMarkdown(\n events: MemoryActionEvent[],\n generatedAtIso: string = new Date().toISOString(),\n): string {\n return buildCompressionGuidelinesMarkdownV2(events, generatedAtIso);\n}\n\nexport function formatCompressionGuidelinesForRecall(\n raw: string,\n maxLines: number = 5,\n): string | null {\n if (typeof raw !== \"string\" || raw.trim().length === 0) return null;\n const sectionMatch = raw.match(\n /## Suggested Guidelines\\s*\\n([\\s\\S]*?)(?:\\n##\\s+|\\s*$)/i,\n );\n if (!sectionMatch) return null;\n\n const lines = sectionMatch[1]\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.startsWith(\"- \"))\n .slice(0, Math.max(1, Math.floor(maxLines)));\n if (lines.length === 0) return null;\n\n return lines.join(\"\\n\");\n}\n\nexport function filterRecallCandidates(\n candidates: QmdSearchResult[],\n options: {\n namespacesEnabled: boolean;\n recallNamespaces: string[];\n resolveNamespace: (path: string) => string;\n limit: number;\n },\n): QmdSearchResult[] {\n const scopedByNamespace = options.namespacesEnabled\n ? candidates.filter((r) =>\n options.recallNamespaces.includes(options.resolveNamespace(r.path)),\n )\n : candidates;\n return scopedByNamespace\n .filter((r) => !isArtifactMemoryPath(r.path))\n .slice(0, Math.max(0, options.limit));\n}\n\nfunction applyQueryAwareCandidateFilter(\n candidates: QmdSearchResult[],\n candidatePaths: Set<string> | null,\n): QmdSearchResult[] {\n if (!candidatePaths || candidatePaths.size === 0) return candidates;\n const filtered = candidates.filter((candidate) =>\n candidatePaths.has(candidate.path),\n );\n return filtered.length > 0 ? filtered : candidates;\n}\n\nfunction tokenizeRecallQuery(prompt: string): string[] {\n return prompt\n .toLowerCase()\n .split(/[^a-z0-9]+/i)\n .map((t) => t.trim())\n .filter((t) => t.length >= 3);\n}\n\nfunction hasLifecycleMetadata(frontmatter: MemoryFrontmatter): boolean {\n return (\n frontmatter.lifecycleState !== undefined ||\n frontmatter.verificationState !== undefined ||\n frontmatter.policyClass !== undefined ||\n frontmatter.lastValidatedAt !== undefined ||\n frontmatter.decayScore !== undefined ||\n frontmatter.heatScore !== undefined\n );\n}\n\nexport function shouldFilterLifecycleRecallCandidate(\n frontmatter: MemoryFrontmatter,\n options: {\n lifecyclePolicyEnabled: boolean;\n lifecycleFilterStaleEnabled: boolean;\n },\n): boolean {\n if (!options.lifecyclePolicyEnabled || !options.lifecycleFilterStaleEnabled)\n return false;\n if (!hasLifecycleMetadata(frontmatter)) return false;\n const lifecycleState = resolveLifecycleState(frontmatter);\n return lifecycleState === \"stale\" || lifecycleState === \"archived\";\n}\n\nexport function lifecycleRecallScoreAdjustment(\n frontmatter: MemoryFrontmatter,\n options: {\n lifecyclePolicyEnabled: boolean;\n },\n): number {\n if (!options.lifecyclePolicyEnabled) return 0;\n if (!hasLifecycleMetadata(frontmatter)) return 0;\n\n let delta = 0;\n const lifecycleState = resolveLifecycleState(frontmatter);\n switch (lifecycleState) {\n case \"active\":\n delta += 0.05;\n break;\n case \"validated\":\n delta += 0.03;\n break;\n case \"candidate\":\n delta -= 0.01;\n break;\n case \"stale\":\n delta -= 0.06;\n break;\n case \"archived\":\n delta -= 0.08;\n break;\n }\n if (frontmatter.verificationState === \"disputed\") {\n delta -= 0.12;\n }\n return delta;\n}\n\nexport function computeArtifactRecallLimit(\n recallMode: RecallPlanMode,\n recallResultLimit: number,\n verbatimArtifactsMaxRecall: number,\n): number {\n if (recallMode === \"no_recall\") return 0;\n if (Math.max(0, recallResultLimit) === 0) return 0;\n const base = Math.max(0, verbatimArtifactsMaxRecall);\n if (recallMode === \"minimal\") {\n return Math.min(base, Math.max(0, recallResultLimit));\n }\n return base;\n}\n\nexport function resolveEffectiveRecallMode(options: {\n plannerEnabled: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n graphExpandedIntentEnabled?: boolean;\n prompt: string;\n}): RecallPlanMode {\n return resolveRecallModeDecision(options).effectiveMode;\n}\n\nexport function resolveRecallModeDecision(options: {\n plannerEnabled: boolean;\n graphRecallEnabled: boolean;\n multiGraphMemoryEnabled: boolean;\n graphExpandedIntentEnabled?: boolean;\n prompt: string;\n}): RecallModeDecision {\n let plannedMode: RecallPlanMode = options.plannerEnabled\n ? planRecallMode(options.prompt)\n : \"full\";\n const graphExpandedIntentDetected =\n options.plannerEnabled &&\n options.graphExpandedIntentEnabled === true &&\n hasBroadGraphIntent(options.prompt);\n if (plannedMode !== \"graph_mode\" && graphExpandedIntentDetected) {\n plannedMode = \"graph_mode\";\n }\n if (\n plannedMode === \"graph_mode\" &&\n (!options.graphRecallEnabled || !options.multiGraphMemoryEnabled)\n ) {\n return {\n plannedMode,\n effectiveMode: \"full\",\n graphExpandedIntentDetected,\n graphReason: !options.graphRecallEnabled\n ? \"graph recall disabled by config\"\n : \"multi-graph memory disabled by config\",\n };\n }\n return {\n plannedMode,\n effectiveMode: plannedMode,\n graphExpandedIntentDetected,\n };\n}\n\nexport function hasIdentityRecoveryIntent(prompt: string): boolean {\n const text = typeof prompt === \"string\" ? prompt.toLowerCase() : \"\";\n if (!text) return false;\n return /\\b(identity|continuity|recover(?:y|ing|ed)?|incident|drift|restore|regress(?:ion|ed|ing)?)\\b/i.test(\n text,\n );\n}\n\nexport function resolveEffectiveIdentityInjectionMode(options: {\n configuredMode: IdentityInjectionMode;\n recallMode: RecallPlanMode;\n prompt: string;\n}): { mode: IdentityInjectionMode; shouldInject: boolean } {\n if (\n options.configuredMode === \"recovery_only\" &&\n !hasIdentityRecoveryIntent(options.prompt)\n ) {\n return { mode: \"recovery_only\", shouldInject: false };\n }\n if (options.recallMode === \"minimal\" && options.configuredMode === \"full\") {\n return { mode: \"minimal\", shouldInject: true };\n }\n return { mode: options.configuredMode, shouldInject: true };\n}\n\nexport function computeArtifactCandidateFetchLimit(\n targetCount: number,\n): number {\n const cappedTarget = Math.max(0, targetCount);\n if (cappedTarget === 0) return 0;\n const headroom = Math.max(8, cappedTarget * 4);\n return Math.min(200, cappedTarget + headroom);\n}\n\nexport function computeQmdHybridFetchLimit(\n recallFetchLimit: number,\n artifactsEnabled: boolean,\n maxArtifactRecall: number,\n): number {\n const cappedRecallLimit = Math.max(0, recallFetchLimit);\n if (cappedRecallLimit === 0) return 0;\n if (!artifactsEnabled) return cappedRecallLimit;\n // Overscan when artifacts are enabled, then filter artifact paths before\n // re-applying the recall cap to avoid artifact-dominated top-N starvation.\n const artifactHeadroom = Math.max(20, Math.max(0, maxArtifactRecall) * 8);\n return Math.min(400, cappedRecallLimit + artifactHeadroom);\n}\n\nexport function mergeGraphExpandedResults(\n primary: QmdSearchResult[],\n expanded: QmdSearchResult[],\n): QmdSearchResult[] {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const item of [...primary, ...expanded]) {\n const prev = mergedByPath.get(item.path);\n if (!prev) {\n mergedByPath.set(item.path, item);\n continue;\n }\n const better = item.score > prev.score ? item : prev;\n const snippet = prev.snippet || item.snippet;\n mergedByPath.set(item.path, { ...better, snippet });\n }\n return Array.from(mergedByPath.values());\n}\n\nexport function graphPathRelativeToStorage(\n storageDir: string,\n candidatePath: string,\n): string | null {\n const absolutePath = path.isAbsolute(candidatePath)\n ? candidatePath\n : path.resolve(storageDir, candidatePath);\n const rel = path.relative(storageDir, absolutePath);\n if (!rel || rel === \".\") return null;\n if (rel.startsWith(\"..\")) return null;\n return rel.split(path.sep).join(\"/\");\n}\n\nfunction normalizeGraphActivationScore(score: number): number {\n const bounded = Number.isFinite(score) && score > 0 ? score : 0;\n return bounded / (1 + bounded);\n}\n\nexport function blendGraphExpandedRecallScore(options: {\n graphActivationScore: number;\n seedRecallScore: number;\n activationWeight: number;\n blendMin: number;\n blendMax: number;\n}): number {\n const graphNorm = normalizeGraphActivationScore(options.graphActivationScore);\n const seedScore = Number.isFinite(options.seedRecallScore)\n ? Math.min(1, Math.max(0, options.seedRecallScore))\n : 0;\n const weight = Math.min(1, Math.max(0, options.activationWeight));\n const rawMin = Math.min(1, Math.max(0, options.blendMin));\n const rawMax = Math.min(1, Math.max(0, options.blendMax));\n const minBound = Math.min(rawMin, rawMax);\n const maxBound = Math.max(rawMin, rawMax);\n const blended = graphNorm * weight + seedScore * (1 - weight);\n return Math.max(minBound, Math.min(maxBound, blended));\n}\n\nexport function summarizeGraphShadowComparison(\n baseline: QmdSearchResult[],\n merged: QmdSearchResult[],\n topN: number,\n): {\n baselineCount: number;\n graphCount: number;\n overlapCount: number;\n overlapRatio: number;\n averageOverlapDelta: number;\n} {\n const limit = Math.max(0, Math.floor(topN));\n const baselineTop = limit > 0 ? baseline.slice(0, limit) : [];\n const graphTop = limit > 0 ? merged.slice(0, limit) : [];\n const baselineByPath = new Map(\n baselineTop.map((item) => [item.path, item.score]),\n );\n const graphByPath = new Map(graphTop.map((item) => [item.path, item.score]));\n\n let overlapCount = 0;\n let overlapDeltaSum = 0;\n for (const [p, baselineScore] of baselineByPath.entries()) {\n const graphScore = graphByPath.get(p);\n if (typeof graphScore !== \"number\") continue;\n overlapCount += 1;\n overlapDeltaSum += graphScore - baselineScore;\n }\n\n const baselineCount = baselineTop.length;\n return {\n baselineCount,\n graphCount: graphTop.length,\n overlapCount,\n overlapRatio: baselineCount > 0 ? overlapCount / baselineCount : 0,\n averageOverlapDelta: overlapCount > 0 ? overlapDeltaSum / overlapCount : 0,\n };\n}\n\nfunction parseGraphRecallRankedResults(\n value: unknown,\n): GraphRecallRankedResult[] {\n if (!Array.isArray(value)) return [];\n const parsed: GraphRecallRankedResult[] = [];\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const candidate = entry as Partial<GraphRecallRankedResult>;\n if (\n typeof candidate.path !== \"string\" ||\n typeof candidate.score !== \"number\"\n )\n continue;\n parsed.push({\n path: candidate.path,\n score: candidate.score,\n docid: typeof candidate.docid === \"string\" ? candidate.docid : undefined,\n sourceLabels: Array.isArray(candidate.sourceLabels)\n ? candidate.sourceLabels.filter(\n (item): item is string => typeof item === \"string\",\n )\n : [],\n });\n }\n return parsed.slice(0, 64);\n}\n\nfunction parseMemoryIntentSnapshot(value: unknown): MemoryIntent {\n const candidate =\n value && typeof value === \"object\" ? (value as Partial<MemoryIntent>) : {};\n return {\n goal: typeof candidate.goal === \"string\" ? candidate.goal : \"unknown\",\n actionType:\n typeof candidate.actionType === \"string\"\n ? candidate.actionType\n : \"unknown\",\n entityTypes: Array.isArray(candidate.entityTypes)\n ? candidate.entityTypes.filter(\n (item): item is string => typeof item === \"string\",\n )\n : [],\n taskInitiation: candidate.taskInitiation === true,\n };\n}\n\nfunction buildQmdIntentHint(intent: MemoryIntent): string | undefined {\n const parts: string[] = [];\n if (intent.goal !== \"unknown\") {\n parts.push(`goal:${intent.goal.replace(/_/g, \" \")}`);\n }\n if (intent.actionType !== \"unknown\") {\n parts.push(`action:${intent.actionType.replace(/_/g, \" \")}`);\n }\n if (intent.entityTypes.length > 0) {\n parts.push(`entities:${intent.entityTypes.join(\",\")}`);\n }\n if (intent.taskInitiation === true) {\n parts.push(\"task_initiation\");\n }\n return parts.length > 0 ? parts.join(\" \") : undefined;\n}\n\nfunction parseQmdRecallResults(value: unknown): QmdSearchResult[] {\n if (!Array.isArray(value)) return [];\n const parsed: QmdSearchResult[] = [];\n for (const entry of value) {\n if (!entry || typeof entry !== \"object\") continue;\n const candidate = entry as Partial<QmdSearchResult>;\n if (\n typeof candidate.path !== \"string\" ||\n typeof candidate.score !== \"number\"\n )\n continue;\n parsed.push({\n docid: typeof candidate.docid === \"string\" ? candidate.docid : \"\",\n path: candidate.path,\n snippet: typeof candidate.snippet === \"string\" ? candidate.snippet : \"\",\n score: candidate.score,\n explain: parseQmdExplain(candidate.explain),\n transport:\n candidate.transport === \"daemon\" ||\n candidate.transport === \"subprocess\" ||\n candidate.transport === \"hybrid\" ||\n candidate.transport === \"scoped_prefilter\"\n ? candidate.transport\n : undefined,\n });\n }\n return parsed.slice(0, 32);\n}\n\nexport function mergeArtifactRecallCandidates(\n candidatesByNamespace: MemoryFile[][],\n limit: number,\n): MemoryFile[] {\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0) return [];\n\n const out: MemoryFile[] = [];\n const seen = new Set<string>();\n let offset = 0;\n while (out.length < cappedLimit) {\n let hasAnyCandidateAtOffset = false;\n for (const list of candidatesByNamespace) {\n if (offset >= list.length) continue;\n hasAnyCandidateAtOffset = true;\n const item = list[offset];\n const dedupeKey = `${item.frontmatter.id}:${item.frontmatter.sourceMemoryId ?? \"\"}:${item.content}`;\n if (seen.has(dedupeKey)) continue;\n seen.add(dedupeKey);\n out.push(item);\n if (out.length >= cappedLimit) break;\n }\n if (!hasAnyCandidateAtOffset) break;\n offset += 1;\n }\n return out;\n}\n\nexport function resolveRecentThreadMemoryPaths(options: {\n threadEpisodeIds: string[];\n currentMemoryId: string;\n allMemsForGraph: MemoryFile[] | null | undefined;\n pathById?: Map<string, string>;\n storageDir: string;\n maxRecent: number;\n}): string[] {\n const maxRecent = Math.max(0, options.maxRecent);\n if (options.threadEpisodeIds.length === 0 || maxRecent === 0) return [];\n const pathById =\n options.pathById ??\n buildMemoryPathById(options.allMemsForGraph, options.storageDir);\n if (pathById.size === 0) return [];\n\n return options.threadEpisodeIds\n .filter((id) => id !== options.currentMemoryId)\n .slice(-maxRecent)\n .map((id) => pathById.get(id))\n .filter((p): p is string => typeof p === \"string\" && p.length > 0);\n}\n\nexport function buildMemoryPathById(\n allMemsForGraph: MemoryFile[] | null | undefined,\n storageDir: string,\n): Map<string, string> {\n const pathById = new Map<string, string>();\n for (const mem of allMemsForGraph ?? []) {\n const id = mem.frontmatter.id;\n if (!id) continue;\n pathById.set(id, path.relative(storageDir, mem.path));\n }\n return pathById;\n}\n\nexport function appendMemoryToGraphContext(options: {\n allMemsForGraph: MemoryFile[] | null | undefined;\n storageDir: string;\n memoryRelPath: string;\n memoryId: string;\n category: MemoryFile[\"frontmatter\"][\"category\"];\n content: string;\n entityRef: string | undefined;\n}): void {\n if (!Array.isArray(options.allMemsForGraph)) return;\n\n const nowIso = new Date().toISOString();\n options.allMemsForGraph.push({\n path: path.join(options.storageDir, options.memoryRelPath),\n content: options.content,\n frontmatter: {\n id: options.memoryId,\n category: options.category,\n created: nowIso,\n updated: nowIso,\n source: \"extraction\",\n confidence: 0.8,\n confidenceTier: \"implied\",\n tags: [],\n entityRef: options.entityRef,\n status: \"active\",\n },\n });\n}\n\nexport function resolvePersistedMemoryRelativePath(options: {\n memoryId: string;\n pathById: Map<string, string>;\n category: string;\n}): string {\n const persisted = options.pathById.get(options.memoryId);\n if (persisted) return persisted;\n if (options.category === \"correction\") {\n return path.join(\"corrections\", `${options.memoryId}.md`);\n }\n // Pick the subtree that matches the StorageManager.writeMemory routing\n // so fallback paths (used before memoryPathById has seen the fresh\n // write) agree with where the file actually lives. Without this branch,\n // reasoning_trace graph edges point at facts/<date>/, and subsequent\n // graph expansion silently drops those nodes when readMemoryByPath\n // cannot resolve them (issue #564 PR 3 review).\n const subtree =\n options.category === \"procedure\"\n ? \"procedures\"\n : options.category === \"reasoning_trace\"\n ? \"reasoning-traces\"\n : \"facts\";\n const idParts = options.memoryId.split(\"-\");\n const maybeTimestamp = Number(idParts[1]);\n if (Number.isFinite(maybeTimestamp) && maybeTimestamp > 0) {\n const day = new Date(maybeTimestamp).toISOString().slice(0, 10);\n return path.join(subtree, day, `${options.memoryId}.md`);\n }\n return path.join(subtree, `${options.memoryId}.md`);\n}\n\nexport class Orchestrator {\n readonly storage: StorageManager;\n private readonly storageRouter: NamespaceStorageRouter;\n private readonly namespaceSearchRouter: NamespaceSearchRouter;\n qmd: SearchBackend;\n private readonly conversationQmd?: ConversationQmdRuntime;\n private readonly conversationFaiss?: ReturnType<\n typeof createConversationIndexRuntime\n >[\"faiss\"];\n private readonly conversationIndexBackend?: ConversationIndexBackend;\n readonly sharedContext?: SharedContextManager;\n readonly compounding?: CompoundingEngine;\n readonly buffer: SmartBuffer;\n readonly transcript: TranscriptManager;\n readonly sessionObserver: SessionObserverState;\n readonly summarizer: HourlySummarizer;\n readonly localLlm: LocalLlmClient;\n readonly fastLlm: LocalLlmClient;\n private readonly judgeVerdictCache: Map<string, JudgeVerdict>;\n /**\n * Per-orchestrator defer-counter map (issue #562, PR 2). Tracks how many\n * times the judge has returned `\"defer\"` for a given candidate content\n * hash so the defer cap can be enforced.\n */\n private readonly judgeDeferCounts: Map<string, number>;\n /**\n * Side-channel: number of facts deferred in the most recent\n * `persistExtraction` call (issue #562, PR 2). The caller reads this after\n * `persistExtraction` returns to decide whether to retain buffer turns for\n * the next extraction pass. Not part of the return signature because many\n * callers already destructure `persistedIds` by position.\n */\n private lastPersistExtractionDeferredCount: number = 0;\n private readonly _fastGatewayLlm: FallbackLlmClient | null;\n\n get fastGatewayLlm(): FallbackLlmClient | null {\n return this._fastGatewayLlm;\n }\n readonly modelRegistry: ModelRegistry;\n readonly relevance: RelevanceStore;\n readonly negatives: NegativeExampleStore;\n readonly lastRecall: LastRecallStore;\n readonly tierMigrationStatus: TierMigrationStatusStore;\n /**\n * In-memory X-ray snapshot from the most recent `recall()` call that\n * was invoked with `xrayCapture: true` (issue #570 PR 1). Scope is\n * per-process; later slices add CLI/HTTP/MCP surfaces that consume\n * this via the shared renderer. `null` until the first capture, and\n * NEVER overwritten by a recall that did not request capture —\n * requests without the flag leave prior captures intact so the\n * capturing caller can still read their snapshot back.\n */\n private lastXraySnapshot: RecallXraySnapshot | null = null;\n readonly embeddingFallback: EmbeddingFallback;\n private readonly conversationIndexDir: string;\n private readonly extraction: ExtractionEngine;\n readonly config: PluginConfig;\n readonly profiler: ProfilingCollector;\n private readonly threading: ThreadingManager;\n /** v8.2: Per-namespace multi-graph memory indexes (entity/time/causal edges) */\n private readonly graphIndexes = new Map<string, GraphIndex>();\n /** Per-namespace BoxBuilders, keyed by the namespace root directory path. */\n private readonly boxBuilders = new Map<string, BoxBuilder>();\n /** Temporal Memory Tree builder — builds hour/day/week/persona summary nodes. */\n private readonly tmtBuilder: TmtBuilder;\n /** Lossless Context Management engine — proactive session archive + DAG summarization. */\n readonly lcmEngine: LcmEngine | null = null;\n private readonly rerankCache = new RerankCache();\n\n /**\n * Short-TTL cache for Memory Worth counter lookups so interactive recall\n * doesn't trigger a full `readAllMemories` scan per query. Keyed by\n * namespace; the filter unions across namespaces at query time. The TTL\n * is intentionally short (seconds, not minutes) because counters are\n * mutated by `recordMemoryOutcome` asynchronously and we'd rather serve\n * a 30-second-stale worth score than a stable-but-wrong one.\n */\n private readonly memoryWorthCounterCache = new Map<\n string,\n { at: number; counters: ReadonlyMap<string, MemoryWorthCounters> }\n >();\n private static readonly MEMORY_WORTH_CACHE_TTL_MS = 30_000;\n /**\n * Per-session workspace overrides 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 private routingRulesStore: RoutingRulesStore | null = null;\n private contentHashIndex: ContentHashIndex | null = null;\n private readonly artifactSourceStatusCache = new WeakMap<\n StorageManager,\n {\n loadedAtMs: number;\n statusVersion: number;\n statuses: Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">;\n }\n >();\n private static readonly ARTIFACT_STATUS_CACHE_TTL_MS = 60_000;\n\n // Access tracking buffer (Phase 1A)\n // Maps memoryId -> {count, lastAccessed} for batched updates\n private accessTrackingBuffer: Map<\n string,\n { count: number; lastAccessed: string }\n > = new Map();\n\n // Background serial queue for extractions (agent_end optimization)\n // Queue stores promises that resolve when extraction should run\n private extractionQueue: Array<() => Promise<void>> = [];\n private queueProcessing = false;\n private heartbeatObserverChains = new Map<string, Promise<void>>();\n private recentExtractionFingerprints = new Map<string, number>();\n private nonZeroExtractionsSinceConsolidation = 0;\n private lastConsolidationRunAtMs = 0;\n private consolidationInFlight = false;\n private readonly consolidationObservers = new Set<\n (observation: ConsolidationObservation) => Promise<void> | void\n >();\n private qmdMaintenanceTimer: NodeJS.Timeout | null = null;\n private qmdMaintenancePending = false;\n private qmdMaintenanceInFlight = false;\n private lastQmdEmbedAtMs = 0;\n private lastQmdReprobeAtMs = 0;\n private tierMigrationInFlight = false;\n private lastTierMigrationRunAtMs = 0;\n private readonly conversationIndexLastUpdateAtMs = new Map<string, number>();\n private lastFileHygieneRunAtMs = 0;\n private lastRecallFailureLogAtMs = 0;\n private lastRecallFailureAtMs = 0;\n private suppressedRecallFailures = 0;\n private readonly policyRuntime: PolicyRuntimeManager;\n private runtimePolicyValues: RuntimePolicyValues | null = null;\n private utilityRuntimeValues: UtilityRuntimeValues | null = null;\n private evalShadowWriteChain: Promise<void> = Promise.resolve();\n\n // Pending background observation-mode direct-answer annotations (#518).\n // Tracks fire-and-forget `annotateDirectAnswerTier` calls so callers (tests,\n // waitForDirectAnswerObservationIdle) can await settlement.\n private directAnswerObservationChain: Promise<void> = Promise.resolve();\n\n // Initialization gate: recall() awaits this before proceeding\n private initPromise: Promise<void> | null = null;\n private resolveInit: (() => void) | null = null;\n\n /**\n * Resolves when deferred initialization (QMD probe, warmup, caches, cron)\n * completes. CLI and http-serve callers that need `qmd.isAvailable()` to\n * reflect reality should `await orchestrator.deferredReady` after\n * `initialize()`. Gateway callers can ignore it — recall() degrades\n * gracefully when QMD isn't ready yet.\n *\n * Also resolves (without error) when `initialize()` throws before reaching\n * the deferred-init phase, so callers never hang on a permanently-pending\n * promise.\n *\n * Host adapters that need to tie deferred init to their stop() lifecycle\n * should `await orchestrator.deferredReady` before proceeding with teardown\n * to prevent background QMD/warmup/cron tasks from racing with shutdown.\n */\n deferredReady: Promise<void> = Promise.resolve();\n private resolveDeferredReady: (() => void) | null = null;\n private deferredInitAbort: AbortController | null = null;\n\n /**\n * Whether the deferred init's QMD startup sync completed successfully.\n * When false after deferredReady resolves, the server retry loop should\n * attempt startupSearchSync() even if `qmd.isAvailable()` is true —\n * availability only means probe succeeded, not that the index is current.\n */\n deferredSyncSucceeded = false;\n\n /**\n * Abort deferred initialization so background QMD sync/warmup stops\n * promptly on shutdown. Safe to call multiple times or before init.\n */\n abortDeferredInit(): void {\n if (this.deferredInitAbort) {\n this.deferredInitAbort.abort();\n this.deferredInitAbort = null;\n }\n }\n\n private async disposeSearchBackendIfNeeded(): Promise<void> {\n await (this.qmd as { dispose?: () => void | Promise<void> }).dispose?.();\n }\n\n /** Set per-session workspace for the next recall() call (compaction reset). @internal */\n setRecallWorkspaceOverride(sessionKey: string, dir: string): void {\n this._recallWorkspaceOverrides.set(sessionKey, dir);\n }\n\n /** Remove a per-session workspace override (cleanup on error or early return). @internal */\n clearRecallWorkspaceOverride(sessionKey: string): void {\n this._recallWorkspaceOverrides.delete(sessionKey);\n }\n\n resolvePrincipal(sessionKey?: string): string {\n return resolvePrincipal(sessionKey, this.config);\n }\n\n resolveSelfNamespace(sessionKey?: string): string {\n const base = defaultNamespaceForPrincipal(\n this.resolvePrincipal(sessionKey),\n this.config,\n );\n return this.applyCodingNamespaceOverlay(sessionKey, base);\n }\n\n /**\n * Attach a coding-agent context to a session (issue #569). Called by the\n * Claude Code / Codex / Cursor connectors at session start after\n * `resolveGitContext(cwd)`. The context is consulted by the recall path\n * and the write path so that memories route to a project- (and optionally\n * branch-) scoped namespace.\n *\n * Pass `null` to clear.\n */\n setCodingContextForSession(sessionKey: string, codingContext: CodingContext | null): void {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return;\n // Defensive init — `Object.create(Orchestrator.prototype)` stubs in\n // legacy tests skip class-field initializers (rule 16 applies to test\n // teardown; we apply the same defensiveness on construction here so\n // PR 2 doesn't break those tests).\n if (!this._codingContextBySession) {\n (this as unknown as { _codingContextBySession: Map<string, CodingContext> })._codingContextBySession = new Map();\n }\n if (codingContext === null) {\n this._codingContextBySession.delete(sessionKey);\n return;\n }\n this._codingContextBySession.set(sessionKey, codingContext);\n }\n\n /**\n * Read-only accessor for the coding context attached to a session. Returns\n * `null` when none is set. Used by `remnic doctor` and by tests.\n *\n * Defensive `_codingContextBySession` lookup — legacy orchestrator-flush\n * tests use `Object.create(Orchestrator.prototype)` which does not run\n * class-field initializers, so the Map may be undefined on stubs.\n */\n getCodingContextForSession(sessionKey: string | undefined): CodingContext | null {\n if (typeof sessionKey !== \"string\" || sessionKey.length === 0) return null;\n return this._codingContextBySession?.get(sessionKey) ?? null;\n }\n\n /**\n * Shared helper used by both the recall path and the write path (rule 42).\n *\n * Given a base namespace computed from the principal, returns the overlaid\n * coding namespace when the session has a coding context AND\n * `codingMode.projectScope` is true AND `namespacesEnabled` is true.\n * Otherwise returns `baseNamespace` unchanged — CLAUDE.md #30 escape hatch.\n *\n * Principal isolation (CLAUDE.md rule 42): the overlay is COMBINED with\n * the principal-derived `baseNamespace` rather than replacing it, so two\n * principals working in the same repository do not share memories through\n * a common `project-*` namespace.\n *\n * Namespaces-disabled gate: when `namespacesEnabled` is false, the\n * storage router maps every namespace to the same `memoryDir`. Returning\n * `project-*` in that mode would create apparent route separation with\n * no actual storage isolation — a false-isolation trap. In that mode we\n * return `baseNamespace` unchanged so coding mode degrades to the existing\n * unscoped behavior.\n *\n * @internal\n */\n applyCodingNamespaceOverlay(sessionKey: string | undefined, baseNamespace: string): string {\n if (!this.config.namespacesEnabled) return baseNamespace;\n const codingContext = this.getCodingContextForSession(sessionKey);\n const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);\n if (!overlay) return baseNamespace;\n return combineNamespaces(baseNamespace, overlay.namespace);\n }\n\n /**\n * Read-side overlay: returns the list of namespaces a session should read\n * from, including any read fallbacks (branch → project asymmetry lands in\n * PR 3; PR 2 returns an empty fallbacks list).\n *\n * Returns `null` when:\n * - `namespacesEnabled` is false (overlay would create false isolation)\n * - no context attached to the session\n * - `codingMode.projectScope` is false (CLAUDE.md #30 escape hatch)\n *\n * The returned `namespace` / `readFallbacks` are RAW overlay fragments\n * (e.g. `project-origin-ab12`). Callers MUST combine them with the\n * principal-derived base through `combineNamespaces()` before passing to\n * storage, so principal isolation is preserved (rule 42).\n *\n * @internal\n */\n applyCodingRecallOverlay(sessionKey: string | undefined): { namespace: string; readFallbacks: string[] } | null {\n if (!this.config.namespacesEnabled) return null;\n const codingContext = this.getCodingContextForSession(sessionKey);\n const overlay = resolveCodingNamespaceOverlay(codingContext, this.config.codingMode);\n if (!overlay) return null;\n return { namespace: overlay.namespace, readFallbacks: overlay.readFallbacks };\n }\n\n async getStorageForNamespace(namespace?: string): Promise<StorageManager> {\n const ns =\n typeof namespace === \"string\" && namespace.trim().length > 0\n ? namespace.trim()\n : this.config.defaultNamespace;\n return this.storageRouter.storageFor(ns);\n }\n\n private configuredNamespaces(): string[] {\n return Array.from(\n new Set(\n [\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((policy) => policy.name),\n ]\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n );\n }\n\n private buildConfiguredQmdSearchOptions(\n queryText: string,\n ): SearchQueryOptions | undefined {\n const intentHint = this.config.qmdIntentHintsEnabled\n ? buildQmdIntentHint(inferIntentFromText(queryText))\n : undefined;\n const explain = this.config.qmdExplainEnabled === true;\n const searchOptions: SearchQueryOptions = {};\n if (intentHint) {\n searchOptions.intent = intentHint;\n }\n if (explain) {\n searchOptions.explain = true;\n }\n return Object.keys(searchOptions).length > 0 ? searchOptions : undefined;\n }\n\n async searchAcrossNamespaces(options: {\n query: string;\n namespaces?: string[];\n maxResults?: number;\n mode?: \"search\" | \"hybrid\" | \"bm25\" | \"vector\";\n searchOptions?: SearchQueryOptions;\n execution?: SearchExecutionOptions;\n }): Promise<QmdSearchResult[]> {\n const namespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set(\n (options.namespaces?.length\n ? options.namespaces\n : this.configuredNamespaces()\n )\n .map((value) => value.trim())\n .filter(Boolean),\n ),\n )\n : [this.config.defaultNamespace];\n\n if (!this.config.namespacesEnabled) {\n switch (options.mode) {\n case \"hybrid\":\n return await this.qmd.hybridSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"bm25\":\n return await this.qmd.bm25Search(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n case \"vector\":\n return await this.qmd.vectorSearch(\n options.query,\n undefined,\n options.maxResults,\n options.execution,\n );\n default:\n return await this.qmd.search(\n options.query,\n undefined,\n options.maxResults,\n options.searchOptions,\n options.execution,\n );\n }\n }\n\n return await this.namespaceSearchRouter.searchAcrossNamespaces({\n query: options.query,\n namespaces,\n maxResults: options.maxResults,\n mode: options.mode,\n searchOptions: options.searchOptions,\n execution: options.execution,\n });\n }\n\n private isSearchAvailableForNamespaceRouting(): boolean {\n if (this.config.namespacesEnabled) return true;\n return this.qmd.isAvailable();\n }\n\n constructor(config: PluginConfig) {\n this.config = config;\n this.profiler = new ProfilingCollector({\n enabled: config.profilingEnabled,\n storageDir: config.profilingStorageDir || path.join(config.memoryDir, \"profiling\"),\n maxTraces: config.profilingMaxTraces,\n });\n this.storageRouter = new NamespaceStorageRouter(config);\n this.namespaceSearchRouter = new NamespaceSearchRouter(\n config,\n this.storageRouter,\n );\n this.storage = new StorageManager(config.memoryDir, config.entitySchemas);\n // Propagate the inline-attribution template so the storage layer can strip\n // citations from legacy facts during the hash-index rebuild path.\n this.storage.citationTemplate = config.inlineSourceAttributionFormat;\n // Wire page-level versioning (issue #371)\n this.storage.setVersioningConfig({\n enabled: config.versioningEnabled,\n maxVersionsPerPage: config.versioningMaxPerPage,\n sidecarDir: config.versioningSidecarDir,\n });\n this.qmd = createSearchBackend(config);\n const conversationIndexRuntime = createConversationIndexRuntime(config, {\n getQmd: () => this.conversationQmd,\n getFaiss: () => this.conversationFaiss,\n });\n this.conversationQmd = conversationIndexRuntime.qmd;\n this.conversationFaiss = conversationIndexRuntime.faiss;\n this.conversationIndexBackend = conversationIndexRuntime.backend;\n this.sharedContext = config.sharedContextEnabled\n ? new SharedContextManager(config)\n : undefined;\n this.compounding = config.compoundingEnabled\n ? new CompoundingEngine(config)\n : undefined;\n this.buffer = new SmartBuffer(config, this.storage);\n this.transcript = new TranscriptManager(config);\n this.conversationIndexDir = path.join(\n config.memoryDir,\n \"conversation-index\",\n \"chunks\",\n );\n this.modelRegistry = new ModelRegistry(config.memoryDir);\n this.relevance = new RelevanceStore(config.memoryDir);\n this.negatives = new NegativeExampleStore(config.memoryDir);\n this.lastRecall = new LastRecallStore(config.memoryDir);\n this.tierMigrationStatus = new TierMigrationStatusStore(config.memoryDir);\n this.sessionObserver = new SessionObserverState({\n memoryDir: config.memoryDir,\n debounceMs: config.sessionObserverDebounceMs ?? 120_000,\n bands: config.sessionObserverBands ?? [],\n });\n this.embeddingFallback = new EmbeddingFallback(config);\n this.policyRuntime = new PolicyRuntimeManager(config.memoryDir, config);\n this.summarizer = new HourlySummarizer(\n config,\n config.gatewayConfig,\n this.modelRegistry,\n this.transcript,\n );\n this.judgeVerdictCache = createVerdictCache();\n this.judgeDeferCounts = createDeferCountMap();\n this.localLlm = new LocalLlmClient(config, this.modelRegistry);\n // Issue #548: the main local-LLM client is used by extraction,\n // consolidation, and other structured-output tasks that gain\n // nothing from chain-of-thought reasoning. Apply the operator's\n // configured preference (default true) so thinking-capable models\n // skip reasoning tokens and avoid the common 60s extraction\n // timeout. Operators can set `localLlmDisableThinking: false`\n // when they want thinking enabled for narrative paths.\n this.localLlm.disableThinking = config.localLlmDisableThinking;\n this.fastLlm = config.localLlmFastEnabled\n ? (() => {\n const client = new LocalLlmClient(\n {\n ...config,\n localLlmModel: config.localLlmFastModel || config.localLlmModel,\n localLlmUrl: config.localLlmFastUrl,\n localLlmTimeoutMs: config.localLlmFastTimeoutMs,\n },\n this.modelRegistry,\n );\n // Fast-tier always suppresses thinking — the contract of\n // `fastLlm` is \"low latency at all costs\" and that is\n // independent of the main-client config.\n client.disableThinking = true;\n return client;\n })()\n : this.localLlm;\n // Initialize gateway fast LLM for fast-tier ops when modelSource is \"gateway\"\n this._fastGatewayLlm = config.modelSource === \"gateway\"\n ? new FallbackLlmClient(config.gatewayConfig)\n : null;\n if (config.modelSource === \"gateway\") {\n log.debug(\n `orchestrator: gateway model source active` +\n (config.gatewayAgentId ? ` (primary: ${config.gatewayAgentId})` : \"\") +\n (config.fastGatewayAgentId ? ` (fast: ${config.fastGatewayAgentId})` : \"\"),\n );\n }\n this.extraction = new ExtractionEngine(\n config,\n this.profiler,\n this.localLlm,\n config.gatewayConfig,\n this.modelRegistry,\n );\n this.threading = new ThreadingManager(\n path.join(config.memoryDir, \"threads\"),\n config.threadingGapMinutes,\n );\n // BoxBuilders are created per-namespace on first use in runExtraction().\n\n // Temporal Memory Tree (v8.2) — lazy build during consolidation\n this.tmtBuilder = new TmtBuilder(config.memoryDir, {\n temporalMemoryTreeEnabled: config.temporalMemoryTreeEnabled,\n tmtHourlyMinMemories: config.tmtHourlyMinMemories,\n tmtSummaryMaxTokens: config.tmtSummaryMaxTokens,\n });\n\n // Lossless Context Management (LCM) — proactive session archive + DAG summarization\n if (config.lcmEnabled) {\n const summarizeFn = async (\n text: string,\n targetTokens: number,\n aggressive: boolean,\n ) => {\n const systemPrompt = aggressive\n ? `Compress the following into bullet points. One bullet per distinct fact or decision. Maximum ${targetTokens} tokens total. No prose.`\n : `Compress the following conversation segment into a dense summary. Preserve: decisions made, code artifacts mentioned, errors encountered, open questions, and any commitments or next-steps. Omit: pleasantries, restatements, and anything the agent would not need to recall later. Output a single paragraph, maximum ${targetTokens} tokens.`;\n try {\n const result = await this.localLlm.chatCompletion(\n [\n { role: \"system\", content: systemPrompt },\n { role: \"user\", content: text.slice(0, 12000) },\n ],\n {\n maxTokens: targetTokens * 2,\n operation: \"lcm-summarize\",\n priority: \"background\",\n },\n );\n return result?.content ?? null;\n } catch {\n return null;\n }\n };\n this.lcmEngine = new LcmEngine(config, summarizeFn);\n }\n\n // Create init gate — recall() will await this before proceeding\n this.initPromise = new Promise<void>((resolve) => {\n this.resolveInit = resolve;\n });\n\n // deferredReady is NOT created here — the property initializer provides a\n // safe default (Promise.resolve()), and initialize() recreates it on every\n // call. Creating a pending promise in the constructor would be orphaned\n // since initialize() unconditionally overwrites it.\n }\n\n /** Get or create a BoxBuilder for the given namespace storage root (namespace-isolated). */\n private boxBuilderFor(storage: StorageManager): BoxBuilder {\n const dir = storage.dir;\n if (!this.boxBuilders.has(dir)) {\n this.boxBuilders.set(\n dir,\n new BoxBuilder(dir, {\n memoryBoxesEnabled: this.config.memoryBoxesEnabled,\n traceWeaverEnabled: this.config.traceWeaverEnabled,\n boxTopicShiftThreshold: this.config.boxTopicShiftThreshold,\n boxTimeGapMs: this.config.boxTimeGapMs,\n boxMaxMemories: this.config.boxMaxMemories,\n traceWeaverLookbackDays: this.config.traceWeaverLookbackDays,\n traceWeaverOverlapThreshold: this.config.traceWeaverOverlapThreshold,\n }),\n );\n }\n return this.boxBuilders.get(dir)!;\n }\n\n private effectiveRecencyWeight(): number {\n return applyRuntimeRetrievalPolicy(\n { recencyWeight: this.config.recencyWeight },\n this.runtimePolicyValues,\n ).recencyWeight;\n }\n\n private effectiveCronRecallInstructionHeavyTokenCap(): number {\n return (\n this.runtimePolicyValues?.cronRecallInstructionHeavyTokenCap ??\n this.config.cronRecallInstructionHeavyTokenCap\n );\n }\n\n private currentPolicyVersion(): string {\n const thresholds = this.effectiveLifecycleThresholds();\n const payload = {\n recencyWeight: this.effectiveRecencyWeight(),\n lifecyclePromoteHeatThreshold: thresholds.promoteHeatThreshold,\n lifecycleStaleDecayThreshold: thresholds.staleDecayThreshold,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n utilityRankingBoostMultiplier:\n this.utilityRuntimeValues?.rankingBoostMultiplier ?? 1,\n utilityRankingSuppressMultiplier:\n this.utilityRuntimeValues?.rankingSuppressMultiplier ?? 1,\n utilityPromoteThresholdDelta:\n this.utilityRuntimeValues?.promoteThresholdDelta ?? 0,\n utilityDemoteThresholdDelta:\n this.utilityRuntimeValues?.demoteThresholdDelta ?? 0,\n };\n return createHash(\"sha256\")\n .update(JSON.stringify(payload))\n .digest(\"hex\")\n .slice(0, 12);\n }\n\n private effectiveLifecycleThresholds(): {\n promoteHeatThreshold: number;\n staleDecayThreshold: number;\n archiveDecayThreshold: number;\n } {\n const archiveDecayThreshold = this.config.lifecycleArchiveDecayThreshold;\n const staleDecayThreshold = Math.min(\n this.runtimePolicyValues?.lifecycleStaleDecayThreshold ??\n this.config.lifecycleStaleDecayThreshold,\n archiveDecayThreshold,\n );\n return {\n promoteHeatThreshold:\n this.runtimePolicyValues?.lifecyclePromoteHeatThreshold ??\n this.config.lifecyclePromoteHeatThreshold,\n staleDecayThreshold,\n archiveDecayThreshold,\n };\n }\n\n private routeEngineOptions(): RoutingEngineOptions {\n const allowedNamespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((policy) => policy.name),\n ]),\n )\n : [this.config.defaultNamespace];\n return { allowedNamespaces };\n }\n\n private getRoutingRulesStore(): RoutingRulesStore {\n if (!this.routingRulesStore) {\n this.routingRulesStore = new RoutingRulesStore(\n this.config.memoryDir,\n this.config.routingRulesStateFile,\n );\n }\n return this.routingRulesStore;\n }\n\n private async loadRoutingRules(): Promise<RouteRule[]> {\n if (!this.config.routingRulesEnabled) return [];\n try {\n return await this.getRoutingRulesStore().read(this.routeEngineOptions());\n } catch (err) {\n log.warn(\n `routing rules unavailable; fail-open to default writes: ${err}`,\n );\n return [];\n }\n }\n\n private async resolveArtifactSourceStatuses(\n storage: StorageManager,\n sourceIds: string[],\n ): Promise<Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">> {\n const currentStatusVersion = storage.getMemoryStatusVersion();\n const cached = this.artifactSourceStatusCache.get(storage);\n let snapshot = cached;\n const isFresh =\n snapshot !== undefined &&\n Date.now() - snapshot.loadedAtMs <=\n Orchestrator.ARTIFACT_STATUS_CACHE_TTL_MS &&\n snapshot.statusVersion === currentStatusVersion;\n\n const rebuildSnapshot = async () => {\n const MAX_STABLE_READ_ATTEMPTS = 3;\n let latestStatuses = new Map<\n string,\n \"active\" | \"superseded\" | \"archived\" | \"missing\"\n >();\n let latestVersionAfter = storage.getMemoryStatusVersion();\n\n for (let attempt = 0; attempt < MAX_STABLE_READ_ATTEMPTS; attempt += 1) {\n const versionBefore = storage.getMemoryStatusVersion();\n const allMemories = await storage.readAllMemories();\n const versionAfter = storage.getMemoryStatusVersion();\n latestVersionAfter = versionAfter;\n latestStatuses = new Map(\n allMemories.map((m) => [\n m.frontmatter.id,\n (m.frontmatter.status ?? \"active\") as\n | \"active\"\n | \"superseded\"\n | \"archived\"\n | \"missing\",\n ]),\n );\n\n if (versionAfter === versionBefore) {\n const rebuilt = {\n loadedAtMs: Date.now(),\n statusVersion: versionAfter,\n statuses: latestStatuses,\n };\n this.artifactSourceStatusCache.set(storage, rebuilt);\n return rebuilt;\n }\n }\n\n // Sustained write churn: return latest read without caching a potentially torn snapshot.\n return {\n loadedAtMs: Date.now(),\n statusVersion: latestVersionAfter,\n statuses: latestStatuses,\n };\n };\n\n if (!isFresh) {\n snapshot = await rebuildSnapshot();\n } else {\n // Warm cache may miss brand-new sourceMemoryId values created after snapshot build.\n // Refresh once on-demand when unseen IDs are requested.\n const hasUnknownSourceIds = sourceIds.some(\n (id) => !snapshot?.statuses.has(id),\n );\n if (hasUnknownSourceIds) {\n snapshot = await rebuildSnapshot();\n }\n }\n\n // Persist negative lookups in the cached snapshot so stale source IDs do not\n // trigger repeated full snapshot rebuilds on every matching recall.\n for (const id of sourceIds) {\n if (!snapshot?.statuses.has(id)) {\n snapshot?.statuses.set(id, \"missing\");\n }\n }\n\n const statuses = new Map<\n string,\n \"active\" | \"superseded\" | \"archived\" | \"missing\"\n >();\n for (const id of sourceIds) {\n const status = snapshot?.statuses.get(id);\n if (status) {\n statuses.set(id, status);\n } else {\n statuses.set(id, \"missing\");\n }\n }\n return statuses;\n }\n\n /**\n * Execute a fast-tier LLM chat completion.\n * When gateway model source is active and fastGatewayAgentId is configured,\n * routes through the gateway chain. Otherwise uses the local fast LLM.\n */\n private async fastChatCompletion(\n messages: Array<{ role: string; content: string }>,\n options: { temperature?: number; maxTokens?: number; timeoutMs?: number; operation?: string; priority?: \"background\" | \"recall-critical\" },\n ): Promise<{ content: string } | null> {\n if (this._fastGatewayLlm && this.config.modelSource === \"gateway\") {\n const agentId =\n this.config.fastGatewayAgentId || this.config.gatewayAgentId || undefined;\n const result = await this._fastGatewayLlm.chatCompletion(\n messages as Array<{ role: \"system\" | \"user\" | \"assistant\"; content: string }>,\n { temperature: options.temperature, maxTokens: options.maxTokens, timeoutMs: options.timeoutMs, agentId },\n );\n return result ? { content: result.content } : null;\n }\n const result = await this.fastLlm.chatCompletion(messages, options);\n return result ? { content: result.content } : null;\n }\n\n /**\n * Get a fast-tier LLM client compatible with the rerank interface.\n * When gateway model source is active, routes through the gateway fast chain.\n * Otherwise returns the local fast LLM directly.\n */\n get fastLlmForRerank(): {\n chatCompletion: (\n messages: Array<{ role: string; content: string }>,\n options?: { maxTokens?: number; temperature?: number; timeoutMs?: number; operation?: string; priority?: \"recall-critical\" | \"background\" },\n ) => Promise<{ content: string } | null>;\n } {\n if (this._fastGatewayLlm && this.config.modelSource === \"gateway\") {\n return {\n chatCompletion: (messages, options) =>\n this.fastChatCompletion(messages, options ?? {}),\n };\n }\n return this.fastLlm;\n }\n\n async initialize(): Promise<void> {\n // Recreate the deferred-ready gate on every initialize() call.\n // The same Orchestrator instance may be reused across stop/start cycles\n // (src/index.ts does this). Without this reset, the second cycle's\n // `await orchestrator.deferredReady` resolves immediately (already settled\n // from the first cycle) while the new deferredInitialize() is still running.\n this.deferredReady = new Promise<void>((resolve) => {\n this.resolveDeferredReady = resolve;\n });\n\n try {\n await migrateFromEngram({\n quiet: true,\n logger: (message) => log.info(message),\n });\n await this.storage.ensureDirectories();\n await this.storage.loadAliases();\n if (this.config.namespacesEnabled) {\n const namespaces = new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]);\n for (const ns of namespaces) {\n const sm = await this.storageRouter.storageFor(ns);\n await sm.ensureDirectories();\n await sm.loadAliases().catch(() => undefined);\n }\n }\n await this.relevance.load();\n await this.negatives.load();\n await this.lastRecall.load();\n await this.tierMigrationStatus.load();\n await this.sessionObserver.load();\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n this.utilityRuntimeValues = await loadUtilityRuntimeValues({\n memoryDir: this.config.memoryDir,\n memoryUtilityLearningEnabled: this.config.memoryUtilityLearningEnabled,\n promotionByOutcomeEnabled: this.config.promotionByOutcomeEnabled,\n });\n\n // Initialize content-hash dedup index\n if (this.config.factDeduplicationEnabled) {\n const stateDir = path.join(this.config.memoryDir, \"state\");\n this.contentHashIndex = new ContentHashIndex(stateDir);\n await this.contentHashIndex.load();\n log.info(\n `content-hash dedup: loaded ${this.contentHashIndex.size} hashes`,\n );\n }\n await this.transcript.initialize();\n await this.summarizer.initialize();\n if (this.sharedContext) {\n await this.sharedContext.ensureStructure();\n }\n if (this.compounding) {\n await this.compounding.ensureDirs();\n }\n\n // Buffer and compaction cleanup are fast and needed for basic operation —\n // load them before the init gate so turn buffering works immediately.\n try {\n await this.buffer.load();\n } catch (bufErr) {\n log.error(\n `buffer.load() failed (init gate will still open): ${bufErr}`,\n );\n this.buffer.resetToEmpty();\n }\n if (this.config.compactionResetEnabled) {\n try {\n const wsDir = this.config.workspaceDir || defaultWorkspaceDir();\n const files = await readdir(wsDir).catch(() => [] as string[]);\n for (const f of files) {\n if (!f.startsWith(\".compaction-reset-signal-\")) continue;\n const fp = path.join(wsDir, f);\n const s = await stat(fp).catch(() => null);\n if (s && Date.now() - s.mtimeMs >= COMPACTION_SIGNAL_MAX_AGE_MS) {\n await unlink(fp).catch(() => {});\n log.debug(`initialize: removed stale compaction signal ${f}`);\n }\n }\n } catch (err) {\n log.debug(\"initialize: stale signal sweep failed:\", err);\n }\n }\n\n // QMD probe + collection check: determines the final QMD state (real\n // client vs NoopSearchBackend). Must complete BEFORE the init gate opens\n // so that recall() — which awaits initPromise — always observes the final\n // QMD state. Without this ordering, a concurrent recall() could read\n // this.qmd while it's still the real client, then get errors when\n // deferredInitialize() swaps it to NoopSearchBackend mid-query.\n try {\n const available = await this.qmd.probe();\n if (available) {\n log.info(`Search backend: available ${this.qmd.debugStatus()}`);\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n const states = await Promise.all(\n namespaces.map(async (namespace) => ({\n namespace,\n state: this.config.namespacesEnabled\n ? await this.namespaceSearchRouter.ensureNamespaceCollection(\n namespace,\n )\n : await this.qmd.ensureCollection(this.config.memoryDir),\n })),\n );\n const defaultState =\n states.find(\n (entry) => entry.namespace === this.config.defaultNamespace,\n )?.state ?? \"unknown\";\n if (defaultState === \"missing\") {\n await this.disposeSearchBackendIfNeeded();\n this.qmd = new NoopSearchBackend();\n log.warn(\n \"Search collection missing for Remnic memory store; disabling search retrieval for this runtime (fallback retrieval remains enabled)\",\n );\n } else if (defaultState === \"unknown\") {\n log.warn(\n \"Search collection check unavailable; keeping search retrieval enabled for fail-open behavior\",\n );\n } else if (defaultState === \"skipped\") {\n log.debug(\n \"Search collection check skipped (remote or daemon-only mode)\",\n );\n }\n for (const entry of states) {\n if (entry.namespace === this.config.defaultNamespace) continue;\n if (entry.state === \"missing\") {\n log.warn(\n `Search collection missing for namespace '${entry.namespace}'; namespace retrieval will fail open to non-search paths`,\n );\n }\n }\n } else if (this.qmd instanceof NoopSearchBackend) {\n log.debug(`Search backend: noop (search intentionally disabled)`);\n } else {\n log.warn(`Search backend: not available ${this.qmd.debugStatus()}`);\n }\n } catch (err) {\n log.error(`QMD probe/collection check failed (non-fatal): ${err}`);\n }\n\n // Open the init gate — essential state (storage, aliases, relevance,\n // transcript, summarizer, buffer) is loaded AND QMD state is finalized\n // (probe + collection check complete, NoopSearchBackend swap done if\n // needed). Warmup, sync, caches, and remaining heavy operations run in\n // the background after this point via deferredInitialize().\n if (this.resolveInit) {\n this.resolveInit();\n this.resolveInit = null;\n log.info(\"init gate opened (essential state + QMD state loaded)\");\n }\n\n // Deferred init: QMD sync, warmup, conversation index, caches, cron.\n // Runs in background so gateway_start returns fast. On low-power hardware\n // (Umbrel, RPi) QMD warmup/sync alone can take 30-60s and cause gateway\n // restart loops when they block the startup path. See issue #462.\n // Note: QMD probe + collection check (including NoopSearchBackend swap)\n // already ran above before the init gate, so this.qmd is finalized.\n //\n // Capture the resolver by value so a concurrent re-initialize() cannot\n // overwrite this.resolveDeferredReady before .finally() runs — that would\n // cause the first cycle's .finally() to resolve the *second* cycle's\n // promise prematurely while leaving the first cycle's promise pending.\n const resolveDeferred = this.resolveDeferredReady;\n this.resolveDeferredReady = null;\n this.deferredInitAbort = new AbortController();\n this.deferredInitialize(this.deferredInitAbort.signal)\n .catch((err) => {\n log.error(`deferred initialization failed (non-fatal): ${err}`);\n })\n .finally(() => {\n resolveDeferred?.();\n });\n } catch (err) {\n // Resolve both gates so callers never hang on permanently-pending promises\n // after catching the initialize() error:\n //\n // - initPromise: recall(), generateDaySummary(), etc. await this as a\n // readiness gate with a 15s timeout. Leaving it pending means every\n // subsequent call pays that timeout penalty.\n //\n // - deferredReady: CLI callers await this for full QMD readiness. Without\n // resolution it hangs forever since deferredInitialize() never ran.\n if (this.resolveInit) {\n this.resolveInit();\n this.resolveInit = null;\n }\n if (this.resolveDeferredReady) {\n this.resolveDeferredReady();\n this.resolveDeferredReady = null;\n }\n throw err;\n }\n }\n\n private async deferredInitialize(signal: AbortSignal): Promise<void> {\n\n // Sync QMD index with current disk state so recall finds recently-written\n // facts. Without this, the index stays stale from the last extraction-\n // triggered update — which can be days ago if the daemon restarted without\n // new extractions. This is the root cause of \"0 memories\" recall results\n // despite thousands of facts on disk.\n if (this.qmd.isAvailable() && this.config.qmdMaintenanceEnabled) {\n try {\n log.info(\"QMD startup sync: updating index to match current disk state\");\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.updateNamespaces(\n this.configuredNamespaces(),\n { signal },\n );\n } else {\n await this.qmd.update({ signal });\n }\n log.info(\"QMD startup sync: complete\");\n this.deferredSyncSucceeded = true;\n } catch (err) {\n log.warn(`QMD startup sync failed (non-fatal): ${err}`);\n // deferredSyncSucceeded stays false — server retry will attempt sync\n }\n } else if (!(this.qmd.isAvailable())) {\n // QMD not available at deferred init time — server retry will handle it\n } else {\n // QMD available but maintenance disabled — consider sync not needed\n this.deferredSyncSucceeded = true;\n }\n\n if (signal.aborted) return;\n\n // Warmup: run cheap searches to pre-load QMD embedding models and the\n // embedding-fallback JSON index so the first real recall is fast.\n const warmupPromises: Promise<void>[] = [];\n if (this.qmd.isAvailable()) {\n const warmupNs = this.config.defaultNamespace;\n log.info(\"QMD warmup: pre-loading models with a test search\");\n warmupPromises.push(\n this.qmd\n .search(\"warmup\", warmupNs, 1, undefined, { signal })\n .then(() => {\n log.info(\"QMD warmup: complete\");\n })\n .catch((err) => {\n log.debug(`QMD warmup search failed (non-fatal): ${err}`);\n }),\n );\n }\n if (this.config.embeddingFallbackEnabled) {\n warmupPromises.push(\n this.embeddingFallback\n .isAvailable()\n .then((ok) => {\n log.info(\n `Embedding fallback warmup: ${ok ? \"available\" : \"unavailable (no provider)\"}`,\n );\n })\n .catch((err) => {\n log.debug(`Embedding fallback warmup failed (non-fatal): ${err}`);\n }),\n );\n }\n await Promise.all(warmupPromises);\n if (signal.aborted) return;\n\n // Pre-warm knowledge index, memory, and entity caches.\n // Awaited so callers of `deferredReady` can rely on warmups being complete\n // and shutdown sequencing does not race with in-flight cache builds.\n const cacheWarmups: Promise<void>[] = [];\n if (this.config.knowledgeIndexEnabled) {\n cacheWarmups.push(\n (async () => {\n try {\n const t0 = Date.now();\n await this.storage.buildKnowledgeIndex(this.config);\n log.info(`Knowledge Index warmup: complete in ${Date.now() - t0}ms`);\n } catch (err) {\n log.debug(`Knowledge Index warmup failed (non-fatal): ${err}`);\n }\n })(),\n );\n }\n cacheWarmups.push(this.storage.readAllMemories().then(() => {}).catch(() => {}));\n cacheWarmups.push(this.storage.readAllEntityFiles().then(() => {}).catch(() => {}));\n await Promise.all(cacheWarmups);\n if (signal.aborted) return;\n\n if (this.config.conversationIndexEnabled && this.conversationIndexBackend) {\n try {\n const init = await this.conversationIndexBackend.initialize();\n if (!init.enabled) {\n this.config.conversationIndexEnabled = false;\n }\n if (init.logLevel === \"info\") {\n log.info(init.message);\n } else if (init.logLevel === \"warn\") {\n log.warn(init.message);\n } else {\n log.debug(init.message);\n }\n } catch (err) {\n log.error(`Conversation index initialization failed (non-fatal): ${err}`);\n this.config.conversationIndexEnabled = false;\n }\n }\n\n if (signal.aborted) return;\n\n if (this.config.localLlmEnabled) {\n try {\n await this.validateLocalLlmModel();\n } catch (err) {\n log.error(`Local LLM validation failed (non-fatal): ${err}`);\n }\n }\n\n if (signal.aborted) return;\n\n // Await cron auto-registration so callers that `await deferredReady` can\n // rely on cron jobs being registered when it resolves. Without this, the\n // fire-and-forget pattern lets deferredReady settle while cron writes are\n // still in flight. Errors are non-fatal — catch individually.\n if (this.config.daySummaryEnabled) {\n try {\n await this.autoRegisterDaySummaryCron();\n } catch (err) {\n log.debug(`day-summary cron auto-register failed (non-fatal): ${err}`);\n }\n }\n if (this.config.nightlyGovernanceCronAutoRegister) {\n try {\n await this.autoRegisterNightlyGovernanceCron();\n } catch (err) {\n log.debug(`nightly governance cron auto-register failed (non-fatal): ${err}`);\n }\n }\n if (this.config.procedural?.proceduralMiningCronAutoRegister) {\n try {\n await this.autoRegisterProceduralMiningCron();\n } catch (err) {\n log.debug(`procedural mining cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n // Auto-register contradiction scan cron (gated by config)\n if (this.config.contradictionScan?.enabled) {\n try {\n await this.autoRegisterContradictionScanCron();\n } catch (err) {\n log.debug(`contradiction scan cron auto-register failed (non-fatal): ${err}`);\n }\n }\n\n log.info(\"orchestrator initialized (full — deferred steps complete)\");\n }\n\n /**\n * Namespace-aware startup search sync. Re-probes QMD, ensures collections\n * (namespace-aware when namespacesEnabled), runs update, and warms up search.\n * Designed for server retry paths that run after the deferred init completes\n * when QMD was not available during initial startup.\n *\n * Accepts an optional AbortSignal so callers can interrupt the sync during\n * shutdown. The signal is checked between phases and forwarded into the QMD\n * update and warmup search calls so a long-running `qmd update` subprocess\n * is killed promptly rather than left in flight after `httpServer.stop()`.\n *\n * Returns true if the sync succeeded (QMD now available), false otherwise.\n */\n async startupSearchSync(signal?: AbortSignal): Promise<boolean> {\n if (signal?.aborted) return false;\n\n const available = await this.qmd.probe();\n if (!available) return false;\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after probe\");\n return false;\n }\n\n log.info(`startupSearchSync: backend now available ${this.qmd.debugStatus()}`);\n\n // Clear namespace router cache so re-probe picks up newly available backends\n if (this.config.namespacesEnabled) {\n this.namespaceSearchRouter.clearCache();\n }\n\n // Ensure collections — namespace-aware when enabled\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n\n const states = await Promise.all(\n namespaces.map(async (namespace) => ({\n namespace,\n state: this.config.namespacesEnabled\n ? await this.namespaceSearchRouter.ensureNamespaceCollection(namespace)\n : await this.qmd.ensureCollection(this.config.memoryDir),\n })),\n );\n\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after ensureCollection\");\n return false;\n }\n\n const defaultState =\n states.find((e) => e.namespace === this.config.defaultNamespace)?.state ?? \"unknown\";\n if (defaultState === \"missing\") {\n // Reset the real backend's available flag before replacing it with noop.\n // probe() set available=true earlier in this call; without this reset,\n // any code that captured a reference to the old backend (e.g. a concurrent\n // recall() that read this.qmd before the reassignment) would observe\n // isAvailable()===true against a backend with a missing collection.\n if (\"available\" in this.qmd) {\n (this.qmd as any).available = false;\n }\n await this.disposeSearchBackendIfNeeded();\n this.qmd = new NoopSearchBackend();\n log.warn(\"startupSearchSync: search collection missing; disabling search (fallback retrieval remains enabled)\");\n return false;\n }\n\n // Run index update — namespace-aware when enabled.\n // qmd.update() swallows errors internally, so we: (1) snapshot fail/run\n // timestamps, (2) reset throttles so the update isn't skipped by stale\n // backoff, and (3) verify timestamps after update to confirm it executed\n // and didn't fail silently.\n // The abort signal is forwarded into the QMD subprocess call so the\n // long-running `qmd update` process is killed promptly on shutdown.\n if (this.config.qmdMaintenanceEnabled) {\n try {\n const failTsBefore = \"lastUpdateFailedAtMs\" in this.qmd\n ? (this.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const hasRunTs = \"lastUpdateRanAtMs\" in this.qmd;\n if (\"resetUpdateThrottles\" in this.qmd) {\n (this.qmd as any).resetUpdateThrottles();\n }\n log.info(\"startupSearchSync: updating index to match current disk state\");\n let namespacesUpdated = 0;\n if (this.config.namespacesEnabled) {\n namespacesUpdated = await this.namespaceSearchRouter.updateNamespaces(\n namespaces,\n { signal },\n );\n } else {\n await this.qmd.update({ signal });\n }\n if (signal?.aborted) {\n log.debug(\"startupSearchSync: aborted after update\");\n return false;\n }\n const failTsAfter = \"lastUpdateFailedAtMs\" in this.qmd\n ? (this.qmd as any).lastUpdateFailedAtMs as number | null\n : null;\n const runTsAfter = hasRunTs\n ? (this.qmd as any).lastUpdateRanAtMs as number | null\n : null;\n if (failTsAfter !== null && failTsAfter !== failTsBefore) {\n log.warn(\"startupSearchSync: update silently failed (detected via fail timestamp)\");\n return false;\n }\n if (this.config.namespacesEnabled) {\n if (namespacesUpdated === 0) {\n log.warn(\"startupSearchSync: no namespace backends were eligible for update (all unavailable or collections missing)\");\n return false;\n }\n log.info(`startupSearchSync: namespace updates succeeded (${namespacesUpdated}/${namespaces.length} namespaces updated)`);\n } else if (hasRunTs && runTsAfter === null) {\n log.warn(\"startupSearchSync: update was throttled/skipped (run timestamp is null after reset + update)\");\n return false;\n }\n log.info(\"startupSearchSync: sync complete\");\n } catch (err) {\n log.warn(`startupSearchSync: update failed: ${err}`);\n return false;\n }\n }\n\n // Warmup search to pre-load embedding models\n if (!signal?.aborted) {\n try {\n await this.qmd.search(\"warmup\", this.config.defaultNamespace, 1, undefined, { signal });\n log.info(\"startupSearchSync: warmup complete\");\n } catch (err) {\n log.debug(`startupSearchSync: warmup search failed (non-fatal): ${err}`);\n }\n }\n\n return true;\n }\n\n /**\n * Auto-register the engram-day-summary cron job in OpenClaw if it doesn't exist.\n * Fire-and-forget — never blocks init or crashes on failure.\n */\n private async autoRegisterDaySummaryCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\n \"day-summary cron: jobs.json not found, skipping auto-register\",\n );\n return;\n }\n const created = await ensureDaySummaryCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(\n `day-summary cron auto-registered (${created.jobId}, 23:47 ${Intl.DateTimeFormat().resolvedOptions().timeZone})`,\n );\n } else {\n log.debug(\"day-summary cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`day-summary cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterNightlyGovernanceCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"nightly governance cron: jobs.json not found, skipping auto-register\");\n return;\n }\n\n const created = await ensureNightlyGovernanceCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(\n `nightly governance cron auto-registered (${created.jobId}, 02:23 ${Intl.DateTimeFormat().resolvedOptions().timeZone})`,\n );\n } else {\n log.debug(\"nightly governance cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`nightly governance cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterProceduralMiningCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"procedural mining cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const created = await ensureProceduralMiningCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(`procedural mining cron auto-registered (${created.jobId})`);\n } else {\n log.debug(\"procedural mining cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`procedural mining cron auto-register error: ${err}`);\n }\n }\n\n private async autoRegisterContradictionScanCron(): Promise<void> {\n const home = resolveHomeDir();\n const jobsPath = path.join(home, \".openclaw\", \"cron\", \"jobs.json\");\n try {\n if (!existsSync(jobsPath)) {\n log.debug(\"contradiction scan cron: jobs.json not found, skipping auto-register\");\n return;\n }\n const created = await ensureContradictionScanCron(jobsPath, {\n timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,\n });\n if (created.created) {\n log.info(`contradiction scan cron auto-registered (${created.jobId})`);\n } else {\n log.debug(\"contradiction scan cron already exists, skipping auto-register\");\n }\n } catch (err) {\n log.debug(`contradiction scan cron auto-register error: ${err}`);\n }\n }\n\n async applyBehaviorRuntimePolicy(\n state: BehaviorLoopPolicyState,\n ): Promise<{\n applied: boolean;\n rolledBack: boolean;\n values: RuntimePolicyValues | null;\n reason: string;\n }> {\n const result = await this.policyRuntime.applyFromBehaviorState(state);\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n return result;\n }\n\n async rollbackBehaviorRuntimePolicy(): Promise<boolean> {\n const rolledBack = await this.policyRuntime.rollback();\n this.runtimePolicyValues = await this.policyRuntime.loadRuntimeValues();\n return rolledBack;\n }\n\n async maybeRunFileHygiene(): Promise<void> {\n const hygiene = this.config.fileHygiene;\n if (!hygiene?.enabled) return;\n\n const now = Date.now();\n if (now - this.lastFileHygieneRunAtMs < hygiene.runMinIntervalMs) return;\n this.lastFileHygieneRunAtMs = now;\n\n // Rotation first (keeps bootstrap files small).\n if (hygiene.rotateEnabled) {\n for (const rel of hygiene.rotatePaths) {\n const abs = path.isAbsolute(rel)\n ? rel\n : path.join(this.config.workspaceDir, rel);\n try {\n const raw = await readFile(abs, \"utf-8\");\n if (raw.length > hygiene.rotateMaxBytes) {\n const archiveDir = path.join(\n this.config.workspaceDir,\n hygiene.archiveDir,\n );\n const base = path.basename(abs);\n const prefix =\n base\n .toUpperCase()\n .replace(/\\.MD$/i, \"\")\n .replace(/[^A-Z0-9]+/g, \"-\") || \"FILE\";\n const { newContent } = await rotateMarkdownFileToArchive({\n filePath: abs,\n archiveDir,\n archivePrefix: prefix,\n keepTailChars: hygiene.rotateKeepTailChars,\n });\n await writeFile(abs, newContent, \"utf-8\");\n }\n } catch {\n // ignore missing/unreadable targets\n }\n }\n }\n\n // Lint (warn before truncation risk).\n if (hygiene.lintEnabled) {\n const warnings = await lintWorkspaceFiles({\n workspaceDir: this.config.workspaceDir,\n paths: hygiene.lintPaths,\n budgetBytes: hygiene.lintBudgetBytes,\n warnRatio: hygiene.lintWarnRatio,\n });\n for (const w of warnings) {\n log.warn(w.message);\n }\n\n if (hygiene.warningsLogEnabled && warnings.length > 0) {\n const fp = path.join(this.config.memoryDir, hygiene.warningsLogPath);\n await mkdir(path.dirname(fp), { recursive: true });\n const stamp = new Date().toISOString();\n const block =\n `\\n\\n## ${stamp}\\n\\n` +\n warnings.map((w) => `- ${w.message}`).join(\"\\n\") +\n \"\\n\";\n let existing = \"\";\n try {\n existing = await readFile(fp, \"utf-8\");\n } catch {\n existing = \"# Engram File Hygiene Warnings\\n\";\n }\n await writeFile(fp, existing + block, \"utf-8\");\n }\n }\n }\n\n async runBootstrap(options: BootstrapOptions): Promise<BootstrapResult> {\n const engine = new BootstrapEngine(this.config, this);\n return engine.run(options);\n }\n\n async runConsolidationNow(): Promise<{\n memoriesProcessed: number;\n merged: number;\n invalidated: number;\n }> {\n return this.runConsolidation();\n }\n\n async reindexMemoryById(\n id: string,\n options?: { storage?: StorageManager },\n ): Promise<void> {\n await this.indexPersistedMemory(options?.storage ?? this.storage, id);\n this.requestQmdMaintenance();\n }\n\n registerConsolidationObserver(\n observer: (observation: ConsolidationObservation) => Promise<void> | void,\n ): () => void {\n this.consolidationObservers.add(observer);\n return () => {\n this.consolidationObservers.delete(observer);\n };\n }\n\n async runSemanticConsolidationNow(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n }): Promise<SemanticConsolidationResult> {\n return this.runSemanticConsolidation({ ...options, force: true });\n }\n\n private async runSemanticConsolidation(options?: {\n dryRun?: boolean;\n thresholdOverride?: number;\n force?: boolean;\n }): Promise<SemanticConsolidationResult> {\n const result: SemanticConsolidationResult = {\n clustersFound: 0,\n memoriesConsolidated: 0,\n memoriesArchived: 0,\n errors: 0,\n clusters: [],\n };\n\n if (!this.config.semanticConsolidationEnabled && !options?.force) {\n log.debug(\"[semantic-consolidation] disabled in config\");\n return result;\n }\n\n log.info(\"[semantic-consolidation] starting run\");\n\n const allMemories = await this.storage.readAllMemories();\n if (allMemories.length < 10) {\n log.debug(\"[semantic-consolidation] too few memories, skipping\");\n return result;\n }\n\n const threshold =\n options?.thresholdOverride ?? this.config.semanticConsolidationThreshold;\n const clusters = findSimilarClusters(allMemories, {\n threshold,\n minClusterSize: this.config.semanticConsolidationMinClusterSize,\n excludeCategories: this.config.semanticConsolidationExcludeCategories,\n maxPerRun: this.config.semanticConsolidationMaxPerRun,\n });\n\n result.clustersFound = clusters.length;\n result.clusters = clusters;\n\n if (clusters.length === 0) {\n log.info(\"[semantic-consolidation] no clusters found\");\n return result;\n }\n\n log.info(`[semantic-consolidation] found ${clusters.length} cluster(s)`);\n\n if (options?.dryRun) {\n log.info(\n \"[semantic-consolidation] dry run — skipping LLM synthesis and archival\",\n );\n return result;\n }\n\n // Use FallbackLlmClient for LLM calls (same pattern as causal-consolidation.ts)\n // Honor semanticConsolidationModel: \"auto\" = primary, \"fast\" = local fast, or specific model\n const { FallbackLlmClient } = await import(\"./fallback-llm.js\");\n const useGateway = this.config.modelSource === \"gateway\";\n const modelSetting = this.config.semanticConsolidationModel;\n if (modelSetting === \"fast\" && this.fastLlm && !useGateway) {\n log.info(\"[semantic-consolidation] using fast local LLM for synthesis\");\n }\n const gatewayAgentId = useGateway\n ? (modelSetting === \"fast\" && this.config.fastGatewayAgentId\n ? this.config.fastGatewayAgentId\n : this.config.gatewayAgentId || undefined)\n : undefined;\n const llm = new FallbackLlmClient(this.config.gatewayConfig);\n if (!llm.isAvailable(gatewayAgentId) && !(modelSetting === \"fast\" && this.fastLlm && !useGateway)) {\n log.warn(\n \"[semantic-consolidation] no LLM available — skipping synthesis\",\n );\n return result;\n }\n\n // Discover memory extensions once for all clusters (#382)\n let extensionsBlock = \"\";\n try {\n extensionsBlock = await buildExtensionsBlockForConsolidation(this.config);\n } catch (err) {\n log.warn(`[semantic-consolidation] extension discovery failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`);\n }\n\n for (const cluster of clusters) {\n try {\n // Operator-aware prompt (issue #561 PR 3): ask the LLM to pick the\n // SPLIT/MERGE/UPDATE operator alongside the canonical output. Falls\n // back to the legacy plain-blob prompt when operator-aware\n // consolidation is explicitly disabled via config, so rollbacks stay\n // clean.\n // Use the `=== true` idiom for default-false flags (PR #632\n // review, cursor Low): sibling disabled-by-default flags like\n // `semanticConsolidationEnabled` follow the same convention,\n // while `!== false` is reserved for default-on flags.\n const operatorAwareEnabled =\n this.config.operatorAwareConsolidationEnabled === true;\n let prompt = operatorAwareEnabled\n ? buildOperatorAwareConsolidationPrompt(cluster)\n : buildConsolidationPrompt(cluster);\n if (extensionsBlock.length > 0) {\n prompt += \"\\n\\n\" + extensionsBlock;\n }\n const messages = [\n {\n role: \"system\" as const,\n content: operatorAwareEnabled\n ? 'You are a memory consolidation system. Return ONLY a JSON object with two keys, \"operator\" and \"output\". The \"operator\" value MUST be one of the exact strings \"merge\", \"update\", or \"split\" — never a pipe-separated placeholder, never prose. The \"output\" value is the canonical memory text.'\n : \"You are a memory consolidation system. Output only the consolidated memory text.\",\n },\n { role: \"user\" as const, content: prompt },\n ];\n const llmOpts = { temperature: 0.2, maxTokens: 2000 };\n\n // Route to the configured model\n let response: { content: string } | null = null;\n if (useGateway) {\n // Gateway model source — use the appropriate agent chain\n response = await llm.chatCompletion(messages, { ...llmOpts, agentId: gatewayAgentId });\n } else if (modelSetting === \"fast\" && this.fastLlm) {\n const fastResult = await this.fastLlm.chatCompletion(messages, {\n operation: \"semantic-consolidation\",\n maxTokens: llmOpts.maxTokens,\n temperature: llmOpts.temperature,\n priority: \"background\",\n });\n response = fastResult ? { content: fastResult.content } : null;\n } else {\n response = await llm.chatCompletion(messages, llmOpts);\n }\n\n if (!response?.content) {\n log.warn(\n `[semantic-consolidation] empty LLM response for cluster in \"${cluster.category}\"`,\n );\n result.errors++;\n continue;\n }\n\n // Operator-aware parse (issue #561 PR 3). In legacy mode we fall\n // back to the plain-text parser and derive the operator from the\n // cluster-shape heuristic so `derived_via` still lands.\n let canonicalContent: string;\n let operator: \"split\" | \"merge\" | \"update\";\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 this.storage.snapshotForProvenance(m.path);\n if (entry) derivedFromEntries.push(entry);\n }\n\n // Write the canonical memory\n const canonicalId = await this.storage.writeMemory(\n newest.frontmatter.category,\n canonicalContent,\n {\n actor: \"semantic-consolidation\",\n confidence: newest.frontmatter.confidence,\n tags: [\n ...new Set(\n cluster.memories.flatMap((m) => m.frontmatter.tags ?? []),\n ),\n ],\n source: \"semantic-consolidation\",\n lineage: lineageIds,\n derivedFrom: derivedFromEntries.length > 0 ? derivedFromEntries : undefined,\n derivedVia: operator,\n },\n );\n\n result.memoriesConsolidated++;\n\n // Archive originals\n for (const m of cluster.memories) {\n const archiveResult = await this.storage.archiveMemory(m, {\n actor: \"semantic-consolidation\",\n reasonCode: \"semantic-consolidation\",\n relatedMemoryIds: [canonicalId],\n });\n if (archiveResult) {\n // Remove from content-hash index.\n // Use the raw-content hash stored on the frontmatter at write\n // time (contentHash) — it is format-agnostic and survives any\n // citation template. Legacy memories without contentHash are\n // skipped (see Finding 2 — Urgw).\n if (this.contentHashIndex) {\n if (m.frontmatter.contentHash) {\n // Modern memory: frontmatter.contentHash is already a SHA-256\n // hex string — use removeByHash to avoid double-hashing.\n this.contentHashIndex.removeByHash(m.frontmatter.contentHash);\n } else {\n // Legacy memory written before contentHash was stored on the\n // frontmatter. Pre-#369 facts were stored without inline\n // citations, so m.content is the raw fact text and we can\n // remove the hash directly from the content. This clears\n // stale dedup entries so the fact can be re-extracted.\n log.warn(\n `[semantic-consolidation] removing hash for legacy memory ${m.frontmatter.id ?? \"(unknown)\"} via content fallback — no contentHash in frontmatter`,\n );\n this.contentHashIndex.remove(m.content);\n }\n }\n await this.embeddingFallback.removeFromIndex(m.frontmatter.id);\n if (\n this.config.queryAwareIndexingEnabled &&\n m.path &&\n m.frontmatter?.created\n ) {\n deindexMemory(\n this.config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n result.memoriesArchived++;\n }\n }\n\n log.info(\n `[semantic-consolidation] consolidated ${cluster.memories.length} memories → ${canonicalId}`,\n );\n } catch (err) {\n log.warn(\n `[semantic-consolidation] cluster processing failed: ${err instanceof Error ? err.message : String(err)}`,\n );\n result.errors++;\n }\n }\n\n // Save hash index if we modified it\n if (result.memoriesArchived > 0 && this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) =>\n log.warn(\n `[semantic-consolidation] content-hash index save failed: ${err}`,\n ),\n );\n }\n\n log.info(\n `[semantic-consolidation] complete: clusters=${result.clustersFound}, consolidated=${result.memoriesConsolidated}, archived=${result.memoriesArchived}, errors=${result.errors}`,\n );\n\n // #378: fire the Codex materialize post-hook so `codexMaterializeOnConsolidation`\n // actually has a runtime effect. The helper silently no-ops when the\n // feature flag or the per-trigger toggle is off, when the sentinel is\n // missing, or when nothing has changed since the previous run, so it's\n // safe to always call here. Wrapped in a try/catch because a failed\n // materialize must never abort the consolidation result — consolidation\n // is the load-bearing operation; materialization is an optional mirror.\n try {\n await materializeAfterSemanticConsolidation({\n config: this.config,\n memoryDir: this.config.memoryDir,\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 return result;\n }\n\n async waitForExtractionIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.queueProcessing || this.extractionQueue.length > 0) {\n if (Date.now() - started > timeoutMs) {\n log.warn(`waitForExtractionIdle timed out after ${timeoutMs}ms`);\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return true;\n }\n\n async waitForConsolidationIdle(timeoutMs: number = 60_000): Promise<boolean> {\n const started = Date.now();\n while (this.consolidationInFlight) {\n if (Date.now() - started > timeoutMs) {\n log.warn(`waitForConsolidationIdle timed out after ${timeoutMs}ms`);\n return false;\n }\n await new Promise((resolve) => setTimeout(resolve, 50));\n }\n return true;\n }\n\n async getStorage(namespace?: string): Promise<StorageManager> {\n const ns =\n namespace && namespace.length > 0\n ? namespace\n : this.config.defaultNamespace;\n return this.storageRouter.storageFor(ns);\n }\n\n async processEntitySynthesisQueue(\n namespace?: string,\n maxEntities: number = 5,\n ): Promise<number> {\n if (\n !this.config.entitySummaryEnabled\n || maxEntities <= 0\n || this.config.entitySynthesisMaxTokens <= 0\n ) return 0;\n const storage = await this.getStorage(namespace);\n const queued = await storage.refreshEntitySynthesisQueue();\n let processed = 0;\n let attempted = 0;\n\n for (const entityName of queued) {\n if (attempted >= maxEntities) break;\n attempted += 1;\n try {\n const raw = await storage.readEntity(entityName);\n if (!raw) continue;\n const entity = parseEntityFile(raw, this.config.entitySchemas);\n const previousSynthesis = entity.synthesis || entity.summary || \"\";\n const sortedTimelineEntries = entity.timeline\n .slice()\n .sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));\n const newerTimelineEntries = sortedTimelineEntries.filter(\n (entry) =>\n !entity.synthesisUpdatedAt\n || compareEntityTimestamps(entry.timestamp, entity.synthesisUpdatedAt) > 0,\n );\n const appendedTimelineEntries = entity.synthesisTimelineCount === undefined\n ? []\n : entity.timeline.slice(Math.max(0, entity.synthesisTimelineCount));\n const structuredEvidenceEntries = flattenStructuredSectionEvidence(entity.structuredSections);\n const structuredEvidenceCount = structuredEvidenceEntries.length;\n const structuredEvidenceDigest = fingerprintEntityStructuredFacts(entity);\n const structuredEvidenceDrifted = structuredEvidenceDigest !== (entity.synthesisStructuredFactDigest?.trim() || undefined);\n const appendedStructuredEvidenceEntries = entity.synthesisStructuredFactCount === undefined\n || structuredEvidenceDrifted\n ? structuredEvidenceEntries\n : structuredEvidenceEntries.slice(Math.max(0, entity.synthesisStructuredFactCount));\n const candidateEvidenceEntries = [\n ...newerTimelineEntries,\n ...appendedTimelineEntries,\n ...appendedStructuredEvidenceEntries,\n ]\n .slice()\n .sort((left, right) => compareEntityTimestamps(right.timestamp, left.timestamp));\n const dedupedEvidenceEntries = dedupeEntitySynthesisEvidenceEntries(\n candidateEvidenceEntries.length > 0\n ? candidateEvidenceEntries\n : [...sortedTimelineEntries, ...structuredEvidenceEntries],\n );\n const chronologicalEvidenceEntries = dedupedEvidenceEntries\n .slice()\n .sort((left, right) => compareEntityTimestamps(left.timestamp, right.timestamp));\n if (chronologicalEvidenceEntries.length === 0) continue;\n const latestEvidenceTimestamp = chronologicalEvidenceEntries\n .slice()\n .reverse()\n .map((entry) => entry.timestamp?.trim() || undefined)\n .find((timestamp) => Boolean(timestamp));\n const previousSynthesisUpdatedAt = entity.synthesisUpdatedAt?.trim() || undefined;\n const nextSynthesisUpdatedAt = compareEntityTimestamps(\n latestEvidenceTimestamp,\n previousSynthesisUpdatedAt,\n ) >= 0\n ? latestEvidenceTimestamp\n : previousSynthesisUpdatedAt;\n const evidenceBatches: typeof chronologicalEvidenceEntries[] = [];\n for (let index = 0; index < chronologicalEvidenceEntries.length; index += 8) {\n evidenceBatches.push(chronologicalEvidenceEntries.slice(index, index + 8));\n }\n\n let nextSynthesis = previousSynthesis;\n let batchFailed = false;\n for (const evidenceEntries of evidenceBatches) {\n const evidenceText = evidenceEntries\n .map((entry) => {\n const sectionTitle = entry.source?.startsWith(\"section:\")\n ? entry.source.slice(\"section:\".length)\n : \"\";\n const metadata = [\n `timestamp=${entry.timestamp}`,\n sectionTitle ? `section=${sectionTitle}` : entry.source ? `source=${entry.source}` : \"\",\n entry.sessionKey ? `session=${entry.sessionKey}` : \"\",\n entry.principal ? `principal=${entry.principal}` : \"\",\n ]\n .filter(Boolean)\n .join(\", \");\n return `- ${metadata}: ${entry.text}`;\n })\n .join(\"\\n\");\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content:\n \"Rewrite the entity synthesis as compact current truth. Preserve uncertainty when evidence conflicts. Return plain text only.\",\n },\n {\n role: \"user\",\n content: [\n `Entity: ${entity.name} (${entity.type})`,\n nextSynthesis ? `Previous synthesis:\\n${nextSynthesis}` : \"Previous synthesis: none\",\n `New evidence:\\n${evidenceText}`,\n ].join(\"\\n\\n\"),\n },\n ],\n {\n temperature: 0.2,\n maxTokens: this.config.entitySynthesisMaxTokens,\n operation: \"entity_summary\",\n priority: \"background\",\n },\n );\n const synthesis = response?.content?.trim().replace(/^[\"']|[\"']$/g, \"\");\n const maxSynthesisChars = Math.max(2_000, this.config.entitySynthesisMaxTokens * 8);\n if (!synthesis || synthesis.length < 10 || synthesis.length > maxSynthesisChars) {\n batchFailed = true;\n break;\n }\n nextSynthesis = synthesis;\n }\n if (batchFailed || nextSynthesis.length === 0) continue;\n const latestRaw = await storage.readEntity(entityName);\n if (!latestRaw) continue;\n const latestEntity = parseEntityFile(latestRaw, this.config.entitySchemas);\n if (\n fingerprintEntitySynthesisEvidence(latestEntity)\n !== fingerprintEntitySynthesisEvidence(entity)\n ) {\n continue;\n }\n await storage.updateEntitySynthesis(entityName, nextSynthesis, {\n entityUpdatedAt: new Date().toISOString(),\n synthesisStructuredFactDigest: structuredEvidenceDigest,\n synthesisStructuredFactCount: structuredEvidenceCount,\n synthesisTimelineCount: entity.timeline.length,\n updatedAt: nextSynthesisUpdatedAt,\n });\n processed += 1;\n } catch (err) {\n log.debug(`entity synthesis refresh failed for ${entityName}: ${err}`);\n }\n }\n\n return processed;\n }\n\n async generateDaySummary(\n memories: string | MemoryFile[],\n ): Promise<DaySummaryResult | null> {\n if (this.initPromise) {\n let initGateTimeoutHandle: ReturnType<typeof setTimeout> | undefined;\n try {\n await Promise.race([\n this.initPromise.catch(() => undefined),\n new Promise((resolve) => {\n initGateTimeoutHandle = setTimeout(resolve, 15_000);\n }),\n ]);\n } finally {\n if (initGateTimeoutHandle) clearTimeout(initGateTimeoutHandle);\n }\n }\n return this.extraction.generateDaySummary(memories);\n }\n\n /**\n * Auto-gather today's facts and hourly summaries from storage, then generate a day summary.\n * Returns null if no facts are found for today.\n */\n async generateDaySummaryAuto(\n namespace?: string,\n ): Promise<DaySummaryResult | null> {\n const gathered = await this.gatherTodayFacts(namespace);\n if (!gathered || !gathered.trim()) {\n log.warn(\"generateDaySummaryAuto: no facts found for today, skipping\");\n return null;\n }\n return this.generateDaySummary(gathered);\n }\n\n /**\n * Read today's facts and hourly summaries from storage, returning them\n * as a formatted string suitable for generateDaySummary().\n */\n async gatherTodayFacts(namespace?: string): Promise<string> {\n const ns =\n namespace && namespace.length > 0\n ? namespace\n : this.config.defaultNamespace;\n const storage = await this.storageRouter.storageFor(ns);\n // Facts are stored under UTC dates, but a local calendar day can span\n // two UTC dates (e.g. 23:47 local in UTC-6 is 05:47 UTC the next day). To capture\n // all facts for the local day, read from both the current UTC date and\n // yesterday's UTC date (which covers the local day's morning hours).\n const now = new Date();\n const utcToday = now.toISOString().slice(0, 10);\n const yesterday = new Date(now.getTime() - 86_400_000)\n .toISOString()\n .slice(0, 10);\n const datesToScan = [yesterday, utcToday].filter(\n (v, i, a) => a.indexOf(v) === i,\n );\n const factsBaseDir = path.join(storage.dir, \"facts\");\n const MAX_CHARS = 100_000;\n\n // --- Read fact files from each date directory ---\n const facts: MemoryFile[] = [];\n for (const date of datesToScan) {\n const factsDir = path.join(factsBaseDir, date);\n try {\n const entries = await readdir(factsDir, { withFileTypes: true });\n for (const entry of entries) {\n if (!entry.name.endsWith(\".md\")) continue;\n const fullPath = path.join(factsDir, entry.name);\n try {\n const raw = await readFile(fullPath, \"utf-8\");\n const fmMatch = raw.match(/^---\\n([\\s\\S]*?)\\n---\\n?([\\s\\S]*)$/);\n if (!fmMatch) continue;\n const fmBlock = fmMatch[1];\n const content = fmMatch[2].trim();\n const fm: Record<string, string> = {};\n for (const line of fmBlock.split(\"\\n\")) {\n const colonIdx = line.indexOf(\":\");\n if (colonIdx === -1) continue;\n fm[line.slice(0, colonIdx).trim()] = line\n .slice(colonIdx + 1)\n .trim();\n }\n facts.push({\n path: fullPath,\n frontmatter: {\n id: fm.id || path.basename(entry.name, \".md\"),\n category: (fm.category as any) || \"fact\",\n created: fm.created || \"unknown\",\n updated: fm.updated || fm.created || \"unknown\",\n source: fm.source || \"unknown\",\n confidence: parseFloat(fm.confidence || \"0.8\"),\n confidenceTier: (fm.confidenceTier as any) || \"implied\",\n tags: [],\n },\n content,\n });\n } catch {\n // Skip unreadable files\n }\n }\n } catch {\n // Directory doesn't exist — no facts for this date\n }\n }\n\n // Sort facts by created timestamp (most recent last) so truncation keeps newest\n facts.sort((a, b) =>\n a.frontmatter.created < b.frontmatter.created ? -1 : 1,\n );\n\n // --- Read hourly summaries for the scanned dates ---\n const hourlySummaries: string[] = [];\n const hourlyBaseDir = path.join(storage.dir, \"summaries\", \"hourly\");\n try {\n const sessionKeys = await readdir(hourlyBaseDir, { withFileTypes: true });\n for (const sk of sessionKeys) {\n if (!sk.isDirectory()) continue;\n for (const date of datesToScan) {\n const summaryFile = path.join(hourlyBaseDir, sk.name, `${date}.md`);\n try {\n const raw = await readFile(summaryFile, \"utf-8\");\n if (raw.trim().length > 0) {\n hourlySummaries.push(raw.trim());\n }\n } catch {\n // No summary file for this session/date\n }\n }\n }\n } catch {\n // No hourly summaries directory\n }\n\n // --- Format and truncate ---\n let formatted = formatDaySummaryMemories(facts);\n if (hourlySummaries.length > 0) {\n formatted +=\n \"\\n\\n---\\n## Hourly Summaries\\n\\n\" +\n hourlySummaries.join(\"\\n\\n---\\n\\n\");\n }\n\n // Truncate intelligently if over budget: drop oldest facts first\n if (formatted.length > MAX_CHARS) {\n // Re-build with fewer facts, keeping most recent\n while (facts.length > 1 && formatted.length > MAX_CHARS) {\n facts.shift(); // drop oldest\n formatted = formatDaySummaryMemories(facts);\n if (hourlySummaries.length > 0) {\n formatted +=\n \"\\n\\n---\\n## Hourly Summaries\\n\\n\" +\n hourlySummaries.join(\"\\n\\n---\\n\\n\");\n }\n }\n // If still over, hard truncate\n if (formatted.length > MAX_CHARS) {\n formatted = formatted.slice(0, MAX_CHARS);\n }\n }\n\n log.info(\n `gatherTodayFacts: collected ${facts.length} facts, ${hourlySummaries.length} hourly summaries (${formatted.length} chars)`,\n );\n\n return formatted;\n }\n\n previewMemoryActionEvent(\n event: Omit<MemoryActionEvent, \"timestamp\"> & { timestamp?: string },\n ): MemoryActionEvent {\n const namespace =\n typeof event.namespace === \"string\" && event.namespace.length > 0\n ? event.namespace\n : this.config.defaultNamespace;\n const eligibility = parseMemoryActionEligibilityContext(\n event.policyEligibility,\n );\n const policy = evaluateMemoryActionPolicy({\n action: event.action,\n eligibility,\n options: {\n actionsEnabled: this.config.contextCompressionActionsEnabled,\n maxCompressionTokensPerHour: this.config.maxCompressionTokensPerHour,\n },\n });\n const dryRun = event.dryRun === true;\n\n const normalizedOutcome = dryRun\n ? event.outcome === \"failed\"\n ? \"failed\"\n : \"skipped\"\n : policy.decision === \"allow\"\n ? event.outcome\n : event.outcome === \"failed\"\n ? \"failed\"\n : \"skipped\";\n const sourceSessionKey =\n typeof event.sourceSessionKey === \"string\" &&\n event.sourceSessionKey.length > 0\n ? event.sourceSessionKey\n : typeof event.sessionKey === \"string\" && event.sessionKey.length > 0\n ? event.sessionKey\n : undefined;\n const outputMemoryIds = Array.isArray(event.outputMemoryIds)\n ? Array.from(\n new Set(\n event.outputMemoryIds.filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n ),\n ),\n )\n : [];\n\n const reasonParts = [\n event.reason,\n `policy:${policy.decision}`,\n policy.rationale,\n ].filter(\n (part): part is string => typeof part === \"string\" && part.length > 0,\n );\n\n return {\n ...event,\n schemaVersion: event.schemaVersion ?? 1,\n actionId:\n typeof event.actionId === \"string\" && event.actionId.length > 0\n ? event.actionId\n : `memact-${Date.now()}-${Math.random().toString(36).slice(2, 8)}`,\n outcome: normalizedOutcome,\n status:\n event.status ??\n (dryRun && policy.decision === \"allow\" && event.outcome !== \"failed\"\n ? \"validated\"\n : normalizedOutcome === \"applied\"\n ? \"applied\"\n : \"rejected\"),\n actor:\n typeof event.actor === \"string\" && event.actor.length > 0\n ? event.actor\n : \"engram\",\n subsystem:\n typeof event.subsystem === \"string\" && event.subsystem.length > 0\n ? event.subsystem\n : \"memory_action\",\n reason: reasonParts.join(\" | \"),\n namespace,\n sessionKey: sourceSessionKey ?? event.sessionKey,\n sourceSessionKey,\n inputSummary:\n typeof event.inputSummary === \"string\" && event.inputSummary.length > 0\n ? event.inputSummary\n : undefined,\n outputMemoryIds,\n dryRun,\n policyVersion:\n typeof event.policyVersion === \"string\" &&\n event.policyVersion.length > 0\n ? event.policyVersion\n : \"memory-action-policy.v1\",\n timestamp:\n typeof event.timestamp === \"string\" && event.timestamp.length > 0\n ? event.timestamp\n : new Date().toISOString(),\n policyDecision: policy.decision,\n policyRationale: policy.rationale,\n policyEligibility: eligibility,\n };\n }\n\n async appendMemoryActionEvent(\n event: Omit<MemoryActionEvent, \"timestamp\"> & { timestamp?: string },\n ): Promise<boolean> {\n try {\n const toWrite = this.previewMemoryActionEvent(event);\n const storage = await this.getStorage(toWrite.namespace);\n await storage.appendMemoryActionEvents([toWrite]);\n return true;\n } catch (err) {\n log.warn(`appendMemoryActionEvent failed (non-fatal): ${err}`);\n return false;\n }\n }\n\n async getLastGraphRecallSnapshot(\n namespace?: string,\n ): Promise<GraphRecallSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(\n storage.dir,\n \"state\",\n \"last_graph_recall.json\",\n );\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<GraphRecallSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n mode: typeof parsed.mode === \"string\" ? parsed.mode : \"full\",\n queryHash: typeof parsed.queryHash === \"string\" ? parsed.queryHash : \"\",\n queryLength:\n typeof parsed.queryLength === \"number\" ? parsed.queryLength : 0,\n namespaces: Array.isArray(parsed.namespaces)\n ? parsed.namespaces.filter((v): v is string => typeof v === \"string\")\n : [],\n seedCount: typeof parsed.seedCount === \"number\" ? parsed.seedCount : 0,\n expandedCount:\n typeof parsed.expandedCount === \"number\" ? parsed.expandedCount : 0,\n seeds: Array.isArray(parsed.seeds)\n ? parsed.seeds.filter((v): v is string => typeof v === \"string\")\n : [],\n expanded: clampGraphRecallExpandedEntries(parsed.expanded, 64),\n status:\n parsed.status === \"completed\" ||\n parsed.status === \"skipped\" ||\n parsed.status === \"aborted\"\n ? parsed.status\n : undefined,\n reason: typeof parsed.reason === \"string\" ? parsed.reason : undefined,\n shadowMode: parsed.shadowMode === true,\n queryIntent: parseMemoryIntentSnapshot(parsed.queryIntent),\n seedResults: parseGraphRecallRankedResults(parsed.seedResults),\n finalResults: parseGraphRecallRankedResults(parsed.finalResults),\n shadowComparison:\n parsed.shadowComparison && typeof parsed.shadowComparison === \"object\"\n ? {\n baselineCount:\n typeof parsed.shadowComparison.baselineCount === \"number\"\n ? parsed.shadowComparison.baselineCount\n : 0,\n graphCount:\n typeof parsed.shadowComparison.graphCount === \"number\"\n ? parsed.shadowComparison.graphCount\n : 0,\n overlapCount:\n typeof parsed.shadowComparison.overlapCount === \"number\"\n ? parsed.shadowComparison.overlapCount\n : 0,\n overlapRatio:\n typeof parsed.shadowComparison.overlapRatio === \"number\"\n ? parsed.shadowComparison.overlapRatio\n : 0,\n averageOverlapDelta:\n typeof parsed.shadowComparison.averageOverlapDelta ===\n \"number\"\n ? parsed.shadowComparison.averageOverlapDelta\n : 0,\n }\n : undefined,\n };\n } catch {\n return null;\n }\n }\n\n async getLastIntentSnapshot(\n namespace?: string,\n ): Promise<IntentDebugSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(storage.dir, \"state\", \"last_intent.json\");\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<IntentDebugSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n const graphDecision =\n parsed.graphDecision && typeof parsed.graphDecision === \"object\"\n ? parsed.graphDecision\n : undefined;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n promptHash:\n typeof parsed.promptHash === \"string\" ? parsed.promptHash : \"\",\n promptLength:\n typeof parsed.promptLength === \"number\" ? parsed.promptLength : 0,\n retrievalQueryHash:\n typeof parsed.retrievalQueryHash === \"string\"\n ? parsed.retrievalQueryHash\n : \"\",\n retrievalQueryLength:\n typeof parsed.retrievalQueryLength === \"number\"\n ? parsed.retrievalQueryLength\n : 0,\n plannerEnabled: parsed.plannerEnabled !== false,\n plannedMode:\n parsed.plannedMode === \"no_recall\" ||\n parsed.plannedMode === \"minimal\" ||\n parsed.plannedMode === \"full\" ||\n parsed.plannedMode === \"graph_mode\"\n ? parsed.plannedMode\n : \"full\",\n effectiveMode:\n parsed.effectiveMode === \"no_recall\" ||\n parsed.effectiveMode === \"minimal\" ||\n parsed.effectiveMode === \"full\" ||\n parsed.effectiveMode === \"graph_mode\"\n ? parsed.effectiveMode\n : \"full\",\n recallResultLimit:\n typeof parsed.recallResultLimit === \"number\"\n ? parsed.recallResultLimit\n : 0,\n queryIntent: parseMemoryIntentSnapshot(parsed.queryIntent),\n graphExpandedIntentDetected:\n parsed.graphExpandedIntentDetected === true,\n graphDecision: {\n status:\n graphDecision?.status === \"skipped\" ||\n graphDecision?.status === \"completed\" ||\n graphDecision?.status === \"aborted\"\n ? graphDecision.status\n : \"not_requested\",\n reason:\n typeof graphDecision?.reason === \"string\"\n ? graphDecision.reason\n : undefined,\n shadowMode: graphDecision?.shadowMode === true,\n qmdAvailable: graphDecision?.qmdAvailable !== false,\n graphRecallEnabled: graphDecision?.graphRecallEnabled !== false,\n multiGraphMemoryEnabled:\n graphDecision?.multiGraphMemoryEnabled !== false,\n },\n };\n } catch {\n return null;\n }\n }\n\n async getLastQmdRecallSnapshot(\n namespace?: string,\n ): Promise<QmdRecallSnapshot | null> {\n const storage = await this.getStorage(namespace);\n const snapshotPath = path.join(\n storage.dir,\n \"state\",\n \"last_qmd_recall.json\",\n );\n try {\n const raw = await readFile(snapshotPath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<QmdRecallSnapshot>;\n if (!parsed || typeof parsed !== \"object\") return null;\n return {\n recordedAt:\n typeof parsed.recordedAt === \"string\" ? parsed.recordedAt : \"\",\n queryHash: typeof parsed.queryHash === \"string\" ? parsed.queryHash : \"\",\n queryLength:\n typeof parsed.queryLength === \"number\" ? parsed.queryLength : 0,\n collection:\n typeof parsed.collection === \"string\" ? parsed.collection : undefined,\n namespaces: Array.isArray(parsed.namespaces)\n ? parsed.namespaces.filter(\n (value): value is string => typeof value === \"string\",\n )\n : [],\n fetchLimit:\n typeof parsed.fetchLimit === \"number\" ? parsed.fetchLimit : 0,\n primaryResultCount:\n typeof parsed.primaryResultCount === \"number\"\n ? parsed.primaryResultCount\n : 0,\n hybridResultCount:\n typeof parsed.hybridResultCount === \"number\"\n ? parsed.hybridResultCount\n : 0,\n queryAwareSeedCount:\n typeof parsed.queryAwareSeedCount === \"number\"\n ? parsed.queryAwareSeedCount\n : 0,\n resultCount:\n typeof parsed.resultCount === \"number\" ? parsed.resultCount : 0,\n intentHint:\n typeof parsed.intentHint === \"string\" ? parsed.intentHint : undefined,\n explainEnabled: parsed.explainEnabled === true,\n hybridTopUpUsed: parsed.hybridTopUpUsed === true,\n hybridTopUpSkippedReason:\n typeof parsed.hybridTopUpSkippedReason === \"string\"\n ? parsed.hybridTopUpSkippedReason\n : undefined,\n results: parseQmdRecallResults(parsed.results),\n };\n } catch {\n return null;\n }\n }\n\n async explainLastGraphRecall(options?: {\n namespace?: string;\n maxExpanded?: number;\n }): Promise<string> {\n const snapshot = await this.getLastGraphRecallSnapshot(options?.namespace);\n if (!snapshot) return \"No graph-recall snapshot found yet.\";\n const maxExpanded = Math.max(1, Math.min(50, options?.maxExpanded ?? 10));\n const expanded = snapshot.expanded.slice(0, maxExpanded);\n const seedResults = (snapshot.seedResults ?? []).slice(0, maxExpanded);\n const finalResults = (snapshot.finalResults ?? []).slice(0, maxExpanded);\n const queryIntent = snapshot.queryIntent ?? {\n goal: \"unknown\",\n actionType: \"unknown\",\n entityTypes: [],\n };\n return [\n \"## Last Graph Recall\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Mode: ${snapshot.mode}`,\n `Status: ${snapshot.status ?? \"completed\"}${snapshot.shadowMode ? \" (shadow)\" : \"\"}`,\n `Reason: ${snapshot.reason ?? \"n/a\"}`,\n `Query hash: ${snapshot.queryHash || \"unknown\"} (len=${snapshot.queryLength})`,\n `Query intent: goal=${queryIntent.goal}, action=${queryIntent.actionType}, entityTypes=${queryIntent.entityTypes.length > 0 ? queryIntent.entityTypes.join(\", \") : \"none\"}`,\n `Namespaces: ${snapshot.namespaces.length > 0 ? snapshot.namespaces.join(\", \") : \"none\"}`,\n `Seed results (${snapshot.seedResults?.length ?? 0}, showing ${seedResults.length}):`,\n ...seedResults.map(\n (entry) =>\n `- ${entry.path} (score=${entry.score.toFixed(3)}, sources=${entry.sourceLabels.join(\",\") || \"baseline\"})`,\n ),\n `Seed paths (${snapshot.seedCount}):`,\n ...snapshot.seeds.map((p) => `- ${p}`),\n `Expanded paths (${snapshot.expandedCount}, showing ${expanded.length}):`,\n ...expanded.map(\n (e) =>\n `- ${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})`,\n ),\n `Final ranked results (${snapshot.finalResults?.length ?? 0}, showing ${finalResults.length}):`,\n ...finalResults.map(\n (entry) =>\n `- ${entry.path} (score=${entry.score.toFixed(3)}, sources=${entry.sourceLabels.join(\",\") || \"baseline\"})`,\n ),\n ...(snapshot.shadowComparison\n ? [\n `Shadow comparison: baseline=${snapshot.shadowComparison.baselineCount}, graph=${snapshot.shadowComparison.graphCount}, overlap=${snapshot.shadowComparison.overlapCount} (${snapshot.shadowComparison.overlapRatio.toFixed(2)}), avgDelta=${snapshot.shadowComparison.averageOverlapDelta.toFixed(3)}`,\n ]\n : []),\n ].join(\"\\n\");\n }\n\n async explainLastIntent(options?: { namespace?: string }): Promise<string> {\n const snapshot = await this.getLastIntentSnapshot(options?.namespace);\n if (!snapshot) return \"No intent-debug snapshot found yet.\";\n return [\n \"## Last Intent Debug\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Prompt hash: ${snapshot.promptHash || \"unknown\"} (len=${snapshot.promptLength})`,\n `Retrieval query hash: ${snapshot.retrievalQueryHash || \"unknown\"} (len=${snapshot.retrievalQueryLength})`,\n `Planner enabled: ${snapshot.plannerEnabled ? \"yes\" : \"no\"}`,\n `Planned mode: ${snapshot.plannedMode}`,\n `Effective mode: ${snapshot.effectiveMode}`,\n `Recall result limit: ${snapshot.recallResultLimit}`,\n `Query intent: goal=${snapshot.queryIntent.goal}, action=${snapshot.queryIntent.actionType}, entityTypes=${snapshot.queryIntent.entityTypes.length > 0 ? snapshot.queryIntent.entityTypes.join(\", \") : \"none\"}`,\n `Broad graph intent: ${snapshot.graphExpandedIntentDetected ? \"yes\" : \"no\"}`,\n `Graph decision: status=${snapshot.graphDecision.status}, reason=${snapshot.graphDecision.reason ?? \"n/a\"}, shadow=${snapshot.graphDecision.shadowMode ? \"yes\" : \"no\"}, qmdAvailable=${snapshot.graphDecision.qmdAvailable ? \"yes\" : \"no\"}, graphRecallEnabled=${snapshot.graphDecision.graphRecallEnabled ? \"yes\" : \"no\"}, multiGraphMemoryEnabled=${snapshot.graphDecision.multiGraphMemoryEnabled ? \"yes\" : \"no\"}`,\n ].join(\"\\n\");\n }\n\n async explainLastQmdRecall(options?: {\n namespace?: string;\n maxResults?: number;\n }): Promise<string> {\n const snapshot = await this.getLastQmdRecallSnapshot(options?.namespace);\n if (!snapshot) return \"No QMD recall snapshot found yet.\";\n const maxResults = Math.max(1, Math.min(25, options?.maxResults ?? 10));\n const shown = snapshot.results.slice(0, maxResults);\n return [\n \"## Last QMD Recall\",\n \"\",\n `Recorded at: ${snapshot.recordedAt || \"unknown\"}`,\n `Query hash: ${snapshot.queryHash || \"unknown\"} (len=${snapshot.queryLength})`,\n `Collection: ${snapshot.collection ?? \"default\"}`,\n `Namespaces: ${snapshot.namespaces.length > 0 ? snapshot.namespaces.join(\", \") : \"none\"}`,\n `Fetch limit: ${snapshot.fetchLimit}`,\n `Primary results: ${snapshot.primaryResultCount}`,\n `Hybrid top-up results: ${snapshot.hybridResultCount}`,\n `Query-aware seeds: ${snapshot.queryAwareSeedCount}`,\n `Final results: ${snapshot.resultCount}`,\n `Intent hint: ${snapshot.intentHint ?? \"none\"}`,\n `Explain enabled: ${snapshot.explainEnabled ? \"yes\" : \"no\"}`,\n `Hybrid top-up used: ${snapshot.hybridTopUpUsed ? \"yes\" : \"no\"}`,\n `Hybrid top-up skipped reason: ${snapshot.hybridTopUpSkippedReason ?? \"n/a\"}`,\n `Top results (${shown.length}):`,\n ...shown.map((result) => {\n const explainParts = [\n typeof result.explain?.blendedScore === \"number\"\n ? `blended=${result.explain.blendedScore.toFixed(3)}`\n : null,\n typeof result.explain?.rerankScore === \"number\"\n ? `rerank=${result.explain.rerankScore.toFixed(3)}`\n : null,\n typeof result.explain?.rrf === \"number\"\n ? `rrf=${result.explain.rrf.toFixed(3)}`\n : null,\n ].filter((entry): entry is string => Boolean(entry));\n const explainText =\n explainParts.length > 0 ? `, explain=${explainParts.join(\"/\")}` : \"\";\n return `- ${result.path} (score=${result.score.toFixed(3)}, transport=${result.transport ?? \"unknown\"}${explainText})`;\n }),\n ].join(\"\\n\");\n }\n\n private async searchConversationRecallResults(\n retrievalQuery: string,\n topK: number,\n ): Promise<Array<{ path: string; snippet: string; score: number }>> {\n if (this.conversationIndexBackend) {\n return this.conversationIndexBackend.search(retrievalQuery, topK);\n }\n return [];\n }\n\n private formatConversationRecallSection(\n results: Array<{ path: string; snippet: string; score: number }>,\n maxChars: number,\n ): string | null {\n if (!Array.isArray(results) || results.length === 0) return null;\n const lines: string[] = [\"## Semantic Recall (Past Conversations)\", \"\"];\n let used = 0;\n for (const r of results) {\n if (!r?.snippet) continue;\n const chunk =\n `### ${r.path}\\n` +\n `Score: ${r.score.toFixed(3)}\\n\\n` +\n `${r.snippet.trim()}\\n`;\n if (used + chunk.length > maxChars) break;\n lines.push(chunk);\n used += chunk.length;\n }\n return used > 0 ? lines.join(\"\\n\") : null;\n }\n\n private async countConversationChunkDocs(dir: string): Promise<number> {\n try {\n const entries = await readdir(dir, { withFileTypes: true });\n let total = 0;\n for (const entry of entries) {\n const fullPath = path.join(dir, entry.name);\n if (entry.isDirectory()) {\n total += await this.countConversationChunkDocs(fullPath);\n continue;\n }\n if (entry.isFile() && entry.name.endsWith(\".md\")) {\n total += 1;\n }\n }\n return total;\n } catch {\n return 0;\n }\n }\n\n private async buildConversationIndexChunks(\n sessionKey?: string,\n hours: number = 24,\n ): Promise<ReturnType<typeof chunkTranscriptEntries>> {\n const entries = await this.transcript.readRecent(hours, sessionKey);\n const effectiveSessionKey = sessionKey ?? \"all-sessions\";\n return chunkTranscriptEntries(effectiveSessionKey, entries, {\n maxChars: this.config.conversationRecallMaxChars * 2,\n maxTurns: Math.max(10, this.config.hourlySummariesMaxTurnsPerRun),\n });\n }\n\n async getConversationIndexHealth(): Promise<{\n enabled: boolean;\n backend: \"qmd\" | \"faiss\";\n status: \"ok\" | \"degraded\" | \"disabled\";\n chunkDocCount: number;\n lastUpdateAt: string | null;\n qmdAvailable?: boolean;\n faiss?: {\n ok: boolean;\n status: \"ok\" | \"degraded\" | \"error\";\n indexPath: string;\n message?: string;\n manifest?: {\n version: number;\n modelId: string;\n normalizedModelId: string;\n dimension: number;\n chunkCount: number;\n updatedAt: string;\n lastSuccessfulRebuildAt: string;\n };\n };\n }> {\n const chunkDocCount = await this.countConversationChunkDocs(\n this.conversationIndexDir,\n );\n const lastUpdateAtMs = Math.max(\n 0,\n ...this.conversationIndexLastUpdateAtMs.values(),\n );\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!this.config.conversationIndexEnabled) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n chunkDocCount,\n lastUpdateAt,\n };\n }\n const backendHealth = this.conversationIndexBackend\n ? await this.conversationIndexBackend.health()\n : {\n backend: this.config.conversationIndexBackend,\n status: \"degraded\" as const,\n };\n return {\n enabled: true,\n chunkDocCount,\n lastUpdateAt,\n ...backendHealth,\n };\n }\n\n async inspectConversationIndex(): Promise<\n ConversationIndexBackendInspection & {\n enabled: boolean;\n chunkDocCount: number;\n lastUpdateAt: string | null;\n }\n > {\n const chunkDocCount = await this.countConversationChunkDocs(\n this.conversationIndexDir,\n );\n const lastUpdateAtMs = Math.max(\n 0,\n ...this.conversationIndexLastUpdateAtMs.values(),\n );\n const lastUpdateAt =\n lastUpdateAtMs > 0 ? new Date(lastUpdateAtMs).toISOString() : null;\n\n if (!this.config.conversationIndexEnabled) {\n return {\n enabled: false,\n backend: this.config.conversationIndexBackend,\n status: \"disabled\",\n available: false,\n indexPath: this.conversationIndexDir,\n supportsIncrementalUpdate: true,\n message: \"Conversation index disabled by config\",\n metadata: {\n chunkCount: chunkDocCount,\n },\n chunkDocCount,\n lastUpdateAt,\n };\n }\n\n const inspection = this.conversationIndexBackend\n ? await this.conversationIndexBackend.inspect()\n : {\n backend: this.config.conversationIndexBackend,\n status: \"degraded\" as const,\n available: false,\n indexPath: this.conversationIndexDir,\n supportsIncrementalUpdate: true,\n message: \"Conversation index backend unavailable\",\n metadata: {\n chunkCount: chunkDocCount,\n },\n };\n\n return {\n enabled: true,\n chunkDocCount,\n lastUpdateAt,\n ...inspection,\n };\n }\n\n async getRecoverySummary(sessionKey?: string): Promise<{\n generatedAt: string;\n sessionKey?: string;\n healthy: boolean;\n issueCount: number;\n incompleteTurns: number;\n brokenChains: number;\n checkpointHealthy: boolean;\n }> {\n return this.transcript.getRecoverySummary(sessionKey);\n }\n\n async updateConversationIndex(\n sessionKey: string,\n hours: number = 24,\n opts?: { embed?: boolean; enforceMinInterval?: boolean },\n ): Promise<{\n chunks: number;\n skipped: boolean;\n reason?: string;\n retryAfterMs?: number;\n embedded?: boolean;\n }> {\n if (!this.config.conversationIndexEnabled) {\n return { chunks: 0, skipped: true, reason: \"disabled\", embedded: false };\n }\n const enforceMinInterval = opts?.enforceMinInterval !== false;\n if (enforceMinInterval) {\n const minIntervalMs = Math.max(\n 0,\n this.config.conversationIndexMinUpdateIntervalMs,\n );\n const now = Date.now();\n const last = this.conversationIndexLastUpdateAtMs.get(sessionKey) ?? 0;\n const elapsed = now - last;\n if (minIntervalMs > 0 && elapsed < minIntervalMs) {\n return {\n chunks: 0,\n skipped: true,\n reason: \"min_interval\",\n retryAfterMs: minIntervalMs - elapsed,\n embedded: false,\n };\n }\n }\n const chunks = await this.buildConversationIndexChunks(sessionKey, hours);\n await writeConversationChunks(this.conversationIndexDir, chunks);\n await cleanupConversationChunks(\n this.conversationIndexDir,\n this.config.conversationIndexRetentionDays,\n );\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n\n if (this.conversationIndexBackend) {\n const result = await this.conversationIndexBackend.update(chunks, {\n embed: shouldEmbed,\n });\n embedded = result.embedded;\n }\n\n this.conversationIndexLastUpdateAtMs.set(sessionKey, Date.now());\n return { chunks: chunks.length, skipped: false, embedded };\n }\n\n async rebuildConversationIndex(\n sessionKey?: string,\n hours: number = 24,\n opts?: { embed?: boolean },\n ): Promise<{\n chunks: number;\n skipped: boolean;\n reason?: string;\n embedded?: boolean;\n rebuilt?: boolean;\n }> {\n if (!this.config.conversationIndexEnabled) {\n return {\n chunks: 0,\n skipped: true,\n reason: \"disabled\",\n embedded: false,\n rebuilt: false,\n };\n }\n\n const chunks = await this.buildConversationIndexChunks(sessionKey, hours);\n await writeConversationChunks(this.conversationIndexDir, chunks);\n await cleanupConversationChunks(\n this.conversationIndexDir,\n this.config.conversationIndexRetentionDays,\n );\n\n const shouldEmbed =\n opts?.embed ?? this.config.conversationIndexEmbedOnUpdate;\n let embedded = false;\n let rebuilt = false;\n if (this.conversationIndexBackend) {\n const result = await this.conversationIndexBackend.rebuild(chunks, {\n embed: shouldEmbed,\n });\n embedded = result.embedded;\n rebuilt = result.rebuilt;\n }\n\n const stamp = Date.now();\n if (sessionKey) {\n this.conversationIndexLastUpdateAtMs.set(sessionKey, stamp);\n } else {\n this.conversationIndexLastUpdateAtMs.set(\"__rebuild__\", stamp);\n }\n return { chunks: chunks.length, skipped: false, embedded, rebuilt };\n }\n\n /**\n * Validate local LLM model availability and context window compatibility.\n * Warns the user if there's a mismatch.\n */\n private async validateLocalLlmModel(): Promise<void> {\n log.debug(\"Local LLM: validating model configuration\");\n try {\n const modelInfo = await this.localLlm.getLoadedModelInfo();\n if (!modelInfo) {\n log.warn(\n \"Local LLM validation: Could not query model info from server\",\n );\n log.warn(\n \"Local LLM validation: Could not query model info. \" +\n \"Ensure LM Studio/Ollama is running with the model loaded.\",\n );\n return;\n }\n\n // Check for context window mismatch\n const configuredMaxContext = this.config.localLlmMaxContext;\n\n if (modelInfo.contextWindow) {\n log.debug(\n `Local LLM: ${modelInfo.id} loaded with ${modelInfo.contextWindow.toLocaleString()} token context window`,\n );\n\n if (\n configuredMaxContext &&\n configuredMaxContext > modelInfo.contextWindow\n ) {\n log.warn(\n `Local LLM context mismatch: engram configured for ${configuredMaxContext.toLocaleString()} tokens, ` +\n `but ${modelInfo.id} only supports ${modelInfo.contextWindow.toLocaleString()}. ` +\n `Reducing to ${modelInfo.contextWindow.toLocaleString()} to avoid errors.`,\n );\n // Update the config in-memory to match actual capability\n // (This is a temporary fix - user should update their config)\n (this.config as { localLlmMaxContext?: number }).localLlmMaxContext =\n modelInfo.contextWindow;\n }\n } else {\n log.debug(\n `Local LLM: ${modelInfo.id} loaded (context window not reported by server)`,\n );\n\n if (!configuredMaxContext) {\n log.warn(\n \"Local LLM: Server did not report context window. \" +\n \"If you get 'context length exceeded' errors, set localLlmMaxContext in your config. \" +\n \"Common defaults: LM Studio (32K), Ollama (2K-128K depending on model).\",\n );\n }\n }\n } catch (err) {\n log.warn(`Local LLM validation failed: ${err}`);\n }\n }\n\n async recall(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n ): Promise<string> {\n const abortController = new AbortController();\n const onAbort = () => {\n abortController.abort();\n };\n if (options.abortSignal?.aborted) {\n abortController.abort();\n } else {\n options.abortSignal?.addEventListener(\"abort\", onAbort, { once: true });\n }\n\n // Wait for initialization to complete before attempting recall.\n // Timeout after 15s in case initialize() never fires (edge case).\n let initGateTimeoutHandle: NodeJS.Timeout | null = null;\n let onInitGateAbort: (() => void) | null = null;\n if (this.initPromise) {\n const INIT_GATE_TIMEOUT_MS = 15_000;\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 INIT_GATE_TIMEOUT_MS,\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 // Keep outer recall timeout above worst-case serialized hybrid search:\n // QMD subprocess BM25 (30s) + vector (30s) can consume ~60s under contention.\n try {\n const recallPromise = this.recallInternal(prompt, sessionKey, {\n ...options,\n abortSignal: abortController.signal,\n });\n const RECALL_TIMEOUT_MS = this.config.recallOuterTimeoutMs ?? 75_000;\n if (RECALL_TIMEOUT_MS <= 0) {\n return await recallPromise;\n }\n\n let timeoutHandle: NodeJS.Timeout | null = null;\n const timeoutPromise = new Promise<string>((_, reject) => {\n timeoutHandle = setTimeout(() => {\n abortController.abort();\n reject(new Error(\"recall timeout\"));\n }, RECALL_TIMEOUT_MS);\n });\n\n let recallResult: string;\n try {\n recallResult = await Promise.race([recallPromise, timeoutPromise]);\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n\n // Observation-mode direct-answer tier (issue #518 slice 3c).\n // Runs after the user's recall already succeeded, fire-and-forget,\n // so annotation latency can never delay the caller's response.\n if (this.config.recallDirectAnswerEnabled && sessionKey) {\n try {\n this.enqueueDirectAnswerObservation(\n prompt,\n sessionKey,\n options.namespace?.trim() || undefined,\n );\n } catch (err) {\n log.debug(`direct-answer observation setup failed: ${err}`);\n }\n }\n\n return recallResult;\n } catch (err) {\n this.logRecallFailure(err);\n // endTrace() is safe here: if no trace is active (disabled or already\n // closed by recallInternal's try/finally), it returns null immediately.\n this.profiler.endTrace();\n return \"\"; // Return empty context on timeout/error\n } finally {\n options.abortSignal?.removeEventListener(\"abort\", onAbort);\n }\n }\n\n /**\n * Return the most recent X-ray snapshot captured during a\n * `recall()` call that passed `xrayCapture: true` (issue #570 PR 1).\n * Returns `null` when no such capture has occurred on this\n * orchestrator instance. Returned snapshot is a deep copy so\n * caller mutation cannot tear the stored value.\n */\n getLastXraySnapshot(): RecallXraySnapshot | null {\n if (!this.lastXraySnapshot) return null;\n return structuredClone(this.lastXraySnapshot);\n }\n\n /** Clear the captured X-ray snapshot. Exposed for tests / explicit reset. */\n clearLastXraySnapshot(): void {\n this.lastXraySnapshot = null;\n }\n\n /**\n * Await the in-flight observation-mode direct-answer annotation chain.\n * Resolves to true when settled, false on timeout.\n */\n async waitForDirectAnswerObservationIdle(\n timeoutMs: number = 60_000,\n ): Promise<boolean> {\n let timeoutHandle: NodeJS.Timeout | null = null;\n try {\n const timeoutPromise = new Promise<\"timeout\">((resolve) => {\n timeoutHandle = setTimeout(() => resolve(\"timeout\"), timeoutMs);\n });\n const result = await Promise.race([\n this.directAnswerObservationChain.then(() => \"ok\" as const),\n timeoutPromise,\n ]);\n if (result === \"timeout\") {\n log.warn(\n `waitForDirectAnswerObservationIdle timed out after ${timeoutMs}ms`,\n );\n return false;\n }\n return true;\n } finally {\n if (timeoutHandle) clearTimeout(timeoutHandle);\n }\n }\n\n private enqueueDirectAnswerObservation(\n prompt: string,\n sessionKey: string,\n namespaceOverride: string | undefined,\n ): void {\n const expectedSnapshot = this.lastRecall.get(sessionKey);\n if (expectedSnapshot === null) return;\n if (expectedSnapshot.plannerMode === \"no_recall\") return;\n\n const principal = resolvePrincipal(sessionKey, this.config);\n // Coding-agent overlay (issue #569) is applied when the session has a\n // coding context and there is no explicit namespaceOverride — mirrors\n // the main recall path above.\n const observationCodingOverlay =\n namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)\n ? null\n : this.applyCodingRecallOverlay(sessionKey);\n const observationPrincipalSelf = defaultNamespaceForPrincipal(principal, this.config);\n const observationCodingSelf = observationCodingOverlay\n ? combineNamespaces(observationPrincipalSelf, observationCodingOverlay.namespace)\n : null;\n let observationNamespaces: string[];\n if (namespaceOverride && canReadNamespace(principal, namespaceOverride, this.config)) {\n observationNamespaces = [namespaceOverride];\n } else if (observationCodingOverlay && observationCodingSelf) {\n // Rule 42 / parity with the main recall path: substitute the self\n // namespace within the principal's recall list rather than\n // replacing the full list. Preserves shared and policy-include\n // namespaces for direct-answer observation queries.\n const base = recallNamespacesForPrincipal(principal, this.config);\n const mapped = base.map((ns) =>\n ns === observationPrincipalSelf ? observationCodingSelf : ns,\n );\n const fallbackNs = observationCodingOverlay.readFallbacks.map((fallback) =>\n combineNamespaces(observationPrincipalSelf, fallback),\n );\n observationNamespaces = Array.from(new Set<string>([...mapped, ...fallbackNs]));\n } else {\n observationNamespaces = recallNamespacesForPrincipal(principal, this.config);\n }\n const observationQueryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,\n cronRecallNormalizedQueryMaxChars:\n this.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.config.cronConversationRecallMode,\n });\n const observationQuery = observationQueryPolicy.retrievalQuery || prompt;\n const expectedIdentity = {\n writeNonce: expectedSnapshot.writeNonce,\n traceId: expectedSnapshot.traceId,\n recordedAt: expectedSnapshot.recordedAt,\n };\n const previous = this.directAnswerObservationChain;\n this.directAnswerObservationChain = previous\n .catch(() => undefined)\n .then(async () => {\n try {\n await this.annotateDirectAnswerTier(\n observationQuery,\n sessionKey,\n observationNamespaces,\n expectedIdentity,\n undefined,\n );\n } catch (err) {\n log.debug(`direct-answer observation chain error: ${err}`);\n }\n });\n }\n\n private async annotateDirectAnswerTier(\n prompt: string,\n sessionKey: string,\n namespaces: string[],\n expectedIdentity:\n | { writeNonce?: string; traceId?: string; recordedAt?: string }\n | undefined,\n _parentAbortSignal?: AbortSignal,\n ): Promise<void> {\n const tierStart = Date.now();\n try {\n if (namespaces.length === 0) return;\n\n const trustZoneByNsAndRecordId = new Map<\n string,\n \"quarantine\" | \"working\" | \"trusted\"\n >();\n const trustZoneKey = (ns: string, recordId: string) =>\n `${ns}\\u0000${recordId}`;\n const scopedStorages = new Map<\n string,\n Awaited<ReturnType<typeof this.storageRouter.storageFor>>\n >();\n\n for (const ns of namespaces) {\n const storage = await this.storageRouter.storageFor(ns);\n scopedStorages.set(ns, storage);\n const trustZones = await listTrustZoneRecords({\n memoryDir: storage.dir,\n trustZoneStoreDir: this.config.trustZoneStoreDir,\n limit: 200,\n }).catch(() => ({\n allRecords: [] as Array<{\n recordId: string;\n zone: \"quarantine\" | \"working\" | \"trusted\";\n }>,\n }));\n for (const record of trustZones.allRecords ?? []) {\n trustZoneByNsAndRecordId.set(\n trustZoneKey(ns, record.recordId),\n record.zone,\n );\n }\n }\n\n const memoryNamespaceByPath = new Map<string, string>();\n const memoryNamespaceById = new Map<string, string>();\n let candidatesConsidered = 0;\n\n const sources: DirectAnswerSources = {\n taxonomy: DEFAULT_TAXONOMY,\n listCandidateMemories: async (options: { namespace: string; abortSignal?: AbortSignal }) => {\n const targetNs = options.namespace;\n const storage =\n scopedStorages.get(targetNs) ??\n (await this.storageRouter.storageFor(targetNs));\n const all = await storage.readAllMemories();\n const active: MemoryFile[] = [];\n for (const m of all) {\n if ((m.frontmatter.status ?? \"active\") === \"active\") {\n active.push(m);\n memoryNamespaceByPath.set(m.path, targetNs);\n if (m.frontmatter.id) {\n memoryNamespaceById.set(m.frontmatter.id, targetNs);\n }\n }\n }\n candidatesConsidered += active.length;\n return active;\n },\n trustZoneFor: async (memoryId: string) => {\n const ns = memoryNamespaceById.get(memoryId);\n if (!ns) return null;\n return (\n trustZoneByNsAndRecordId.get(\n trustZoneKey(ns, memoryId),\n ) ?? null\n );\n },\n importanceFor: (memory) =>\n typeof memory.frontmatter.importance?.score === \"number\"\n ? memory.frontmatter.importance.score\n : 0,\n };\n\n let result: import(\"./direct-answer.js\").DirectAnswerResult | undefined;\n for (const ns of namespaces) {\n const r = await tryDirectAnswer({\n query: prompt,\n namespace: ns,\n config: this.config,\n sources,\n });\n if (r.eligible && r.winner) {\n result = r;\n break;\n }\n }\n\n if (!result?.eligible || !result?.winner) return;\n\n const explain: RecallTierExplain = {\n tier: \"direct-answer\",\n tierReason: result.narrative,\n filteredBy: result.filteredBy,\n candidatesConsidered,\n latencyMs: Date.now() - tierStart,\n sourceAnchors: [{ path: result.winner.memory.path }],\n };\n\n await this.lastRecall.annotateTierExplain(\n sessionKey,\n explain,\n expectedIdentity,\n );\n } catch (err) {\n if (err instanceof Error && err.name === \"AbortError\") return;\n log.debug(`direct-answer observation failed: ${err}`);\n }\n }\n\n private logRecallFailure(err: unknown): void {\n const now = Date.now();\n const errorMsg = err instanceof Error ? err.message : String(err);\n const LOG_WINDOW_MS = 60_000;\n const idleSinceLastFailureMs = now - this.lastRecallFailureAtMs;\n this.lastRecallFailureAtMs = now;\n if (idleSinceLastFailureMs >= LOG_WINDOW_MS) {\n this.suppressedRecallFailures = 0;\n }\n\n if (now - this.lastRecallFailureLogAtMs >= LOG_WINDOW_MS) {\n const suffix =\n this.suppressedRecallFailures > 0\n ? ` (suppressed ${this.suppressedRecallFailures} similar failures in last minute)`\n : \"\";\n log.warn(`recall timed out or failed: ${errorMsg}${suffix}`);\n this.lastRecallFailureLogAtMs = now;\n this.suppressedRecallFailures = 0;\n return;\n }\n\n this.suppressedRecallFailures += 1;\n log.debug(`recall timed out or failed (suppressed): ${errorMsg}`);\n }\n\n private artifactTypeForCategory(\n category: string,\n ):\n | \"decision\"\n | \"constraint\"\n | \"todo\"\n | \"definition\"\n | \"commitment\"\n | \"correction\"\n | \"fact\" {\n if (category === \"decision\") return \"decision\";\n if (category === \"commitment\") return \"commitment\";\n if (category === \"correction\") return \"correction\";\n if (category === \"principle\") return \"constraint\";\n return \"fact\";\n }\n\n private truncateArtifactForRecall(text: string, maxChars = 280): string {\n if (text.length <= maxChars) return text;\n return `${text.slice(0, maxChars - 1)}…`;\n }\n\n private async fetchActiveArtifactsForNamespace(\n namespace: string,\n prompt: string,\n targetCount: number,\n ): Promise<MemoryFile[]> {\n const storage = await this.storageRouter.storageFor(namespace);\n let fetchLimit = computeArtifactCandidateFetchLimit(targetCount);\n const maxFetchLimit = Math.min(800, Math.max(fetchLimit, targetCount * 8));\n const MAX_ATTEMPTS = 4;\n let bestFiltered: MemoryFile[] = [];\n\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {\n const rawResults = await storage.searchArtifacts(prompt, fetchLimit);\n const sourceIds = Array.from(\n new Set(\n rawResults\n .map((a) => a.frontmatter.sourceMemoryId)\n .filter(\n (id): id is string => typeof id === \"string\" && id.length > 0,\n ),\n ),\n );\n const sourceStatus =\n sourceIds.length > 0\n ? await this.resolveArtifactSourceStatuses(storage, sourceIds)\n : new Map<string, \"active\" | \"superseded\" | \"archived\" | \"missing\">();\n\n const filtered: MemoryFile[] = [];\n for (const artifact of rawResults) {\n const sourceId = artifact.frontmatter.sourceMemoryId;\n if (!sourceId) {\n filtered.push(artifact);\n if (filtered.length >= targetCount) break;\n continue;\n }\n const status = sourceStatus.get(sourceId) ?? \"missing\";\n if (status !== \"active\") continue;\n filtered.push(artifact);\n if (filtered.length >= targetCount) break;\n }\n\n if (filtered.length >= targetCount) return filtered.slice(0, targetCount);\n if (filtered.length > bestFiltered.length) {\n bestFiltered = filtered;\n }\n if (rawResults.length === 0) return filtered;\n if (rawResults.length < fetchLimit && filtered.length > 0)\n return filtered;\n if (fetchLimit >= maxFetchLimit) return filtered;\n\n const growth = Math.max(targetCount * 2, 12);\n fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);\n }\n\n return bestFiltered;\n }\n\n private async recallArtifactsAcrossNamespaces(\n prompt: string,\n recallNamespaces: string[],\n targetCount: number,\n ): Promise<MemoryFile[]> {\n if (targetCount <= 0) return [];\n const namespaces = Array.from(new Set(recallNamespaces));\n const filteredByNamespace = await Promise.all(\n namespaces.map((namespace) =>\n this.fetchActiveArtifactsForNamespace(namespace, prompt, targetCount),\n ),\n );\n\n return mergeArtifactRecallCandidates(filteredByNamespace, targetCount);\n }\n\n private scopeQueryAwarePaths(\n paths: Set<string> | null,\n recallNamespaces: string[],\n ): Set<string> | null {\n if (!paths || paths.size === 0) return null;\n const scoped = new Set<string>();\n for (const memoryPath of paths) {\n if (!memoryPath || isArtifactMemoryPath(memoryPath)) continue;\n if (\n this.config.namespacesEnabled &&\n !recallNamespaces.includes(this.namespaceFromPath(memoryPath))\n ) {\n continue;\n }\n scoped.add(memoryPath);\n }\n return scoped.size > 0 ? scoped : null;\n }\n\n private async buildQueryAwarePrefilter(\n prompt: string,\n recallNamespaces: string[],\n ): Promise<QueryAwarePrefilter> {\n if (!this.config.queryAwareIndexingEnabled || !prompt.trim()) {\n return {\n candidatePaths: null,\n temporalFromDate: null,\n matchedTags: [],\n expandedTags: [],\n combination: \"none\",\n filteredToFullSearch: false,\n };\n }\n\n const temporalFromDate = isTemporalQuery(prompt)\n ? recencyWindowFromPrompt(prompt, Date.now())\n : null;\n const [rawTemporal, tagSignals] = await Promise.all([\n temporalFromDate\n ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n resolvePromptTagPrefilterAsync(this.config.memoryDir, prompt).catch(\n () => ({\n matchedTags: extractTagsFromPrompt(prompt),\n expandedTags: extractTagsFromPrompt(prompt),\n paths: null,\n }),\n ),\n ]);\n\n const temporalCandidates = this.scopeQueryAwarePaths(\n rawTemporal,\n recallNamespaces,\n );\n const tagCandidates = this.scopeQueryAwarePaths(\n tagSignals.paths,\n recallNamespaces,\n );\n const maxCandidates = this.config.queryAwareIndexingMaxCandidates;\n\n let candidatePaths: Set<string> | null = null;\n let combination: QueryAwarePrefilter[\"combination\"] = \"none\";\n let filteredToFullSearch = false;\n\n if (temporalCandidates && tagCandidates) {\n const intersection = new Set(\n Array.from(temporalCandidates).filter((memoryPath) =>\n tagCandidates.has(memoryPath),\n ),\n );\n if (intersection.size > 0) {\n candidatePaths = intersection;\n combination = \"intersection\";\n } else {\n candidatePaths = new Set([...temporalCandidates, ...tagCandidates]);\n combination = \"union\";\n }\n } else if (temporalCandidates) {\n candidatePaths = temporalCandidates;\n combination = \"temporal\";\n } else if (tagCandidates) {\n candidatePaths = tagCandidates;\n combination = \"tag\";\n }\n\n if (\n candidatePaths &&\n maxCandidates > 0 &&\n candidatePaths.size > maxCandidates\n ) {\n filteredToFullSearch = true;\n candidatePaths = null;\n }\n\n return {\n candidatePaths,\n temporalFromDate,\n matchedTags: tagSignals.matchedTags,\n expandedTags: tagSignals.expandedTags,\n combination,\n filteredToFullSearch,\n };\n }\n\n private async searchScopedMemoryCandidates(\n candidatePaths: Set<string>,\n query: string,\n limit: number,\n options?: {\n allowArchived?: boolean;\n },\n ): Promise<QmdSearchResult[]> {\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0 || candidatePaths.size === 0) return [];\n\n const tokens = Array.from(new Set(tokenizeRecallQuery(query)));\n const memories = (\n await Promise.all(\n Array.from(candidatePaths).map(async (memoryPath) => {\n const namespace = this.config.namespacesEnabled\n ? this.namespaceFromPath(memoryPath)\n : this.config.defaultNamespace;\n const storage = await this.storageRouter.storageFor(namespace);\n return await storage.readMemoryByPath(memoryPath);\n }),\n )\n ).filter((memory): memory is MemoryFile => memory !== null);\n\n const results: QmdSearchResult[] = [];\n for (const memory of memories) {\n const status = memory.frontmatter.status ?? \"active\";\n if (!options?.allowArchived && status !== \"active\") continue;\n\n const haystack = [\n memory.content,\n memory.frontmatter.category,\n ...(memory.frontmatter.tags ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n let hits = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) hits += 1;\n }\n const score = tokens.length > 0 ? hits / tokens.length : 0.01;\n if (tokens.length > 0 && hits === 0) continue;\n\n results.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n score,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n transport: \"scoped_prefilter\",\n });\n }\n\n return results.sort((a, b) => b.score - a.score).slice(0, cappedLimit);\n }\n\n private async fetchQmdMemoryResultsWithArtifactTopUp(\n prompt: string,\n qmdFetchLimit: number,\n qmdHybridFetchLimit: number,\n options: {\n namespacesEnabled: boolean;\n recallNamespaces: string[];\n resolveNamespace: (path: string) => string;\n collection?: string;\n queryAwarePrefilter?: QueryAwarePrefilter;\n searchOptions?: SearchQueryOptions;\n onDebugSnapshot?: (snapshot: QmdRecallSnapshot) => Promise<void>;\n abortSignal?: AbortSignal;\n },\n ): Promise<QmdSearchResult[]> {\n throwIfRecallAborted(options.abortSignal);\n const queryAwarePrefilter =\n options.queryAwarePrefilter ??\n (await this.buildQueryAwarePrefilter(prompt, options.recallNamespaces));\n const scopedSeedResults = queryAwarePrefilter.candidatePaths?.size\n ? await this.searchScopedMemoryCandidates(\n queryAwarePrefilter.candidatePaths,\n prompt,\n qmdFetchLimit,\n { allowArchived: options.collection !== undefined },\n )\n : [];\n\n let fetchLimit = Math.max(qmdFetchLimit, qmdHybridFetchLimit);\n const maxFetchLimit = Math.min(\n 320,\n Math.max(fetchLimit, qmdFetchLimit * 5),\n );\n const MAX_ATTEMPTS = 2;\n const qmdRecallBudgetMs = this.config.recallEnrichmentDeadlineMs ?? 25_000;\n const qmdRecallBudgetEnabled = qmdRecallBudgetMs > 0;\n const startedAtMs = Date.now();\n let lastPrimaryResultCount = 0;\n let lastHybridResultCount = 0;\n let lastHybridTopUpUsed = false;\n let lastHybridTopUpSkippedReason: string | undefined;\n const backendHonorsQmdSearchSignals =\n (this.config.searchBackend ?? \"qmd\") === \"qmd\";\n const resolvedSearchOptions = (() => {\n const resolver = (\n this.qmd as {\n resolveSupportedSearchOptions?: (\n options?: SearchQueryOptions,\n ) => SearchQueryOptions | undefined;\n }\n ).resolveSupportedSearchOptions;\n if (typeof resolver === \"function\") {\n return resolver.call(this.qmd, options.searchOptions);\n }\n return options.searchOptions;\n })();\n const primarySearchOptions = backendHonorsQmdSearchSignals\n ? resolvedSearchOptions\n : options.searchOptions;\n const debugSearchOptions = backendHonorsQmdSearchSignals\n ? resolvedSearchOptions\n : undefined;\n let bestFiltered = filterRecallCandidates(scopedSeedResults, {\n namespacesEnabled: options.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: options.resolveNamespace,\n limit: qmdFetchLimit,\n });\n const emitDebugSnapshot = async (\n results: QmdSearchResult[],\n currentFetchLimit: number,\n ) => {\n if (!options.onDebugSnapshot) return;\n await options.onDebugSnapshot({\n recordedAt: new Date().toISOString(),\n queryHash: createHash(\"sha256\").update(prompt).digest(\"hex\"),\n queryLength: prompt.length,\n collection: options.collection,\n namespaces: options.recallNamespaces,\n fetchLimit: currentFetchLimit,\n primaryResultCount: lastPrimaryResultCount,\n hybridResultCount: lastHybridResultCount,\n queryAwareSeedCount: scopedSeedResults.length,\n resultCount: results.length,\n intentHint: debugSearchOptions?.intent,\n explainEnabled: debugSearchOptions?.explain === true,\n hybridTopUpUsed: lastHybridTopUpUsed,\n hybridTopUpSkippedReason: lastHybridTopUpSkippedReason,\n results: results.slice(0, 32).map((result) => ({\n ...result,\n snippet: result.snippet.slice(0, 280),\n })),\n });\n };\n\n for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt += 1) {\n throwIfRecallAborted(options.abortSignal);\n if (\n qmdRecallBudgetEnabled &&\n Date.now() - startedAtMs >= qmdRecallBudgetMs\n ) {\n break;\n }\n\n const primaryResults = options.collection\n ? options.abortSignal\n ? await this.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n {\n signal: options.abortSignal,\n },\n )\n : await this.qmd.search(\n prompt,\n options.collection,\n fetchLimit,\n primarySearchOptions,\n )\n : await this.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"search\",\n searchOptions: primarySearchOptions,\n execution: { signal: options.abortSignal },\n });\n lastPrimaryResultCount = primaryResults.length;\n lastHybridResultCount = 0;\n lastHybridTopUpUsed = false;\n lastHybridTopUpSkippedReason = undefined;\n let mergedResults = primaryResults;\n\n // Backfill with hybrid results only when primary retrieval underfills.\n if (\n primaryResults.length < qmdFetchLimit &&\n (!qmdRecallBudgetEnabled ||\n Date.now() - startedAtMs < qmdRecallBudgetMs)\n ) {\n if (debugSearchOptions?.intent) {\n lastHybridTopUpSkippedReason = \"intent_hint_active\";\n } else {\n const hybridResults = options.collection\n ? await this.qmd.hybridSearch(\n prompt,\n options.collection,\n fetchLimit,\n {\n signal: options.abortSignal,\n },\n )\n : await this.searchAcrossNamespaces({\n query: prompt,\n namespaces: options.namespacesEnabled\n ? options.recallNamespaces\n : undefined,\n maxResults: fetchLimit,\n mode: \"hybrid\",\n execution: { signal: options.abortSignal },\n });\n lastHybridResultCount = hybridResults.length;\n lastHybridTopUpUsed = hybridResults.length > 0;\n if (hybridResults.length > 0) {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...primaryResults, ...hybridResults]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n transport: result.transport ?? \"hybrid\",\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n mergedResults = [...mergedByPath.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, fetchLimit);\n }\n }\n }\n\n if (scopedSeedResults.length > 0) {\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...scopedSeedResults, ...mergedResults]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n mergedResults = [...mergedByPath.values()]\n .sort((a, b) => b.score - a.score)\n .slice(0, fetchLimit);\n }\n\n const filteredResults = filterRecallCandidates(mergedResults, {\n namespacesEnabled: options.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: options.resolveNamespace,\n limit: fetchLimit,\n });\n\n if (filteredResults.length >= qmdFetchLimit) {\n const capped = filteredResults.slice(0, qmdFetchLimit);\n await emitDebugSnapshot(capped, fetchLimit);\n return capped;\n }\n if (filteredResults.length > bestFiltered.length) {\n bestFiltered = filteredResults;\n }\n if (mergedResults.length === 0) {\n await emitDebugSnapshot(filteredResults, fetchLimit);\n return filteredResults;\n }\n if (mergedResults.length < fetchLimit && filteredResults.length > 0) {\n await emitDebugSnapshot(filteredResults, fetchLimit);\n return filteredResults;\n }\n if (fetchLimit >= maxFetchLimit) {\n break;\n }\n\n const growth = Math.max(20, Math.floor(fetchLimit / 2));\n fetchLimit = Math.min(maxFetchLimit, fetchLimit + growth);\n }\n\n const capped = bestFiltered.slice(0, qmdFetchLimit);\n await emitDebugSnapshot(capped, fetchLimit);\n return capped;\n }\n\n private async expandResultsViaGraph(options: {\n memoryResults: QmdSearchResult[];\n recallNamespaces: string[];\n recallResultLimit: number;\n }): Promise<{\n merged: QmdSearchResult[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n seedResults: QmdSearchResult[];\n }> {\n const byNamespace = new Map<string, QmdSearchResult[]>();\n for (const result of options.memoryResults) {\n const ns = this.namespaceFromPath(result.path);\n if (!options.recallNamespaces.includes(ns)) continue;\n const existing = byNamespace.get(ns);\n if (existing) {\n existing.push(result);\n } else {\n byNamespace.set(ns, [result]);\n }\n }\n\n const perNamespaceSeedCap = Math.max(3, options.recallResultLimit);\n const perNamespaceExpandedCap = Math.max(8, options.recallResultLimit * 2);\n const seedPaths: string[] = [];\n const seedResults: QmdSearchResult[] = [];\n const expandedPaths: GraphRecallExpandedEntry[] = [];\n const expandedResults: QmdSearchResult[] = [];\n\n for (const [namespace, nsResults] of byNamespace.entries()) {\n const storage = await this.storageRouter.storageFor(namespace);\n const seedCandidates = nsResults.slice(0, perNamespaceSeedCap);\n seedResults.push(...seedCandidates);\n const seedRelativePaths = seedCandidates\n .map((result) => graphPathRelativeToStorage(storage.dir, result.path))\n .filter(\n (value): value is string =>\n typeof value === \"string\" && value.length > 0,\n );\n if (seedRelativePaths.length === 0) continue;\n\n const seedRecallScore = seedCandidates.reduce(\n (max, item) => Math.max(max, item.score),\n 0,\n );\n seedPaths.push(\n ...seedRelativePaths.map((rel) => path.join(storage.dir, rel)),\n );\n const seedSet = new Set(seedRelativePaths);\n const expanded = await this.graphIndexFor(storage).spreadingActivation(\n seedRelativePaths,\n this.config.maxGraphTraversalSteps,\n );\n if (expanded.length === 0) continue;\n\n for (const candidate of expanded.slice(0, perNamespaceExpandedCap)) {\n if (seedSet.has(candidate.path)) continue;\n const memoryPath = path.resolve(storage.dir, candidate.path);\n const memory = await storage.readMemoryByPath(memoryPath);\n if (!memory) continue;\n if (isArtifactMemoryPath(memory.path)) continue;\n if (memory.frontmatter.status && memory.frontmatter.status !== \"active\")\n continue;\n\n const snippet = memory.content.slice(0, 400);\n const score = blendGraphExpandedRecallScore({\n graphActivationScore: candidate.score,\n seedRecallScore,\n activationWeight: this.config.graphExpansionActivationWeight,\n blendMin: this.config.graphExpansionBlendMin,\n blendMax: this.config.graphExpansionBlendMax,\n });\n expandedResults.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n snippet,\n score,\n });\n expandedPaths.push({\n path: memory.path,\n score,\n namespace,\n seed: path.resolve(storage.dir, candidate.seed),\n hopDepth: candidate.hopDepth,\n decayedWeight: candidate.decayedWeight,\n graphType: candidate.graphType,\n });\n }\n }\n\n return {\n merged: mergeGraphExpandedResults(options.memoryResults, expandedResults),\n seedPaths,\n expandedPaths,\n seedResults,\n };\n }\n\n private async recordLastGraphRecallSnapshot(options: {\n storage: StorageManager;\n prompt: string;\n recallMode: RecallPlanMode;\n recallNamespaces: string[];\n seedPaths: string[];\n expandedPaths: GraphRecallExpandedEntry[];\n status: \"completed\" | \"skipped\" | \"aborted\";\n reason?: string;\n shadowMode?: boolean;\n queryIntent: MemoryIntent;\n seedResults?: GraphRecallRankedResult[];\n finalResults?: GraphRecallRankedResult[];\n shadowComparison?: GraphRecallShadowComparison;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_graph_recall.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n const now = new Date().toISOString();\n const totalSeedCount = options.seedPaths.length;\n const totalExpandedCount = options.expandedPaths.length;\n const seeds = options.seedPaths.slice(0, 64);\n const expanded = clampGraphRecallExpandedEntries(\n options.expandedPaths,\n 64,\n );\n const payload = {\n recordedAt: now,\n mode: options.recallMode,\n queryHash: createHash(\"sha256\").update(options.prompt).digest(\"hex\"),\n queryLength: options.prompt.length,\n namespaces: options.recallNamespaces,\n seedCount: totalSeedCount,\n expandedCount: totalExpandedCount,\n seeds,\n expanded,\n status: options.status,\n reason: options.reason,\n shadowMode: options.shadowMode === true,\n queryIntent: options.queryIntent,\n seedResults: (options.seedResults ?? []).slice(0, 64),\n finalResults: (options.finalResults ?? []).slice(0, 64),\n shadowComparison: options.shadowComparison,\n };\n await writeFile(snapshotPath, JSON.stringify(payload, null, 2), \"utf-8\");\n } catch (err) {\n log.debug(`last graph recall write failed: ${err}`);\n }\n }\n\n private async recordLastIntentSnapshot(options: {\n storage: StorageManager;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_intent.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last intent write failed: ${err}`);\n }\n }\n\n private async recordLastQmdRecallSnapshot(options: {\n storage: StorageManager;\n snapshot: QmdRecallSnapshot;\n }): Promise<void> {\n try {\n const snapshotPath = path.join(\n options.storage.dir,\n \"state\",\n \"last_qmd_recall.json\",\n );\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last qmd recall write failed: ${err}`);\n }\n }\n\n private async recordLastIntentSnapshotForNamespace(options: {\n namespace: string;\n snapshot: IntentDebugSnapshot;\n }): Promise<void> {\n try {\n const stateDir = await this.resolveStateDirForNamespace(\n options.namespace,\n );\n const snapshotPath = path.join(stateDir, \"last_intent.json\");\n await mkdir(path.dirname(snapshotPath), { recursive: true });\n await writeFile(\n snapshotPath,\n JSON.stringify(options.snapshot, null, 2),\n \"utf-8\",\n );\n } catch (err) {\n log.debug(`last intent write failed: ${err}`);\n }\n }\n\n private async resolveStateDirForNamespace(\n namespace: string,\n ): Promise<string> {\n if (!this.config.namespacesEnabled) {\n return path.join(this.config.memoryDir, \"state\");\n }\n if (namespace !== this.config.defaultNamespace) {\n return path.join(this.config.memoryDir, \"namespaces\", namespace, \"state\");\n }\n const candidate = path.join(\n this.config.memoryDir,\n \"namespaces\",\n this.config.defaultNamespace,\n );\n try {\n const candidateStat = await stat(candidate);\n if (candidateStat.isDirectory()) {\n return path.join(candidate, \"state\");\n }\n } catch {\n // Fall back to the legacy root when the migrated default namespace directory is absent.\n }\n return path.join(this.config.memoryDir, \"state\");\n }\n\n private buildGraphRecallRankedResults(\n results: QmdSearchResult[],\n sourceLabelResolver: (path: string) => string[],\n limit: number = 64,\n ): GraphRecallRankedResult[] {\n return results.slice(0, limit).map((result) => ({\n path: result.path,\n score: result.score,\n docid: result.docid,\n sourceLabels: sourceLabelResolver(result.path),\n }));\n }\n\n private getRecallSectionEntry(\n sectionId: string,\n ): RecallSectionConfig | undefined {\n const pipeline = Array.isArray(this.config.recallPipeline)\n ? this.config.recallPipeline\n : [];\n return pipeline.find((entry) => entry.id === sectionId);\n }\n\n private isRecallSectionEnabled(\n sectionId: string,\n defaultEnabled: boolean = true,\n ): boolean {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return defaultEnabled;\n return entry.enabled !== false;\n }\n\n private getRecallSectionMaxChars(\n sectionId: string,\n ): number | null | undefined {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return undefined;\n if (entry.maxChars === null) return null;\n if (typeof entry.maxChars !== \"number\") return undefined;\n return Math.max(0, Math.floor(entry.maxChars));\n }\n\n private getRecallSectionNumber(\n sectionId: string,\n key: keyof RecallSectionConfig,\n ): number | undefined {\n const entry = this.getRecallSectionEntry(sectionId);\n if (!entry) return undefined;\n const value = entry[key];\n if (typeof value !== \"number\" || !Number.isFinite(value)) return undefined;\n return Math.max(0, Math.floor(value));\n }\n\n private appendRecallSection(\n sectionBuckets: Map<string, string[]>,\n sectionId: string,\n content: string,\n ): void {\n if (!this.isRecallSectionEnabled(sectionId)) return;\n const trimmed = content.trim();\n if (trimmed.length === 0) return;\n\n const maxChars = this.getRecallSectionMaxChars(sectionId);\n let finalContent = trimmed;\n if (maxChars === 0) return;\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 }\n\n private truncateRecallSectionToBudget(\n content: string,\n maxChars: number,\n ): string {\n if (maxChars <= 0) return \"\";\n if (content.length <= maxChars) return content;\n const suffix = \"\\n\\n...(memory context trimmed)\";\n if (maxChars <= suffix.length) {\n return content.slice(0, maxChars);\n }\n return `${content.slice(0, maxChars - suffix.length)}${suffix}`;\n }\n\n private protectedRecallSectionIds(\n sectionBuckets: Map<string, string[]>,\n ): Set<string> {\n const protectedIds = new Set<string>();\n if ((sectionBuckets.get(\"memories\")?.length ?? 0) > 0) {\n protectedIds.add(\"memories\");\n }\n return protectedIds;\n }\n\n private protectedRecallReservationChars(content: string): number {\n const headingBoundary = content.indexOf(\"\\n\\n\");\n const headingChars =\n headingBoundary >= 0 ? headingBoundary + 2 : Math.min(content.length, 24);\n return Math.min(content.length, Math.max(headingChars, 24));\n }\n\n private estimateReservedRecallBudget(\n entries: Array<{ id: string; content: string }>,\n startIndex: number,\n protectedIds: Set<string>,\n alreadyIncludedCount: number,\n ): number {\n const separatorLength = \"\\n\\n---\\n\\n\".length;\n let reserved = 0;\n let simulatedIncluded = alreadyIncludedCount;\n for (let i = startIndex; i < entries.length; i += 1) {\n const entry = entries[i];\n if (!entry || !protectedIds.has(entry.id)) continue;\n if (simulatedIncluded > 0) {\n reserved += separatorLength;\n }\n reserved += this.protectedRecallReservationChars(entry.content);\n simulatedIncluded += 1;\n }\n return reserved;\n }\n\n private getRecallBudgetChars(override?: number): number {\n if (\n typeof override === \"number\" &&\n Number.isFinite(override) &&\n override >= 0\n ) {\n return Math.floor(override);\n }\n const configuredBudget = this.config.recallBudgetChars;\n if (\n typeof configuredBudget === \"number\" &&\n Number.isFinite(configuredBudget) &&\n configuredBudget >= 0\n ) {\n return Math.floor(configuredBudget);\n }\n const tokenBudget = this.config.maxMemoryTokens;\n if (\n typeof tokenBudget === \"number\" &&\n Number.isFinite(tokenBudget) &&\n tokenBudget >= 0\n ) {\n return Math.floor(tokenBudget * 4);\n }\n return 0;\n }\n\n private assembleRecallSections(\n sectionBuckets: Map<string, string[]>,\n budgetOverride?: number,\n ): {\n sections: string[];\n includedIds: string[];\n omittedIds: string[];\n truncated: boolean;\n finalChars: number;\n } {\n const orderedEntries: Array<{ id: string; content: string }> = [];\n const pipeline = Array.isArray(this.config.recallPipeline)\n ? this.config.recallPipeline\n : [];\n const orderedIds = pipeline\n .filter((entry) => entry.enabled !== false)\n .map((entry) => entry.id);\n const seen = new Set<string>();\n\n for (const id of orderedIds) {\n const chunks = sectionBuckets.get(id);\n if (!chunks || chunks.length === 0) continue;\n orderedEntries.push({ id, content: chunks.join(\"\\n\\n\") });\n seen.add(id);\n }\n\n for (const [id, chunks] of sectionBuckets.entries()) {\n if (seen.has(id)) continue;\n if (chunks.length === 0) continue;\n orderedEntries.push({ id, content: chunks.join(\"\\n\\n\") });\n }\n\n const budget = this.getRecallBudgetChars(budgetOverride);\n if (budget === 0) {\n return {\n sections: [],\n includedIds: [],\n omittedIds: orderedEntries.map((entry) => entry.id),\n truncated: orderedEntries.length > 0,\n finalChars: 0,\n };\n }\n\n const separator = \"\\n\\n---\\n\\n\";\n const protectedIds = this.protectedRecallSectionIds(sectionBuckets);\n const sections: string[] = [];\n const includedIds: string[] = [];\n const omittedIds: string[] = [];\n let usedChars = 0;\n let truncated = false;\n\n for (let index = 0; index < orderedEntries.length; index += 1) {\n const entry = orderedEntries[index]!;\n const separatorChars = sections.length > 0 ? separator.length : 0;\n const reserve = protectedIds.has(entry.id)\n ? 0\n : this.estimateReservedRecallBudget(\n orderedEntries,\n index + 1,\n protectedIds,\n sections.length + 1,\n );\n const availableForEntry = budget - usedChars - separatorChars - reserve;\n if (availableForEntry <= 0) {\n omittedIds.push(entry.id);\n truncated = true;\n continue;\n }\n const finalContent = this.truncateRecallSectionToBudget(\n entry.content,\n availableForEntry,\n );\n if (!finalContent) {\n omittedIds.push(entry.id);\n truncated = true;\n continue;\n }\n if (finalContent.length < entry.content.length) {\n truncated = true;\n }\n sections.push(finalContent);\n includedIds.push(entry.id);\n usedChars += separatorChars + finalContent.length;\n }\n\n return {\n sections,\n includedIds,\n omittedIds,\n truncated,\n finalChars: usedChars,\n };\n }\n\n private async recallInternal(\n prompt: string,\n sessionKey?: string,\n options: RecallInvocationOptions = {},\n ): Promise<string> {\n const recallStart = Date.now();\n const timings: Record<string, string> = {};\n const profileTraceId = this.profiler.startTrace(\"recall\", sessionKey, {\n qmdEnabled: this.config.qmdEnabled,\n rerankEnabled: this.config.rerankEnabled,\n parallelRetrieval: this.config.parallelRetrievalEnabled,\n });\n this.profiler.startSpan(\"planning\", profileTraceId);\n let profileTraceClosed = false;\n const closeProfileTrace = () => {\n if (profileTraceClosed) return;\n profileTraceClosed = true;\n this.profiler.endTrace(profileTraceId); // persists to JSONL file\n };\n const recallSectionDeadlineMs = this.config.recallCoreDeadlineMs ?? 75_000;\n const enrichmentSectionDeadlineMs =\n this.config.recallEnrichmentDeadlineMs ?? 25_000;\n // Wrap entire recall body in try/finally so profiling trace is always closed,\n // even on unexpected exceptions (e.g., throwIfRecallAborted, phase-1 errors).\n try {\n type DeferredEnrichmentOutcome<T> =\n | { status: \"resolved\"; value: T }\n | { status: \"rejected\"; error: unknown };\n type ObservedDeferredEnrichmentPromise<T> =\n Promise<DeferredEnrichmentOutcome<T>> & {\n getSettledOutcome: () => DeferredEnrichmentOutcome<T> | undefined;\n cancel: () => void;\n };\n const createEnrichmentAbortHandle = (parentSignal?: AbortSignal) => {\n const controller = new AbortController();\n const onAbort = () => controller.abort();\n if (parentSignal?.aborted) {\n controller.abort();\n } else if (parentSignal) {\n parentSignal.addEventListener(\"abort\", onAbort, { once: true });\n }\n let disposed = false;\n const dispose = () => {\n if (disposed) return;\n disposed = true;\n parentSignal?.removeEventListener(\"abort\", onAbort);\n };\n return {\n signal: controller.signal,\n cancel: () => {\n controller.abort();\n dispose();\n },\n dispose,\n };\n };\n const observeEnrichmentPromise = <T>(\n promise: Promise<T>,\n cancel: () => void = () => {},\n ): ObservedDeferredEnrichmentPromise<T> => {\n let settledOutcome: DeferredEnrichmentOutcome<T> | undefined;\n const observed = promise\n .then<DeferredEnrichmentOutcome<T>, DeferredEnrichmentOutcome<T>>(\n (value) => ({ status: \"resolved\", value }),\n (error) => ({ status: \"rejected\", error }),\n )\n .then((outcome) => {\n settledOutcome = outcome;\n return outcome;\n }) as ObservedDeferredEnrichmentPromise<T>;\n observed.getSettledOutcome = () => settledOutcome;\n observed.cancel = cancel;\n return observed;\n };\n const recordRecallSectionMetric = createRecallSectionMetricRecorder({\n timings,\n logger: log,\n });\n const promptHash = createHash(\"sha256\").update(prompt).digest(\"hex\");\n const traceId = createHash(\"sha256\")\n .update(`${sessionKey ?? \"default\"}:${recallStart}:${promptHash}`)\n .digest(\"hex\")\n .slice(0, 16);\n const sectionBuckets = new Map<string, string[]>();\n const queryPolicy = buildRecallQueryPolicy(prompt, sessionKey, {\n cronRecallPolicyEnabled: this.config.cronRecallPolicyEnabled,\n cronRecallNormalizedQueryMaxChars:\n this.config.cronRecallNormalizedQueryMaxChars,\n cronRecallInstructionHeavyTokenCap:\n this.effectiveCronRecallInstructionHeavyTokenCap(),\n cronConversationRecallMode: this.config.cronConversationRecallMode,\n });\n const retrievalQuery = queryPolicy.retrievalQuery || prompt;\n const retrievalQueryHash = createHash(\"sha256\")\n .update(retrievalQuery)\n .digest(\"hex\");\n const policyVersion = this.currentPolicyVersion();\n let impressionRecorded = false;\n let recallSource:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\" = \"none\";\n let recalledMemoryCount = 0;\n let recalledMemoryIds: string[] = [];\n let recalledMemoryPaths: string[] = [];\n // Per-branch pre-limit candidate pool size for the X-ray filter\n // trace (issue #570 PR 1). `recalledMemoryCount` is assigned\n // AFTER MMR + truncation so using it alone would make the\n // `recall-result-limit` trace report `considered == admitted`\n // even when many candidates were dropped. Each entry captures\n // the pool size BEFORE truncation at that branch. The X-ray\n // capture block picks the pool that corresponds to the branch\n // that actually produced the admitted results (via `recallSource`)\n // so a pool from a branch whose candidates were killed by an\n // earlier gate cannot leak into the `considered` count.\n const xrayBranchPoolSize: Record<\n \"hot_qmd\" | \"hot_embedding\" | \"cold_fallback\" | \"recent_scan\",\n number\n > = {\n hot_qmd: 0,\n hot_embedding: 0,\n cold_fallback: 0,\n recent_scan: 0,\n };\n // Shared out-parameter sink the cold-fallback pipeline writes\n // its pre-truncation pool size into (issue #570 PR 1). Declared\n // once so every call to `applyColdFallbackPipeline` (four call\n // sites) updates the same counter; the X-ray capture block\n // reads this as the cold-fallback pool.\n const xrayColdPoolSink = { size: 0 };\n let identityInjectionModeUsed: IdentityInjectionMode | \"none\" = \"none\";\n let identityInjectedChars = 0;\n let identityInjectionTruncated = false;\n timings.queryPolicy = `${queryPolicy.promptShape}/${queryPolicy.retrievalBudgetMode}${queryPolicy.skipConversationRecall ? \"/skip-conv\" : \"\"}`;\n const recallDecision = resolveRecallModeDecision({\n plannerEnabled: this.config.recallPlannerEnabled,\n graphRecallEnabled: this.config.graphRecallEnabled,\n multiGraphMemoryEnabled: this.config.multiGraphMemoryEnabled,\n graphExpandedIntentEnabled:\n this.config.graphExpandedIntentEnabled === true,\n prompt,\n });\n this.profiler.endSpan(\"planning\", profileTraceId);\n const requestedMode = options.mode;\n const recallMode: RecallPlanMode =\n requestedMode ?? recallDecision.effectiveMode;\n const queryIntent = inferIntentFromText(retrievalQuery);\n const qmdSearchOptions =\n this.buildConfiguredQmdSearchOptions(retrievalQuery);\n timings.recallPlan = recallMode;\n const plannerRecallResultLimit =\n recallMode === \"no_recall\"\n ? 0\n : recallMode === \"minimal\"\n ? Math.max(\n 0,\n Math.min(\n this.config.qmdMaxResults,\n this.config.recallPlannerMaxQmdResultsMinimal,\n ),\n )\n : this.config.qmdMaxResults;\n const policyMinimalLimit = Math.max(\n 0,\n Math.min(\n this.config.qmdMaxResults,\n this.config.recallPlannerMaxQmdResultsMinimal,\n ),\n );\n const baseRecallResultLimit =\n recallMode !== \"no_recall\" &&\n queryPolicy.retrievalBudgetMode === \"minimal\"\n ? Math.min(plannerRecallResultLimit, policyMinimalLimit)\n : plannerRecallResultLimit;\n const memoriesSectionEnabled = this.isRecallSectionEnabled(\"memories\");\n const memorySectionMaxResults = this.getRecallSectionNumber(\n \"memories\",\n \"maxResults\",\n );\n const requestedTopK =\n typeof options.topK === \"number\" && Number.isFinite(options.topK)\n ? Math.max(0, Math.min(200, Math.floor(options.topK)))\n : undefined;\n const recallResultLimit = memoriesSectionEnabled\n ? (() => {\n let limit = baseRecallResultLimit;\n if (memorySectionMaxResults !== undefined) {\n limit = Math.min(limit, memorySectionMaxResults);\n }\n if (requestedTopK !== undefined) {\n limit = Math.min(limit, requestedTopK);\n }\n return limit;\n })()\n : 0;\n const recallHeadroom = this.config.verbatimArtifactsEnabled\n ? Math.max(12, this.config.verbatimArtifactsMaxRecall * 4)\n : 12;\n const computedFetchLimit =\n recallResultLimit === 0\n ? 0\n : Math.max(\n recallResultLimit,\n Math.min(200, recallResultLimit + recallHeadroom),\n );\n const qmdFetchLimit = computedFetchLimit;\n const qmdHybridFetchLimit = computeQmdHybridFetchLimit(\n qmdFetchLimit,\n this.config.verbatimArtifactsEnabled,\n this.config.verbatimArtifactsMaxRecall,\n );\n const embeddingFetchLimit = computedFetchLimit;\n // Principal resolution honours the access-surface override (issue\n // #570 PR 4). Access surfaces that have already authenticated the\n // caller at the transport layer (HTTP / MCP) pass their resolved\n // principal directly so namespace ACL decisions use the same\n // identity the surface authorized, instead of re-running\n // `resolvePrincipal(sessionKey)` which only maps raw session keys\n // through configured rules and otherwise collapses to `\"default\"`.\n const principal =\n typeof options.principalOverride === \"string\"\n && options.principalOverride.length > 0\n ? options.principalOverride\n : resolvePrincipal(sessionKey, this.config);\n const namespaceOverride = options.namespace?.trim() || undefined;\n const readableRecallNamespaces = recallNamespacesForPrincipal(\n principal,\n this.config,\n );\n if (\n namespaceOverride &&\n !canReadNamespace(principal, namespaceOverride, this.config)\n ) {\n throw new Error(\n `namespace override is not readable: ${namespaceOverride}`,\n );\n }\n // Recall path — overlay the coding-agent namespace (issue #569) when\n // the session has a codingContext and `codingMode.projectScope` is true.\n // Explicit `namespace` option still wins, preserving pre-#569 semantics.\n //\n // Rule 42: the overlay substitutes the SELF namespace within the\n // principal's recall list — it does NOT replace the full list. Shared\n // and `includeInRecallByDefault` policy namespaces stay in the recall\n // set so coding sessions continue to see team/shared memories. The\n // overlay is combined with the principal base through `combineNamespaces`\n // to preserve principal isolation (cross-tenant leakage guard).\n const codingOverlay = namespaceOverride ? null : this.applyCodingRecallOverlay(sessionKey);\n const principalSelfNamespace = defaultNamespaceForPrincipal(principal, this.config);\n const codingSelfNamespace = codingOverlay\n ? combineNamespaces(principalSelfNamespace, codingOverlay.namespace)\n : null;\n const selfNamespace =\n namespaceOverride ??\n codingSelfNamespace ??\n principalSelfNamespace;\n let recallNamespaces: string[];\n if (namespaceOverride) {\n recallNamespaces = [namespaceOverride];\n } else if (codingOverlay && codingSelfNamespace) {\n // Substitute the principal's self namespace with the coding-scoped\n // one, and append any read fallbacks (branch→project, PR 3) combined\n // with the principal base so principal isolation is preserved on\n // fallback entries as well.\n const mapped = readableRecallNamespaces.map((ns) =>\n ns === principalSelfNamespace ? codingSelfNamespace : ns,\n );\n const fallbackNs = codingOverlay.readFallbacks.map((fallback) =>\n combineNamespaces(principalSelfNamespace, fallback),\n );\n recallNamespaces = Array.from(new Set<string>([...mapped, ...fallbackNs]));\n } else {\n recallNamespaces = readableRecallNamespaces;\n }\n const qmdAvailable = this.qmd.isAvailable();\n let graphDecisionStatus: IntentDebugSnapshot[\"graphDecision\"][\"status\"] =\n recallDecision.plannedMode === \"graph_mode\" ? \"skipped\" : \"not_requested\";\n let graphDecisionReason = recallDecision.graphReason;\n let graphDecisionShadowMode = false;\n let shouldPersistGraphSnapshot =\n recallDecision.plannedMode === \"graph_mode\";\n let graphSnapshotStatus: GraphRecallSnapshot[\"status\"] | undefined =\n recallDecision.plannedMode === \"graph_mode\" ? \"skipped\" : undefined;\n let graphSnapshotReason = recallDecision.graphReason;\n let graphSnapshotSeedPaths: string[] = [];\n let graphSnapshotExpandedPaths: GraphRecallExpandedEntry[] = [];\n let graphSnapshotSeedResults: GraphRecallRankedResult[] = [];\n let graphSnapshotFinalResults: GraphRecallRankedResult[] = [];\n let graphSnapshotShadowComparison: GraphRecallShadowComparison | undefined;\n const graphBaselinePaths = new Set<string>();\n const graphExpandedResultPaths = new Set<string>();\n const graphSourceLabelsForPath = (resultPath: string): string[] => {\n const labels: string[] = [];\n const normalizedPath = resultPath.split(path.sep).join(\"/\");\n const isEntityPath =\n normalizedPath.startsWith(\"entities/\") ||\n normalizedPath.includes(\"/entities/\");\n if (graphBaselinePaths.has(resultPath)) labels.push(\"baseline\");\n if (graphExpandedResultPaths.has(resultPath))\n labels.push(\"graph_expanded\");\n if (isEntityPath) labels.push(\"reconstructed_entity\");\n return labels.length > 0 ? labels : [\"baseline\"];\n };\n const buildIntentDebugSnapshot = (): IntentDebugSnapshot => ({\n recordedAt: new Date().toISOString(),\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n plannerEnabled: this.config.recallPlannerEnabled,\n plannedMode: requestedMode ?? recallDecision.plannedMode,\n effectiveMode: recallMode,\n recallResultLimit,\n queryIntent,\n graphExpandedIntentDetected: recallDecision.graphExpandedIntentDetected,\n graphDecision: {\n status: graphDecisionStatus,\n reason: graphDecisionReason,\n shadowMode: graphDecisionShadowMode,\n qmdAvailable,\n graphRecallEnabled: this.config.graphRecallEnabled,\n multiGraphMemoryEnabled: this.config.multiGraphMemoryEnabled,\n },\n });\n\n if (recallMode === \"no_recall\") {\n const intentSnapshot = buildIntentDebugSnapshot();\n await this.recordLastIntentSnapshotForNamespace({\n namespace: selfNamespace,\n snapshot: intentSnapshot,\n });\n // Clean up workspace override before early return to prevent Map leaks.\n const earlySessionKey = sessionKey ?? \"default\";\n this._recallWorkspaceOverrides.delete(earlySessionKey);\n timings.total = `${Date.now() - recallStart}ms`;\n // X-ray capture for the `no_recall` early-return path\n // (issue #570 PR 1). `no_recall` skips retrieval entirely, so\n // the snapshot carries zero results and an empty-budget accounting\n // — but we STILL capture it when the caller opts in so\n // `getLastXraySnapshot()` returns a useful debug document rather\n // than silently `null` (or a stale prior capture).\n //\n // Skip capture when the caller has already aborted this recall —\n // otherwise a canceled call could clobber a prior successful\n // capture (issue #570 PR 1 review follow-up).\n if (\n options.xrayCapture === true &&\n !options.abortSignal?.aborted\n ) {\n try {\n this.lastXraySnapshot = buildXraySnapshot({\n query: retrievalQuery,\n tierExplain: null,\n results: [],\n filters: [\n {\n name: \"planner-mode\",\n considered: 0,\n admitted: 0,\n reason: \"no_recall\",\n },\n ],\n budget: {\n chars: this.getRecallBudgetChars(options.budgetCharsOverride),\n used: 0,\n },\n sessionKey,\n namespace: selfNamespace,\n traceId,\n });\n } catch (err) {\n // Capture is a best-effort side channel: a capture failure\n // must NEVER propagate into the primary recall path.\n log.debug(`x-ray capture (no_recall) failed: ${err}`);\n }\n }\n if (sessionKey) {\n this.lastRecall\n .record({\n sessionKey,\n query: retrievalQuery,\n memoryIds: [],\n namespace: selfNamespace,\n traceId,\n plannerMode: recallMode,\n requestedMode,\n source: recallSource,\n fallbackUsed: false,\n sourcesUsed: [],\n budgetsApplied: this.buildLastRecallBudgetSummary({\n requestedTopK,\n recallResultLimit,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n }),\n latencyMs: Date.now() - recallStart,\n resultPaths: [],\n policyVersion,\n appendImpression: this.config.recordEmptyRecallImpressions,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n })\n .catch((err) => log.debug(`last recall record failed: ${err}`));\n }\n if (sessionKey) {\n this.queueEvalShadowRecall({\n traceId,\n recordedAt: new Date().toISOString(),\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n source: recallSource,\n recalledMemoryCount,\n injected: false,\n contextChars: 0,\n memoryIds: [],\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n }\n closeProfileTrace();\n this.emitTrace({\n kind: \"recall_summary\",\n traceId,\n operation: \"recall\",\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n qmdEnabled: this.config.qmdEnabled,\n qmdAvailable: this.qmd.isAvailable(),\n recallNamespaces: [],\n source: recallSource,\n recalledMemoryCount,\n injected: false,\n contextChars: 0,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n return \"\";\n }\n\n const profileStorage = await this.storageRouter.storageFor(selfNamespace);\n\n // --- Phase 1: Launch ALL independent data fetches in parallel ---\n throwIfRecallAborted(options.abortSignal);\n\n // 0. Shared context (v4.0, optional)\n const sharedContextPromise = (async (): Promise<string | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"shared-context\",\n this.config.sharedContextEnabled === true,\n )\n )\n return null;\n if (!this.sharedContext) return null;\n const t0 = Date.now();\n const [priorities, roundtable, crossSignals] = await Promise.all([\n this.sharedContext.readPriorities(),\n this.sharedContext.readLatestRoundtable(),\n this.sharedContext.readLatestCrossSignals(),\n ]);\n const max = Math.max(500, this.config.sharedContextMaxInjectChars);\n const capSection = (\n label: string,\n body: string | null,\n limit: number,\n ): string => {\n const trimmedBody = body?.trim();\n if (!trimmedBody) return \"\";\n const safeLimit = Math.max(120, limit);\n const section = `${label}\\n\\n${trimmedBody}`;\n return section.length > safeLimit\n ? `${section.slice(0, safeLimit)}\\n\\n...(trimmed)\\n`\n : section;\n };\n\n const prioritiesSection = capSection(\n \"### Priorities\",\n priorities,\n Math.floor(max * 0.35),\n );\n const crossSignalsSection = capSection(\n \"### Latest Cross-Signals\",\n crossSignals,\n Math.floor(max * 0.35),\n );\n const fixedSections = [prioritiesSection, crossSignalsSection].filter(\n (section) => section.trim().length > 0,\n );\n const fixedPrefix = [\"## Shared Context\", ...fixedSections].join(\"\\n\\n\");\n const reserved = fixedPrefix.length + \"\\n\\n\".length;\n const roundtableBudget = Math.max(160, max - reserved);\n const roundtableSection = capSection(\n \"### Latest Roundtable\",\n roundtable,\n roundtableBudget,\n );\n const combined = [\n \"## Shared Context\",\n ...fixedSections,\n roundtableSection,\n ]\n .filter((s) => s.trim().length > 0)\n .join(\"\\n\\n\");\n\n const trimmed =\n combined.length > max\n ? combined.slice(0, max) + \"\\n\\n...(trimmed)\\n\"\n : combined;\n recordRecallSectionMetric({\n section: \"sharedCtx\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return trimmed.trim().length > 0 ? trimmed : null;\n })();\n\n // 1. Profile\n const profilePromise = (async (): Promise<string | null> => {\n if (!this.isRecallSectionEnabled(\"profile\")) return null;\n const t0 = Date.now();\n const profile = await profileStorage.readProfile();\n recordRecallSectionMetric({\n section: \"profile\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return profile || null;\n })();\n\n // 1a. Identity continuity signals (v8.4)\n const identityContinuityPromise = (async () => {\n if (\n !this.isRecallSectionEnabled(\n \"identity-continuity\",\n this.config.identityContinuityEnabled === true,\n )\n )\n return null;\n const t0 = Date.now();\n const section = await this.buildIdentityContinuitySection({\n storage: profileStorage,\n recallMode,\n prompt: retrievalQuery,\n });\n recordRecallSectionMetric({\n section: \"identityContinuity\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const entityRetrievalPromise = (async (): Promise<string | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"entity-retrieval\",\n this.config.entityRetrievalEnabled,\n )\n )\n return null;\n if (!this.config.entityRetrievalEnabled) return null;\n const maxChars =\n this.getRecallSectionMaxChars(\"entity-retrieval\") ??\n this.config.entityRetrievalMaxChars;\n const maxHints =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxHints\") ??\n this.config.entityRetrievalMaxHints;\n const maxSupportingFacts =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxSupportingFacts\") ??\n this.config.entityRetrievalMaxSupportingFacts;\n const maxRelatedEntities =\n this.getRecallSectionNumber(\"entity-retrieval\", \"maxRelatedEntities\") ??\n this.config.entityRetrievalMaxRelatedEntities;\n const recentTurns =\n this.getRecallSectionNumber(\"entity-retrieval\", \"recentTurns\") ??\n this.config.entityRetrievalRecentTurns;\n if (maxChars === 0 || maxHints === 0 || maxSupportingFacts === 0) {\n recordRecallSectionMetric({\n section: \"entityRetrieval\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n const t0 = Date.now();\n const transcriptEntries = sessionKey\n ? await readRecentEntityTranscriptEntries(\n this.transcript.readRecent(\n entityRecentTranscriptLookbackHours,\n sessionKey,\n ),\n recentTurns,\n )\n : [];\n const section = await buildEntityRecallSection({\n config: this.config,\n storage: profileStorage,\n query: retrievalQuery,\n recallNamespaces,\n recentTurns,\n maxHints,\n maxSupportingFacts,\n maxRelatedEntities,\n maxChars,\n transcriptEntries,\n }).catch((err) => {\n log.warn(`entity retrieval build failed: ${err}`);\n return null;\n });\n recordRecallSectionMetric({\n section: \"entityRetrieval\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n // 1b. Knowledge Index (v7.0)\n const knowledgeIndexPromise = (async (): Promise<{\n result: string;\n cached: boolean;\n } | null> => {\n if (\n !this.isRecallSectionEnabled(\n \"knowledge-index\",\n this.config.knowledgeIndexEnabled,\n )\n )\n return null;\n if (!this.config.knowledgeIndexEnabled) return null;\n const t0 = Date.now();\n try {\n const ki = await this.storage.buildKnowledgeIndex(this.config, {\n maxEntities: this.getRecallSectionNumber(\n \"knowledge-index\",\n \"maxEntities\",\n ),\n maxChars: this.getRecallSectionNumber(\"knowledge-index\", \"maxChars\"),\n });\n recordRecallSectionMetric({\n section: \"ki\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: ki.cached ? \"stale\" : \"fresh\",\n success: true,\n timing: `${Date.now() - t0}ms${ki.cached ? \" (cached)\" : \"\"}`,\n });\n return ki.result ? ki : null;\n } catch (err) {\n recordRecallSectionMetric({\n section: \"ki\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: `${Date.now() - t0}ms (err)`,\n });\n log.warn(`Knowledge Index build failed: ${err}`);\n return null;\n }\n })();\n\n // 1c. Verbatim artifacts (v8.0 phase 1)\n const artifactsPromise = (async (): Promise<MemoryFile[]> => {\n if (\n !this.isRecallSectionEnabled(\n \"verbatim-artifacts\",\n this.config.verbatimArtifactsEnabled === true,\n )\n )\n return [];\n if (!this.config.verbatimArtifactsEnabled) return [];\n const t0 = Date.now();\n const targetCount = computeArtifactRecallLimit(\n recallMode,\n recallResultLimit,\n this.config.verbatimArtifactsMaxRecall,\n );\n if (targetCount <= 0) {\n recordRecallSectionMetric({\n section: \"artifacts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return [];\n }\n const results = await this.recallArtifactsAcrossNamespaces(\n retrievalQuery,\n recallNamespaces,\n targetCount,\n );\n\n recordRecallSectionMetric({\n section: \"artifacts\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results;\n })();\n\n const objectiveStatePromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.objectiveStateMemoryEnabled ||\n !this.config.objectiveStateRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"objective-state\",\n this.config.objectiveStateRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"objective-state\", \"maxResults\") ?? 4;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchObjectiveStateSnapshots({\n memoryDir: this.config.memoryDir,\n objectiveStateStoreDir: this.config.objectiveStateStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"objectiveState\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatObjectiveStateResults(results)\n : null;\n })();\n\n const causalTrajectoryPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.causalTrajectoryMemoryEnabled ||\n !this.config.causalTrajectoryRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"causal-trajectories\",\n this.config.causalTrajectoryRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"causal-trajectories\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchCausalTrajectories({\n memoryDir: this.config.memoryDir,\n causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"causalTrajectories\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatCausalTrajectoryResults(results)\n : null;\n })();\n\n const cmcRetrievalPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.cmcRetrievalEnabled ||\n !this.isRecallSectionEnabled(\n \"cmc-causal-chains\",\n this.config.cmcRetrievalEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n try {\n const { retrieveCausalChains } = await import(\"./causal-retrieval.js\");\n const section = await retrieveCausalChains({\n memoryDir: this.config.memoryDir,\n causalTrajectoryStoreDir: this.config.causalTrajectoryStoreDir,\n query: retrievalQuery,\n sessionKey,\n config: {\n maxDepth: this.config.cmcRetrievalMaxDepth,\n maxChars: this.config.cmcRetrievalMaxChars,\n counterfactualBoost: this.config.cmcRetrievalCounterfactualBoost,\n },\n });\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n } catch (err) {\n log.warn(\"[cmc] causal retrieval failed (non-fatal)\", err);\n recordRecallSectionMetric({\n section: \"cmcCausalChains\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: \"error\",\n });\n return null;\n }\n })();\n\n const calibrationPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.calibrationEnabled ||\n !this.isRecallSectionEnabled(\n \"calibration-rules\",\n this.config.calibrationEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n try {\n const { getCalibrationRulesForRecall, buildCalibrationRecallSection } =\n await import(\"./calibration.js\");\n const rules = await getCalibrationRulesForRecall(this.config.memoryDir);\n if (rules.length === 0) {\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(no-rules)\",\n });\n return null;\n }\n const section = buildCalibrationRecallSection(\n rules.slice(0, this.config.calibrationMaxRulesPerRecall),\n retrievalQuery,\n this.config.calibrationMaxChars,\n );\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n } catch (err) {\n log.warn(\"[calibration] recall section failed (non-fatal)\", err);\n recordRecallSectionMetric({\n section: \"calibrationRules\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: false,\n timing: \"error\",\n });\n return null;\n }\n })();\n\n const trustZonePromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.trustZonesEnabled ||\n !this.config.trustZoneRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"trust-zones\",\n this.config.trustZoneRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"trust-zones\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchTrustZoneRecords({\n memoryDir: this.config.memoryDir,\n trustZoneStoreDir: this.config.trustZoneStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"trustZones\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0 ? this.formatTrustZoneResults(results) : null;\n })();\n\n const harmonicRetrievalAbort = createEnrichmentAbortHandle(\n options.abortSignal,\n );\n const harmonicRetrievalPromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.harmonicRetrievalEnabled ||\n !this.isRecallSectionEnabled(\n \"harmonic-retrieval\",\n this.config.harmonicRetrievalEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"harmonic-retrieval\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchHarmonicRetrieval({\n memoryDir: this.config.memoryDir,\n abstractionNodeStoreDir: this.config.abstractionNodeStoreDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n anchorsEnabled: this.config.abstractionAnchorsEnabled,\n abortSignal: harmonicRetrievalAbort.signal,\n });\n\n recordRecallSectionMetric({\n section: \"harmonicRetrieval\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatHarmonicRetrievalResults(results)\n : null;\n })().finally(() => harmonicRetrievalAbort.dispose()),\n () => harmonicRetrievalAbort.cancel(),\n );\n\n // Verified recall and semantic rules both need readAllMemories().\n // Instead of a shared preload (which has namespace/dir mismatch issues),\n // each subsystem calls readAllMemories() on its correct storage instance.\n // The process-level memory cache (keyed by baseDir + memoryStatusVersion)\n // ensures only one actual disk scan happens — subsequent calls return\n // from cache in <1ms.\n\n const verifiedRecallPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.verifiedRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"verified-episodes\",\n this.config.verifiedRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"verified-episodes\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const VERIFIED_RECALL_TIMEOUT_MS = 15_000;\n let timeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const results = await Promise.race([\n searchVerifiedEpisodes({\n memoryDir: profileStorage.dir,\n query: retrievalQuery,\n maxResults,\n boxRecallDays: this.config.boxRecallDays,\n }),\n new Promise<[]>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve([]),\n VERIFIED_RECALL_TIMEOUT_MS,\n );\n }),\n ]).catch(() => [] as VerifiedEpisodeResult[]);\n if (timeoutHandle) clearTimeout(timeoutHandle);\n\n const durationMs = Date.now() - t0;\n if (durationMs >= VERIFIED_RECALL_TIMEOUT_MS) {\n log.debug(\n `verified recall: timed out after ${VERIFIED_RECALL_TIMEOUT_MS}ms`,\n );\n }\n recordRecallSectionMetric({\n section: \"verifiedRecall\",\n priority: \"core\",\n durationMs,\n deadlineMs: VERIFIED_RECALL_TIMEOUT_MS,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatVerifiedEpisodeResults(results)\n : null;\n })();\n\n const verifiedRulesPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.semanticRuleVerificationEnabled ||\n !this.isRecallSectionEnabled(\n \"verified-rules\",\n this.config.semanticRuleVerificationEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"verified-rules\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const VERIFIED_RULES_TIMEOUT_MS = 15_000;\n let rulesTimeoutHandle: ReturnType<typeof setTimeout> | undefined;\n const results = await Promise.race([\n searchVerifiedSemanticRules({\n memoryDir: this.config.memoryDir,\n query: retrievalQuery,\n maxResults,\n }),\n new Promise<[]>((resolve) => {\n rulesTimeoutHandle = setTimeout(\n () => resolve([]),\n VERIFIED_RULES_TIMEOUT_MS,\n );\n }),\n ]).catch(() => [] as VerifiedSemanticRuleResult[]);\n if (rulesTimeoutHandle) clearTimeout(rulesTimeoutHandle);\n\n const durationMs = Date.now() - t0;\n if (durationMs >= VERIFIED_RULES_TIMEOUT_MS) {\n log.debug(\n `verified rules: timed out after ${VERIFIED_RULES_TIMEOUT_MS}ms`,\n );\n }\n recordRecallSectionMetric({\n section: \"verifiedRules\",\n priority: \"core\",\n durationMs,\n deadlineMs: VERIFIED_RULES_TIMEOUT_MS,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0\n ? this.formatVerifiedSemanticRuleResults(results)\n : null;\n })();\n\n const workProductsPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.creationMemoryEnabled ||\n !this.config.workProductRecallEnabled ||\n !this.isRecallSectionEnabled(\n \"work-products\",\n this.config.workProductRecallEnabled === true,\n )\n ) {\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxResults =\n this.getRecallSectionNumber(\"work-products\", \"maxResults\") ?? 3;\n if (maxResults <= 0) {\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const results = await searchWorkProductLedgerEntries({\n memoryDir: this.config.memoryDir,\n workProductLedgerDir: this.config.workProductLedgerDir,\n query: retrievalQuery,\n maxResults,\n sessionKey,\n });\n\n recordRecallSectionMetric({\n section: \"workProducts\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return results.length > 0 ? this.formatWorkProductResults(results) : null;\n })();\n\n const queryAwarePrefilterPromise =\n (async (): Promise<QueryAwarePrefilter> => {\n const t0 = Date.now();\n if (!this.config.queryAwareIndexingEnabled || !prompt.trim()) {\n recordRecallSectionMetric({\n section: \"queryAware\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return {\n candidatePaths: null,\n temporalFromDate: null,\n matchedTags: [],\n expandedTags: [],\n combination: \"none\",\n filteredToFullSearch: false,\n };\n }\n\n const prefilter = await this.buildQueryAwarePrefilter(\n retrievalQuery,\n recallNamespaces,\n );\n const candidateCount = prefilter.candidatePaths?.size ?? 0;\n const temporalLabel = prefilter.temporalFromDate ?? \"-\";\n const tagLabel =\n prefilter.expandedTags.length > 0\n ? prefilter.expandedTags.join(\"|\")\n : \"-\";\n const fallbackLabel = prefilter.filteredToFullSearch\n ? \"/full-search\"\n : \"\";\n recordRecallSectionMetric({\n section: \"queryAware\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: prefilter.filteredToFullSearch ? \"stale\" : \"fresh\",\n success: true,\n timing: `${Date.now() - t0}ms(${prefilter.combination}${fallbackLabel};count=${candidateCount};time=${temporalLabel};tags=${tagLabel})`,\n });\n return prefilter;\n })();\n\n // 2. QMD search (the slow part — runs in parallel with preamble)\n type QmdPhaseResult = {\n memoryResultsLists: QmdSearchResult[][];\n globalResults: QmdSearchResult[];\n /** Top QMD score BEFORE contextual weight scaling from the agent merge.\n * Used by the confidence gate so that enabling parallel retrieval doesn't\n * silently lower scores below the calibrated gate threshold. */\n preAugmentTopScore: number;\n /** Max score from direct + temporal agents (post-weight) BEFORE merge.\n * Included in the confidence gate so that strong specialized hits (e.g.\n * an exact entity-name match) are not discarded just because the QMD\n * contextual pass returned a weak result. */\n maxSpecializedScore: number;\n } | null;\n\n const qmdEnrichmentAbort = createEnrichmentAbortHandle(options.abortSignal);\n const qmdPromise = observeEnrichmentPromise(\n (async (): Promise<QmdPhaseResult> => {\n const t0 = Date.now();\n if (recallResultLimit <= 0) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const qmdCacheKey = buildQmdRecallCacheKey({\n query: retrievalQuery,\n namespaces: recallNamespaces,\n recallMode,\n maxResults: qmdFetchLimit,\n memoryDir: this.config.memoryDir,\n searchOptions: qmdSearchOptions,\n });\n const cachedQmd = getCachedQmdRecall<Exclude<QmdPhaseResult, null>>(\n qmdCacheKey,\n {\n freshTtlMs: this.config.qmdRecallCacheTtlMs ?? 60_000,\n staleTtlMs: this.config.qmdRecallCacheStaleTtlMs ?? 10 * 60_000,\n },\n );\n const staleQmdFallback =\n cachedQmd?.source === \"stale\" ? cachedQmd : null;\n if (cachedQmd?.source === \"fresh\") {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: cachedQmd.source,\n success: true,\n timing: `${Math.max(0, Math.round(cachedQmd.ageMs))}ms-cache`,\n });\n return cachedQmd.value;\n }\n\n if (!this.qmd.isAvailable()) {\n const now = Date.now();\n const QMD_REPROBE_COOLDOWN_MS = 60_000;\n if (\n this.lastQmdReprobeAtMs &&\n now - this.lastQmdReprobeAtMs < QMD_REPROBE_COOLDOWN_MS\n ) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(reprobe-cooldown:${Math.max(0, Math.round(staleQmdFallback.ageMs))}ms)`,\n });\n return staleQmdFallback.value;\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(reprobe-cooldown)\",\n });\n return null;\n }\n this.lastQmdReprobeAtMs = now;\n const reprobed = await this.qmd.probe();\n if (!reprobed) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(reprobe-failed:${Math.max(0, Math.round(staleQmdFallback.ageMs))}ms)`,\n });\n return staleQmdFallback.value;\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n log.debug(\n `Search skip (re-probe failed): ${this.qmd.debugStatus()}`,\n );\n return null;\n }\n log.info(`QMD re-probe succeeded: ${this.qmd.debugStatus()}`);\n }\n\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const maxPerAgent = this.config.parallelMaxResultsPerAgent;\n const specializedAgentPromise: Promise<\n [ParallelSearchResult[], ParallelSearchResult[]]\n > | null =\n this.config.parallelRetrievalEnabled && maxPerAgent > 0\n ? Promise.all([\n shouldRunAgent(\"direct\", retrievalQuery, 0)\n ? runDirectAgent(\n retrievalQuery,\n profileStorage.dir,\n maxPerAgent,\n ).catch((err) => {\n log.debug(`DirectAgent pre-start failed: ${err}`);\n return [] as ParallelSearchResult[];\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n shouldRunAgent(\"temporal\", retrievalQuery, 0)\n ? runTemporalAgent(\n retrievalQuery,\n this.config.memoryDir,\n maxPerAgent,\n queryAwarePrefilter.candidatePaths,\n ).catch((err) => {\n log.debug(`TemporalAgent pre-start failed: ${err}`);\n return [] as ParallelSearchResult[];\n })\n : Promise.resolve([] as ParallelSearchResult[]),\n ])\n : null;\n\n try {\n const filteredResults =\n await this.fetchQmdMemoryResultsWithArtifactTopUp(\n retrievalQuery,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n queryAwarePrefilter,\n searchOptions: qmdSearchOptions,\n abortSignal: qmdEnrichmentAbort.signal,\n onDebugSnapshot: async (snapshot) => {\n await this.recordLastQmdRecallSnapshot({\n storage: profileStorage,\n snapshot,\n });\n },\n },\n );\n\n const preAugmentTopScore =\n filteredResults.length > 0\n ? Math.max(...filteredResults.map((r) => r.score))\n : 0;\n let augmentedResults = filteredResults;\n let maxSpecializedScore = 0;\n if (this.config.parallelRetrievalEnabled && specializedAgentPromise) {\n try {\n const [directResults, temporalResults] =\n await specializedAgentPromise;\n if (filteredResults.length > 0) {\n const w = this.config.parallelAgentWeights;\n maxSpecializedScore = Math.max(\n directResults.length > 0\n ? Math.max(...directResults.map((r) => r.score * w.direct))\n : 0,\n temporalResults.length > 0\n ? Math.max(\n ...temporalResults.map((r) => r.score * w.temporal),\n )\n : 0,\n );\n const lifecycleHeadroom =\n this.config.parallelMaxResultsPerAgent * 2;\n augmentedResults = await mergeWithAgentResults(\n filteredResults,\n directResults,\n temporalResults,\n this.config.parallelAgentWeights,\n qmdFetchLimit + lifecycleHeadroom,\n );\n }\n } catch (err) {\n log.debug(\n `parallelRetrieval augmentation failed, using base results: ${err}`,\n );\n maxSpecializedScore = 0;\n }\n }\n\n const result = {\n memoryResultsLists: [augmentedResults],\n globalResults: [],\n preAugmentTopScore,\n maxSpecializedScore,\n };\n if (\n augmentedResults.length > 0 ||\n result.globalResults.length > 0\n ) {\n setCachedQmdRecall(qmdCacheKey, result, {\n maxEntries: this.config.qmdRecallCacheMaxEntries ?? 128,\n });\n }\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return result;\n } catch (err) {\n if (staleQmdFallback) {\n recordRecallSectionMetric({\n section: \"qmd\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"stale\",\n success: true,\n timing: `stale-cache(${err instanceof Error ? err.message : String(err)})`,\n });\n return staleQmdFallback.value;\n }\n throw err;\n }\n })()\n .catch((err): QmdPhaseResult => {\n if (options.abortSignal?.aborted) {\n log.debug(\n `recall phase-1 enrichment [qmd]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n log.warn(\n `recall phase-1 enrichment [qmd] failed open: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n })\n .finally(() => qmdEnrichmentAbort.dispose()),\n () => qmdEnrichmentAbort.cancel(),\n );\n\n const transcriptPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.transcriptEnabled ||\n !this.isRecallSectionEnabled(\"transcript\", true)\n ) {\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const transcriptMaxTokens =\n this.getRecallSectionNumber(\"transcript\", \"maxTokens\") ??\n this.config.maxTranscriptTokens;\n const transcriptMaxTurns =\n this.getRecallSectionNumber(\"transcript\", \"maxTurns\") ??\n this.config.maxTranscriptTurns;\n const transcriptLookbackHours =\n this.getRecallSectionNumber(\"transcript\", \"lookbackHours\") ??\n this.config.transcriptRecallHours;\n if (\n transcriptMaxTokens === 0 ||\n transcriptMaxTurns === 0 ||\n transcriptLookbackHours === 0\n ) {\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n let section: string | null = null;\n // Try checkpoint first (post-compaction recovery)\n let checkpointInjected = false;\n if (this.config.checkpointEnabled) {\n const checkpoint = await this.transcript.loadCheckpoint(sessionKey);\n log.debug(\n `recall: checkpoint loaded, turns=${checkpoint?.turns?.length ?? 0}`,\n );\n if (checkpoint && checkpoint.turns.length > 0) {\n const formatted = this.transcript.formatForRecall(\n checkpoint.turns,\n transcriptMaxTokens,\n );\n if (formatted) {\n section = `## Working Context (Recovered)\\n\\n${formatted}`;\n checkpointInjected = true;\n // Clear checkpoint after injection\n await this.transcript.clearCheckpoint();\n }\n }\n }\n\n if (!checkpointInjected) {\n const entries = await this.transcript.readRecent(\n transcriptLookbackHours,\n sessionKey,\n );\n log.debug(\n `recall: read ${entries.length} transcript entries for sessionKey=${sessionKey}`,\n );\n\n // Apply max turns cap\n const cappedEntries = entries.slice(-transcriptMaxTurns);\n if (cappedEntries.length > 0) {\n log.debug(\n `recall: injecting ${cappedEntries.length} transcript entries`,\n );\n const formatted = this.transcript.formatForRecall(\n cappedEntries,\n transcriptMaxTokens,\n );\n if (formatted) section = formatted;\n }\n }\n\n recordRecallSectionMetric({\n section: \"transcript\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n // Compaction reset runs independently of transcript — it must work even when\n // transcriptEnabled=false, since compaction recovery is a separate concern.\n const compactionPromise = (async (): Promise<string | null> => {\n // Always clean up per-session workspace overrides, even if the feature is off,\n // to prevent the Map from accumulating stale entries on long-running gateways.\n const effectiveSessionKey = sessionKey ?? \"default\";\n const compactionWorkspaceDir =\n this._recallWorkspaceOverrides.get(effectiveSessionKey);\n this._recallWorkspaceOverrides.delete(effectiveSessionKey);\n\n if (!this.config.compactionResetEnabled) return null;\n\n const workspaceDir =\n compactionWorkspaceDir ||\n this.config.workspaceDir ||\n defaultWorkspaceDir();\n const safeSessionKey = sanitizeSessionKeyForFilename(effectiveSessionKey);\n const signalPath = path.join(\n workspaceDir,\n `.compaction-reset-signal-${safeSessionKey}`,\n );\n const bootPath = path.join(workspaceDir, \"BOOT.md\");\n\n try {\n const signalStat = await stat(signalPath).catch(() => null);\n if (!signalStat) return null;\n\n const signalAge = Date.now() - signalStat.mtimeMs;\n const signalData = JSON.parse(await readFile(signalPath, \"utf-8\"));\n\n // Validate signal belongs to this session (defense-in-depth: filename\n // is already per-session, but the sessionKey inside provides a second check).\n // Use strict !== so missing/null sessionKey also fails validation.\n if (signalData.sessionKey !== effectiveSessionKey) {\n log.debug(\n `recall: compaction signal is for ${signalData.sessionKey}, not ${effectiveSessionKey} — skipping`,\n );\n return null;\n }\n\n if (signalAge >= COMPACTION_SIGNAL_MAX_AGE_MS) {\n log.debug(\n `recall: stale compaction signal (${Math.round(signalAge / 1000)}s old), skipping`,\n );\n await unlink(signalPath).catch(() => {});\n return null;\n }\n\n // Signal is fresh and belongs to this session — build recovery context\n let section = \"\\n\\n## Session Recovery (Post-Compaction)\\n\\n\";\n section += `⚠️ A compaction occurred at ${signalData.compactedAt} and this is a fresh session.\\n\\n`;\n\n try {\n const bootContent = await readFile(bootPath, \"utf-8\");\n section += \"### BOOT.md (working state before compaction)\\n\\n\";\n section += bootContent + \"\\n\";\n } catch {\n section += \"### ⚠️ BOOT.md is MISSING\\n\\n\";\n section +=\n \"The memory flush may not have written BOOT.md before compaction. \";\n section += \"Ask the user what you were working on — do not guess.\\n\";\n }\n\n log.info(\n `recall: injected compaction reset context for ${effectiveSessionKey}`,\n );\n await unlink(signalPath).catch(() => {});\n return section;\n } catch (err) {\n log.debug(\"recall: compaction signal check failed:\", err);\n // Remove corrupt/unreadable signal files so they don't cause repeated\n // parse failures on every recall() until the 1-hour sweep runs.\n await unlink(signalPath).catch(() => {});\n return null;\n }\n })();\n\n const summariesPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.hourlySummariesEnabled ||\n !sessionKey ||\n !this.isRecallSectionEnabled(\"summaries\", true)\n ) {\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const summariesLookbackHours =\n this.getRecallSectionNumber(\"summaries\", \"lookbackHours\") ??\n this.config.summaryRecallHours;\n const summariesMaxCount =\n this.getRecallSectionNumber(\"summaries\", \"maxCount\") ??\n this.config.maxSummaryCount;\n if (summariesLookbackHours <= 0 || summariesMaxCount <= 0) {\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const summaries = await this.summarizer.readRecent(\n sessionKey,\n summariesLookbackHours,\n );\n const cappedSummaries = summaries.slice(0, summariesMaxCount);\n const section =\n cappedSummaries.length > 0\n ? this.summarizer.formatForRecall(cappedSummaries, summariesMaxCount)\n : null;\n recordRecallSectionMetric({\n section: \"summaries\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const nativeKnowledgeAbort = createEnrichmentAbortHandle(\n options.abortSignal,\n );\n const nativeKnowledgePromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.nativeKnowledge?.enabled ||\n !this.isRecallSectionEnabled(\n \"native-knowledge\",\n this.config.nativeKnowledge.enabled,\n )\n ) {\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n if (\n this.config.nativeKnowledge.maxResults === 0 ||\n this.config.nativeKnowledge.maxChars === 0\n ) {\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n\n const chunks = await collectNativeKnowledgeChunks({\n workspaceDir: this.config.workspaceDir,\n memoryDir: this.config.memoryDir,\n config: this.config.nativeKnowledge,\n recallNamespaces: this.config.namespacesEnabled\n ? recallNamespaces\n : undefined,\n defaultNamespace: this.config.defaultNamespace,\n abortSignal: nativeKnowledgeAbort.signal,\n }).catch(() => []);\n const results = searchNativeKnowledge({\n query: retrievalQuery,\n chunks,\n maxResults:\n this.getRecallSectionNumber(\"native-knowledge\", \"maxResults\") ??\n this.config.nativeKnowledge.maxResults,\n });\n const section = formatNativeKnowledgeSection({\n results,\n maxChars:\n this.getRecallSectionNumber(\"native-knowledge\", \"maxChars\") ??\n this.config.nativeKnowledge.maxChars,\n });\n recordRecallSectionMetric({\n section: \"nativeKnowledge\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })().finally(() => nativeKnowledgeAbort.dispose()),\n () => nativeKnowledgeAbort.cancel(),\n );\n\n const conversationRecallPromise = (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.config.conversationIndexEnabled ||\n queryPolicy.skipConversationRecall ||\n !this.isRecallSectionEnabled(\"conversation-recall\", true)\n ) {\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n\n const topKOverride = this.getRecallSectionNumber(\n \"conversation-recall\",\n \"topK\",\n );\n if (topKOverride === 0) {\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: 0,\n deadlineMs: recallSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(topK=0)\",\n });\n return null;\n }\n\n const startedAtMs = Date.now();\n const timeoutMs = Math.max(\n 200,\n this.getRecallSectionNumber(\"conversation-recall\", \"timeoutMs\") ??\n this.config.conversationRecallTimeoutMs,\n );\n const topK = Math.max(\n 1,\n topKOverride ?? this.config.conversationRecallTopK,\n );\n const maxChars = Math.max(\n 400,\n this.getRecallSectionNumber(\"conversation-recall\", \"maxChars\") ??\n this.config.conversationRecallMaxChars,\n );\n\n const results = (await Promise.race([\n this.searchConversationRecallResults(retrievalQuery, topK),\n new Promise<[]>((resolve) => setTimeout(() => resolve([]), timeoutMs)),\n ]).catch(() => [])) as Array<{\n path: string;\n snippet: string;\n score: number;\n }>;\n\n const durationMs = Date.now() - startedAtMs;\n if (durationMs >= timeoutMs) {\n log.debug(`conversation recall: timed out after ${timeoutMs}ms`);\n }\n\n const section = this.formatConversationRecallSection(results, maxChars);\n recordRecallSectionMetric({\n section: \"convRecall\",\n priority: \"core\",\n durationMs: Date.now() - t0,\n deadlineMs: timeoutMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })();\n\n const procedureRecallPromise = (async (): Promise<string | null> => {\n if (this.config.procedural?.enabled !== true) return null;\n if (!this.isRecallSectionEnabled(\"procedure-recall\", true)) return null;\n try {\n return await buildProcedureRecallSection(\n profileStorage,\n retrievalQuery,\n this.config,\n );\n } catch (err) {\n log.debug(\n `procedure-recall: failed open: ${err instanceof Error ? err.message : String(err)}`,\n );\n return null;\n }\n })();\n\n const compoundingPromise = observeEnrichmentPromise(\n (async (): Promise<string | null> => {\n const t0 = Date.now();\n if (\n !this.compounding ||\n !this.config.compoundingInjectEnabled ||\n !this.isRecallSectionEnabled(\"compounding\", true)\n ) {\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip\",\n });\n return null;\n }\n const maxPatterns =\n this.getRecallSectionNumber(\"compounding\", \"maxPatterns\") ?? 40;\n const maxRubrics =\n this.getRecallSectionNumber(\"compounding\", \"maxRubrics\") ?? 4;\n if (maxPatterns === 0 && maxRubrics === 0) {\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: 0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"skip\",\n success: true,\n timing: \"skip(limit=0)\",\n });\n return null;\n }\n const section = await this.compounding.buildRecallSection(\n retrievalQuery,\n { maxPatterns, maxRubrics },\n );\n recordRecallSectionMetric({\n section: \"compounding\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n return section;\n })(),\n );\n\n // Start memory-boxes read in parallel with the rest of phase-1 (it can take\n // several seconds on large box directories due to sequential I/O). We kick it\n // off here so it overlaps with QMD and other concurrent work rather than\n // running sequentially in phase-2 and blocking assembly.\n const recentBoxesPromise: Promise<BoxFrontmatter[]> =\n this.isRecallSectionEnabled(\n \"memory-boxes\",\n this.config.memoryBoxesEnabled === true,\n ) &&\n this.config.memoryBoxesEnabled &&\n this.config.boxRecallDays > 0\n ? this.boxBuilderFor(profileStorage)\n .readRecentBoxes(this.config.boxRecallDays)\n .catch(() => [] as BoxFrontmatter[])\n : Promise.resolve([] as BoxFrontmatter[]);\n\n // --- Wait for core sections first, then bounded enrichment ---\n this.profiler.startSpan(\"phase-1-parallel\", profileTraceId);\n const phase1Start = Date.now();\n log.info(\n `recall phase-1: starting parallel work at +${phase1Start - recallStart}ms`,\n );\n const [\n sharedCtx,\n profile,\n identityContinuity,\n entityRetrievalSection,\n kiResult,\n artifacts,\n objectiveStateSection,\n causalTrajectorySection,\n cmcCausalChainsSection,\n calibrationSection,\n procedureRecallSection,\n trustZoneSection,\n verifiedRecallSection,\n verifiedRulesSection,\n workProductsSection,\n transcriptSection,\n compactionSection,\n summariesSection,\n conversationRecallSection,\n ] = 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 ] 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 ]\n >,\n options.abortSignal,\n \"recall aborted during phase-one preamble\",\n );\n\n this.profiler.endSpan(\"phase-1-parallel\", profileTraceId);\n log.info(\n `recall phase-1: core work done at +${Date.now() - recallStart}ms ` +\n `(phase took ${Date.now() - phase1Start}ms); continuing with incremental enrichment assembly`,\n );\n throwIfRecallAborted(options.abortSignal);\n\n const enrichmentAssemblyDeadlineAtMs =\n enrichmentSectionDeadlineMs > 0\n ? Date.now() + enrichmentSectionDeadlineMs\n : null;\n\n const awaitEnrichmentSection = async <T>(\n name: string,\n promise: ObservedDeferredEnrichmentPromise<T>,\n ): Promise<T | null> => {\n const finalizeEnrichmentOutcome = (\n outcome: DeferredEnrichmentOutcome<T>,\n ): T | null => {\n if (outcome.status === \"resolved\") {\n log.debug(\n `recall phase-1 enrichment [${name}]: resolved at +${Date.now() - phase1Start}ms`,\n );\n return outcome.value;\n }\n\n if (options.abortSignal?.aborted) {\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n log.warn(\n `recall phase-1 enrichment [${name}] failed open: ` +\n `${outcome.error instanceof Error ? outcome.error.message : String(outcome.error)}`,\n );\n return null;\n };\n\n if (options.abortSignal?.aborted) {\n promise.cancel();\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after abort at +${Date.now() - phase1Start}ms`,\n );\n return null;\n }\n\n let timeoutHandle: NodeJS.Timeout | undefined;\n const timeoutMs =\n enrichmentAssemblyDeadlineAtMs === null\n ? null\n : Math.max(0, enrichmentAssemblyDeadlineAtMs - Date.now());\n if (timeoutMs === 0) {\n const settledOutcome = promise.getSettledOutcome();\n if (settledOutcome) {\n log.debug(\n `recall phase-1 enrichment [${name}]: consumed already-settled result after shared ${enrichmentSectionDeadlineMs}ms budget expired ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n return finalizeEnrichmentOutcome(settledOutcome);\n }\n log.debug(\n `recall phase-1 enrichment [${name}]: skipped after shared ${enrichmentSectionDeadlineMs}ms budget expired ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n promise.cancel();\n return null;\n }\n\n const outcome = await (timeoutMs !== null\n ? Promise.race<DeferredEnrichmentOutcome<T> | { status: \"timed_out\" }>([\n promise,\n new Promise<{ status: \"timed_out\" }>((resolve) => {\n timeoutHandle = setTimeout(\n () => resolve({ status: \"timed_out\" }),\n timeoutMs,\n );\n }),\n ])\n : promise);\n if (timeoutHandle) clearTimeout(timeoutHandle);\n\n if (outcome.status === \"timed_out\") {\n log.debug(\n `recall phase-1 enrichment [${name}]: timed out within shared ${enrichmentSectionDeadlineMs}ms budget ` +\n `at +${Date.now() - phase1Start}ms`,\n );\n promise.cancel();\n return null;\n }\n\n return finalizeEnrichmentOutcome(outcome);\n };\n\n // --- Phase 2: Assemble sections in correct order ---\n this.profiler.startSpan(\"assembly\", profileTraceId);\n\n // 0. Shared context\n if (sharedCtx)\n this.appendRecallSection(sectionBuckets, \"shared-context\", sharedCtx);\n\n // 1. Profile\n if (profile)\n this.appendRecallSection(\n sectionBuckets,\n \"profile\",\n `## User Profile\\n\\n${profile}`,\n );\n\n // 1-pre. Calibration rules (injected early so model sees adjustments first)\n if (calibrationSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"calibration-rules\",\n calibrationSection,\n );\n }\n\n if (procedureRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"procedure-recall\",\n procedureRecallSection,\n );\n }\n\n // 1a. Identity continuity\n if (identityContinuity) {\n this.appendRecallSection(\n sectionBuckets,\n \"identity-continuity\",\n identityContinuity.section,\n );\n identityInjectionModeUsed = identityContinuity.mode;\n identityInjectedChars = identityContinuity.injectedChars;\n identityInjectionTruncated = identityContinuity.truncated;\n }\n\n if (entityRetrievalSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"entity-retrieval\",\n entityRetrievalSection,\n );\n }\n\n // 1b. Knowledge Index\n if (kiResult?.result) {\n this.appendRecallSection(\n sectionBuckets,\n \"knowledge-index\",\n kiResult.result,\n );\n log.debug(\n `Knowledge Index: ${kiResult.result.split(\"\\n\").length - 4} entities, ${kiResult.result.length} chars${kiResult.cached ? \" (cached)\" : \"\"}`,\n );\n }\n\n const nativeKnowledgeSection = await awaitEnrichmentSection(\n \"nativeKnowledge\",\n nativeKnowledgePromise,\n );\n if (nativeKnowledgeSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"native-knowledge\",\n nativeKnowledgeSection,\n );\n }\n\n // 1c. Verbatim artifacts (quote-first anchors)\n if (artifacts.length > 0) {\n const lines = artifacts.map((a) => {\n const artifactType = a.frontmatter.artifactType ?? \"fact\";\n const createdRaw =\n typeof a.frontmatter.created === \"string\"\n ? a.frontmatter.created\n : \"\";\n const created = createdRaw\n ? createdRaw.slice(0, 19).replace(\"T\", \" \")\n : \"unknown-time\";\n return `- [${artifactType}] \"${this.truncateArtifactForRecall(a.content)}\" (${created})`;\n });\n this.appendRecallSection(\n sectionBuckets,\n \"verbatim-artifacts\",\n `## Verbatim Artifacts\\n\\n${lines.join(\"\\n\")}`,\n );\n }\n\n // 1d. Memory Boxes (topic continuity windows, v8.0 Phase 2A)\n // recentBoxesPromise was kicked off before phase-1 so it ran concurrently.\n {\n const recentBoxes = await recentBoxesPromise;\n if (recentBoxes.length > 0) {\n const boxLines = recentBoxes.slice(0, 5).map((b: BoxFrontmatter) => {\n const sealedDate = b.sealedAt\n ? b.sealedAt.slice(0, 16).replace(\"T\", \" \")\n : \"?\";\n const traceNote = b.traceId\n ? ` [trace: ${b.traceId.slice(0, 12)}]`\n : \"\";\n return `- [${sealedDate}${traceNote}] Topics: ${b.topics.join(\", \")} (${b.memoryIds.length} memories)`;\n });\n this.appendRecallSection(\n sectionBuckets,\n \"memory-boxes\",\n `## Recent Topic Windows\\n\\n${boxLines.join(\"\\n\")}`,\n );\n }\n }\n\n // 1e. TMT node (temporal memory tree, v8.2)\n if (\n this.isRecallSectionEnabled(\n \"temporal-memory-tree\",\n this.config.temporalMemoryTreeEnabled === true,\n ) &&\n this.config.temporalMemoryTreeEnabled &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n const tmtNode = await this.tmtBuilder.getMostRelevantNode();\n if (tmtNode) {\n const levelLabel =\n tmtNode.level.charAt(0).toUpperCase() + tmtNode.level.slice(1);\n this.appendRecallSection(\n sectionBuckets,\n \"temporal-memory-tree\",\n `## Memory Timeline (${levelLabel})\\n\\n${tmtNode.summary}`,\n );\n }\n }\n\n // LCM compressed history section\n if (\n this.lcmEngine?.enabled &&\n recallMode !== \"minimal\" &&\n (recallMode as RecallPlanMode) !== \"no_recall\"\n ) {\n try {\n const lcmSection = await this.lcmEngine.assembleRecall(\n sessionKey ?? \"default\",\n this.config.recallBudgetChars,\n );\n if (lcmSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"lcm-compressed-history\",\n lcmSection,\n );\n }\n } catch (err) {\n log.debug(`LCM recall assembly error: ${err}`);\n }\n }\n\n if (objectiveStateSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"objective-state\",\n objectiveStateSection,\n );\n }\n\n if (causalTrajectorySection) {\n this.appendRecallSection(\n sectionBuckets,\n \"causal-trajectories\",\n causalTrajectorySection,\n );\n }\n\n if (cmcCausalChainsSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"cmc-causal-chains\",\n cmcCausalChainsSection,\n );\n }\n\n if (trustZoneSection) {\n this.appendRecallSection(sectionBuckets, \"trust-zones\", trustZoneSection);\n }\n\n const harmonicRetrievalSection = await awaitEnrichmentSection(\n \"harmonic\",\n harmonicRetrievalPromise,\n );\n if (harmonicRetrievalSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"harmonic-retrieval\",\n harmonicRetrievalSection,\n );\n }\n\n if (verifiedRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"verified-episodes\",\n verifiedRecallSection,\n );\n }\n\n if (verifiedRulesSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"verified-rules\",\n verifiedRulesSection,\n );\n }\n\n if (workProductsSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"work-products\",\n workProductsSection,\n );\n }\n\n // 2. QMD results — post-process and format\n const qmdResult = await awaitEnrichmentSection(\"qmd\", qmdPromise);\n if (qmdResult) {\n const t0 = Date.now();\n const {\n memoryResultsLists,\n globalResults,\n preAugmentTopScore,\n maxSpecializedScore,\n } = qmdResult;\n\n // Merge/dedupe by path; keep the best score and first non-empty snippet.\n const memoryResultsRaw = mergeGraphExpandedResults(\n memoryResultsLists.flat(),\n [],\n );\n\n let memoryResults = memoryResultsRaw;\n\n // Enforce namespace read policies by filtering paths.\n if (this.config.namespacesEnabled) {\n memoryResults = memoryResults.filter((r) =>\n recallNamespaces.includes(this.namespaceFromPath(r.path)),\n );\n }\n // Artifacts are injected through dedicated verbatim recall flow only.\n memoryResults = memoryResults.filter(\n (r) => !isArtifactMemoryPath(r.path),\n );\n\n const isFullModeGraphAssist =\n this.config.multiGraphMemoryEnabled &&\n this.config.graphAssistInFullModeEnabled !== false &&\n recallMode === \"full\" &&\n memoryResults.length >=\n Math.max(1, this.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n recallMode === \"graph_mode\" || isFullModeGraphAssist;\n const graphShadowEvalEnabled =\n isFullModeGraphAssist &&\n this.config.graphAssistShadowEvalEnabled === true;\n if (shouldRunGraphExpansion) {\n shouldPersistGraphSnapshot = true;\n graphDecisionShadowMode = graphShadowEvalEnabled;\n }\n if (shouldRunGraphExpansion) {\n const baselineMemoryResults = memoryResults;\n graphBaselinePaths.clear();\n baselineMemoryResults.forEach((result) =>\n graphBaselinePaths.add(result.path),\n );\n if (baselineMemoryResults.length === 0) {\n graphSnapshotStatus = \"skipped\";\n graphDecisionStatus = \"skipped\";\n graphDecisionReason =\n \"graph recall skipped because baseline retrieval produced no seed results\";\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = [];\n graphSnapshotSeedResults = [];\n graphSnapshotExpandedPaths = [];\n graphExpandedResultPaths.clear();\n } else {\n try {\n const {\n merged,\n seedPaths,\n expandedPaths,\n seedResults = baselineMemoryResults,\n } = await this.expandResultsViaGraph({\n memoryResults,\n recallNamespaces,\n recallResultLimit,\n });\n graphSnapshotStatus = \"completed\";\n graphDecisionStatus = \"completed\";\n graphDecisionReason = graphShadowEvalEnabled\n ? \"graph shadow evaluation completed without altering injected context\"\n : \"graph expansion merged into recall ranking\";\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = seedPaths;\n graphSnapshotExpandedPaths = expandedPaths;\n graphSnapshotSeedResults = this.buildGraphRecallRankedResults(\n seedResults,\n () => [\"baseline\"],\n );\n graphExpandedResultPaths.clear();\n expandedPaths.forEach((entry) =>\n graphExpandedResultPaths.add(entry.path),\n );\n memoryResults = graphShadowEvalEnabled\n ? baselineMemoryResults\n : merged;\n\n if (graphShadowEvalEnabled) {\n const comparison = summarizeGraphShadowComparison(\n baselineMemoryResults,\n merged,\n recallResultLimit,\n );\n graphSnapshotShadowComparison = comparison;\n recordRecallSectionMetric({\n section: \"graphShadow\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n timing:\n `on b=${comparison.baselineCount} g=${comparison.graphCount} ` +\n `ov=${comparison.overlapCount} (${comparison.overlapRatio.toFixed(2)}) ` +\n `avgDelta=${comparison.averageOverlapDelta.toFixed(3)}`,\n });\n }\n } catch (err) {\n graphSnapshotStatus = \"aborted\";\n graphDecisionStatus = \"aborted\";\n graphDecisionReason = `graph expansion failed: ${err instanceof Error ? err.message : String(err)}`;\n graphSnapshotReason = graphDecisionReason;\n graphSnapshotSeedPaths = baselineMemoryResults\n .slice(0, Math.max(1, recallResultLimit))\n .map((result) => result.path);\n graphSnapshotSeedResults = this.buildGraphRecallRankedResults(\n baselineMemoryResults,\n () => [\"baseline\"],\n );\n graphSnapshotExpandedPaths = [];\n graphExpandedResultPaths.clear();\n log.warn(`graph recall failed open: ${graphDecisionReason}`);\n memoryResults = baselineMemoryResults;\n }\n }\n }\n\n // Apply recency and access count boosting\n memoryResults = await this.boostSearchResults(\n memoryResults,\n recallNamespaces,\n retrievalQuery,\n );\n\n // Optional LLM reranking (default off). Fail-open if rerank fails/slow.\n if (this.config.rerankEnabled && this.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: retrievalQuery,\n candidates: memoryResults\n .slice(0, this.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.config.rerankTimeoutMs,\n maxCandidates: this.config.rerankMaxCandidates,\n cache: this.rerankCache,\n cacheEnabled: this.config.rerankCacheEnabled,\n cacheTtlMs: this.config.rerankCacheTtlMs,\n });\n if (ranked && ranked.length > 0) {\n const byPath = new Map(memoryResults.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const p of ranked) {\n const it = byPath.get(p);\n if (it) reordered.push(it);\n }\n // Append any unranked items in original order.\n const rankedSet = new Set(ranked);\n for (const r of memoryResults) {\n if (!rankedSet.has(r.path)) reordered.push(r);\n }\n memoryResults = reordered;\n }\n }\n if (this.config.rerankEnabled && this.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Memory Worth recall filter (issue #560 PR 4). When enabled, multiply\n // each candidate's score by its Memory Worth factor so memories with\n // a history of failed outcomes sink. Default off in this PR; PR 5\n // flips the default once bench shows tie-or-win. Fail-open: any\n // lookup error leaves the original scores untouched rather than\n // breaking recall for the whole namespace.\n if (this.config.recallMemoryWorthFilterEnabled && memoryResults.length > 0) {\n try {\n memoryResults = await this.applyMemoryWorthRerank(memoryResults, recallNamespaces);\n } catch (err) {\n log.debug(\"memory-worth filter failed open\", { error: (err as Error).message });\n }\n }\n\n // Synapse-inspired confidence gate: check scores BEFORE slicing so\n // reranking doesn't affect which score the gate evaluates.\n //\n // Gate exclusively on the pre-augmentation QMD top score so the threshold\n // stays on the same scale it was calibrated against (raw QMD scores, not\n // post-merge weighted scores). This avoids two pitfalls:\n // 1. The 0.7× contextual weight silently lowering scores below threshold.\n // 2. A direct/temporal hit on a different scale inflating the gate score.\n // We also include maxSpecializedScore so that a strong direct/temporal hit (e.g.\n // an exact entity-name match at score 1.0) is not discarded just because the QMD\n // contextual pass returned a weak result. maxSpecializedScore is post-weight, so\n // direct hits at weight 1.0 stay on the same 0-1 scale as QMD scores.\n // IMPORTANT: maxSpecializedScore is only included when QMD also found something\n // (preAugmentTopScore > 0). When QMD returns nothing, a weak specialized hit must\n // NOT block the embedding fallback safety net — that path exists precisely for the\n // case where QMD finds nothing. Setting effectiveGateScore = 0 when QMD is empty\n // preserves the original behaviour: empty QMD → gate skipped → fallback available.\n const effectiveGateScore =\n preAugmentTopScore > 0\n ? Math.max(preAugmentTopScore, maxSpecializedScore)\n : 0;\n // Capture pre-gate pool size for X-ray before the confidence\n // gate can zero `memoryResults`. Placing the capture after the\n // gate would record 0 instead of the true pre-gate pool size\n // (issue #570 PR 1 review follow-up).\n xrayBranchPoolSize.hot_qmd = Math.max(\n xrayBranchPoolSize.hot_qmd,\n memoryResults.length,\n );\n let confidenceGateRejected = false;\n if (this.config.recallConfidenceGateEnabled && effectiveGateScore > 0) {\n if (effectiveGateScore < this.config.recallConfidenceGateThreshold) {\n log.debug(\n `recall: confidence gate rejected ${memoryResults.length} results (effective score ${effectiveGateScore.toFixed(3)} below ${this.config.recallConfidenceGateThreshold})`,\n );\n memoryResults = [];\n confidenceGateRejected = true;\n }\n }\n\n // Diversify via MMR over the full candidate pool *before* truncating to\n // the final recall limit. Running MMR after the slice would be unable\n // to promote diverse candidates sitting just below the cutoff.\n memoryResults = this.diversifyAndLimitRecallResults(\n \"memories\",\n memoryResults,\n recallResultLimit,\n retrievalQuery,\n );\n\n // E-Mem-inspired memory reconstruction: fill gaps for referenced entities\n if (this.config.memoryReconstructionEnabled && memoryResults.length > 0) {\n try {\n const snippets = memoryResults.map((r) => r.snippet);\n // Extract entity paths already present in recall results to avoid duplicates\n const coveredRefs = memoryResults\n .map((r) => r.path)\n .filter((p) => p.startsWith(\"entities/\"))\n .map((p) => p.replace(/^entities\\//, \"\").replace(/\\.md$/, \"\"));\n const knownEntities = await profileStorage.listEntityNames();\n const missing = findUnresolvedEntityRefs(\n snippets,\n coveredRefs,\n knownEntities,\n );\n if (missing.length > 0) {\n // Allow up to maxExpansions successful entity expansions\n const budget = this.config.memoryReconstructionMaxExpansions;\n let expanded = 0;\n for (const entityName of missing) {\n if (expanded >= budget) break;\n const raw = await profileStorage.readEntity(entityName);\n if (raw && raw.length > 0) {\n const snippet =\n raw.length > 300 ? raw.slice(0, 300) + \"…\" : raw;\n memoryResults.push({\n docid: `entity:${entityName}`,\n path: `entities/${entityName}.md`,\n snippet: `[Entity: ${entityName}] ${snippet}`,\n score: 0.1,\n });\n expanded++;\n }\n }\n if (expanded > 0) {\n log.debug(`recall: reconstructed ${expanded} entity contexts`);\n }\n }\n } catch (err) {\n log.warn(\"recall: memory reconstruction failed (non-fatal)\", err);\n }\n }\n\n if (memoryResults.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n memoryResults,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_qmd\";\n recalledMemoryCount = memoryResults.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: memoryResults,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(memoryResults);\n recalledMemoryPaths = memoryResults\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n } else if (!confidenceGateRejected) {\n // Only attempt fallback paths if the confidence gate did NOT fire.\n // When the gate rejects, all recall pathways are skipped to prevent\n // low-relevance results from polluting context.\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const embeddingResults = await this.searchEmbeddingFallback(\n retrievalQuery,\n embeddingFetchLimit,\n );\n const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(\n embeddingResults,\n queryAwarePrefilter.candidatePaths,\n );\n const scopedCandidates = filterRecallCandidates(\n prefilteredEmbeddingResults,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.boostSearchResults(\n scopedCandidates,\n recallNamespaces,\n retrievalQuery,\n );\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.hot_embedding = Math.max(\n xrayBranchPoolSize.hot_embedding,\n boostedScoped.length,\n );\n const scoped = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n );\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: scoped,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(scoped);\n recalledMemoryPaths = scoped\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n }\n }\n }\n\n if (globalResults.length > 0) {\n this.appendRecallSection(\n sectionBuckets,\n \"workspace-context\",\n this.formatQmdResults(\"Workspace Context\", globalResults),\n );\n }\n\n recordRecallSectionMetric({\n section: \"qmdPost\",\n priority: \"enrichment\",\n durationMs: Date.now() - t0,\n deadlineMs: enrichmentSectionDeadlineMs,\n source: \"fresh\",\n success: true,\n });\n\n // If the user is pushing back (\"that's not right\", \"why did you say that\"),\n // gently suggest an explicit workflow to inspect what was recalled and record feedback.\n // IMPORTANT: this is suggestion-only; never auto-mark negatives.\n if (isDisagreementPrompt(prompt)) {\n this.appendRecallSection(\n sectionBuckets,\n \"memories\",\n [\n \"## Retrieval Feedback Helper\",\n \"\",\n \"The user may be disputing an answer. To debug whether retrieval misled the response:\",\n \"- Use tool `memory_last_recall` to see which memory IDs were injected into context.\",\n \"- Use tool `memory_intent_debug` to inspect the planner mode decision and graph fallback reason.\",\n \"- If negative examples are enabled, you can use `memory_feedback_last_recall` to mark specific recalled IDs as not useful.\",\n \"\",\n \"Safety: do not mass-mark negatives automatically; prefer explicit IDs.\",\n ].join(\"\\n\"),\n );\n }\n } else if (recallResultLimit > 0 && !this.qmd.isAvailable()) {\n // Fallback: embeddings first, then recency-only.\n const queryAwarePrefilter = await queryAwarePrefilterPromise;\n const embeddingResults = await this.searchEmbeddingFallback(\n retrievalQuery,\n embeddingFetchLimit,\n );\n const prefilteredEmbeddingResults = applyQueryAwareCandidateFilter(\n embeddingResults,\n queryAwarePrefilter.candidatePaths,\n );\n const scopedCandidates = filterRecallCandidates(\n prefilteredEmbeddingResults,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n limit: embeddingFetchLimit,\n },\n );\n const boostedScoped = await this.boostSearchResults(\n scopedCandidates,\n recallNamespaces,\n retrievalQuery,\n );\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.hot_embedding = Math.max(\n xrayBranchPoolSize.hot_embedding,\n boostedScoped.length,\n );\n const scoped = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedScoped,\n recallResultLimit,\n retrievalQuery,\n );\n if (scoped.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n scoped,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"hot_embedding\";\n recalledMemoryCount = scoped.length;\n this.publishRecallResults({\n title: \"Relevant Memories\",\n results: scoped,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(scoped);\n recalledMemoryPaths = scoped\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n } else {\n const memories =\n await this.readAllMemoriesForNamespaces(recallNamespaces);\n if (memories.length > 0) {\n // Filter out non-active memories. Delegate to\n // shouldFilterSupersededFromRecall for superseded-status logic so\n // that the recent-scan path and the boostSearchResults (QMD) path\n // have identical semantics:\n // • temporalSupersessionEnabled=false → never filter superseded\n // (mirrors QMD path; user disabled the feature, so old marks\n // are ignored and all memories surface)\n // • temporalSupersessionIncludeInRecall=true → never filter (audit mode)\n // • enabled=true + includeInRecall=false → filter superseded\n // Previously the recent-scan path checked `enabled && includeInRecall`\n // directly, which disagreed with the QMD path when enabled=false\n // (memories were still filtered, contrary to the kill-switch intent).\n // Using the shared gate fixes both Finding 2 and Finding 3 from\n // PR #402 (round 6).\n const supersessionOptions = {\n enabled: this.config.temporalSupersessionEnabled,\n includeInRecall: this.config.temporalSupersessionIncludeInRecall,\n };\n 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 // Include superseded memory only if the canonical gate says\n // NOT to filter it (kill switch off or audit mode on).\n return !shouldFilterSupersededFromRecall(m.frontmatter, supersessionOptions);\n }\n // Other non-active statuses (archived, retired, etc.) are\n // excluded from the recent-scan path by default.\n return false;\n },\n );\n // Convert all active memories to QmdSearchResult with recency-based\n // baseline score, then pass through boostSearchResults so temporal/tag\n // boosts apply consistently with the primary QMD retrieval path.\n // Cap AFTER boosting so boosted-but-recency-ranked memories can surface.\n // Pass a pre-populated memoryByPath so boostSearchResults skips redundant\n // disk reads for files already loaded by readAllMemoriesForNamespaces.\n const queryAwareScopedMemories = queryAwarePrefilter.candidatePaths\n ? activeMemories.filter((memory) =>\n queryAwarePrefilter.candidatePaths?.has(memory.path),\n )\n : activeMemories;\n if (\n queryAwarePrefilter.candidatePaths &&\n queryAwareScopedMemories.length === 0\n ) {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n });\n if (longTerm.length > 0) {\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n }\n } else {\n const recentSorted = queryAwareScopedMemories.sort(\n (a, b) =>\n new Date(b.frontmatter.updated).getTime() -\n new Date(a.frontmatter.updated).getTime(),\n );\n const preloadedMap = new Map<string, MemoryFile>(\n queryAwareScopedMemories\n .filter((m) => m.path)\n .map((m) => [m.path, m]),\n );\n const recentAsResults: QmdSearchResult[] = recentSorted.map(\n (m, i) => ({\n docid: m.frontmatter.id,\n path: m.path,\n snippet: m.content,\n score: 1.0 - i / Math.max(recentSorted.length, 1),\n }),\n );\n const boostedRecent = (\n await this.boostSearchResults(\n recentAsResults,\n recallNamespaces,\n retrievalQuery,\n preloadedMap,\n )\n ).sort((a, b) => b.score - a.score);\n // MMR runs on the pre-truncation pool so diverse candidates just\n // below the cutoff can be promoted into the injected set.\n xrayBranchPoolSize.recent_scan = Math.max(\n xrayBranchPoolSize.recent_scan,\n boostedRecent.length,\n );\n const recent = this.diversifyAndLimitRecallResults(\n \"memories\",\n boostedRecent,\n recallResultLimit,\n retrievalQuery,\n );\n\n if (recent.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n recent,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"recent_scan\";\n recalledMemoryCount = recent.length;\n this.publishRecallResults({\n title: \"Recent Memories\",\n results: recent,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(recent);\n recalledMemoryPaths = recent\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults =\n this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n }\n }\n }\n } else {\n const longTerm = await this.applyColdFallbackPipeline({\n prompt: retrievalQuery,\n recallNamespaces,\n recallResultLimit,\n recallMode,\n queryAwarePrefilter,\n abortSignal: options.abortSignal,\n xrayPoolSizeSink: xrayColdPoolSink,\n });\n if (longTerm.length > 0) {\n if (shouldPersistGraphSnapshot) {\n graphSnapshotFinalResults = this.buildGraphRecallRankedResults(\n longTerm,\n graphSourceLabelsForPath,\n );\n }\n recallSource = \"cold_fallback\";\n recalledMemoryCount = longTerm.length;\n this.publishRecallResults({\n title: \"Long-Term Memories (Fallback)\",\n results: longTerm,\n sectionBuckets,\n retrievalQuery,\n sessionKey,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n });\n recalledMemoryIds = this.extractMemoryIdsFromResults(longTerm);\n recalledMemoryPaths = longTerm\n .map((result) => result.path)\n .filter(Boolean);\n impressionRecorded = true;\n }\n }\n }\n\n if (isDisagreementPrompt(prompt)) {\n this.appendRecallSection(\n sectionBuckets,\n \"memories\",\n [\n \"## Retrieval Feedback Helper\",\n \"\",\n \"The user may be disputing an answer. To debug whether retrieval misled the response:\",\n \"- Use tool `memory_last_recall` to see which memory IDs were injected into context.\",\n \"- Use tool `memory_intent_debug` to inspect the planner mode decision and graph fallback reason.\",\n \"- If graph recall is enabled, use `memory_graph_explain_last_recall` to inspect seed/expanded graph paths.\",\n \"- If negative examples are enabled, you can use `memory_feedback_last_recall` to mark specific recalled IDs as not useful.\",\n \"\",\n \"Safety: do not mass-mark negatives automatically; prefer explicit IDs.\",\n ].join(\"\\n\"),\n );\n }\n }\n\n const phase2AfterQmdMs = Date.now() - recallStart;\n if (shouldPersistGraphSnapshot) {\n if (!graphSnapshotStatus) {\n graphSnapshotStatus = \"skipped\";\n }\n if (!graphSnapshotReason) {\n graphSnapshotReason = qmdAvailable\n ? \"graph recall skipped before expansion\"\n : \"graph recall skipped because QMD was unavailable\";\n }\n if (graphDecisionStatus === \"not_requested\") {\n graphDecisionStatus = graphSnapshotStatus;\n }\n if (!graphDecisionReason) {\n graphDecisionReason = graphSnapshotReason;\n }\n await this.recordLastGraphRecallSnapshot({\n storage: profileStorage,\n prompt: retrievalQuery,\n recallMode,\n recallNamespaces,\n seedPaths: graphSnapshotSeedPaths,\n expandedPaths: graphSnapshotExpandedPaths,\n status: graphSnapshotStatus,\n reason: graphSnapshotReason,\n shadowMode: graphDecisionShadowMode,\n queryIntent,\n seedResults: graphSnapshotSeedResults,\n finalResults: graphSnapshotFinalResults,\n shadowComparison: graphSnapshotShadowComparison,\n });\n }\n await this.recordLastIntentSnapshot({\n storage: profileStorage,\n snapshot: buildIntentDebugSnapshot(),\n });\n\n // 2.5. Compression guideline recall section (v8.11 Task 5)\n if (\n this.isRecallSectionEnabled(\n \"compression-guidelines\",\n this.config.compressionGuidelineLearningEnabled === true,\n )\n ) {\n const compressionGuidelineSection =\n await this.buildCompressionGuidelineRecallSection();\n if (compressionGuidelineSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compression-guidelines\",\n compressionGuidelineSection,\n );\n }\n }\n\n // 3. Transcript/summaries/conversation/compounding are fetched in parallel above,\n // then assembled here according to recallPipeline order.\n if (transcriptSection) {\n this.appendRecallSection(sectionBuckets, \"transcript\", transcriptSection);\n }\n // Compaction reset context — independent section so it works even when transcript is disabled.\n if (compactionSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compaction-reset\",\n compactionSection,\n );\n }\n if (summariesSection) {\n this.appendRecallSection(sectionBuckets, \"summaries\", summariesSection);\n }\n if (conversationRecallSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"conversation-recall\",\n conversationRecallSection,\n );\n }\n const compoundingSection = await awaitEnrichmentSection(\n \"compounding\",\n compoundingPromise,\n );\n if (compoundingSection) {\n this.appendRecallSection(\n sectionBuckets,\n \"compounding\",\n compoundingSection,\n );\n }\n\n // 5. Inject most relevant question (if enabled) (existing)\n if (\n this.config.injectQuestions &&\n this.isRecallSectionEnabled(\"questions\", true)\n ) {\n const questions = await profileStorage.readQuestions({\n unresolvedOnly: true,\n });\n if (questions.length > 0) {\n // Find the most relevant question to the current prompt\n // Simple approach: use the highest-priority unresolved question\n // TODO: Could use QMD search to find the most contextually relevant one\n const topQuestion = questions[0]; // Already sorted by priority desc\n this.appendRecallSection(\n sectionBuckets,\n \"questions\",\n `## Open Question\\n\\nSomething I've been curious about: ${topQuestion.question}\\n\\n_Context: ${topQuestion.context}_`,\n );\n }\n }\n\n const phase2QuestionsDoneMs = Date.now() - recallStart;\n const finalizedQueryAwarePrefilter = await queryAwarePrefilterPromise;\n const phase2QapDoneMs = Date.now() - recallStart;\n throwIfRecallAborted(options.abortSignal);\n if (\n timings.queryAware &&\n finalizedQueryAwarePrefilter.candidatePaths?.size\n ) {\n const helpedCount = recalledMemoryPaths.filter((memoryPath) =>\n finalizedQueryAwarePrefilter.candidatePaths?.has(memoryPath),\n ).length;\n timings.queryAware = `${timings.queryAware};helped=${helpedCount}`;\n }\n\n // --- Timing summary ---\n timings.total = `${Date.now() - recallStart}ms`;\n this.profiler.endSpan(\"assembly\", profileTraceId);\n log.info(\n `recall phase-2 checkpoints: afterQmd=${phase2AfterQmdMs}ms, afterQuestions=${phase2QuestionsDoneMs}ms, afterQap=${phase2QapDoneMs}ms`,\n );\n const timingParts = Object.entries(timings)\n .map(([k, v]) => `${k}=${v}`)\n .join(\", \");\n log.info(`recall timings: ${timingParts}`);\n\n const assembledRecall = this.assembleRecallSections(\n sectionBuckets,\n options.budgetCharsOverride,\n );\n const context =\n assembledRecall.sections.length === 0\n ? \"\"\n : assembledRecall.sections.join(\"\\n\\n---\\n\\n\");\n const sourcesUsed = this.collectLastRecallSources(\n sectionBuckets,\n recallSource,\n );\n const budgetsApplied = this.buildLastRecallBudgetSummary({\n requestedTopK,\n recallResultLimit,\n qmdFetchLimit,\n qmdHybridFetchLimit,\n finalContextChars: assembledRecall.finalChars,\n truncated: assembledRecall.truncated,\n includedSections: assembledRecall.includedIds,\n omittedSections: assembledRecall.omittedIds,\n });\n\n // X-ray capture (issue #570 PR 1). Only fires when the caller\n // explicitly opts in via `xrayCapture: true`. No behavior change\n // when the flag is absent — this branch and the setter both\n // short-circuit. Captured data is composed from values we have\n // already derived above, so capture cost is a single object\n // allocation; no new recall work is performed.\n //\n // Skip capture when the caller has already aborted this recall —\n // otherwise a canceled call could clobber a prior successful\n // capture that the capturing caller has not yet read back\n // (issue #570 PR 1 review follow-up).\n if (\n options.xrayCapture === true &&\n !options.abortSignal?.aborted\n ) {\n try {\n const servedBy = mapRecallSourceToXrayServedBy(recallSource);\n // Derive xray results from `recalledMemoryPaths` as the single\n // source of truth — `recalledMemoryIds` and `recalledMemoryPaths`\n // are built with two independent filters upstream\n // (`extractMemoryIdsFromResults` drops paths whose filename does\n // not match `*.md`, while `.map(path).filter(Boolean)` drops\n // empty paths only), so zipping them positionally would silently\n // misalign when the two filters differ. Re-deriving `memoryId`\n // from the path here guarantees `memoryId` and `path` refer to\n // the same underlying result.\n const idFromPath = (p: string): string | null => {\n const match = p.match(/([^/]+)\\.md$/);\n return match ? match[1] ?? null : null;\n };\n const results: RecallXrayResult[] = [];\n for (const recalledPath of recalledMemoryPaths) {\n const derivedId = idFromPath(recalledPath);\n if (!derivedId) continue;\n results.push({\n memoryId: derivedId,\n path: recalledPath,\n servedBy,\n scoreDecomposition: { final: 0 },\n admittedBy: [],\n });\n }\n // `considered` must reflect the pool size of the branch that\n // actually produced the admitted results, NOT the max across\n // every branch that ran. Otherwise a flow where hot_qmd\n // assembled a large pool that was killed by the confidence\n // gate and a different branch (or none) ultimately served\n // the recall would report hot_qmd's pool as \"considered\" —\n // incorrectly attributing those drops to the result limit.\n // Pick the pool by `recallSource`; fall back to\n // `recalledMemoryCount` when no branch ran (e.g. every branch\n // returned zero). This path never runs for `no_recall` —\n // that branch captures its own snapshot earlier.\n let xrayConsidered: number;\n switch (recallSource) {\n case \"hot_qmd\":\n xrayConsidered = xrayBranchPoolSize.hot_qmd;\n break;\n case \"hot_embedding\":\n xrayConsidered = xrayBranchPoolSize.hot_embedding;\n break;\n case \"cold_fallback\":\n xrayConsidered = xrayColdPoolSink.size;\n break;\n case \"recent_scan\":\n xrayConsidered = xrayBranchPoolSize.recent_scan;\n break;\n case \"none\":\n xrayConsidered = recalledMemoryCount;\n break;\n default: {\n // Compile-time guard: adding a new `recallSource` value\n // must force this switch to be updated.\n const _exhaustive: never = recallSource;\n void _exhaustive;\n xrayConsidered = recalledMemoryCount;\n }\n }\n // `considered` must never be less than `admitted` — in degenerate\n // flows where a branch's pool counter missed an assignment, prefer\n // the admitted count as the floor so the trace stays self-consistent.\n xrayConsidered = Math.max(xrayConsidered, recalledMemoryIds.length);\n const filters: RecallFilterTrace[] = [\n {\n name: \"recall-result-limit\",\n considered: xrayConsidered,\n admitted: recalledMemoryIds.length,\n },\n ];\n this.lastXraySnapshot = buildXraySnapshot({\n query: retrievalQuery,\n tierExplain: null,\n results,\n filters,\n budget: {\n chars: this.getRecallBudgetChars(options.budgetCharsOverride),\n used: assembledRecall.finalChars,\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 failed: ${err}`);\n }\n }\n\n if (sessionKey) {\n throwIfRecallAborted(options.abortSignal);\n this.lastRecall\n .record({\n sessionKey,\n query: retrievalQuery,\n memoryIds: recalledMemoryIds,\n namespace: selfNamespace,\n traceId,\n plannerMode: recallMode,\n requestedMode,\n source: recallSource,\n fallbackUsed: recallSource !== \"none\" && recallSource !== \"hot_qmd\",\n sourcesUsed,\n budgetsApplied,\n latencyMs: Date.now() - recallStart,\n resultPaths: recalledMemoryPaths,\n policyVersion,\n appendImpression:\n impressionRecorded ||\n recalledMemoryIds.length > 0 ||\n this.config.recordEmptyRecallImpressions,\n identityInjection: {\n mode: identityInjectionModeUsed,\n injectedChars: identityInjectedChars,\n truncated: identityInjectionTruncated,\n },\n })\n .catch((err) => log.debug(`last recall record failed: ${err}`));\n }\n if (sessionKey) {\n this.queueEvalShadowRecall({\n traceId,\n recordedAt: new Date().toISOString(),\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n source: recallSource,\n recalledMemoryCount,\n injected: context.length > 0,\n contextChars: context.length,\n memoryIds: recalledMemoryIds,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n });\n }\n closeProfileTrace();\n this.emitTrace({\n kind: \"recall_summary\",\n traceId,\n operation: \"recall\",\n sessionKey,\n promptHash,\n promptLength: prompt.length,\n retrievalQueryHash,\n retrievalQueryLength: retrievalQuery.length,\n recallMode,\n recallResultLimit,\n qmdEnabled: this.config.qmdEnabled,\n qmdAvailable: this.qmd.isAvailable(),\n recallNamespaces,\n source: recallSource,\n recalledMemoryCount,\n injected: context.length > 0,\n contextChars: context.length,\n policyVersion,\n identityInjectionMode: identityInjectionModeUsed,\n identityInjectedChars,\n identityInjectionTruncated,\n durationMs: Date.now() - recallStart,\n timings: { ...timings },\n recalledContent:\n this.config.traceRecallContent && context.length > 0\n ? context\n : undefined,\n });\n\n return context;\n } finally {\n closeProfileTrace();\n }\n }\n\n async processTurn(\n role: \"user\" | \"assistant\",\n content: string,\n sessionKey?: string,\n options: {\n bufferKey?: string;\n logicalSessionKey?: string;\n providerThreadId?: string | null;\n turnFingerprint?: string;\n persistProcessedFingerprint?: boolean;\n } = {},\n ): Promise<void> {\n if (role !== \"user\" && role !== \"assistant\") {\n log.debug(`processTurn: ignoring unsupported role=${String(role)}`);\n return;\n }\n if (shouldSkipImplicitExtraction(this.config)) {\n log.debug(\n \"processTurn: skipping implicit extraction because captureMode=explicit\",\n );\n return;\n }\n\n const bufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : typeof sessionKey === \"string\" && sessionKey.length > 0\n ? sessionKey\n : \"default\";\n const turn: BufferTurn = {\n role,\n content,\n timestamp: new Date().toISOString(),\n sessionKey,\n logicalSessionKey: options.logicalSessionKey ?? bufferKey,\n providerThreadId: options.providerThreadId ?? null,\n turnFingerprint: options.turnFingerprint,\n persistProcessedFingerprint: options.persistProcessedFingerprint === true,\n };\n\n const decision = await this.buffer.addTurn(bufferKey, turn);\n\n if (decision === \"keep_buffering\") return;\n await this.queueBufferedExtraction(\n this.buffer.getTurns(bufferKey),\n \"trigger_mode\",\n { bufferKey },\n );\n }\n\n async flushSession(\n sessionKey: string,\n options: {\n reason: string;\n abortSignal?: AbortSignal;\n bufferKey?: string;\n },\n ): Promise<void> {\n const explicitBufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : null;\n const discoveredBufferKeys =\n explicitBufferKey ||\n typeof sessionKey !== \"string\" ||\n sessionKey.length === 0 ||\n typeof this.buffer.findBufferKeysForSession !== \"function\"\n ? []\n : await this.buffer.findBufferKeysForSession(sessionKey);\n const bufferKeys = explicitBufferKey\n ? [explicitBufferKey]\n : discoveredBufferKeys.length > 0\n ? discoveredBufferKeys\n : typeof sessionKey === \"string\" && sessionKey.length > 0\n ? [sessionKey]\n : [\"default\"];\n for (const bufferKey of bufferKeys) {\n const turns = this.buffer.getTurns(bufferKey);\n if (turns.length === 0) continue;\n await new Promise<void>((resolve, reject) => {\n void this\n .queueBufferedExtraction(turns, \"trigger_mode\", {\n bufferKey,\n clearBufferAfterExtraction: true,\n skipDedupeCheck: true,\n abortSignal: options.abortSignal,\n onTaskSettled: (error) => (error ? reject(error) : resolve()),\n })\n .catch(reject);\n });\n }\n }\n\n async ingestReplayBatch(\n turns: ReplayTurn[],\n options: { deadlineMs?: number } = {},\n ): Promise<void> {\n if (!Array.isArray(turns) || turns.length === 0) return;\n if (shouldSkipImplicitExtraction(this.config)) {\n log.debug(\n \"ingestReplayBatch: skipping implicit extraction because captureMode=explicit\",\n );\n return;\n }\n\n const bySession = new Map<string, BufferTurn[]>();\n for (const turn of turns) {\n if (turn.role !== \"user\" && turn.role !== \"assistant\") continue;\n const key = normalizeReplaySessionKey(turn.sessionKey);\n const list = bySession.get(key) ?? [];\n list.push({\n role: turn.role,\n content: turn.content,\n timestamp: turn.timestamp,\n sessionKey: key,\n });\n bySession.set(key, list);\n }\n\n const replayTasks: Array<Promise<void>> = [];\n for (const [key, sessionTurns] of bySession.entries()) {\n if (sessionTurns.length === 0) continue;\n replayTasks.push(\n new Promise<void>((resolve, reject) => {\n void this.queueBufferedExtraction(sessionTurns, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n bufferKey: key,\n extractionDeadlineMs: options.deadlineMs,\n onTaskSettled: (err) => (err ? reject(err) : resolve()),\n }).catch(reject);\n }),\n );\n }\n if (replayTasks.length > 0) {\n const settled = await Promise.allSettled(replayTasks);\n const firstRejected = settled.find(\n (result): result is PromiseRejectedResult =>\n result.status === \"rejected\",\n );\n if (firstRejected) {\n throw firstRejected.reason;\n }\n }\n }\n\n /**\n * Return the namespace that `ingestBulkImportBatch` writes into (#460).\n *\n * Exposed so host CLIs can snapshot the same storage root that extraction\n * actually writes to, avoiding the \"CLI counts files at namespace A while\n * writes land in namespace B\" footgun that a naïve\n * `config.defaultNamespace` snapshot could hit when a namespace policy\n * named `\"default\"` also exists.\n *\n * Today bulk-import is pinned to `config.defaultNamespace`; future\n * per-invocation namespace routing would thread an explicit target here\n * and through `ingestBulkImportBatch`.\n */\n bulkImportWriteNamespace(): string {\n return this.config.defaultNamespace;\n }\n\n /**\n * Ingest a batch of bulk-import turns (#460). Like ingestReplayBatch, this\n * normalizes user/assistant turns into the extraction buffer and awaits\n * settlement, but it intentionally bypasses the captureMode=\"explicit\"\n * gate because bulk-import is itself an explicit user action — the user\n * ran `bulk-import --source <name> --file ...` and would be surprised to\n * see the command silently no-op when capture is otherwise restricted.\n *\n * Turns with role=\"other\" are skipped (not supported by the extraction\n * pipeline).\n *\n * Two design decisions worth calling out:\n *\n * - **sessionKey is truthy and per-batch-unique.**\n * `ThreadingManager.shouldStartNewThread` only applies the session-key\n * boundary check when `turn.sessionKey` is truthy (threading.ts:82);\n * with an empty string, imported turns could attach to the current\n * live thread or merge across unrelated import batches. A unique\n * `bulk-import:batch:<timestamp>-<rand>` key forces a fresh thread per\n * batch without matching common prefix/map rules in\n * `principalFromSessionKeyRules`. (Catch-all regex rules could still\n * remap the principal, but that only affects metadata provenance —\n * see the next point for why write routing is unaffected.)\n *\n * - **writeNamespaceOverride pins the storage target.**\n * We pass `writeNamespaceOverride: this.bulkImportWriteNamespace()` to\n * `queueBufferedExtraction`, which tells `runExtraction` to skip\n * `defaultNamespaceForPrincipal` and write directly into the\n * orchestrator's declared bulk-import write namespace. This keeps\n * writes deterministic even when namespace policies named `\"default\"`\n * exist alongside a different `config.defaultNamespace`, and also\n * guards against regex-catch-all principal rules steering bulk-import\n * into an unexpected tenant.\n *\n * Per-invocation namespace routing (letting callers target a namespace\n * other than `bulkImportWriteNamespace()`) is a separate feature tracked\n * as a follow-up — the hook is the `writeNamespaceOverride` option, but\n * the CLI surface does not yet expose a `--namespace` flag.\n */\n async ingestBulkImportBatch(\n turns: ImportTurn[],\n options: {\n deadlineMs?: number;\n } = {},\n ): Promise<void> {\n if (!Array.isArray(turns) || turns.length === 0) return;\n\n // Per-batch unique sessionKey keeps threading honest without matching\n // typical prefix/map routing rules. Combined with writeNamespaceOverride\n // below, the storage target is independent of principal resolution.\n // Uses crypto.randomBytes (not Math.random) so CodeQL does not flag a\n // security-context insecure-randomness use even though this value never\n // leaves the process; the bytes just need to be collision-resistant\n // across concurrent bulk-import batches.\n const sessionKey =\n `bulk-import:batch:${Date.now().toString(36)}-` +\n randomBytes(6).toString(\"hex\");\n\n const sessionTurns: BufferTurn[] = [];\n for (const turn of turns) {\n if (turn.role !== \"user\" && turn.role !== \"assistant\") continue;\n sessionTurns.push({\n role: turn.role,\n content: turn.content,\n timestamp: turn.timestamp,\n sessionKey,\n });\n }\n if (sessionTurns.length === 0) return;\n\n await new Promise<void>((resolve, reject) => {\n void this.queueBufferedExtraction(sessionTurns, \"trigger_mode\", {\n skipDedupeCheck: true,\n clearBufferAfterExtraction: false,\n skipCharThreshold: true,\n bufferKey: sessionKey,\n extractionDeadlineMs: options.deadlineMs,\n writeNamespaceOverride: this.bulkImportWriteNamespace(),\n onTaskSettled: (err) => (err ? reject(err) : resolve()),\n }).catch(reject);\n });\n }\n\n async observeSessionHeartbeat(\n sessionKey: string,\n options: { bufferKey?: string } = {},\n ): Promise<void> {\n if (this.config.sessionObserverEnabled !== true) return;\n if (!sessionKey || sessionKey.length === 0) return;\n\n const bufferKey =\n typeof options.bufferKey === \"string\" && options.bufferKey.length > 0\n ? options.bufferKey\n : sessionKey;\n const previous =\n this.heartbeatObserverChains.get(sessionKey) ?? Promise.resolve();\n const next = previous\n .catch(() => undefined)\n .then(async () => {\n const turns = this.buffer.getTurns(bufferKey);\n if (turns.length === 0) return;\n const normalizedSessionKey = normalizeReplaySessionKey(sessionKey);\n const allowSharedSessionBuffer = bufferKey.startsWith(\n CODEX_THREAD_KEY_PREFIX,\n );\n if (\n !allowSharedSessionBuffer &&\n turns.some(\n (turn) =>\n turn.sessionKey &&\n normalizeReplaySessionKey(turn.sessionKey) !== normalizedSessionKey,\n )\n ) {\n log.debug(\n `heartbeat observer skipped: mixed-session buffer contents for ${bufferKey}`,\n );\n return;\n }\n if (!this.shouldQueueExtraction(turns, {\n commit: false,\n bufferKey,\n })) {\n log.debug(\n `heartbeat observer skipped: extraction dedupe for ${bufferKey}`,\n );\n return;\n }\n const footprint =\n await this.transcript.estimateSessionFootprint(sessionKey);\n const decision = await this.sessionObserver.observe({\n sessionKey,\n totalBytes: footprint.bytes,\n totalTokens: footprint.tokens,\n });\n if (!decision.triggered) return;\n log.debug(\n `heartbeat observer trigger: session=${sessionKey} deltaBytes=${decision.deltaBytes} deltaTokens=${decision.deltaTokens}`,\n );\n await this.queueBufferedExtraction(turns, \"heartbeat_observer\", {\n bufferKey,\n });\n });\n\n this.heartbeatObserverChains.set(sessionKey, next);\n try {\n await next;\n } finally {\n if (this.heartbeatObserverChains.get(sessionKey) === next) {\n this.heartbeatObserverChains.delete(sessionKey);\n }\n }\n }\n\n private async queueBufferedExtraction(\n turnsToExtract: BufferTurn[],\n reason: \"trigger_mode\" | \"heartbeat_observer\",\n options: {\n skipDedupeCheck?: boolean;\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n extractionDeadlineMs?: number;\n onTaskSettled?: (error?: unknown) => void;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n /**\n * Explicit namespace override for the write path (#460). When set,\n * `runExtraction` writes to this namespace instead of deriving one\n * from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.\n * Used by bulk-import to pin writes to a deterministic namespace\n * regardless of user-configured principal routing rules.\n */\n writeNamespaceOverride?: string;\n } = {},\n ): Promise<void> {\n const bufferKey = options.bufferKey ?? turnsToExtract[0]?.sessionKey ?? \"default\";\n if (\n !options.skipDedupeCheck &&\n !this.shouldQueueExtraction(turnsToExtract, { bufferKey })\n ) {\n log.debug(`extraction dedupe skip: preserving buffer (${reason})`);\n options.onTaskSettled?.();\n return;\n }\n\n this.extractionQueue.push(async () => {\n try {\n await this.runExtraction(turnsToExtract, {\n clearBufferAfterExtraction:\n options.clearBufferAfterExtraction ?? true,\n skipCharThreshold: options.skipCharThreshold ?? false,\n deadlineMs: options.extractionDeadlineMs,\n bufferKey,\n abortSignal: options.abortSignal,\n writeNamespaceOverride: options.writeNamespaceOverride,\n });\n options.onTaskSettled?.();\n } catch (err) {\n options.onTaskSettled?.(err);\n throw err;\n }\n });\n\n if (!this.queueProcessing) {\n this.queueProcessing = true;\n this.processQueue().catch((err) => {\n this.logExtractionQueueFailure(err, \"processor\");\n this.queueProcessing = false;\n });\n }\n log.debug(`queued extraction from ${reason}`);\n }\n\n private normalizeExtractionFingerprintTurns(turns: BufferTurn[]): string[] {\n if (!Array.isArray(turns) || turns.length === 0) return [];\n return turns\n .filter((turn) => turn.role === \"user\" || turn.role === \"assistant\")\n .map((turn) => {\n if (\n typeof turn.turnFingerprint === \"string\" &&\n turn.turnFingerprint.length > 0\n ) {\n return `fp:${turn.turnFingerprint}`;\n }\n return `${turn.role}:${(turn.content ?? \"\").replace(/\\s+/g, \" \").trim().slice(0, this.config.extractionMaxTurnChars)}`;\n })\n .filter((value) => value.length > 0);\n }\n\n private buildExtractionFingerprint(\n turns: BufferTurn[],\n bufferKey: string,\n ): string | null {\n const normalized = this.normalizeExtractionFingerprintTurns(turns).join(\"\\n\");\n if (!normalized) return null;\n return createHash(\"sha256\")\n .update(`${bufferKey}\\n${normalized}`)\n .digest(\"hex\");\n }\n\n private shouldQueueExtraction(\n turns: BufferTurn[],\n options: { commit?: boolean; bufferKey?: string } = {},\n ): boolean {\n if (!this.config.extractionDedupeEnabled) return true;\n if (!Array.isArray(turns) || turns.length === 0) return false;\n\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const fingerprint = this.buildExtractionFingerprint(turns, bufferKey);\n if (!fingerprint) return false;\n const now = Date.now();\n const seenAt = this.recentExtractionFingerprints.get(fingerprint);\n if (seenAt && now - seenAt < this.config.extractionDedupeWindowMs) {\n log.debug(\"extraction dedupe: skipped duplicate buffered turn set\");\n return false;\n }\n\n if (options.commit !== false) {\n this.recentExtractionFingerprints.set(fingerprint, now);\n }\n // Keep this cache bounded to avoid unbounded growth.\n if (\n options.commit !== false &&\n this.recentExtractionFingerprints.size > 200\n ) {\n const entries = Array.from(\n this.recentExtractionFingerprints.entries(),\n ).sort((a, b) => a[1] - b[1]);\n for (const [key] of entries.slice(0, entries.length - 200)) {\n this.recentExtractionFingerprints.delete(key);\n }\n }\n\n return true;\n }\n\n /**\n * Background serial queue processor.\n * Processes extractions one at a time to avoid race conditions.\n * Called automatically when items are queued.\n */\n private async processQueue(): Promise<void> {\n while (this.extractionQueue.length > 0) {\n const task = this.extractionQueue.shift();\n if (task) {\n try {\n await task();\n } catch (err) {\n this.logExtractionQueueFailure(err, \"task\");\n }\n }\n }\n\n this.queueProcessing = false;\n }\n\n /**\n * Classify + log a failure from either the per-task catch inside\n * `processQueue()` or the outer `processQueue().catch(...)` in\n * `queueBufferedExtraction()`. Issue #549: `throwIfRecallAborted`\n * (used throughout `runExtraction`) raises an Error whose `name` is\n * `\"AbortError\"`. That path fires when `before_reset` aborts a\n * queued task to avoid duplicate extraction — it is intentional\n * cancellation, not a failure. Downgrading the log to debug\n * prevents spurious `error`-level lines that routinely appear\n * right next to a successful `persisted: N facts, M entities` log\n * and that confuse operators into thinking extraction is broken.\n * Genuine extraction failures (network, parse, I/O) still log at\n * `error`.\n *\n * Source differentiates the two call sites so the log message\n * names the right layer (`task` vs `processor`).\n */\n private logExtractionQueueFailure(\n err: unknown,\n source: \"task\" | \"processor\",\n ): void {\n const aborted =\n source === \"task\"\n ? \"background extraction task aborted (session transition)\"\n : \"background extraction queue processor aborted (session transition)\";\n const failed =\n source === \"task\"\n ? \"background extraction task failed\"\n : \"background extraction queue processor failed\";\n if (isAbortError(err)) {\n log.debug(aborted);\n } else {\n log.error(failed, err);\n }\n }\n\n private async runExtraction(\n turns: BufferTurn[],\n options: {\n clearBufferAfterExtraction?: boolean;\n skipCharThreshold?: boolean;\n deadlineMs?: number;\n bufferKey?: string;\n abortSignal?: AbortSignal;\n /**\n * Explicit namespace override for the write path (#460). When set,\n * extraction writes go to this namespace instead of the one derived\n * from `defaultNamespaceForPrincipal(resolvePrincipal(sessionKey))`.\n * The resolved `principal` is still threaded into memory metadata\n * for provenance; only the storage target is overridden.\n */\n writeNamespaceOverride?: string;\n } = {},\n ): Promise<void> {\n log.debug(`running extraction on ${turns.length} turns`);\n const clearBufferAfterExtraction =\n options.clearBufferAfterExtraction ?? true;\n const skipCharThreshold = options.skipCharThreshold ?? false;\n const deadlineMs =\n typeof options.deadlineMs === \"number\" &&\n Number.isFinite(options.deadlineMs)\n ? options.deadlineMs\n : undefined;\n const bufferKey = options.bufferKey ?? turns[0]?.sessionKey ?? \"default\";\n const throwIfDeadlineExceeded = (stage: string): void => {\n if (typeof deadlineMs === \"number\" && Date.now() > deadlineMs) {\n throw new Error(`replay extraction deadline exceeded (${stage})`);\n }\n };\n const throwIfAborted = (stage: string): void => {\n throwIfRecallAborted(options.abortSignal, `extraction aborted (${stage})`);\n };\n const clearBuffer = async (options?: { ignoreAbort?: boolean }) => {\n if (options?.ignoreAbort !== true) {\n throwIfAborted(\"before_clear_buffer\");\n }\n if (clearBufferAfterExtraction) {\n await this.buffer.clearAfterExtraction(bufferKey);\n }\n };\n\n // Skip extraction for cron job sessions - these are system operations, not user conversations\n const sessionKey = turns[0]?.sessionKey ?? \"\";\n if (sessionKey.includes(\":cron:\")) {\n log.debug(`skipping extraction for cron session: ${sessionKey}`);\n await clearBuffer();\n return;\n }\n\n const normalizedTurns = turns\n .filter(\n (t) =>\n (t.role === \"user\" || t.role === \"assistant\") &&\n typeof t.content === \"string\",\n )\n .map((t) => ({\n ...t,\n content: t.content.trim().slice(0, this.config.extractionMaxTurnChars),\n }))\n .filter((t) => t.content.length > 0);\n throwIfDeadlineExceeded(\"before_extract\");\n throwIfAborted(\"before_extract\");\n\n const userTurns = normalizedTurns.filter((t) => t.role === \"user\");\n const totalChars = normalizedTurns.reduce(\n (sum, t) => sum + t.content.length,\n 0,\n );\n const belowCharThreshold = totalChars < this.config.extractionMinChars;\n const belowUserTurnThreshold =\n userTurns.length < this.config.extractionMinUserTurns;\n if ((!skipCharThreshold && belowCharThreshold) || belowUserTurnThreshold) {\n log.debug(\n `skipping extraction: below threshold (totalChars=${totalChars}, userTurns=${userTurns.length})`,\n );\n await clearBuffer();\n return;\n }\n\n const principal = resolvePrincipal(sessionKey, this.config);\n // Write path — overlay the coding-agent namespace (issue #569) when the\n // session has a codingContext and `codingMode.projectScope` is true.\n // Explicit `writeNamespaceOverride` from callers still wins, matching\n // pre-#569 semantics.\n const selfNamespace =\n typeof options.writeNamespaceOverride === \"string\" &&\n options.writeNamespaceOverride.length > 0\n ? options.writeNamespaceOverride\n : this.applyCodingNamespaceOverlay(\n sessionKey,\n defaultNamespaceForPrincipal(principal, this.config),\n );\n const storage = await this.storageRouter.storageFor(selfNamespace);\n const shouldPersistProcessedFingerprint = normalizedTurns.some(\n (turn) => turn.persistProcessedFingerprint === true,\n );\n const extractionFingerprint = this.buildExtractionFingerprint(\n normalizedTurns,\n bufferKey,\n );\n let meta =\n extractionFingerprint && shouldPersistProcessedFingerprint\n ? await storage.loadMeta()\n : null;\n if (\n extractionFingerprint &&\n shouldPersistProcessedFingerprint &&\n (meta?.processedExtractionFingerprints ?? []).some(\n (entry) => entry.fingerprint === extractionFingerprint,\n )\n ) {\n log.debug(\n `runExtraction: skipping already-processed extraction fingerprint for ${bufferKey}`,\n );\n await clearBuffer();\n return;\n }\n\n // Pass existing entity names so the LLM can reuse them instead of inventing variants\n const existingEntities = await storage.listEntityNames();\n const result = await raceRecallAbort(\n this.extraction.extract(\n normalizedTurns,\n existingEntities,\n ),\n options.abortSignal,\n \"extraction aborted (during_extract)\",\n );\n throwIfDeadlineExceeded(\"before_persist\");\n throwIfAborted(\"before_persist\");\n\n // Defensive: validate extraction result before processing\n if (!result) {\n log.warn(\"runExtraction: extraction returned null/undefined\");\n await clearBuffer();\n return;\n }\n if (!Array.isArray(result.facts)) {\n log.warn(\n \"runExtraction: extraction returned invalid facts (not an array)\",\n { factsType: typeof result.facts, resultKeys: Object.keys(result) },\n );\n await clearBuffer();\n return;\n }\n if (\n result.facts.length === 0 &&\n result.entities.length === 0 &&\n result.questions.length === 0 &&\n result.profileUpdates.length === 0\n ) {\n log.debug(\n \"runExtraction: extraction produced no durable outputs; skipping persistence\",\n );\n await clearBuffer();\n return;\n }\n\n let threadIdForExtraction: string | null = null;\n if (this.config.threadingEnabled && turns.length > 0) {\n const lastTurn = turns[turns.length - 1];\n try {\n threadIdForExtraction = await this.threading.processTurn(lastTurn, []);\n } catch (err) {\n // Fail-open: threading errors must not block memory persistence.\n log.warn(\n \"[threading] processTurn failed before persistence (non-fatal)\",\n err,\n );\n }\n }\n\n const persistedIds = await this.persistExtraction(\n result,\n storage,\n threadIdForExtraction,\n { sessionKey, principal },\n );\n meta ??= await storage.loadMeta();\n if (extractionFingerprint && shouldPersistProcessedFingerprint) {\n try {\n await this.recordProcessedExtractionFingerprint(\n storage,\n extractionFingerprint,\n meta,\n );\n } catch (error) {\n log.warn(\n \"runExtraction: failed to persist processed extraction fingerprint; continuing with buffer clear\",\n error,\n );\n }\n }\n // Persist extraction counters and processed fingerprints before running\n // follow-on helpers so replay dedupe survives any later non-essential\n // failure. If this aggregate meta write fails, still clear the buffer:\n // the durable memories are already written and replaying the same turns\n // would duplicate them.\n meta.extractionCount += 1;\n meta.lastExtractionAt = new Date().toISOString();\n meta.totalMemories += Array.isArray(result?.facts)\n ? result.facts.length\n : 0;\n meta.totalEntities += Array.isArray(result?.entities)\n ? result.entities.length\n : 0;\n let postPersistMetaError: unknown;\n try {\n await storage.saveMeta(meta);\n } catch (error) {\n postPersistMetaError = error;\n }\n\n // Buffer retention for defer verdicts (issue #562, PR 2). When the judge\n // deferred at least one candidate, retain the tail of the current turn\n // window so the next extraction pass has the surrounding context that\n // may disambiguate the deferred fact. Non-defer runs clear the slot.\n //\n // Gated on:\n // - `clearBufferAfterExtraction` — replay / bulk-import paths call\n // `runExtraction` with this false and do not operate on live buffer\n // state. Writing retention there would create synthetic buffer\n // entries and cross-contaminate future live extractions.\n // - NOT `extractionJudgeShadow` — in shadow mode the judge is only\n // advisory; facts are still persisted regardless of verdict, so\n // retaining the turn window on top of a persisted write would both\n // waste buffer space and cause the same facts to re-enter the\n // pipeline on the next pass.\n try {\n if (\n clearBufferAfterExtraction &&\n !this.config.extractionJudgeShadow\n ) {\n const deferredCount = this.lastPersistExtractionDeferredCount;\n if (deferredCount > 0 && normalizedTurns.length > 0) {\n await this.buffer.retainDeferredTurns(\n bufferKey,\n normalizedTurns as BufferTurn[],\n 10,\n );\n } else {\n await this.buffer.retainDeferredTurns(bufferKey, [], 0);\n }\n }\n } catch (err) {\n // Fail-open: retention is a nice-to-have. If it fails the judge will\n // still cap deferrals and convert to reject on the next pass.\n log.debug(\n `extraction-judge: defer retention failed (non-fatal): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n\n await clearBuffer({ ignoreAbort: true });\n\n // Build memory box from this extraction (v8.0 Phase 2A)\n // Topics are derived from the current extraction's facts and entities only —\n // not from readAllMemories() — so box topics accurately reflect the current\n // session window and the call is free of expensive full-corpus I/O.\n if (this.config.memoryBoxesEnabled && persistedIds.length > 0) {\n const extractionTopics = deriveTopicsFromExtraction(result);\n // Derive episodic metadata from buffer turns (REMem-inspired)\n const firstUserTurn = turns.find((t) => t.role === \"user\");\n const boxGoal =\n firstUserTurn?.content?.slice(0, 100)?.trim() || undefined;\n await this.boxBuilderFor(storage)\n .onExtraction({\n topics: extractionTopics,\n memoryIds: persistedIds,\n timestamp: new Date().toISOString(),\n goal: boxGoal,\n })\n .catch((err) =>\n log.warn(\"[boxes] onExtraction failed (non-fatal)\", err),\n );\n }\n\n // Batch-append persisted IDs so non-fact memories (entities/questions) are\n // always attached to the thread.\n if (\n this.config.threadingEnabled &&\n threadIdForExtraction &&\n persistedIds.length > 0\n ) {\n try {\n await this.threading.appendEpisodeIds(\n threadIdForExtraction,\n persistedIds,\n );\n } catch (err) {\n log.warn(\n \"[threading] appendEpisodeIds failed after persistence (non-fatal)\",\n err,\n );\n }\n }\n\n // Thread title update for the already-established thread context.\n if (this.config.threadingEnabled && threadIdForExtraction) {\n const conversationContent = turns.map((t) => t.content).join(\" \");\n await this.threading.updateThreadTitle(\n threadIdForExtraction,\n conversationContent,\n );\n }\n\n // Check if consolidation is needed (debounced + non-zero gated).\n const nonZeroExtraction =\n result.facts.length > 0 ||\n result.entities.length > 0 ||\n result.questions.length > 0 ||\n result.profileUpdates.length > 0;\n if (nonZeroExtraction) this.nonZeroExtractionsSinceConsolidation += 1;\n this.maybeScheduleConsolidation(nonZeroExtraction);\n\n this.requestQmdMaintenance();\n await this.runTierMigrationCycle(storage, \"extraction\");\n\n if (postPersistMetaError) {\n throw postPersistMetaError;\n }\n }\n\n private async recordProcessedExtractionFingerprint(\n storage: StorageManager,\n fingerprint: string,\n preloadedMeta?: Awaited<ReturnType<StorageManager[\"loadMeta\"]>>,\n ): Promise<void> {\n const meta = preloadedMeta ?? (await storage.loadMeta());\n const observedAt = new Date().toISOString();\n const seen = new Map(\n (meta.processedExtractionFingerprints ?? []).map((entry) => [\n entry.fingerprint,\n entry.observedAt,\n ]),\n );\n seen.set(fingerprint, observedAt);\n meta.processedExtractionFingerprints = Array.from(seen.entries())\n .map(([value, at]) => ({ fingerprint: value, observedAt: at }))\n .sort((left, right) => left.observedAt.localeCompare(right.observedAt))\n .slice(-500);\n if (!preloadedMeta) {\n await storage.saveMeta(meta);\n }\n }\n\n private async runTierMigrationCycle(\n storage: StorageManager,\n trigger: \"extraction\" | \"maintenance\" | \"manual\",\n options?: {\n dryRun?: boolean;\n limitOverride?: number;\n force?: boolean;\n },\n ): Promise<TierMigrationCycleSummary> {\n const dryRun = options?.dryRun === true;\n const persistSkipped = options?.force === true || trigger === \"manual\";\n if (!this.config.qmdTierMigrationEnabled && options?.force !== true) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"tier_migration_disabled\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (\n trigger === \"maintenance\" &&\n !this.config.qmdTierAutoBackfillEnabled &&\n options?.force !== true\n ) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"maintenance_backfill_disabled\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n if (this.tierMigrationInFlight) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit: 0,\n dryRun,\n skipped: \"migration_in_flight\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const budgetTrigger = trigger === \"manual\" ? \"maintenance\" : trigger;\n const budget =\n this.compounding?.tierMigrationCycleBudget(budgetTrigger) ??\n defaultTierMigrationCycleBudget(this.config, budgetTrigger);\n const limit =\n options?.limitOverride !== undefined\n ? Math.max(0, Math.floor(options.limitOverride))\n : budget.limit;\n const nowMs = Date.now();\n if (\n options?.force !== true &&\n nowMs - this.lastTierMigrationRunAtMs < budget.minIntervalMs\n ) {\n const skipped: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit,\n dryRun,\n skipped: \"min_interval\",\n };\n if (persistSkipped) await this.tierMigrationStatus.recordCycle(skipped);\n return skipped;\n }\n\n const policy = applyUtilityPromotionRuntimePolicy(\n {\n enabled: this.config.qmdTierMigrationEnabled,\n demotionMinAgeDays: this.config.qmdTierDemotionMinAgeDays,\n demotionValueThreshold: this.config.qmdTierDemotionValueThreshold,\n promotionValueThreshold: this.config.qmdTierPromotionValueThreshold,\n },\n this.utilityRuntimeValues,\n );\n\n this.tierMigrationInFlight = true;\n try {\n const coldStorage = new StorageManager(path.join(storage.dir, \"cold\"));\n const [hotMemories, coldMemories] = await Promise.all([\n storage.readAllMemories(),\n coldStorage.readAllMemories(),\n ]);\n const now = new Date();\n const scanLimit = Math.max(0, Math.floor(budget.scanLimit));\n const hotScanLimit = Math.min(\n hotMemories.length,\n Math.ceil(scanLimit * 0.75),\n );\n const coldScanLimit = Math.min(\n coldMemories.length,\n Math.max(0, scanLimit - hotScanLimit),\n );\n const toTimestamp = (memory: MemoryFile): number =>\n Date.parse(memory.frontmatter.updated ?? memory.frontmatter.created);\n const hotCandidates = hotMemories\n .map((memory) => ({ memory, tier: \"hot\" as MemoryTier }))\n .sort((a, b) => toTimestamp(a.memory) - toTimestamp(b.memory))\n .slice(0, hotScanLimit);\n const coldCandidates = coldMemories\n .map((memory) => ({ memory, tier: \"cold\" as MemoryTier }))\n .sort((a, b) => toTimestamp(b.memory) - toTimestamp(a.memory))\n .slice(0, coldScanLimit);\n const candidates = [...hotCandidates, ...coldCandidates];\n\n const migration = new TierMigrationExecutor({\n storage,\n qmd: this.qmd,\n hotCollection: this.config.qmdCollection,\n coldCollection:\n this.config.qmdColdCollection ?? `${this.config.qmdCollection}-cold`,\n autoEmbed: this.config.qmdAutoEmbedEnabled,\n });\n\n let migrated = 0;\n let promoted = 0;\n let demoted = 0;\n for (const candidate of candidates) {\n if (migrated >= limit) break;\n const decision = decideTierTransition(\n candidate.memory,\n candidate.tier,\n policy,\n now,\n );\n if (!decision.changed) continue;\n\n if (!dryRun) {\n const res = await migration.migrateMemory({\n memory: candidate.memory,\n fromTier: candidate.tier,\n toTier: decision.nextTier,\n reason: `${trigger}:${decision.reason}`,\n });\n if (!res.changed) continue;\n }\n migrated += 1;\n if (decision.nextTier === \"cold\") demoted += 1;\n if (decision.nextTier === \"hot\") promoted += 1;\n }\n\n if (!dryRun) this.lastTierMigrationRunAtMs = Date.now();\n log.debug(\n `tier migration cycle completed: trigger=${trigger} scanned=${candidates.length} migrated=${migrated} limit=${limit}${dryRun ? \" dryRun=true\" : \"\"}`,\n );\n const summary: TierMigrationCycleSummary = {\n trigger,\n scanned: candidates.length,\n migrated,\n promoted,\n demoted,\n limit,\n dryRun,\n };\n const shouldPersistCycle = trigger === \"manual\" || migrated > 0;\n if (shouldPersistCycle)\n await this.tierMigrationStatus.recordCycle(summary);\n return summary;\n } catch (err) {\n this.lastTierMigrationRunAtMs = Date.now();\n log.warn(`tier migration cycle failed (${trigger}, fail-open): ${err}`);\n const failed: TierMigrationCycleSummary = {\n trigger,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n limit,\n dryRun,\n errorCount: 1,\n };\n await this.tierMigrationStatus.recordCycle(failed);\n return failed;\n } finally {\n this.tierMigrationInFlight = false;\n }\n }\n\n async getTierMigrationStatus(): Promise<TierMigrationStatusSnapshot> {\n return this.tierMigrationStatus.get();\n }\n\n async runTierMigrationNow(options?: {\n dryRun?: boolean;\n limit?: number;\n }): Promise<TierMigrationCycleSummary> {\n return this.runTierMigrationCycle(this.storage, \"manual\", {\n dryRun: options?.dryRun === true,\n limitOverride: options?.limit,\n force: false,\n });\n }\n\n private maybeScheduleConsolidation(nonZeroExtraction: boolean): void {\n if (this.config.consolidationRequireNonZeroExtraction && !nonZeroExtraction)\n return;\n if (\n this.nonZeroExtractionsSinceConsolidation < this.config.consolidateEveryN\n )\n return;\n\n const now = Date.now();\n if (\n now - this.lastConsolidationRunAtMs <\n this.config.consolidationMinIntervalMs\n )\n return;\n if (this.consolidationInFlight) return;\n\n this.consolidationInFlight = true;\n this.lastConsolidationRunAtMs = now;\n this.nonZeroExtractionsSinceConsolidation = 0;\n this.runConsolidation()\n .catch((err) => log.error(\"background consolidation failed\", err))\n .finally(() => {\n this.consolidationInFlight = false;\n });\n }\n\n private requestQmdMaintenance(): void {\n if (!this.qmd.isAvailable()) return;\n if (!this.config.qmdMaintenanceEnabled) return;\n\n this.qmdMaintenancePending = true;\n if (this.qmdMaintenanceTimer) return;\n\n this.qmdMaintenanceTimer = setTimeout(() => {\n this.qmdMaintenanceTimer = null;\n this.runQmdMaintenance().catch((err) =>\n log.debug(`background qmd maintenance failed: ${err}`),\n );\n }, this.config.qmdMaintenanceDebounceMs);\n }\n\n /**\n * Public entrypoint for tool-driven QMD maintenance requests.\n * Routes through existing debounced/singleflight maintenance controls.\n */\n requestQmdMaintenanceForTool(reason: string): void {\n try {\n this.requestQmdMaintenance();\n } catch (err) {\n const msg = err instanceof Error ? err.message : String(err);\n log.warn(`qmd maintenance request failed (${reason}): ${msg}`);\n }\n }\n\n private async runQmdMaintenance(): Promise<void> {\n if (this.qmdMaintenanceInFlight) return;\n if (!this.qmdMaintenancePending) return;\n this.qmdMaintenanceInFlight = true;\n this.qmdMaintenancePending = false;\n\n try {\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.updateNamespaces(\n this.configuredNamespaces(),\n );\n } else {\n await this.qmd.update();\n }\n const now = Date.now();\n if (\n this.config.qmdAutoEmbedEnabled &&\n now - this.lastQmdEmbedAtMs >= this.config.qmdEmbedMinIntervalMs\n ) {\n if (this.config.namespacesEnabled) {\n await this.namespaceSearchRouter.embedNamespaces(\n this.configuredNamespaces(),\n );\n } else {\n await this.qmd.embed();\n }\n this.lastQmdEmbedAtMs = now;\n }\n } finally {\n this.qmdMaintenanceInFlight = false;\n if (this.qmdMaintenancePending) {\n this.requestQmdMaintenance();\n }\n }\n }\n\n private async persistExtraction(\n result: ExtractionResult,\n storage: StorageManager,\n threadIdForExtraction?: string | null,\n sourceContext?: { sessionKey?: string; principal?: string },\n ): Promise<string[]> {\n // Inline source attribution (issue #369). When enabled, every extracted\n // fact is rewritten to carry a compact provenance tag inside its body so\n // the citation survives prompt injection, copy/paste, and LLM quoting.\n // The helper is a no-op when the feature flag is off, so legacy pipelines\n // see zero behavioral change.\n const citationEnabled = this.config.inlineSourceAttributionEnabled === true;\n const citationTemplate = this.config.inlineSourceAttributionFormat;\n // The stable fields (agent, session) are computed once; `ts` is intentionally\n // omitted here and added fresh per invocation so each fact in a large batch\n // gets its own insertion timestamp rather than sharing a single batch-start time.\n const citationContextBase: Omit<CitationContext, \"ts\"> = citationEnabled\n ? {\n agent: sourceContext?.principal,\n session: sourceContext?.sessionKey,\n }\n : {};\n const applyInlineCitation = (content: string): string => {\n if (!citationEnabled) return content;\n if (typeof content !== \"string\" || content.length === 0) return content;\n // Build a fresh CitationContext per call so `ts` reflects the actual\n // insertion time of each individual fact rather than the batch-start time.\n const citationContext: CitationContext = {\n ...citationContextBase,\n ts: new Date().toISOString(),\n };\n // `attachCitation` already calls `hasCitationForTemplate` internally and\n // is a no-op when the content already carries a citation (default or\n // custom template). The outer check was redundant and has been removed\n // to avoid a maintenance hazard where the two guard paths could diverge.\n return attachCitation(content, citationContext, citationTemplate);\n };\n const persistedIds: string[] = [];\n const persistedIdsByStorage = new Map<\n string,\n { storage: StorageManager; ids: string[] }\n >();\n const trackPersistedId = (\n targetStorage: StorageManager,\n id: string,\n options: { includeReturnedIds?: boolean } = {},\n ): void => {\n if (options.includeReturnedIds !== false) {\n persistedIds.push(id);\n }\n const key = targetStorage.dir;\n const existing = persistedIdsByStorage.get(key);\n if (existing) {\n existing.ids.push(id);\n return;\n }\n persistedIdsByStorage.set(key, { storage: targetStorage, ids: [id] });\n };\n let dedupedCount = 0;\n // Counter for facts skipped by the importance write-gate (issue #372).\n // Emitted via the `importance_gated` metric below and rolled into the\n // final `persisted:` log line so operators can tune the threshold.\n let importanceGatedCount = 0;\n // UUI2: short-circuit semantic dedup after first backend-unavailable signal\n // within this batch. Once any fact in the batch gets reason=\"backend_unavailable\"\n // (meaning the embedding backend is degraded), subsequent facts skip the\n // lookup entirely and proceed directly to write. This prevents N-fact batches\n // from paying N × timeout when the backend is down. The flag resets per-batch\n // (declared here, inside persistExtraction) so a transient hiccup in one\n // batch does not permanently disable dedup in future batches.\n let batchBackendUnavailable = false;\n const behaviorSignalsByStorage = new Map<\n string,\n { storage: StorageManager; events: BehaviorSignalEvent[] }\n >();\n const trackBehaviorSignals = (\n targetStorage: StorageManager,\n events: BehaviorSignalEvent[],\n ): void => {\n if (events.length === 0) return;\n const key = targetStorage.dir;\n const existing = behaviorSignalsByStorage.get(key);\n if (existing) {\n existing.events.push(...events);\n return;\n }\n behaviorSignalsByStorage.set(key, {\n storage: targetStorage,\n events: [...events],\n });\n };\n const confidenceTierOrder = [\n \"explicit\",\n \"implied\",\n \"inferred\",\n \"speculative\",\n ] as const;\n const shouldPromoteToShared = (\n targetStorage: StorageManager,\n category: string,\n confidence: number,\n ): boolean => {\n if (\n !this.config.namespacesEnabled ||\n !this.config.autoPromoteToSharedEnabled\n )\n return false;\n if (\n this.namespaceFromStorageDir(targetStorage.dir) ===\n this.config.sharedNamespace\n )\n return false;\n if (!this.config.autoPromoteToSharedCategories.includes(category as any))\n return false;\n const actualTier = confidenceTier(confidence);\n const actualRank = confidenceTierOrder.indexOf(actualTier);\n const minimumRank = confidenceTierOrder.indexOf(\n this.config.autoPromoteMinConfidenceTier,\n );\n if (actualRank === -1 || minimumRank === -1) return false;\n return actualRank <= minimumRank;\n };\n const promoteMemoryToShared = async (options: {\n sourceStorage: StorageManager;\n category: string;\n content: string;\n confidence: number;\n tags: string[];\n entityRef?: string;\n structuredAttributes?: Record<string, string>;\n sourceMemoryId: string;\n importance?: ReturnType<typeof scoreImportance>;\n intentGoal?: string;\n intentActionType?: string;\n intentEntityTypes?: string[];\n memoryKind?: MemoryFrontmatter[\"memoryKind\"];\n source: string;\n }): Promise<void> => {\n if (\n !shouldPromoteToShared(\n options.sourceStorage,\n options.category,\n options.confidence,\n )\n )\n return;\n try {\n const sharedStorage = await this.storageRouter.storageFor(\n this.config.sharedNamespace,\n );\n // Dedup gate: canonicalize content before hashing.\n //\n // Issue #369 (PR #401): When inline attribution is enabled,\n // `applyInlineCitation` appends a timestamp-bearing marker (e.g.\n // `[Source: ..., ts=2026-04-11T...]`). Because the timestamp changes\n // on every call, hashing cited content produces a unique hash each\n // time — defeating dedup entirely and allowing the same logical fact to\n // be promoted repeatedly. Also, both promotion call sites pass\n // `fact.content`, which can already carry an inline citation (e.g. a\n // relayed or reprocessed fact). Strip any pre-existing citation so the\n // dedup key matches the hash stored from the original un-cited write.\n //\n // PR #402 round-6 (Fix #2 / chatgpt-codex P1 PRRT_kwDORJXyws56U74n):\n // Compute the enriched content before the hash-dedup check so the\n // lookup uses the same content that writeMemory will actually store.\n // When structuredAttributes are present, writeMemory appends an\n // \"[Attributes: ...]\" suffix before hashing; hasFactContentHash must\n // receive the same enriched body or the check is against a different\n // hash and dedup fails to fire (letting duplicates through) or fires\n // when it shouldn't (collapsing memories with different enrichments).\n // Fix #1 (P2 PRRT_kwDORJXyws56VHZc): use normalizeAttributePairs so\n // key order and casing are canonical — identical to the enrichment\n // applied by storage.writeMemory — preventing spurious hash misses\n // when attribute maps arrive with different insertion orders or casing.\n //\n // Fix #4 (Low PRRT_kwDORJXyws56VHth): sanitize the base content before\n // building dedupContent. writeMemory runs sanitizeMemoryContent on the\n // enriched body before hashing; if sanitization redacts the content to\n // REDACTED_PLACEHOLDER the stored hash is for the redacted form, not\n // the raw form. Computing dedupContent from sanitized.text here ensures\n // the hash lookup and the normalizedIncoming comparison both use the\n // same content that writeMemory will actually store.\n //\n // Combined fix: strip any pre-existing citation FIRST to obtain\n // rawContent (the canonical body), then sanitize rawContent (not\n // options.content) when building dedupContent, so that citation\n // stripping and sanitization are applied in a consistent order.\n const rawContent =\n citationEnabled &&\n hasCitationForTemplate(options.content, citationTemplate)\n ? stripCitationForTemplate(options.content, citationTemplate)\n : options.content;\n const citedContent = applyInlineCitation(rawContent);\n const sanitizedBase = sanitizeMemoryContent(rawContent);\n const dedupContent =\n options.category === \"fact\" &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ? `${sanitizedBase.text}\\n[Attributes: ${normalizeAttributePairs(options.structuredAttributes)}]`\n : sanitizedBase.text;\n if (\n options.category === \"fact\" &&\n (await sharedStorage.hasFactContentHash(dedupContent))\n ) {\n // Uj6H fix: shared-namespace temporal supersession must also run when\n // the hash-dedup short-circuit fires. Without this, an existing shared\n // fact whose structuredAttributes are stale (or an older conflicting\n // shared fact that is still active) never gets retired — supersession\n // only ran in the post-writeMemory block which is unreachable here.\n //\n // Strategy: scan the shared namespace for the existing fact whose\n // normalized content matches the incoming content, then run\n // applyTemporalSupersession against it using the same logic that\n // would have run post-writeMemory. This is a best-effort / fail-open\n // step — if the lookup fails we skip silently (same as the normal path).\n if (\n this.config.temporalSupersessionEnabled &&\n options.entityRef &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ) {\n // PR #402 round-7 (Fix #2 / Codex P1 PRRT_kwDORJXyws56VALC):\n // Track whether matchingFact lookup completed before the try block\n // so the catch block can distinguish an early-lookup failure (where\n // we don't know if a duplicate exists) from a post-lookup supersession\n // failure (where we confirmed a duplicate and must skip the write).\n let hashDedupMatchingFact: MemoryFile | undefined;\n let hashDedupLookupComplete = false;\n try {\n // Fix #2 (P2 PRRT_kwDORJXyws56VHZf): dedupContent is now built\n // from sanitizedBase.text (see fix #4 above), so normalizedIncoming\n // uses the same sanitized+normalized content that writeMemory hashes\n // and that hasFactContentHash just matched. Previously this used the\n // raw options.content, which diverged from the stored hash when\n // sanitization redacted the content, causing the candidate lookup to\n // return undefined and leaving stale facts active.\n const normalizedIncoming = ContentHashIndex.normalizeContent(dedupContent);\n const allShared = await sharedStorage.readAllMemories();\n // PR #402 round-12 (Finding Uybg): restrict hash-dedup matching to\n // the SAME entity. Content-hash equality alone can collide across\n // entities when two entities share identical fact text. Using an\n // unrelated entity's existing fact as `newMemoryId` would anchor\n // supersession to that entity's record and corrupt its\n // `supersededBy` links. Only consider facts whose normalized\n // `entityRef` matches the incoming entity.\n const incomingEntityNorm = normalizeSupersessionKey(options.entityRef);\n hashDedupMatchingFact = allShared.find((m) => {\n if (m.frontmatter.category !== \"fact\") return false;\n if ((m.frontmatter.status ?? \"active\") !== \"active\") return false;\n // Same-entity guard: skip if entity doesn't match.\n if (!m.frontmatter.entityRef) return false;\n if (normalizeSupersessionKey(m.frontmatter.entityRef) !== incomingEntityNorm) {\n log.debug(\n `persistExtraction: hash-dedup skipping cross-entity match (incoming=\"${incomingEntityNorm}\" candidate=\"${normalizeSupersessionKey(m.frontmatter.entityRef)}\")`,\n );\n return false;\n }\n // PR #402 round-7 (Fix #2): compare stored fact's full body\n // (including any appended \"[Attributes: ...]\" suffix) against the\n // enriched normalizedIncoming so the candidate selected is the one\n // whose hash actually matched in hasFactContentHash.\n return ContentHashIndex.normalizeContent(m.content ?? \"\") === normalizedIncoming;\n });\n hashDedupLookupComplete = true;\n if (hashDedupMatchingFact) {\n // Finding UvU1 (PR #402 round-11): anchor supersession to the\n // CURRENT wall-clock time, not the existing fact's persisted\n // `created`. The matching fact may be an old shared copy whose\n // `created` predates the incoming promotion event — using it as\n // `createdAt` would make the new memory appear older than the\n // existing one, preventing supersession from firing.\n // PR #402 round-12 (Finding Uyui): the matching fact is an\n // existing OLD memory — its persisted `frontmatter.created` is\n // stale relative to the incoming promotion event. Pass\n // `useCallerTimestamp: true` so the function uses\n // `createdAt` (current wall-clock) as the ordering anchor\n // instead of the old fact's timestamp, ensuring supersession\n // fires correctly even when the matching fact predates\n // conflicting candidates.\n await applyTemporalSupersession({\n storage: sharedStorage,\n newMemoryId: hashDedupMatchingFact.frontmatter.id,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: true,\n useCallerTimestamp: true,\n });\n // Active matching fact exists — normal short-circuit is safe.\n return;\n }\n // No active same-entity shared fact found with this content hash.\n // This can happen when the previously-written shared fact has since\n // been superseded (e.g. Austin → NYC → Austin reversion): the hash\n // index still records the hash but the fact is no longer active.\n // Fall through to the write path below so a new active shared\n // memory is created, then supersession fires post-write as usual.\n log.debug(\n `persistExtraction: hash-dedup found no active same-entity shared fact for ${options.sourceMemoryId}; falling through to write`,\n );\n } catch (hashDedupSupersessionErr) {\n log.warn(\n `persistExtraction: shared-namespace supersession on hash-dedup path failed open for ${options.sourceMemoryId}: ${hashDedupSupersessionErr}`,\n );\n // PR #402 round-7 (Fix #1 / cursor Medium PRRT_kwDORJXyws56U_ig):\n // Only skip the write if we CONFIRMED a matching active shared fact\n // before the error occurred (hashDedupLookupComplete is true AND\n // hashDedupMatchingFact is set). If the error was thrown before\n // matchingFact was resolved — e.g. readAllMemories() threw — we\n // cannot assume a duplicate exists, and unconditionally returning\n // would permanently lose the shared promotion. Fall through to the\n // write path so the fact is not silently dropped.\n if (hashDedupLookupComplete && hashDedupMatchingFact) {\n // A matching active shared fact was confirmed — skip the write to\n // avoid duplicating content that is already present. The existing\n // fact remains active and the supersession failure is logged above.\n return;\n }\n // Lookup did not complete or no candidate was found — we cannot\n // confirm a duplicate. Fall through to the write + post-write\n // supersession path so the shared promotion is not lost.\n log.debug(\n `persistExtraction: hash-dedup catch: lookup incomplete or no candidate found for ${options.sourceMemoryId}; falling through to write`,\n );\n }\n } else {\n // temporalSupersessionEnabled is off or no entity/attributes — keep\n // the original short-circuit behaviour.\n return;\n }\n }\n const promotedId = await sharedStorage.writeMemory(\n options.category as any,\n citedContent,\n {\n confidence: options.confidence,\n tags: [...options.tags, \"shared-promotion\"],\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n source: `${options.source}-shared-promotion`,\n importance: options.importance,\n lineage: [options.sourceMemoryId],\n sourceMemoryId: options.sourceMemoryId,\n intentGoal: options.intentGoal,\n intentActionType: options.intentActionType,\n intentEntityTypes: options.intentEntityTypes,\n memoryKind: options.memoryKind,\n // Index the RAW content hash so hasFactContentHash(rawContent)\n // returns true on subsequent extractions. Without this, the index\n // would record the hash of citedContent (which changes every call\n // due to an updated timestamp), causing duplicate promotions.\n contentHashSource: rawContent,\n },\n );\n // PR #402 Finding 3 fix: run temporal supersession against the shared\n // namespace after the promoted write lands so stale shared-namespace\n // copies of the same entity attribute are retired. Without this,\n // source-namespace supersession leaves the shared copy active and\n // shared recall continues returning the stale state. Reuses the same\n // applyTemporalSupersession helper — no logic duplication.\n if (\n this.config.temporalSupersessionEnabled &&\n options.entityRef &&\n options.structuredAttributes &&\n Object.keys(options.structuredAttributes).length > 0\n ) {\n try {\n await applyTemporalSupersession({\n storage: sharedStorage,\n newMemoryId: promotedId,\n entityRef: options.entityRef,\n structuredAttributes: options.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: true,\n });\n } catch (sharedSupersessionErr) {\n log.warn(\n `persistExtraction: shared-namespace temporal supersession failed open for promoted ${promotedId}: ${sharedSupersessionErr}`,\n );\n }\n }\n trackPersistedId(sharedStorage, promotedId, {\n includeReturnedIds: false,\n });\n await this.indexPersistedMemory(sharedStorage, promotedId);\n trackBehaviorSignals(\n sharedStorage,\n buildBehaviorSignalsForMemory({\n memoryId: promotedId,\n category: options.category as any,\n content: options.content,\n namespace: this.config.sharedNamespace,\n confidence: options.confidence,\n source: \"extraction\",\n }),\n );\n } catch (err) {\n log.warn(\n `persistExtraction: shared promotion failed open for ${options.sourceMemoryId}: ${err}`,\n );\n }\n };\n\n // Defensive: validate result and facts array\n if (!result || !Array.isArray(result.facts)) {\n log.warn(\n \"persistExtraction: result or result.facts is invalid, skipping\",\n { resultType: typeof result, factsType: typeof result?.facts },\n );\n return persistedIds;\n }\n\n // Chunking config from plugin settings\n const chunkingConfig: ChunkingConfig = {\n targetTokens: this.config.chunkingTargetTokens,\n minTokens: this.config.chunkingMinTokens,\n overlapSentences: this.config.chunkingOverlapSentences,\n };\n\n const rawEntities = Array.isArray((result as any).entities)\n ? (result as any).entities\n : [];\n const rawQuestions = Array.isArray((result as any).questions)\n ? (result as any).questions\n : [];\n const rawProfileUpdates = Array.isArray((result as any).profileUpdates)\n ? (result as any).profileUpdates\n : [];\n\n const facts = result.facts.slice(0, this.config.extractionMaxFactsPerRun);\n const entities = rawEntities.slice(\n 0,\n this.config.extractionMaxEntitiesPerRun,\n );\n const questions = rawQuestions.slice(\n 0,\n this.config.extractionMaxQuestionsPerRun,\n );\n const profileUpdates = rawProfileUpdates.slice(\n 0,\n this.config.extractionMaxProfileUpdatesPerRun,\n );\n\n if (\n facts.length < result.facts.length ||\n entities.length < result.entities.length ||\n questions.length < result.questions.length ||\n profileUpdates.length < result.profileUpdates.length\n ) {\n log.warn(\n \"persistExtraction: capped extraction payload to guardrails \" +\n `(facts ${facts.length}/${result.facts.length}, entities ${entities.length}/${result.entities.length}, ` +\n `questions ${questions.length}/${result.questions.length}, profile ${profileUpdates.length}/${result.profileUpdates.length})`,\n );\n }\n\n // v8.2: pre-load all memories once for entity-sibling graph edges (avoids per-fact disk scan)\n type GraphStorageContext = {\n allMemsForGraph: Awaited<\n ReturnType<typeof storage.readAllMemories>\n > | null;\n memoryPathById: Map<string, string>;\n previousPersistedRelPath?: string;\n };\n const graphContextByStorageDir = new Map<string, GraphStorageContext>();\n const ensureGraphContext = async (\n targetStorage: StorageManager,\n ): Promise<GraphStorageContext> => {\n const existing = graphContextByStorageDir.get(targetStorage.dir);\n if (existing) return existing;\n const created: GraphStorageContext = {\n allMemsForGraph: null,\n memoryPathById: new Map<string, string>(),\n };\n if (this.config.multiGraphMemoryEnabled) {\n try {\n created.allMemsForGraph = await targetStorage.readAllMemories();\n for (const [id, relPath] of buildMemoryPathById(\n created.allMemsForGraph,\n targetStorage.dir,\n )) {\n created.memoryPathById.set(id, relPath);\n }\n } catch {\n /* fail-open */\n }\n }\n graphContextByStorageDir.set(targetStorage.dir, created);\n return created;\n };\n let threadEpisodeIdsForGraph: string[] | undefined;\n if (this.config.multiGraphMemoryEnabled && threadIdForExtraction) {\n try {\n const thread = await this.threading.loadThread(threadIdForExtraction);\n threadEpisodeIdsForGraph = thread?.episodeIds\n ? [...thread.episodeIds]\n : [];\n } catch {\n /* fail-open */\n }\n }\n const routeRules = await this.loadRoutingRules();\n const routeOptions = this.routeEngineOptions();\n\n // Pre-routing pass: compute the routed category for every fact BEFORE\n // building judge candidates. Route rules may override f.category (e.g.\n // via taxonomy remapping), and the judge must evaluate against the\n // *final* category that will actually be persisted — not the raw\n // extraction-time category. The per-fact write loop below reuses\n // these pre-computed results so routing is evaluated exactly once per\n // fact (no duplicated logic).\n const preRoutedCategories: Array<string | undefined> = new Array(facts.length);\n if (routeRules.length > 0) {\n for (let fi = 0; fi < facts.length; fi++) {\n const f = facts[fi];\n if (\n !f ||\n typeof f.content !== \"string\" ||\n !f.content.trim() ||\n typeof f.category !== \"string\" ||\n !f.category.trim()\n ) {\n continue;\n }\n try {\n const tags = Array.isArray(f.tags) ? f.tags : [];\n const routeText = `${f.category} ${tags.join(\" \")} ${f.content}`;\n const selected = selectRouteRule(routeText, routeRules, routeOptions);\n if (selected?.target.category) {\n preRoutedCategories[fi] = selected.target.category;\n }\n } catch {\n // Fail-open: routing errors fall through to the extracted category.\n }\n }\n }\n\n // Extraction judge gate (issue #376). When enabled, batch-evaluate all\n // candidate facts for durability before the per-fact write loop.\n // The verdicts map is keyed by candidate index — we maintain a\n // candidateIndexToFactIndex mapping so the write loop can look up\n // verdicts by original fact index.\n //\n // Candidates are built using the *routed* category (preRoutedCategories)\n // so the judge evaluates durability against the same category that will\n // be persisted, not the raw extraction-time category.\n let judgeVerdictsByFactIndex: Map<number, import(\"./extraction-judge.js\").JudgeVerdict> | null = null;\n let judgeGatedCount = 0;\n // Reset the side-channel defer count at the start of every\n // persistExtraction call so stale state from a prior call cannot leak\n // into the caller's buffer-retention decision.\n this.lastPersistExtractionDeferredCount = 0;\n if (this.config.extractionJudgeEnabled) {\n try {\n const judgeCandidates: JudgeCandidate[] = [];\n const candidateToFactIndex: number[] = [];\n for (let fi = 0; fi < facts.length; fi++) {\n const f = facts[fi];\n if (\n !f ||\n typeof f.content !== \"string\" ||\n !f.content.trim() ||\n typeof f.category !== \"string\" ||\n !f.category.trim()\n ) {\n continue;\n }\n // Use the routed category when available so the judge sees the\n // final persisted category, not the raw extraction-time value.\n // Cast to MemoryCategory — routing targets are always valid\n // category slugs defined in the taxonomy; the fallback is the\n // original ExtractedFact.category which is already typed.\n const judgeCategory = (preRoutedCategories[fi] ?? f.category) as import(\"./types.js\").MemoryCategory;\n if (judgeCategory === \"procedure\") {\n continue;\n }\n const tags = Array.isArray(f.tags) ? f.tags : [];\n const imp = scoreImportance(\n f.content,\n judgeCategory,\n tags,\n );\n // Pre-filter: skip facts below importance threshold to avoid\n // wasting LLM calls on facts that will be filtered anyway in\n // the per-fact write loop (issue #376 review finding).\n if (\n !isAboveImportanceThreshold(\n imp.level,\n this.config.extractionMinImportanceLevel,\n )\n ) {\n continue;\n }\n judgeCandidates.push({\n text: f.content,\n category: judgeCategory,\n confidence: typeof f.confidence === \"number\" ? f.confidence : 0.7,\n tags,\n importanceLevel: imp.level,\n });\n candidateToFactIndex.push(fi);\n }\n // Telemetry + training-pair emit (issue #562 PR 3 + PR 4). The\n // orchestrator wires two fire-and-forget writers behind a single\n // callback so `judgeFactDurability` does not need to know about\n // either ledger. Both handlers are skipped when their flags are\n // off; the combined callback itself is undefined when both are\n // disabled so there is zero overhead in the default configuration.\n const judgeTelemetryOpts = {\n enabled: this.config.extractionJudgeTelemetryEnabled === true,\n memoryDir: this.config.memoryDir,\n };\n const judgeTrainingOpts = {\n enabled: this.config.collectJudgeTrainingPairs === true,\n ...(this.config.judgeTrainingDir\n ? { directory: this.config.judgeTrainingDir }\n : {}),\n };\n const judgeTelemetryHandler =\n judgeTelemetryOpts.enabled || judgeTrainingOpts.enabled\n ? (obs: import(\"./extraction-judge.js\").JudgeVerdictObservation) => {\n const ts = new Date().toISOString();\n const verdictKind = getVerdictKind(obs.verdict);\n if (judgeTelemetryOpts.enabled) {\n const event: import(\"./extraction-judge-telemetry.js\").JudgeVerdictEvent = {\n version: 1,\n category: EXTRACTION_JUDGE_VERDICT_CATEGORY,\n ts,\n verdictKind,\n reason: obs.verdict.reason,\n deferrals: obs.priorDeferrals,\n elapsedMs: obs.elapsedMs,\n candidateCategory: obs.candidate.category,\n confidence: obs.candidate.confidence,\n contentHash: obs.contentHash,\n fromCache: obs.source === \"cache\",\n ...(obs.source === \"llm-cap-rejected\"\n ? { deferCapTriggered: true }\n : {}),\n };\n void recordJudgeVerdict(event, judgeTelemetryOpts);\n }\n if (judgeTrainingOpts.enabled) {\n const pair: import(\"./extraction-judge-training.js\").JudgeTrainingPair = {\n version: 1,\n ts,\n candidateText: obs.candidate.text,\n candidateCategory: obs.candidate.category,\n ...(typeof obs.candidate.confidence === \"number\"\n ? { candidateConfidence: obs.candidate.confidence }\n : {}),\n verdictKind,\n reason: obs.verdict.reason,\n priorDeferrals: obs.priorDeferrals,\n };\n void recordJudgeTrainingPair(pair, judgeTrainingOpts);\n }\n }\n : undefined;\n const judgeResult = await judgeFactDurability(\n judgeCandidates,\n this.config,\n this.localLlm,\n new FallbackLlmClient(this.config.gatewayConfig),\n this.judgeVerdictCache,\n this.judgeDeferCounts,\n judgeTelemetryHandler,\n );\n // Remap candidate-indexed verdicts to original fact indexes\n judgeVerdictsByFactIndex = new Map();\n for (const [candidateIdx, verdict] of judgeResult.verdicts) {\n const factIdx = candidateToFactIndex[candidateIdx];\n if (factIdx !== undefined) {\n judgeVerdictsByFactIndex.set(factIdx, verdict);\n }\n }\n log.info(\n `extraction-judge: ${judgeResult.verdicts.size}/${judgeCandidates.length} facts evaluated, ` +\n `${judgeResult.cached} cached, ${judgeResult.judged} judged, ` +\n `${judgeResult.deferred} deferred` +\n (judgeResult.deferredCappedToReject > 0\n ? ` (${judgeResult.deferredCappedToReject} cap-rejected)`\n : \"\") +\n `, ${judgeResult.elapsed}ms`,\n );\n // Expose defer count to the caller (issue #562 PR 2) so it can decide\n // whether to retain buffer turns for the next extraction pass.\n this.lastPersistExtractionDeferredCount = judgeResult.deferred;\n } catch (err) {\n // Fail-open: if the entire judge pipeline errors, proceed without filtering\n log.warn(\n `extraction-judge: pipeline error, proceeding without filtering (fail-open): ${err instanceof Error ? err.message : String(err)}`,\n );\n }\n }\n\n let factLoopIndex = -1;\n for (const fact of facts) {\n factLoopIndex++;\n if (\n !fact ||\n typeof (fact as any).content !== \"string\" ||\n !(fact as any).content.trim()\n ) {\n continue;\n }\n if (\n typeof (fact as any).category !== \"string\" ||\n !(fact as any).category.trim()\n ) {\n continue;\n }\n (fact as any).tags = Array.isArray((fact as any).tags)\n ? (fact as any).tags.filter((t: any) => typeof t === \"string\")\n : [];\n (fact as any).confidence =\n typeof (fact as any).confidence === \"number\"\n ? (fact as any).confidence\n : 0.7;\n\n // Content-hash dedup check (v6.0)\n //\n // Canonicalize pre-tagged facts before hashing (Codex P2 — issue #369).\n // When a fact already carries an inline citation (e.g. relayed or\n // reprocessed), hashing `fact.content` as-is would produce a different\n // hash than the one stored from the original write (which used the raw,\n // un-cited body as contentHashSource). Strip any citation first so the\n // dedup key matches what the hash index recorded.\n //\n // stripCitationForTemplate handles both the default and custom template\n // formats. For all-placeholder templates it cannot detect citations and\n // returns the text unchanged — dedup may miss in that edge case, which\n // is acceptable (no false-positive suppression).\n //\n // Routing runs before content-hash dedup and scoring so category overrides\n // affect both the dedup fingerprint and importance (issue #519 procedure routing).\n let writeCategory = fact.category;\n let targetStorage = storage;\n let routedRuleId: string | undefined;\n 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 targetStorage = await this.storageRouter.storageFor(\n selected.target.namespace,\n );\n }\n }\n } catch (err) {\n log.warn(\n `routing evaluation failed; fail-open to extracted category/namespace: ${err}`,\n );\n }\n }\n\n // Procedures: fingerprint the full serialized body (title + steps), not\n // the title alone, so distinct step lists are not collapsed (issue #519).\n const canonicalContentForHash =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const contentHashDedupKey =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : canonicalContentForHash;\n if (this.contentHashIndex && this.contentHashIndex.has(contentHashDedupKey)) {\n log.debug(\n `dedup: skipping duplicate fact \"${fact.content.slice(0, 60)}…\"`,\n );\n dedupedCount++;\n continue;\n }\n\n // Score importance using local heuristics (Phase 1B).\n // writeCategory / targetStorage already reflect routing.\n const importance = scoreImportance(\n fact.content,\n writeCategory,\n fact.tags,\n );\n\n if (writeCategory === \"procedure\" && this.config.procedural?.enabled !== true) {\n log.debug(\"persistExtraction: skip procedure memory (procedural.enabled is false)\");\n continue;\n }\n\n // Importance write-gate (issue #372). Drop facts whose locally-scored\n // level falls below the configured minimum BEFORE the semantic dedup\n // lookup so that low-importance facts never incur an embedding search.\n // scoreImportance() already applies category boosts (e.g. corrections\n // +0.15) before deriving the level, so a correction at raw ~0.35\n // still lands at \"normal\" and passes the default gate. Without this\n // gate, trivial turn-level chatter (\"hi\", \"k\", heartbeat pings) gets\n // persisted as a fact memory and dilutes the store.\n if (\n !isAboveImportanceThreshold(\n importance.level,\n this.config.extractionMinImportanceLevel,\n )\n ) {\n importanceGatedCount++;\n const snippet = fact.content.slice(0, 60).replace(/\\s+/g, \" \").trim();\n log.debug(`extraction: skip trivial \"${snippet}\"`);\n // Log-based counter (no dedicated metric bus in remnic-core yet).\n // Operators can grep for `metric:importance_gated` in gateway.log\n // to tune extractionMinImportanceLevel.\n log.debug(\n `metric:importance_gated level=${importance.level} threshold=${this.config.extractionMinImportanceLevel} category=${writeCategory} count=${importanceGatedCount}`,\n );\n continue;\n }\n\n // Extraction judge gate (issue #376 + #562 PR 2). After the local\n // importance gate passes, consult the judge verdict (computed before\n // the loop). In active mode, non-durable facts are dropped. In shadow\n // mode, verdicts are logged but all facts proceed to write.\n //\n // Defer verdicts (issue #562): do not persist now, but also do not\n // cache the outcome so the candidate is re-evaluated on a later\n // extraction pass. The judge module tracks how many times the same\n // content has been deferred and converts to reject at the configured\n // cap, so the orchestrator only needs to skip the write here.\n if (judgeVerdictsByFactIndex) {\n const verdict = judgeVerdictsByFactIndex.get(factLoopIndex);\n if (verdict && !verdict.durable) {\n const verdictKind = getVerdictKind(verdict);\n if (this.config.extractionJudgeShadow) {\n log.info(\n `extraction-judge[shadow]: would ${verdictKind} \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n } else if (verdictKind === \"defer\") {\n judgeGatedCount++;\n log.debug(\n `extraction-judge: deferred \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n continue;\n } else {\n judgeGatedCount++;\n log.debug(\n `extraction-judge: rejected \"${fact.content.slice(0, 60)}…\" reason=\"${verdict.reason}\"`,\n );\n continue;\n }\n }\n }\n\n // Procedure extraction gate (issue #519): ≥2 steps + trigger phrasing.\n // Runs even when extractionJudgeEnabled is false (durability judge is unrelated).\n // Never tied to extractionJudgeShadow — that flag is only for the LLM durability judge.\n if (writeCategory === \"procedure\") {\n const procGate = validateProcedureExtraction({\n content: fact.content,\n procedureSteps: fact.procedureSteps,\n });\n if (!procGate.durable) {\n log.debug(\n `extraction-procedure-gate: rejected \"${fact.content.slice(0, 60)}…\" reason=\"${procGate.reason}\"`,\n );\n continue;\n }\n }\n\n // Issue #373 — write-time semantic similarity guard. Hook runs after\n // the exact content-hash miss and the importance gate so that:\n // (a) paraphrased near-duplicates never reach writeMemory(), and\n // (b) low-importance facts that will be dropped never trigger an\n // embedding lookup (avoids unnecessary API latency/cost).\n // Fails open when the embedding backend is unavailable.\n //\n // Defense in depth (PR #399 review): decideSemanticDedup already\n // catches lookup errors internally, and the embedding fetch is\n // bounded by a timeout in embedding-fallback.ts. We still wrap the\n // whole call in its own try/catch here so that any unexpected\n // rejection (future refactors, misbehaving custom backends, etc.)\n // can never block the persist loop — a failure in the dedup path\n // must always default to \"not a duplicate\".\n // Track a pending semantic-skip decision (populated inside the block\n // below). The actual drop happens AFTER contradiction detection so that\n // a high-similarity update/correction is linked as a superseding\n // contradiction rather than silently dropped.\n let pendingSemanticSkip: (SemanticDedupDecision & { action: \"skip\" }) | null = null;\n if (this.config.semanticDedupEnabled) {\n let semanticDecision: SemanticDedupDecision;\n // UUI2: skip embedding lookup for the rest of this batch once we know\n // the backend is unavailable. The flag is reset per-batch (set to false\n // at the top of persistExtraction), so a transient hiccup in one call\n // does not permanently disable dedup in subsequent calls.\n if (batchBackendUnavailable) {\n semanticDecision = { action: \"keep\", reason: \"backend_unavailable\" };\n } else {\n try {\n // Pass the resolved target storage so the lookup scopes the\n // embedding index to the target namespace (PR #399 P1 fix).\n // Without this, a high-similarity hit in a different namespace\n // would cause the fact to be dropped here — cross-namespace\n // write suppression / data loss.\n const lookupStorage = targetStorage;\n semanticDecision = await decideSemanticDedup(\n fact.content,\n (content, limit) =>\n this.semanticDedupLookup(content, limit, lookupStorage),\n {\n enabled: true,\n threshold: this.config.semanticDedupThreshold,\n candidates: this.config.semanticDedupCandidates,\n },\n );\n } catch (err) {\n log.warn(\n `semantic dedup decision failed; failing open and writing fact: ${err}`,\n );\n semanticDecision = {\n action: \"keep\",\n reason: \"backend_unavailable\",\n };\n }\n // UUI2: cache the backend-unavailable signal for the rest of this batch.\n if (semanticDecision.reason === \"backend_unavailable\") {\n batchBackendUnavailable = true;\n }\n }\n if (semanticDecision.action === \"skip\") {\n pendingSemanticSkip = semanticDecision;\n }\n }\n\n const inferredIntent = this.config.intentRoutingEnabled\n ? inferIntentFromText(\n `${writeCategory} ${fact.tags.join(\" \")} ${fact.content}`,\n )\n : null;\n const extractionWriteSource =\n (fact as any).source === \"proactive\"\n ? \"extraction-proactive\"\n : \"extraction\";\n\n // Check for contradictions before writing (Phase 2B).\n // NOTE: This block was moved above the chunking branch so that the\n // pendingSemanticSkip guard (below) can also protect the chunking path.\n // Previously, contradiction detection only ran on the non-chunked path,\n // meaning chunked facts could be persisted even when semanticDecision was\n // \"skip\" (the deferred guard was bypassed by the chunking `continue`).\n let supersedes: string | undefined;\n let links: MemoryLink[] = [];\n // True when contradiction detection ran and confirmed a contradiction,\n // regardless of whether auto-resolve is enabled. Used by the\n // semantic-skip guard so that contradictory updates are never silently\n // dropped — even when `contradictionAutoResolve=false` (in which case\n // `supersedes` is intentionally left unset to avoid retiring the old\n // memory without user confirmation).\n let contradictionDetected = false;\n\n if (this.config.contradictionDetectionEnabled && this.qmd.isAvailable()) {\n const targetNamespace = this.namespaceFromStorageDir(targetStorage.dir);\n const contradiction = await this.checkForContradiction(\n fact.content,\n writeCategory,\n targetNamespace,\n );\n if (contradiction) {\n contradictionDetected = true;\n // When auto-resolve is enabled the existing memory has already been\n // marked superseded; set `supersedes` so the new write carries the\n // relationship. When auto-resolve is disabled we still record the\n // contradiction link (so the memory is annotated for manual review)\n // but do NOT set `supersedes` on the new write — the old memory\n // remains active until a human resolves it.\n if (this.config.contradictionAutoResolve) {\n supersedes = contradiction.supersededId;\n }\n links.push({\n targetId: contradiction.supersededId,\n linkType: \"contradicts\",\n strength: contradiction.confidence,\n reason: contradiction.reason,\n });\n // Deindex the superseded memory so stale paths don't remain in\n // index_time.json / index_tags.json after the incremental update.\n // Only applicable when auto-resolve is on and the old memory is\n // actually being retired; skip when manual review is required.\n if (\n this.config.contradictionAutoResolve &&\n this.config.queryAwareIndexingEnabled &&\n contradiction.supersededPath\n ) {\n deindexMemory(\n this.config.memoryDir,\n contradiction.supersededPath,\n contradiction.supersededCreated,\n contradiction.supersededTags,\n );\n }\n }\n }\n\n // Apply the deferred semantic-skip now that contradiction detection has\n // run. If a contradiction was found (contradictionDetected is true), the\n // candidate is a contradictory update and must be written — do not skip\n // it. Only drop it when there is no detected contradiction (true\n // near-duplicate). This check intentionally runs BEFORE the chunking\n // branch so that a fact flagged as a semantic near-duplicate cannot be\n // persisted (with its hash registered) simply because it was long enough\n // to trigger chunking.\n //\n // NOTE: We use `contradictionDetected` rather than `!!supersedes` here\n // so that facts are preserved even when `contradictionAutoResolve=false`.\n // When auto-resolve is disabled `supersedes` is intentionally unset, but\n // the write must still proceed so the user can manually reconcile the\n // two memories later.\n //\n // UUI1: correction category writes are NEVER suppressed by the semantic\n // skip fallback, regardless of whether supersedes is set. When contradiction\n // detection is disabled or QMD is unavailable, supersedes is never set —\n // without this exemption a high-similarity correction would be silently\n // dropped, leaving a stale fact active. writeCategory (not fact.category)\n // is used because routing rules may have overridden the raw category.\n const isCorrection = writeCategory === \"correction\";\n if (pendingSemanticSkip && !contradictionDetected && !isCorrection) {\n log.debug(\n `dedup: skipping semantic near-duplicate fact \"${fact.content\n .slice(0, 60)\n .replace(/\\s+/g, \" \")}…\" score=${pendingSemanticSkip.topScore.toFixed(\n 3,\n )} neighbor=${pendingSemanticSkip.topId}`,\n );\n dedupedCount++;\n // Do NOT add fact.content to contentHashIndex here. No memory was\n // persisted for this fact, so registering a synthetic hash would\n // permanently suppress exact-copy writes once the neighbor memory is\n // archived or deleted (the hash would linger with no backing record).\n continue;\n }\n\n // Check if chunking is enabled and content should be chunked.\n // When semanticChunkingEnabled is true, prefer the embedding-based\n // semantic chunker which produces more coherent topic-aligned segments.\n // Falls back to the recursive sentence-boundary chunker on failure.\n if (this.config.chunkingEnabled && writeCategory !== \"procedure\") {\n let chunkResult: { chunked: boolean; chunks: { content: string; index: number; tokenCount: number }[] };\n\n if (this.config.semanticChunkingEnabled) {\n try {\n const embedFn = this.embeddingFallback.embedTexts.bind(this.embeddingFallback);\n const semanticResult: SemanticChunkResult = await semanticChunkContent(\n fact.content,\n embedFn,\n this.config.semanticChunkingConfig,\n );\n chunkResult = semanticResult;\n } catch (err) {\n // Honor the fallbackToRecursive contract: when the user explicitly\n // disables fallback, re-throw so extraction fails fast instead of\n // silently using the recursive chunker. semanticChunkContent already\n // throws when fallback is disabled, but this outer catch swallowed\n // that signal. (PR #439 post-merge Finding 1.)\n if (this.config.semanticChunkingConfig?.fallbackToRecursive === false) {\n throw err;\n }\n log.debug(\n `semantic chunking failed, falling back to recursive chunker: ${err}`,\n );\n chunkResult = chunkContent(fact.content, chunkingConfig);\n }\n } else {\n chunkResult = chunkContent(fact.content, chunkingConfig);\n }\n\n if (chunkResult.chunked && chunkResult.chunks.length > 1) {\n // Classify memory kind (v8.0 Phase 2B: HiMem episode/note dual store)\n const memoryKind = this.config.episodeNoteModeEnabled\n ? classifyMemoryKind(fact.content, fact.tags ?? [], writeCategory)\n : undefined;\n\n // Write the parent memory first (with full content for reference).\n //\n // Compute the cited content once so that writeMemory and writeArtifact\n // (when verbatim artifacts are enabled) share the same citation timestamp.\n // See the normal write path comment for the full dedup rationale.\n //\n // Propagate supersedes/links from contradiction detection (round 6\n // fix): contradiction detection now runs BEFORE this branch so the\n // parent must carry the supersession relationship — without it the\n // old memory is deindexed but the new chunked parent has no link\n // back, leaving a dangling deindex with no replacement reference.\n // Child chunks intentionally do NOT carry supersedes; only the\n // parent represents the logical memory unit.\n //\n // Canonicalize contentHashSource before writing (Thread 3 — Codex P2,\n // issue #369). If fact.content already carries an inline citation\n // (e.g. re-processed or relayed fact), strip it so contentHashSource\n // records the raw un-cited body — matching what the dedup check hashes\n // via stripCitationForTemplate before calling hasFactContentHash.\n const rawChunkedContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const citedChunkedContent = applyInlineCitation(rawChunkedContent);\n const parentId = await targetStorage.writeMemory(\n writeCategory,\n citedChunkedContent,\n {\n confidence: fact.confidence,\n tags: [...fact.tags, \"chunked\"],\n entityRef: fact.entityRef,\n source: extractionWriteSource,\n importance,\n supersedes,\n links: links.length > 0 ? links : undefined,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n structuredAttributes: fact.structuredAttributes,\n contentHashSource: rawChunkedContent,\n },\n );\n\n // Write individual chunks with parent reference\n for (const chunk of chunkResult.chunks) {\n // Score each chunk's importance separately\n const chunkImportance = scoreImportance(\n chunk.content,\n writeCategory,\n fact.tags,\n );\n const chunkWriteSource =\n (fact as any).source === \"proactive\"\n ? \"chunking-proactive\"\n : \"chunking\";\n\n await targetStorage.writeChunk(\n parentId,\n chunk.index,\n chunkResult.chunks.length,\n writeCategory,\n // Each chunk carries its own inline citation so provenance\n // survives when a single chunk is quoted in isolation.\n applyInlineCitation(chunk.content),\n {\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef: fact.entityRef,\n source: chunkWriteSource,\n importance: chunkImportance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n },\n );\n }\n\n if (routedRuleId) {\n log.debug(\n `routing applied for chunked memory ${parentId}: rule=${routedRuleId} category=${writeCategory} storage=${targetStorage.dir}`,\n );\n }\n log.debug(\n `chunked memory ${parentId} into ${chunkResult.chunks.length} chunks`,\n );\n trackPersistedId(targetStorage, parentId);\n if (\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(parentId)\n ) {\n threadEpisodeIdsForGraph.push(parentId);\n }\n await this.indexPersistedMemory(targetStorage, parentId);\n // PR #402 Thread 1 fix: run source-namespace temporal supersession for\n // chunked writes, matching the non-chunked path. Without this the\n // source namespace retains stale facts that should have been superseded.\n try {\n const supersessionEntityRef =\n typeof (fact as any).entityRef === \"string\"\n ? ((fact as any).entityRef as string)\n : undefined;\n await applyTemporalSupersession({\n storage: targetStorage,\n newMemoryId: parentId,\n entityRef: supersessionEntityRef,\n structuredAttributes: fact.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: this.config.temporalSupersessionEnabled,\n });\n } catch (err) {\n log.warn(`temporal-supersession (chunked): unexpected error: ${err}`);\n }\n await promoteMemoryToShared({\n sourceStorage: targetStorage,\n category: writeCategory,\n content: fact.content,\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef: fact.entityRef,\n structuredAttributes: fact.structuredAttributes,\n sourceMemoryId: parentId,\n importance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n source: extractionWriteSource,\n });\n // Register chunked content in hash index too.\n // Thread 3 fix: canonicalize by stripping any pre-existing citation\n // so the stored hash matches what the dedup check computes via\n // stripCitationForTemplate before calling contentHashIndex.has().\n if (this.contentHashIndex) {\n const canonicalChunkedContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n this.contentHashIndex.add(canonicalChunkedContent);\n }\n\n for (const chunk of chunkResult.chunks) {\n const chunkId = `${parentId}-chunk-${chunk.index}`;\n // Do NOT push chunkId into persistedIds — chunk IDs must not leak\n // into boxBuilder.onExtraction() or threading.processTurn(), which\n // only expect canonical parent memory IDs. Call indexPersistedMemory\n // directly for embedding-fallback sync of each chunk document.\n await this.indexPersistedMemory(targetStorage, chunkId);\n }\n if (\n this.config.verbatimArtifactsEnabled &&\n this.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.config.verbatimArtifactsMinConfidence\n ) {\n // Reuse citedChunkedContent so the artifact carries the same citation\n // timestamp as the parent memory write above (Fix #3 — duplicate-citation).\n await targetStorage.writeArtifact(citedChunkedContent, {\n confidence: fact.confidence,\n tags: [...fact.tags, \"artifact\", \"chunked-parent\"],\n artifactType: this.artifactTypeForCategory(writeCategory),\n sourceMemoryId: parentId,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n });\n }\n // v8.2: graph edge building for chunked memories\n if (this.config.multiGraphMemoryEnabled) {\n try {\n const graphContext = await ensureGraphContext(targetStorage);\n const entityRef =\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined;\n const parentRelPath = resolvePersistedMemoryRelativePath({\n memoryId: parentId,\n pathById: graphContext.memoryPathById,\n category: writeCategory,\n });\n graphContext.memoryPathById.set(parentId, parentRelPath);\n appendMemoryToGraphContext({\n allMemsForGraph: graphContext.allMemsForGraph,\n storageDir: targetStorage.dir,\n memoryRelPath: parentRelPath,\n memoryId: parentId,\n category: writeCategory,\n content: fact.content ?? \"\",\n entityRef,\n });\n await this.buildGraphEdge(\n targetStorage,\n parentRelPath,\n entityRef,\n parentId,\n fact.content ?? \"\",\n graphContext.allMemsForGraph,\n graphContext.memoryPathById,\n threadIdForExtraction ?? undefined,\n threadEpisodeIdsForGraph,\n graphContext.previousPersistedRelPath,\n );\n graphContext.previousPersistedRelPath = parentRelPath;\n } catch {\n /* fail-open */\n }\n }\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId: parentId,\n category: writeCategory,\n content: fact.content,\n namespace: this.namespaceFromStorageDir(targetStorage.dir),\n confidence: fact.confidence,\n source: \"extraction\",\n }),\n );\n continue; // Skip the normal write below\n }\n }\n\n // Suggest links for this memory (Phase 3A)\n if (this.config.memoryLinkingEnabled && this.qmd.isAvailable()) {\n const targetNamespace = this.namespaceFromStorageDir(targetStorage.dir);\n const suggestedLinks = await this.suggestLinksForMemory(\n fact.content,\n writeCategory,\n targetNamespace,\n );\n if (suggestedLinks.length > 0) {\n links.push(...suggestedLinks);\n }\n }\n\n // Classify memory kind (v8.0 Phase 2B: HiMem episode/note dual store)\n const memoryKind =\n writeCategory === \"procedure\"\n ? undefined\n : this.config.episodeNoteModeEnabled\n ? classifyMemoryKind(fact.content, fact.tags ?? [], writeCategory)\n : undefined;\n\n // Normal write (no chunking)\n //\n // Compute the cited content once so that writeMemory and writeArtifact\n // (when verbatim artifacts are enabled) share the same citation timestamp.\n // Calling applyInlineCitation twice on the same raw content would produce\n // two different timestamps, creating duplicate citations with divergent\n // provenance metadata on the memory and artifact copies of the same fact.\n //\n // Pass the RAW (pre-citation) fact as `contentHashSource` so the\n // fact-content hash index records the hash of the canonical fact text\n // rather than the citation-annotated variant. When inline attribution is\n // enabled, `applyInlineCitation` appends a timestamp-bearing marker, so\n // hashing the persisted body would produce a different hash on every\n // write and defeat cross-session dedup (see `findDuplicateExplicitCapture`\n // in explicit-capture.ts which calls `hasFactContentHash(candidate.content)`\n // on raw content).\n const rawPersistBody =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : fact.content;\n const citedFactContent = applyInlineCitation(rawPersistBody);\n const memoryId = await targetStorage.writeMemory(\n writeCategory,\n citedFactContent,\n {\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef:\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined,\n source: extractionWriteSource,\n importance,\n supersedes,\n links: links.length > 0 ? links : undefined,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n structuredAttributes: fact.structuredAttributes,\n contentHashSource: writeCategory === \"fact\" ? fact.content : undefined,\n },\n );\n if (routedRuleId) {\n log.debug(\n `routing applied for memory ${memoryId}: rule=${routedRuleId} category=${writeCategory} storage=${targetStorage.dir}`,\n );\n }\n // Temporal supersession (issue #375): when the new fact has structured\n // attributes, retire any older fact with the same entity + attribute\n // key that has a conflicting value.\n try {\n const supersessionEntityRef =\n typeof (fact as any).entityRef === \"string\"\n ? ((fact as any).entityRef as string)\n : undefined;\n await applyTemporalSupersession({\n storage: targetStorage,\n newMemoryId: memoryId,\n entityRef: supersessionEntityRef,\n structuredAttributes: fact.structuredAttributes,\n createdAt: new Date().toISOString(),\n enabled: this.config.temporalSupersessionEnabled,\n });\n } catch (err) {\n log.warn(`temporal-supersession: unexpected error: ${err}`);\n }\n trackBehaviorSignals(\n targetStorage,\n buildBehaviorSignalsForMemory({\n memoryId,\n category: writeCategory,\n content: fact.content,\n namespace: this.namespaceFromStorageDir(targetStorage.dir),\n confidence: fact.confidence,\n source: \"extraction\",\n }),\n );\n trackPersistedId(targetStorage, memoryId);\n if (\n threadEpisodeIdsForGraph &&\n !threadEpisodeIdsForGraph.includes(memoryId)\n ) {\n threadEpisodeIdsForGraph.push(memoryId);\n }\n await this.indexPersistedMemory(targetStorage, memoryId);\n await promoteMemoryToShared({\n sourceStorage: targetStorage,\n category: writeCategory,\n content: fact.content,\n confidence: fact.confidence,\n tags: fact.tags,\n entityRef:\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined,\n structuredAttributes: fact.structuredAttributes,\n sourceMemoryId: memoryId,\n importance,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n memoryKind,\n source: extractionWriteSource,\n });\n // v8.2: graph edge building (fail-open — errors caught inside GraphIndex)\n if (this.config.multiGraphMemoryEnabled) {\n try {\n const graphContext = await ensureGraphContext(targetStorage);\n const entityRef =\n typeof (fact as any).entityRef === \"string\"\n ? (fact as any).entityRef\n : undefined;\n const memoryRelPath = resolvePersistedMemoryRelativePath({\n memoryId,\n pathById: graphContext.memoryPathById,\n category: writeCategory,\n });\n graphContext.memoryPathById.set(memoryId, memoryRelPath);\n appendMemoryToGraphContext({\n allMemsForGraph: graphContext.allMemsForGraph,\n storageDir: targetStorage.dir,\n memoryRelPath: memoryRelPath,\n memoryId,\n category: writeCategory,\n content: fact.content ?? \"\",\n entityRef,\n });\n await this.buildGraphEdge(\n targetStorage,\n memoryRelPath,\n entityRef,\n memoryId,\n fact.content ?? \"\",\n graphContext.allMemsForGraph,\n graphContext.memoryPathById,\n threadIdForExtraction ?? undefined,\n threadEpisodeIdsForGraph,\n graphContext.previousPersistedRelPath,\n );\n graphContext.previousPersistedRelPath = memoryRelPath;\n } catch {\n /* fail-open */\n }\n }\n if (\n this.config.verbatimArtifactsEnabled &&\n this.config.verbatimArtifactCategories.includes(writeCategory) &&\n fact.confidence >= this.config.verbatimArtifactsMinConfidence\n ) {\n // Reuse citedFactContent so the artifact carries the same citation\n // timestamp as the memory write above (Fix #3 — duplicate-citation).\n await targetStorage.writeArtifact(citedFactContent, {\n confidence: fact.confidence,\n tags: [...fact.tags, \"artifact\"],\n artifactType: this.artifactTypeForCategory(writeCategory),\n sourceMemoryId: memoryId,\n intentGoal: inferredIntent?.goal,\n intentActionType: inferredIntent?.actionType,\n intentEntityTypes: inferredIntent?.entityTypes,\n });\n }\n // Register in content-hash index after successful write.\n // Thread 3 fix: canonicalize by stripping any pre-existing citation so\n // the stored hash matches what the dedup check computes via\n // stripCitationForTemplate before calling contentHashIndex.has().\n if (this.contentHashIndex) {\n const canonicalFactContent =\n citationEnabled &&\n hasCitationForTemplate(fact.content, citationTemplate)\n ? stripCitationForTemplate(fact.content, citationTemplate)\n : fact.content;\n const hashRegisterKey =\n writeCategory === \"procedure\"\n ? buildProcedurePersistBody(fact.content, fact.procedureSteps)\n : canonicalFactContent;\n this.contentHashIndex.add(hashRegisterKey);\n }\n }\n\n for (const entity of entities) {\n try {\n const name = (entity as any)?.name;\n const type = (entity as any)?.type;\n if (\n typeof name !== \"string\" ||\n !name.trim() ||\n typeof type !== \"string\" ||\n !type.trim()\n ) {\n continue;\n }\n const safeFacts = Array.isArray((entity as any)?.facts)\n ? (entity as any).facts.filter((f: any) => typeof f === \"string\")\n : [];\n const id = await storage.writeEntity(name, type, safeFacts, {\n source: typeof (entity as any)?.source === \"string\" ? (entity as any).source : \"extraction\",\n sessionKey: sourceContext?.sessionKey,\n principal: sourceContext?.principal,\n structuredSections: Array.isArray((entity as any)?.structuredSections)\n ? (entity as any).structuredSections\n : undefined,\n });\n if (id) trackPersistedId(storage, id);\n } catch (err) {\n log.warn(`persistExtraction: entity write failed: ${err}`);\n }\n }\n\n // Persist entity relationships (v7.0)\n if (\n this.config.entityRelationshipsEnabled &&\n Array.isArray(result.relationships)\n ) {\n for (const rel of result.relationships.slice(0, 5)) {\n if (!rel.source || !rel.target || !rel.label) continue;\n try {\n // Add bidirectional relationship\n await storage.addEntityRelationship(rel.source, {\n target: rel.target,\n label: rel.label,\n });\n await storage.addEntityRelationship(rel.target, {\n target: rel.source,\n label: `${rel.label} (reverse)`,\n });\n } catch (err) {\n log.debug(`relationship persist failed: ${err}`);\n }\n }\n }\n\n // Persist entity activity (v7.0)\n if (this.config.entityActivityLogEnabled) {\n const today = new Date().toISOString().slice(0, 10);\n for (const entity of entities) {\n const name = (entity as any)?.name;\n const type = (entity as any)?.type;\n if (typeof name !== \"string\" || typeof type !== \"string\") continue;\n try {\n const normalized = normalizeEntityName(name, type);\n await storage.addEntityActivity(\n normalized,\n { date: today, note: \"Mentioned in conversation\" },\n this.config.entityActivityLogMaxEntries,\n );\n } catch (err) {\n log.debug(`activity persist failed: ${err}`);\n }\n }\n }\n\n if (profileUpdates.length > 0) {\n await storage.appendToProfile(profileUpdates);\n }\n\n // Persist questions\n for (const q of questions) {\n const id = await storage.writeQuestion(q.question, q.context, q.priority);\n if (id) trackPersistedId(storage, id);\n }\n\n // Persist identity reflection\n if (this.config.identityEnabled && result.identityReflection) {\n try {\n await storage.appendIdentityReflection(result.identityReflection);\n } catch (err) {\n log.debug(`identity reflection write failed: ${err}`);\n }\n }\n\n // Save content-hash index after batch\n if (this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) => log.warn(`content-hash index save failed: ${err}`));\n }\n\n for (const {\n storage: targetStorage,\n events,\n } of behaviorSignalsByStorage.values()) {\n const dedupedSignals = dedupeBehaviorSignalsByMemoryAndHash(events);\n if (dedupedSignals.length === 0) continue;\n await targetStorage\n .appendBehaviorSignals(dedupedSignals)\n .catch((err) =>\n log.warn(`appendBehaviorSignals failed (non-fatal): ${err}`),\n );\n }\n\n const dedupSuffix = dedupedCount > 0 ? ` (${dedupedCount} deduped)` : \"\";\n const gatedSuffix =\n importanceGatedCount > 0 ? ` (${importanceGatedCount} gated)` : \"\";\n const judgeSuffix =\n judgeGatedCount > 0 ? ` (${judgeGatedCount} judge-rejected)` : \"\";\n log.info(\n `persisted: ${facts.length - dedupedCount - importanceGatedCount - judgeGatedCount} facts${dedupSuffix}${gatedSuffix}${judgeSuffix}, ${entities.length} entities, ${questions.length} questions, ${profileUpdates.length} profile updates`,\n );\n\n // Update temporal + tag indexes (v8.1) — fire-and-forget, fail-open\n void (async () => {\n if (persistedIdsByStorage.size === 0) {\n await this.updateTemporalTagIndexes(storage, []);\n return;\n }\n for (const entry of persistedIdsByStorage.values()) {\n await this.updateTemporalTagIndexes(entry.storage, entry.ids);\n }\n })().catch((err) =>\n log.debug(`temporal-index update error (non-fatal): ${err}`),\n );\n\n // Return the persisted fact IDs for threading\n return persistedIds;\n }\n\n private async indexPersistedMemory(\n storage: StorageManager,\n memoryId: string,\n ): Promise<void> {\n if (!this.config.embeddingFallbackEnabled) return;\n if (!(await this.embeddingFallback.isAvailable())) return;\n const memory = await storage.getMemoryById(memoryId);\n if (!memory) return;\n await this.embeddingFallback.indexFile(\n memoryId,\n memory.content,\n memory.path,\n );\n }\n\n /**\n * Build a graph edge for a persisted memory (v8.2).\n * Shared helper used by both the chunked and non-chunked write paths to avoid duplication.\n * Fail-open: caller wraps in try/catch.\n */\n private async buildGraphEdge(\n storage: StorageManager,\n memoryRelPath: string,\n entityRef: string | undefined,\n memoryId: string,\n factContent: string,\n allMemsForGraph: import(\"./types.js\").MemoryFile[] | null | undefined,\n memoryPathById: Map<string, string>,\n threadIdForEdge: string | undefined,\n threadEpisodeIdsForGraph: string[] | undefined,\n fallbackCausalPredecessor: string | undefined,\n ): Promise<void> {\n // Entity siblings: other memories sharing the same entityRef\n const entitySiblings: string[] = [];\n if (entityRef) {\n try {\n const allMems = allMemsForGraph ?? [];\n for (const m of allMems) {\n if (m.frontmatter.entityRef === entityRef) {\n const rel = path.relative(storage.dir, m.path);\n if (rel !== memoryRelPath) entitySiblings.push(rel);\n }\n }\n } catch {\n /* fail-open */\n }\n }\n // Recent thread memories for time graph\n const recentInThread: string[] = [];\n if (threadIdForEdge && threadEpisodeIdsForGraph?.length) {\n try {\n recentInThread.push(\n ...resolveRecentThreadMemoryPaths({\n threadEpisodeIds: threadEpisodeIdsForGraph,\n currentMemoryId: memoryId,\n allMemsForGraph,\n pathById: memoryPathById,\n storageDir: storage.dir,\n maxRecent: 3,\n }),\n );\n } catch {\n /* fail-open */\n }\n }\n if (\n recentInThread.length === 0 &&\n this.config.graphWriteSessionAdjacencyEnabled !== false &&\n fallbackCausalPredecessor &&\n fallbackCausalPredecessor !== memoryRelPath\n ) {\n recentInThread.push(fallbackCausalPredecessor);\n }\n const causalPredecessor =\n recentInThread[recentInThread.length - 1] ?? fallbackCausalPredecessor;\n await this.graphIndexFor(storage).onMemoryWritten({\n memoryPath: memoryRelPath,\n entityRef,\n content: factContent,\n created: new Date().toISOString(),\n threadId: threadIdForEdge,\n recentInThread,\n entitySiblings,\n causalPredecessor,\n });\n }\n\n private graphIndexFor(storage: StorageManager): GraphIndex {\n const key = storage.dir;\n const existing = this.graphIndexes.get(key);\n if (existing) return existing;\n const created = new GraphIndex(key, this.config);\n this.graphIndexes.set(key, created);\n return created;\n }\n\n /**\n * Batch-update temporal and tag indexes after extraction (v8.1).\n * Reads each persisted memory's path + frontmatter and adds them to\n * state/index_time.json and state/index_tags.json.\n * Fail-open: any error is logged but does not abort extraction.\n */\n private async updateTemporalTagIndexes(\n storage: StorageManager,\n persistedIds: string[],\n ): Promise<void> {\n // Build temporal/tag indexes whenever either consumer is enabled:\n // - queryAwareIndexingEnabled: uses indexes for query-aware prefiltering in recall\n // - parallelRetrievalEnabled: temporal agent reads index_time.json for date-range lookup\n // Enabling only parallelRetrievalEnabled without queryAwareIndexingEnabled would silently\n // produce an empty temporal index, leaving the temporal agent with no data to work from.\n if (\n !this.config.queryAwareIndexingEnabled &&\n !this.config.parallelRetrievalEnabled\n )\n return;\n // Check for missing indexes BEFORE the early-return so first-time enablement\n // can bootstrap the full corpus even when this extraction turn persisted nothing.\n const needsFullRebuild = !indexesExist(this.config.memoryDir);\n if (!needsFullRebuild && persistedIds.length === 0) return;\n try {\n // Read the corpus once to avoid N separate full-corpus scans.\n // On full rebuild with namespaces enabled, span all configured namespaces so\n // memories written to other namespaces before the index existed are also captured.\n const allMemories =\n needsFullRebuild && this.config.namespacesEnabled\n ? await this.readAllMemoriesForNamespaces(\n Array.from(\n new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]),\n ),\n )\n : await storage.readAllMemories();\n\n // Bootstrap: index only active (non-archived, non-superseded) memories.\n // Incremental: index only the newly persisted IDs.\n const isActive = (m: { frontmatter: { status?: string } }) =>\n !m.frontmatter.status || m.frontmatter.status === \"active\";\n const pool = needsFullRebuild\n ? allMemories.filter(isActive)\n : (() => {\n const idSet = new Set(persistedIds);\n return allMemories.filter((m) => idSet.has(m.frontmatter.id));\n })();\n\n const entries: Array<{\n path: string;\n createdAt: string;\n tags: string[];\n }> = [];\n for (const mem of pool) {\n if (mem.path && mem.frontmatter?.created) {\n entries.push({\n path: mem.path,\n createdAt: mem.frontmatter.created,\n tags: mem.frontmatter.tags ?? [],\n });\n }\n }\n if (needsFullRebuild) {\n // Always write empty indexes on full rebuild — even when the active pool\n // is empty (e.g. store contains only archived/superseded entries).\n // This marks bootstrap completion so indexesExist() returns true and\n // subsequent extractions skip the full-corpus scan.\n clearIndexes(this.config.memoryDir);\n if (entries.length > 0) {\n indexMemoriesBatch(this.config.memoryDir, entries);\n }\n log.info(\n `temporal-index: bootstrapped from ${entries.length} active memories`,\n );\n } else if (entries.length > 0) {\n indexMemoriesBatch(this.config.memoryDir, entries);\n }\n } catch (err) {\n log.debug(`temporal-index update failed (non-fatal): ${err}`);\n }\n }\n\n /** IDs of facts persisted in the last extraction */\n private lastPersistedIds: string[] = [];\n\n private async runConsolidation(): Promise<{\n memoriesProcessed: number;\n merged: number;\n invalidated: number;\n }> {\n log.info(\"running consolidation pass\");\n let merged = 0;\n let invalidated = 0;\n\n // Flush access tracking buffer first\n if (this.accessTrackingBuffer.size > 0) {\n await this.flushAccessTracking();\n }\n\n let allMemories = await this.storage.readAllMemories();\n if (allMemories.length < 5) {\n return { memoriesProcessed: allMemories.length, merged, invalidated };\n }\n\n const recent = allMemories\n .sort(\n (a, b) =>\n new Date(b.frontmatter.created).getTime() -\n new Date(a.frontmatter.created).getTime(),\n )\n .slice(0, 20);\n\n const older = allMemories.sort(\n (a, b) =>\n new Date(a.frontmatter.created).getTime() -\n new Date(b.frontmatter.created).getTime(),\n );\n\n const profile = await this.storage.readProfile();\n const result = await this.extraction.consolidate(recent, older, profile);\n\n // Build a lookup map from the already-loaded corpus to avoid repeated\n // readAllMemories() scans inside getMemoryById for pre-action deindex reads.\n const memoryLookup = this.config.queryAwareIndexingEnabled\n ? new Map(allMemories.map((m) => [m.frontmatter.id, m]))\n : null;\n\n for (const item of result.items) {\n switch (item.action) {\n case \"INVALIDATE\": {\n // Capture path/frontmatter before invalidation for index cleanup\n const toInvalidate = this.config.queryAwareIndexingEnabled\n ? (memoryLookup?.get(item.existingId) ?? null)\n : null;\n if (await this.storage.invalidateMemory(item.existingId)) {\n invalidated += 1;\n await this.embeddingFallback.removeFromIndex(item.existingId);\n if (toInvalidate?.path && toInvalidate.frontmatter?.created) {\n deindexMemory(\n this.config.memoryDir,\n toInvalidate.path,\n toInvalidate.frontmatter.created,\n toInvalidate.frontmatter.tags ?? [],\n );\n }\n }\n break;\n }\n case \"UPDATE\":\n if (item.updatedContent) {\n await this.storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n lineage: [item.existingId],\n },\n );\n await this.indexPersistedMemory(this.storage, item.existingId);\n // updateMemory() only changes content/updated/lineage — path, created, and tags\n // are preserved, so the temporal/tag index entry is already correct; no reindex needed.\n }\n break;\n case \"MERGE\":\n if (item.updatedContent && item.mergeWith) {\n await this.storage.updateMemory(\n item.existingId,\n item.updatedContent,\n {\n supersedes: item.mergeWith,\n lineage: [item.existingId, item.mergeWith],\n },\n );\n await this.indexPersistedMemory(this.storage, item.existingId);\n // updateMemory() only changes content/updated/supersedes/lineage — path, created, and tags\n // are preserved, so the temporal/tag index entry for the survivor is already correct.\n // Capture before invalidation for index cleanup\n const toMergeInvalidate = this.config.queryAwareIndexingEnabled\n ? (memoryLookup?.get(item.mergeWith) ?? null)\n : null;\n if (await this.storage.invalidateMemory(item.mergeWith)) {\n invalidated += 1;\n merged += 1;\n await this.embeddingFallback.removeFromIndex(item.mergeWith);\n if (\n toMergeInvalidate?.path &&\n toMergeInvalidate.frontmatter?.created\n ) {\n deindexMemory(\n this.config.memoryDir,\n toMergeInvalidate.path,\n toMergeInvalidate.frontmatter.created,\n toMergeInvalidate.frontmatter.tags ?? [],\n );\n }\n }\n }\n break;\n }\n }\n\n if (result.profileUpdates.length > 0) {\n await this.storage.appendToProfile(result.profileUpdates);\n }\n\n for (const entity of result.entityUpdates) {\n const safeFacts = Array.isArray((entity as any)?.facts)\n ? (entity as any).facts.filter((f: any) => typeof f === \"string\")\n : [];\n await this.storage.writeEntity(entity.name, entity.type, safeFacts, {\n source: \"consolidation\",\n structuredSections: Array.isArray((entity as any)?.structuredSections)\n ? (entity as any).structuredSections\n : undefined,\n });\n }\n\n // Merge fragmented entity files\n const entitiesMerged = await this.storage.mergeFragmentedEntities();\n if (entitiesMerged > 0) {\n log.info(`merged ${entitiesMerged} fragmented entity files`);\n }\n\n if (this.config.entitySummaryEnabled) {\n try {\n const synthesized = await this.processEntitySynthesisQueue(\n this.config.defaultNamespace,\n 5,\n );\n if (synthesized > 0) {\n log.info(`refreshed ${synthesized} entity syntheses`);\n }\n } catch (err) {\n log.debug(`entity synthesis pass failed: ${err}`);\n }\n }\n\n // Clean expired commitments\n const deletedCommitments = await this.storage.cleanExpiredCommitments(\n this.config.commitmentDecayDays,\n );\n if (deletedCommitments.length > 0) {\n log.info(`cleaned ${deletedCommitments.length} expired commitments`);\n if (this.config.queryAwareIndexingEnabled) {\n for (const m of deletedCommitments) {\n deindexMemory(\n this.config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n }\n }\n\n if (\n this.config.creationMemoryEnabled &&\n this.config.commitmentLedgerEnabled &&\n this.config.commitmentLifecycleEnabled\n ) {\n try {\n const lifecycle = await applyCommitmentLedgerLifecycle({\n memoryDir: this.config.memoryDir,\n commitmentLedgerDir: this.config.commitmentLedgerDir,\n enabled: true,\n decayDays: this.config.commitmentDecayDays,\n });\n if (\n lifecycle.transitionedToExpired.length > 0 ||\n lifecycle.deletedResolved.length > 0\n ) {\n log.info(\n `commitment ledger lifecycle: expired ${lifecycle.transitionedToExpired.length}, cleaned ${lifecycle.deletedResolved.length}`,\n );\n }\n } catch (err) {\n log.debug(`commitment ledger lifecycle pass failed: ${err}`);\n }\n }\n\n // Clean memories past their TTL (speculative memories auto-expire)\n const deletedTTL = await this.storage.cleanExpiredTTL();\n if (deletedTTL.length > 0) {\n log.info(`cleaned ${deletedTTL.length} TTL-expired memories`);\n if (this.config.queryAwareIndexingEnabled) {\n for (const m of deletedTTL) {\n deindexMemory(\n this.config.memoryDir,\n m.path,\n m.frontmatter.created,\n m.frontmatter.tags ?? [],\n );\n }\n }\n }\n\n // v8.3 Lifecycle policy pass — deterministic promotion/decay metadata\n if (this.config.lifecyclePolicyEnabled) {\n try {\n const lifecycleCorpus = await this.storage.readAllMemories();\n await this.runLifecyclePolicyPass(lifecycleCorpus);\n } catch (err) {\n log.warn(`lifecycle policy pass failed (ignored): ${err}`);\n }\n }\n\n // v8.3 Compression guideline learning pass (default off, fail-open).\n await this.runCompressionGuidelineLearningPass();\n\n await this.runTierMigrationCycle(this.storage, \"maintenance\");\n allMemories = await this.storage.readAllMemories();\n\n // Fact archival pass (v6.0) — move old, low-importance, rarely-accessed facts to archive/\n if (this.config.factArchivalEnabled) {\n const archived = await this.runFactArchival(allMemories);\n if (archived > 0) {\n log.info(`archived ${archived} old low-importance facts`);\n }\n }\n\n // Semantic consolidation pass — find similar memories, synthesize canonical versions\n if (this.config.semanticConsolidationEnabled) {\n try {\n const stateFilePath = path.join(\n this.config.memoryDir,\n \"state\",\n \"semantic-consolidation-last-run.json\",\n );\n let shouldRun = true;\n try {\n const stateRaw = await readFile(stateFilePath, \"utf-8\");\n const stateData = JSON.parse(stateRaw) as { lastRunAt?: string };\n if (stateData.lastRunAt) {\n const lastRunMs = new Date(stateData.lastRunAt).getTime();\n const intervalMs =\n this.config.semanticConsolidationIntervalHours * 60 * 60 * 1000;\n if (Date.now() - lastRunMs < intervalMs) {\n shouldRun = false;\n log.debug(\n \"[semantic-consolidation] skipping — not enough time since last run\",\n );\n }\n }\n } catch {\n // No state file yet — first run\n }\n\n if (shouldRun) {\n const semResult = await this.runSemanticConsolidation();\n if (semResult.memoriesArchived > 0) {\n log.info(\n `[semantic-consolidation] archived ${semResult.memoriesArchived} memories during maintenance`,\n );\n allMemories = await this.storage.readAllMemories();\n }\n // Only persist last-run timestamp if the run succeeded (had no errors or made progress)\n if (semResult.errors === 0 || semResult.memoriesArchived > 0) {\n const stateDir = path.join(this.config.memoryDir, \"state\");\n await mkdir(stateDir, { recursive: true });\n await writeFile(\n stateFilePath,\n JSON.stringify({ lastRunAt: new Date().toISOString() }),\n \"utf-8\",\n );\n }\n }\n } catch (err) {\n log.warn(\n `[semantic-consolidation] maintenance pass failed (non-fatal): ${err}`,\n );\n }\n }\n\n // Auto-consolidate IDENTITY.md if it's getting large\n if (this.config.identityEnabled) {\n await this.autoConsolidateIdentity();\n }\n\n // Auto-consolidate profile.md if it exceeds max lines\n const profileSection = this.getRecallSectionEntry(\"profile\");\n const profileConsolidationTriggerLines =\n typeof profileSection?.consolidateTriggerLines === \"number\"\n ? Math.max(0, Math.floor(profileSection.consolidateTriggerLines))\n : undefined;\n const profileConsolidationTargetLines =\n typeof profileSection?.consolidateTargetLines === \"number\"\n ? Math.max(0, Math.floor(profileSection.consolidateTargetLines))\n : 50;\n if (\n await this.storage.profileNeedsConsolidation(\n profileConsolidationTriggerLines,\n )\n ) {\n log.info(\"profile.md exceeds max lines — running smart consolidation\");\n const currentProfile = await this.storage.readProfile();\n if (currentProfile) {\n const profileResult = await this.extraction.consolidateProfile(\n currentProfile,\n profileConsolidationTargetLines,\n );\n if (profileResult) {\n await this.storage.writeProfile(profileResult.consolidatedProfile);\n log.info(\n `profile.md consolidated: removed ${profileResult.removedCount} items — ${profileResult.summary}`,\n );\n }\n }\n }\n\n // Memory Summarization (Phase 4A)\n if (this.config.summarizationEnabled) {\n await this.runSummarization(allMemories);\n }\n\n // Topic Extraction (Phase 4B)\n if (this.config.topicExtractionEnabled) {\n await this.runTopicExtraction(allMemories);\n }\n\n const meta = await this.storage.loadMeta();\n meta.lastConsolidationAt = new Date().toISOString();\n await this.storage.saveMeta(meta);\n\n // Temporal Memory Tree (v8.2) — rebuild nodes from all memories, fail-open\n if (this.config.temporalMemoryTreeEnabled) {\n try {\n const tmtEntries = allMemories\n .filter(\n (m) =>\n m.frontmatter.status !== \"superseded\" &&\n m.frontmatter.status !== \"archived\",\n )\n .map((m) => ({\n path: m.path,\n id: m.frontmatter.id,\n created: m.frontmatter.created,\n content: m.content,\n }));\n await this.tmtBuilder.maybeRebuildNodes(\n tmtEntries,\n async (texts, level) => {\n const prompt = `You are a memory archivist. Summarize the following ${level}-level memories into 3–5 sentences, preserving key facts, decisions, and preferences.\\n\\n${texts.map((t, i) => `[${i + 1}] ${t}`).join(\"\\n\\n\")}`;\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content:\n \"Respond with a 3–5 sentence narrative summary. No JSON, just plain prose.\",\n },\n { role: \"user\", content: prompt },\n ],\n {\n temperature: 0.3,\n maxTokens: this.config.tmtSummaryMaxTokens,\n operation: \"tmt_summary\",\n priority: \"background\",\n },\n );\n return response?.content?.trim() || texts.slice(0, 3).join(\" \");\n },\n );\n } catch (err) {\n log.warn(`tmt: consolidation hook failed (ignored): ${err}`);\n }\n }\n\n if (this.consolidationObservers.size > 0) {\n const observation: ConsolidationObservation = {\n runAt: new Date().toISOString(),\n recentMemories: recent,\n existingMemories: older.slice(-50),\n profile,\n result,\n merged,\n invalidated,\n };\n for (const observer of this.consolidationObservers) {\n try {\n await observer(observation);\n } catch (err) {\n log.warn(`consolidation observer failed (ignored): ${err}`);\n }\n }\n }\n\n log.info(\"consolidation complete\");\n return { memoriesProcessed: allMemories.length, merged, invalidated };\n }\n\n async optimizeCompressionGuidelines(options?: {\n dryRun?: boolean;\n eventLimit?: number;\n }): Promise<{\n enabled: boolean;\n dryRun: boolean;\n eventCount: number;\n previousGuidelineVersion: number | null;\n nextGuidelineVersion: number;\n changedRules: number;\n semanticRefinementApplied: boolean;\n persisted: boolean;\n draftContentHash: string | null;\n }> {\n const dryRun = options?.dryRun === true;\n const eventLimit =\n typeof options?.eventLimit === \"number\"\n ? Math.max(0, Math.floor(options.eventLimit))\n : 500;\n\n const [activeState, draftState] = await Promise.all([\n this.storage.readCompressionGuidelineOptimizerState(),\n this.storage.readCompressionGuidelineDraftState().catch(() => null),\n ]);\n const previousState =\n draftState &&\n ((activeState?.guidelineVersion ?? 0) < draftState.guidelineVersion ||\n (activeState?.guidelineVersion ?? 0) === draftState.guidelineVersion)\n ? draftState\n : activeState;\n\n if (!this.config.compressionGuidelineLearningEnabled) {\n return {\n enabled: false,\n dryRun,\n eventCount: 0,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: previousState?.guidelineVersion ?? 0,\n changedRules: 0,\n semanticRefinementApplied: false,\n persisted: false,\n draftContentHash: null,\n };\n }\n\n let events = await this.storage.readMemoryActionEvents(eventLimit);\n if (eventLimit > 0) {\n let effectiveEvents = events.filter((event) => event.dryRun !== true);\n let fetchLimit = eventLimit;\n while (\n effectiveEvents.length < eventLimit &&\n events.length === fetchLimit\n ) {\n fetchLimit = Math.min(fetchLimit * 2, fetchLimit + 1000);\n if (fetchLimit <= events.length) break;\n events = await this.storage.readMemoryActionEvents(fetchLimit);\n effectiveEvents = events.filter((event) => event.dryRun !== true);\n }\n events = effectiveEvents.slice(-eventLimit);\n }\n const generatedAt = new Date().toISOString();\n const candidate = computeCompressionGuidelineCandidate(events, {\n generatedAtIso: generatedAt,\n previousState,\n });\n if (candidate.eventCounts.total === 0) {\n return {\n enabled: true,\n dryRun,\n eventCount: 0,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: previousState?.guidelineVersion ?? 0,\n changedRules: 0,\n semanticRefinementApplied: false,\n persisted: false,\n draftContentHash: null,\n };\n }\n const refinedCandidate =\n await refineCompressionGuidelineCandidateSemantically(candidate, {\n enabled: this.config.compressionGuidelineSemanticRefinementEnabled,\n timeoutMs: this.config.compressionGuidelineSemanticTimeoutMs,\n runRefinement: async (baseline) => {\n const prompt = [\n \"You refine compression policy suggestions conservatively.\",\n \"Return JSON only in this shape:\",\n '{\"updates\":[{\"action\":\"summarize_node\",\"delta\":0.02,\"confidence\":\"medium\",\"note\":\"...\"}]}',\n \"Constraints:\",\n \"- Keep updates sparse and conservative.\",\n \"- delta must stay between -0.15 and 0.15.\",\n \"- Only include actions present in the input.\",\n \"Input candidate:\",\n JSON.stringify(baseline),\n ].join(\"\\n\");\n\n const response = await this.fastChatCompletion(\n [\n {\n role: \"system\",\n content: \"Respond with strict JSON only. No markdown.\",\n },\n { role: \"user\", content: prompt },\n ],\n {\n temperature: 0.1,\n maxTokens: 400,\n operation: \"compression_guideline_semantic_refinement\",\n priority: \"background\",\n },\n );\n\n return this.parseCompressionSemanticRefinement(\n response?.content ?? \"\",\n );\n },\n });\n\n const content = renderCompressionGuidelinesMarkdown(refinedCandidate);\n const contentHash = createHash(\"sha256\").update(content).digest(\"hex\");\n const semanticRefinementApplied =\n JSON.stringify(refinedCandidate.ruleUpdates) !==\n JSON.stringify(candidate.ruleUpdates);\n const changedRules = refinedCandidate.ruleUpdates.filter(\n (rule) => rule.delta !== 0,\n ).length;\n\n if (!dryRun) {\n await this.storage.writeCompressionGuidelineDraft(content);\n await this.storage.writeCompressionGuidelineDraftState({\n version: refinedCandidate.optimizerVersion,\n updatedAt: refinedCandidate.generatedAt,\n sourceWindow: refinedCandidate.sourceWindow,\n eventCounts: refinedCandidate.eventCounts,\n guidelineVersion: refinedCandidate.guidelineVersion,\n contentHash,\n activationState: \"draft\",\n actionSummaries: refinedCandidate.actionSummaries,\n ruleUpdates: refinedCandidate.ruleUpdates,\n });\n }\n\n return {\n enabled: true,\n dryRun,\n eventCount: candidate.eventCounts.total,\n previousGuidelineVersion: previousState?.guidelineVersion ?? null,\n nextGuidelineVersion: refinedCandidate.guidelineVersion,\n changedRules,\n semanticRefinementApplied,\n persisted: !dryRun,\n draftContentHash: dryRun ? null : contentHash,\n };\n }\n\n async activateCompressionGuidelineDraft(options?: {\n expectedContentHash?: string;\n expectedGuidelineVersion?: number;\n }): Promise<{\n enabled: boolean;\n activated: boolean;\n guidelineVersion: number | null;\n reason?:\n | \"disabled\"\n | \"missing_draft\"\n | \"expected_revision_required\"\n | \"content_hash_mismatch\"\n | \"guideline_version_mismatch\"\n | \"draft_changed\";\n }> {\n if (!this.config.compressionGuidelineLearningEnabled) {\n return {\n enabled: false,\n activated: false,\n guidelineVersion: null,\n reason: \"disabled\",\n };\n }\n\n const draftState = await this.storage.readCompressionGuidelineDraftState();\n if (!draftState) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"missing_draft\",\n };\n }\n\n const expectedContentHash = options?.expectedContentHash?.trim();\n const expectedGuidelineVersion = options?.expectedGuidelineVersion;\n\n if (\n (!expectedContentHash || expectedContentHash.length === 0) &&\n typeof expectedGuidelineVersion !== \"number\"\n ) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"expected_revision_required\",\n };\n }\n\n if (expectedContentHash && draftState.contentHash !== expectedContentHash) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"content_hash_mismatch\",\n };\n }\n\n if (\n typeof expectedGuidelineVersion === \"number\" &&\n draftState.guidelineVersion !== expectedGuidelineVersion\n ) {\n return {\n enabled: true,\n activated: false,\n guidelineVersion: null,\n reason: \"guideline_version_mismatch\",\n };\n }\n\n const activated = await this.storage.activateCompressionGuidelineDraft({\n ...(expectedContentHash ? { expectedContentHash } : {}),\n ...(typeof expectedGuidelineVersion === \"number\"\n ? { expectedGuidelineVersion }\n : {}),\n });\n return {\n enabled: true,\n activated,\n guidelineVersion: activated ? draftState.guidelineVersion : null,\n ...(activated ? {} : { reason: \"draft_changed\" as const }),\n };\n }\n\n private async runCompressionGuidelineLearningPass(): Promise<void> {\n if (!this.config.compressionGuidelineLearningEnabled) return;\n try {\n const result = await this.optimizeCompressionGuidelines({\n dryRun: false,\n eventLimit: 500,\n });\n log.info(\n `compression guideline learning updated (${result.eventCount} events)`,\n );\n } catch (err) {\n log.warn(`compression guideline learning failed (ignored): ${err}`);\n }\n }\n\n private async buildCompressionGuidelineRecallSection(): Promise<\n string | null\n > {\n if (!this.config.contextCompressionActionsEnabled) return null;\n if (!this.config.compressionGuidelineLearningEnabled) return null;\n\n const state = await this.storage\n .readCompressionGuidelineOptimizerState()\n .catch(() => null);\n if (!state || state.guidelineVersion <= 0) return null;\n\n const raw = await this.storage\n .readCompressionGuidelines()\n .catch(() => null);\n const summary = raw ? formatCompressionGuidelinesForRecall(raw, 5) : null;\n if (!summary) return null;\n\n return [\n \"## Active Compression Guidelines\",\n \"\",\n `Guideline version: ${state.guidelineVersion}`,\n `Updated: ${state.updatedAt}`,\n \"\",\n summary,\n ].join(\"\\n\");\n }\n\n private parseCompressionSemanticRefinement(raw: string): {\n updates: Array<{\n action: MemoryActionType;\n delta?: number;\n confidence?: \"low\" | \"medium\" | \"high\";\n note?: string;\n }>;\n } | null {\n if (typeof raw !== \"string\" || raw.trim().length === 0) return null;\n const trimmed = raw.trim();\n const start = trimmed.indexOf(\"{\");\n const end = trimmed.lastIndexOf(\"}\");\n if (start === -1 || end === -1 || end <= start) return null;\n\n try {\n const parsed = JSON.parse(trimmed.slice(start, end + 1)) as {\n updates?: Array<{\n action?: unknown;\n delta?: unknown;\n confidence?: unknown;\n note?: unknown;\n }>;\n };\n if (!Array.isArray(parsed?.updates)) return null;\n\n const validActions = new Set<MemoryActionType>([\n \"store_episode\",\n \"store_note\",\n \"update_note\",\n \"create_artifact\",\n \"summarize_node\",\n \"discard\",\n \"link_graph\",\n ]);\n\n const updates = parsed.updates\n .filter(\n (item) =>\n item &&\n typeof item.action === \"string\" &&\n validActions.has(item.action as MemoryActionType),\n )\n .map((item) => {\n const confidence: \"low\" | \"medium\" | \"high\" | undefined =\n item.confidence === \"low\" ||\n item.confidence === \"medium\" ||\n item.confidence === \"high\"\n ? item.confidence\n : undefined;\n return {\n action: item.action as MemoryActionType,\n delta:\n typeof item.delta === \"number\" && Number.isFinite(item.delta)\n ? item.delta\n : undefined,\n confidence,\n note: typeof item.note === \"string\" ? item.note : undefined,\n };\n });\n\n return { updates };\n } catch {\n return null;\n }\n }\n\n private actionOutcomePriorDelta(event: MemoryActionEvent): number {\n if (event.outcome === \"failed\") return -0.3;\n if (event.policyDecision === \"deny\") return -0.22;\n if (event.policyDecision === \"defer\") return -0.14;\n if (event.outcome === \"skipped\") return -0.1;\n\n if (event.outcome !== \"applied\") return 0;\n switch (event.action) {\n case \"store_episode\":\n case \"store_note\":\n case \"update_note\":\n return 0.08;\n case \"create_artifact\":\n case \"summarize_node\":\n case \"link_graph\":\n return 0.04;\n case \"discard\":\n return -0.03;\n default:\n return 0;\n }\n }\n\n private async buildLifecycleActionPriors(): Promise<Map<string, number>> {\n const events = await this.storage.readMemoryActionEvents(1200);\n if (events.length === 0) return new Map<string, number>();\n\n const nowMs = Date.now();\n const windowMs = 14 * 24 * 60 * 60 * 1000;\n const byMemory = new Map<\n string,\n Array<{ weightedDelta: number; weight: number }>\n >();\n\n for (const event of events) {\n if (\n typeof event.memoryId !== \"string\" ||\n event.memoryId.trim().length === 0\n )\n continue;\n const ts = Date.parse(event.timestamp);\n if (!Number.isFinite(ts)) continue;\n const ageMs = nowMs - ts;\n if (ageMs < 0 || ageMs > windowMs) continue;\n\n const delta = this.actionOutcomePriorDelta(event);\n if (delta === 0) continue;\n\n const recencyWeight = Math.max(0.2, 1 - ageMs / windowMs);\n const list = byMemory.get(event.memoryId) ?? [];\n if (list.length >= 8) list.shift();\n list.push({\n weightedDelta: delta * recencyWeight,\n weight: recencyWeight,\n });\n byMemory.set(event.memoryId, list);\n }\n\n const out = new Map<string, number>();\n for (const [memoryId, deltas] of byMemory.entries()) {\n if (deltas.length === 0) continue;\n const weightedSum = deltas.reduce(\n (sum, item) => sum + item.weightedDelta,\n 0,\n );\n const weightTotal = deltas.reduce((sum, item) => sum + item.weight, 0);\n if (weightTotal <= 0) continue;\n const score = weightedSum / weightTotal;\n out.set(memoryId, Math.max(-0.25, Math.min(0.15, score)));\n }\n return out;\n }\n\n private async runLifecyclePolicyPass(\n allMemories: MemoryFile[],\n ): Promise<void> {\n const now = new Date();\n const nowIso = now.toISOString();\n const countsByState: Record<LifecycleState, number> = {\n candidate: 0,\n validated: 0,\n active: 0,\n stale: 0,\n archived: 0,\n };\n const transitionCounts: Record<string, number> = {};\n let updatedCount = 0;\n let disputedCount = 0;\n let evaluatedCount = 0;\n\n const thresholds = this.effectiveLifecycleThresholds();\n const policy = {\n promoteHeatThreshold: thresholds.promoteHeatThreshold,\n staleDecayThreshold: thresholds.staleDecayThreshold,\n archiveDecayThreshold: thresholds.archiveDecayThreshold,\n protectedCategories: this.config.lifecycleProtectedCategories,\n };\n const actionPriors = await this.buildLifecycleActionPriors();\n\n for (const memory of allMemories) {\n if (memory.frontmatter.status === \"superseded\") {\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 this.storage.writeMemoryFrontmatter(memory, {\n lifecycleState: nextState,\n heatScore: decision.heatScore,\n decayScore: decision.decayScore,\n lastValidatedAt: nowIso,\n });\n if (wrote) updatedCount += 1;\n }\n\n if (!this.config.lifecycleMetricsEnabled) return;\n\n const total = evaluatedCount;\n const metrics = {\n generatedAt: nowIso,\n memoriesEvaluated: total,\n memoriesUpdated: updatedCount,\n countsByLifecycleState: countsByState,\n transitionCounts,\n staleRatio: total > 0 ? countsByState.stale / total : 0,\n disputedRatio: total > 0 ? disputedCount / total : 0,\n policy: {\n promoteHeatThreshold: thresholds.promoteHeatThreshold,\n staleDecayThreshold: thresholds.staleDecayThreshold,\n archiveDecayThreshold: thresholds.archiveDecayThreshold,\n protectedCategories: this.config.lifecycleProtectedCategories,\n },\n };\n const metricsPath = path.join(\n this.storage.dir,\n \"state\",\n \"lifecycle-metrics.json\",\n );\n await mkdir(path.dirname(metricsPath), { recursive: true });\n await writeFile(metricsPath, JSON.stringify(metrics, null, 2), \"utf-8\");\n }\n\n /**\n * Archive old, low-importance, rarely-accessed facts (v6.0).\n * Moves eligible facts from facts/ to archive/YYYY-MM-DD/.\n * Returns the number of archived facts.\n */\n private async runFactArchival(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<number> {\n const now = Date.now();\n const ageCutoffMs = this.config.factArchivalAgeDays * 24 * 60 * 60 * 1000;\n const protectedCategories = new Set(\n this.config.factArchivalProtectedCategories,\n );\n let archivedCount = 0;\n\n for (const memory of allMemories) {\n const fm = memory.frontmatter;\n\n // Skip already-archived or superseded\n if (fm.status && fm.status !== \"active\") continue;\n\n // Skip protected categories\n if (protectedCategories.has(fm.category)) continue;\n\n // Skip corrections (always keep)\n if (fm.category === \"correction\") continue;\n\n // Check age requirement\n const createdMs = new Date(fm.created).getTime();\n if (now - createdMs < ageCutoffMs) continue;\n\n // Check importance (only archive low-importance facts)\n const importanceScore = fm.importance?.score ?? 0.5;\n if (importanceScore >= this.config.factArchivalMaxImportance) continue;\n\n // Check access count\n const accessCount = fm.accessCount ?? 0;\n if (accessCount > this.config.factArchivalMaxAccessCount) continue;\n\n // All criteria met — archive\n const result = await this.storage.archiveMemory(memory);\n if (result) {\n // Remove from content-hash index since it's no longer in hot search.\n // Prefer the raw-content hash stored on the frontmatter at write\n // time (contentHash) — it is format-agnostic and survives any\n // citation template.\n if (this.contentHashIndex) {\n if (memory.frontmatter.contentHash) {\n // Modern memory: frontmatter.contentHash is already a SHA-256\n // hex string — use removeByHash to avoid double-hashing.\n this.contentHashIndex.removeByHash(memory.frontmatter.contentHash);\n } else {\n // Legacy memory written before contentHash was stored on the\n // frontmatter. Pre-#369 facts were stored without inline\n // citations, so memory.content is the raw fact text and we can\n // remove the hash directly from the content. This clears\n // stale dedup entries so the fact can be re-extracted.\n log.warn(\n `[fact-archival] removing hash for legacy memory ${memory.frontmatter.id ?? \"(unknown)\"} via content fallback — no contentHash in frontmatter`,\n );\n this.contentHashIndex.remove(memory.content);\n }\n }\n await this.embeddingFallback.removeFromIndex(memory.frontmatter.id);\n if (\n this.config.queryAwareIndexingEnabled &&\n memory.path &&\n memory.frontmatter?.created\n ) {\n deindexMemory(\n this.config.memoryDir,\n memory.path,\n memory.frontmatter.created,\n memory.frontmatter.tags ?? [],\n );\n }\n archivedCount++;\n }\n }\n\n // Save hash index if we removed any entries\n if (archivedCount > 0 && this.contentHashIndex) {\n await this.contentHashIndex\n .save()\n .catch((err) =>\n log.warn(`content-hash index save failed during archival: ${err}`),\n );\n }\n\n return archivedCount;\n }\n\n /**\n * Run memory summarization if memory count exceeds threshold (Phase 4A).\n */\n private async runSummarization(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<void> {\n // Only active memories count toward the threshold\n const activeMemories = allMemories.filter(\n (m) => !m.frontmatter.status || m.frontmatter.status === \"active\",\n );\n\n if (activeMemories.length < this.config.summarizationTriggerCount) {\n return;\n }\n\n log.info(\n `memory count (${activeMemories.length}) exceeds threshold (${this.config.summarizationTriggerCount}) — running summarization`,\n );\n\n // Sort by creation date, oldest first\n const sorted = activeMemories.sort(\n (a, b) =>\n new Date(a.frontmatter.created).getTime() -\n new Date(b.frontmatter.created).getTime(),\n );\n\n // Keep recent memories\n const toKeep = sorted.slice(-this.config.summarizationRecentToKeep);\n const toSummarize = sorted.slice(0, -this.config.summarizationRecentToKeep);\n\n // Filter candidates for summarization\n const candidates = toSummarize.filter((m) => {\n // Skip if protected by entity reference\n if (m.frontmatter.entityRef) return false;\n\n // Skip if protected by tag\n const protectedTags = this.config.summarizationProtectedTags;\n if (m.frontmatter.tags.some((t) => protectedTags.includes(t)))\n return false;\n\n // Skip if importance is above threshold\n const importance = m.frontmatter.importance?.score ?? 0.5;\n if (importance >= this.config.summarizationImportanceThreshold)\n return false;\n\n return true;\n });\n\n if (candidates.length < 50) {\n log.debug(\n `only ${candidates.length} candidates for summarization — skipping`,\n );\n return;\n }\n\n // Summarize in batches of 50\n const batchSize = 50;\n for (let i = 0; i < candidates.length; i += batchSize) {\n const batch = candidates.slice(i, i + batchSize);\n const batchData = batch.map((m) => ({\n id: m.frontmatter.id,\n content: m.content,\n category: m.frontmatter.category,\n created: m.frontmatter.created,\n }));\n\n const result = await this.extraction.summarizeMemories(batchData);\n if (!result) continue;\n\n // Create summary\n const summary: MemorySummary = {\n id: `summary-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`,\n createdAt: new Date().toISOString(),\n timeRangeStart: batch[0].frontmatter.created,\n timeRangeEnd: batch[batch.length - 1].frontmatter.created,\n summaryText: result.summaryText,\n keyFacts: result.keyFacts,\n keyEntities: result.keyEntities,\n sourceEpisodeIds: batch.map((m) => m.frontmatter.id),\n };\n\n await this.storage.writeSummary(summary);\n\n // Archive source memories\n const archived = await this.storage.archiveMemories(\n batch.map((m) => m.frontmatter.id),\n summary.id,\n );\n\n log.info(\n `created summary ${summary.id} from ${batch.length} memories, archived ${archived}`,\n );\n }\n }\n\n /**\n * Run topic extraction on all memories (Phase 4B).\n */\n private async runTopicExtraction(\n allMemories: import(\"./types.js\").MemoryFile[],\n ): Promise<void> {\n // Only extract from active memories\n const activeMemories = allMemories.filter(\n (m) => !m.frontmatter.status || m.frontmatter.status === \"active\",\n );\n\n if (activeMemories.length === 0) return;\n\n const topics = extractTopics(\n activeMemories,\n this.config.topicExtractionTopN,\n );\n await this.storage.saveTopics(topics);\n\n log.debug(\n `extracted ${topics.length} topics from ${activeMemories.length} memories`,\n );\n }\n\n /** Threshold (bytes) at which IDENTITY.md reflections get auto-consolidated */\n private static readonly IDENTITY_CONSOLIDATE_THRESHOLD = 8_000;\n\n private async autoConsolidateIdentity(): Promise<void> {\n const namespaces = this.config.namespacesEnabled\n ? this.configuredNamespaces()\n : [this.config.defaultNamespace];\n\n for (const namespace of namespaces) {\n const storage = await this.storageRouter.storageFor(namespace);\n const identityNamespace =\n this.config.namespacesEnabled &&\n namespace !== this.config.defaultNamespace\n ? namespace\n : undefined;\n const reflectionsContent =\n (await storage.readIdentityReflections()) ?? \"\";\n\n const existingIdentity = await storage.readIdentity(\n this.config.workspaceDir,\n identityNamespace,\n );\n const headerEnd =\n existingIdentity.indexOf(\"## Learned Patterns\") !== -1\n ? existingIdentity.indexOf(\"## Learned Patterns\")\n : existingIdentity.indexOf(\"## Reflection\");\n const staticHeader =\n (headerEnd !== -1\n ? existingIdentity.slice(0, headerEnd)\n : existingIdentity\n ).trimEnd() || \"# IDENTITY\";\n const identityContent = `${staticHeader}\\n\\n${reflectionsContent.trim()}\\n`;\n if (identityContent.length < Orchestrator.IDENTITY_CONSOLIDATE_THRESHOLD)\n continue;\n\n log.info(\n `IDENTITY(${namespace}) is ${identityContent.length} chars — auto-consolidating reflections`,\n );\n const result = await this.extraction.consolidateIdentity(\n identityContent,\n \"## Reflection\",\n );\n\n if (!result || result.learnedPatterns.length === 0) {\n log.warn(\n `identity consolidation produced no patterns for namespace=${namespace}`,\n );\n continue;\n }\n\n const patternsSection = [\n \"## Learned Patterns (consolidated from reflections, \" +\n new Date().toISOString().slice(0, 10) +\n \")\",\n \"\",\n ...result.learnedPatterns.map((p) => `- ${p}`),\n \"\",\n ].join(\"\\n\");\n\n const newContent = staticHeader + \"\\n\\n\" + patternsSection + \"\\n\";\n\n await storage.writeIdentity(\n this.config.workspaceDir,\n newContent,\n identityNamespace,\n );\n await storage.writeIdentityReflections(\"\");\n log.info(\n `IDENTITY(${namespace}) consolidated: ${identityContent.length} → ${newContent.length} chars, ${result.learnedPatterns.length} patterns`,\n );\n }\n }\n\n private formatQmdResults(title: string, results: QmdSearchResult[]): string {\n const lines = results.map((r, i) => {\n const snippet = r.snippet\n ? r.snippet.slice(0, 500).replace(/\\n/g, \" \")\n : \"(no preview)\";\n return `[${i + 1}] ${r.path} (score: ${r.score.toFixed(3)})\\n${snippet}`;\n });\n return `## ${title}\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatObjectiveStateResults(\n results: ObjectiveStateSearchResult[],\n ): string {\n const lines = results.map(({ snapshot }, index) => {\n const parts = [\n snapshot.recordedAt.replace(\"T\", \" \").slice(0, 16),\n `${snapshot.kind}/${snapshot.changeKind}`,\n ];\n if (snapshot.outcome) parts.push(snapshot.outcome);\n const header = `[${index + 1}] ${parts.join(\" | \")} | ${snapshot.scope}`;\n const detailParts = [snapshot.summary];\n if (snapshot.command) detailParts.push(`command: ${snapshot.command}`);\n else if (snapshot.toolName)\n detailParts.push(`tool: ${snapshot.toolName}`);\n return `${header}\\n${detailParts.join(\" | \")}`;\n });\n return `## Objective State\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatCausalTrajectoryResults(\n results: CausalTrajectorySearchResult[],\n ): string {\n const lines = results.map(({ record, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${record.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n record.outcomeKind,\n ].join(\" | \");\n const details = [\n `goal: ${record.goal}`,\n `action: ${record.actionSummary}`,\n `observation: ${record.observationSummary}`,\n `outcome: ${record.outcomeSummary}`,\n ];\n if (record.followUpSummary)\n details.push(`follow-up: ${record.followUpSummary}`);\n if (matchedFields.length > 0)\n details.push(`matched: ${matchedFields.join(\", \")}`);\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Causal Trajectories\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatTrustZoneResults(results: TrustZoneSearchResult[]): string {\n const lines = results.map(({ record, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${record.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n record.zone,\n record.kind,\n ].join(\" | \");\n const details = [\n record.summary,\n `provenance: ${record.provenance.sourceClass}`,\n ];\n if (record.entityRefs && record.entityRefs.length > 0) {\n details.push(`entities: ${record.entityRefs.join(\", \")}`);\n }\n if (record.tags && record.tags.length > 0) {\n details.push(`tags: ${record.tags.join(\", \")}`);\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Trust Zones\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatHarmonicRetrievalResults(\n results: HarmonicRetrievalResult[],\n ): string {\n const lines = results.map(\n (\n { node, matchedAnchors, matchedFields, nodeScore, anchorScore },\n index,\n ) => {\n const header = [\n `[${index + 1}] ${node.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n `${node.kind}/${node.abstractionLevel}`,\n node.sessionKey,\n ].join(\" | \");\n const details = [\n node.title,\n node.summary,\n `scores: node=${nodeScore.toFixed(1)} anchor=${anchorScore.toFixed(1)}`,\n ];\n if (matchedAnchors.length > 0) {\n details.push(\n `anchors: ${matchedAnchors.map((anchor) => `${anchor.anchorType}:${anchor.anchorValue}`).join(\"; \")}`,\n );\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Harmonic Retrieval\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatWorkProductResults(\n results: WorkProductLedgerSearchResult[],\n ): string {\n const lines = results.map(({ entry, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${entry.recordedAt.replace(\"T\", \" \").slice(0, 16)}`,\n `${entry.kind}/${entry.action}`,\n entry.sessionKey,\n ].join(\" | \");\n const details = [entry.summary, `scope: ${entry.scope}`];\n if (entry.artifactPath) details.push(`artifact: ${entry.artifactPath}`);\n if (entry.tags && entry.tags.length > 0)\n details.push(`tags: ${entry.tags.join(\", \")}`);\n if (matchedFields.length > 0)\n details.push(`matched: ${matchedFields.join(\", \")}`);\n return `${header}\\n${details.join(\"\\n\")}`;\n });\n\n return `## Work Products\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatVerifiedEpisodeResults(\n results: VerifiedEpisodeResult[],\n ): string {\n const lines = results.map(\n ({ box, verifiedEpisodeCount, matchedFields }, index) => {\n const header = [\n `[${index + 1}] ${box.sealedAt.replace(\"T\", \" \").slice(0, 16)}`,\n box.traceId ? `trace:${box.traceId.slice(0, 12)}` : \"trace:none\",\n ].join(\" | \");\n const details = [\n box.goal ?? `topics: ${box.topics.join(\", \")}`,\n `verified episodes: ${verifiedEpisodeCount}`,\n ];\n if (box.toolsUsed && box.toolsUsed.length > 0) {\n details.push(`tools: ${box.toolsUsed.join(\", \")}`);\n }\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Verified Episodes\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private formatVerifiedSemanticRuleResults(\n results: VerifiedSemanticRuleResult[],\n ): string {\n const lines = results.map(\n (\n {\n rule,\n sourceMemoryId,\n verificationStatus,\n effectiveConfidence,\n matchedFields,\n },\n index,\n ) => {\n const header = [\n `[${index + 1}] ${rule.frontmatter.updated.replace(\"T\", \" \").slice(0, 16)}`,\n verificationStatus,\n `confidence:${effectiveConfidence.toFixed(2)}`,\n ].join(\" | \");\n const details = [rule.content, `source memory: ${sourceMemoryId}`];\n if (matchedFields.length > 0) {\n details.push(`matched: ${matchedFields.join(\", \")}`);\n }\n return `${header}\\n${details.join(\"\\n\")}`;\n },\n );\n\n return `## Verified Rules\\n\\n${lines.join(\"\\n\\n\")}`;\n }\n\n private summarizeIdentityText(\n raw: string,\n maxLines: number,\n maxChars: number,\n ): string {\n const lines = raw\n .replace(/\\r/g, \"\")\n .split(\"\\n\")\n .map((line) => line.trim())\n .filter((line) => line.length > 0 && !line.startsWith(\"#\"));\n const compact = lines.slice(0, Math.max(1, maxLines)).join(\" \");\n if (compact.length <= maxChars) return compact;\n return `${compact.slice(0, Math.max(0, maxChars - 1))}…`;\n }\n\n private formatOpenIncidentLine(\n incident: ContinuityIncidentRecord,\n includeDetails: boolean,\n ): string {\n const base = `[${incident.id}] ${incident.symptom.trim()}`;\n if (!includeDetails) return `- ${base}`;\n const parts = [base];\n if (incident.suspectedCause)\n parts.push(`cause: ${incident.suspectedCause.trim()}`);\n if (incident.triggerWindow)\n parts.push(`window: ${incident.triggerWindow.trim()}`);\n return `- ${parts.join(\" | \")}`;\n }\n\n private trimIdentitySection(\n content: string,\n maxChars: number,\n ): { text: string; truncated: boolean } {\n if (maxChars <= 0) return { text: \"\", truncated: false };\n if (content.length <= maxChars) return { text: content, truncated: false };\n const suffix = \"\\n\\n...(identity continuity trimmed)\";\n if (maxChars <= suffix.length) {\n return { text: content.slice(0, maxChars), truncated: true };\n }\n const headroom = Math.max(0, maxChars - suffix.length);\n return { text: `${content.slice(0, headroom)}${suffix}`, truncated: true };\n }\n\n private async buildIdentityContinuitySection(options: {\n storage: StorageManager;\n recallMode: RecallPlanMode;\n prompt: string;\n }): Promise<{\n section: string;\n mode: IdentityInjectionMode;\n injectedChars: number;\n truncated: boolean;\n } | null> {\n if (!this.config.identityContinuityEnabled) return null;\n if (this.config.identityMaxInjectChars <= 0) return null;\n\n const resolved = resolveEffectiveIdentityInjectionMode({\n configuredMode: this.config.identityInjectionMode,\n recallMode: options.recallMode,\n prompt: options.prompt,\n });\n if (!resolved.shouldInject) return null;\n\n const [anchorRaw, loopsRaw, incidents] = await Promise.all([\n options.storage.readIdentityAnchor(),\n options.storage.readIdentityImprovementLoops(),\n options.storage.readContinuityIncidents(200),\n ]);\n const openIncidents = incidents.filter(\n (incident) => incident.state === \"open\",\n );\n\n const lines: string[] = [];\n if (resolved.mode === \"full\") {\n lines.push(\"## Identity Continuity\");\n if (anchorRaw && anchorRaw.trim().length > 0) {\n lines.push(\"\", \"### Anchor\", \"\", anchorRaw.trim());\n }\n if (loopsRaw && loopsRaw.trim().length > 0) {\n lines.push(\"\", \"### Improvement Loops\", \"\", loopsRaw.trim());\n }\n lines.push(\"\", \"### Open Incidents\", \"\");\n if (openIncidents.length === 0) {\n lines.push(\"- none\");\n } else {\n lines.push(\n ...openIncidents\n .slice(0, 5)\n .map((incident) => this.formatOpenIncidentLine(incident, true)),\n );\n }\n } else {\n const anchorSummary = anchorRaw\n ? this.summarizeIdentityText(anchorRaw, 3, 320)\n : \"\";\n const loopsSummary = loopsRaw\n ? this.summarizeIdentityText(loopsRaw, 2, 240)\n : \"\";\n lines.push(\"## Identity Continuity Signals\", \"\");\n if (anchorSummary) lines.push(`- anchor: ${anchorSummary}`);\n if (loopsSummary) lines.push(`- loops: ${loopsSummary}`);\n if (openIncidents.length === 0) {\n lines.push(\"- incidents: 0 open\");\n } else {\n lines.push(`- incidents: ${openIncidents.length} open`);\n lines.push(\n ...openIncidents\n .slice(0, 2)\n .map((incident) => this.formatOpenIncidentLine(incident, false)),\n );\n }\n }\n\n const body = lines.join(\"\\n\").trim();\n if (!body) return null;\n\n const { text, truncated } = this.trimIdentitySection(\n body,\n this.config.identityMaxInjectChars,\n );\n if (!text) return null;\n\n return {\n section: text,\n mode: resolved.mode,\n injectedChars: text.length,\n truncated,\n };\n }\n\n private emitTrace(event: EngramTraceEvent): void {\n try {\n const cb = (globalThis as any).__openclawEngramTrace;\n if (typeof cb === \"function\") cb(event);\n } catch (err) {\n log.debug(`trace callback failed: ${err}`);\n }\n }\n\n private queueEvalShadowRecall(\n record: Omit<EvalShadowRecallRecord, \"schemaVersion\">,\n ): void {\n if (!this.config.evalHarnessEnabled || !this.config.evalShadowModeEnabled)\n return;\n this.evalShadowWriteChain = this.evalShadowWriteChain\n .catch(() => undefined)\n .then(async () => {\n try {\n await recordEvalShadowRecall({\n memoryDir: this.config.memoryDir,\n evalStoreDir: this.config.evalStoreDir,\n record: {\n schemaVersion: 1,\n ...record,\n },\n });\n } catch (err) {\n log.debug(`eval shadow recall write failed: ${err}`);\n }\n });\n }\n\n private publishRecallResults(options: {\n title: string;\n results: QmdSearchResult[];\n sectionBuckets: Map<string, string[]>;\n retrievalQuery: string;\n sessionKey: string | undefined;\n identityInjection?: {\n mode: IdentityInjectionMode | \"none\";\n injectedChars: number;\n truncated: boolean;\n };\n }): void {\n const sectionId = \"memories\";\n const memoryIds = this.extractMemoryIdsFromResults(options.results);\n this.trackMemoryAccess(memoryIds);\n\n this.appendRecallSection(\n options.sectionBuckets,\n sectionId,\n this.formatQmdResults(options.title, options.results),\n );\n }\n\n /**\n * Apply MMR over the pre-truncation recall candidate pool and then slice\n * the result to `limit`. This is the single place in the pipeline where\n * MMR runs, and it must be called *before* callers throw away candidates\n * that would otherwise sit below the final cutoff. Running MMR post-slice\n * is a no-op in the cases we care about — diverse candidates just below\n * the cutoff are already gone and can never be promoted.\n *\n * Callers must pass the full candidate pool (post-rerank, pre-slice).\n */\n private async applyMemoryWorthRerank(\n results: QmdSearchResult[],\n namespaces: string[],\n ): Promise<QmdSearchResult[]> {\n // Build the counter lookup. We union frontmatter counters across every\n // namespace the recall spans — the recall path itself already\n // aggregates candidates from multiple namespaces, so we must do the\n // same when looking up counters. Per-namespace results are cached with\n // a short TTL so interactive recall doesn't trigger a full\n // `readAllMemories` scan per query (addresses codex P2 on PR 4).\n const counters = new Map<string, MemoryWorthCounters>();\n const seenNamespaces = new Set<string>();\n const nowMs = Date.now();\n\n // Evict all expired entries on every call so long-running processes\n // touching a high-cardinality namespace set (coding/project overlays,\n // per-branch) don't grow the cache unboundedly. Without this, an entry\n // for a namespace that's never looked up again would pin its full\n // counter map forever.\n for (const [key, entry] of this.memoryWorthCounterCache) {\n if (nowMs - entry.at >= Orchestrator.MEMORY_WORTH_CACHE_TTL_MS) {\n this.memoryWorthCounterCache.delete(key);\n }\n }\n\n for (const ns of namespaces) {\n if (seenNamespaces.has(ns)) continue;\n seenNamespaces.add(ns);\n try {\n const cached = this.memoryWorthCounterCache.get(ns);\n let nsMap: ReadonlyMap<string, MemoryWorthCounters> | undefined;\n if (\n cached &&\n nowMs - cached.at < Orchestrator.MEMORY_WORTH_CACHE_TTL_MS\n ) {\n nsMap = cached.counters;\n } else {\n const storage = await this.getStorage(ns);\n const memories = await storage.readAllMemories();\n nsMap = buildMemoryWorthCounterMap(memories);\n this.memoryWorthCounterCache.set(ns, { at: nowMs, counters: nsMap });\n }\n for (const [path, c] of nsMap) counters.set(path, c);\n } catch (err) {\n log.debug(\"memory-worth: failed to read namespace, skipping\", {\n namespace: ns,\n error: (err as Error).message,\n });\n }\n }\n\n // For candidates whose path didn't show up in any hot-tier namespace\n // scan (typical of cold-tier / archive fallback), try a direct\n // per-path read. Without this, cold-tier candidates always stay at\n // multiplier 1.0 even when they have outcome history. Errors are\n // swallowed so a single unreadable archive entry can't break the\n // whole recall.\n const missing = results.filter((r) => !counters.has(r.path));\n if (missing.length > 0) {\n // Use the first-seen namespace's storage as the reader — all\n // StorageManagers share the same on-disk format, and\n // `readMemoryByPath` takes an absolute path so the baseDir doesn't\n // have to match.\n let reader: StorageManager | null = null;\n for (const ns of namespaces) {\n try {\n reader = await this.getStorage(ns);\n break;\n } catch {\n // try next namespace\n }\n }\n if (reader) {\n for (const r of missing) {\n try {\n const memory = await reader.readMemoryByPath(r.path);\n if (!memory) continue;\n const fm = memory.frontmatter;\n if (fm.mw_success === undefined && fm.mw_fail === undefined) continue;\n counters.set(r.path, {\n mw_success: fm.mw_success,\n mw_fail: fm.mw_fail,\n lastAccessed: fm.lastAccessed,\n });\n } catch (err) {\n log.debug(\"memory-worth: direct path lookup failed\", {\n path: r.path,\n error: (err as Error).message,\n });\n }\n }\n }\n }\n\n // If no memory in the candidate set has any counter data, the filter\n // would be a no-op — skip the reorder to avoid spurious log spam.\n if (counters.size === 0) return results;\n\n // Preserve upstream ordering (reranker, specialized tiers, etc.) for\n // neutral candidates. The upstream stages set `memoryResults` in their\n // intended order but often leave `r.score` as the raw QMD score. If we\n // sorted by `r.score * multiplier` directly, neutral candidates\n // (multiplier 1.0) would snap back to raw-QMD order and silently undo\n // the reranker. Feed the filter a synthetic monotone-decreasing rank\n // score so it uses input position as the baseline, then applies the\n // multiplier on top. Ties fall back to the stable secondary key in\n // `applyMemoryWorthFilter`.\n const rankedInputs = results.map((r, i) => ({\n path: r.path,\n // Large positive rank score so multiplier math stays well-scaled and\n // we never hit zero; descending so earlier items rank higher.\n score: results.length - i,\n }));\n const filtered = applyMemoryWorthFilter(rankedInputs, {\n counters,\n now: new Date(),\n halfLifeMs:\n this.config.recallMemoryWorthHalfLifeMs > 0\n ? this.config.recallMemoryWorthHalfLifeMs\n : undefined,\n });\n\n // Reconstruct the QmdSearchResult list in the new order. `.score` is\n // preserved from the upstream pipeline (rerank, tier scoring, etc.) —\n // we only reorder. Writing the synthetic rank-weighted score back\n // would contaminate downstream logic (telemetry, confidence gates)\n // that expects the original QMD/rerank score semantics.\n const byPath = new Map(results.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const item of filtered) {\n const original = byPath.get(item.path);\n if (original) reordered.push(original);\n }\n return reordered;\n }\n\n private diversifyAndLimitRecallResults(\n sectionId: string,\n results: QmdSearchResult[],\n limit: number,\n retrievalQuery?: string,\n ): QmdSearchResult[] {\n const safeLimit =\n typeof limit === \"number\" && Number.isFinite(limit)\n ? Math.max(0, Math.floor(limit))\n : 0;\n if (!Array.isArray(results) || results.length === 0) return [];\n // `recallResultLimit === 0` is a true zero limit (e.g. when\n // `memoriesSectionEnabled` is false) and must return an empty array so\n // the memories section is genuinely skipped. This mirrors the\n // `slice(0, 0)` semantics of every call site this helper replaced.\n if (safeLimit === 0) return [];\n // Issue #564 PR 3: when the feature flag is on, boost reasoning_trace\n // memories for problem-solving asks so they bubble up ahead of ordinary\n // facts/decisions before MMR picks the final section. No-op when the\n // flag is off or the query is not a problem-solving ask.\n const boosted =\n this.config.recallReasoningTraceBoostEnabled && typeof retrievalQuery === \"string\"\n ? applyReasoningTraceBoost(results, {\n enabled: true,\n query: retrievalQuery,\n })\n : results;\n const diversified = this.applyMmrToQmdResults(sectionId, boosted);\n return diversified.slice(0, safeLimit);\n }\n\n /**\n * Apply Maximal Marginal Relevance to a section's ordered candidate list.\n *\n * Operates per-section so one redundant cluster cannot dominate a section,\n * and so one section's MMR pass cannot starve other sections. Returns the\n * input unchanged when disabled, when there are fewer than 2 candidates, or\n * when no budget information is available.\n */\n private applyMmrToQmdResults(\n sectionId: string,\n results: QmdSearchResult[],\n ): QmdSearchResult[] {\n if (this.config.recallMmrEnabled === false) return results;\n if (!Array.isArray(results) || results.length < 2) return results;\n\n // Config is runtime API (see AGENTS.md §4): preserve `0` as a true zero\n // limit rather than coercing it to a non-zero value. A configured topN of\n // 0 means \"apply MMR over an empty window\" — i.e. skip the reorder and\n // return the upstream candidates unchanged. This keeps read-time\n // behavior symmetric with the write-time semantics parseConfig exposes.\n const configuredTopN = this.config.recallMmrTopN;\n const topN =\n typeof configuredTopN === \"number\" && Number.isFinite(configuredTopN)\n ? Math.max(0, Math.floor(configuredTopN))\n : 40;\n if (topN === 0) return results;\n const lambda = this.config.recallMmrLambda ?? 0.7;\n\n // Delegate to the pure helper so candidate keying (path-first, index\n // suffixed for uniqueness) and the head-of-list diversity metric are\n // exercised by the same code path that the unit tests cover.\n const { reordered, diversity } = reorderRecallResultsWithMmr(results, {\n lambda,\n topN,\n });\n\n try {\n log.info(\n `recall_mmr: section=${sectionId} kept=${diversity.kept}/${diversity.considered} ` +\n `headReorderCount=${diversity.headReorderCount} ` +\n `avgSimBefore=${diversity.avgPairwiseSimBefore.toFixed(3)} ` +\n `avgSimAfter=${diversity.avgPairwiseSimAfter.toFixed(3)} ` +\n `lambda=${lambda.toFixed(2)}`,\n );\n } catch {\n // Metrics must never break recall.\n }\n\n return reordered;\n }\n\n private buildLastRecallBudgetSummary(options: {\n requestedTopK?: number;\n recallResultLimit: number;\n qmdFetchLimit: number;\n qmdHybridFetchLimit: number;\n finalContextChars?: number;\n truncated?: boolean;\n includedSections?: string[];\n omittedSections?: string[];\n }): LastRecallBudgetSummary {\n return {\n requestedTopK: options.requestedTopK,\n appliedTopK: options.recallResultLimit,\n recallBudgetChars: this.getRecallBudgetChars(),\n maxMemoryTokens: this.config.maxMemoryTokens,\n qmdFetchLimit: options.qmdFetchLimit,\n qmdHybridFetchLimit: options.qmdHybridFetchLimit,\n finalContextChars: options.finalContextChars,\n truncated: options.truncated,\n includedSections: [...(options.includedSections ?? [])],\n omittedSections: [...(options.omittedSections ?? [])],\n };\n }\n\n private collectLastRecallSources(\n sectionBuckets: Map<string, string[]>,\n recallSource:\n | \"none\"\n | \"hot_qmd\"\n | \"hot_embedding\"\n | \"cold_fallback\"\n | \"recent_scan\",\n ): string[] {\n const used = new Set<string>();\n if (recallSource !== \"none\") {\n used.add(recallSource);\n }\n for (const [sectionId, chunks] of sectionBuckets.entries()) {\n if (chunks.length > 0) {\n used.add(sectionId);\n }\n }\n return [...used];\n }\n\n /**\n * Issue #373 — nearest-neighbor lookup for the write-time semantic dedup\n * guard. Returns the top-K embedding hits against the currently indexed\n * memories, or an empty array when the embedding backend is unavailable.\n * Intentionally does NOT throw; `decideSemanticDedup` treats both \"empty\"\n * and \"error\" outcomes as fail-open (keep the candidate).\n *\n * PR #399 P1 fix: when namespaces are enabled the lookup must be scoped\n * to the SAME namespace as the fact being written. Otherwise a\n * high-similarity memory from another namespace can suppress a write in\n * the target namespace — cross-tenant data loss. Callers pass the target\n * storage so we can translate its root directory into the correct index\n * path prefix (and, for the legacy default-namespace layout at\n * `memoryDir` root, an exclusion list for `namespaces/*`).\n */\n async semanticDedupLookup(\n content: string,\n limit: number,\n targetStorage: StorageManager,\n ): Promise<SemanticDedupHit[]> {\n // Round 6 fix (Finding 3): backend-unavailable conditions must THROW so\n // that `decideSemanticDedup`'s catch block can return\n // reason=\"backend_unavailable\". Previously all error/unavailable paths\n // returned [] — causing decideSemanticDedup to always report\n // reason=\"no_candidates\" even when the provider was actually down.\n //\n // Contract after this fix:\n // • embeddingFallbackEnabled=false → throw (feature not configured;\n // caller treats this as backend_unavailable and fails open).\n // • isAvailable() returns false → throw (provider is reachable but\n // reports itself unavailable; distinct from empty index).\n // • search() throws → re-throw (network/provider error).\n // • search() returns [] → return [] (empty index, not a\n // backend failure; decideSemanticDedup reports no_candidates).\n if (!this.config.embeddingFallbackEnabled) {\n throw new Error(\"semantic dedup: embedding backend not configured\");\n }\n if (!(await this.embeddingFallback.isAvailable())) {\n log.debug(\"semantic dedup: embedding backend unavailable, skipping\");\n throw new Error(\"semantic dedup: embedding backend unavailable\");\n }\n // search() may throw — let it propagate so decideSemanticDedup catches it\n // and returns reason=\"backend_unavailable\". Pass throwOnTimeout:true so\n // EmbeddingTimeoutError is re-thrown here (Round 10 fix, Ui1J+Ui1L: the\n // recall-path caller searchEmbeddingFallback does NOT pass this flag,\n // keeping its fail-open [] contract on timeout).\n const scope = this.semanticDedupScopeFor(targetStorage);\n const hits = await this.embeddingFallback.search(content, limit, { ...scope, throwOnTimeout: true });\n if (!Array.isArray(hits) || hits.length === 0) return [];\n return hits.map((hit) => ({\n id: hit.id,\n score: hit.score,\n path: hit.path,\n }));\n }\n\n /**\n * Resolve the namespace-scoped filter to pass into\n * `EmbeddingFallback.search()` for semantic dedup. Returns an empty\n * object (no filter) when namespaces are disabled, preserving the\n * pre-PR #399 behavior for single-tenant installs.\n *\n * Index entries are stored as paths relative to `config.memoryDir`, so:\n * - A non-default namespace `ns` lives under `namespaces/<ns>/…` and\n * we include exactly that prefix.\n * - The default namespace may live at `memoryDir` root (legacy) or at\n * `memoryDir/namespaces/<default>/…` (migrated). When it lives at\n * root we include everything but EXCLUDE all `namespaces/…` entries\n * so facts from non-default namespaces can't cross-match.\n */\n private semanticDedupScopeFor(targetStorage: StorageManager): {\n pathPrefix?: string;\n pathExcludePrefixes?: readonly string[];\n } {\n if (!this.config.namespacesEnabled) return {};\n const memoryDir = path.resolve(this.config.memoryDir);\n const storageDir = path.resolve(targetStorage.dir);\n if (storageDir === memoryDir) {\n // Default namespace at legacy root. Include everything that isn't\n // under `namespaces/*` (those belong to other namespaces).\n return { pathExcludePrefixes: [\"namespaces/\"] };\n }\n let rel = path.relative(memoryDir, storageDir);\n if (!rel || rel.startsWith(\"..\")) {\n // Round 12 fix (PR #399 thread PRRT_kwDORJXyws56U6Gj): when\n // targetStorage.dir is outside memoryDir (custom namespace routing),\n // toMemoryRelativePath() stores the absolute file path in the index\n // rather than a memoryDir-relative path. Return the absolute storageDir\n // as the pathPrefix so the search() filter still scopes the lookup to\n // the correct tenant's files. Previously this returned {} (no scoping),\n // which let high-similarity hits from other namespaces' absolute-path\n // entries suppress writes in the target namespace — a cross-tenant\n // dedup suppression path.\n log.debug(\n `semantic dedup: target storage dir ${storageDir} is outside memoryDir ${memoryDir}; scoping lookup to absolute path prefix`,\n );\n const absPrefix = storageDir.replace(/\\\\/g, \"/\");\n return { pathPrefix: absPrefix.endsWith(\"/\") ? absPrefix : `${absPrefix}/` };\n }\n rel = rel.replace(/\\\\/g, \"/\");\n if (!rel.endsWith(\"/\")) rel = `${rel}/`;\n return { pathPrefix: rel };\n }\n\n private async searchEmbeddingFallback(\n query: string,\n limit: number,\n ): Promise<QmdSearchResult[]> {\n if (!this.config.embeddingFallbackEnabled) return [];\n if (!(await this.embeddingFallback.isAvailable())) return [];\n const hits = await this.embeddingFallback.search(query, limit);\n if (hits.length === 0) return [];\n\n const results: QmdSearchResult[] = [];\n for (const hit of hits) {\n const fullPath = path.isAbsolute(hit.path)\n ? hit.path\n : path.join(this.config.memoryDir, hit.path);\n const memory = await this.storage.readMemoryByPath(fullPath);\n if (!memory) continue;\n results.push({\n docid: hit.id,\n path: fullPath,\n score: hit.score,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n });\n }\n return results;\n }\n\n /**\n * Long-term fallback retrieval.\n * Searches archived memories only, and is invoked only when hot recall returns zero hits.\n */\n private async searchLongTermArchiveFallback(\n prompt: string,\n recallNamespaces: string[],\n limit: number,\n queryAwarePrefilter?: QueryAwarePrefilter,\n abortSignal?: AbortSignal,\n ): Promise<QmdSearchResult[]> {\n throwIfRecallAborted(abortSignal);\n const cappedLimit = Math.max(0, limit);\n if (cappedLimit === 0) return [];\n\n const scopedSeedResults = queryAwarePrefilter?.candidatePaths?.size\n ? await this.searchScopedMemoryCandidates(\n queryAwarePrefilter.candidatePaths,\n prompt,\n cappedLimit,\n { allowArchived: true },\n )\n : [];\n if (scopedSeedResults.length >= cappedLimit) {\n return scopedSeedResults\n .filter((result) => !isArtifactMemoryPath(result.path))\n .slice(0, cappedLimit);\n }\n\n const tokens = Array.from(new Set(tokenizeRecallQuery(prompt)));\n if (tokens.length === 0) return scopedSeedResults;\n\n throwIfRecallAborted(abortSignal);\n const archivedMemories =\n await this.readArchivedMemoriesForNamespaces(recallNamespaces);\n if (archivedMemories.length === 0) return scopedSeedResults;\n\n const scored: QmdSearchResult[] = [];\n for (const memory of archivedMemories) {\n throwIfRecallAborted(abortSignal);\n const haystack = [\n memory.content,\n memory.frontmatter.category,\n ...(memory.frontmatter.tags ?? []),\n ]\n .join(\" \")\n .toLowerCase();\n let hits = 0;\n for (const token of tokens) {\n if (haystack.includes(token)) hits += 1;\n }\n if (hits === 0) continue;\n const normalized = hits / tokens.length;\n scored.push({\n docid: memory.frontmatter.id,\n path: memory.path,\n score: normalized,\n snippet: memory.content.slice(0, 400).replace(/\\n/g, \" \"),\n });\n }\n\n const mergedByPath = new Map<string, QmdSearchResult>();\n for (const result of [...scopedSeedResults, ...scored]) {\n const key = result.path || result.docid;\n const existing = mergedByPath.get(key);\n if (!existing || result.score > existing.score) {\n mergedByPath.set(key, {\n ...result,\n snippet: result.snippet || existing?.snippet || \"\",\n });\n }\n }\n\n return [...mergedByPath.values()]\n .filter((result) => !isArtifactMemoryPath(result.path))\n .sort((a, b) => b.score - a.score)\n .slice(0, cappedLimit);\n }\n\n private async applyColdFallbackPipeline(options: {\n prompt: string;\n recallNamespaces: string[];\n recallResultLimit: number;\n recallMode: RecallPlanMode;\n queryAwarePrefilter?: QueryAwarePrefilter;\n abortSignal?: AbortSignal;\n /**\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 }): Promise<QmdSearchResult[]> {\n const coldQmdEnabled = this.config.qmdColdTierEnabled === true;\n const coldCollection =\n this.config.qmdColdCollection ?? \"openclaw-engram-cold\";\n const coldMaxResults =\n this.config.qmdColdMaxResults ?? this.config.qmdMaxResults;\n\n let longTerm: QmdSearchResult[] = [];\n if (coldQmdEnabled && this.qmd.isAvailable()) {\n const coldFetchLimit = Math.max(\n 0,\n Math.min(options.recallResultLimit, Math.max(0, coldMaxResults)),\n );\n if (coldFetchLimit > 0) {\n const coldHybridLimit = computeQmdHybridFetchLimit(\n coldFetchLimit,\n false,\n 0,\n );\n longTerm = await this.fetchQmdMemoryResultsWithArtifactTopUp(\n options.prompt,\n coldFetchLimit,\n coldHybridLimit,\n {\n namespacesEnabled: this.config.namespacesEnabled,\n recallNamespaces: options.recallNamespaces,\n resolveNamespace: (p) => this.namespaceFromPath(p),\n collection: coldCollection,\n queryAwarePrefilter: options.queryAwarePrefilter,\n searchOptions: this.buildConfiguredQmdSearchOptions(options.prompt),\n abortSignal: options.abortSignal,\n },\n );\n if (longTerm.length > 0) {\n log.debug(\n `cold-tier recall source=cold-qmd collection=${coldCollection} hits=${longTerm.length}`,\n );\n }\n }\n }\n if (longTerm.length === 0) {\n longTerm = await this.searchLongTermArchiveFallback(\n options.prompt,\n options.recallNamespaces,\n options.recallResultLimit,\n options.queryAwarePrefilter,\n options.abortSignal,\n );\n if (longTerm.length > 0) {\n log.debug(\"cold-tier recall source=archive-scan\");\n }\n }\n if (longTerm.length === 0) return [];\n\n let results = longTerm;\n if (this.config.namespacesEnabled) {\n results = results.filter((r) =>\n options.recallNamespaces.includes(this.namespaceFromPath(r.path)),\n );\n }\n // Artifact isolation contract: generic recall paths must exclude artifacts.\n results = results.filter((r) => !isArtifactMemoryPath(r.path));\n if (results.length === 0) return [];\n\n const isFullModeGraphAssist =\n this.config.qmdTierParityGraphEnabled &&\n this.config.multiGraphMemoryEnabled &&\n this.config.graphAssistInFullModeEnabled !== false &&\n options.recallMode === \"full\" &&\n results.length >= Math.max(1, this.config.graphAssistMinSeedResults ?? 3);\n const shouldRunGraphExpansion =\n this.config.qmdTierParityGraphEnabled &&\n (options.recallMode === \"graph_mode\" || isFullModeGraphAssist);\n\n if (shouldRunGraphExpansion) {\n const { merged } = await this.expandResultsViaGraph({\n memoryResults: results,\n recallNamespaces: options.recallNamespaces,\n recallResultLimit: options.recallResultLimit,\n });\n results = merged;\n }\n\n results = await this.boostSearchResults(\n results,\n options.recallNamespaces,\n options.prompt,\n undefined,\n { allowLifecycleFiltered: true },\n );\n\n if (this.config.rerankEnabled && this.config.rerankProvider === \"local\") {\n const ranked = await rerankLocalOrNoop({\n query: options.prompt,\n candidates: results\n .slice(0, this.config.rerankMaxCandidates)\n .map((r) => ({\n id: r.path,\n snippet: r.snippet || r.path,\n })),\n local: this.fastLlmForRerank,\n enabled: true,\n timeoutMs: this.config.rerankTimeoutMs,\n maxCandidates: this.config.rerankMaxCandidates,\n cache: this.rerankCache,\n cacheEnabled: this.config.rerankCacheEnabled,\n cacheTtlMs: this.config.rerankCacheTtlMs,\n });\n if (ranked && ranked.length > 0) {\n const byPath = new Map(results.map((r) => [r.path, r]));\n const reordered: QmdSearchResult[] = [];\n for (const p of ranked) {\n const it = byPath.get(p);\n if (it) reordered.push(it);\n }\n const rankedSet = new Set(ranked);\n for (const r of results) {\n if (!rankedSet.has(r.path)) reordered.push(r);\n }\n results = reordered;\n }\n }\n if (this.config.rerankEnabled && this.config.rerankProvider === \"cloud\") {\n log.debug(\n \"rerankProvider=cloud is reserved/experimental in v2.2.0; skipping rerank\",\n );\n }\n\n // Memory Worth filter — must fire on the cold fallback path too, or the\n // feature flag produces divergent behavior by retrieval path (CLAUDE.md\n // rule 39). Fail-open on lookup errors.\n if (this.config.recallMemoryWorthFilterEnabled && results.length > 0) {\n try {\n results = await this.applyMemoryWorthRerank(results, options.recallNamespaces);\n } catch (err) {\n log.debug(\"memory-worth filter (cold) failed open\", {\n error: (err as Error).message,\n });\n }\n }\n\n // Apply MMR before final truncation so the cold fallback path mirrors\n // the diversification policy applied in the hot QMD/embedding/recent\n // paths. Running MMR post-slice would be unable to promote diverse\n // candidates sitting just below the cutoff.\n if (options.xrayPoolSizeSink) {\n options.xrayPoolSizeSink.size = Math.max(\n options.xrayPoolSizeSink.size,\n results.length,\n );\n }\n return this.diversifyAndLimitRecallResults(\n \"memories\",\n results,\n options.recallResultLimit,\n options.prompt,\n );\n }\n\n // ---------------------------------------------------------------------------\n // Access Tracking (Phase 1A)\n // ---------------------------------------------------------------------------\n\n /**\n * Record that memories were accessed (retrieved).\n * Updates are batched in memory and flushed during consolidation.\n */\n trackMemoryAccess(memoryIds: string[]): void {\n if (!this.config.accessTrackingEnabled) return;\n\n const now = new Date().toISOString();\n for (const id of memoryIds) {\n const existing = this.accessTrackingBuffer.get(id);\n this.accessTrackingBuffer.set(id, {\n count: (existing?.count ?? 0) + 1,\n lastAccessed: now,\n });\n }\n\n // Flush if buffer exceeds max size\n if (\n this.accessTrackingBuffer.size >= this.config.accessTrackingBufferMaxSize\n ) {\n this.flushAccessTracking().catch((err) =>\n log.debug(`background access tracking flush failed: ${err}`),\n );\n }\n }\n\n /**\n * Flush access tracking buffer to disk.\n * Called during consolidation or when buffer is full.\n */\n async flushAccessTracking(): Promise<void> {\n if (this.accessTrackingBuffer.size === 0) return;\n\n // Build entries from buffer, merging with existing counts\n const entries: AccessTrackingEntry[] = [];\n const namespaces = this.config.namespacesEnabled\n ? Array.from(\n new Set<string>([\n this.config.defaultNamespace,\n this.config.sharedNamespace,\n ...this.config.namespacePolicies.map((p) => p.name),\n ]),\n )\n : [this.config.defaultNamespace];\n const memories = await this.readAllMemoriesForNamespaces(namespaces);\n const memoryMap = new Map(memories.map((m) => [m.frontmatter.id, m]));\n\n for (const [memoryId, update] of this.accessTrackingBuffer) {\n const memory = memoryMap.get(memoryId);\n const existingCount = memory?.frontmatter.accessCount ?? 0;\n entries.push({\n memoryId,\n newCount: existingCount + update.count,\n lastAccessed: update.lastAccessed,\n });\n }\n\n const byNamespace = new Map<string, AccessTrackingEntry[]>();\n for (const e of entries) {\n const m = memoryMap.get(e.memoryId);\n if (!m) continue;\n const ns = this.namespaceFromPath(m.path);\n const list = byNamespace.get(ns) ?? [];\n list.push(e);\n byNamespace.set(ns, list);\n }\n for (const [ns, list] of byNamespace) {\n const sm = await this.storageRouter.storageFor(ns);\n await sm.flushAccessTracking(list);\n }\n this.accessTrackingBuffer.clear();\n log.debug(`flushed ${entries.length} access tracking entries`);\n }\n\n /**\n * Apply recency, access count, and importance boosting to QMD search results.\n * Returns re-ranked results.\n */\n private async boostSearchResults(\n results: QmdSearchResult[],\n _recallNamespaces: string[],\n prompt?: string,\n preloadedMemoryMap?: Map<string, MemoryFile>,\n options?: {\n allowLifecycleFiltered?: boolean;\n allowDedicatedSurface?: boolean;\n },\n ): Promise<QmdSearchResult[]> {\n if (results.length === 0) return results;\n\n const now = Date.now();\n // Seed with any pre-loaded memories (e.g. from the recency fallback path)\n // to avoid redundant disk reads for files already in memory.\n const memoryByPath: Map<string, MemoryFile> = preloadedMemoryMap\n ? new Map(preloadedMemoryMap)\n : new Map();\n\n // Determine temporal/tag query params before I/O (pure computation).\n const resultPaths = new Set(\n results.map((r) => r.path).filter(Boolean) as string[],\n );\n let temporalFromDate: string | null = null;\n let promptTags: string[] = [];\n if (this.config.queryAwareIndexingEnabled && prompt) {\n if (isTemporalQuery(prompt)) {\n temporalFromDate = recencyWindowFromPrompt(prompt, now);\n }\n promptTags = extractTagsFromPrompt(prompt);\n }\n\n // Run all file I/O in parallel: memory files not yet preloaded + index files.\n const [, rawTemporal, rawTags] = await Promise.all([\n Promise.all(\n results.map(async (r) => {\n if (!r.path || memoryByPath.has(r.path)) return;\n const mem = await this.storage.readMemoryByPath(r.path);\n if (mem) memoryByPath.set(r.path, mem);\n }),\n ),\n temporalFromDate !== null\n ? queryByDateRangeAsync(this.config.memoryDir, temporalFromDate)\n : Promise.resolve<Set<string> | null>(null),\n promptTags.length > 0\n ? queryByTagsAsync(this.config.memoryDir, promptTags)\n : Promise.resolve<Set<string> | null>(null),\n ]);\n\n const queryIntent =\n this.config.intentRoutingEnabled && prompt\n ? inferIntentFromText(prompt)\n : null;\n\n // v8.1: Temporal + Tag prefilter candidate set\n // Scope to result paths first so cross-namespace paths don't consume the cap.\n let temporalCandidates: Set<string> | null = null;\n let tagCandidates: Set<string> | null = null;\n if (this.config.queryAwareIndexingEnabled && prompt) {\n const maxCandidates = this.config.queryAwareIndexingMaxCandidates;\n const capSet = (s: Set<string> | null): Set<string> | null => {\n if (!s) return null;\n // Intersect with result paths first so out-of-scope paths don't exhaust the budget\n const scoped = new Set(Array.from(s).filter((p) => resultPaths.has(p)));\n if (maxCandidates === 0 || scoped.size <= maxCandidates)\n return scoped.size > 0 ? scoped : null;\n return new Set(Array.from(scoped).slice(0, maxCandidates));\n };\n if (temporalFromDate !== null) {\n temporalCandidates = capSet(rawTemporal);\n }\n if (promptTags.length > 0) {\n tagCandidates = capSet(rawTags);\n }\n }\n\n let lifecycleFilteredCount = 0;\n let temporalSupersededFilteredCount = 0;\n let dedicatedSurfaceFilteredCount = 0;\n const boosted: QmdSearchResult[] = [];\n const recencyWeight = this.effectiveRecencyWeight();\n for (const r of results) {\n const memory = memoryByPath.get(r.path);\n let score = r.score;\n\n if (memory) {\n if (\n options?.allowLifecycleFiltered !== true &&\n shouldFilterLifecycleRecallCandidate(memory.frontmatter, {\n lifecyclePolicyEnabled: this.config.lifecyclePolicyEnabled,\n lifecycleFilterStaleEnabled:\n this.config.lifecycleFilterStaleEnabled,\n })\n ) {\n lifecycleFilteredCount += 1;\n continue;\n }\n\n // Temporal supersession filter (issue #375): drop memories that a\n // newer fact has retired, unless the caller opted in to history.\n // NOTE: This check is intentionally independent of allowLifecycleFiltered\n // (Finding A fix) — cold fallback sets allowLifecycleFiltered=true to\n // include archived/retired candidates, but superseded memories must\n // still be filtered unless temporalSupersessionIncludeInRecall is set.\n if (\n shouldFilterSupersededFromRecall(memory.frontmatter, {\n enabled: this.config.temporalSupersessionEnabled,\n includeInRecall: this.config.temporalSupersessionIncludeInRecall,\n })\n ) {\n temporalSupersededFilteredCount += 1;\n continue;\n }\n\n if (\n options?.allowDedicatedSurface !== true &&\n (memory.frontmatter.memoryKind === \"dream\" ||\n memory.frontmatter.memoryKind === \"procedural\")\n ) {\n dedicatedSurfaceFilteredCount += 1;\n continue;\n }\n\n // Recency boost: exponential decay over 7 days\n if (recencyWeight > 0) {\n const createdAt = new Date(memory.frontmatter.created).getTime();\n const ageMs = now - createdAt;\n const ageDays = ageMs / (1000 * 60 * 60 * 24);\n const halfLifeDays = 7;\n const recencyScore = Math.pow(0.5, ageDays / halfLifeDays);\n score = score * (1 - recencyWeight) + recencyScore * recencyWeight;\n }\n\n // Access count boost: log scale, capped\n if (this.config.boostAccessCount && memory.frontmatter.accessCount) {\n const accessBoost =\n Math.log10(memory.frontmatter.accessCount + 1) / 3;\n score += applyUtilityRankingRuntimeDelta(\n Math.min(accessBoost, 0.1),\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n\n // Importance boost (Phase 1B): higher importance = higher rank\n if (memory.frontmatter.importance) {\n const importanceScore = memory.frontmatter.importance.score;\n // Boost important memories, slightly penalize trivial ones\n // Scale: trivial (-0.05) to critical (+0.15)\n const importanceBoost = (importanceScore - 0.4) * 0.25;\n score += applyUtilityRankingRuntimeDelta(\n importanceBoost,\n this.utilityRuntimeValues,\n importanceBoost >= 0 ? \"boost\" : \"suppress\",\n );\n }\n\n // Feedback bias (v2.2): apply small user-provided up/down vote adjustments.\n if (this.config.feedbackEnabled) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const feedbackDelta = this.relevance.adjustment(memoryId);\n score += applyUtilityRankingRuntimeDelta(\n feedbackDelta,\n this.utilityRuntimeValues,\n feedbackDelta >= 0 ? \"boost\" : \"suppress\",\n );\n }\n }\n\n // Negative examples (v2.2): apply a small penalty for memories repeatedly marked \"not useful\".\n if (this.config.negativeExamplesEnabled) {\n const match = memory.path.match(/([^/]+)\\.md$/);\n const memoryId = match ? match[1] : null;\n if (memoryId) {\n const negativePenalty = this.negatives.penalty(memoryId, {\n perHit: this.config.negativeExamplesPenaltyPerHit,\n cap: this.config.negativeExamplesPenaltyCap,\n });\n score -= applyUtilityRankingRuntimeDelta(\n negativePenalty,\n this.utilityRuntimeValues,\n \"suppress\",\n );\n }\n }\n\n if (\n queryIntent &&\n memory.frontmatter.intentGoal &&\n memory.frontmatter.intentActionType\n ) {\n const compatibility = intentCompatibilityScore(queryIntent, {\n goal: memory.frontmatter.intentGoal,\n actionType: memory.frontmatter.intentActionType,\n entityTypes: memory.frontmatter.intentEntityTypes ?? [],\n });\n score += applyUtilityRankingRuntimeDelta(\n compatibility * this.config.intentRoutingBoost,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n\n // v8.1: Temporal + Tag index boost\n // Results that match the detected temporal window or tag query get a small additive boost.\n if (this.config.queryAwareIndexingEnabled && r.path) {\n if (temporalCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.08,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n if (tagCandidates?.has(r.path)) {\n score += applyUtilityRankingRuntimeDelta(\n 0.06,\n this.utilityRuntimeValues,\n \"boost\",\n );\n }\n }\n\n // v8.3: lifecycle retrieval weighting (fail-open on legacy memories).\n const lifecycleDelta = lifecycleRecallScoreAdjustment(\n memory.frontmatter,\n {\n lifecyclePolicyEnabled: this.config.lifecyclePolicyEnabled,\n },\n );\n score += applyUtilityRankingRuntimeDelta(\n lifecycleDelta,\n this.utilityRuntimeValues,\n lifecycleDelta >= 0 ? \"boost\" : \"suppress\",\n );\n }\n\n boosted.push({ ...r, score });\n }\n if (lifecycleFilteredCount > 0) {\n log.debug(\n `lifecycle retrieval filter removed ${lifecycleFilteredCount} stale/archived candidates`,\n );\n }\n if (temporalSupersededFilteredCount > 0) {\n log.debug(\n `temporal supersession filter removed ${temporalSupersededFilteredCount} superseded candidates`,\n );\n }\n if (dedicatedSurfaceFilteredCount > 0) {\n log.debug(\n `dedicated surface filter removed ${dedicatedSurfaceFilteredCount} dream/procedural candidates from generic recall`,\n );\n }\n\n // Re-sort by boosted score\n return boosted.sort((a, b) => b.score - a.score);\n }\n\n /**\n * Extract memory IDs from QMD search results for access tracking.\n */\n private extractMemoryIdsFromResults(results: QmdSearchResult[]): string[] {\n // QMD results have paths like /path/to/fact-123.md\n // Extract the ID from the filename\n return results\n .map((r) => {\n const match = r.path.match(/([^/]+)\\.md$/);\n return match ? match[1] : null;\n })\n .filter((id): id is string => id !== null);\n }\n\n // ---------------------------------------------------------------------------\n // Contradiction Detection (Phase 2B)\n // ---------------------------------------------------------------------------\n\n // ---------------------------------------------------------------------------\n // Feedback (v2.2)\n // ---------------------------------------------------------------------------\n\n async recordMemoryFeedback(\n memoryId: string,\n vote: \"up\" | \"down\",\n note?: string,\n ): Promise<void> {\n await this.relevance.record(memoryId, vote, note);\n }\n\n // Negative Examples (v2.2)\n async recordNotUsefulMemories(\n memoryIds: string[],\n note?: string,\n ): Promise<void> {\n await this.negatives.recordNotUseful(memoryIds, note);\n }\n\n getLastRecall(sessionKey: string): LastRecallSnapshot | null {\n return this.lastRecall.get(sessionKey);\n }\n\n /**\n * Check if a new memory contradicts an existing one.\n * Uses QMD to find similar memories, then LLM to verify contradiction.\n */\n private async checkForContradiction(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<{\n supersededId: string;\n confidence: number;\n reason: string;\n supersededPath: string;\n supersededCreated: string;\n supersededTags: string[];\n } | null> {\n if (!this.isSearchAvailableForNamespaceRouting()) return null;\n\n // Search for similar memories\n const results = await this.searchAcrossNamespaces({\n query: content,\n namespaces: [namespaceScope],\n maxResults: 5,\n mode: \"search\",\n });\n\n for (const result of results) {\n // Check similarity threshold\n if (result.score < this.config.contradictionSimilarityThreshold) {\n continue;\n }\n\n // Get the existing memory\n const memoryId = this.extractMemoryIdsFromResults([result])[0];\n if (!memoryId) continue;\n\n const resultNamespace = this.namespaceFromPath(result.path);\n if (resultNamespace !== namespaceScope) continue;\n const resultStorage =\n await this.storageRouter.storageFor(resultNamespace);\n const existingMemory = await resultStorage.getMemoryById(memoryId);\n if (!existingMemory) continue;\n\n // Skip already superseded memories\n if (existingMemory.frontmatter.status === \"superseded\") continue;\n\n // Verify contradiction with LLM\n const verification = await this.extraction.verifyContradiction(\n { content, category },\n {\n id: existingMemory.frontmatter.id,\n content: existingMemory.content,\n category: existingMemory.frontmatter.category,\n created: existingMemory.frontmatter.created,\n },\n );\n\n if (!verification) continue;\n\n // Check if it's a real contradiction with high confidence\n if (\n verification.isContradiction &&\n verification.confidence >= this.config.contradictionMinConfidence\n ) {\n // When the LLM says the existing memory is newer (whichIsNewer ===\n // \"first\") the incoming fact is the stale one in both resolve modes —\n // log and continue so the caller never marks contradictionDetected and\n // the semantic-skip gate can discard the outdated write normally.\n if (verification.whichIsNewer === \"first\") {\n log.info(\n `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory — existing is newer, incoming fact is stale`,\n );\n continue;\n }\n\n // The new fact is newer than the existing one. When auto-resolve is\n // enabled, immediately retire the old memory. When disabled, leave the\n // old memory active for manual review.\n if (this.config.contradictionAutoResolve) {\n await resultStorage.supersedeMemory(\n existingMemory.frontmatter.id,\n \"pending-new\", // Will be updated after the new memory is written\n verification.reasoning,\n );\n }\n\n // Return the contradiction info regardless of auto-resolve setting.\n // The caller uses this to set `contradictionDetected=true` which\n // prevents the semantic-skip guard from silently dropping a\n // legitimately contradictory update (the regression this fixes).\n log.info(\n `detected contradiction (confidence: ${verification.confidence}): ${existingMemory.frontmatter.id} vs new memory${this.config.contradictionAutoResolve ? \" (auto-resolved)\" : \" (queued for manual review)\"}`,\n );\n return {\n supersededId: existingMemory.frontmatter.id,\n confidence: verification.confidence,\n reason: verification.reasoning,\n supersededPath: existingMemory.path,\n supersededCreated: existingMemory.frontmatter.created,\n supersededTags: existingMemory.frontmatter.tags ?? [],\n };\n }\n }\n\n return null;\n }\n\n // ---------------------------------------------------------------------------\n // Memory Linking (Phase 3A)\n // ---------------------------------------------------------------------------\n\n /**\n * Suggest links for a new memory based on similar existing memories.\n */\n private async suggestLinksForMemory(\n content: string,\n category: string,\n namespaceScope: string,\n ): Promise<MemoryLink[]> {\n if (!this.isSearchAvailableForNamespaceRouting()) return [];\n\n // Search for related memories\n const results = await this.searchAcrossNamespaces({\n query: content,\n namespaces: [namespaceScope],\n maxResults: 5,\n mode: \"search\",\n });\n if (results.length === 0) return [];\n\n // Get full memory details for candidates\n const candidates: Array<{ id: string; content: string; category: string }> =\n [];\n for (const result of results) {\n const memoryId = this.extractMemoryIdsFromResults([result])[0];\n if (!memoryId) continue;\n\n const resultNamespace = this.namespaceFromPath(result.path);\n if (resultNamespace !== namespaceScope) continue;\n const resultStorage =\n await this.storageRouter.storageFor(resultNamespace);\n const memory = await resultStorage.getMemoryById(memoryId);\n if (memory && memory.frontmatter.status !== \"superseded\") {\n candidates.push({\n id: memory.frontmatter.id,\n content: memory.content,\n category: memory.frontmatter.category,\n });\n }\n }\n\n if (candidates.length === 0) return [];\n\n // Ask LLM for link suggestions\n const suggestions = await this.extraction.suggestLinks(\n { content, category },\n candidates,\n );\n\n if (!suggestions || suggestions.links.length === 0) return [];\n\n // Convert to MemoryLink format\n return suggestions.links.map((link) => ({\n targetId: link.targetId,\n linkType: link.linkType,\n strength: link.strength,\n reason: link.reason || undefined,\n }));\n }\n\n private namespaceFromPath(p: string): string {\n if (!this.config.namespacesEnabled) return this.config.defaultNamespace;\n const m = p.match(/[\\\\/]+namespaces[\\\\/]+([^\\\\/]+)(?:[\\\\/]|$)/);\n return m && m[1] ? m[1] : this.config.defaultNamespace;\n }\n\n private namespaceFromStorageDir(storageDir: string): string {\n if (!this.config.namespacesEnabled) return this.config.defaultNamespace;\n const resolvedStorageDir = path.resolve(storageDir);\n const resolvedMemoryDir = path.resolve(this.config.memoryDir);\n if (resolvedStorageDir === resolvedMemoryDir)\n return this.config.defaultNamespace;\n const m = resolvedStorageDir.match(/[\\\\/]namespaces[\\\\/]([^\\\\/]+)$/);\n return m && m[1] ? m[1] : this.config.defaultNamespace;\n }\n\n private async readAllMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n const uniq = Array.from(new Set(namespaces.filter(Boolean)));\n const lists = await Promise.all(\n uniq.map(async (ns) => {\n const sm = await this.storageRouter.storageFor(ns);\n return sm.readAllMemories();\n }),\n );\n return lists.flat();\n }\n\n private async readArchivedMemoriesForNamespaces(\n namespaces: string[],\n ): Promise<MemoryFile[]> {\n const uniq = Array.from(new Set(namespaces.filter(Boolean)));\n const lists = await Promise.all(\n uniq.map(async (ns) => {\n const sm = await this.storageRouter.storageFor(ns);\n return sm.readArchivedMemories();\n }),\n );\n return lists.flat();\n }\n}\n","import { createHash } from \"node:crypto\";\nimport path from \"node:path\";\nimport {\n copyFile,\n mkdir,\n open,\n readFile,\n readdir,\n rm,\n stat,\n unlink,\n writeFile,\n} from \"node:fs/promises\";\nimport { existsSync } from \"node:fs\";\nimport { resolveHomeDir } from \"../runtime/env.js\";\nimport { launchProcessSync } from \"../runtime/child-process.js\";\n\nexport interface MigrationResult {\n status: \"fresh-install\" | \"already-migrated\" | \"migrated\";\n copied: string[];\n tokensRegenerated: number;\n servicesReinstalled: string[];\n rollbackCommand: string;\n}\n\ninterface RollbackManifestEntry {\n targetPath: string;\n backupPath?: string;\n createdByMigration?: boolean;\n}\n\ninterface RollbackManifest {\n version: 1;\n createdAt: string;\n entries: RollbackManifestEntry[];\n}\n\nexport interface MigrationOptions {\n connectorConfigPaths?: string[];\n cwd?: string;\n execCommand?: (command: string, args: string[]) => void;\n homeDir?: string;\n logger?: (message: string) => void;\n platform?: NodeJS.Platform;\n quiet?: boolean;\n}\n\nexport interface RollbackResult {\n removed: string[];\n restored: string[];\n}\n\ninterface TokenEntry {\n connector: string;\n createdAt: string;\n token: string;\n}\n\nconst MARKER_FILE = \".migrated-from-engram\";\nconst LOCK_FILE = \".migration.lock\";\nconst ROLLBACK_MANIFEST = \".rollback.json\";\nconst BACKUP_DIR = \".backup\";\nconst LOCK_RETRY_MS = 100;\nconst LOCK_STALE_MS = 30_000;\nconst LOCK_TIMEOUT_MS = 5_000;\n\nfunction resolvePlatform(options?: MigrationOptions): NodeJS.Platform {\n return options?.platform ?? process.platform;\n}\n\nfunction resolveMigrationHome(options?: MigrationOptions): string {\n return options?.homeDir ?? resolveHomeDir();\n}\n\nfunction resolveLogger(options?: MigrationOptions): (message: string) => void {\n const sink = options?.logger ?? ((message: string) => console.log(message));\n return (message: string) => {\n if (!options?.quiet) sink(`[remnic] ${message}`);\n };\n}\n\nfunction resolveExec(options?: MigrationOptions): (command: string, args: string[]) => void {\n return options?.execCommand ?? ((command: string, args: string[]) => {\n const result = launchProcessSync(command, args, { stdio: \"ignore\" });\n if (result.error) {\n throw result.error;\n }\n if (result.status !== 0) {\n const reason = result.status === null\n ? `signal ${result.signal ?? \"unknown\"}`\n : `exit code ${result.status}`;\n throw new Error(`migration command failed: ${command} ${args.join(\" \")} (${reason})`);\n }\n });\n}\n\nfunction remnicRoot(homeDir: string): string {\n return path.join(homeDir, \".remnic\");\n}\n\nfunction legacyRoot(homeDir: string): string {\n return path.join(homeDir, \".engram\");\n}\n\nfunction legacyConfigPath(homeDir: string): string {\n return path.join(homeDir, \".config\", \"engram\", \"config.json\");\n}\n\nfunction remnicConfigPath(homeDir: string): string {\n return path.join(homeDir, \".config\", \"remnic\", \"config.json\");\n}\n\nfunction markerPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), MARKER_FILE);\n}\n\nfunction lockPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), LOCK_FILE);\n}\n\nfunction rollbackManifestPath(homeDir: string): string {\n return path.join(remnicRoot(homeDir), ROLLBACK_MANIFEST);\n}\n\nfunction backupRoot(homeDir: string): string {\n return path.join(remnicRoot(homeDir), BACKUP_DIR);\n}\n\nfunction defaultRollbackCommand(): string {\n return \"remnic migrate --rollback\";\n}\n\nasync function ensureParent(filePath: string): Promise<void> {\n await mkdir(path.dirname(filePath), { recursive: true });\n}\n\nasync function copyTreeMissing(source: string, destination: string, copied: string[]): Promise<void> {\n if (!existsSync(source)) return;\n const sourceStat = await stat(source);\n if (sourceStat.isDirectory()) {\n await mkdir(destination, { recursive: true });\n const entries = await readdir(source, { withFileTypes: true });\n for (const entry of entries) {\n if (entry.name === MARKER_FILE || entry.name === LOCK_FILE || entry.name === ROLLBACK_MANIFEST) {\n continue;\n }\n await copyTreeMissing(\n path.join(source, entry.name),\n path.join(destination, entry.name),\n copied,\n );\n }\n return;\n }\n\n if (existsSync(destination)) return;\n await ensureParent(destination);\n await copyFile(source, destination);\n copied.push(destination);\n}\n\nfunction rewriteRemnicText(content: string): string {\n return content\n .replaceAll(\".engram/\", \".remnic/\")\n .replaceAll(\".engram\\\\\", \".remnic\\\\\")\n .replaceAll(\"ENGRAM_\", \"REMNIC_\")\n .replaceAll(\"{{ENGRAM_TOKEN}}\", \"{{REMNIC_TOKEN}}\")\n .replaceAll(\"${ENGRAM_AUTH_TOKEN}\", \"${REMNIC_AUTH_TOKEN}\")\n .replaceAll(\"ai.engram.daemon\", \"ai.remnic.daemon\")\n .replaceAll(\"engram.service\", \"remnic.service\");\n}\n\nfunction rewriteTokenValue(token: string): string {\n return token.startsWith(\"engram_\") ? `remnic_${token.slice(\"engram_\".length)}` : token;\n}\n\nfunction parseTokenEntries(raw: unknown): TokenEntry[] {\n if (typeof raw !== \"object\" || raw === null) return [];\n\n if (Array.isArray((raw as { tokens?: unknown }).tokens)) {\n return ((raw as { tokens: unknown[] }).tokens)\n .filter((entry): entry is TokenEntry => {\n if (typeof entry !== \"object\" || entry === null) return false;\n const candidate = entry as Partial<TokenEntry>;\n return typeof candidate.connector === \"string\" &&\n candidate.connector.length > 0 &&\n typeof candidate.token === \"string\" &&\n candidate.token.length > 0 &&\n typeof candidate.createdAt === \"string\" &&\n candidate.createdAt.length > 0;\n })\n .map((entry) => ({ ...entry }));\n }\n\n return Object.entries(raw)\n .filter(([key, value]) => key !== \"tokens\" && typeof value === \"string\" && value.length > 0)\n .map(([connector, token]) => ({\n connector,\n createdAt: new Date().toISOString(),\n token,\n }));\n}\n\nasync function rewriteTokensIfPresent(filePath: string): Promise<number> {\n if (!existsSync(filePath)) return 0;\n let raw: Record<string, unknown>;\n try {\n raw = JSON.parse(await readFile(filePath, \"utf8\")) as Record<string, unknown>;\n } catch {\n return 0;\n }\n let rewritten = 0;\n\n if (Array.isArray(raw.tokens)) {\n for (const entry of raw.tokens as Array<Record<string, unknown>>) {\n if (typeof entry.token === \"string\") {\n const next = rewriteTokenValue(entry.token);\n if (next !== entry.token) {\n entry.token = next;\n rewritten += 1;\n }\n }\n }\n } else {\n for (const [key, value] of Object.entries(raw)) {\n if (typeof value === \"string\") {\n const next = rewriteTokenValue(value);\n if (next !== value) {\n raw[key] = next;\n rewritten += 1;\n }\n }\n }\n }\n\n if (rewritten > 0) {\n await writeFile(filePath, `${JSON.stringify(raw, null, 2)}\\n`, \"utf8\");\n }\n return rewritten;\n}\n\nasync function mergeLegacyTokens(\n legacyTokensPath: string,\n remnicTokensPath: string,\n homeDir: string,\n manifest: RollbackManifest,\n backupExisting: boolean,\n): Promise<number> {\n if (!existsSync(remnicTokensPath)) return 0;\n if (!existsSync(legacyTokensPath)) return rewriteTokensIfPresent(remnicTokensPath);\n\n let remnicRaw: unknown;\n let legacyRaw: unknown;\n const originalRemnic = await readFile(remnicTokensPath, \"utf8\");\n\n try {\n remnicRaw = JSON.parse(originalRemnic) as unknown;\n legacyRaw = JSON.parse(await readFile(legacyTokensPath, \"utf8\")) as unknown;\n } catch {\n try {\n legacyRaw = JSON.parse(await readFile(legacyTokensPath, \"utf8\")) as unknown;\n } catch {\n return rewriteTokensIfPresent(remnicTokensPath);\n }\n\n const legacyEntries = parseTokenEntries(legacyRaw);\n let rewritten = 0;\n const recoveredEntries = legacyEntries.map((entry) => {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) rewritten += 1;\n return {\n ...entry,\n token: nextToken,\n };\n });\n\n if (backupExisting) {\n await backupFile(remnicTokensPath, originalRemnic, homeDir, manifest);\n }\n\n await writeFile(\n remnicTokensPath,\n `${JSON.stringify({ tokens: recoveredEntries }, null, 2)}\\n`,\n \"utf8\",\n );\n return rewritten;\n }\n\n const mergedEntries = parseTokenEntries(remnicRaw);\n const legacyEntries = parseTokenEntries(legacyRaw);\n const existingConnectors = new Set(mergedEntries.map((entry) => entry.connector));\n let rewritten = 0;\n let changed = false;\n\n for (const entry of mergedEntries) {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) {\n entry.token = nextToken;\n rewritten += 1;\n changed = true;\n }\n }\n\n for (const entry of legacyEntries) {\n const nextToken = rewriteTokenValue(entry.token);\n if (nextToken !== entry.token) {\n rewritten += 1;\n }\n if (existingConnectors.has(entry.connector)) continue;\n mergedEntries.push({ ...entry, token: nextToken });\n existingConnectors.add(entry.connector);\n changed = true;\n }\n\n if (!changed) return rewritten;\n\n if (backupExisting) {\n await backupFile(remnicTokensPath, originalRemnic, homeDir, manifest);\n }\n\n await writeFile(\n remnicTokensPath,\n `${JSON.stringify({ tokens: mergedEntries }, null, 2)}\\n`,\n \"utf8\",\n );\n return rewritten;\n}\n\nasync function rewriteJsonFile(\n targetPath: string,\n homeDir: string,\n manifest: RollbackManifest,\n): Promise<boolean> {\n if (!existsSync(targetPath)) return false;\n\n const original = await readFile(targetPath, \"utf8\");\n let parsed: Record<string, unknown>;\n try {\n parsed = JSON.parse(original) as Record<string, unknown>;\n } catch {\n return false;\n }\n\n let changed = false;\n if (\n parsed.mcpServers &&\n typeof parsed.mcpServers === \"object\" &&\n !Array.isArray(parsed.mcpServers)\n ) {\n const servers = parsed.mcpServers as Record<string, unknown>;\n if (servers.engram && !servers.remnic) {\n servers.remnic = servers.engram;\n delete servers.engram;\n changed = true;\n }\n }\n\n const rewritten = rewriteRemnicText(JSON.stringify(parsed, null, 2));\n const next = `${rewritten}\\n`;\n if (!changed && next === original) return false;\n\n await backupFile(targetPath, original, homeDir, manifest);\n await writeFile(targetPath, next, \"utf8\");\n return true;\n}\n\nasync function backupFile(\n targetPath: string,\n originalContent: string,\n homeDir: string,\n manifest: RollbackManifest,\n): Promise<void> {\n if (manifest.entries.some((entry) => entry.targetPath === targetPath && entry.backupPath)) {\n return;\n }\n const digest = createHash(\"sha256\").update(targetPath).digest(\"hex\").slice(0, 12);\n const backupPath = path.join(backupRoot(homeDir), \"mcp\", `${digest}.json`);\n await ensureParent(backupPath);\n await writeFile(backupPath, originalContent, \"utf8\");\n manifest.entries.push({ targetPath, backupPath });\n}\n\nasync function recordCreatedPath(filePath: string, manifest: RollbackManifest): Promise<void> {\n if (manifest.entries.some((entry) => entry.targetPath === filePath)) return;\n manifest.entries.push({ targetPath: filePath, createdByMigration: true });\n}\n\nfunction defaultConnectorConfigPaths(homeDir: string, cwd: string): string[] {\n return [\n path.join(homeDir, \".claude.json\"),\n path.join(homeDir, \".claude\", \".mcp.json\"),\n path.join(cwd, \"packages\", \"plugin-claude-code\", \".mcp.json\"),\n path.join(cwd, \"packages\", \"plugin-codex\", \".mcp.json\"),\n ];\n}\n\nasync function updateConnectorConfigs(\n homeDir: string,\n cwd: string,\n options: MigrationOptions | undefined,\n manifest: RollbackManifest,\n): Promise<string[]> {\n const updated: string[] = [];\n const candidates = options?.connectorConfigPaths ?? defaultConnectorConfigPaths(homeDir, cwd);\n for (const targetPath of candidates) {\n if (await rewriteJsonFile(targetPath, homeDir, manifest)) {\n updated.push(targetPath);\n }\n }\n return updated;\n}\n\nasync function copyLegacyConfig(homeDir: string, copied: string[]): Promise<void> {\n const source = legacyConfigPath(homeDir);\n const destination = remnicConfigPath(homeDir);\n if (!existsSync(source) || existsSync(destination)) return;\n await ensureParent(destination);\n const original = await readFile(source, \"utf8\");\n let next = rewriteRemnicText(original);\n try {\n const parsed = JSON.parse(next) as Record<string, unknown>;\n if (parsed.engram && !parsed.remnic) {\n parsed.remnic = parsed.engram;\n delete parsed.engram;\n next = JSON.stringify(parsed, null, 2);\n }\n } catch {\n // Keep rewritten text when config is not JSON.\n }\n await writeFile(destination, `${next.trimEnd()}\\n`, \"utf8\");\n copied.push(destination);\n}\n\nfunction rewriteServiceText(content: string): string {\n return rewriteRemnicText(content);\n}\n\nasync function migrateServices(\n homeDir: string,\n options: MigrationOptions | undefined,\n manifest: RollbackManifest,\n): Promise<string[]> {\n const logger = resolveLogger(options);\n const exec = resolveExec(options);\n const servicesReinstalled: string[] = [];\n const platform = resolvePlatform(options);\n\n if (platform === \"darwin\") {\n const legacyPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.engram.daemon.plist\");\n const remnicPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.remnic.daemon.plist\");\n if (existsSync(legacyPlist) && !existsSync(remnicPlist)) {\n const next = rewriteServiceText(await readFile(legacyPlist, \"utf8\"));\n await ensureParent(remnicPlist);\n await writeFile(remnicPlist, next, \"utf8\");\n await recordCreatedPath(remnicPlist, manifest);\n try {\n exec(\"launchctl\", [\"unload\", legacyPlist]);\n } catch {\n // Keep migration fail-open when launchd rejects unload.\n }\n try {\n exec(\"launchctl\", [\"load\", \"-w\", remnicPlist]);\n } catch {\n // Keep migration fail-open when launchd rejects load.\n }\n servicesReinstalled.push(\"ai.remnic.daemon\");\n logger(\"launchd: ai.engram.daemon unloaded, ai.remnic.daemon installed\");\n }\n return servicesReinstalled;\n }\n\n if (platform === \"linux\") {\n const legacyUnit = path.join(homeDir, \".config\", \"systemd\", \"user\", \"engram.service\");\n const remnicUnit = path.join(homeDir, \".config\", \"systemd\", \"user\", \"remnic.service\");\n if (existsSync(legacyUnit) && !existsSync(remnicUnit)) {\n const next = rewriteServiceText(await readFile(legacyUnit, \"utf8\"));\n await ensureParent(remnicUnit);\n await writeFile(remnicUnit, next, \"utf8\");\n await recordCreatedPath(remnicUnit, manifest);\n try {\n exec(\"systemctl\", [\"--user\", \"stop\", \"engram.service\"]);\n exec(\"systemctl\", [\"--user\", \"disable\", \"engram.service\"]);\n exec(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n exec(\"systemctl\", [\"--user\", \"enable\", \"remnic.service\"]);\n exec(\"systemctl\", [\"--user\", \"start\", \"remnic.service\"]);\n } catch {\n // Keep migration fail-open when systemd is unavailable.\n }\n servicesReinstalled.push(\"remnic.service\");\n logger(\"systemd: engram.service disabled, remnic.service installed\");\n }\n }\n\n return servicesReinstalled;\n}\n\nasync function writeRollbackManifest(homeDir: string, manifest: RollbackManifest): Promise<void> {\n await ensureParent(rollbackManifestPath(homeDir));\n await writeFile(\n rollbackManifestPath(homeDir),\n `${JSON.stringify(manifest, null, 2)}\\n`,\n \"utf8\",\n );\n}\n\nasync function readRollbackManifest(homeDir: string): Promise<RollbackManifest | null> {\n const target = rollbackManifestPath(homeDir);\n if (!existsSync(target)) return null;\n try {\n return JSON.parse(await readFile(target, \"utf8\")) as RollbackManifest;\n } catch {\n return null;\n }\n}\n\nasync function acquireLock(homeDir: string): Promise<() => Promise<void>> {\n const target = lockPath(homeDir);\n await mkdir(remnicRoot(homeDir), { recursive: true });\n const started = Date.now();\n\n while (true) {\n try {\n const handle = await open(target, \"wx\");\n await handle.writeFile(`${process.pid}\\n${Date.now()}\\n`, \"utf8\");\n return async () => {\n try {\n await handle.close();\n } finally {\n await unlink(target).catch(() => undefined);\n }\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") throw error;\n\n const details = await readFile(target, \"utf8\").catch(() => \"\");\n const lines = details.split(\"\\n\");\n const pid = Number.parseInt(lines[0] ?? \"\", 10);\n const createdAt = Number.parseInt(lines[1] ?? \"\", 10);\n const malformed = !Number.isFinite(pid) || !Number.isFinite(createdAt);\n const stale = Number.isFinite(createdAt) && Date.now() - createdAt > LOCK_STALE_MS;\n const deadPid = Number.isFinite(pid) && pid > 0 ? !processIsAlive(pid) : false;\n if (malformed || stale || deadPid) {\n await rm(target, { force: true }).catch(() => undefined);\n continue;\n }\n if (Date.now() - started > LOCK_TIMEOUT_MS) {\n throw new Error(`timed out waiting for migration lock: ${target}`);\n }\n await new Promise((resolve) => setTimeout(resolve, LOCK_RETRY_MS));\n }\n }\n}\n\nfunction processIsAlive(pid: number): boolean {\n try {\n process.kill(pid, 0);\n return true;\n } catch {\n return false;\n }\n}\n\nexport async function rollbackFromEngramMigration(options?: MigrationOptions): Promise<RollbackResult> {\n const homeDir = resolveMigrationHome(options);\n const manifest = await readRollbackManifest(homeDir);\n const exec = resolveExec(options);\n const platform = resolvePlatform(options);\n const restored: string[] = [];\n const removed: string[] = [];\n\n if (!manifest) return { restored, removed };\n\n if (platform === \"darwin\") {\n const remnicPlist = path.join(homeDir, \"Library\", \"LaunchAgents\", \"ai.remnic.daemon.plist\");\n if (existsSync(remnicPlist)) {\n try {\n exec(\"launchctl\", [\"unload\", remnicPlist]);\n } catch {\n // Ignore launchctl rollback failures.\n }\n }\n } else if (platform === \"linux\") {\n try {\n exec(\"systemctl\", [\"--user\", \"stop\", \"remnic.service\"]);\n exec(\"systemctl\", [\"--user\", \"disable\", \"remnic.service\"]);\n } catch {\n // Ignore systemd rollback failures.\n }\n }\n\n for (const entry of [...manifest.entries].reverse()) {\n if (entry.backupPath && existsSync(entry.backupPath)) {\n await ensureParent(entry.targetPath);\n await copyFile(entry.backupPath, entry.targetPath);\n restored.push(entry.targetPath);\n continue;\n }\n if (entry.createdByMigration && existsSync(entry.targetPath)) {\n await rm(entry.targetPath, { recursive: true, force: true });\n removed.push(entry.targetPath);\n }\n }\n\n if (platform === \"linux\") {\n try {\n exec(\"systemctl\", [\"--user\", \"daemon-reload\"]);\n } catch {\n // Ignore systemd rollback failures after removing unit files.\n }\n }\n\n await rm(markerPath(homeDir), { force: true }).catch(() => undefined);\n await rm(rollbackManifestPath(homeDir), { force: true }).catch(() => undefined);\n return { restored, removed };\n}\n\nexport async function migrateFromEngram(options?: MigrationOptions): Promise<MigrationResult> {\n const homeDir = resolveMigrationHome(options);\n const cwd = options?.cwd ?? process.cwd();\n const logger = resolveLogger(options);\n const copied: string[] = [];\n let tokensRegenerated = 0;\n let servicesReinstalled: string[] = [];\n\n if (existsSync(markerPath(homeDir))) {\n return {\n status: \"already-migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const hasLegacyRoot = existsSync(legacyRoot(homeDir));\n const hasLegacyConfig = existsSync(legacyConfigPath(homeDir));\n if (!hasLegacyRoot && !hasLegacyConfig) {\n return {\n status: \"fresh-install\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const releaseLock = await acquireLock(homeDir);\n try {\n if (existsSync(markerPath(homeDir))) {\n return {\n status: \"already-migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n }\n\n const manifest: RollbackManifest = {\n version: 1,\n createdAt: new Date().toISOString(),\n entries: [],\n };\n\n logger(\"First run after Engram -> Remnic rename. Migrating...\");\n await mkdir(remnicRoot(homeDir), { recursive: true });\n await copyTreeMissing(legacyRoot(homeDir), remnicRoot(homeDir), copied);\n await copyLegacyConfig(homeDir, copied);\n\n const legacyTokens = path.join(legacyRoot(homeDir), \"tokens.json\");\n const remnicTokens = path.join(remnicRoot(homeDir), \"tokens.json\");\n if (copied.includes(remnicTokens)) {\n tokensRegenerated += await rewriteTokensIfPresent(remnicTokens);\n } else {\n tokensRegenerated += await mergeLegacyTokens(\n legacyTokens,\n remnicTokens,\n homeDir,\n manifest,\n true,\n );\n }\n if (existsSync(remnicTokens)) {\n logger(\"tokens copied to ~/.remnic/tokens.json (legacy prefixes rewritten)\");\n }\n\n const updatedConfigs = await updateConnectorConfigs(homeDir, cwd, options, manifest);\n for (const updated of updatedConfigs) {\n logger(`Updated connector config: ${updated}`);\n }\n\n servicesReinstalled = await migrateServices(homeDir, options, manifest);\n await writeRollbackManifest(homeDir, manifest);\n await writeFile(markerPath(homeDir), `${new Date().toISOString()}\\n`, \"utf8\");\n logger(\"Migration complete. Welcome to Remnic.\");\n\n return {\n status: \"migrated\",\n copied,\n tokensRegenerated,\n servicesReinstalled,\n rollbackCommand: defaultRollbackCommand(),\n };\n } finally {\n await releaseLock();\n }\n}\n","/**\n * Intent-gated recall for active procedure memories (issue #519).\n */\n\nimport type { MemoryFile, PluginConfig } from \"../types.js\";\nimport type { StorageManager } from \"../storage.js\";\nimport { inferIntentFromText, intentCompatibilityScore, isTaskInitiationIntent } from \"../intent.js\";\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 m.frontmatter.status !== \"pending_review\" &&\n m.frontmatter.status !== \"rejected\" &&\n m.frontmatter.status !== \"quarantined\" &&\n m.frontmatter.status !== \"superseded\" &&\n m.frontmatter.status !== \"archived\",\n )\n .map((m) => ({ m, score: scoreProcedureForPrompt(m, trimmed, queryIntent) }))\n .filter((x) => x.score > 0.04)\n .sort((a, b) => b.score - a.score)\n .slice(0, maxN);\n\n if (scored.length === 0) return null;\n\n const blocks = scored.map(({ m, score }) => {\n const id = m.frontmatter.id;\n const flat = m.content.replace(/\\s+/g, \" \").trim();\n const preview = flat.slice(0, 320);\n const suffix = flat.length > 320 ? \"…\" : \"\";\n return `### ${id} (match ${score.toFixed(2)})\\n\\n${preview}${suffix}`;\n });\n\n return `## Relevant procedures\\n\\n${blocks.join(\"\\n\\n\")}`;\n}\n","import { mkdir, readFile, rename, rm, stat, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\n\nconst DAY_SUMMARY_CRON_ID = \"engram-day-summary\";\nconst GOVERNANCE_CRON_ID = \"engram-nightly-governance\";\nconst PROCEDURAL_MINING_CRON_ID = \"engram-procedural-mining\";\nconst CONTRADICTION_SCAN_CRON_ID = \"engram-contradiction-scan\";\n\ntype CronJobsShape =\n | Array<Record<string, unknown>>\n | {\n jobs: Array<Record<string, unknown>>;\n [key: string]: unknown;\n };\n\nasync function acquireCronJobsLock(jobsPath: string): Promise<() => Promise<void>> {\n const lockPath = `${jobsPath}.lock`;\n const start = Date.now();\n const staleMs = 30_000;\n const timeoutMs = 5_000;\n await mkdir(path.dirname(lockPath), { recursive: true });\n\n while (Date.now() - start < timeoutMs) {\n try {\n await mkdir(lockPath);\n return async () => {\n try {\n await rm(lockPath, { recursive: true, force: true });\n } catch {\n // Lock cleanup should not fail cron registration.\n }\n };\n } catch (error) {\n const code = (error as NodeJS.ErrnoException).code;\n if (code !== \"EEXIST\") {\n throw error;\n }\n try {\n const lockStat = await stat(lockPath);\n if (Date.now() - lockStat.mtimeMs > staleMs) {\n await rm(lockPath, { recursive: true, force: true });\n continue;\n }\n } catch {\n // Lock may have been released between stat/rm attempts.\n }\n await new Promise((resolve) => setTimeout(resolve, 25));\n }\n }\n\n throw new Error(`cron jobs lock acquisition timed out after ${timeoutMs}ms`);\n}\n\nfunction parseCronJobsShape(raw: string): { parsed: CronJobsShape; jobs: Array<Record<string, unknown>> } {\n const parsed = JSON.parse(raw) as CronJobsShape;\n const jobs = Array.isArray(parsed) ? parsed : Array.isArray(parsed.jobs) ? parsed.jobs : null;\n if (!jobs) {\n throw new Error(\"jobs.json has unexpected structure\");\n }\n return { parsed, jobs };\n}\n\nasync function writeCronJobsAtomic(jobsPath: string, value: CronJobsShape): Promise<void> {\n const tempPath = `${jobsPath}.${process.pid}.${Date.now()}.tmp`;\n await writeFile(tempPath, JSON.stringify(value, null, 2) + \"\\n\", \"utf-8\");\n await rename(tempPath, jobsPath);\n}\n\nasync function ensureCronJob(\n jobsPath: string,\n jobId: string,\n buildJob: () => Record<string, unknown>,\n): Promise<{ created: boolean; jobId: string }> {\n const releaseLock = await acquireCronJobsLock(jobsPath);\n try {\n const raw = await readFile(jobsPath, \"utf-8\");\n const { parsed, jobs } = parseCronJobsShape(raw);\n\n if (jobs.some((job) => job.id === jobId)) {\n return { created: false, jobId };\n }\n\n jobs.push(buildJob());\n const output = Array.isArray(parsed) ? jobs : { ...parsed, jobs };\n await writeCronJobsAtomic(jobsPath, output);\n return { created: true, jobId };\n } finally {\n await releaseLock();\n }\n}\n\nexport async function ensureDaySummaryCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, DAY_SUMMARY_CRON_ID, () => ({\n id: DAY_SUMMARY_CRON_ID,\n agentId,\n name: \"Remnic Day Summary (auto)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: \"47 23 * * *\",\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool engram.day_summary with empty params (it will auto-gather today's facts). If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureNightlyGovernanceCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n recentDays?: number;\n maxMemories?: number;\n batchSize?: number;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const recentDays =\n typeof options.recentDays === \"number\" && Number.isFinite(options.recentDays)\n ? Math.max(1, Math.floor(options.recentDays))\n : 2;\n const maxMemories =\n typeof options.maxMemories === \"number\" && Number.isFinite(options.maxMemories)\n ? Math.max(1, Math.floor(options.maxMemories))\n : 500;\n const batchSize =\n typeof options.batchSize === \"number\" && Number.isFinite(options.batchSize)\n ? Math.max(1, Math.floor(options.batchSize))\n : 100;\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"23 2 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, GOVERNANCE_CRON_ID, () => ({\n id: GOVERNANCE_CRON_ID,\n agentId,\n name: \"Remnic Nightly Governance (batched)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call the tool `engram.memory_governance_run` with params \" +\n `{\"mode\": \"apply\", \"recentDays\": ${recentDays}, \"maxMemories\": ${maxMemories}, \"batchSize\": ${batchSize}}` +\n \". If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureProceduralMiningCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"17 3 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, PROCEDURAL_MINING_CRON_ID, () => ({\n id: PROCEDURAL_MINING_CRON_ID,\n agentId,\n name: \"Remnic Procedural Mining (nightly)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.procedure_mining_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n\nexport async function ensureContradictionScanCron(\n jobsPath: string,\n options: {\n timezone: string;\n agentId?: string;\n scheduleExpr?: string;\n },\n): Promise<{ created: boolean; jobId: string }> {\n const scheduleExpr =\n typeof options.scheduleExpr === \"string\" && options.scheduleExpr.trim().length > 0\n ? options.scheduleExpr.trim()\n : \"37 3 * * *\";\n const agentId =\n typeof options.agentId === \"string\" && options.agentId.trim().length > 0\n ? options.agentId.trim()\n : \"main\";\n\n return ensureCronJob(jobsPath, CONTRADICTION_SCAN_CRON_ID, () => ({\n id: CONTRADICTION_SCAN_CRON_ID,\n agentId,\n name: \"Remnic Contradiction Scan (nightly)\",\n enabled: true,\n schedule: {\n kind: \"cron\",\n expr: scheduleExpr,\n tz: options.timezone,\n },\n sessionTarget: \"isolated\",\n wakeMode: \"now\",\n payload: {\n kind: \"agentTurn\",\n timeoutSeconds: 900,\n thinking: \"off\",\n message:\n \"You are OpenClaw automation. Call tool `engram.contradiction_scan_run` with empty params. \" +\n \"If successful output exactly NO_REPLY. On error output one concise line. Do NOT use message tool.\",\n },\n delivery: { mode: \"none\" },\n }));\n}\n","/**\n * @remnic/core — Write-time semantic dedup guard\n *\n * Complements the exact content-hash check in the orchestrator's write path\n * by detecting near-duplicate candidate facts via embedding cosine similarity.\n *\n * The module intentionally has no dependency on the EmbeddingFallback or QMD\n * classes directly — callers pass in a `lookup` function that returns the\n * top-K nearest neighbors with their cosine scores. This keeps the decision\n * logic pure and trivially testable with synthetic fixtures, and lets the\n * orchestrator reuse whichever backend it already has wired up.\n *\n * Related issue: joshuaswarren/remnic#373\n */\n\n// ── Public types ──────────────────────────────────────────────────────────────\n\n/** A single nearest-neighbor hit from the embedding backend. */\nexport interface SemanticDedupHit {\n /** Memory id of the existing neighbor. */\n id: string;\n /** Cosine similarity score in [0, 1]. */\n score: number;\n /** Optional source path, purely informational. */\n path?: string;\n}\n\n/**\n * Lookup function passed by the caller. Must return an array of hits sorted\n * descending by score. Implementations should return an empty array (never\n * throw) when the embedding backend is unavailable — the decision function\n * treats that as \"no near duplicate\" (fail-open).\n */\nexport type SemanticDedupLookup = (\n content: string,\n limit: number,\n) => Promise<SemanticDedupHit[]>;\n\nexport interface SemanticDedupOptions {\n /** Master switch. When false, `decideSemanticDedup` always returns `keep`. */\n enabled: boolean;\n /** Cosine similarity threshold (0-1). ≥ threshold ⇒ treat as duplicate. */\n threshold: number;\n /** How many nearest neighbors to compare against. */\n candidates: number;\n}\n\nexport type SemanticDedupDecision =\n | {\n action: \"keep\";\n reason:\n | \"disabled\"\n | \"backend_unavailable\"\n | \"no_candidates\"\n | \"no_near_duplicate\";\n topScore?: number;\n topId?: string;\n }\n | {\n action: \"skip\";\n reason: \"near_duplicate\";\n topScore: number;\n topId: string;\n topPath?: string;\n };\n\n// ── Pure decision function ────────────────────────────────────────────────────\n\n/**\n * Pure decision function: given a lookup callback and options, decide whether\n * the candidate content should be written or skipped as a near-duplicate.\n *\n * Contract:\n * - When `options.enabled` is false → always keep, reason=\"disabled\".\n * - When the lookup throws (provider down / network error) → keep,\n * reason=\"backend_unavailable\". Fail-open: a lookup failure must not block\n * writes.\n * - When the lookup succeeds but returns 0 hits (empty index or no\n * neighbors above the score floor) → keep, reason=\"no_candidates\".\n * This is distinct from backend_unavailable so telemetry dashboards can\n * correctly distinguish \"provider is down\" from \"index is empty\".\n * - When the top hit's score ≥ threshold → skip with reason=\"near_duplicate\".\n * - Otherwise → keep with reason=\"no_near_duplicate\".\n */\nexport async function decideSemanticDedup(\n content: string,\n lookup: SemanticDedupLookup,\n options: SemanticDedupOptions,\n): Promise<SemanticDedupDecision> {\n if (!options.enabled) {\n return { action: \"keep\", reason: \"disabled\" };\n }\n // Zero candidates means the operator has disabled the embedding lookup.\n // Treat it identically to enabled=false so no backend call is made.\n if (options.candidates === 0) {\n return { action: \"keep\", reason: \"disabled\" };\n }\n const trimmed = typeof content === \"string\" ? content.trim() : \"\";\n if (!trimmed) {\n return { action: \"keep\", reason: \"no_near_duplicate\" };\n }\n const candidates = Math.max(1, Math.floor(options.candidates));\n let hits: SemanticDedupHit[] = [];\n try {\n hits = await lookup(trimmed, candidates);\n } catch {\n // Fail-open: a lookup error must not block writes.\n return { action: \"keep\", reason: \"backend_unavailable\" };\n }\n if (!Array.isArray(hits) || hits.length === 0) {\n // Provider responded (no throw) but returned no hits: the embedding index\n // is empty or contains no neighbors above the score floor. Use a distinct\n // reason so callers and telemetry can differentiate this from a genuine\n // backend failure.\n return { action: \"keep\", reason: \"no_candidates\" };\n }\n\n // Defensive: callers ought to return sorted, but don't trust it.\n let top: SemanticDedupHit | undefined;\n for (const hit of hits) {\n if (!hit || typeof hit.score !== \"number\" || !Number.isFinite(hit.score)) {\n continue;\n }\n if (!top || hit.score > top.score) {\n top = hit;\n }\n }\n if (!top) {\n return { action: \"keep\", reason: \"no_near_duplicate\" };\n }\n\n if (top.score >= options.threshold) {\n return {\n action: \"skip\",\n reason: \"near_duplicate\",\n topScore: top.score,\n topId: top.id,\n topPath: top.path,\n };\n }\n\n return {\n action: \"keep\",\n reason: \"no_near_duplicate\",\n topScore: top.score,\n topId: top.id,\n };\n}\n","/**\n * Default MECE taxonomy that maps every existing MemoryCategory value\n * to exactly one taxonomy category, ordered by priority.\n */\n\nimport type { Taxonomy } from \"./types.js\";\n\nexport const DEFAULT_TAXONOMY: Taxonomy = {\n version: 1,\n categories: [\n {\n id: \"corrections\",\n name: \"Corrections\",\n description: \"Corrections to previously stored information\",\n filingRules: [\"Any update that supersedes a prior fact\"],\n priority: 10,\n memoryCategories: [\"correction\"],\n },\n {\n id: \"principles\",\n name: \"Principles\",\n description: \"Rules, guidelines, and recurring patterns\",\n filingRules: [\"A guiding principle, rule, or skill\"],\n priority: 20,\n memoryCategories: [\"principle\", \"rule\", \"skill\"],\n },\n {\n id: \"procedures\",\n name: \"Procedures\",\n description: \"Ordered multi-step workflows the user repeats\",\n filingRules: [\"A repeatable sequence of steps or commands for a task\"],\n priority: 25,\n memoryCategories: [\"procedure\"],\n },\n {\n id: \"entities\",\n name: \"Entities\",\n description: \"People, organizations, places, projects\",\n filingRules: [\"Named entity with attributes\"],\n priority: 30,\n memoryCategories: [\"entity\", \"relationship\"],\n },\n {\n id: \"decisions\",\n name: \"Decisions\",\n description: \"Choices made and their rationale\",\n filingRules: [\"A decision or commitment with reasoning\"],\n priority: 35,\n memoryCategories: [\"decision\", \"commitment\"],\n },\n {\n id: \"preferences\",\n name: \"Preferences\",\n description: \"User likes, dislikes, and style choices\",\n filingRules: [\"Anything expressing a preference or taste\"],\n priority: 40,\n memoryCategories: [\"preference\"],\n },\n {\n id: \"facts\",\n name: \"Facts\",\n description: \"Objective statements about the world\",\n filingRules: [\"Any factual claim or piece of information\"],\n priority: 50,\n memoryCategories: [\"fact\"],\n },\n {\n id: \"moments\",\n name: \"Moments\",\n description: \"Significant events or experiences\",\n filingRules: [\"A specific event worth remembering\"],\n priority: 60,\n memoryCategories: [\"moment\"],\n },\n {\n id: \"reasoning-traces\",\n name: \"Reasoning Traces\",\n description:\n \"Stored intermediate reasoning / solution chains for a problem the agent previously solved\",\n filingRules: [\n \"A multi-step reasoning chain or solution walkthrough the agent can replay for a similar problem\",\n ],\n priority: 55,\n memoryCategories: [\"reasoning_trace\"],\n },\n ],\n};\n","/**\n * Generates a markdown decision-tree document (RESOLVER.md) from a\n * taxonomy definition.\n *\n * The document walks a user through filing a new piece of knowledge\n * by checking each category in priority order (lowest number first).\n */\n\nimport type { Taxonomy } from \"./types.js\";\n\n/**\n * Produce a markdown decision tree for the given taxonomy.\n *\n * Categories are listed in priority order (lowest number = checked first).\n * Each step asks whether the knowledge fits the category and, if so,\n * instructs the reader to file it there.\n */\nexport function generateResolverDocument(taxonomy: Taxonomy): string {\n const sorted = [...taxonomy.categories].sort((a, b) => {\n if (a.priority !== b.priority) return a.priority - b.priority;\n return a.id.localeCompare(b.id);\n });\n\n const lines: string[] = [\n \"# Memory Filing Resolver\",\n \"\",\n \"Given a new piece of knowledge, follow this tree to determine where it belongs.\",\n \"\",\n ];\n\n let step = 1;\n for (const cat of sorted) {\n lines.push(`## Step ${step}: ${cat.description}?`);\n lines.push(\"\");\n for (const rule of cat.filingRules) {\n lines.push(`- ${rule}`);\n }\n lines.push(\"\");\n lines.push(\n `> YES: File under **${cat.id}/** (priority ${cat.priority})`,\n );\n lines.push(\"\");\n step++;\n }\n\n lines.push(\"## Tie-breaking\");\n lines.push(\"\");\n lines.push(\n \"If a fact could go in multiple categories, file under the one with the **lowest priority number**.\",\n );\n lines.push(\"\");\n lines.push(`---`);\n lines.push(`*Generated from taxonomy v${taxonomy.version}*`);\n lines.push(\"\");\n\n return lines.join(\"\\n\");\n}\n","/**\n * Loads and validates a user-customized taxonomy from disk, merging\n * with the built-in defaults.\n *\n * User taxonomies are stored at `<memoryDir>/.taxonomy/taxonomy.json`.\n */\n\nimport { readFile, mkdir, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport type { Taxonomy, TaxonomyCategory } from \"./types.js\";\nimport { DEFAULT_TAXONOMY } from \"./default-taxonomy.js\";\n\nconst TAXONOMY_DIR = \".taxonomy\";\nconst TAXONOMY_FILE = \"taxonomy.json\";\n\n/** Maximum allowed slug length */\nconst MAX_SLUG_LENGTH = 32;\n\n/** Regex for valid slug: lowercase letters, digits, hyphens */\nconst SLUG_RE = /^[a-z][a-z0-9-]*$/;\n\n/**\n * Validate a taxonomy category slug.\n * Throws if the slug is invalid.\n */\nexport function validateSlug(slug: string): void {\n if (slug.length === 0) {\n throw new Error(\"Taxonomy category ID must not be empty\");\n }\n if (slug.length > MAX_SLUG_LENGTH) {\n throw new Error(\n `Taxonomy category ID \"${slug}\" exceeds ${MAX_SLUG_LENGTH} characters`,\n );\n }\n if (!SLUG_RE.test(slug)) {\n throw new Error(\n `Taxonomy category ID \"${slug}\" is invalid: must be lowercase letters, digits, and hyphens, starting with a letter`,\n );\n }\n}\n\n/**\n * Validate an entire taxonomy for structural correctness.\n * Throws on the first error found.\n */\nexport function validateTaxonomy(taxonomy: Taxonomy): void {\n if (typeof taxonomy.version !== \"number\" || taxonomy.version < 1) {\n throw new Error(\"Taxonomy version must be a positive integer\");\n }\n if (!Array.isArray(taxonomy.categories)) {\n throw new Error(\"Taxonomy categories must be an array\");\n }\n\n const seenIds = new Set<string>();\n for (const cat of taxonomy.categories) {\n validateSlug(cat.id);\n if (seenIds.has(cat.id)) {\n throw new Error(`Duplicate taxonomy category ID: \"${cat.id}\"`);\n }\n seenIds.add(cat.id);\n\n if (typeof cat.name !== \"string\" || cat.name.trim().length === 0) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a non-empty name`);\n }\n if (typeof cat.description !== \"string\" || cat.description.trim().length === 0) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a non-empty description`);\n }\n if (!Array.isArray(cat.filingRules)) {\n throw new Error(`Taxonomy category \"${cat.id}\" filingRules must be an array`);\n }\n if (typeof cat.priority !== \"number\" || !Number.isFinite(cat.priority)) {\n throw new Error(`Taxonomy category \"${cat.id}\" must have a finite numeric priority`);\n }\n if (!Array.isArray(cat.memoryCategories)) {\n throw new Error(`Taxonomy category \"${cat.id}\" memoryCategories must be an array`);\n }\n if (cat.parentId !== undefined) {\n if (typeof cat.parentId !== \"string\") {\n throw new Error(`Taxonomy category \"${cat.id}\" parentId must be a string if set`);\n }\n }\n }\n\n // Validate parentId references\n for (const cat of taxonomy.categories) {\n if (cat.parentId !== undefined && !seenIds.has(cat.parentId)) {\n throw new Error(\n `Taxonomy category \"${cat.id}\" references unknown parentId \"${cat.parentId}\"`,\n );\n }\n }\n}\n\n/**\n * Load a taxonomy from the user's memory directory.\n *\n * If `<memoryDir>/.taxonomy/taxonomy.json` exists, loads it, validates\n * it, and merges with the defaults (user categories override defaults\n * by ID). If the file does not exist, returns the defaults.\n */\nexport async function loadTaxonomy(memoryDir: string): Promise<Taxonomy> {\n const taxonomyPath = path.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);\n let raw: string;\n try {\n raw = await readFile(taxonomyPath, \"utf-8\");\n } catch (err: unknown) {\n // Only fall back to defaults for missing file; rethrow permission / I/O errors\n if (err instanceof Error && (err as NodeJS.ErrnoException).code === \"ENOENT\") {\n return structuredClone(DEFAULT_TAXONOMY);\n }\n throw err;\n }\n\n const parsed: unknown = JSON.parse(raw);\n if (typeof parsed !== \"object\" || parsed === null || Array.isArray(parsed)) {\n throw new Error(\"taxonomy.json must be a JSON object\");\n }\n\n const obj = parsed as Record<string, unknown>;\n const userVersion = typeof obj.version === \"number\" ? obj.version : DEFAULT_TAXONOMY.version;\n const userCategories = Array.isArray(obj.categories)\n ? (obj.categories as TaxonomyCategory[])\n : [];\n\n // Validate: reject duplicate IDs in user categories before merging.\n // Without this check, duplicates are silently collapsed with last-write-wins\n // semantics when inserted into the Map.\n const userIdCounts = new Map<string, number>();\n for (const cat of userCategories) {\n const id = typeof cat.id === \"string\" ? cat.id : String(cat.id);\n userIdCounts.set(id, (userIdCounts.get(id) ?? 0) + 1);\n }\n const duplicateIds = [...userIdCounts.entries()]\n .filter(([, count]) => count > 1)\n .map(([id]) => id);\n if (duplicateIds.length > 0) {\n throw new Error(\n `Duplicate category IDs in taxonomy.json: ${duplicateIds.map((id) => `\"${id}\"`).join(\", \")}`,\n );\n }\n\n // Merge: user categories override defaults by ID\n const mergedMap = new Map<string, TaxonomyCategory>();\n for (const cat of DEFAULT_TAXONOMY.categories) {\n mergedMap.set(cat.id, { ...cat });\n }\n for (const cat of userCategories) {\n mergedMap.set(cat.id, cat);\n }\n\n const merged: Taxonomy = {\n version: userVersion,\n categories: [...mergedMap.values()],\n };\n\n validateTaxonomy(merged);\n return merged;\n}\n\n/**\n * Save a taxonomy to the user's memory directory.\n */\nexport async function saveTaxonomy(\n memoryDir: string,\n taxonomy: Taxonomy,\n): Promise<void> {\n validateTaxonomy(taxonomy);\n const dir = path.join(memoryDir, TAXONOMY_DIR);\n await mkdir(dir, { recursive: true });\n const filePath = path.join(dir, TAXONOMY_FILE);\n await writeFile(filePath, JSON.stringify(taxonomy, null, 2) + \"\\n\", \"utf-8\");\n}\n\n/**\n * Get the taxonomy directory path for a given memory directory.\n */\nexport function getTaxonomyDir(memoryDir: string): string {\n return path.join(memoryDir, TAXONOMY_DIR);\n}\n\n/**\n * Get the taxonomy file path for a given memory directory.\n */\nexport function getTaxonomyFilePath(memoryDir: string): string {\n return path.join(memoryDir, TAXONOMY_DIR, TAXONOMY_FILE);\n}\n","import path from \"node:path\";\nimport { mkdir } from \"node:fs/promises\";\nimport { log } from \"../logger.js\";\nimport {\n openBetterSqlite3,\n type BetterSqlite3Database,\n} from \"../runtime/better-sqlite.js\";\n\nconst LCM_SCHEMA_VERSION = 1;\n\nexport function openLcmDatabase(memoryDir: string): BetterSqlite3Database {\n const dbPath = path.join(memoryDir, \"state\", \"lcm.sqlite\");\n const db = openBetterSqlite3(dbPath);\n db.pragma(\"journal_mode = WAL\");\n db.pragma(\"busy_timeout = 5000\");\n db.pragma(\"synchronous = NORMAL\");\n applySchema(db);\n return db;\n}\n\nexport async function ensureLcmStateDir(memoryDir: string): Promise<void> {\n await mkdir(path.join(memoryDir, \"state\"), { recursive: true });\n}\n\nfunction applySchema(db: BetterSqlite3Database): void {\n const versionRow = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_meta'\")\n .get() as { name: string } | undefined;\n\n if (!versionRow) {\n createTables(db);\n return;\n }\n\n const meta = db\n .prepare(\"SELECT value FROM lcm_meta WHERE key = 'schema_version'\")\n .get() as { value: string } | undefined;\n const currentVersion = meta ? parseInt(meta.value, 10) : 0;\n\n if (currentVersion < LCM_SCHEMA_VERSION) {\n // TODO: When v2 is needed, add explicit ALTER TABLE migrations here\n // instead of relying on CREATE TABLE IF NOT EXISTS (which won't add\n // new columns to existing tables).\n log.info(`LCM schema upgrade: v${currentVersion} → v${LCM_SCHEMA_VERSION}`);\n createTables(db);\n }\n}\n\nfunction createTables(db: BetterSqlite3Database): void {\n db.exec(`\n CREATE TABLE IF NOT EXISTS lcm_meta (\n key TEXT PRIMARY KEY,\n value TEXT NOT NULL\n );\n\n CREATE TABLE IF NOT EXISTS lcm_messages (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n turn_index INTEGER NOT NULL,\n role TEXT NOT NULL,\n content TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n created_at TEXT NOT NULL,\n metadata TEXT\n );\n CREATE INDEX IF NOT EXISTS idx_lcm_messages_session\n ON lcm_messages(session_id, turn_index);\n\n CREATE TABLE IF NOT EXISTS lcm_summary_nodes (\n id TEXT PRIMARY KEY,\n session_id TEXT NOT NULL,\n depth INTEGER NOT NULL,\n parent_id TEXT,\n summary_text TEXT NOT NULL,\n token_count INTEGER NOT NULL,\n msg_start INTEGER NOT NULL,\n msg_end INTEGER NOT NULL,\n escalation INTEGER NOT NULL DEFAULT 0,\n created_at TEXT NOT NULL,\n FOREIGN KEY (parent_id) REFERENCES lcm_summary_nodes(id)\n );\n CREATE INDEX IF NOT EXISTS idx_lcm_summary_session\n ON lcm_summary_nodes(session_id, depth);\n CREATE INDEX IF NOT EXISTS idx_lcm_summary_range\n ON lcm_summary_nodes(session_id, msg_start, msg_end);\n\n CREATE TABLE IF NOT EXISTS lcm_compaction_events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n session_id TEXT NOT NULL,\n fired_at TEXT NOT NULL,\n msg_before INTEGER NOT NULL,\n tokens_before INTEGER NOT NULL,\n tokens_after INTEGER NOT NULL\n );\n `);\n\n // FTS5 tables — created separately so IF NOT EXISTS works correctly\n const hasFts = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_messages_fts'\")\n .get();\n if (!hasFts) {\n db.exec(`\n CREATE VIRTUAL TABLE lcm_messages_fts USING fts5(\n content,\n content=lcm_messages,\n content_rowid=id\n );\n `);\n }\n\n const hasSummaryFts = db\n .prepare(\"SELECT name FROM sqlite_master WHERE type='table' AND name='lcm_summaries_fts'\")\n .get();\n if (!hasSummaryFts) {\n db.exec(`\n CREATE VIRTUAL TABLE lcm_summaries_fts USING fts5(\n summary_text,\n content=lcm_summary_nodes,\n content_rowid=rowid\n );\n `);\n }\n\n // Upsert meta version\n db.prepare(\"INSERT OR REPLACE INTO lcm_meta (key, value) VALUES ('schema_version', ?)\").run(\n String(LCM_SCHEMA_VERSION),\n );\n}\n","import type Database from \"better-sqlite3\";\nimport { log } from \"../logger.js\";\n\nexport interface LcmMessage {\n id: number;\n session_id: string;\n turn_index: number;\n role: string;\n content: string;\n token_count: number;\n created_at: string;\n metadata: string | null;\n}\n\nexport interface LcmSearchResult {\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n score: number;\n}\n\nexport interface LcmSearchWithContentResult {\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n score: number;\n}\n\n/** Rough token count: ~4 chars per token. */\nexport function estimateTokens(text: string): number {\n return Math.ceil(text.length / 4);\n}\n\nexport class LcmArchive {\n constructor(private readonly db: Database.Database) {}\n\n /** Append a message to the archive. Returns the row id. */\n appendMessage(\n sessionId: string,\n turnIndex: number,\n role: string,\n content: string,\n metadata?: Record<string, unknown>,\n ): number {\n const tokenCount = estimateTokens(content);\n const now = new Date().toISOString();\n const metaJson = metadata ? JSON.stringify(metadata) : null;\n\n const stmt = this.db.prepare(`\n INSERT INTO lcm_messages (session_id, turn_index, role, content, token_count, created_at, metadata)\n VALUES (?, ?, ?, ?, ?, ?, ?)\n `);\n const result = stmt.run(sessionId, turnIndex, role, content, tokenCount, now, metaJson);\n const rowId = Number(result.lastInsertRowid);\n\n // Keep FTS in sync\n this.db\n .prepare(\"INSERT INTO lcm_messages_fts (rowid, content) VALUES (?, ?)\")\n .run(rowId, content);\n\n return rowId;\n }\n\n /** Append multiple messages in a single transaction. */\n appendMessages(\n sessionId: string,\n messages: Array<{ turnIndex: number; role: string; content: string; metadata?: Record<string, unknown> }>,\n ): void {\n if (messages.length === 0) return;\n\n const txn = this.db.transaction(() => {\n for (const msg of messages) {\n this.appendMessage(sessionId, msg.turnIndex, msg.role, msg.content, msg.metadata);\n }\n });\n txn();\n }\n\n /** Get the highest turn_index for a session, or -1 if none. */\n getMaxTurnIndex(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT MAX(turn_index) as max_turn FROM lcm_messages WHERE session_id = ?\")\n .get(sessionId) as { max_turn: number | null } | undefined;\n return row?.max_turn ?? -1;\n }\n\n /** Retrieve messages in a turn range (inclusive). */\n getMessages(sessionId: string, fromTurn: number, toTurn: number): LcmMessage[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_messages WHERE session_id = ? AND turn_index >= ? AND turn_index <= ? ORDER BY turn_index\",\n )\n .all(sessionId, fromTurn, toTurn) as LcmMessage[];\n }\n\n /** Retrieve unsummarized messages (after last leaf summary). */\n getUnsummarizedMessages(sessionId: string): LcmMessage[] {\n const lastLeafEnd = this.db\n .prepare(\n \"SELECT MAX(msg_end) as last_end FROM lcm_summary_nodes WHERE session_id = ? AND depth = 0\",\n )\n .get(sessionId) as { last_end: number | null } | undefined;\n\n const lastSummarized = lastLeafEnd?.last_end ?? -1;\n return this.db\n .prepare(\n \"SELECT * FROM lcm_messages WHERE session_id = ? AND turn_index > ? ORDER BY turn_index\",\n )\n .all(sessionId, lastSummarized) as LcmMessage[];\n }\n\n /** Full-text search across all messages. */\n search(query: string, limit: number, sessionId?: string): LcmSearchResult[] {\n try {\n const ftsQuery = sanitizeFtsQuery(query);\n if (!ftsQuery) return [];\n\n let sql: string;\n const params: unknown[] = [ftsQuery];\n\n if (sessionId) {\n sql = `\n SELECT m.turn_index, m.role, snippet(lcm_messages_fts, 0, '>>>', '<<<', '...', 48) as snippet,\n m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n AND m.session_id = ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(sessionId, limit);\n } else {\n sql = `\n SELECT m.turn_index, m.role, snippet(lcm_messages_fts, 0, '>>>', '<<<', '...', 48) as snippet,\n m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(limit);\n }\n\n const rows = this.db.prepare(sql).all(...params) as Array<{\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n rank: number;\n }>;\n\n return rows.map((r) => ({\n turn_index: r.turn_index,\n role: r.role,\n snippet: r.snippet,\n session_id: r.session_id,\n score: -r.rank, // FTS5 rank is negative; negate for ascending score\n }));\n } catch (err) {\n log.debug(`LCM FTS search error: ${err}`);\n return [];\n }\n }\n\n /**\n * Full-text search returning focused excerpts around matching terms.\n * Returns ~1000-char windows centered on query term matches.\n * Deduplicates by message id and returns results sorted by FTS rank.\n */\n searchWithContent(query: string, limit: number, sessionId?: string, excerptChars = 1000): LcmSearchWithContentResult[] {\n try {\n const ftsQuery = sanitizeFtsQuery(query);\n if (!ftsQuery) return [];\n\n // Extract content words from query for excerpt windowing\n const queryWords = query\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 1 && !STOPWORDS.has(w.toLowerCase()))\n .map((w) => w.toLowerCase());\n\n let sql: string;\n const params: unknown[] = [ftsQuery];\n\n if (sessionId) {\n sql = `\n SELECT m.id, m.turn_index, m.role, m.content, m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n AND m.session_id = ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(sessionId, limit);\n } else {\n sql = `\n SELECT m.id, m.turn_index, m.role, m.content, m.session_id, rank\n FROM lcm_messages_fts f\n JOIN lcm_messages m ON m.id = f.rowid\n WHERE lcm_messages_fts MATCH ?\n ORDER BY rank\n LIMIT ?\n `;\n params.push(limit);\n }\n\n const rows = this.db.prepare(sql).all(...params) as Array<{\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n rank: number;\n }>;\n\n // Deduplicate by message id (same message may match multiple terms)\n const seen = new Set<number>();\n const results: LcmSearchWithContentResult[] = [];\n for (const r of rows) {\n if (seen.has(r.id)) continue;\n seen.add(r.id);\n results.push({\n id: r.id,\n turn_index: r.turn_index,\n role: r.role,\n content: extractExcerpt(r.content, queryWords, excerptChars),\n session_id: r.session_id,\n score: -r.rank,\n });\n }\n return results;\n } catch (err) {\n log.debug(`LCM FTS searchWithContent error: ${err}`);\n return [];\n }\n }\n\n /** Get total message count for a session. */\n getMessageCount(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_messages WHERE session_id = ?\")\n .get(sessionId) as { cnt: number };\n return row.cnt;\n }\n\n /** Get total message count across all sessions. */\n getTotalMessageCount(): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_messages\")\n .get() as { cnt: number };\n return row.cnt;\n }\n\n /** Prune messages older than retentionDays. */\n pruneOldMessages(retentionDays: number): number {\n const cutoff = new Date(Date.now() - retentionDays * 86400_000).toISOString();\n\n // Delete from FTS first\n this.db\n .prepare(\n \"DELETE FROM lcm_messages_fts WHERE rowid IN (SELECT id FROM lcm_messages WHERE created_at < ?)\",\n )\n .run(cutoff);\n\n const result = this.db\n .prepare(\"DELETE FROM lcm_messages WHERE created_at < ?\")\n .run(cutoff);\n return result.changes;\n }\n}\n\n/**\n * Extract a focused excerpt from content centered on query term matches.\n * Returns a window of ~excerptChars around the first matching term.\n * If content is shorter than excerptChars, returns the full content.\n */\nfunction extractExcerpt(content: string, queryWords: string[], excerptChars: number): string {\n if (content.length <= excerptChars) return content;\n\n // Find the earliest position of any query word in the content\n const contentLower = content.toLowerCase();\n let bestPos = -1;\n for (const word of queryWords) {\n const pos = contentLower.indexOf(word);\n if (pos !== -1 && (bestPos === -1 || pos < bestPos)) {\n bestPos = pos;\n }\n }\n\n // If no match found (shouldn't happen for FTS results), return start\n if (bestPos === -1) {\n return content.slice(0, excerptChars) + \"...\";\n }\n\n // Center the window around the match\n const halfWindow = Math.floor(excerptChars / 2);\n let start = Math.max(0, bestPos - halfWindow);\n let end = Math.min(content.length, start + excerptChars);\n\n // Adjust start if we hit the end\n if (end === content.length) {\n start = Math.max(0, end - excerptChars);\n }\n\n // Extend to sentence boundaries if possible\n if (start > 0) {\n const sentenceStart = content.lastIndexOf(\". \", start);\n if (sentenceStart !== -1 && start - sentenceStart < 200) {\n start = sentenceStart + 2;\n }\n }\n if (end < content.length) {\n const sentenceEnd = content.indexOf(\". \", end - 1);\n if (sentenceEnd !== -1 && sentenceEnd - end < 200) {\n end = sentenceEnd + 1;\n }\n }\n\n const prefix = start > 0 ? \"...\" : \"\";\n const suffix = end < content.length ? \"...\" : \"\";\n return prefix + content.slice(start, end) + suffix;\n}\n\nconst STOPWORDS = new Set([\n \"a\", \"an\", \"the\", \"is\", \"are\", \"was\", \"were\", \"be\", \"been\", \"being\",\n \"have\", \"has\", \"had\", \"do\", \"does\", \"did\", \"will\", \"would\", \"could\",\n \"should\", \"may\", \"might\", \"shall\", \"can\", \"to\", \"of\", \"in\", \"for\",\n \"on\", \"with\", \"at\", \"by\", \"from\", \"as\", \"into\", \"about\", \"between\",\n \"through\", \"during\", \"before\", \"after\", \"and\", \"but\", \"or\", \"nor\",\n \"not\", \"so\", \"if\", \"then\", \"than\", \"that\", \"this\", \"it\", \"its\",\n \"what\", \"which\", \"who\", \"whom\", \"how\", \"when\", \"where\", \"why\",\n \"all\", \"each\", \"every\", \"both\", \"few\", \"more\", \"most\", \"other\",\n \"some\", \"such\", \"no\", \"only\", \"own\", \"same\", \"just\", \"very\",\n \"my\", \"your\", \"his\", \"her\", \"our\", \"their\", \"me\", \"him\", \"us\", \"them\",\n \"i\", \"you\", \"he\", \"she\", \"we\", \"they\",\n]);\n\n/**\n * Sanitize a query for FTS5 MATCH.\n * Uses OR logic so partial matches rank higher than no matches.\n * Filters stopwords to focus on content words.\n */\nfunction sanitizeFtsQuery(raw: string): string {\n const words = raw\n .replace(/[^\\w\\s]/g, \" \")\n .split(/\\s+/)\n .filter((w) => w.length > 1 && !STOPWORDS.has(w.toLowerCase()));\n if (words.length === 0) {\n // If all words were stopwords, fall back to using all words\n const allWords = raw.replace(/[^\\w\\s]/g, \" \").split(/\\s+/).filter((w) => w.length > 1);\n if (allWords.length === 0) return \"\";\n return allWords.map((w) => `\"${w}\"`).join(\" OR \");\n }\n return words.map((w) => `\"${w}\"`).join(\" OR \");\n}\n","import type Database from \"better-sqlite3\";\nimport { log } from \"../logger.js\";\n\nexport interface SummaryNode {\n id: string;\n session_id: string;\n depth: number;\n parent_id: string | null;\n summary_text: string;\n token_count: number;\n msg_start: number;\n msg_end: number;\n escalation: number;\n created_at: string;\n}\n\nexport class LcmDag {\n constructor(private readonly db: Database.Database) {}\n\n /** Insert a new summary node. */\n insertNode(node: Omit<SummaryNode, \"created_at\">): void {\n const now = new Date().toISOString();\n this.db\n .prepare(`\n INSERT INTO lcm_summary_nodes (id, session_id, depth, parent_id, summary_text, token_count, msg_start, msg_end, escalation, created_at)\n VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?)\n `)\n .run(\n node.id,\n node.session_id,\n node.depth,\n node.parent_id,\n node.summary_text,\n node.token_count,\n node.msg_start,\n node.msg_end,\n node.escalation,\n now,\n );\n\n // Keep FTS in sync\n const rowid = this.db\n .prepare(\"SELECT rowid FROM lcm_summary_nodes WHERE id = ?\")\n .get(node.id) as { rowid: number } | undefined;\n if (rowid) {\n this.db\n .prepare(\"INSERT INTO lcm_summaries_fts (rowid, summary_text) VALUES (?, ?)\")\n .run(rowid.rowid, node.summary_text);\n }\n }\n\n /** Get leaf nodes (depth=0) for a session without a parent yet, ordered by msg_start. */\n getOrphanNodesAtDepth(sessionId: string, depth: number): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? AND depth = ? AND parent_id IS NULL ORDER BY msg_start\",\n )\n .all(sessionId, depth) as SummaryNode[];\n }\n\n /** Get all nodes at a given depth for a session. */\n getNodesAtDepth(sessionId: string, depth: number): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? AND depth = ? ORDER BY msg_start\",\n )\n .all(sessionId, depth) as SummaryNode[];\n }\n\n /** Get child nodes of a parent. */\n getChildren(parentId: string): SummaryNode[] {\n return this.db\n .prepare(\"SELECT * FROM lcm_summary_nodes WHERE parent_id = ? ORDER BY msg_start\")\n .all(parentId) as SummaryNode[];\n }\n\n /** Get the deepest summary nodes covering a session (highest depth, broadest coverage). */\n getDeepestNodes(sessionId: string): SummaryNode[] {\n const maxDepth = this.db\n .prepare(\"SELECT MAX(depth) as max_depth FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { max_depth: number | null } | undefined;\n\n if (!maxDepth?.max_depth && maxDepth?.max_depth !== 0) return [];\n\n return this.getNodesAtDepth(sessionId, maxDepth.max_depth);\n }\n\n /** Get the maximum depth for a session. */\n getMaxDepth(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT MAX(depth) as max_depth FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { max_depth: number | null } | undefined;\n return row?.max_depth ?? -1;\n }\n\n /** Get summary nodes that best cover a turn range, preferring higher depth. */\n getCoveringNodes(sessionId: string, fromTurn: number, toTurn: number): SummaryNode[] {\n return this.db\n .prepare(`\n SELECT * FROM lcm_summary_nodes\n WHERE session_id = ?\n AND msg_start <= ?\n AND msg_end >= ?\n ORDER BY depth DESC, msg_start\n `)\n .all(sessionId, toTurn, fromTurn) as SummaryNode[];\n }\n\n /** Get all nodes for a session, ordered by depth then range. */\n getAllNodes(sessionId: string): SummaryNode[] {\n return this.db\n .prepare(\n \"SELECT * FROM lcm_summary_nodes WHERE session_id = ? ORDER BY depth, msg_start\",\n )\n .all(sessionId) as SummaryNode[];\n }\n\n /** Get total node count for a session. */\n getNodeCount(sessionId: string): number {\n const row = this.db\n .prepare(\"SELECT COUNT(*) as cnt FROM lcm_summary_nodes WHERE session_id = ?\")\n .get(sessionId) as { cnt: number };\n return row.cnt;\n }\n\n /** Set parent_id for a list of child node IDs. */\n setParent(childIds: string[], parentId: string): void {\n const stmt = this.db.prepare(\n \"UPDATE lcm_summary_nodes SET parent_id = ? WHERE id = ?\",\n );\n const txn = this.db.transaction(() => {\n for (const childId of childIds) {\n stmt.run(parentId, childId);\n }\n });\n txn();\n }\n\n /** Record a compaction event. */\n recordCompaction(\n sessionId: string,\n msgBefore: number,\n tokensBefore: number,\n tokensAfter: number,\n ): void {\n this.db\n .prepare(`\n INSERT INTO lcm_compaction_events (session_id, fired_at, msg_before, tokens_before, tokens_after)\n VALUES (?, ?, ?, ?, ?)\n `)\n .run(sessionId, new Date().toISOString(), msgBefore, tokensBefore, tokensAfter);\n }\n\n /** Prune summary nodes for old sessions. */\n pruneOldNodes(retentionDays: number): number {\n const cutoff = new Date(Date.now() - retentionDays * 86400_000).toISOString();\n\n this.db\n .prepare(\n \"DELETE FROM lcm_summaries_fts WHERE rowid IN (SELECT rowid FROM lcm_summary_nodes WHERE created_at < ?)\",\n )\n .run(cutoff);\n\n const result = this.db\n .prepare(\"DELETE FROM lcm_summary_nodes WHERE created_at < ?\")\n .run(cutoff);\n return result.changes;\n }\n}\n","import { log } from \"../logger.js\";\nimport type { LcmArchive, LcmMessage } from \"./archive.js\";\nimport { LcmDag } from \"./dag.js\";\nimport { estimateTokens } from \"./archive.js\";\n\n/** Generate a ULID-like ID (timestamp + random). */\nfunction generateNodeId(): string {\n const ts = Date.now().toString(36).padStart(9, \"0\");\n const rand = Math.random().toString(36).slice(2, 10);\n return `lcm-${ts}-${rand}`;\n}\n\nexport type SummarizeFn = (\n text: string,\n targetTokens: number,\n aggressive: boolean,\n) => Promise<string | null>;\n\nexport interface LcmSummarizerConfig {\n leafBatchSize: number;\n rollupFanIn: number;\n maxDepth: number;\n deterministicMaxTokens: number;\n}\n\nexport class LcmSummarizer {\n constructor(\n private readonly archive: LcmArchive,\n private readonly dag: LcmDag,\n private readonly summarizeFn: SummarizeFn,\n private readonly config: LcmSummarizerConfig,\n ) {}\n\n /**\n * Run incremental summarization for a session.\n * Creates leaf nodes from unsummarized messages, then rolls up as needed.\n */\n async summarizeIncremental(sessionId: string): Promise<number> {\n let nodesCreated = 0;\n\n // Phase 1: Create leaf nodes from unsummarized messages\n const unsummarized = this.archive.getUnsummarizedMessages(sessionId);\n if (unsummarized.length >= this.config.leafBatchSize) {\n const batches = chunkArray(unsummarized, this.config.leafBatchSize);\n // Only process complete batches (leave partial for next time)\n const completeBatches = unsummarized.length % this.config.leafBatchSize === 0\n ? batches\n : batches.slice(0, -1);\n\n for (const batch of completeBatches) {\n const created = await this.createLeafNode(sessionId, batch);\n if (created) nodesCreated++;\n }\n }\n\n // Phase 2: Roll up at each depth level\n if (nodesCreated > 0) {\n nodesCreated += await this.rollupAll(sessionId);\n }\n\n return nodesCreated;\n }\n\n /** Create a leaf summary node (depth 0) from a batch of messages. */\n private async createLeafNode(\n sessionId: string,\n messages: LcmMessage[],\n ): Promise<boolean> {\n if (messages.length === 0) return false;\n\n const combinedText = messages\n .map((m) => `[${m.role}] ${m.content}`)\n .join(\"\\n\\n\");\n\n const inputTokens = estimateTokens(combinedText);\n const targetTokens = Math.max(64, Math.ceil(inputTokens * 0.25));\n\n const summary = await this.summarizeWithEscalation(combinedText, targetTokens);\n\n this.dag.insertNode({\n id: generateNodeId(),\n session_id: sessionId,\n depth: 0,\n parent_id: null,\n summary_text: summary.text,\n token_count: estimateTokens(summary.text),\n msg_start: messages[0].turn_index,\n msg_end: messages[messages.length - 1].turn_index,\n escalation: summary.escalation,\n });\n\n return true;\n }\n\n /** Roll up orphan nodes at each depth level up to maxDepth. */\n private async rollupAll(sessionId: string): Promise<number> {\n let totalCreated = 0;\n\n for (let depth = 0; depth < this.config.maxDepth; depth++) {\n const orphans = this.dag.getOrphanNodesAtDepth(sessionId, depth);\n if (orphans.length < this.config.rollupFanIn) continue;\n\n const batches = chunkArray(orphans, this.config.rollupFanIn);\n // Only process complete batches\n const completeBatches = orphans.length % this.config.rollupFanIn === 0\n ? batches\n : batches.slice(0, -1);\n\n for (const batch of completeBatches) {\n const combinedText = batch\n .map((n) => n.summary_text)\n .join(\"\\n\\n\");\n\n const inputTokens = estimateTokens(combinedText);\n const targetTokens = Math.max(64, Math.ceil(inputTokens * 0.25));\n\n const summary = await this.summarizeWithEscalation(combinedText, targetTokens);\n\n const parentId = generateNodeId();\n this.dag.insertNode({\n id: parentId,\n session_id: sessionId,\n depth: depth + 1,\n parent_id: null,\n summary_text: summary.text,\n token_count: estimateTokens(summary.text),\n msg_start: batch[0].msg_start,\n msg_end: batch[batch.length - 1].msg_end,\n escalation: summary.escalation,\n });\n\n this.dag.setParent(\n batch.map((n) => n.id),\n parentId,\n );\n\n totalCreated++;\n }\n }\n\n return totalCreated;\n }\n\n /**\n * Three-level escalation:\n * 0 = Normal LLM summary\n * 1 = Aggressive bullet compression\n * 2 = Deterministic truncation (no LLM)\n */\n private async summarizeWithEscalation(\n text: string,\n targetTokens: number,\n ): Promise<{ text: string; escalation: number }> {\n // Level 0: Normal LLM summary\n try {\n const result = await this.summarizeFn(text, targetTokens, false);\n if (result && estimateTokens(result) <= targetTokens * 1.5) {\n return { text: result, escalation: 0 };\n }\n // If too long, try aggressive\n } catch (err) {\n log.debug(`LCM level-0 summary failed: ${err}`);\n }\n\n // Level 1: Aggressive bullet compression\n try {\n const aggressiveTarget = Math.max(32, Math.ceil(targetTokens * 0.5));\n const result = await this.summarizeFn(text, aggressiveTarget, true);\n if (result && estimateTokens(result) <= targetTokens * 1.5) {\n return { text: result, escalation: 1 };\n }\n } catch (err) {\n log.debug(`LCM level-1 summary failed: ${err}`);\n }\n\n // Level 2: Deterministic truncation (guaranteed, no LLM)\n return {\n text: deterministicTruncate(text, this.config.deterministicMaxTokens),\n escalation: 2,\n };\n }\n}\n\n/** Deterministic truncation: first and last sentence, plus middle truncation. */\nfunction deterministicTruncate(text: string, maxTokens: number): string {\n const maxChars = maxTokens * 4;\n if (text.length <= maxChars) return text;\n\n const sentences = text.split(/(?<=[.!?])\\s+/).filter((s) => s.length > 0);\n if (sentences.length <= 2) {\n return text.slice(0, maxChars);\n }\n\n const first = sentences[0];\n const last = sentences[sentences.length - 1];\n const budget = maxChars - first.length - last.length - 20;\n\n if (budget <= 0) {\n return text.slice(0, maxChars);\n }\n\n // Fill from the beginning until budget runs out\n const middle: string[] = [];\n let used = 0;\n for (let i = 1; i < sentences.length - 1; i++) {\n if (used + sentences[i].length > budget) break;\n middle.push(sentences[i]);\n used += sentences[i].length;\n }\n\n return `${first} ${middle.join(\" \")}${middle.length < sentences.length - 2 ? \" [...] \" : \" \"}${last}`;\n}\n\nfunction chunkArray<T>(arr: T[], size: number): T[][] {\n const chunks: T[][] = [];\n for (let i = 0; i < arr.length; i += size) {\n chunks.push(arr.slice(i, i + size));\n }\n return chunks;\n}\n","import type { LcmDag, SummaryNode } from \"./dag.js\";\nimport type { LcmArchive } from \"./archive.js\";\nimport { log } from \"../logger.js\";\n\nexport interface LcmRecallConfig {\n freshTailTurns: number;\n budgetChars: number;\n}\n\n/**\n * Assemble a compressed session history section from the summary DAG.\n *\n * Strategy:\n * 1. For the \"fresh tail\" (most recent N turns), use leaf-level summaries for maximum detail.\n * 2. For older portions, use the deepest available summary nodes (most compressed).\n * 3. Fill within budget, prioritizing recent content.\n */\nexport function assembleCompressedHistory(\n dag: LcmDag,\n archive: LcmArchive,\n sessionId: string,\n config: LcmRecallConfig,\n): string {\n const maxTurn = archive.getMaxTurnIndex(sessionId);\n if (maxTurn < 0) return \"\";\n\n const allNodes = dag.getAllNodes(sessionId);\n if (allNodes.length === 0) return \"\";\n\n const freshTailStart = Math.max(0, maxTurn - config.freshTailTurns + 1);\n const sections: string[] = [];\n let usedChars = 0;\n\n // Collect nodes covering the \"old\" portion (before fresh tail)\n if (freshTailStart > 0) {\n const oldNodes = selectBestCoverage(allNodes, 0, freshTailStart - 1);\n for (const node of oldNodes) {\n const label = formatRangeLabel(node, maxTurn);\n const entry = `**${label}** (depth ${node.depth}):\\n${node.summary_text}`;\n if (usedChars + entry.length > config.budgetChars) break;\n sections.push(entry);\n usedChars += entry.length;\n }\n }\n\n // Collect leaf nodes that overlap with the fresh tail region.\n // The old section uses deep nodes (depth > 0), so leaf nodes included here\n // won't duplicate old-section content. Use msg_end >= freshTailStart to\n // include straddling leaf nodes that partially cover the fresh region.\n const freshNodes = allNodes\n .filter(\n (n) => n.depth === 0 && n.msg_end >= freshTailStart && n.msg_end <= maxTurn,\n )\n .sort((a, b) => a.msg_start - b.msg_start);\n\n for (const node of freshNodes) {\n const label = `Recent (turns ${node.msg_start}-${node.msg_end})`;\n const entry = `**${label}**:\\n${node.summary_text}`;\n if (usedChars + entry.length > config.budgetChars) break;\n sections.push(entry);\n usedChars += entry.length;\n }\n\n if (sections.length === 0) return \"\";\n\n return `## Session History (Compressed)\\n\\n${sections.join(\"\\n\\n\")}`;\n}\n\n/**\n * Select the best coverage for a turn range.\n * Prefers deeper (more compressed) nodes. Avoids overlapping coverage.\n */\nfunction selectBestCoverage(\n allNodes: SummaryNode[],\n fromTurn: number,\n toTurn: number,\n): SummaryNode[] {\n // Filter to nodes that overlap with the requested range\n const candidates = allNodes.filter(\n (n) => n.msg_start <= toTurn && n.msg_end >= fromTurn,\n );\n\n if (candidates.length === 0) return [];\n\n // Sort by msg_start ascending, then depth descending (prefer deeper at same position)\n candidates.sort((a, b) => {\n if (a.msg_start !== b.msg_start) return a.msg_start - b.msg_start;\n return b.depth - a.depth;\n });\n\n // Greedily select non-overlapping nodes, preferring deeper coverage.\n // Clamp msg_end to toTurn to prevent deep nodes from extending\n // past the requested range (e.g., into the fresh tail region).\n const selected: SummaryNode[] = [];\n let coveredUpTo = fromTurn - 1;\n\n for (const node of candidates) {\n if (node.msg_start > coveredUpTo) {\n selected.push(node);\n coveredUpTo = Math.min(node.msg_end, toTurn);\n if (coveredUpTo >= toTurn) break;\n }\n }\n\n // Re-sort selected by msg_start for chronological output\n selected.sort((a, b) => a.msg_start - b.msg_start);\n return selected;\n}\n\nfunction formatRangeLabel(node: SummaryNode, maxTurn: number): string {\n const startPct = Math.round((node.msg_start / Math.max(1, maxTurn)) * 100);\n const endPct = Math.round((node.msg_end / Math.max(1, maxTurn)) * 100);\n\n if (startPct < 33) return `Early session (turns ${node.msg_start}-${node.msg_end})`;\n if (endPct < 66) return `Mid session (turns ${node.msg_start}-${node.msg_end})`;\n return `Later session (turns ${node.msg_start}-${node.msg_end})`;\n}\n","export interface LcmObserveMessage {\n role: string;\n content: string;\n}\n\nexport interface LcmWorkQueueHooks {\n onJobStart?: (input: {\n sessionId: string;\n depth: number;\n inFlight: number;\n waitMs: number;\n }) => void;\n onJobFinish?: (input: {\n sessionId: string;\n depth: number;\n inFlight: number;\n waitMs: number;\n runMs: number;\n totalMs: number;\n error?: unknown;\n }) => void;\n}\n\nexport interface LcmWorkQueueOptions {\n concurrency?: number;\n worker: (sessionId: string, messages: LcmObserveMessage[]) => Promise<void>;\n hooks?: LcmWorkQueueHooks;\n}\n\ninterface PendingJob {\n sessionId: string;\n messages: LcmObserveMessage[];\n enqueuedAt: number;\n}\n\n/**\n * Small keyed work queue for LCM observe processing.\n *\n * Jobs are coalesced per session while they are pending. A session can have\n * at most one in-flight job at a time, and the queue processes jobs FIFO up to\n * the configured concurrency limit.\n */\nexport class LcmWorkQueue {\n private readonly concurrency: number;\n private readonly worker: (\n sessionId: string,\n messages: LcmObserveMessage[],\n ) => Promise<void>;\n private readonly hooks: LcmWorkQueueHooks;\n private readonly pending = new Map<string, PendingJob>();\n private readonly inFlightSessions = new Set<string>();\n private inFlight = 0;\n private readonly idleWaiters: Array<() => void> = [];\n private readonly sessionIdleWaiters = new Map<string, Array<() => void>>();\n private drainScheduled = false;\n\n constructor(options: LcmWorkQueueOptions) {\n this.concurrency = Math.max(1, Math.floor(options.concurrency ?? 1));\n this.worker = options.worker;\n this.hooks = options.hooks ?? {};\n }\n\n enqueue(sessionId: string, messages: LcmObserveMessage[]): void {\n if (messages.length === 0) return;\n\n const now = Date.now();\n const existing = this.pending.get(sessionId);\n if (existing) {\n existing.messages.push(...messages.map((message) => ({ ...message })));\n } else {\n this.pending.set(sessionId, {\n sessionId,\n messages: messages.map((message) => ({ ...message })),\n enqueuedAt: now,\n });\n }\n\n this.scheduleDrain();\n }\n\n get depth(): number {\n return this.pending.size;\n }\n\n get inFlightCount(): number {\n return this.inFlight;\n }\n\n async whenIdle(): Promise<void> {\n if (this.depth === 0 && this.inFlight === 0) return;\n await new Promise<void>((resolve) => {\n this.idleWaiters.push(resolve);\n });\n }\n\n async whenSessionIdle(sessionId: string): Promise<void> {\n if (!this.pending.has(sessionId) && !this.inFlightSessions.has(sessionId))\n return;\n await new Promise<void>((resolve) => {\n const waiters = this.sessionIdleWaiters.get(sessionId) ?? [];\n waiters.push(resolve);\n this.sessionIdleWaiters.set(sessionId, waiters);\n });\n }\n\n private startAvailableJobs(): void {\n while (this.inFlight < this.concurrency && this.pending.size > 0) {\n const next = Array.from(this.pending.entries()).find(\n ([sessionId]) => !this.inFlightSessions.has(sessionId),\n );\n if (!next) break;\n\n const [sessionId, job] = next;\n this.pending.delete(sessionId);\n this.inFlight++;\n this.inFlightSessions.add(sessionId);\n\n const startedAt = Date.now();\n const waitMs = startedAt - job.enqueuedAt;\n this.hooks.onJobStart?.({\n sessionId,\n depth: this.depth,\n inFlight: this.inFlight,\n waitMs,\n });\n\n void this.runJob(job, startedAt, waitMs);\n }\n\n this.resolveIdleWaitersIfNeeded();\n }\n\n private scheduleDrain(): void {\n if (this.drainScheduled) return;\n this.drainScheduled = true;\n\n queueMicrotask(() => {\n this.drainScheduled = false;\n this.startAvailableJobs();\n });\n }\n\n private async runJob(\n job: PendingJob,\n startedAt: number,\n waitMs: number,\n ): Promise<void> {\n let error: unknown;\n\n try {\n await this.worker(job.sessionId, job.messages);\n } catch (err) {\n error = err;\n } finally {\n const finishedAt = Date.now();\n const runMs = finishedAt - startedAt;\n const totalMs = finishedAt - job.enqueuedAt;\n\n this.inFlight--;\n this.inFlightSessions.delete(job.sessionId);\n this.hooks.onJobFinish?.({\n sessionId: job.sessionId,\n depth: this.depth,\n inFlight: this.inFlight,\n waitMs,\n runMs,\n totalMs,\n error,\n });\n\n if (this.pending.size > 0) {\n this.scheduleDrain();\n } else {\n this.resolveIdleWaitersIfNeeded();\n }\n this.resolveSessionIdleWaitersIfNeeded(job.sessionId);\n }\n }\n\n private resolveIdleWaitersIfNeeded(): void {\n if (this.depth !== 0 || this.inFlight !== 0) return;\n\n const waiters = this.idleWaiters.splice(0, this.idleWaiters.length);\n for (const resolve of waiters) resolve();\n }\n\n private resolveSessionIdleWaitersIfNeeded(sessionId: string): void {\n if (this.pending.has(sessionId) || this.inFlightSessions.has(sessionId))\n return;\n\n const waiters = this.sessionIdleWaiters.get(sessionId);\n if (!waiters || waiters.length === 0) return;\n\n this.sessionIdleWaiters.delete(sessionId);\n for (const resolve of waiters) resolve();\n }\n}\n","import type Database from \"better-sqlite3\";\nimport { openLcmDatabase, ensureLcmStateDir } from \"./schema.js\";\nimport { LcmArchive } from \"./archive.js\";\nimport { LcmDag } from \"./dag.js\";\nimport { LcmSummarizer, type SummarizeFn } from \"./summarizer.js\";\nimport { assembleCompressedHistory, type LcmRecallConfig } from \"./recall.js\";\nimport { LcmWorkQueue, type LcmObserveMessage } from \"./queue.js\";\nimport type { PluginConfig } from \"../types.js\";\nimport { log } from \"../logger.js\";\n\nexport interface LcmEngineConfig {\n enabled: boolean;\n leafBatchSize: number;\n rollupFanIn: number;\n freshTailTurns: number;\n maxDepth: number;\n deterministicMaxTokens: number;\n archiveRetentionDays: number;\n recallBudgetShare: number;\n}\n\nexport function extractLcmConfig(cfg: PluginConfig): LcmEngineConfig {\n return {\n enabled: (cfg as any).lcmEnabled === true,\n leafBatchSize: (cfg as any).lcmLeafBatchSize ?? 8,\n rollupFanIn: (cfg as any).lcmRollupFanIn ?? 4,\n freshTailTurns: (cfg as any).lcmFreshTailTurns ?? 16,\n maxDepth: (cfg as any).lcmMaxDepth ?? 5,\n deterministicMaxTokens: (cfg as any).lcmDeterministicMaxTokens ?? 512,\n archiveRetentionDays: (cfg as any).lcmArchiveRetentionDays ?? 90,\n recallBudgetShare: (cfg as any).lcmRecallBudgetShare ?? 0.15,\n };\n}\n\nexport class LcmEngine {\n private db: Database.Database | null = null;\n private archive: LcmArchive | null = null;\n private dag: LcmDag | null = null;\n private summarizer: LcmSummarizer | null = null;\n private observeQueue: LcmWorkQueue | null = null;\n private closed = false;\n private readonly config: LcmEngineConfig;\n private readonly memoryDir: string;\n private initPromise: Promise<void> | null = null;\n private readonly pendingObserveInitCounts = new Map<string, number>();\n private readonly pendingObserveInitWaiters = new Map<string, Array<() => void>>();\n private readonly pendingObserveInitIdleWaiters: Array<() => void> = [];\n\n constructor(\n pluginConfig: PluginConfig,\n private readonly summarizeFn: SummarizeFn,\n ) {\n this.config = extractLcmConfig(pluginConfig);\n this.memoryDir = pluginConfig.memoryDir;\n }\n\n get enabled(): boolean {\n return this.config.enabled;\n }\n\n /** Lazy init — open database on first use. */\n async ensureInitialized(): Promise<void> {\n if (this.closed) return;\n if (this.db) return;\n if (this.initPromise) {\n await this.initPromise;\n return;\n }\n this.initPromise = this.doInit().catch((err) => {\n // Reset so next call retries instead of caching the failure\n this.initPromise = null;\n throw err;\n });\n await this.initPromise;\n }\n\n private async doInit(): Promise<void> {\n await ensureLcmStateDir(this.memoryDir);\n const db = openLcmDatabase(this.memoryDir);\n const archive = new LcmArchive(db);\n const dag = new LcmDag(db);\n const summarizer = new LcmSummarizer(\n archive,\n dag,\n this.summarizeFn,\n {\n leafBatchSize: this.config.leafBatchSize,\n rollupFanIn: this.config.rollupFanIn,\n maxDepth: this.config.maxDepth,\n deterministicMaxTokens: this.config.deterministicMaxTokens,\n },\n );\n const observeQueue = new LcmWorkQueue({\n concurrency: 1,\n worker: async (sessionId, messages) => {\n await this.processObserveMessages(sessionId, messages);\n },\n hooks: {\n onJobStart: ({ sessionId, depth, inFlight, waitMs }) => {\n log.debug(\n `LCM observe queue start: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms`,\n );\n },\n onJobFinish: ({\n sessionId,\n depth,\n inFlight,\n waitMs,\n runMs,\n totalMs,\n error,\n }) => {\n if (error) {\n log.error(\n `LCM observe queue failure: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms, run=${runMs}ms, total=${totalMs}ms, error=${error}`,\n );\n return;\n }\n\n log.debug(\n `LCM observe queue finish: session=${sessionId}, depth=${depth}, inFlight=${inFlight}, wait=${waitMs}ms, run=${runMs}ms, total=${totalMs}ms`,\n );\n },\n },\n });\n\n if (this.closed) {\n db.close();\n return;\n }\n\n this.db = db;\n this.archive = archive;\n this.dag = dag;\n this.summarizer = summarizer;\n this.observeQueue = observeQueue;\n log.info(\"LCM engine initialized\");\n }\n\n /**\n * Enqueue messages from agent_end hook.\n * The queue worker performs the archive append and incremental summarization.\n */\n async observeMessages(\n sessionId: string,\n messages: Array<{ role: string; content: string }>,\n ): Promise<void> {\n this.enqueueObserveMessages(sessionId, messages);\n }\n\n /** Enqueue an observe job without waiting for worker completion. */\n enqueueObserveMessages(\n sessionId: string,\n messages: Array<{ role: string; content: string }>,\n ): void {\n if (!this.config.enabled || this.closed) return;\n if (messages.length === 0) return;\n\n this.reservePendingObserveInit(sessionId);\n\n void this.ensureInitialized()\n .then(() => {\n if (this.closed || !this.observeQueue) return;\n this.observeQueue.enqueue(sessionId, messages);\n log.debug(\n `LCM observe enqueued: session=${sessionId}, depth=${this.observeQueue.depth}, inFlight=${this.observeQueue.inFlightCount}`,\n );\n })\n .catch((err) => {\n if (this.closed) return;\n log.error(`LCM observe enqueue initialization error: ${err}`);\n })\n .finally(() => {\n this.releasePendingObserveInit(sessionId);\n });\n }\n\n private async processObserveMessages(\n sessionId: string,\n messages: LcmObserveMessage[],\n ): Promise<void> {\n if (this.closed) return;\n await this.ensureInitialized();\n if (this.closed || !this.archive || !this.summarizer) return;\n\n if (messages.length === 0) return;\n\n const currentMax = this.archive.getMaxTurnIndex(sessionId);\n const newMessages = messages.map((m, i) => ({\n turnIndex: currentMax + 1 + i,\n role: m.role,\n content: m.content,\n }));\n\n this.archive.appendMessages(sessionId, newMessages);\n\n // Trigger incremental summarization inside the worker, after append.\n try {\n await this.summarizer.summarizeIncremental(sessionId);\n } catch (err) {\n log.debug(`LCM incremental summarization error: ${err}`);\n }\n }\n\n get observeQueueDepth(): number {\n return this.observeQueue?.depth ?? 0;\n }\n\n get observeQueueInFlightCount(): number {\n return this.observeQueue?.inFlightCount ?? 0;\n }\n\n async waitForObserveQueueIdle(): Promise<void> {\n if (!this.config.enabled || this.closed) return;\n await this.ensureInitialized();\n if (this.closed) return;\n await this.waitForPendingObserveInitIdle();\n await this.observeQueue?.whenIdle();\n }\n\n async waitForSessionObserveIdle(sessionId: string): Promise<void> {\n if (!this.config.enabled || this.closed) return;\n await this.ensureInitialized();\n if (this.closed) return;\n await this.waitForPendingObserveInitIdle(sessionId);\n await this.observeQueue?.whenSessionIdle(sessionId);\n }\n\n private reservePendingObserveInit(sessionId: string): void {\n const count = this.pendingObserveInitCounts.get(sessionId) ?? 0;\n this.pendingObserveInitCounts.set(sessionId, count + 1);\n }\n\n private releasePendingObserveInit(sessionId: string): void {\n const count = this.pendingObserveInitCounts.get(sessionId);\n if (!count) return;\n\n if (count === 1) {\n this.pendingObserveInitCounts.delete(sessionId);\n const waiters = this.pendingObserveInitWaiters.get(sessionId) ?? [];\n this.pendingObserveInitWaiters.delete(sessionId);\n for (const resolve of waiters) resolve();\n if (this.pendingObserveInitCounts.size === 0) {\n const idleWaiters = this.pendingObserveInitIdleWaiters.splice(\n 0,\n this.pendingObserveInitIdleWaiters.length,\n );\n for (const resolve of idleWaiters) resolve();\n }\n return;\n }\n\n this.pendingObserveInitCounts.set(sessionId, count - 1);\n }\n\n private async waitForPendingObserveInitIdle(sessionId?: string): Promise<void> {\n if (sessionId) {\n if (!this.pendingObserveInitCounts.has(sessionId)) return;\n await new Promise<void>((resolve) => {\n const waiters = this.pendingObserveInitWaiters.get(sessionId) ?? [];\n waiters.push(resolve);\n this.pendingObserveInitWaiters.set(sessionId, waiters);\n });\n return;\n }\n\n if (this.pendingObserveInitCounts.size === 0) return;\n await new Promise<void>((resolve) => {\n this.pendingObserveInitIdleWaiters.push(resolve);\n });\n }\n\n /** Build the compressed history recall section for a session. */\n async assembleRecall(\n sessionId: string,\n budgetChars: number,\n ): Promise<string> {\n if (!this.config.enabled) return \"\";\n await this.ensureInitialized();\n\n const effectiveBudget = Math.ceil(\n budgetChars * this.config.recallBudgetShare,\n );\n if (effectiveBudget <= 0) return \"\";\n\n return assembleCompressedHistory(this.dag!, this.archive!, sessionId, {\n freshTailTurns: this.config.freshTailTurns,\n budgetChars: effectiveBudget,\n });\n }\n\n /** Flush pending summaries before compaction (called from before_compaction hook). */\n async preCompactionFlush(sessionId: string): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n try {\n await this.summarizer!.summarizeIncremental(sessionId);\n } catch (err) {\n log.debug(`LCM pre-compaction flush error: ${err}`);\n }\n }\n\n /** Record a compaction event with real token counts (called from after_compaction hook). */\n async recordCompaction(\n sessionId: string,\n tokensBefore: number,\n tokensAfter: number,\n ): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n const maxTurn = this.archive!.getMaxTurnIndex(sessionId);\n\n this.dag!.recordCompaction(sessionId, maxTurn, tokensBefore, tokensAfter);\n log.info(\n `LCM compaction recorded: session=${sessionId}, turn=${maxTurn}, tokens ${tokensBefore}→${tokensAfter}`,\n );\n }\n\n /** Verify archive coverage after compaction. */\n async verifyPostCompaction(sessionId: string): Promise<void> {\n if (!this.config.enabled) return;\n await this.ensureInitialized();\n\n const msgCount = this.archive!.getMessageCount(sessionId);\n const nodeCount = this.dag!.getNodeCount(sessionId);\n log.debug(\n `LCM post-compaction verify: session=${sessionId}, messages=${msgCount}, summaryNodes=${nodeCount}`,\n );\n }\n\n // ── MCP Tool implementations ──\n\n /** Search across all conversation history via FTS (snippet mode). */\n async searchContext(\n query: string,\n limit: number,\n sessionId?: string,\n ): Promise<\n Array<{\n turn_index: number;\n role: string;\n snippet: string;\n session_id: string;\n }>\n > {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n return this.archive!.search(query, limit, sessionId);\n }\n\n /** Search via FTS returning full message content (not snippets). */\n async searchContextFull(\n query: string,\n limit: number,\n sessionId?: string,\n ): Promise<\n Array<{\n id: number;\n turn_index: number;\n role: string;\n content: string;\n session_id: string;\n score: number;\n }>\n > {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n return this.archive!.searchWithContent(query, limit, sessionId);\n }\n\n /** Get a compressed summary of a turn range. */\n async describeContext(\n sessionId: string,\n fromTurn: number,\n toTurn: number,\n ): Promise<{ summary: string; turn_count: number; depth: number } | null> {\n if (!this.config.enabled) return null;\n await this.ensureInitialized();\n\n const nodes = this.dag!.getCoveringNodes(sessionId, fromTurn, toTurn);\n if (nodes.length === 0) {\n // No summary exists — build a description from raw messages\n const messages = this.archive!.getMessages(sessionId, fromTurn, toTurn);\n if (messages.length === 0) return null;\n const preview = messages\n .slice(0, 5)\n .map((m) => `[${m.role}] ${m.content.slice(0, 100)}`)\n .join(\"\\n\");\n return {\n summary: `No summary available for this range. Preview of ${messages.length} messages:\\n${preview}`,\n turn_count: messages.length,\n depth: -1,\n };\n }\n\n // Use the deepest covering node\n const best = nodes[0]; // Already sorted by depth DESC\n return {\n summary: best.summary_text,\n turn_count: best.msg_end - best.msg_start + 1,\n depth: best.depth,\n };\n }\n\n /** Retrieve raw messages for a turn range (lossless expansion). */\n async expandContext(\n sessionId: string,\n fromTurn: number,\n toTurn: number,\n maxTokens: number,\n ): Promise<Array<{ turn_index: number; role: string; content: string }>> {\n if (!this.config.enabled) return [];\n await this.ensureInitialized();\n\n const messages = this.archive!.getMessages(sessionId, fromTurn, toTurn);\n if (messages.length === 0) return [];\n\n // Enforce token budget — keep first and last, truncate middle\n const maxChars = maxTokens * 4;\n let totalChars = 0;\n for (const m of messages) totalChars += m.content.length;\n\n if (totalChars <= maxChars) {\n return messages.map((m) => ({\n turn_index: m.turn_index,\n role: m.role,\n content: m.content,\n }));\n }\n\n // Keep first and last messages, truncate from middle\n const result: Array<{ turn_index: number; role: string; content: string }> =\n [];\n let budget = maxChars;\n\n // Reserve space for the last message\n const lastMsg = messages[messages.length - 1];\n const lastMsgChars = Math.min(\n lastMsg.content.length,\n Math.floor(maxChars * 0.3),\n );\n budget -= lastMsgChars;\n\n // Add messages from the beginning\n for (let i = 0; i < messages.length - 1; i++) {\n if (budget <= 0) break;\n const m = messages[i];\n const truncated = m.content.slice(0, budget);\n result.push({\n turn_index: m.turn_index,\n role: m.role,\n content: truncated,\n });\n budget -= truncated.length;\n }\n\n // Always append the last message\n result.push({\n turn_index: lastMsg.turn_index,\n role: lastMsg.role,\n content: lastMsg.content.slice(0, lastMsgChars + Math.max(0, budget)),\n });\n\n return result;\n }\n\n /** Get statistics about the LCM archive. */\n async getStats(sessionId?: string): Promise<{\n totalMessages: number;\n totalSummaryNodes: number;\n maxDepth: number;\n }> {\n if (!this.config.enabled)\n return { totalMessages: 0, totalSummaryNodes: 0, maxDepth: -1 };\n await this.ensureInitialized();\n\n if (sessionId) {\n return {\n totalMessages: this.archive!.getMessageCount(sessionId),\n totalSummaryNodes: this.dag!.getNodeCount(sessionId),\n maxDepth: this.dag!.getMaxDepth(sessionId),\n };\n }\n\n return {\n totalMessages: this.archive!.getTotalMessageCount(),\n totalSummaryNodes: 0, // Would need a global count query\n maxDepth: -1,\n };\n }\n\n /** Prune old data beyond retention period. */\n async prune(): Promise<{ messagesPruned: number; nodesPruned: number }> {\n if (!this.config.enabled) return { messagesPruned: 0, nodesPruned: 0 };\n await this.ensureInitialized();\n\n const messagesPruned = this.archive!.pruneOldMessages(\n this.config.archiveRetentionDays,\n );\n const nodesPruned = this.dag!.pruneOldNodes(\n this.config.archiveRetentionDays,\n );\n return { messagesPruned, nodesPruned };\n }\n\n /** Close the database connection. */\n close(): void {\n this.closed = true;\n if (this.db) {\n this.db.close();\n }\n this.db = null;\n this.archive = null;\n this.dag = null;\n this.summarizer = null;\n this.observeQueue = null;\n this.initPromise = null;\n }\n}\n","import { Type } from \"@sinclair/typebox\";\nimport type { LcmEngine } from \"./engine.js\";\nimport { log } from \"../logger.js\";\n\ninterface ToolApi {\n registerTool(\n spec: {\n name: string;\n label: string;\n description: string;\n parameters: unknown;\n execute: (\n toolCallId: string,\n params: Record<string, unknown>,\n signal?: AbortSignal,\n ) => Promise<{ content: Array<{ type: string; text: string }>; details: undefined }>;\n },\n options: { name: string },\n ): void;\n}\n\nfunction toolResult(text: string) {\n return { content: [{ type: \"text\" as const, text }], details: undefined as undefined };\n}\n\nfunction registerAliasedTool(\n api: ToolApi,\n name: string,\n label: string,\n description: string,\n parameters: unknown,\n execute: (\n toolCallId: string,\n params: Record<string, unknown>,\n signal?: AbortSignal,\n ) => Promise<{ content: Array<{ type: string; text: string }>; details: undefined }>,\n): void {\n const aliases = [name];\n if (name.startsWith(\"engram_\")) {\n aliases.unshift(`remnic_${name.slice(\"engram_\".length)}`);\n }\n\n for (const alias of aliases) {\n api.registerTool(\n {\n name: alias,\n label,\n description,\n parameters,\n execute,\n },\n { name: alias },\n );\n }\n}\n\nexport function registerLcmTools(api: ToolApi, engine: LcmEngine): void {\n // engram.context_search — FTS search across conversation history\n registerAliasedTool(\n api,\n \"engram_context_search\",\n \"Search Conversation History\",\n \"Search all conversation history (including compacted regions) by keyword. Returns matching message snippets from the lossless context archive.\",\n Type.Object({\n query: Type.String({\n description: \"Search query — keywords or phrases\",\n }),\n limit: Type.Optional(\n Type.Number({\n description: \"Maximum results (default: 10)\",\n minimum: 1,\n maximum: 50,\n }),\n ),\n session_id: Type.Optional(\n Type.String({\n description: \"Limit search to a specific session\",\n }),\n ),\n }),\n async (_toolCallId, params) => {\n const query = params.query as string;\n const limit = (params.limit as number) ?? 10;\n const sessionId = params.session_id as string | undefined;\n\n const results = await engine.searchContext(query, limit, sessionId);\n\n if (results.length === 0) {\n return toolResult(`No results found for \"${query}\" in conversation history.`);\n }\n\n const formatted = results\n .map(\n (r, i) =>\n `${i + 1}. [${r.session_id}:${r.turn_index}] (${r.role})\\n ${r.snippet}`,\n )\n .join(\"\\n\\n\");\n\n return toolResult(\n `## Context Search: \"${query}\"\\n\\nFound ${results.length} result(s):\\n\\n${formatted}`,\n );\n },\n );\n\n // engram.context_describe — Get compressed summary of a turn range\n registerAliasedTool(\n api,\n \"engram_context_describe\",\n \"Describe Conversation Range\",\n \"Get a compressed summary of a conversation turn range. Uses the hierarchical summary DAG to provide the best available summary.\",\n Type.Object({\n session_id: Type.String({\n description: \"Session ID to describe\",\n }),\n from_turn: Type.Number({\n description: \"Start turn index\",\n minimum: 0,\n }),\n to_turn: Type.Number({\n description: \"End turn index\",\n minimum: 0,\n }),\n }),\n async (_toolCallId, params) => {\n const sessionId = params.session_id as string;\n const fromTurn = params.from_turn as number;\n const toTurn = params.to_turn as number;\n\n const result = await engine.describeContext(sessionId, fromTurn, toTurn);\n if (!result) {\n return toolResult(`No data found for session \"${sessionId}\" turns ${fromTurn}-${toTurn}.`);\n }\n\n return toolResult(\n `## Context Description (turns ${fromTurn}-${toTurn})\\n\\n` +\n `**Turns covered:** ${result.turn_count} | **Summary depth:** ${result.depth}\\n\\n` +\n result.summary,\n );\n },\n );\n\n // engram.context_expand — Retrieve raw messages (lossless)\n registerAliasedTool(\n api,\n \"engram_context_expand\",\n \"Expand Conversation Range\",\n \"Retrieve full conversation messages for a turn range (lossless). Use this to recover the exact content of messages that may have been compacted.\",\n Type.Object({\n session_id: Type.String({\n description: \"Session ID to expand\",\n }),\n from_turn: Type.Number({\n description: \"Start turn index\",\n minimum: 0,\n }),\n to_turn: Type.Number({\n description: \"End turn index\",\n minimum: 0,\n }),\n max_tokens: Type.Optional(\n Type.Number({\n description: \"Maximum tokens to return (default: 8000)\",\n minimum: 100,\n maximum: 32000,\n }),\n ),\n }),\n async (_toolCallId, params) => {\n const sessionId = params.session_id as string;\n const fromTurn = params.from_turn as number;\n const toTurn = params.to_turn as number;\n const maxTokens = (params.max_tokens as number) ?? 8000;\n\n const messages = await engine.expandContext(sessionId, fromTurn, toTurn, maxTokens);\n if (messages.length === 0) {\n return toolResult(\n `No messages found for session \"${sessionId}\" turns ${fromTurn}-${toTurn}.`,\n );\n }\n\n const formatted = messages\n .map((m) => `### Turn ${m.turn_index} (${m.role})\\n\\n${m.content}`)\n .join(\"\\n\\n---\\n\\n\");\n\n return toolResult(\n `## Context Expansion (turns ${fromTurn}-${toTurn})\\n\\n` +\n `**Messages:** ${messages.length}\\n\\n${formatted}`,\n );\n },\n );\n}\n","import type { TranscriptEntry } from \"../types.js\";\n\nexport interface ConversationChunk {\n id: string;\n sessionKey: string;\n startTs: string;\n endTs: string;\n text: string;\n}\n\nexport function chunkTranscriptEntries(\n sessionKey: string,\n entries: TranscriptEntry[],\n opts: { maxChars: number; maxTurns: number },\n): ConversationChunk[] {\n const maxChars = Math.max(500, opts.maxChars);\n const maxTurns = Math.max(5, opts.maxTurns);\n const sorted = [...entries].sort((a, b) => a.timestamp.localeCompare(b.timestamp));\n\n const out: ConversationChunk[] = [];\n let buf: TranscriptEntry[] = [];\n let bufChars = 0;\n\n function flush(): void {\n if (buf.length === 0) return;\n const startTs = buf[0]!.timestamp;\n const endTs = buf[buf.length - 1]!.timestamp;\n const text = buf.map((e) => `[${e.role}] ${e.content}`).join(\"\\n\\n\");\n const id = `${startTs}-${out.length}`.replace(/[:.]/g, \"-\");\n out.push({ id, sessionKey, startTs, endTs, text });\n buf = [];\n bufChars = 0;\n }\n\n for (const e of sorted) {\n const line = `[${e.role}] ${e.content}\\n\\n`;\n if (buf.length >= maxTurns || bufChars + line.length > maxChars) {\n flush();\n }\n buf.push(e);\n bufChars += line.length;\n }\n flush();\n\n return out;\n}\n\n","import { readdir, rm } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { log } from \"../logger.js\";\n\n/**\n * Best-effort retention cleanup for conversation chunk docs.\n *\n * Layout (written by indexer.ts):\n * <root>/<safeSessionKey>/<YYYY-MM-DD>/<chunkId>.md\n *\n * We prune day directories older than retentionDays, and remove empty session dirs.\n */\nexport async function cleanupConversationChunks(\n rootDir: string,\n retentionDays: number,\n): Promise<void> {\n if (!Number.isFinite(retentionDays) || retentionDays <= 0) return;\n\n const cutoffMs = Date.now() - retentionDays * 24 * 60 * 60 * 1000;\n\n try {\n const sessions = await readdir(rootDir, { withFileTypes: true });\n for (const s of sessions) {\n if (!s.isDirectory()) continue;\n const sessionDir = path.join(rootDir, s.name);\n const dayDirs = await readdir(sessionDir, { withFileTypes: true });\n\n for (const d of dayDirs) {\n if (!d.isDirectory()) continue;\n // Expect YYYY-MM-DD\n if (!/^\\d{4}-\\d{2}-\\d{2}$/.test(d.name)) continue;\n const dayMs = new Date(d.name + \"T00:00:00.000Z\").getTime();\n if (!Number.isFinite(dayMs)) continue;\n if (dayMs < cutoffMs) {\n await rm(path.join(sessionDir, d.name), { recursive: true, force: true });\n }\n }\n\n // Remove empty session dirs after pruning.\n try {\n const remaining = await readdir(sessionDir);\n if (remaining.length === 0) {\n await rm(sessionDir, { recursive: true, force: true });\n }\n } catch {\n // ignore\n }\n }\n } catch (err) {\n log.debug(`conversation chunk cleanup failed: ${err}`);\n }\n}\n\n","/**\n * GitContextResolver — pure module for detecting the git project + branch\n * a session is operating in.\n *\n * Introduced by issue #569 (coding-agent project/branch-scoped namespaces).\n *\n * This module is deliberately pure:\n * - no orchestrator references\n * - no config side-effects\n * - no namespace wiring\n *\n * Downstream slices (PR 2+ of #569) wire `resolveGitContext` into the\n * `NamespaceResolver` / `Orchestrator` so that memories are scoped to a\n * detected project / branch without leaking across repos.\n *\n * CLAUDE.md rule 17 (expand `~`): the `rootPath` returned here is always an\n * absolute, tilde-expanded path. Callers must not re-expand.\n *\n * CLAUDE.md rule 51 (reject invalid input): `cwd` must be an absolute path\n * and must exist. `resolveGitContext` returns `null` — rather than throwing —\n * when the directory is not inside a git worktree, because being outside a\n * repo is a normal runtime state (e.g. agent opened in a scratch dir).\n */\nimport path from \"node:path\";\n\nimport { expandTildePath } from \"../utils/path.js\";\nimport { launchProcessSync } from \"../runtime/child-process.js\";\n\n// Re-export so existing callers / tests that imported `expandTildePath` from\n// this module keep working. CLAUDE.md #17 requires consistent `~` expansion\n// across every user-facing path input; the canonical implementation now\n// lives in `utils/path.ts`.\nexport { expandTildePath };\n\n// ──────────────────────────────────────────────────────────────────────────\n// Public types\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface GitContext {\n /**\n * Stable identifier for the project. Derived from `git remote get-url origin`\n * when an origin remote is configured, otherwise from the repo root path.\n *\n * Formatted as `origin:<hex>` or `root:<hex>` so that the source is visible\n * to operators (see `remnic doctor`, issue #569 acceptance criteria).\n */\n projectId: string;\n /**\n * Current branch, e.g. `main`, `feat/foo`. `null` only in detached-HEAD\n * state (e.g. rebase in progress). Callers should treat `null` as \"no\n * branch-scope overlay applies\" without erroring.\n */\n branch: string | null;\n /**\n * Absolute path to the repository root (the directory containing `.git`).\n * Tilde-expanded per CLAUDE.md #17.\n */\n rootPath: string;\n /**\n * Best-effort default branch (usually `main` or `master`). Derived from the\n * `refs/remotes/origin/HEAD` symbolic ref. `null` when not available (e.g.\n * fresh clone without a default branch symref, or no origin remote).\n */\n defaultBranch: string | null;\n}\n\n/**\n * Injectable git-invocation surface. Only the commands `resolveGitContext`\n * actually needs are exposed. Tests inject a mock implementation to avoid\n * spawning a real git process.\n */\nexport interface GitInvoker {\n /**\n * Run `git <args>` with `cwd` as the working directory. Must return\n * `{ stdout, exitCode }` with `stdout` trimmed by the caller as needed.\n * Implementations should NOT throw for non-zero exit codes — they should\n * return the exit code so the resolver can decide how to recover.\n */\n (cwd: string, args: string[]): { stdout: string; exitCode: number };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Default git invoker — spawns real `git` via the shared child-process helper\n// ──────────────────────────────────────────────────────────────────────────\n\nconst DEFAULT_GIT_TIMEOUT_MS = 2_000;\n\nexport function defaultGitInvoker(): GitInvoker {\n return (cwd: string, args: string[]) => {\n const result = launchProcessSync(\"git\", args, {\n cwd,\n encoding: \"utf-8\",\n timeout: DEFAULT_GIT_TIMEOUT_MS,\n shell: false,\n });\n if (result.error) {\n // Spawn failure (git not on PATH, timeout, etc.). Surface as non-zero.\n return { stdout: \"\", exitCode: 127 };\n }\n return {\n stdout: typeof result.stdout === \"string\" ? result.stdout : \"\",\n exitCode: typeof result.status === \"number\" ? result.status : 1,\n };\n };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Stable hashing\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Non-cryptographic stable hash. Used only to derive a deterministic\n * `projectId` from either the origin URL or the root path. The hash does not\n * need to be collision-resistant against adversarial input — it is purely a\n * namespace discriminator.\n *\n * Uses FNV-1a 32-bit so we don't pull in `node:crypto` for a simple bucket\n * key. Output is lowercase hex, zero-padded to 8 characters.\n */\nexport function stableHash(input: string): string {\n let hash = 0x811c9dc5;\n for (let i = 0; i < input.length; i++) {\n hash ^= input.charCodeAt(i);\n hash = Math.imul(hash, 0x01000193) >>> 0;\n }\n return hash.toString(16).padStart(8, \"0\");\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Origin URL normalization\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a git remote URL so that equivalent SSH / HTTPS forms of the\n * same repo produce the same `projectId`. Handles:\n * - `git@github.com:foo/bar.git` → `github.com/foo/bar`\n * - `https://github.com/foo/bar` → `github.com/foo/bar`\n * - `https://github.com/foo/bar.git` → `github.com/foo/bar`\n * - `ssh://git@github.com/foo/bar` → `github.com/foo/bar`\n * - `ssh://git@github.com:2222/foo/bar` → `github.com/foo/bar` (port stripped)\n *\n * Case-insensitive (remote hostnames and most repo paths on major forges are\n * case-insensitive in practice).\n */\nexport function normalizeOriginUrl(rawUrl: string): string {\n let url = rawUrl.trim();\n if (!url) return \"\";\n\n // Strip trailing `.git` case-insensitively — the whole result is\n // lowercased at the end, so `.GIT` / `.Git` must be treated the same as\n // `.git`. Previously the `.endsWith(\".git\")` check let `.GIT` leak\n // through and appear in the output.\n if (/\\.git$/i.test(url)) url = url.slice(0, -4);\n\n // Windows drive-letter local path (e.g. `C:/repos/app`): detect here\n // so the scp matcher below can accept single-character SSH host aliases\n // (`h:foo/bar` from `.ssh/config`). A drive letter is exactly one ASCII\n // letter followed by `:/` or `:\\`; SSH aliases never have a slash\n // immediately after the colon.\n if (/^[A-Za-z]:[\\\\/]/.test(url)) {\n return url.toLowerCase();\n }\n\n // Protocol-prefixed: ssh://, https://, http://, git://, file://\n // Must be tried FIRST so that scp-style detection below doesn't\n // incorrectly swallow an ssh:// URL that happens to contain `:port/`.\n //\n // Matches:\n // 1: host — bracketed IPv6 `[2001:db8::1]`, plain host with no `:` / `/`,\n // OR empty (for `file:///path` which has no host component).\n // 2: port (optional) — preserved in the output so two repos on the same\n // host under different ports get distinct project namespaces.\n // Losing the port risked false-coalescing separate repos on custom\n // SSH mesh setups.\n // 3: path (optional)\n const protoMatch =\n /^[a-z][a-z0-9+.-]*:\\/\\/(?:[^@/]+@)?(\\[[^\\]]+\\]|[^/:]*)(?::(\\d+))?(\\/.*)?$/i.exec(url);\n if (protoMatch) {\n let host = protoMatch[1] ?? \"\";\n // Detect IPv6 via the bracketed input form BEFORE stripping brackets,\n // so that when we later re-attach a port we can preserve the\n // `[host]:port` boundary. Without the brackets, `host:2222` is\n // ambiguous with a longer bare IPv6 address like `2001:db8::1:2222`.\n const wasBracketed =\n host.startsWith(\"[\") && host.endsWith(\"]\");\n if (wasBracketed) host = host.slice(1, -1);\n const port = protoMatch[2];\n const repoPath = (protoMatch[3] ?? \"\").replace(/^\\/+/, \"\");\n const hostPort = port\n ? wasBracketed\n ? `[${host}]:${port}`\n : `${host}:${port}`\n : host;\n // For protocols without a host component (file:///path), fall back to\n // a stable prefix so distinct local paths don't collapse to \"/path\".\n const prefix = hostPort.length > 0 ? hostPort : \"localhost\";\n return `${prefix}/${repoPath}`.toLowerCase();\n }\n\n // scp-like syntax: [user@]host:path. Protocol-prefixed URLs (`scheme://`)\n // are handled above, so the scp branch below guards against them: a\n // matched `host` of `scheme` followed by a path starting with `//` is\n // a protocol URL that fell through and must NOT be parsed here.\n // `user@` is optional — git also accepts userless scp forms like\n // `host:org/repo`. Valid scp paths may start with digits (e.g.\n // `git@host:123/repo.git`), so no numeric guard is needed: port-bearing\n // URLs have the `://` prefix and match the protocol branch above before\n // reaching here.\n //\n // Windows drive letters were filtered above, so single-character SSH\n // host aliases (`h:foo/bar`) are accepted here.\n //\n // Bracketed IPv6 (`[2001:db8::1]`) is supported: the host alternative\n // matches the bracketed literal up to `]` without splitting on internal\n // `:`. Brackets are stripped in the normalised form so the scp and\n // `ssh://` forms of the same IPv6 remote produce identical projectIds.\n const scpMatch =\n /^(?:([^@\\s/]+)@)?(\\[[^\\]]+\\]|[^:@\\s/]+):(.+)$/.exec(url);\n if (scpMatch) {\n let host = scpMatch[2] ?? \"\";\n if (host.startsWith(\"[\") && host.endsWith(\"]\")) host = host.slice(1, -1);\n const repoPath = scpMatch[3] ?? \"\";\n // Reject protocol-like leftovers (e.g. `file:///path` where the scp\n // regex greedily matched `file` as host and `///path` as path).\n if (repoPath.startsWith(\"//\")) {\n return url.toLowerCase();\n }\n return `${host}/${repoPath.replace(/^\\/+/, \"\")}`.toLowerCase();\n }\n\n // Fallback: use raw lowercased\n return url.toLowerCase();\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Resolver\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface ResolveGitContextOptions {\n /** Inject a git invoker (tests). Defaults to spawning real `git`. */\n invoker?: GitInvoker;\n}\n\n/**\n * Detect the git project + branch for `cwd`.\n *\n * Returns `null` when:\n * - `cwd` is not an absolute path (invalid input, CLAUDE.md #51)\n * - `cwd` is not inside a git worktree\n * - `git` is not available on PATH\n *\n * Never throws.\n */\nexport async function resolveGitContext(\n cwd: string,\n options: ResolveGitContextOptions = {},\n): Promise<GitContext | null> {\n // Wrap the whole body so the documented \"Never throws\" contract is\n // enforced. Possible throw sites include:\n // - `expandTildePath` → `resolveHomeDir()` → `os.homedir()` when HOME\n // is unset (e.g. minimal containers)\n // - a custom `options.invoker` that raises instead of returning a\n // non-zero exitCode\n // - any future helper added to this chain\n // All of those map to \"not in a repo\" / `null`.\n try {\n // Validate input: must be a non-empty string.\n if (typeof cwd !== \"string\" || cwd.length === 0) return null;\n\n // Expand `~` per CLAUDE.md #17, then require absolute path.\n const expanded = expandTildePath(cwd);\n if (!path.isAbsolute(expanded)) return null;\n\n const invoker = options.invoker ?? defaultGitInvoker();\n\n // 1. Locate the repo root.\n const topLevel = invoker(expanded, [\"rev-parse\", \"--show-toplevel\"]);\n if (topLevel.exitCode !== 0) return null;\n const rootPath = topLevel.stdout.trim();\n if (!rootPath) return null;\n\n // 2. Current branch. `--abbrev-ref HEAD` returns `HEAD` in detached\n // state, which we normalize to `null`. On a fresh `git init` the\n // HEAD ref is unborn and `--abbrev-ref HEAD` fails, but\n // `symbolic-ref HEAD` still returns the target branch. Fall back\n // so newly-initialized repos get a sensible branch name.\n const branchResult = invoker(rootPath, [\"rev-parse\", \"--abbrev-ref\", \"HEAD\"]);\n let branch: string | null = null;\n if (branchResult.exitCode === 0) {\n const raw = branchResult.stdout.trim();\n branch = raw && raw !== \"HEAD\" ? raw : null;\n } else {\n const unbornRef = invoker(rootPath, [\"symbolic-ref\", \"--quiet\", \"HEAD\"]);\n if (unbornRef.exitCode === 0) {\n const raw = unbornRef.stdout.trim();\n const prefix = \"refs/heads/\";\n if (raw.startsWith(prefix)) {\n const candidate = raw.slice(prefix.length);\n if (candidate) branch = candidate;\n }\n }\n }\n\n // 3. Origin URL — optional. Used to derive a stable `projectId`.\n const originResult = invoker(rootPath, [\"remote\", \"get-url\", \"origin\"]);\n let projectId: string;\n if (originResult.exitCode === 0) {\n const normalized = normalizeOriginUrl(originResult.stdout);\n projectId = normalized ? `origin:${stableHash(normalized)}` : `root:${stableHash(rootPath)}`;\n } else {\n projectId = `root:${stableHash(rootPath)}`;\n }\n\n // 4. Default branch — best effort.\n const headRef = invoker(rootPath, [\"symbolic-ref\", \"--quiet\", \"refs/remotes/origin/HEAD\"]);\n let defaultBranch: string | null = null;\n if (headRef.exitCode === 0) {\n const raw = headRef.stdout.trim();\n const prefix = \"refs/remotes/origin/\";\n if (raw.startsWith(prefix)) {\n const candidate = raw.slice(prefix.length);\n if (candidate) defaultBranch = candidate;\n }\n }\n\n return {\n projectId,\n branch,\n rootPath,\n defaultBranch,\n };\n } catch {\n // Never throws — any unexpected error falls back to \"not in a repo\".\n return null;\n }\n}\n","/**\n * Coding-agent namespace overlay (issue #569 PR 2 + PR 3).\n *\n * Given a `CodingContext` (from `resolveGitContext`) and a `CodingModeConfig`,\n * returns the namespace that recall + write paths should use — or `null` when\n * no overlay should apply (coding mode disabled, no context supplied, or\n * feature flags off).\n *\n * PR 2 ships the project overlay. PR 3 will add the branch overlay; the\n * function here already handles both flags so the schema / types / plumbing\n * don't have to change a second time when branch-scope lands.\n *\n * Pure function — no orchestrator, no config side-effects. Callers keep rule\n * 42 (read + write through same namespace layer) by consulting the same\n * function on both paths.\n */\n\nimport type { CodingContext, CodingModeConfig } from \"../types.js\";\nimport { stableHash } from \"./git-context.js\";\n\nexport interface CodingNamespaceOverlay {\n /**\n * Effective namespace to use for this session's memory operations. When\n * `branchScope` is on, takes the form `project:<id>/branch:<b>`; otherwise\n * `project:<id>`.\n */\n namespace: string;\n /**\n * Read fallbacks — additional namespaces a caller should include in recall\n * so that, for example, a branch-scoped session still sees project-level\n * memories that were written before the branch scope was enabled.\n *\n * Writes MUST go to `namespace` only; these are read-side only.\n *\n * Introduced to carry PR 3's branch→project fallback; PR 2 returns an empty\n * array here.\n */\n readFallbacks: string[];\n /**\n * `\"project\"` when only project scope applies, `\"branch\"` when branch scope\n * is also layered on. Used for diagnostics (`remnic doctor`) and logging.\n */\n scope: \"project\" | \"branch\";\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Sanitization\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Normalize a projectId / branch fragment so the resulting namespace passes\n * the router's `isSafeRouteNamespace` check (`[A-Za-z0-9._-]{1,64}`).\n *\n * Namespaces are used as filesystem directory names and must not contain\n * path separators (`/`, `\\`) or colons — so both `:` and `/` collapse to `-`.\n * The project-id format `origin:<8hex>` and branch names like `feat/x` both\n * flow through this helper before hitting the storage layer.\n *\n * NOT a security boundary — projectIds come from `resolveGitContext` (known\n * hex), and branch names come from local git. This defends against corrupt\n * input only.\n */\n/**\n * Single-pass sanitization — each input character is visited exactly once.\n * Rewriting as an explicit loop (instead of chained `replace()` calls with\n * greedy quantifiers) closes the polynomial-backtracking surface that\n * CodeQL flagged on patterns like `-+` and `^-+|-+$`.\n */\nfunction sanitizeFragment(input: string): string {\n if (typeof input !== \"string\") return \"\";\n const trimmed = input.trim().toLowerCase();\n let out = \"\";\n let prevIsDash = true; // suppress leading dashes\n for (let i = 0; i < trimmed.length; i += 1) {\n const c = trimmed[i]!;\n const cc = trimmed.charCodeAt(i);\n const isSafe =\n (cc >= 48 && cc <= 57) /* 0-9 */ ||\n (cc >= 97 && cc <= 122) /* a-z */ ||\n cc === 46 /* . */ ||\n cc === 95 /* _ */;\n if (isSafe) {\n out += c;\n prevIsDash = false;\n } else if (!prevIsDash) {\n out += \"-\";\n prevIsDash = true;\n }\n }\n // Strip a single trailing dash introduced by the final run of unsafe chars.\n if (out.endsWith(\"-\")) out = out.slice(0, -1);\n return out;\n}\n\n/**\n * Cap to the router's per-namespace upper bound.\n *\n * Raw truncation alone would collapse distinct long inputs that differ near\n * the end (e.g. two `feat/...` branches with different suffixes) into the\n * same namespace — silently mixing recall/write state across branches or\n * projects. When truncation is needed, we append a short deterministic\n * hash suffix (`-<8hex>`) derived from the FULL pre-truncated value so\n * collisions only happen under true hash collisions, not simple prefix\n * overlap.\n *\n * The tail is trimmed to leave room for the separator and 8-char hash and\n * any trailing `-` introduced by the slice is stripped so the final\n * character before `-<hash>` is always alphanumeric or `.`/`_`.\n */\nconst MAX_NAMESPACE_LEN = 64;\nconst HASH_SUFFIX_LEN = 9; // \"-\" + 8 hex chars\n\nfunction capLength(value: string): string {\n if (value.length <= MAX_NAMESPACE_LEN) return value;\n // Reuse the FNV-1a 32-bit hash from git-context — one canonical\n // implementation, one set of edge-case fixes. Uses Math.imul for\n // correct 32-bit wrap-around, which plain `*` would not guarantee\n // for the largest intermediate products.\n const hash = stableHash(value);\n // Trim trailing '-' with a linear, non-backtracking loop. A regex\n // like `-+$` is linear too, but an explicit loop keeps CodeQL happy\n // about polynomial backtracking warnings when several `\\-+` patterns\n // appear in the same module.\n let end = MAX_NAMESPACE_LEN - HASH_SUFFIX_LEN;\n while (end > 0 && value.charCodeAt(end - 1) === 45 /* '-' */) end -= 1;\n return `${value.slice(0, end)}-${hash}`;\n}\n\n/**\n * Produce the project-scope namespace name. Exported for tests and for\n * `remnic doctor` to render. Guaranteed to satisfy `isSafeRouteNamespace`:\n * no `/`, no `:`, lowercase only, length-capped to 64 chars.\n */\nexport function projectNamespaceName(projectId: string): string {\n const frag = sanitizeFragment(projectId);\n return capLength(`project-${frag || \"unknown\"}`);\n}\n\n/**\n * Preserve case when sanitizing a principal-derived base namespace. The\n * router's `isSafeRouteNamespace` check accepts `[A-Za-z0-9._-]{1,64}`, so\n * upper-case characters in the principal name are safe and MUST be kept to\n * avoid colliding two otherwise-distinct principals (e.g. `Alice` vs\n * `alice`) into the same combined namespace.\n *\n * Otherwise identical to `sanitizeFragment`: single-pass, linear, no\n * polynomial-backtracking quantifiers, unsafe chars collapse to `-` with\n * leading/trailing dashes suppressed.\n */\nfunction sanitizeBaseFragment(input: string): string {\n if (typeof input !== \"string\") return \"\";\n const trimmed = input.trim();\n let out = \"\";\n let prevIsDash = true;\n for (let i = 0; i < trimmed.length; i += 1) {\n const c = trimmed[i]!;\n const cc = trimmed.charCodeAt(i);\n const isSafe =\n (cc >= 48 && cc <= 57) /* 0-9 */ ||\n (cc >= 65 && cc <= 90) /* A-Z */ ||\n (cc >= 97 && cc <= 122) /* a-z */ ||\n cc === 46 /* . */ ||\n cc === 95 /* _ */;\n if (isSafe) {\n out += c;\n prevIsDash = false;\n } else if (!prevIsDash) {\n out += \"-\";\n prevIsDash = true;\n }\n }\n if (out.endsWith(\"-\")) out = out.slice(0, -1);\n return out;\n}\n\n/**\n * Combine a principal-derived base namespace (e.g. `default`, `alice`) with a\n * coding-agent overlay namespace (e.g. `project-origin-abcd1234`). The result\n * is a single safe-route token that preserves principal isolation (CLAUDE.md\n * rule 42: read + write must resolve through the same namespace layer — and\n * here, through the same principal-scoped prefix) while layering project or\n * project/branch scope on top.\n *\n * Multiple principals working in the same repo thus get distinct namespaces:\n *\n * alice + project-origin-ab12 → alice-project-origin-ab12\n * bob + project-origin-ab12 → bob-project-origin-ab12\n * Alice + project-origin-ab12 → Alice-project-origin-ab12 (distinct)\n *\n * The base fragment preserves case so `Alice` and `alice` remain distinct;\n * the overlay fragment is still lowercase-sanitized because it derives from\n * deterministic, pre-lowercased git hashes.\n *\n * Output is re-capped through `capLength` so a very long base + overlay\n * combination still fits inside `isSafeRouteNamespace` (≤ 64 chars). The\n * deterministic hash suffix on truncation keeps distinct inputs distinct.\n */\nexport function combineNamespaces(base: string, overlay: string): string {\n const baseFrag = sanitizeBaseFragment(base);\n const overlayFrag = sanitizeFragment(overlay);\n if (!baseFrag) return capLength(overlayFrag || \"unknown\");\n if (!overlayFrag) return capLength(baseFrag);\n return capLength(`${baseFrag}-${overlayFrag}`);\n}\n\n/**\n * Produce the branch-scope namespace name. Format:\n * `project-<id>-branch-<name>[-<hash>]`. Uses `-` as the structural separator\n * rather than `/` or `:` so the result is a single safe route-namespace\n * token that can be used directly as a filesystem directory.\n *\n * Two failure modes must not collapse distinct branches to one namespace:\n *\n * 1. Sanitization is lossy (`feat/x` and `feat-x` both sanitize to\n * `feat-x`; `Feature` and `feature` both sanitize to `feature`). When\n * sanitization rewrote any character, we append a short hash of the\n * RAW branch so distinct inputs stay distinct.\n * 2. Truncation is applied when the total exceeds 64 chars. In that\n * mode `capLength` appends its own hash of the full pre-truncated\n * value.\n *\n * Long branches that also sanitize may receive both kinds of hashes — that\n * is acceptable: the router only requires the result be unique and\n * deterministic, and the two hashes derive from different domains so they\n * don't conflict.\n */\nexport function branchNamespaceName(projectId: string, branch: string): string {\n const projectFrag = sanitizeFragment(projectId);\n const trimmedBranch = branch.trim();\n const branchFrag = sanitizeFragment(trimmedBranch);\n // Lossy-sanitization disambiguator: append hash of the raw (trimmed)\n // branch when sanitization actually changed the string. Preserves\n // distinctness across `feat/x` vs `feat-x` and `Feature` vs `feature`.\n // The comparison uses the raw trimmed value (NOT `.toLowerCase()`) so\n // case-only variants are treated as lossy and receive their own hash.\n // Empty / already-safe-lowercase inputs get no hash so the common case\n // stays readable.\n const disambig = trimmedBranch.length > 0 && branchFrag !== trimmedBranch;\n const base = `project-${projectFrag || \"unknown\"}-branch-${branchFrag || \"unknown\"}`;\n const suffixed = disambig ? `${base}-${stableHash(trimmedBranch)}` : base;\n return capLength(suffixed);\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Overlay resolver\n// ──────────────────────────────────────────────────────────────────────────\n\n/**\n * Compute the namespace overlay for a session.\n *\n * Returns `null` when no overlay applies — callers should then use their\n * existing `defaultNamespaceForPrincipal(...)` result unchanged. This keeps\n * CLAUDE.md #30 (escape hatch): setting `codingMode.projectScope: false`\n * exactly restores pre-#569 behaviour at every call site.\n */\nexport function resolveCodingNamespaceOverlay(\n codingContext: CodingContext | null | undefined,\n config: Pick<CodingModeConfig, \"projectScope\" | \"branchScope\">,\n): CodingNamespaceOverlay | null {\n // No context supplied (session isn't in a git repo, or connector didn't\n // attach one) → no overlay.\n if (!codingContext) return null;\n\n // Project scope disabled → no overlay at all. Branch scope depends on\n // project scope being on; there is no branch-only mode.\n if (!config.projectScope) return null;\n\n // Require a non-empty projectId — defensive.\n const projectId = typeof codingContext.projectId === \"string\" ? codingContext.projectId.trim() : \"\";\n if (!projectId) return null;\n\n const projectNs = projectNamespaceName(projectId);\n\n // Branch-scope layering (PR 3):\n // - only when config.branchScope is explicitly true\n // - only when we actually have a branch (null in detached HEAD)\n // - project namespace becomes a read fallback so project-level memories\n // remain visible from any branch (deliberate asymmetry — branch writes\n // don't leak up, but project reads leak down).\n if (config.branchScope && typeof codingContext.branch === \"string\" && codingContext.branch.length > 0) {\n const branchNs = branchNamespaceName(projectId, codingContext.branch);\n return {\n namespace: branchNs,\n readFallbacks: [projectNs],\n scope: \"branch\",\n };\n }\n\n return {\n namespace: projectNs,\n readFallbacks: [],\n scope: \"project\",\n };\n}\n\n// ──────────────────────────────────────────────────────────────────────────\n// Diagnostics (issue #569 PR 3 + PR 8)\n// ──────────────────────────────────────────────────────────────────────────\n\nexport interface CodingScopeDescription {\n /** \"none\" when no overlay is active; otherwise the resolved scope level. */\n scope: \"none\" | \"project\" | \"branch\";\n /** Project id (raw, not sanitized) when a context is attached. */\n projectId: string | null;\n /** Branch name (raw, not sanitized) when available. */\n branch: string | null;\n /** Effective namespace writes route to. `null` when no overlay applies. */\n effectiveNamespace: string | null;\n /** Read fallbacks included in recall (non-empty only when branch-scope is on). */\n readFallbacks: string[];\n /**\n * Why no overlay applies, when `scope === \"none\"`. One of:\n * - `\"no-context\"` — connector didn't attach a CodingContext\n * - `\"disabled\"` — codingMode.projectScope is false\n * - `\"empty-project\"` — codingContext.projectId was empty/whitespace\n */\n disabledReason: \"no-context\" | \"disabled\" | \"empty-project\" | null;\n}\n\n/**\n * Human-readable description of the coding-agent scope that currently applies\n * for a session. Consumed by `remnic doctor` (PR 8) and by logs to surface\n * why recall routes where it does.\n *\n * Pure — callers pass the coding context + config they already have.\n */\nexport function describeCodingScope(\n codingContext: CodingContext | null | undefined,\n config: Pick<CodingModeConfig, \"projectScope\" | \"branchScope\">,\n): CodingScopeDescription {\n const projectId = codingContext?.projectId ?? null;\n const branch = codingContext?.branch ?? null;\n\n if (!codingContext) {\n return {\n scope: \"none\",\n projectId: null,\n branch: null,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"no-context\",\n };\n }\n if (!config.projectScope) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"disabled\",\n };\n }\n const trimmedId = typeof projectId === \"string\" ? projectId.trim() : \"\";\n if (!trimmedId) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"empty-project\",\n };\n }\n\n const overlay = resolveCodingNamespaceOverlay(codingContext, config);\n // Unreachable in practice given the guards above, but keep the return\n // shape consistent if the resolver grows new null branches later.\n if (!overlay) {\n return {\n scope: \"none\",\n projectId,\n branch,\n effectiveNamespace: null,\n readFallbacks: [],\n disabledReason: \"disabled\",\n };\n }\n return {\n scope: overlay.scope,\n projectId,\n branch,\n effectiveNamespace: overlay.namespace,\n readFallbacks: overlay.readFallbacks,\n disabledReason: null,\n };\n}\n"],"mappings":"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","names":["path","createHash","existsSync","mkdir","readdir","readFile","stat","unlink","writeFile","legacyEntries","rewritten","mkdir","readFile","rm","stat","writeFile","path","lockPath","readFile","mkdir","writeFile","path","path","readFile","mkdir","writeFile","path","mkdir","path","mkdir","sessionId","readdir","rm","path","readdir","path","rm","path","path","createHash","path","buildCompressionGuidelinesMarkdown","result","readdir","stat","unlink","existsSync","readFile","writeFile","mkdir","FallbackLlmClient","capped","profile","outcome","throwIfAborted","options","memoryKind"]}
|