@remnic/core 9.7.15 → 9.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.d.ts +13 -6
- package/dist/access-admin-ops-surface.js +85 -71
- package/dist/access-audit.js +2 -2
- package/dist/access-boundary.d.ts +35 -17
- package/dist/access-boundary.js +86 -74
- package/dist/access-citation.d.ts +28 -0
- package/dist/access-citation.js +9 -0
- package/dist/access-cli.js +194 -178
- package/dist/access-cli.js.map +1 -1
- package/dist/access-errors.d.ts +16 -1
- package/dist/access-errors.js +7 -3
- package/dist/access-http.d.ts +25 -19
- package/dist/access-http.js +100 -87
- package/dist/access-identity-continuity-surface.d.ts +13 -8
- package/dist/access-identity-continuity-surface.js +85 -71
- package/dist/access-lcm-surface.d.ts +16 -9
- package/dist/access-lcm-surface.js +85 -71
- package/dist/access-mcp.d.ts +23 -16
- package/dist/access-mcp.js +96 -84
- package/dist/access-memory-search-fanout.d.ts +93 -0
- package/dist/access-memory-search-fanout.js +18 -0
- package/dist/access-observe-write-surface.d.ts +26 -8
- package/dist/access-observe-write-surface.js +85 -71
- package/dist/access-operations-batch.js +92 -80
- package/dist/access-operations.d.ts +29 -22
- package/dist/access-operations.js +94 -82
- package/dist/access-recall-concurrency.d.ts +250 -0
- package/dist/access-recall-concurrency.js +157 -0
- package/dist/access-recall-response.d.ts +130 -0
- package/dist/access-recall-response.js +147 -0
- package/dist/access-recall-surface.d.ts +15 -7
- package/dist/access-recall-surface.js +85 -71
- package/dist/access-schema.d.ts +98 -98
- package/dist/access-schema.js +8 -6
- package/dist/{access-service-DpcYZ9Nl.d.ts → access-service-DEL4qCrc.d.ts} +25 -32
- package/dist/access-service.d.ts +13 -6
- package/dist/access-service.js +89 -72
- package/dist/access-surface-catalog.d.ts +23 -16
- package/dist/access-surface-catalog.js +1 -0
- package/dist/access-surface-catalog.js.map +1 -1
- package/dist/access-token-capabilities.d.ts +2 -1
- package/dist/access-token-capabilities.js +4 -2
- package/dist/action-confidence.d.ts +3 -1
- package/dist/active-memory-bridge.d.ts +3 -1
- package/dist/active-memory-bridge.js +4 -4
- package/dist/active-recall.d.ts +4 -1
- package/dist/active-recall.js +23 -13
- package/dist/active-recall.js.map +1 -1
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/{auto-sync-AAMTVZMK.js → auto-sync-UZG3XQZ5.js} +14 -8
- package/dist/{auto-sync-AAMTVZMK.js.map → auto-sync-UZG3XQZ5.js.map} +1 -1
- package/dist/behavior-learner.d.ts +3 -1
- package/dist/behavior-signals.d.ts +3 -1
- package/dist/bootstrap.d.ts +12 -7
- package/dist/bootstrap.js +2 -2
- package/dist/bounded-jsonl-state.d.ts +54 -0
- package/dist/bounded-jsonl-state.js +10 -0
- package/dist/boxes.js +2 -2
- package/dist/briefing.d.ts +5 -2
- package/dist/briefing.js +34 -24
- package/dist/buffer-surprise-report.d.ts +3 -1
- package/dist/buffer.d.ts +60 -2
- package/dist/buffer.js +3 -3
- package/dist/bulk-import/index.d.ts +5 -3
- package/dist/calibration.d.ts +3 -1
- package/dist/calibration.js +6 -6
- package/dist/capabilities.d.ts +7 -7
- package/dist/capabilities.js +1 -1
- package/dist/{capsule-crypto-CZJSLEFG.js → capsule-crypto-YO5QJ6L3.js} +3 -3
- package/dist/capsule-crypto-YO5QJ6L3.js.map +1 -0
- package/dist/{catalog-C9444P10.d.ts → catalog-BWqHb5HT.d.ts} +1 -1
- package/dist/causal-behavior.d.ts +3 -1
- package/dist/causal-behavior.js +6 -6
- package/dist/causal-chain.js +4 -4
- package/dist/causal-consolidation.d.ts +3 -1
- package/dist/causal-consolidation.js +43 -34
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/causal-retrieval.js +6 -6
- package/dist/causal-trajectory-graph.d.ts +3 -1
- package/dist/causal-trajectory-graph.js +1 -1
- package/dist/causal-trajectory.js +1 -1
- package/dist/{chunk-A3GOMRJG.js → chunk-23L3IXFD.js} +2 -2
- package/dist/chunk-2CGLBUW3.js +15 -0
- package/dist/chunk-2CGLBUW3.js.map +1 -0
- package/dist/{chunk-MRHFJV44.js → chunk-2DQ2XREU.js} +2 -2
- package/dist/{chunk-QKQYXZVS.js → chunk-2EJOEICD.js} +1819 -1481
- package/dist/chunk-2EJOEICD.js.map +1 -0
- package/dist/{chunk-L2B3EE7B.js → chunk-2QMKMVHH.js} +2 -2
- package/dist/{chunk-VJVNLNDQ.js → chunk-2UFO7X4Q.js} +7 -7
- package/dist/{chunk-2MR3MFQB.js → chunk-2VEOKUPP.js} +3 -3
- package/dist/chunk-2Z24E5W2.js +22 -0
- package/dist/chunk-2Z24E5W2.js.map +1 -0
- package/dist/{chunk-RHOZ5LLO.js → chunk-347WD2LE.js} +2 -2
- package/dist/{chunk-HDTQVNWD.js → chunk-3QAH2S33.js} +3 -3
- package/dist/{chunk-37CTGERM.js → chunk-3WCASNQZ.js} +12 -1
- package/dist/chunk-3WCASNQZ.js.map +1 -0
- package/dist/{chunk-LRNMRXJO.js → chunk-3Y224NYC.js} +3 -3
- package/dist/{chunk-3IY64MV6.js → chunk-44XZ75OQ.js} +44 -10
- package/dist/chunk-44XZ75OQ.js.map +1 -0
- package/dist/{chunk-VFSP73LP.js → chunk-45GF7Y3V.js} +2 -2
- package/dist/{chunk-K7LOWSLU.js → chunk-4BJQODZF.js} +2479 -1520
- package/dist/chunk-4BJQODZF.js.map +1 -0
- package/dist/{chunk-JREB6UFH.js → chunk-57OWKFUQ.js} +17 -6
- package/dist/chunk-57OWKFUQ.js.map +1 -0
- package/dist/{chunk-OEHCMALU.js → chunk-5I4M26Q7.js} +5 -5
- package/dist/{chunk-2AZXIZEN.js → chunk-5Q7EVV4X.js} +6 -6
- package/dist/{chunk-LC7OODWZ.js → chunk-5SB7SC2G.js} +80 -49
- package/dist/chunk-5SB7SC2G.js.map +1 -0
- package/dist/{chunk-PUBTHW5O.js → chunk-6DRPPQEJ.js} +2 -2
- package/dist/{chunk-NWTGD4AN.js → chunk-6KIQT7RG.js} +10 -9
- package/dist/chunk-6KIQT7RG.js.map +1 -0
- package/dist/{chunk-FDCTQWLW.js → chunk-6O22TZSB.js} +3 -3
- package/dist/{chunk-ZQ7UBUZ6.js → chunk-6QYST5XN.js} +6 -6
- package/dist/{chunk-W4PGTAS2.js → chunk-6WAFYNVT.js} +3 -3
- package/dist/chunk-6ZMAMSHS.js +20 -0
- package/dist/chunk-6ZMAMSHS.js.map +1 -0
- package/dist/{chunk-R5VAVVHP.js → chunk-72A4L5JJ.js} +2 -2
- package/dist/{chunk-X64YLC24.js → chunk-72VAXGEI.js} +5 -13
- package/dist/chunk-72VAXGEI.js.map +1 -0
- package/dist/{chunk-IKQTFQMI.js → chunk-755Q3DGF.js} +22 -3
- package/dist/chunk-755Q3DGF.js.map +1 -0
- package/dist/{chunk-OVJ2HIPE.js → chunk-76GLCM57.js} +158 -125
- package/dist/chunk-76GLCM57.js.map +1 -0
- package/dist/{chunk-D7FOKIY5.js → chunk-7AMFUATK.js} +12 -9
- package/dist/{chunk-D7FOKIY5.js.map → chunk-7AMFUATK.js.map} +1 -1
- package/dist/{chunk-BFVEEB7W.js → chunk-7ON2JW73.js} +57 -22
- package/dist/chunk-7ON2JW73.js.map +1 -0
- package/dist/chunk-7RNBVZZO.js +270 -0
- package/dist/chunk-7RNBVZZO.js.map +1 -0
- package/dist/{chunk-3FAMU5TX.js → chunk-A6USBZTO.js} +2 -2
- package/dist/{chunk-ZHIVCODT.js → chunk-A72SWTWW.js} +7 -7
- package/dist/{chunk-FC77VUX5.js → chunk-A7Q43EUZ.js} +2 -2
- package/dist/{chunk-UJBESW6X.js → chunk-AE7WMV4V.js} +7 -7
- package/dist/{chunk-J2HSAU72.js → chunk-AIK5W3IW.js} +29 -1
- package/dist/chunk-AIK5W3IW.js.map +1 -0
- package/dist/{chunk-A5UXZRRM.js → chunk-AJ7QCSIS.js} +2 -2
- package/dist/{chunk-FNMFJWBY.js → chunk-ANEUPF6O.js} +5 -5
- package/dist/chunk-AREGMX2J.js +50 -0
- package/dist/chunk-AREGMX2J.js.map +1 -0
- package/dist/chunk-AVPXXV6J.js +448 -0
- package/dist/chunk-AVPXXV6J.js.map +1 -0
- package/dist/{chunk-2A3OXAP2.js → chunk-B7RWBZXW.js} +2 -2
- package/dist/{chunk-GWTFLF2P.js → chunk-BJMBJZ2Y.js} +59 -59
- package/dist/chunk-BJMBJZ2Y.js.map +1 -0
- package/dist/{chunk-74F5STS4.js → chunk-BLAKS3CP.js} +4 -4
- package/dist/{chunk-M7VGG3ID.js → chunk-BV5WMSIJ.js} +9 -9
- package/dist/{chunk-2BFLDH5F.js → chunk-BXLOS5AJ.js} +2 -2
- package/dist/{chunk-UXKMMNJD.js → chunk-C23BYTJV.js} +6 -6
- package/dist/{chunk-JZHHREBL.js → chunk-C3AKM55W.js} +2 -2
- package/dist/{chunk-RP7YXA67.js → chunk-C5JF6EZ7.js} +2 -2
- package/dist/{chunk-T7Y5KPLN.js → chunk-C6XBRYVD.js} +16 -15
- package/dist/chunk-C6XBRYVD.js.map +1 -0
- package/dist/{chunk-FTYDWKO6.js → chunk-CEN6DW6X.js} +12 -2
- package/dist/chunk-CEN6DW6X.js.map +1 -0
- package/dist/chunk-CGASUJVP.js +421 -0
- package/dist/chunk-CGASUJVP.js.map +1 -0
- package/dist/{chunk-EHCONI6E.js → chunk-CQMEM5CC.js} +2 -2
- package/dist/{chunk-PBNZVPFS.js → chunk-CXZQOVIE.js} +12 -12
- package/dist/chunk-D3V3UMET.js +44 -0
- package/dist/chunk-D3V3UMET.js.map +1 -0
- package/dist/{chunk-7N2RUBAP.js → chunk-DDA47TES.js} +2 -2
- package/dist/{chunk-64SE4X5G.js → chunk-DEBHXHJR.js} +3 -3
- package/dist/{chunk-EHK6KZHK.js → chunk-DNHVPZOD.js} +2 -2
- package/dist/{chunk-437S3G37.js → chunk-DQEMWVMT.js} +2 -2
- package/dist/{chunk-LZZNTPLR.js → chunk-DX3XRGLH.js} +2 -2
- package/dist/chunk-EA2H5LML.js +72 -0
- package/dist/chunk-EA2H5LML.js.map +1 -0
- package/dist/{chunk-INELTPRG.js → chunk-EEC7UJPX.js} +103 -106
- package/dist/chunk-EEC7UJPX.js.map +1 -0
- package/dist/{chunk-KSNVDPDF.js → chunk-EKBNDKDY.js} +21 -20
- package/dist/chunk-EKBNDKDY.js.map +1 -0
- package/dist/{chunk-YF6FMLBT.js → chunk-EQWEIIKQ.js} +64 -34
- package/dist/chunk-EQWEIIKQ.js.map +1 -0
- package/dist/{chunk-DZKHSDOM.js → chunk-ES36HTSC.js} +4 -4
- package/dist/{chunk-TN7THW5U.js → chunk-ET356KSB.js} +2 -2
- package/dist/{chunk-YNDLCWXS.js → chunk-EZ25VE3G.js} +4 -4
- package/dist/{chunk-DMSDUGDM.js → chunk-F7GAIWFA.js} +20 -20
- package/dist/{chunk-G6XXLKC5.js → chunk-FFPJINJE.js} +6 -6
- package/dist/chunk-FMLKOL2Z.js +636 -0
- package/dist/chunk-FMLKOL2Z.js.map +1 -0
- package/dist/chunk-FQC3DHH2.js +20 -0
- package/dist/chunk-FQC3DHH2.js.map +1 -0
- package/dist/{chunk-G4CN3ZXL.js → chunk-FUTF72MJ.js} +15 -15
- package/dist/chunk-GCASGYIO.js +71 -0
- package/dist/chunk-GCASGYIO.js.map +1 -0
- package/dist/{chunk-HF77M34J.js → chunk-GFPZS3F5.js} +8 -8
- package/dist/{chunk-BCDKBDSY.js → chunk-GNVZQ5JN.js} +99 -41
- package/dist/chunk-GNVZQ5JN.js.map +1 -0
- package/dist/{chunk-G6NKALRN.js → chunk-H4WG3UQZ.js} +2 -2
- package/dist/{chunk-UDQUSU27.js → chunk-HNZKVLAN.js} +2 -2
- package/dist/{chunk-5EZXHU36.js → chunk-HYQJQGD3.js} +2 -2
- package/dist/{chunk-OAZVR2BV.js → chunk-IDZFBSHN.js} +8 -6
- package/dist/{chunk-OAZVR2BV.js.map → chunk-IDZFBSHN.js.map} +1 -1
- package/dist/{chunk-PLQE6MJA.js → chunk-IFH6LWTO.js} +50 -8
- package/dist/chunk-IFH6LWTO.js.map +1 -0
- package/dist/{chunk-RULE4VG5.js → chunk-ILGC6JH6.js} +21 -6
- package/dist/chunk-ILGC6JH6.js.map +1 -0
- package/dist/chunk-IUM3VSHI.js +113 -0
- package/dist/chunk-IUM3VSHI.js.map +1 -0
- package/dist/{chunk-DCFV7A7H.js → chunk-IYNGIMVG.js} +101 -91
- package/dist/chunk-IYNGIMVG.js.map +1 -0
- package/dist/{chunk-TRWPCR6P.js → chunk-JECBQBEX.js} +3 -3
- package/dist/{chunk-E6CBU7XP.js → chunk-JYIFGGEM.js} +2 -2
- package/dist/{chunk-VA4WSW54.js → chunk-JYIJNNN3.js} +3 -3
- package/dist/{chunk-L5HJQC36.js → chunk-K2TDK7GG.js} +3 -3
- package/dist/{chunk-KDXVOFYY.js → chunk-KAVBJSBQ.js} +4 -4
- package/dist/{chunk-BS4SGLWV.js → chunk-KF5EUVKQ.js} +16 -6
- package/dist/chunk-KF5EUVKQ.js.map +1 -0
- package/dist/chunk-KFZY2OFH.js +42 -0
- package/dist/chunk-KFZY2OFH.js.map +1 -0
- package/dist/{chunk-4OKLXWDZ.js → chunk-KNB7IBBU.js} +2 -2
- package/dist/{chunk-QLULYKWZ.js → chunk-KSXJOC4F.js} +2 -2
- package/dist/{chunk-2S6QHZGJ.js → chunk-L2DPF4DF.js} +1 -1
- package/dist/{chunk-JI5AVXYO.js → chunk-LEPOP46W.js} +6 -6
- package/dist/{chunk-O7BBFJLP.js → chunk-LTAVSOZW.js} +2 -2
- package/dist/{chunk-E3VODCC3.js → chunk-LUDXM7MD.js} +14 -2
- package/dist/{chunk-E3VODCC3.js.map → chunk-LUDXM7MD.js.map} +1 -1
- package/dist/{chunk-2IZAGAJR.js → chunk-LULR4IUW.js} +3 -3
- package/dist/{chunk-QQGPUKMT.js → chunk-MC5Q3J7S.js} +398 -7
- package/dist/chunk-MC5Q3J7S.js.map +1 -0
- package/dist/{chunk-WMWVO45V.js → chunk-MC6XO7T4.js} +2 -2
- package/dist/chunk-MKQBXQKU.js +107 -0
- package/dist/chunk-MKQBXQKU.js.map +1 -0
- package/dist/{chunk-7PND4PUC.js → chunk-MMGGVZ4Q.js} +29 -9
- package/dist/{chunk-7PND4PUC.js.map → chunk-MMGGVZ4Q.js.map} +1 -1
- package/dist/{chunk-D6RIFG4O.js → chunk-MNB5RMAY.js} +2 -2
- package/dist/{chunk-Q5WG43OP.js → chunk-MYFQ3ED4.js} +7 -7
- package/dist/{chunk-V3UE5I5F.js → chunk-MYVPLJOO.js} +2 -2
- package/dist/chunk-NINSR6LX.js +83 -0
- package/dist/chunk-NINSR6LX.js.map +1 -0
- package/dist/{chunk-MTWKDOVO.js → chunk-NLE6TSLG.js} +2 -2
- package/dist/{chunk-DBRYEIGY.js → chunk-OJP3N7UK.js} +2 -2
- package/dist/{chunk-VDW4VU7B.js → chunk-OQJIB32H.js} +28 -23
- package/dist/chunk-OQJIB32H.js.map +1 -0
- package/dist/{chunk-SMX5267P.js → chunk-OZKOPQCM.js} +2 -2
- package/dist/{chunk-JCK7V6SN.js → chunk-P65YJEEL.js} +2 -2
- package/dist/{chunk-MTR7BZQN.js → chunk-PBGWYM3H.js} +3 -3
- package/dist/chunk-PIG4WJFQ.js +87 -0
- package/dist/chunk-PIG4WJFQ.js.map +1 -0
- package/dist/chunk-PQVCH2AE.js +76 -0
- package/dist/chunk-PQVCH2AE.js.map +1 -0
- package/dist/{chunk-AXTXN4T6.js → chunk-PWFCHOB3.js} +2 -2
- package/dist/{chunk-FDPZVY6D.js → chunk-QFN4U7AG.js} +2 -2
- package/dist/{chunk-K2ZLHESQ.js → chunk-QIEUU4UK.js} +2 -2
- package/dist/{chunk-DYP3YYJJ.js → chunk-QJAQNXWI.js} +39 -5
- package/dist/chunk-QJAQNXWI.js.map +1 -0
- package/dist/{chunk-3D6AFGQR.js → chunk-QVT3E4CE.js} +7 -7
- package/dist/{chunk-FIJUY7GG.js → chunk-R26ZMXR2.js} +23 -23
- package/dist/{chunk-FIJUY7GG.js.map → chunk-R26ZMXR2.js.map} +1 -1
- package/dist/chunk-R3DJVOSM.js +34 -0
- package/dist/chunk-R3DJVOSM.js.map +1 -0
- package/dist/{chunk-SFQ6QNL7.js → chunk-R6YJI3HE.js} +2 -1
- package/dist/{chunk-5CJVLG3H.js → chunk-RFDD3B7W.js} +5 -5
- package/dist/{chunk-JBPKEARU.js → chunk-RKNJBZ55.js} +4 -4
- package/dist/chunk-ROI7BK7H.js +88 -0
- package/dist/chunk-ROI7BK7H.js.map +1 -0
- package/dist/{chunk-FNZQGN76.js → chunk-S2BBISHU.js} +4 -4
- package/dist/{chunk-IALLX7EE.js → chunk-S2FSBU4H.js} +3 -3
- package/dist/{chunk-BFPETA3S.js → chunk-SCCO46KZ.js} +3 -2
- package/dist/chunk-SCCO46KZ.js.map +1 -0
- package/dist/chunk-SICXL4MK.js +165 -0
- package/dist/chunk-SICXL4MK.js.map +1 -0
- package/dist/chunk-SK7AMF2J.js +168 -0
- package/dist/chunk-SK7AMF2J.js.map +1 -0
- package/dist/{chunk-LZOV7MX7.js → chunk-TDTXKOAJ.js} +6474 -5747
- package/dist/chunk-TDTXKOAJ.js.map +1 -0
- package/dist/{chunk-KSBEEMQF.js → chunk-TG6IHVE2.js} +151 -6
- package/dist/chunk-TG6IHVE2.js.map +1 -0
- package/dist/{chunk-7K5Q6COX.js → chunk-TVVEYCNW.js} +4 -4
- package/dist/{chunk-DPAENM7O.js → chunk-U3ZAVRP3.js} +2 -2
- package/dist/{chunk-ODPLEWB6.js → chunk-UFGFMWAD.js} +47 -17
- package/dist/chunk-UFGFMWAD.js.map +1 -0
- package/dist/{chunk-4KJLYTLS.js → chunk-V57NLO5P.js} +2 -2
- package/dist/{chunk-FLVL4L3L.js → chunk-VDX2J7OX.js} +2 -2
- package/dist/{chunk-AJLLIIML.js → chunk-W4FBGYGK.js} +1 -1
- package/dist/{chunk-TXLGHDHS.js → chunk-W4XJFLAL.js} +53 -32
- package/dist/chunk-W4XJFLAL.js.map +1 -0
- package/dist/{chunk-6SXVCD7W.js → chunk-W7IGLX4G.js} +2 -2
- package/dist/{chunk-KQDNAXOM.js → chunk-WG5HSQ4P.js} +19 -6
- package/dist/chunk-WG5HSQ4P.js.map +1 -0
- package/dist/{chunk-LTJAMRGI.js → chunk-WL5EBRDH.js} +17 -3
- package/dist/chunk-WL5EBRDH.js.map +1 -0
- package/dist/{chunk-KAWTOYAW.js → chunk-WLZYGLJ4.js} +2 -2
- package/dist/{chunk-RO4LQGT3.js → chunk-WON4APQY.js} +4 -4
- package/dist/{chunk-PQVK2S3J.js → chunk-WZFAPHIK.js} +6 -6
- package/dist/{chunk-KQPJLK3X.js → chunk-XL24QQ63.js} +2 -2
- package/dist/{chunk-RVZRYUQH.js → chunk-YROFNEG5.js} +7 -7
- package/dist/{chunk-RAR2BSEM.js → chunk-YV32N67O.js} +1 -1
- package/dist/chunk-YV32N67O.js.map +1 -0
- package/dist/{chunk-PBSAPHHA.js → chunk-YVKF3HEW.js} +1 -1
- package/dist/chunk-YVKF3HEW.js.map +1 -0
- package/dist/{chunk-VRAD2FGO.js → chunk-Z54EM5YZ.js} +12 -12
- package/dist/{chunk-2VN4JAX7.js → chunk-ZOKZIR5K.js} +95 -33
- package/dist/chunk-ZOKZIR5K.js.map +1 -0
- package/dist/{cli-Cd5fMmhq.d.ts → cli-C_pqqTCw.d.ts} +28 -12
- package/dist/cli.d.ts +16 -9
- package/dist/cli.js +142 -127
- package/dist/compounding/engine.d.ts +5 -2
- package/dist/compounding/engine.js +36 -26
- package/dist/compounding/preference-consolidator.d.ts +3 -1
- package/dist/compounding/preference-consolidator.js +1 -1
- package/dist/compression-optimizer.d.ts +3 -1
- package/dist/config-qmd.d.ts +8 -0
- package/dist/config-qmd.js +20 -0
- package/dist/config-qmd.js.map +1 -0
- package/dist/config.d.ts +3 -1
- package/dist/config.js +15 -10
- package/dist/connectors/codex-materialize-runner.d.ts +3 -1
- package/dist/connectors/codex-materialize-runner.js +36 -26
- package/dist/connectors/codex-materialize.d.ts +3 -1
- package/dist/connectors/codex-materialize.js +2 -2
- package/dist/connectors/index.d.ts +3 -1
- package/dist/connectors/index.js +41 -32
- package/dist/consolidation-provenance-check.d.ts +5 -2
- package/dist/consolidation-undo.d.ts +5 -2
- package/dist/contradiction/index.d.ts +5 -2
- package/dist/contradiction/index.js +10 -4
- package/dist/{contradiction-scan-J57T5QV7.js → contradiction-scan-RJBABNRH.js} +4 -4
- package/dist/contradiction-scan-RJBABNRH.js.map +1 -0
- package/dist/conversation-index/backend.d.ts +3 -1
- package/dist/conversation-index/backend.js +5 -5
- package/dist/conversation-index/chunker.d.ts +3 -1
- package/dist/conversation-index/cleanup.js +2 -2
- package/dist/conversation-index/faiss-adapter.d.ts +3 -1
- package/dist/conversation-index/faiss-adapter.js +2 -2
- package/dist/conversation-index/indexer.d.ts +3 -1
- package/dist/conversation-index/indexer.js +2 -2
- package/dist/conversation-index/search.d.ts +3 -1
- package/dist/conversation-index/search.js +2 -2
- package/dist/cross-namespace-budget.d.ts +45 -1
- package/dist/cross-namespace-budget.js +5 -3
- package/dist/dashboard-runtime.js +2 -2
- package/dist/day-summary.d.ts +3 -1
- package/dist/day-summary.js +3 -3
- package/dist/delinearize.d.ts +3 -1
- package/dist/direct-answer-wiring.d.ts +3 -1
- package/dist/direct-answer.d.ts +3 -1
- package/dist/{dreams-ledger-6UODQOX6.js → dreams-ledger-567VKVOU.js} +4 -2
- package/dist/dreams-ledger-567VKVOU.js.map +1 -0
- package/dist/embedding-fallback.d.ts +3 -1
- package/dist/embedding-fallback.js +3 -3
- package/dist/enrichment/index.d.ts +3 -1
- package/dist/entity-retrieval.d.ts +5 -2
- package/dist/entity-retrieval.js +35 -26
- package/dist/entity-schema.d.ts +3 -1
- package/dist/explicit-capture.d.ts +13 -8
- package/dist/explicit-capture.js +7 -3
- package/dist/extraction-faithfulness.d.ts +3 -1
- package/dist/extraction-faithfulness.js +5 -5
- package/dist/extraction-judge-telemetry.d.ts +3 -1
- package/dist/extraction-judge-telemetry.js +2 -2
- package/dist/extraction-judge-training.d.ts +3 -1
- package/dist/extraction-judge-training.js +2 -2
- package/dist/extraction-judge.d.ts +3 -1
- package/dist/extraction-judge.js +5 -5
- package/dist/extraction.d.ts +3 -1
- package/dist/extraction.js +13 -12
- package/dist/faithfulness-config.js +3 -2
- package/dist/fallback-llm.d.ts +3 -1
- package/dist/fallback-llm.js +4 -4
- package/dist/{first-start-migration-TI67YMLG.js → first-start-migration-CSRHCJIQ.js} +2 -2
- package/dist/{forget-CQCLB5LB.js → forget-HRPLVB3W.js} +5 -5
- package/dist/graph-dashboard-diff.d.ts +3 -1
- package/dist/graph-dashboard-key.d.ts +3 -1
- package/dist/graph-dashboard-parser.d.ts +3 -1
- package/dist/{graph-edge-decay-IOGBBAGC.js → graph-edge-decay-Z6ENALU2.js} +3 -3
- package/dist/graph-edge-decay-Z6ENALU2.js.map +1 -0
- package/dist/graph-edge-reinforcement.d.ts +3 -1
- package/dist/graph-snapshot.d.ts +3 -1
- package/dist/graph-snapshot.js +2 -2
- package/dist/graph.d.ts +3 -1
- package/dist/graph.js +1 -1
- package/dist/identity-continuity.d.ts +1 -2
- package/dist/importance.d.ts +3 -1
- package/dist/importers/index.d.ts +3 -1
- package/dist/in-flight-reads.d.ts +3 -1
- package/dist/index.d.ts +473 -464
- package/dist/index.js +287 -239
- package/dist/intent.d.ts +3 -1
- package/dist/lcm/archive.js +2 -2
- package/dist/lcm/engine.d.ts +3 -1
- package/dist/lcm/engine.js +6 -6
- package/dist/lcm/index.d.ts +3 -1
- package/dist/lcm/index.js +13 -13
- package/dist/lcm/schema.js +2 -2
- package/dist/lcm/summarizer.js +3 -3
- package/dist/lcm/tools.d.ts +3 -1
- package/dist/lifecycle.d.ts +3 -1
- package/dist/live-connectors-runner.d.ts +3 -1
- package/dist/local-llm.d.ts +5 -2
- package/dist/local-llm.js +3 -3
- package/dist/local-model-endpoint.d.ts +3 -1
- package/dist/logger.d.ts +3 -1
- package/dist/logger.js +7 -3
- package/dist/maintenance/archive-observations.js +2 -2
- package/dist/maintenance/memory-governance.d.ts +3 -1
- package/dist/maintenance/memory-governance.js +35 -25
- package/dist/maintenance/migrate-observations.js +3 -3
- package/dist/maintenance/observation-ledger-utils.js +2 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +102 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +37 -25
- package/dist/maintenance/rebuild-memory-projection.js +38 -28
- package/dist/maintenance/rebuild-observations.js +3 -3
- package/dist/mcp-memory-inspector-app.d.ts +22 -15
- package/dist/memory-action-policy.d.ts +3 -1
- package/dist/memory-cache.d.ts +3 -1
- package/dist/memory-lifecycle-ledger-utils.d.ts +25 -2
- package/dist/memory-lifecycle-ledger-utils.js +11 -1
- package/dist/memory-projection-store.d.ts +3 -1
- package/dist/memory-projection-store.js +2 -2
- package/dist/memory-provenance.d.ts +3 -1
- package/dist/memory-worth-outcomes.d.ts +5 -2
- package/dist/model-registry.js +2 -2
- package/dist/models-json.d.ts +3 -1
- package/dist/models-json.js +2 -2
- package/dist/namespaces/migrate.d.ts +6 -3
- package/dist/namespaces/migrate.js +51 -42
- package/dist/namespaces/principal.d.ts +27 -2
- package/dist/namespaces/principal.js +6 -2
- package/dist/namespaces/search.d.ts +16 -2
- package/dist/namespaces/search.js +24 -20
- package/dist/namespaces/storage.d.ts +24 -3
- package/dist/namespaces/storage.js +35 -27
- package/dist/native-knowledge.d.ts +3 -1
- package/dist/native-knowledge.js +2 -2
- package/dist/negative.js +2 -2
- package/dist/offline-sync-exclude-globs.d.ts +13 -0
- package/dist/offline-sync-exclude-globs.js +10 -0
- package/dist/offline-sync-exclude-globs.js.map +1 -0
- package/dist/offline-sync-impression-drain.d.ts +78 -0
- package/dist/offline-sync-impression-drain.js +37 -0
- package/dist/offline-sync-impression-drain.js.map +1 -0
- package/dist/offline-sync.js +4 -2
- package/dist/operator-toolkit.d.ts +5 -2
- package/dist/operator-toolkit.js +69 -54
- package/dist/orchestration/compression-guideline-coordinator.d.ts +5 -2
- package/dist/orchestration/compression-guideline-coordinator.js +3 -3
- package/dist/orchestration/maintenance.d.ts +121 -2
- package/dist/orchestration/maintenance.js +44 -31
- package/dist/{orchestrator-Bp_jeBHK.d.ts → orchestrator-CQJ8U7En.d.ts} +85 -79
- package/dist/orchestrator.d.ts +13 -8
- package/dist/orchestrator.js +194 -177
- package/dist/patterns-cli.d.ts +3 -1
- package/dist/{pipeline-BAj5bx7g.d.ts → pipeline-Cn-kvYeV.d.ts} +1 -1
- package/dist/policy-runtime.d.ts +3 -1
- package/dist/prioritized-embed.d.ts +19 -0
- package/dist/prioritized-embed.js +8 -0
- package/dist/prioritized-embed.js.map +1 -0
- package/dist/proactive-contention.d.ts +28 -0
- package/dist/proactive-contention.js +8 -0
- package/dist/proactive-contention.js.map +1 -0
- package/dist/profiling.js +2 -2
- package/dist/provenance.d.ts +3 -1
- package/dist/provenance.js +3 -2
- package/dist/{purge-NDWV6WYD.js → purge-IRF47ZTX.js} +3 -3
- package/dist/{qmd-_MDSlj1m.d.ts → qmd-oh9VXz1d.d.ts} +11 -1
- package/dist/qmd-preflight.d.ts +5 -2
- package/dist/qmd-recall-cache.d.ts +3 -1
- package/dist/qmd-status.d.ts +57 -0
- package/dist/qmd-status.js +18 -0
- package/dist/qmd-status.js.map +1 -0
- package/dist/qmd.d.ts +5 -2
- package/dist/qmd.js +7 -3
- package/dist/recall-concurrency-config.d.ts +16 -0
- package/dist/recall-concurrency-config.js +10 -0
- package/dist/recall-concurrency-config.js.map +1 -0
- package/dist/recall-disclosure-escalation.d.ts +3 -1
- package/dist/recall-explain-renderer.d.ts +4 -1
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-memory-map.d.ts +26 -0
- package/dist/recall-memory-map.js +18 -0
- package/dist/recall-memory-map.js.map +1 -0
- package/dist/recall-planner-llm.d.ts +3 -1
- package/dist/recall-planner-llm.js +4 -4
- package/dist/recall-qos.js +2 -2
- package/dist/recall-state.d.ts +163 -2
- package/dist/recall-state.js +6 -3
- package/dist/recall-tag-filter.d.ts +3 -1
- package/dist/recall-timings.d.ts +11 -2
- package/dist/recall-timings.js +3 -1
- package/dist/recall-xray-cli.d.ts +3 -1
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.d.ts +3 -1
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.d.ts +3 -1
- package/dist/recall-xray.js +2 -2
- package/dist/relevance.js +3 -3
- package/dist/replay/normalizers/chatgpt.d.ts +3 -1
- package/dist/replay/normalizers/claude.d.ts +3 -1
- package/dist/replay/normalizers/openclaw.d.ts +3 -1
- package/dist/replay/normalizers/shared.d.ts +3 -1
- package/dist/replay/runner.d.ts +3 -1
- package/dist/replay/types.d.ts +3 -1
- package/dist/rerank.d.ts +8 -1
- package/dist/rerank.js +3 -1
- package/dist/resolution-3K27T4VO.js +18 -0
- package/dist/resolution-3K27T4VO.js.map +1 -0
- package/dist/resolve-auth-token.d.ts +3 -1
- package/dist/resolve-provider-secret.js +2 -2
- package/dist/resume-bundles.js +19 -14
- package/dist/retrieval-agents.d.ts +19 -16
- package/dist/retrieval-agents.js +3 -3
- package/dist/retrieval-tiers.d.ts +3 -1
- package/dist/routing/engine.d.ts +3 -1
- package/dist/routing/store.d.ts +3 -1
- package/dist/routing/store.js +2 -2
- package/dist/salvage-envelope.d.ts +18 -0
- package/dist/salvage-envelope.js +15 -0
- package/dist/salvage-envelope.js.map +1 -0
- package/dist/schemas.d.ts +98 -98
- package/dist/scope-profiles-EpJG7yKP.d.ts +30 -0
- package/dist/search/document-scanner.js +3 -2
- package/dist/search/embed-helper.d.ts +3 -1
- package/dist/search/embed-helper.js +3 -3
- package/dist/search/factory.d.ts +3 -1
- package/dist/search/factory.js +18 -16
- package/dist/search/index.d.ts +3 -1
- package/dist/search/index.js +22 -20
- package/dist/search/lancedb-backend.d.ts +3 -1
- package/dist/search/lancedb-backend.js +6 -5
- package/dist/search/meilisearch-backend.d.ts +3 -1
- package/dist/search/meilisearch-backend.js +6 -5
- package/dist/search/noop-backend.d.ts +3 -1
- package/dist/search/orama-backend.d.ts +3 -1
- package/dist/search/orama-backend.js +6 -5
- package/dist/search/port.d.ts +16 -2
- package/dist/search/port.js +1 -1
- package/dist/search/remote-backend.d.ts +3 -1
- package/dist/search/remote-backend.js +3 -3
- package/dist/secure-store/index.d.ts +12 -1
- package/dist/secure-store/index.js +6 -3
- package/dist/{semantic-consolidation-C2m5eHHE.d.ts → semantic-consolidation-DILZEQq3.d.ts} +1 -1
- package/dist/semantic-consolidation.d.ts +4 -2
- package/dist/semantic-consolidation.js +38 -29
- package/dist/semantic-rule-promotion.js +34 -24
- package/dist/semantic-rule-verifier.d.ts +3 -1
- package/dist/semantic-rule-verifier.js +35 -25
- package/dist/session-observer-bands.d.ts +3 -1
- package/dist/session-observer-state.d.ts +3 -1
- package/dist/session-observer-state.js +2 -2
- package/dist/session-transcript-migration.js +2 -2
- package/dist/shared-context/manager.d.ts +11 -9
- package/dist/shared-context/manager.js +3 -3
- package/dist/signal.d.ts +3 -1
- package/dist/{storage-hr_Y2z5R.d.ts → storage-NIyKYD8g.d.ts} +489 -110
- package/dist/storage-guards.js +2 -2
- package/dist/storage.d.ts +6 -3
- package/dist/storage.js +38 -26
- package/dist/structured-attributes.d.ts +23 -1
- package/dist/structured-attributes.js +7 -1
- package/dist/summarizer.d.ts +3 -1
- package/dist/summarizer.js +11 -11
- package/dist/summary-snapshot.d.ts +3 -1
- package/dist/summary-snapshot.js +2 -2
- package/dist/temporal-index-batch.d.ts +1 -0
- package/dist/temporal-index-batch.js +10 -0
- package/dist/temporal-index-batch.js.map +1 -0
- package/dist/temporal-index-compat.d.ts +279 -1
- package/dist/temporal-index-compat.js +1 -1
- package/dist/temporal-index.d.ts +1 -225
- package/dist/temporal-index.js +35 -3
- package/dist/temporal-supersession.d.ts +5 -2
- package/dist/temporal-supersession.js +2 -2
- package/dist/temporal-timeline-recall.d.ts +3 -1
- package/dist/temporal-validity.d.ts +3 -1
- package/dist/threading.d.ts +3 -1
- package/dist/threading.js +2 -2
- package/dist/tier-migration.d.ts +5 -2
- package/dist/tier-routing.d.ts +3 -1
- package/dist/{tier-stats-KV7IWCJR.js → tier-stats-QEJSPFV2.js} +2 -2
- package/dist/tokens.js +3 -3
- package/dist/topics.d.ts +3 -1
- package/dist/transcript.d.ts +3 -1
- package/dist/transcript.js +2 -2
- package/dist/transfer/backup.js +3 -3
- package/dist/transfer/capsule-export.js +3 -3
- package/dist/transfer/capsule-import.js +3 -3
- package/dist/transfer/types.d.ts +90 -90
- package/dist/trust-score-stage.d.ts +75 -38
- package/dist/trust-score-stage.js +11 -3
- package/dist/trust-score.d.ts +3 -1
- package/dist/{types-Cg8q7W7_.d.ts → types-D_fG2ix8.d.ts} +39 -63
- package/dist/types-continuity.d.ts +52 -0
- package/dist/types-continuity.js +1 -0
- package/dist/types-continuity.js.map +1 -0
- package/dist/types.d.ts +3 -1
- package/dist/types.js +1 -1
- package/dist/utility-runtime.d.ts +3 -1
- package/dist/utils/serialize-mutations.d.ts +31 -2
- package/dist/utils/serialize-mutations.js +1 -1
- package/dist/verified-recall.js +36 -26
- package/dist/write-envelope.d.ts +282 -0
- package/dist/write-envelope.js +35 -0
- package/dist/write-envelope.js.map +1 -0
- package/dist/write-quarantine.d.ts +79 -0
- package/dist/write-quarantine.js +11 -0
- package/dist/write-quarantine.js.map +1 -0
- package/dist/write-rate-limiter.d.ts +45 -0
- package/dist/write-rate-limiter.js +9 -0
- package/dist/write-rate-limiter.js.map +1 -0
- package/package.json +37 -2
- package/src/access-admin-ops-surface.ts +17 -7
- package/src/access-boundary.test.ts +28 -0
- package/src/access-boundary.ts +31 -2
- package/src/access-citation.test.ts +72 -0
- package/src/access-citation.ts +139 -0
- package/src/access-errors.ts +21 -0
- package/src/access-fingerprint-parity.test.ts +211 -0
- package/src/access-http-cancellation.test.ts +59 -21
- package/src/access-http.test.ts +90 -0
- package/src/access-http.ts +79 -79
- package/src/access-mcp-cancellation.test.ts +16 -7
- package/src/access-memory-search-fanout.test.ts +220 -0
- package/src/access-memory-search-fanout.ts +168 -0
- package/src/access-observe-quarantine.test.ts +120 -0
- package/src/access-observe-write-surface.ts +130 -11
- package/src/access-operations-batch.ts +2 -0
- package/src/access-recall-concurrency.ts +773 -0
- package/src/access-recall-response.ts +307 -0
- package/src/access-recall-surface.ts +100 -252
- package/src/access-service-coding-write.test.ts +22 -4
- package/src/access-service-health.test.ts +49 -0
- package/src/access-service-namespace.test.ts +486 -8
- package/src/access-service-observe-scope.test.ts +4 -0
- package/src/access-service-recall-concurrency.test.ts +1990 -0
- package/src/access-service.ts +182 -175
- package/src/access-surface-catalog.ts +1 -0
- package/src/access-token-capabilities.ts +16 -9
- package/src/active-recall.test.ts +35 -0
- package/src/active-recall.ts +7 -0
- package/src/bounded-jsonl-state.ts +93 -0
- package/src/buffer-session.test.ts +422 -5
- package/src/buffer-surprise-trigger.test.ts +41 -0
- package/src/buffer.ts +218 -3
- package/src/capabilities-cluster-b.test.ts +1 -0
- package/src/capabilities.ts +5 -6
- package/src/cli.ts +21 -22
- package/src/coding/architecture-surfaces.test.ts +6 -3
- package/src/coding/architecture-surfaces.ts +36 -25
- package/src/coding/decision-surfaces.ts +42 -34
- package/src/compounding/engine.test.ts +5 -1
- package/src/compounding/engine.ts +7 -7
- package/src/config-qmd.ts +89 -0
- package/src/config.test.ts +136 -0
- package/src/config.ts +113 -118
- package/src/connector-provenance-lifecycle.test.ts +4 -4
- package/src/connectors/coerce.test.ts +131 -0
- package/src/connectors/coerce.ts +80 -7
- package/src/contradiction/contradiction.test.ts +10 -6
- package/src/contradiction/resolution.ts +17 -4
- package/src/correction/correction-access-wiring.ts +62 -18
- package/src/cross-namespace-budget.test.ts +35 -0
- package/src/cross-namespace-budget.ts +86 -19
- package/src/explicit-capture.ts +54 -17
- package/src/extraction.ts +2 -3
- package/src/faithfulness-graph-guard.test.ts +16 -69
- package/src/graph-recall.test.ts +31 -0
- package/src/index.ts +22 -2
- package/src/local-llm.ts +4 -6
- package/src/logger.ts +16 -0
- package/src/maintenance/dreams-ledger.ts +100 -49
- package/src/maintenance/rebuild-memory-lifecycle-ledger-cli.ts +77 -0
- package/src/maintenance/rebuild-memory-lifecycle-ledger.ts +373 -9
- package/src/memory-lifecycle-ledger-utils.ts +51 -5
- package/src/namespaces/principal.test.ts +37 -1
- package/src/namespaces/principal.ts +48 -0
- package/src/namespaces/search.test.ts +79 -5
- package/src/namespaces/search.ts +59 -6
- package/src/namespaces/storage.ts +43 -1
- package/src/offline-sync-exclude-globs.ts +58 -0
- package/src/offline-sync-impression-drain.test.ts +316 -0
- package/src/offline-sync-impression-drain.ts +260 -0
- package/src/offline-sync.test.ts +32 -5
- package/src/offline-sync.ts +1 -14
- package/src/operator-toolkit.ts +1 -1
- package/src/orchestration/batch-deindex-flush.test.ts +146 -0
- package/src/orchestration/consolidation-run.ts +96 -85
- package/src/orchestration/extraction-envelope.ts +94 -0
- package/src/orchestration/extraction-persist-promotion.ts +134 -0
- package/src/orchestration/extraction-persist.ts +325 -260
- package/src/orchestration/extraction-run.test.ts +1 -1
- package/src/orchestration/extraction-run.ts +2 -2
- package/src/orchestration/graph-recall-coordinator.ts +18 -7
- package/src/orchestration/lifecycle-policy-coordinator.ts +63 -48
- package/src/orchestration/maintenance.test.ts +2103 -3
- package/src/orchestration/maintenance.ts +574 -2
- package/src/orchestration/namespace-read-fanout.ts +14 -8
- package/src/orchestration/orchestrator-helpers.ts +8 -1
- package/src/orchestration/orchestrator-init.ts +22 -6
- package/src/orchestration/orchestrator-namespace-scope.ts +71 -0
- package/src/orchestration/persistence-index.ts +64 -9
- package/src/orchestration/qmd-result-resolver.ts +27 -0
- package/src/orchestration/recall-entry.ts +34 -19
- package/src/orchestration/recall-internal.ts +207 -79
- package/src/orchestration/recall-rerank-coordinator.ts +229 -82
- package/src/orchestration/recall-result-formatter.ts +76 -20
- package/src/orchestration/recall-search-pipeline.test.ts +70 -0
- package/src/orchestration/recall-search-pipeline.ts +102 -129
- package/src/orchestration/recall-section-coordinator.ts +315 -85
- package/src/orchestration/semantic-consolidation-coordinator.ts +69 -37
- package/src/orchestration/session-context.ts +21 -0
- package/src/orchestration/workspace-ops.test.ts +348 -0
- package/src/orchestration/workspace-ops.ts +168 -34
- package/src/orchestrator-chunked-hash-durability.test.ts +126 -0
- package/src/orchestrator-connector-dedup.test.ts +1061 -40
- package/src/orchestrator-flush.test.ts +155 -39
- package/src/orchestrator-nonchunked-hash-durability.test.ts +121 -0
- package/src/orchestrator-source-attribution.test.ts +9 -9
- package/src/orchestrator.ts +160 -149
- package/src/prioritized-embed.ts +123 -0
- package/src/proactive-contention.test.ts +80 -0
- package/src/proactive-contention.ts +39 -0
- package/src/procedural/procedure-miner.test.ts +19 -14
- package/src/procedural/procedure-miner.ts +44 -13
- package/src/qmd-client.test.ts +111 -1
- package/src/qmd-status.ts +186 -0
- package/src/qmd.ts +47 -47
- package/src/recall-budget-config.test.ts +30 -0
- package/src/recall-cold-deadline.test.ts +149 -0
- package/src/recall-concurrency-config.ts +28 -0
- package/src/recall-memory-map.ts +74 -0
- package/src/recall-rerank-coordinator.test.ts +508 -0
- package/src/recall-state.test.ts +825 -1
- package/src/recall-state.ts +406 -7
- package/src/recall-timings-access.test.ts +41 -0
- package/src/recall-timings.ts +16 -0
- package/src/relay/mission-access.test.ts +5 -5
- package/src/rerank.ts +22 -0
- package/src/retrieval-agents.test.ts +79 -0
- package/src/retrieval-agents.ts +71 -19
- package/src/salvage-envelope.ts +28 -0
- package/src/scopes/scope-plan.test.ts +42 -0
- package/src/scopes/scope-plan.ts +45 -0
- package/src/search/port.ts +13 -0
- package/src/secure-store/index.ts +1 -0
- package/src/secure-store/secure-fs.ts +48 -0
- package/src/secure-store/secure-store.test.ts +40 -0
- package/src/semantic-rule-promotion.ts +13 -4
- package/src/storage/content-hash-index.ts +655 -0
- package/src/storage/entity-timeline.ts +473 -0
- package/src/storage/memory-lifecycle-ledger-access.ts +603 -0
- package/src/storage/secure-line-reader.test.ts +197 -0
- package/src/storage/secure-line-reader.ts +181 -3
- package/src/storage-append-header-sniff.test.ts +195 -0
- package/src/storage-behavior-signals-cache.test.ts +237 -0
- package/src/storage-contract/cache-coherence.test.ts +96 -1
- package/src/storage-contract/content-hash.test.ts +47 -2
- package/src/storage-fact-hash-index-defer.test.ts +1200 -0
- package/src/storage-memory-lifecycle-ledger.test.ts +1146 -3
- package/src/storage.ts +882 -890
- package/src/structured-attributes.ts +52 -0
- package/src/temporal-index-batch.ts +112 -0
- package/src/temporal-index.test.ts +193 -0
- package/src/temporal-index.ts +49 -53
- package/src/testing/lifecycle-matrix.test.ts +212 -0
- package/src/testing/lifecycle-matrix.ts +271 -0
- package/src/testing/orchestrator-lite.ts +236 -0
- package/src/testing/subjects/dreams-ledger.test.ts +67 -0
- package/src/testing/subjects/extraction-lifecycle.test.ts +442 -0
- package/src/testing/subjects/lifecycle-ledger.test.ts +93 -0
- package/src/testing/subjects/recall-budget.test.ts +461 -0
- package/src/testing/subjects/serialized-write-chain.test.ts +224 -0
- package/src/trust-score-stage.test.ts +154 -0
- package/src/trust-score-stage.ts +216 -53
- package/src/types-continuity.ts +57 -0
- package/src/types.ts +51 -77
- package/src/utils/path-containment.test.ts +75 -0
- package/src/utils/path-containment.ts +76 -0
- package/src/utils/serialize-mutations.test.ts +122 -0
- package/src/utils/serialize-mutations.ts +68 -3
- package/src/wearables/memory-gen.test.ts +31 -9
- package/src/wearables/memory-gen.ts +95 -55
- package/src/wearables/pipeline.test.ts +10 -7
- package/src/wearables/service.test.ts +6 -8
- package/src/wearables/service.ts +2 -2
- package/src/write-envelope.extension.test.ts +111 -0
- package/src/write-envelope.test.ts +683 -0
- package/src/write-envelope.ts +902 -0
- package/src/write-quarantine.test.ts +193 -0
- package/src/write-quarantine.ts +241 -0
- package/src/write-rate-limiter.test.ts +105 -0
- package/src/write-rate-limiter.ts +135 -0
- package/src/write-sealed-parity.test.ts +204 -0
- package/dist/chunk-2VN4JAX7.js.map +0 -1
- package/dist/chunk-37CTGERM.js.map +0 -1
- package/dist/chunk-3IY64MV6.js.map +0 -1
- package/dist/chunk-BCDKBDSY.js.map +0 -1
- package/dist/chunk-BFPETA3S.js.map +0 -1
- package/dist/chunk-BFVEEB7W.js.map +0 -1
- package/dist/chunk-BS4SGLWV.js.map +0 -1
- package/dist/chunk-DCFV7A7H.js.map +0 -1
- package/dist/chunk-DYP3YYJJ.js.map +0 -1
- package/dist/chunk-E5BK6CGV.js +0 -335
- package/dist/chunk-E5BK6CGV.js.map +0 -1
- package/dist/chunk-FTYDWKO6.js.map +0 -1
- package/dist/chunk-GWTFLF2P.js.map +0 -1
- package/dist/chunk-IKQTFQMI.js.map +0 -1
- package/dist/chunk-INELTPRG.js.map +0 -1
- package/dist/chunk-J2HSAU72.js.map +0 -1
- package/dist/chunk-JREB6UFH.js.map +0 -1
- package/dist/chunk-K7LOWSLU.js.map +0 -1
- package/dist/chunk-KQDNAXOM.js.map +0 -1
- package/dist/chunk-KSBEEMQF.js.map +0 -1
- package/dist/chunk-KSNVDPDF.js.map +0 -1
- package/dist/chunk-LC7OODWZ.js.map +0 -1
- package/dist/chunk-LTJAMRGI.js.map +0 -1
- package/dist/chunk-LZOV7MX7.js.map +0 -1
- package/dist/chunk-NWTGD4AN.js.map +0 -1
- package/dist/chunk-ODPLEWB6.js.map +0 -1
- package/dist/chunk-OVJ2HIPE.js.map +0 -1
- package/dist/chunk-PBSAPHHA.js.map +0 -1
- package/dist/chunk-PHK3HARR.js +0 -32
- package/dist/chunk-PHK3HARR.js.map +0 -1
- package/dist/chunk-PLQE6MJA.js.map +0 -1
- package/dist/chunk-QKQYXZVS.js.map +0 -1
- package/dist/chunk-QQGPUKMT.js.map +0 -1
- package/dist/chunk-RANHFI3P.js +0 -8
- package/dist/chunk-RANHFI3P.js.map +0 -1
- package/dist/chunk-RAR2BSEM.js.map +0 -1
- package/dist/chunk-RULE4VG5.js.map +0 -1
- package/dist/chunk-SVOZFLIQ.js +0 -16
- package/dist/chunk-SVOZFLIQ.js.map +0 -1
- package/dist/chunk-T7Y5KPLN.js.map +0 -1
- package/dist/chunk-TXLGHDHS.js.map +0 -1
- package/dist/chunk-VDW4VU7B.js.map +0 -1
- package/dist/chunk-VSMRDBFT.js +0 -17
- package/dist/chunk-VSMRDBFT.js.map +0 -1
- package/dist/chunk-X64YLC24.js.map +0 -1
- package/dist/chunk-XDSXEKYK.js +0 -118
- package/dist/chunk-XDSXEKYK.js.map +0 -1
- package/dist/chunk-YF6FMLBT.js.map +0 -1
- package/dist/resolution-VH4NGENZ.js +0 -12
- /package/dist/{capsule-crypto-CZJSLEFG.js.map → access-citation.js.map} +0 -0
- /package/dist/{contradiction-scan-J57T5QV7.js.map → access-memory-search-fanout.js.map} +0 -0
- /package/dist/{dreams-ledger-6UODQOX6.js.map → access-recall-concurrency.js.map} +0 -0
- /package/dist/{graph-edge-decay-IOGBBAGC.js.map → access-recall-response.js.map} +0 -0
- /package/dist/{resolution-VH4NGENZ.js.map → bounded-jsonl-state.js.map} +0 -0
- /package/dist/{chunk-A3GOMRJG.js.map → chunk-23L3IXFD.js.map} +0 -0
- /package/dist/{chunk-MRHFJV44.js.map → chunk-2DQ2XREU.js.map} +0 -0
- /package/dist/{chunk-L2B3EE7B.js.map → chunk-2QMKMVHH.js.map} +0 -0
- /package/dist/{chunk-VJVNLNDQ.js.map → chunk-2UFO7X4Q.js.map} +0 -0
- /package/dist/{chunk-2MR3MFQB.js.map → chunk-2VEOKUPP.js.map} +0 -0
- /package/dist/{chunk-RHOZ5LLO.js.map → chunk-347WD2LE.js.map} +0 -0
- /package/dist/{chunk-HDTQVNWD.js.map → chunk-3QAH2S33.js.map} +0 -0
- /package/dist/{chunk-LRNMRXJO.js.map → chunk-3Y224NYC.js.map} +0 -0
- /package/dist/{chunk-VFSP73LP.js.map → chunk-45GF7Y3V.js.map} +0 -0
- /package/dist/{chunk-OEHCMALU.js.map → chunk-5I4M26Q7.js.map} +0 -0
- /package/dist/{chunk-2AZXIZEN.js.map → chunk-5Q7EVV4X.js.map} +0 -0
- /package/dist/{chunk-PUBTHW5O.js.map → chunk-6DRPPQEJ.js.map} +0 -0
- /package/dist/{chunk-FDCTQWLW.js.map → chunk-6O22TZSB.js.map} +0 -0
- /package/dist/{chunk-ZQ7UBUZ6.js.map → chunk-6QYST5XN.js.map} +0 -0
- /package/dist/{chunk-W4PGTAS2.js.map → chunk-6WAFYNVT.js.map} +0 -0
- /package/dist/{chunk-R5VAVVHP.js.map → chunk-72A4L5JJ.js.map} +0 -0
- /package/dist/{chunk-3FAMU5TX.js.map → chunk-A6USBZTO.js.map} +0 -0
- /package/dist/{chunk-ZHIVCODT.js.map → chunk-A72SWTWW.js.map} +0 -0
- /package/dist/{chunk-FC77VUX5.js.map → chunk-A7Q43EUZ.js.map} +0 -0
- /package/dist/{chunk-UJBESW6X.js.map → chunk-AE7WMV4V.js.map} +0 -0
- /package/dist/{chunk-A5UXZRRM.js.map → chunk-AJ7QCSIS.js.map} +0 -0
- /package/dist/{chunk-FNMFJWBY.js.map → chunk-ANEUPF6O.js.map} +0 -0
- /package/dist/{chunk-2A3OXAP2.js.map → chunk-B7RWBZXW.js.map} +0 -0
- /package/dist/{chunk-74F5STS4.js.map → chunk-BLAKS3CP.js.map} +0 -0
- /package/dist/{chunk-M7VGG3ID.js.map → chunk-BV5WMSIJ.js.map} +0 -0
- /package/dist/{chunk-2BFLDH5F.js.map → chunk-BXLOS5AJ.js.map} +0 -0
- /package/dist/{chunk-UXKMMNJD.js.map → chunk-C23BYTJV.js.map} +0 -0
- /package/dist/{chunk-JZHHREBL.js.map → chunk-C3AKM55W.js.map} +0 -0
- /package/dist/{chunk-RP7YXA67.js.map → chunk-C5JF6EZ7.js.map} +0 -0
- /package/dist/{chunk-EHCONI6E.js.map → chunk-CQMEM5CC.js.map} +0 -0
- /package/dist/{chunk-PBNZVPFS.js.map → chunk-CXZQOVIE.js.map} +0 -0
- /package/dist/{chunk-7N2RUBAP.js.map → chunk-DDA47TES.js.map} +0 -0
- /package/dist/{chunk-64SE4X5G.js.map → chunk-DEBHXHJR.js.map} +0 -0
- /package/dist/{chunk-EHK6KZHK.js.map → chunk-DNHVPZOD.js.map} +0 -0
- /package/dist/{chunk-437S3G37.js.map → chunk-DQEMWVMT.js.map} +0 -0
- /package/dist/{chunk-LZZNTPLR.js.map → chunk-DX3XRGLH.js.map} +0 -0
- /package/dist/{chunk-DZKHSDOM.js.map → chunk-ES36HTSC.js.map} +0 -0
- /package/dist/{chunk-TN7THW5U.js.map → chunk-ET356KSB.js.map} +0 -0
- /package/dist/{chunk-YNDLCWXS.js.map → chunk-EZ25VE3G.js.map} +0 -0
- /package/dist/{chunk-DMSDUGDM.js.map → chunk-F7GAIWFA.js.map} +0 -0
- /package/dist/{chunk-G6XXLKC5.js.map → chunk-FFPJINJE.js.map} +0 -0
- /package/dist/{chunk-G4CN3ZXL.js.map → chunk-FUTF72MJ.js.map} +0 -0
- /package/dist/{chunk-HF77M34J.js.map → chunk-GFPZS3F5.js.map} +0 -0
- /package/dist/{chunk-G6NKALRN.js.map → chunk-H4WG3UQZ.js.map} +0 -0
- /package/dist/{chunk-UDQUSU27.js.map → chunk-HNZKVLAN.js.map} +0 -0
- /package/dist/{chunk-5EZXHU36.js.map → chunk-HYQJQGD3.js.map} +0 -0
- /package/dist/{chunk-TRWPCR6P.js.map → chunk-JECBQBEX.js.map} +0 -0
- /package/dist/{chunk-E6CBU7XP.js.map → chunk-JYIFGGEM.js.map} +0 -0
- /package/dist/{chunk-VA4WSW54.js.map → chunk-JYIJNNN3.js.map} +0 -0
- /package/dist/{chunk-L5HJQC36.js.map → chunk-K2TDK7GG.js.map} +0 -0
- /package/dist/{chunk-KDXVOFYY.js.map → chunk-KAVBJSBQ.js.map} +0 -0
- /package/dist/{chunk-4OKLXWDZ.js.map → chunk-KNB7IBBU.js.map} +0 -0
- /package/dist/{chunk-QLULYKWZ.js.map → chunk-KSXJOC4F.js.map} +0 -0
- /package/dist/{chunk-2S6QHZGJ.js.map → chunk-L2DPF4DF.js.map} +0 -0
- /package/dist/{chunk-JI5AVXYO.js.map → chunk-LEPOP46W.js.map} +0 -0
- /package/dist/{chunk-O7BBFJLP.js.map → chunk-LTAVSOZW.js.map} +0 -0
- /package/dist/{chunk-2IZAGAJR.js.map → chunk-LULR4IUW.js.map} +0 -0
- /package/dist/{chunk-WMWVO45V.js.map → chunk-MC6XO7T4.js.map} +0 -0
- /package/dist/{chunk-D6RIFG4O.js.map → chunk-MNB5RMAY.js.map} +0 -0
- /package/dist/{chunk-Q5WG43OP.js.map → chunk-MYFQ3ED4.js.map} +0 -0
- /package/dist/{chunk-V3UE5I5F.js.map → chunk-MYVPLJOO.js.map} +0 -0
- /package/dist/{chunk-MTWKDOVO.js.map → chunk-NLE6TSLG.js.map} +0 -0
- /package/dist/{chunk-DBRYEIGY.js.map → chunk-OJP3N7UK.js.map} +0 -0
- /package/dist/{chunk-SMX5267P.js.map → chunk-OZKOPQCM.js.map} +0 -0
- /package/dist/{chunk-JCK7V6SN.js.map → chunk-P65YJEEL.js.map} +0 -0
- /package/dist/{chunk-MTR7BZQN.js.map → chunk-PBGWYM3H.js.map} +0 -0
- /package/dist/{chunk-AXTXN4T6.js.map → chunk-PWFCHOB3.js.map} +0 -0
- /package/dist/{chunk-FDPZVY6D.js.map → chunk-QFN4U7AG.js.map} +0 -0
- /package/dist/{chunk-K2ZLHESQ.js.map → chunk-QIEUU4UK.js.map} +0 -0
- /package/dist/{chunk-3D6AFGQR.js.map → chunk-QVT3E4CE.js.map} +0 -0
- /package/dist/{chunk-SFQ6QNL7.js.map → chunk-R6YJI3HE.js.map} +0 -0
- /package/dist/{chunk-5CJVLG3H.js.map → chunk-RFDD3B7W.js.map} +0 -0
- /package/dist/{chunk-JBPKEARU.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-FNZQGN76.js.map → chunk-S2BBISHU.js.map} +0 -0
- /package/dist/{chunk-IALLX7EE.js.map → chunk-S2FSBU4H.js.map} +0 -0
- /package/dist/{chunk-7K5Q6COX.js.map → chunk-TVVEYCNW.js.map} +0 -0
- /package/dist/{chunk-DPAENM7O.js.map → chunk-U3ZAVRP3.js.map} +0 -0
- /package/dist/{chunk-4KJLYTLS.js.map → chunk-V57NLO5P.js.map} +0 -0
- /package/dist/{chunk-FLVL4L3L.js.map → chunk-VDX2J7OX.js.map} +0 -0
- /package/dist/{chunk-AJLLIIML.js.map → chunk-W4FBGYGK.js.map} +0 -0
- /package/dist/{chunk-6SXVCD7W.js.map → chunk-W7IGLX4G.js.map} +0 -0
- /package/dist/{chunk-KAWTOYAW.js.map → chunk-WLZYGLJ4.js.map} +0 -0
- /package/dist/{chunk-RO4LQGT3.js.map → chunk-WON4APQY.js.map} +0 -0
- /package/dist/{chunk-PQVK2S3J.js.map → chunk-WZFAPHIK.js.map} +0 -0
- /package/dist/{chunk-KQPJLK3X.js.map → chunk-XL24QQ63.js.map} +0 -0
- /package/dist/{chunk-RVZRYUQH.js.map → chunk-YROFNEG5.js.map} +0 -0
- /package/dist/{chunk-VRAD2FGO.js.map → chunk-Z54EM5YZ.js.map} +0 -0
- /package/dist/{first-start-migration-TI67YMLG.js.map → first-start-migration-CSRHCJIQ.js.map} +0 -0
- /package/dist/{forget-CQCLB5LB.js.map → forget-HRPLVB3W.js.map} +0 -0
- /package/dist/{purge-NDWV6WYD.js.map → purge-IRF47ZTX.js.map} +0 -0
- /package/dist/{tier-stats-KV7IWCJR.js.map → tier-stats-QEJSPFV2.js.map} +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/recall-state.ts"],"sourcesContent":["import { appendFile, mkdir, readFile, rename, rm, stat, unlink, writeFile } from \"node:fs/promises\";\nimport path from \"node:path\";\nimport { createHash, randomUUID } from \"node:crypto\";\nimport { log } from \"./logger.js\";\nimport { writeFileAtomically } from \"./maintenance/atomic-file.js\";\nimport { isErrnoCode } from \"./utils/errno.js\";\nimport { withHeldFileLock, type HeldFileLockOptions } from \"./utils/serialize-mutations.js\";\nimport { ensureContainedSpillDir, listContainedSpillFiles } from \"./utils/path-containment.js\";\nimport type { SearchDegradation } from \"./search/port.js\";\nimport type {\n IdentityInjectionMode,\n RecallPlanMode,\n RecallTierExplain,\n} from \"./types.js\";\n\nexport interface LastRecallBudgetSummary {\n requestedTopK?: number;\n appliedTopK: number;\n recallBudgetChars: number;\n maxMemoryTokens: number;\n qmdFetchLimit?: number;\n qmdHybridFetchLimit?: number;\n finalContextChars?: number;\n truncated?: boolean;\n includedSections?: string[];\n omittedSections?: string[];\n includedMemoryIds?: string[];\n includedMemoryPaths?: string[];\n includedMemoryNamespaces?: Array<string | undefined>;\n omittedMemoryIds?: string[];\n}\n\nexport interface LastRecallSnapshot {\n sessionKey: string;\n recordedAt: string;\n queryHash: string;\n queryLen: number;\n memoryIds: string[];\n namespace?: string;\n recallNamespaces?: string[];\n traceId?: string;\n plannerMode?: RecallPlanMode;\n requestedMode?: RecallPlanMode;\n source?: string;\n fallbackUsed?: boolean;\n sourcesUsed?: string[];\n budgetsApplied?: LastRecallBudgetSummary;\n latencyMs?: number;\n resultPaths?: string[];\n resultNamespaces?: Array<string | undefined>;\n policyVersion?: string;\n identityInjectionMode?: IdentityInjectionMode | \"none\";\n identityInjectedChars?: number;\n identityInjectionTruncated?: boolean;\n /**\n * Collision-safe write nonce. Random UUID set on every `record()`\n * call so the observation-mode direct-answer hook can detect stale\n * snapshots and avoid annotating a snapshot that a subsequent recall\n * already replaced (issue #518).\n */\n writeNonce?: string;\n /**\n * Optional tier-level explanation of how recall was served\n * (issue #518). Populated by orchestrator call sites that can\n * identify a concrete tier; surfaces expose the block via\n * `engram query --explain`, the `?explain=1` HTTP flag, and the\n * `remnic_recall_explain` MCP tool. Orthogonal to the existing\n * graph-path `recallExplain` operation.\n */\n tierExplain?: RecallTierExplain;\n /**\n * Backend degradations observed while serving this recall (issue #1536).\n * Present only when a search backend reported unavailable/loading/timeout\n * during the recall — distinguishing \"no matches\" from \"backend could not\n * answer\" (CLAUDE.md rule 34). Deliberately independent of `tierExplain`,\n * which is gated behind `recallDirectAnswerEnabled`.\n */\n backendDegradations?: SearchDegradation[];\n}\n\nexport interface GraphRecallExpandedEntry {\n path: string;\n score: number;\n namespace: string;\n seed: string;\n hopDepth: number;\n decayedWeight: number;\n graphType: \"entity\" | \"time\" | \"causal\";\n /**\n * Issue #681 PR 3/3 — confidence of the edge that produced this entry's\n * recorded provenance (strongest edge along the chosen entry path).\n * Range `[0, 1]`. Optional so persisted snapshots from older builds\n * round-trip through `clampGraphRecallExpandedEntries` without dropping.\n */\n edgeConfidence?: number;\n}\n\nexport function clampGraphRecallExpandedEntries(\n entries: unknown,\n maxEntries: number = 64,\n): GraphRecallExpandedEntry[] {\n const limit = Math.max(1, Math.floor(maxEntries));\n if (!Array.isArray(entries)) return [];\n return entries\n .filter((item): item is Record<string, unknown> => !!item && typeof item === \"object\")\n .map((item) => {\n const graphType: \"entity\" | \"time\" | \"causal\" =\n item.graphType === \"entity\" || item.graphType === \"time\" || item.graphType === \"causal\"\n ? item.graphType\n : \"entity\";\n const out: GraphRecallExpandedEntry = {\n path: typeof item.path === \"string\" ? item.path : \"\",\n score: typeof item.score === \"number\" && Number.isFinite(item.score) ? item.score : 0,\n namespace: typeof item.namespace === \"string\" ? item.namespace : \"\",\n seed: typeof item.seed === \"string\" ? item.seed : \"\",\n hopDepth:\n typeof item.hopDepth === \"number\" && Number.isFinite(item.hopDepth)\n ? Math.max(0, Math.floor(item.hopDepth))\n : 0,\n decayedWeight:\n typeof item.decayedWeight === \"number\" && Number.isFinite(item.decayedWeight)\n ? Math.max(0, item.decayedWeight)\n : 0,\n graphType,\n };\n // Issue #681 PR 3/3: clamp `edgeConfidence` into [0, 1] when present.\n // Older snapshots without the field round-trip cleanly via the\n // optional shape; legacy callers always rendered as 1.0.\n if (\n typeof item.edgeConfidence === \"number\" &&\n Number.isFinite(item.edgeConfidence)\n ) {\n out.edgeConfidence = Math.min(1, Math.max(0, item.edgeConfidence));\n }\n return out;\n })\n .filter((item) => item.path.length > 0 && item.namespace.length > 0)\n .slice(0, limit);\n}\n\ntype LastRecallState = Record<string, LastRecallSnapshot>;\ntype StateFileWriter = (filePath: string, content: string) => Promise<void>;\n\n/**\n * Deep-copy a RecallTierExplain block. Used by both the write path\n * (so caller mutation after `record()` cannot tear the persisted\n * snapshot) and the read path (so caller mutation after `get()` /\n * `getMostRecent()` cannot tear the in-memory store).\n *\n * Uses structuredClone so future additions to RecallTierExplain do\n * not silently share references through hand-enumerated fields —\n * matching the pattern used elsewhere in the codebase (e.g.,\n * qmd-recall-cache.ts). The payload is pure JSON-shaped data, so\n * structuredClone is both safe and complete here.\n */\n/**\n * Stale-snapshot identity guard shared by the annotate methods (issue #518):\n * a writeNonce match wins outright; otherwise traceId (when expected) and\n * recordedAt are compared. Extracted so every annotation surface applies\n * identical guards (CLAUDE.md rule 22).\n */\nfunction snapshotMatchesExpectedIdentity(\n current: LastRecallSnapshot,\n expected?: { writeNonce?: string; traceId?: string; recordedAt?: string },\n): boolean {\n if (!expected) return true;\n if (typeof expected.writeNonce === \"string\" && expected.writeNonce.length > 0) {\n return current.writeNonce === expected.writeNonce;\n }\n const hasExpectedTraceId =\n typeof expected.traceId === \"string\" && expected.traceId.length > 0;\n if (hasExpectedTraceId) {\n return current.traceId === expected.traceId;\n }\n if (expected.recordedAt !== undefined) {\n return current.recordedAt === expected.recordedAt;\n }\n return true;\n}\n\nfunction cloneTierExplain(\n tierExplain: RecallTierExplain | undefined,\n): RecallTierExplain | undefined {\n if (!tierExplain) return undefined;\n return structuredClone(tierExplain);\n}\n\n/**\n * Deep-copy a LastRecallSnapshot so callers that receive it cannot\n * mutate the store's internal state through mutable array/object\n * fields. Same structuredClone rationale as cloneTierExplain above.\n */\nfunction cloneLastRecallSnapshot(\n snapshot: LastRecallSnapshot | null,\n): LastRecallSnapshot | null {\n if (!snapshot) return null;\n return structuredClone(snapshot);\n}\n\nexport interface TierMigrationCycleSummary {\n trigger: \"extraction\" | \"maintenance\" | \"manual\";\n scanned: number;\n migrated: number;\n promoted: number;\n demoted: number;\n limit: number;\n dryRun: boolean;\n skipped?: string;\n errorCount?: number;\n}\n\nexport interface TierMigrationStatusSnapshot {\n updatedAt: string;\n lastCycle: TierMigrationCycleSummary | null;\n totals: {\n cycles: number;\n scanned: number;\n migrated: number;\n promoted: number;\n demoted: number;\n errors: number;\n };\n}\n\nconst DEFAULT_TIER_MIGRATION_STATUS: TierMigrationStatusSnapshot = {\n updatedAt: new Date(0).toISOString(),\n lastCycle: null,\n totals: {\n cycles: 0,\n scanned: 0,\n migrated: 0,\n promoted: 0,\n demoted: 0,\n errors: 0,\n },\n};\n\n/**\n * Suffix marking an impression spill CLAIMED for commit but not yet deleted.\n * The crash-safe drain renames `<uuid>.jsonl` -> `<uuid>.jsonl.claimed` before\n * committing its rows, mirroring the lifecycle ledger's claim/commit protocol\n * (#2033).\n */\nconst CLAIMED_IMPRESSION_SPILL_SUFFIX = \".claimed\";\n\n/**\n * Outcome of {@link LastRecallStore.drainPendingImpressions}. Distinguishes a\n * completed drain (or nothing pending) from a DEFERRED drain that left durable\n * spills in the offline-sync-EXCLUDED queue, so the caller can tell the\n * data-safe cases apart from the one where an offline-sync snapshot would\n * silently omit recorded impressions (#2033).\n */\nexport interface DrainPendingImpressionsResult {\n /** Pending spill rows were folded into the synced active file this call. */\n folded: boolean;\n /**\n * Durable spill rows remain in the offline-sync-EXCLUDED pending queue after\n * this drain: the rotation lock could not be acquired, a spill could not be\n * claimed, or the drain-only fold left rows that would only fit by rotating\n * into a sync-excluded archive. A snapshot taken now would silently omit them\n * (#2033): the caller MUST treat the active file as INCOMPLETE and retry or\n * abort the snapshot rather than report success. `false` means the active file\n * is complete — every pending row was folded or nothing was pending.\n */\n pendingDeferred: boolean;\n}\n\nexport class LastRecallStore {\n private readonly statePath: string;\n private readonly impressionsPath: string;\n private readonly writeStateFile: StateFileWriter;\n private readonly impressionsRotateBytes: number;\n private readonly impressionsRotateKeep: number;\n // Lock-acquisition timing for the cross-process impression rotation lock.\n // Only tests set this (small maxWaitMs) to force the acquisition-timeout\n // (`acquired=false`) branch deterministically; production uses the defaults.\n private readonly impressionsLockOptions?: Pick<HeldFileLockOptions, \"maxWaitMs\" | \"pollMs\">;\n private state: LastRecallState = {};\n private stateWriteChain: Promise<void> = Promise.resolve();\n // Serializes the rotate-then-append critical section so concurrent record()\n // calls never interleave rotation renames with each other's appends (#1910).\n private impressionsWriteChain: Promise<void> = Promise.resolve();\n\n constructor(\n memoryDir: string,\n options: {\n writeStateFile?: StateFileWriter;\n impressionsRotateBytes?: number;\n impressionsRotateKeep?: number;\n impressionsLockOptions?: Pick<HeldFileLockOptions, \"maxWaitMs\" | \"pollMs\">;\n } = {},\n ) {\n this.statePath = path.join(memoryDir, \"state\", \"last_recall.json\");\n this.impressionsPath = path.join(memoryDir, \"state\", \"recall_impressions.jsonl\");\n // 0 disables rotation (never coerced to a default); keep floors at 1.\n this.impressionsRotateBytes = Math.max(0, Math.floor(options.impressionsRotateBytes ?? 0));\n this.impressionsRotateKeep = Math.max(1, Math.floor(options.impressionsRotateKeep ?? 5));\n this.impressionsLockOptions = options.impressionsLockOptions;\n this.writeStateFile =\n options.writeStateFile ??\n (async (filePath, content) => {\n await writeFileAtomically(filePath, content);\n });\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw) as LastRecallState;\n if (parsed && typeof parsed === \"object\") this.state = parsed;\n } catch {\n this.state = {};\n }\n }\n\n get(sessionKey: string): LastRecallSnapshot | null {\n // Defensive copy: callers must not be able to mutate internal state\n // by reaching into array/object fields on the returned snapshot.\n return cloneLastRecallSnapshot(this.state[sessionKey] ?? null);\n }\n\n getMostRecent(): LastRecallSnapshot | null {\n const snapshots = Object.values(this.state);\n if (snapshots.length === 0) return null;\n // Secondary key on sessionKey keeps the sort stable when two\n // snapshots share a recordedAt timestamp (CLAUDE.md rule 19).\n snapshots.sort((a, b) => {\n const byTime = b.recordedAt.localeCompare(a.recordedAt);\n if (byTime !== 0) return byTime;\n return a.sessionKey.localeCompare(b.sessionKey);\n });\n return cloneLastRecallSnapshot(snapshots[0] ?? null);\n }\n\n /**\n * Persist last-recall snapshot and append an impression log entry.\n * Does not store raw query text; uses a stable hash for correlation.\n */\n async record(opts: {\n sessionKey: string;\n query: string;\n memoryIds: string[];\n namespace?: string;\n recallNamespaces?: string[];\n traceId?: string;\n plannerMode?: RecallPlanMode;\n requestedMode?: RecallPlanMode;\n source?: string;\n fallbackUsed?: boolean;\n sourcesUsed?: string[];\n budgetsApplied?: LastRecallBudgetSummary;\n latencyMs?: number;\n resultPaths?: string[];\n resultNamespaces?: Array<string | undefined>;\n policyVersion?: string;\n appendImpression?: boolean;\n identityInjection?: {\n mode: IdentityInjectionMode | \"none\";\n injectedChars: number;\n truncated: boolean;\n };\n /**\n * Per-tier explain annotation (issue #518). When supplied, the\n * snapshot carries it so downstream surfaces (CLI / HTTP / MCP)\n * can render which retrieval tier served the query.\n */\n tierExplain?: RecallTierExplain;\n /**\n * Backend degradations observed while serving this recall (issue #1536).\n * Passed at record time so the published snapshot is born annotated —\n * a post-record annotation would leave a window where readers see the\n * snapshot without them (codex review on #1544).\n */\n backendDegradations?: SearchDegradation[];\n }): Promise<void> {\n const now = new Date().toISOString();\n const queryHash = createHash(\"sha256\").update(opts.query).digest(\"hex\");\n\n // Build the snapshot from opts, then deep-copy it via\n // cloneLastRecallSnapshot so caller arrays/objects passed in\n // `opts` cannot retain a live reference to the persisted state and\n // tear it after `record()` returns.\n const liveSnapshot: LastRecallSnapshot = {\n sessionKey: opts.sessionKey,\n recordedAt: now,\n queryHash,\n writeNonce: randomUUID(),\n queryLen: opts.query.length,\n memoryIds: opts.memoryIds,\n namespace: opts.namespace,\n recallNamespaces: opts.recallNamespaces,\n traceId: opts.traceId,\n plannerMode: opts.plannerMode,\n requestedMode: opts.requestedMode,\n source: opts.source,\n fallbackUsed: opts.fallbackUsed,\n sourcesUsed: opts.sourcesUsed,\n budgetsApplied: opts.budgetsApplied,\n latencyMs: opts.latencyMs,\n resultPaths: opts.resultPaths,\n resultNamespaces: opts.resultNamespaces,\n policyVersion: opts.policyVersion,\n identityInjectionMode: opts.identityInjection?.mode,\n identityInjectedChars: opts.identityInjection?.injectedChars,\n identityInjectionTruncated: opts.identityInjection?.truncated,\n tierExplain: opts.tierExplain,\n backendDegradations:\n opts.backendDegradations && opts.backendDegradations.length > 0\n ? opts.backendDegradations\n : undefined,\n };\n // `cloneLastRecallSnapshot` handles `null` but that never applies\n // at this call site — the non-null assertion keeps the type\n // checker honest.\n const snapshot = cloneLastRecallSnapshot(liveSnapshot)!;\n\n this.state[opts.sessionKey] = snapshot;\n\n // Keep the state bounded; the impression log is append-only.\n const keys = Object.keys(this.state);\n if (keys.length > 50) {\n const ordered = keys\n .map((k) => ({ k, at: this.state[k]?.recordedAt ?? \"\" }))\n .sort((a, b) => b.at.localeCompare(a.at));\n for (const doomed of ordered.slice(50)) {\n delete this.state[doomed.k];\n }\n }\n\n try {\n await this.flushState();\n } catch (err) {\n log.debug(`last recall store write failed: ${err}`);\n }\n\n if (opts.appendImpression !== false) {\n const line = JSON.stringify(snapshot) + \"\\n\";\n // Chain onto the previous impression write so rotation + append run as one\n // serialized critical section — concurrent record() calls can never\n // interleave a rename with another call's append (#1910). `.catch` before\n // the link keeps a prior failure from poisoning the chain.\n const chained = this.impressionsWriteChain\n .catch(() => {})\n .then(() => this.appendImpressionSerialized(line));\n this.impressionsWriteChain = chained;\n try {\n await chained;\n } catch (err) {\n log.debug(`recall impressions append failed: ${err}`);\n }\n }\n }\n\n /**\n * Drain pending spills, rotate (best-effort, sized to the projected payload),\n * then append one impression line under ONE shared cross-process lock (#1910,\n * #2033). Both the archive-shift renames AND the append run inside the same\n * held lock so a peer process holding the lock can never rename the active\n * inode to `.1` between our open and write — which would land the impression in\n * a rotated archive that offline-sync excludes, silently dropping it from\n * active-state/sync consumers.\n *\n * On lock-acquisition timeout the impression is NEVER written to the active\n * file unlocked (#2033): a peer holding the lock is likely mid-rotation, so an\n * unlocked append can land in the inode it is about to rename to `.1` — the\n * exact silent-drop this lock prevents. Instead the row is spilled to a\n * durable node-local per-event file under `<impressions>.pending.d/` and\n * folded back into the active file by the next append that DOES hold the lock,\n * preserving durability without racing rotation. Rotation failure under the\n * held lock is logged and the append still runs. Callers invoke this only\n * through `impressionsWriteChain` so the sequence is serialized in-process.\n */\n private get impressionsPendingDir(): string {\n return `${this.impressionsPath}.pending.d`;\n }\n\n private async spillImpression(line: string): Promise<void> {\n await ensureContainedSpillDir(this.impressionsPendingDir);\n // Write to a temp name the drain's `.jsonl` lister ignores, then atomically\n // rename to the final `<uuid>.jsonl` (#2033). writeFile creates the path\n // before its bytes are durable, so writing straight to the final name lets a\n // concurrent lock holder's drain read/rename/delete a partial spill and\n // append malformed JSON — permanently losing that impression. The temp lives\n // in the SAME contained dir, so the rename is atomic and stays symlink-safe.\n const id = randomUUID();\n const tempPath = path.join(this.impressionsPendingDir, `${id}.jsonl.tmp`);\n const finalPath = path.join(this.impressionsPendingDir, `${id}.jsonl`);\n await writeFile(tempPath, line, \"utf-8\");\n await rename(tempPath, finalPath);\n }\n\n /**\n * Recover a claim a crashed drain left mid-flight (#2033): the crash-safe\n * drain renames `<uuid>.jsonl` -> `<uuid>.jsonl.claimed` BEFORE committing, so\n * a `.claimed` file with no matching commit is the ONLY durable copy of those\n * rows. Rename each orphan back to `<uuid>.jsonl` so it re-enters the normal\n * collect+claim+commit flow. MUST run under the held rotation lock, before\n * collecting. listContainedSpillFiles skips symlinked/escaping entries.\n */\n private async recoverOrphanedImpressionClaims(): Promise<void> {\n const orphans = await listContainedSpillFiles(\n this.impressionsPendingDir,\n `.jsonl${CLAIMED_IMPRESSION_SPILL_SUFFIX}`,\n );\n for (const claimedPath of orphans) {\n const original = claimedPath.slice(0, -CLAIMED_IMPRESSION_SPILL_SUFFIX.length);\n await rename(claimedPath, original).catch(() => undefined);\n }\n }\n\n /**\n * Recover a crash-orphaned spill temp after its write completed but before\n * the atomic `.tmp` → `.jsonl` rename. Valid JSONL temps are promoted back\n * into the normal queue; incomplete temps remain pending and keep offline sync\n * deferred rather than being discarded.\n */\n private async recoverOrphanedImpressionTemps(): Promise<void> {\n const temps = await listContainedSpillFiles(this.impressionsPendingDir, \".jsonl.tmp\");\n for (const tempPath of temps) {\n let content: string;\n try {\n content = await readFile(tempPath, \"utf-8\");\n for (const line of content.split(\"\\n\")) {\n if (line.trim().length > 0) JSON.parse(line);\n }\n } catch {\n continue;\n }\n const finalPath = tempPath.slice(0, -\".tmp\".length);\n await rename(tempPath, finalPath).catch(() => undefined);\n }\n }\n\n private async appendImpressionSerialized(line: string): Promise<void> {\n await mkdir(path.dirname(this.impressionsPath), { recursive: true });\n // Every active-file write goes under the shared cross-process rotation lock,\n // even when THIS writer's local rotation is disabled (`impressionsRotateBytes\n // <= 0`). A peer process with rotation enabled shares this lock and may\n // rename the active inode to `.1` at any moment, so an unlocked append could\n // land in an offline-sync-excluded archive and be silently dropped (#2033).\n // Only the local rotate DECISION is disabled — the bounded fold skips\n // rotation when this writer's limit is 0 — the lock itself is not.\n const lockPath = `${this.impressionsPath}.lock`;\n await withHeldFileLock(\n lockPath,\n { staleMs: 30_000, ...this.impressionsLockOptions },\n async (acquired) => {\n // withHeldFileLock falls back to task(false) when it cannot acquire the\n // lock within the budget. Do NOT append to the active file unlocked: a\n // peer holding the lock may be mid-rotation, so an unlocked append could\n // land in the inode it renames to `.1` (an offline-sync-excluded\n // archive), silently dropping the impression. Spill it to the durable\n // pending queue instead — the next lock holder folds it back in (#2033).\n if (!acquired) {\n log.debug(\"recall impressions rotation lock not acquired; spilling impression to the durable pending queue\");\n await this.spillImpression(line);\n return;\n }\n await this.foldPendingImpressionsAndAppend(line);\n },\n );\n }\n\n /**\n * Fold any durable pending recall-impression spills into the synced active\n * `recall_impressions.jsonl` WITHOUT recording a new impression (#2033).\n *\n * The pending spill dir is offline-sync-excluded, so an impression that a\n * lock-timed-out `record()` spilled there is absent from an offline-sync\n * snapshot and lost if this node is discarded before the next `record()`\n * folds it back. Offline sync calls this before building a snapshot so a\n * recorded impression always reaches the remote. Fast no-op — no lock and no\n * dir/lock-file creation — when nothing is pending.\n *\n * Returns a {@link DrainPendingImpressionsResult}: `folded` is true when rows\n * were folded into the active file; `pendingDeferred` is true when durable\n * spills still remain in the offline-sync-EXCLUDED queue after this call —\n * because the rotation lock could not be acquired, a spill could not be\n * claimed, or the drain-only fold deferred rows that would only fit by\n * rotating into a sync-excluded archive (#2033). A snapshot taken while\n * `pendingDeferred` is true would silently drop those rows, so the caller MUST\n * NOT report a clean snapshot — it either retries or aborts.\n */\n async drainPendingImpressions(): Promise<DrainPendingImpressionsResult> {\n if (!(await this.pendingSpillsRemain())) {\n return { folded: false, pendingDeferred: false };\n }\n const lockPath = `${this.impressionsPath}.lock`;\n let folded = false;\n let acquiredLock = false;\n let spillsRemain = false;\n await withHeldFileLock(\n lockPath,\n { staleMs: 30_000, ...this.impressionsLockOptions },\n async (acquired) => {\n // A peer holds the lock (mid-rotation or mid-append). We MUST NOT touch\n // the active file unlocked (#2033), so the spills stay in the\n // offline-sync-EXCLUDED pending queue. Report the drain as DEFERRED\n // (pendingDeferred=true) so the caller does not build a snapshot that\n // silently omits them; the next lock holder — or a caller retry — folds\n // them in.\n if (!acquired) return;\n acquiredLock = true;\n folded = await this.foldPendingImpressionsAndAppend(null);\n // Even WITH the lock, a spill the fold could not claim or a `.claimed`\n // orphan a failed commit left behind keeps durable rows in the excluded\n // queue. Treat that as an incomplete drain so the caller retries/aborts\n // rather than snapshotting an active file that omits them (#2033).\n spillsRemain = await this.pendingSpillsRemain();\n },\n );\n return { folded, pendingDeferred: !acquiredLock || spillsRemain };\n }\n\n /**\n * Claim/commit fold of durable pending impression spills into the active file\n * under the held rotation lock (#2033). `line` is a new impression to append\n * after the drained rows, or null for a drain-only pre-sync fold.\n *\n * Each spill is folded as an INDEPENDENT claim -> append -> finalize unit\n * rather than materializing the whole queue as one joined payload and\n * splitting it in a single synchronous pass (#2033). A multi-hundred-MB drain\n * done as one join/split blocks the event loop long enough for\n * `withHeldFileLock`'s ownership-refresh timer to miss its window, so a peer\n * stale-breaks the 30s lock and rotates/appends concurrently — defeating the\n * rotation lock this drain relies on. The per-file `await`s keep the payload\n * bounded to one spill at a time and let the refresh timer fire between files.\n *\n * The DRAIN-ONLY path (`line === null`, run before an offline-sync snapshot)\n * NEVER rotates a drained row into an archive. `recall_impressions.jsonl.*`\n * is offline-sync-EXCLUDED, so rotating a just-drained row into `.1`/`.2` and\n * then deleting its spill would leave that row only in a path sync omits —\n * silently lost when the node is discarded after a \"successful\" sync (#2033).\n * It folds only the rows that fit the synced active file under the cap and\n * leaves the rest durable in the pending queue; {@link drainPendingImpressions}\n * then reports the drain DEFERRED so the caller retries or aborts. The\n * record() path (`line !== null`) keeps rotating normally — its archives stay\n * on a live node that is not being discarded.\n *\n * Recovers any crash-orphaned claim first. Each impression carries a unique\n * writeNonce, so a crash-recovered re-commit is a collapsible duplicate, never\n * a lost row. listContainedSpillFiles rejects symlinked/escaping entries; a\n * spill that cannot be claimed is skipped this pass. An append failure rolls\n * that spill's claim back so the row retries on the next lock holder's drain.\n * Returns true when the active file was written. MUST run under the held\n * rotation lock.\n */\n private async foldPendingImpressionsAndAppend(line: string | null): Promise<boolean> {\n await this.recoverOrphanedImpressionTemps();\n await this.recoverOrphanedImpressionClaims();\n const spillFiles = await listContainedSpillFiles(this.impressionsPendingDir);\n const drainOnly = line === null;\n const cap = this.impressionsRotateBytes;\n let activeSize = 0;\n if (cap > 0) {\n try {\n activeSize = (await stat(this.impressionsPath)).size;\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n }\n }\n let wrote = false;\n for (const filePath of spillFiles) {\n const content = await readFile(filePath, \"utf-8\");\n const unit = content.length === 0 || content.endsWith(\"\\n\") ? content : `${content}\\n`;\n const unitBytes = Buffer.byteLength(unit, \"utf-8\");\n // Drain-only fold must never push a drained row into a sync-excluded\n // archive (#2033). Once the active file cannot take this spill under the\n // cap without rotating, stop: the remaining spills stay durable in the\n // pending queue and the drain reports itself deferred. A lone spill larger\n // than the cap on an empty active file is still folded whole (it cannot be\n // split without corrupting JSONL) so it reaches sync rather than stranding.\n if (drainOnly && cap > 0 && activeSize > 0 && activeSize + unitBytes >= cap) break;\n const claimedPath = `${filePath}${CLAIMED_IMPRESSION_SPILL_SUFFIX}`;\n try {\n await rename(filePath, claimedPath);\n } catch {\n continue; // could not claim → do not commit; a later drain retries it.\n }\n try {\n activeSize = await this.appendImpressionUnit(unit, activeSize, drainOnly);\n } catch (err) {\n // Commit failed: roll this spill's claim back so it retries on the next\n // lock holder's drain instead of being lost.\n await rename(claimedPath, filePath).catch(() => undefined);\n throw err;\n }\n // Commit is durable: delete the claimed file. A delete that fails leaves a\n // `.claimed` orphan the next drain recovers and re-commits — a\n // writeNonce-collapsible duplicate, never a lost row (#2033).\n await unlink(claimedPath).catch(() => undefined);\n wrote = true;\n }\n if (line !== null) {\n activeSize = await this.appendImpressionUnit(line, activeSize, false);\n wrote = true;\n }\n return wrote;\n }\n\n /**\n * Append one whole JSONL unit (a claimed spill's rows or a fresh impression\n * line) to the active impressions file, returning the resulting active-file\n * byte size. On the rotating (record) path, when the unit would push the\n * current active generation to/over `impressionsRotateBytes`, the full active\n * file is rotated aside FIRST so no generation exceeds the cap (#2033); a lone\n * unit larger than the cap on an empty active file is written whole because\n * splitting a JSONL row would corrupt it. `drainOnly` and disabled rotation\n * (`impressionsRotateBytes <= 0`) both skip rotation — drain-only defers its\n * overflow in {@link foldPendingImpressionsAndAppend} rather than rotating into\n * a sync-excluded archive. A rotation error is logged and the append still\n * runs so a row is never lost; an append failure propagates so the caller\n * rolls its claim back. MUST run under the held rotation lock.\n */\n private async appendImpressionUnit(\n unit: string,\n activeSize: number,\n drainOnly: boolean,\n ): Promise<number> {\n const cap = this.impressionsRotateBytes;\n const unitBytes = Buffer.byteLength(unit, \"utf-8\");\n if (cap > 0 && !drainOnly && activeSize > 0 && activeSize + unitBytes >= cap) {\n try {\n await this.shiftImpressionArchives();\n activeSize = 0;\n } catch (err) {\n log.debug(`recall impressions rotation failed (append preserved): ${err}`);\n }\n }\n await appendFile(this.impressionsPath, unit, \"utf-8\");\n return activeSize + unitBytes;\n }\n\n /**\n * True when any live `<uuid>.jsonl` spill, crash-orphaned `.claimed` file,\n * or crash-orphaned `.jsonl.tmp` spill remains in the offline-sync-EXCLUDED\n * pending queue (#2033). After a drain acquires the rotation lock, a spill\n * the fold could not claim (rename race / read-only dir) or a `.claimed`\n * orphan a failed commit left behind means durable rows are STILL excluded\n * from a snapshot — the drain must report itself INCOMPLETE so the caller\n * retries or aborts rather than snapshotting an active file that omits them.\n */\n private async pendingSpillsRemain(): Promise<boolean> {\n if ((await listContainedSpillFiles(this.impressionsPendingDir, \".jsonl.tmp\")).length > 0) {\n return true;\n }\n const liveSpills = await listContainedSpillFiles(this.impressionsPendingDir);\n if (liveSpills.length > 0) return true;\n const claimed = await listContainedSpillFiles(\n this.impressionsPendingDir,\n `.jsonl${CLAIMED_IMPRESSION_SPILL_SUFFIX}`,\n );\n return claimed.length > 0;\n }\n\n /**\n * Shift `.1..N` archives down one slot and move the active file to `.1`,\n * dropping anything beyond `keep`. Callers invoke this only while holding the\n * cross-process rotation lock (issue #1910).\n */\n private async shiftImpressionArchives(): Promise<void> {\n const keep = this.impressionsRotateKeep;\n // Drop the archive that would fall off the end, then shift down: .(keep-1)\n // -> .keep, ..., .1 -> .2, active -> .1.\n try {\n await rm(`${this.impressionsPath}.${keep}`, { force: true });\n } catch {\n // best-effort cleanup of the oldest archive\n }\n for (let i = keep - 1; i >= 1; i -= 1) {\n try {\n await rename(`${this.impressionsPath}.${i}`, `${this.impressionsPath}.${i + 1}`);\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n }\n }\n try {\n await rename(this.impressionsPath, `${this.impressionsPath}.1`);\n } catch (err) {\n if (!isErrnoCode(err, \"ENOENT\")) throw err;\n }\n }\n\n /**\n * Attach a RecallTierExplain block to the existing snapshot for a\n * session without rewriting the entire snapshot. Used by the\n * post-recall direct-answer annotation path (issue #518 slice 3c):\n * recallInternal records the snapshot first, then the orchestrator\n * fires the direct-answer tier in observation mode and annotates\n * the stored snapshot with whichever tier served the query.\n *\n * No-op when no snapshot exists for the given session; callers do\n * not need to guard on existence.\n */\n async annotateTierExplain(\n sessionKey: string,\n tierExplain: RecallTierExplain,\n expected?: { writeNonce?: string; traceId?: string; recordedAt?: string },\n ): Promise<void> {\n const current = this.state[sessionKey];\n if (!current) return;\n if (!snapshotMatchesExpectedIdentity(current, expected)) return;\n this.state[sessionKey] = {\n ...current,\n tierExplain: cloneTierExplain(tierExplain),\n };\n try {\n await this.flushState();\n } catch (err) {\n log.debug(`last recall tier-explain annotate failed: ${err}`);\n }\n }\n\n\n private flushState(): Promise<void> {\n const run = this.stateWriteChain.catch(() => undefined).then(async () => {\n await mkdir(path.dirname(this.statePath), { recursive: true });\n await this.writeStateFile(this.statePath, JSON.stringify(this.state, null, 2));\n });\n this.stateWriteChain = run.then(\n () => undefined,\n () => undefined,\n );\n return run;\n }\n}\n\nexport class TierMigrationStatusStore {\n private readonly statePath: string;\n private state: TierMigrationStatusSnapshot = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n\n constructor(memoryDir: string) {\n this.statePath = path.join(memoryDir, \"state\", \"tier-migration-status.json\");\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw) as Partial<TierMigrationStatusSnapshot> | null;\n if (!parsed || typeof parsed !== \"object\") {\n this.state = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n return;\n }\n const totals = parsed.totals && typeof parsed.totals === \"object\"\n ? parsed.totals\n : DEFAULT_TIER_MIGRATION_STATUS.totals;\n this.state = {\n updatedAt:\n typeof parsed.updatedAt === \"string\" && parsed.updatedAt.length > 0\n ? parsed.updatedAt\n : DEFAULT_TIER_MIGRATION_STATUS.updatedAt,\n lastCycle:\n parsed.lastCycle && typeof parsed.lastCycle === \"object\"\n ? (parsed.lastCycle as TierMigrationCycleSummary)\n : null,\n totals: {\n cycles: typeof totals.cycles === \"number\" && Number.isFinite(totals.cycles) ? totals.cycles : 0,\n scanned: typeof totals.scanned === \"number\" && Number.isFinite(totals.scanned) ? totals.scanned : 0,\n migrated: typeof totals.migrated === \"number\" && Number.isFinite(totals.migrated) ? totals.migrated : 0,\n promoted: typeof totals.promoted === \"number\" && Number.isFinite(totals.promoted) ? totals.promoted : 0,\n demoted: typeof totals.demoted === \"number\" && Number.isFinite(totals.demoted) ? totals.demoted : 0,\n errors: typeof totals.errors === \"number\" && Number.isFinite(totals.errors) ? totals.errors : 0,\n },\n };\n } catch {\n this.state = structuredClone(DEFAULT_TIER_MIGRATION_STATUS);\n }\n }\n\n get(): TierMigrationStatusSnapshot {\n return {\n updatedAt: this.state.updatedAt,\n lastCycle: this.state.lastCycle ? { ...this.state.lastCycle } : null,\n totals: { ...this.state.totals },\n };\n }\n\n async recordCycle(summary: TierMigrationCycleSummary): Promise<void> {\n const now = new Date().toISOString();\n const migratedDelta = summary.dryRun ? 0 : Math.max(0, summary.migrated);\n const promotedDelta = summary.dryRun ? 0 : Math.max(0, summary.promoted);\n const demotedDelta = summary.dryRun ? 0 : Math.max(0, summary.demoted);\n const next: TierMigrationStatusSnapshot = {\n updatedAt: now,\n lastCycle: { ...summary },\n totals: {\n cycles: this.state.totals.cycles + 1,\n scanned: this.state.totals.scanned + Math.max(0, summary.scanned),\n migrated: this.state.totals.migrated + migratedDelta,\n promoted: this.state.totals.promoted + promotedDelta,\n demoted: this.state.totals.demoted + demotedDelta,\n errors: this.state.totals.errors + Math.max(0, summary.errorCount ?? 0),\n },\n };\n this.state = next;\n try {\n await mkdir(path.dirname(this.statePath), { recursive: true });\n await writeFile(this.statePath, JSON.stringify(next, null, 2), \"utf-8\");\n } catch (err) {\n log.debug(`tier migration status write failed: ${err}`);\n }\n }\n}\n\n\n/**\n * Per-session bounded history of recent recall memory-id sets, used ONLY by\n * handle resolution (issue #1582). Distinct from {@link LastRecallStore} —\n * that keeps ONE last snapshot per session; this keeps a small ring (depth N)\n * of the memory-id arrays a session has recalled, newest first, so a handle\n * cited in a later turn still resolves even after a newer recall displaced the\n * \"last\" snapshot.\n *\n * Deliberately lightweight: stores only `string[]` per entry (no full\n * snapshot), capped at `depth` per session and 50 sessions total (rule 27\n * slice/cap guards). Misses are acceptable and tagged at resolution time.\n */\nexport class RecallHandleHistoryStore {\n private readonly statePath: string;\n private readonly writeStateFile: StateFileWriter;\n private state: Record<string, Array<{ at: string; ids: string[] }>> = {};\n private writeChain: Promise<void> = Promise.resolve();\n private readonly maxDepth: number;\n\n constructor(memoryDir: string, options: { writeStateFile?: StateFileWriter; maxDepth?: number } = {}) {\n this.statePath = path.join(memoryDir, \"state\", \"handle_history.json\");\n this.writeStateFile =\n options.writeStateFile ??\n (async (filePath, content) => {\n await writeFileAtomically(filePath, content);\n });\n this.maxDepth =\n typeof options.maxDepth === \"number\" && Number.isFinite(options.maxDepth)\n ? Math.max(1, Math.min(50, Math.floor(options.maxDepth)))\n : 5;\n }\n\n async load(): Promise<void> {\n try {\n const raw = await readFile(this.statePath, \"utf-8\");\n const parsed = JSON.parse(raw);\n if (parsed && typeof parsed === \"object\") this.state = parsed as typeof this.state;\n } catch {\n this.state = {};\n }\n }\n\n /**\n * Record one recall's admitted memory ids for a session, newest first.\n * The ring is capped at {@link maxDepth}; older entries drop off the tail.\n */\n async record(sessionKey: string, memoryIds: readonly string[]): Promise<void> {\n if (!sessionKey) return;\n const ids = memoryIds.filter((id): id is string => typeof id === \"string\" && id.length > 0);\n const entry = { at: new Date().toISOString(), ids };\n const prior = this.state[sessionKey] ?? [];\n const next = [entry, ...prior].slice(0, this.maxDepth);\n this.state[sessionKey] = next;\n this.capSessions();\n try {\n await this.flush();\n } catch (err) {\n log.debug(`recall handle history write failed: ${err}`);\n }\n }\n\n /**\n * Return the memory-id arrays for a session, newest first, capped at `depth`.\n * Empty array when the session has no recorded history.\n */\n recent(sessionKey: string, depth: number = this.maxDepth): Array<readonly string[]> {\n const entries = this.state[sessionKey];\n if (!entries || entries.length === 0) return [];\n const limit = Math.max(0, Math.min(depth, entries.length));\n return entries.slice(0, limit).map((e) => e.ids);\n }\n\n /** Test seam: drop all history (used by the corpus-scan hygiene test). */\n clearForTest(): void {\n this.state = {};\n }\n\n private capSessions(): void {\n const keys = Object.keys(this.state);\n if (keys.length <= 50) return;\n const ordered = keys\n .map((k) => ({ k, at: this.state[k]?.[0]?.at ?? \"\" }))\n .sort((a, b) => b.at.localeCompare(a.at));\n for (const doomed of ordered.slice(50)) {\n delete this.state[doomed.k];\n }\n }\n\n private flush(): Promise<void> {\n const run = this.writeChain.catch(() => undefined).then(async () => {\n await mkdir(path.dirname(this.statePath), { recursive: true });\n await this.writeStateFile(this.statePath, JSON.stringify(this.state, null, 2));\n });\n this.writeChain = run.then(() => undefined, () => undefined);\n return run;\n }\n}\n"],"mappings":"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","names":[]}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import {
|
|
2
|
+
composeMemoryEnvelope
|
|
3
|
+
} from "./chunk-CGASUJVP.js";
|
|
4
|
+
import {
|
|
5
|
+
log
|
|
6
|
+
} from "./chunk-3WCASNQZ.js";
|
|
7
|
+
|
|
8
|
+
// src/salvage-envelope.ts
|
|
9
|
+
function composeSalvagedEnvelope(label, input, ctx) {
|
|
10
|
+
const envelope = composeMemoryEnvelope(input, ctx, { salvage: true });
|
|
11
|
+
if (envelope.salvageNotes.length > 0) {
|
|
12
|
+
log.warn(`${label} write salvaged invalid fields: ${envelope.salvageNotes.join("; ")}`);
|
|
13
|
+
}
|
|
14
|
+
return envelope;
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export {
|
|
18
|
+
composeSalvagedEnvelope
|
|
19
|
+
};
|
|
20
|
+
//# sourceMappingURL=chunk-FQC3DHH2.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/salvage-envelope.ts"],"sourcesContent":["import {\n composeMemoryEnvelope,\n type MemoryWriteInput,\n type SealedMemoryEnvelope,\n type WriteContext,\n} from \"./write-envelope.js\";\nimport { log } from \"./logger.js\";\n\n/**\n * Shared salvage-compose helper for MACHINE-GENERATED or replayed-from-store\n * write input (issue #1989 PR4): one malformed optional field must not abort\n * the surrounding batch/action, and every drop is warn-logged with the\n * caller's label — visible, never silent (rule 34).\n *\n * Operator/system-built input must NOT use this — compose strict so caller\n * bugs surface (see AGENTS.md \"Sealed memory-write envelope\").\n */\nexport function composeSalvagedEnvelope(\n label: string,\n input: MemoryWriteInput,\n ctx: WriteContext,\n): SealedMemoryEnvelope {\n const envelope = composeMemoryEnvelope(input, ctx, { salvage: true });\n if (envelope.salvageNotes.length > 0) {\n log.warn(`${label} write salvaged invalid fields: ${envelope.salvageNotes.join(\"; \")}`);\n }\n return envelope;\n}\n"],"mappings":";;;;;;;;AAiBO,SAAS,wBACd,OACA,OACA,KACsB;AACtB,QAAM,WAAW,sBAAsB,OAAO,KAAK,EAAE,SAAS,KAAK,CAAC;AACpE,MAAI,SAAS,aAAa,SAAS,GAAG;AACpC,QAAI,KAAK,GAAG,KAAK,mCAAmC,SAAS,aAAa,KAAK,IAAI,CAAC,EAAE;AAAA,EACxF;AACA,SAAO;AACT;","names":[]}
|
|
@@ -1,38 +1,38 @@
|
|
|
1
|
+
import {
|
|
2
|
+
RemoteSearchBackend
|
|
3
|
+
} from "./chunk-3Y224NYC.js";
|
|
4
|
+
import {
|
|
5
|
+
EmbedHelper
|
|
6
|
+
} from "./chunk-ANEUPF6O.js";
|
|
1
7
|
import {
|
|
2
8
|
LanceDbBackend
|
|
3
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-BLAKS3CP.js";
|
|
4
10
|
import {
|
|
5
11
|
MeilisearchBackend
|
|
6
|
-
} from "./chunk-
|
|
12
|
+
} from "./chunk-S2BBISHU.js";
|
|
7
13
|
import {
|
|
8
14
|
NoopSearchBackend
|
|
9
15
|
} from "./chunk-CYEPCZN5.js";
|
|
10
16
|
import {
|
|
11
17
|
OramaBackend
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import {
|
|
14
|
-
RemoteSearchBackend
|
|
15
|
-
} from "./chunk-LRNMRXJO.js";
|
|
16
|
-
import {
|
|
17
|
-
EmbedHelper
|
|
18
|
-
} from "./chunk-FNMFJWBY.js";
|
|
18
|
+
} from "./chunk-ES36HTSC.js";
|
|
19
19
|
import {
|
|
20
20
|
createConversationIndexBackend
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-LEPOP46W.js";
|
|
22
22
|
import {
|
|
23
23
|
FaissConversationIndexAdapter
|
|
24
|
-
} from "./chunk-
|
|
24
|
+
} from "./chunk-ET356KSB.js";
|
|
25
25
|
import {
|
|
26
26
|
QmdClient
|
|
27
|
-
} from "./chunk-
|
|
27
|
+
} from "./chunk-QJAQNXWI.js";
|
|
28
28
|
import {
|
|
29
29
|
resolveIndexingCapabilities,
|
|
30
30
|
resolvePipelineProcessingCapabilities,
|
|
31
31
|
resolveQmdCapabilities
|
|
32
|
-
} from "./chunk-
|
|
32
|
+
} from "./chunk-SCCO46KZ.js";
|
|
33
33
|
import {
|
|
34
34
|
log
|
|
35
|
-
} from "./chunk-
|
|
35
|
+
} from "./chunk-3WCASNQZ.js";
|
|
36
36
|
|
|
37
37
|
// src/search/factory.ts
|
|
38
38
|
import path from "path";
|
|
@@ -175,4 +175,4 @@ export {
|
|
|
175
175
|
createConversationSearchBackend,
|
|
176
176
|
createConversationIndexRuntime
|
|
177
177
|
};
|
|
178
|
-
//# sourceMappingURL=chunk-
|
|
178
|
+
//# sourceMappingURL=chunk-FUTF72MJ.js.map
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
isErrnoCode
|
|
3
|
+
} from "./chunk-5UZXUTVO.js";
|
|
4
|
+
|
|
5
|
+
// src/utils/path-containment.ts
|
|
6
|
+
import path from "path";
|
|
7
|
+
import { lstat, mkdir, readdir, realpath } from "fs/promises";
|
|
8
|
+
function pathIsInside(parent, child) {
|
|
9
|
+
const relative = path.relative(parent, child);
|
|
10
|
+
return relative === "" || !relative.startsWith("..") && !path.isAbsolute(relative);
|
|
11
|
+
}
|
|
12
|
+
function assertPathInsideRoot(rootReal, candidateReal, originalPath) {
|
|
13
|
+
if (!pathIsInside(rootReal, candidateReal)) {
|
|
14
|
+
throw new Error(`Refusing to scan memory path outside memoryDir: ${originalPath}`);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
async function listContainedSpillFiles(dir, suffix = ".jsonl") {
|
|
18
|
+
let dirReal;
|
|
19
|
+
try {
|
|
20
|
+
const dirStat = await lstat(dir);
|
|
21
|
+
if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) return [];
|
|
22
|
+
dirReal = await realpath(dir);
|
|
23
|
+
} catch (err) {
|
|
24
|
+
if (isErrnoCode(err, "ENOENT")) return [];
|
|
25
|
+
throw err;
|
|
26
|
+
}
|
|
27
|
+
let names;
|
|
28
|
+
try {
|
|
29
|
+
names = (await readdir(dir)).filter((name) => name.endsWith(suffix)).sort();
|
|
30
|
+
} catch (err) {
|
|
31
|
+
if (isErrnoCode(err, "ENOENT")) return [];
|
|
32
|
+
throw err;
|
|
33
|
+
}
|
|
34
|
+
const files = [];
|
|
35
|
+
for (const name of names) {
|
|
36
|
+
const filePath = path.join(dir, name);
|
|
37
|
+
let entryStat;
|
|
38
|
+
try {
|
|
39
|
+
entryStat = await lstat(filePath);
|
|
40
|
+
} catch (err) {
|
|
41
|
+
if (isErrnoCode(err, "ENOENT")) continue;
|
|
42
|
+
throw err;
|
|
43
|
+
}
|
|
44
|
+
if (entryStat.isSymbolicLink() || !entryStat.isFile()) continue;
|
|
45
|
+
let entryReal;
|
|
46
|
+
try {
|
|
47
|
+
entryReal = await realpath(filePath);
|
|
48
|
+
} catch (err) {
|
|
49
|
+
if (isErrnoCode(err, "ENOENT")) continue;
|
|
50
|
+
throw err;
|
|
51
|
+
}
|
|
52
|
+
if (!pathIsInside(dirReal, entryReal)) continue;
|
|
53
|
+
files.push(filePath);
|
|
54
|
+
}
|
|
55
|
+
return files;
|
|
56
|
+
}
|
|
57
|
+
async function ensureContainedSpillDir(dir) {
|
|
58
|
+
await mkdir(dir, { recursive: true });
|
|
59
|
+
const dirStat = await lstat(dir);
|
|
60
|
+
if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) {
|
|
61
|
+
throw new Error(`Refusing to write spill file into symlinked or non-directory path: ${dir}`);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export {
|
|
66
|
+
pathIsInside,
|
|
67
|
+
assertPathInsideRoot,
|
|
68
|
+
listContainedSpillFiles,
|
|
69
|
+
ensureContainedSpillDir
|
|
70
|
+
};
|
|
71
|
+
//# sourceMappingURL=chunk-GCASGYIO.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/utils/path-containment.ts"],"sourcesContent":["/**\n * @remnic/core — Path Containment Guards\n *\n * Shared symlink/traversal containment helpers for filesystem walkers that\n * scan the memory store. Extracted from search/document-scanner.ts so every\n * walker (the search index scanner, the CLI dedupe walker, ...) enforces the\n * SAME containment semantics instead of forking the check (CLAUDE.md rule 22).\n *\n * Both helpers operate on realpath()-resolved absolute paths: callers resolve\n * symlinks first, then assert the resolved target is still inside the (also\n * realpath-resolved) memory root. This blocks a symlinked category directory\n * (e.g. decisions/ → /etc) from redirecting a scan — or a destructive dedupe\n * unlink — outside the memory store.\n */\n\nimport path from \"node:path\";\nimport { lstat, mkdir, readdir, realpath } from \"node:fs/promises\";\nimport { isErrnoCode } from \"./errno.js\";\n\n/**\n * True when `child` is `parent` itself or nested underneath it. Both arguments\n * must already be resolved (realpath) absolute paths.\n */\nexport function pathIsInside(parent: string, child: string): boolean {\n const relative = path.relative(parent, child);\n return relative === \"\" || (!relative.startsWith(\"..\") && !path.isAbsolute(relative));\n}\n\n/**\n * Throw if the realpath-resolved `candidateReal` escapes `rootReal`. The\n * message references the original (pre-realpath) path so operators can locate\n * the offending symlink/entry.\n */\nexport function assertPathInsideRoot(\n rootReal: string,\n candidateReal: string,\n originalPath: string,\n): void {\n if (!pathIsInside(rootReal, candidateReal)) {\n throw new Error(`Refusing to scan memory path outside memoryDir: ${originalPath}`);\n }\n}\n\n/**\n * List the regular-file children of `dir` whose name ends in `suffix` (default\n * `.jsonl`) in sorted name order as absolute paths, rejecting a symlinked/\n * non-directory `dir` and skipping any entry that is a symlink or whose realpath\n * escapes `dir`. Returns `[]` when the directory is absent or cannot be safely\n * enumerated. Used by the durable pending-spill drains (lifecycle ledger +\n * recall impressions, #2033) so a poisoned link planted in a spill directory\n * cannot redirect a secure read — or a later unlink — outside that directory.\n * The `suffix` override lets the lifecycle drain enumerate crash-orphaned\n * `*.jsonl.claimed` files with the SAME containment guard as live spills.\n */\nexport async function listContainedSpillFiles(dir: string, suffix = \".jsonl\"): Promise<string[]> {\n let dirReal: string;\n try {\n const dirStat = await lstat(dir);\n if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) return [];\n dirReal = await realpath(dir);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return [];\n throw err;\n }\n let names: string[];\n try {\n names = (await readdir(dir)).filter((name) => name.endsWith(suffix)).sort();\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) return [];\n throw err;\n }\n const files: string[] = [];\n for (const name of names) {\n const filePath = path.join(dir, name);\n let entryStat;\n try {\n entryStat = await lstat(filePath);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) continue; // vanished between readdir and lstat\n throw err;\n }\n // Reject a symlinked entry or one whose real target escapes the spill dir\n // BEFORE any secure read/delete: a poisoned link must never redirect a\n // decrypt or a later unlink outside the directory (#2033).\n if (entryStat.isSymbolicLink() || !entryStat.isFile()) continue;\n let entryReal: string;\n try {\n entryReal = await realpath(filePath);\n } catch (err) {\n if (isErrnoCode(err, \"ENOENT\")) continue;\n throw err;\n }\n if (!pathIsInside(dirReal, entryReal)) continue;\n files.push(filePath);\n }\n return files;\n}\n\n/**\n * Create `dir` (recursively, if absent) and assert it is a REAL directory —\n * never a symlink — BEFORE any spill file is written into it (#2033). This\n * mirrors the lstat guard {@link listContainedSpillFiles} applies on the read\n * side so the durable-spill WRITE and its later drain enforce the SAME\n * symlink-safe containment: a symlink planted at the spill-directory path (e.g.\n * `<ledger>.pending.d` -> /etc) cannot redirect a write/rename/unlink outside\n * the intended location. `mkdir` recursive is a no-op when the path already\n * resolves through a symlink, so the post-mkdir lstat is what actually refuses\n * the poisoned link. Throws on a symlinked or non-directory target.\n */\nexport async function ensureContainedSpillDir(dir: string): Promise<void> {\n await mkdir(dir, { recursive: true });\n const dirStat = await lstat(dir);\n if (dirStat.isSymbolicLink() || !dirStat.isDirectory()) {\n throw new Error(`Refusing to write spill file into symlinked or non-directory path: ${dir}`);\n }\n}\n"],"mappings":";;;;;AAeA,OAAO,UAAU;AACjB,SAAS,OAAO,OAAO,SAAS,gBAAgB;AAOzC,SAAS,aAAa,QAAgB,OAAwB;AACnE,QAAM,WAAW,KAAK,SAAS,QAAQ,KAAK;AAC5C,SAAO,aAAa,MAAO,CAAC,SAAS,WAAW,IAAI,KAAK,CAAC,KAAK,WAAW,QAAQ;AACpF;AAOO,SAAS,qBACd,UACA,eACA,cACM;AACN,MAAI,CAAC,aAAa,UAAU,aAAa,GAAG;AAC1C,UAAM,IAAI,MAAM,mDAAmD,YAAY,EAAE;AAAA,EACnF;AACF;AAaA,eAAsB,wBAAwB,KAAa,SAAS,UAA6B;AAC/F,MAAI;AACJ,MAAI;AACF,UAAM,UAAU,MAAM,MAAM,GAAG;AAC/B,QAAI,QAAQ,eAAe,KAAK,CAAC,QAAQ,YAAY,EAAG,QAAO,CAAC;AAChE,cAAU,MAAM,SAAS,GAAG;AAAA,EAC9B,SAAS,KAAK;AACZ,QAAI,YAAY,KAAK,QAAQ,EAAG,QAAO,CAAC;AACxC,UAAM;AAAA,EACR;AACA,MAAI;AACJ,MAAI;AACF,aAAS,MAAM,QAAQ,GAAG,GAAG,OAAO,CAAC,SAAS,KAAK,SAAS,MAAM,CAAC,EAAE,KAAK;AAAA,EAC5E,SAAS,KAAK;AACZ,QAAI,YAAY,KAAK,QAAQ,EAAG,QAAO,CAAC;AACxC,UAAM;AAAA,EACR;AACA,QAAM,QAAkB,CAAC;AACzB,aAAW,QAAQ,OAAO;AACxB,UAAM,WAAW,KAAK,KAAK,KAAK,IAAI;AACpC,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,MAAM,QAAQ;AAAA,IAClC,SAAS,KAAK;AACZ,UAAI,YAAY,KAAK,QAAQ,EAAG;AAChC,YAAM;AAAA,IACR;AAIA,QAAI,UAAU,eAAe,KAAK,CAAC,UAAU,OAAO,EAAG;AACvD,QAAI;AACJ,QAAI;AACF,kBAAY,MAAM,SAAS,QAAQ;AAAA,IACrC,SAAS,KAAK;AACZ,UAAI,YAAY,KAAK,QAAQ,EAAG;AAChC,YAAM;AAAA,IACR;AACA,QAAI,CAAC,aAAa,SAAS,SAAS,EAAG;AACvC,UAAM,KAAK,QAAQ;AAAA,EACrB;AACA,SAAO;AACT;AAaA,eAAsB,wBAAwB,KAA4B;AACxE,QAAM,MAAM,KAAK,EAAE,WAAW,KAAK,CAAC;AACpC,QAAM,UAAU,MAAM,MAAM,GAAG;AAC/B,MAAI,QAAQ,eAAe,KAAK,CAAC,QAAQ,YAAY,GAAG;AACtD,UAAM,IAAI,MAAM,sEAAsE,GAAG,EAAE;AAAA,EAC7F;AACF;","names":[]}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import {
|
|
2
2
|
resolveDefaultNamespaceRoot,
|
|
3
3
|
resolveNamespaceStorageRoot
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-44XZ75OQ.js";
|
|
5
5
|
import {
|
|
6
6
|
getConfiguredNamespaces
|
|
7
|
-
} from "./chunk-
|
|
7
|
+
} from "./chunk-MMGGVZ4Q.js";
|
|
8
8
|
import {
|
|
9
9
|
namespaceIdentityFromToken,
|
|
10
10
|
namespaceIdentityToken,
|
|
@@ -13,20 +13,20 @@ import {
|
|
|
13
13
|
import {
|
|
14
14
|
MutationSerializer,
|
|
15
15
|
withHeldFileLock
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-WL5EBRDH.js";
|
|
17
17
|
import {
|
|
18
18
|
displayErrorDetail
|
|
19
19
|
} from "./chunk-RL6NEVXT.js";
|
|
20
|
+
import {
|
|
21
|
+
ALL_CATEGORY_DIRS
|
|
22
|
+
} from "./chunk-VS2IYZRU.js";
|
|
20
23
|
import {
|
|
21
24
|
isSafeRouteNamespace
|
|
22
25
|
} from "./chunk-U3PN77QT.js";
|
|
23
26
|
import {
|
|
24
27
|
resolveConversationContextCapabilities,
|
|
25
28
|
resolveNamespaceCapabilities
|
|
26
|
-
} from "./chunk-
|
|
27
|
-
import {
|
|
28
|
-
ALL_CATEGORY_DIRS
|
|
29
|
-
} from "./chunk-VS2IYZRU.js";
|
|
29
|
+
} from "./chunk-SCCO46KZ.js";
|
|
30
30
|
|
|
31
31
|
// src/namespaces/catalog.ts
|
|
32
32
|
import path from "path";
|
|
@@ -2204,4 +2204,4 @@ export {
|
|
|
2204
2204
|
runNamespaceMaintenancePlan,
|
|
2205
2205
|
runNamespaceMaintenanceBatchPlan
|
|
2206
2206
|
};
|
|
2207
|
-
//# sourceMappingURL=chunk-
|
|
2207
|
+
//# sourceMappingURL=chunk-GFPZS3F5.js.map
|
|
@@ -7,6 +7,12 @@ import {
|
|
|
7
7
|
} from "./chunk-IISBCCWR.js";
|
|
8
8
|
|
|
9
9
|
// src/trust-score-stage.ts
|
|
10
|
+
function trustResultKey(result) {
|
|
11
|
+
return JSON.stringify([result.namespace ?? "", result.path]);
|
|
12
|
+
}
|
|
13
|
+
function trustResultFor(trustByPath, result) {
|
|
14
|
+
return trustByPath.get(trustResultKey(result)) ?? trustByPath.get(result.path);
|
|
15
|
+
}
|
|
10
16
|
function buildTrustSignalMap(memories, now, options = {}) {
|
|
11
17
|
const map = /* @__PURE__ */ new Map();
|
|
12
18
|
const nowMs = now.getTime();
|
|
@@ -62,7 +68,7 @@ function applyTrustScoreStage(candidates, options) {
|
|
|
62
68
|
const quarantined = [];
|
|
63
69
|
for (let i = 0; i < candidates.length; i += 1) {
|
|
64
70
|
const c = candidates[i];
|
|
65
|
-
const signals = options.signals.get(c.path);
|
|
71
|
+
const signals = options.signals.get(c.key ?? c.path) ?? options.signals.get(c.path);
|
|
66
72
|
const trust = computeTrustScore(signals, options.weights);
|
|
67
73
|
const isQuarantined = quarantine && trust.band === "quarantine";
|
|
68
74
|
const multiplier = isQuarantined ? 1 : trustMultiplier(trust.score, minMul, maxMul);
|
|
@@ -70,6 +76,7 @@ function applyTrustScoreStage(candidates, options) {
|
|
|
70
76
|
const scored = safeBase * multiplier;
|
|
71
77
|
const item = {
|
|
72
78
|
path: c.path,
|
|
79
|
+
...c.key === void 0 ? {} : { key: c.key },
|
|
73
80
|
score: scored,
|
|
74
81
|
originalScore: c.score,
|
|
75
82
|
multiplier,
|
|
@@ -107,67 +114,118 @@ function explainQuarantine(trust) {
|
|
|
107
114
|
if (c.contradiction && c.contradiction.value <= 0.2) return "contradiction: pending review";
|
|
108
115
|
return "hard-negative trust signal";
|
|
109
116
|
}
|
|
110
|
-
|
|
111
|
-
|
|
117
|
+
var TRUST_SIGNAL_CACHE_MAX_AGE_MS = 3e5;
|
|
118
|
+
var TRUST_SIGNAL_CACHE_MAX_NAMESPACES = 64;
|
|
119
|
+
function capTrustSignalCache(cache, max) {
|
|
120
|
+
while (cache.size > max) {
|
|
121
|
+
const oldest = cache.keys().next().value;
|
|
122
|
+
if (oldest === void 0) break;
|
|
123
|
+
cache.delete(oldest);
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
async function buildTrustSignalsForRerank(candidates, namespaces, deps, signalCache, now, options = {}) {
|
|
112
127
|
const logDebug = options.logDebug ?? (() => {
|
|
113
128
|
});
|
|
114
129
|
const signals = /* @__PURE__ */ new Map();
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
const
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
namespace: ns,
|
|
138
|
-
error: err.message
|
|
139
|
-
});
|
|
130
|
+
const corpusFallbackEnabled = options.corpusFallbackEnabled ?? true;
|
|
131
|
+
const halfLife = { recencyHalfLifeDays: options.recencyHalfLifeDays };
|
|
132
|
+
const preloadedKeys = /* @__PURE__ */ new Set();
|
|
133
|
+
const normalized = candidates.map(
|
|
134
|
+
(c) => typeof c === "string" ? { path: c, signalKey: c, lookupKey: c, namespace: void 0 } : {
|
|
135
|
+
path: c.path,
|
|
136
|
+
signalKey: c.signalKey ?? c.path,
|
|
137
|
+
lookupKey: c.lookupKey ?? c.path,
|
|
138
|
+
namespace: c.namespace
|
|
139
|
+
}
|
|
140
|
+
);
|
|
141
|
+
if (options.preloadedFrontmatter) {
|
|
142
|
+
const preloaded = [];
|
|
143
|
+
for (const c of normalized) {
|
|
144
|
+
const mem = options.preloadedFrontmatter.get(c.lookupKey) ?? options.preloadedFrontmatter.get(c.path);
|
|
145
|
+
if (!mem) continue;
|
|
146
|
+
preloadedKeys.add(c.signalKey);
|
|
147
|
+
preloaded.push({ path: c.signalKey, frontmatter: mem.frontmatter });
|
|
148
|
+
}
|
|
149
|
+
if (preloaded.length > 0) {
|
|
150
|
+
const seeded = buildTrustSignalMap(preloaded, now, halfLife);
|
|
151
|
+
for (const [key, s] of seeded) signals.set(key, s);
|
|
140
152
|
}
|
|
141
153
|
}
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const
|
|
145
|
-
|
|
154
|
+
if (corpusFallbackEnabled) {
|
|
155
|
+
const seenNamespaces = /* @__PURE__ */ new Set();
|
|
156
|
+
for (const ns of namespaces) {
|
|
157
|
+
if (options.abortSignal?.aborted) break;
|
|
158
|
+
if (seenNamespaces.has(ns)) continue;
|
|
159
|
+
seenNamespaces.add(ns);
|
|
160
|
+
if (normalized.every((c) => signals.has(c.signalKey) || preloadedKeys.has(c.signalKey))) break;
|
|
146
161
|
try {
|
|
147
|
-
const
|
|
148
|
-
|
|
162
|
+
const version = await deps.getNamespaceVersion(ns);
|
|
163
|
+
const cached = signalCache.cache.get(ns);
|
|
164
|
+
const nowMs = now.getTime();
|
|
165
|
+
let nsMap;
|
|
166
|
+
if (cached && cached.version === version && nowMs - cached.cachedAt < TRUST_SIGNAL_CACHE_MAX_AGE_MS) {
|
|
167
|
+
nsMap = cached.signals;
|
|
168
|
+
} else {
|
|
169
|
+
const memories = await deps.readNamespaceMemories(ns);
|
|
170
|
+
nsMap = buildTrustSignalMap(memories, now, halfLife);
|
|
171
|
+
signalCache.cache.set(ns, { version, cachedAt: nowMs, signals: nsMap });
|
|
172
|
+
capTrustSignalCache(signalCache.cache, TRUST_SIGNAL_CACHE_MAX_NAMESPACES);
|
|
173
|
+
}
|
|
174
|
+
for (const c of normalized) {
|
|
175
|
+
if (signals.has(c.signalKey) || preloadedKeys.has(c.signalKey)) continue;
|
|
176
|
+
if (c.namespace !== void 0 && c.namespace !== ns) continue;
|
|
177
|
+
const s = nsMap.get(c.path);
|
|
178
|
+
if (s) signals.set(c.signalKey, s);
|
|
179
|
+
}
|
|
149
180
|
} catch (err) {
|
|
150
|
-
logDebug("trust-score:
|
|
151
|
-
|
|
181
|
+
logDebug("trust-score: failed to read namespace, skipping", {
|
|
182
|
+
namespace: ns,
|
|
152
183
|
error: err.message
|
|
153
184
|
});
|
|
154
185
|
}
|
|
155
186
|
}
|
|
187
|
+
}
|
|
188
|
+
const missing = normalized.filter(
|
|
189
|
+
(c) => !signals.has(c.signalKey) && !preloadedKeys.has(c.signalKey)
|
|
190
|
+
);
|
|
191
|
+
if (missing.length > 0) {
|
|
192
|
+
const fallbackMemories = [];
|
|
193
|
+
const BATCH = 16;
|
|
194
|
+
for (let off = 0; off < missing.length; off += BATCH) {
|
|
195
|
+
if (options.abortSignal?.aborted) break;
|
|
196
|
+
const batch = await Promise.all(
|
|
197
|
+
missing.slice(off, off + BATCH).map(async (c) => {
|
|
198
|
+
try {
|
|
199
|
+
const frontmatter = await deps.readMemoryFrontmatter(c.path, c.namespace);
|
|
200
|
+
return frontmatter ? { path: c.signalKey, frontmatter } : null;
|
|
201
|
+
} catch (err) {
|
|
202
|
+
logDebug("trust-score: direct path lookup failed", {
|
|
203
|
+
path: c.path,
|
|
204
|
+
error: err.message
|
|
205
|
+
});
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
})
|
|
209
|
+
);
|
|
210
|
+
for (const item of batch) if (item) fallbackMemories.push(item);
|
|
211
|
+
}
|
|
156
212
|
if (fallbackMemories.length > 0) {
|
|
157
|
-
const fallbackSignals = buildTrustSignalMap(fallbackMemories, now,
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
for (const [path, s] of fallbackSignals) signals.set(path, s);
|
|
213
|
+
const fallbackSignals = buildTrustSignalMap(fallbackMemories, now, halfLife);
|
|
214
|
+
for (const [key, s] of fallbackSignals) signals.set(key, s);
|
|
161
215
|
}
|
|
162
216
|
}
|
|
163
217
|
return signals;
|
|
164
218
|
}
|
|
165
219
|
|
|
166
220
|
export {
|
|
221
|
+
trustResultKey,
|
|
222
|
+
trustResultFor,
|
|
167
223
|
buildTrustSignalMap,
|
|
168
224
|
applyTrustScoreStage,
|
|
169
225
|
projectTrustForXray,
|
|
170
226
|
explainQuarantine,
|
|
227
|
+
TRUST_SIGNAL_CACHE_MAX_AGE_MS,
|
|
228
|
+
TRUST_SIGNAL_CACHE_MAX_NAMESPACES,
|
|
171
229
|
buildTrustSignalsForRerank
|
|
172
230
|
};
|
|
173
|
-
//# sourceMappingURL=chunk-
|
|
231
|
+
//# sourceMappingURL=chunk-GNVZQ5JN.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/trust-score-stage.ts"],"sourcesContent":["import type { QmdSearchResult } from \"./types.js\";\n\n/** Stable key for a recall result whose path may repeat across namespaces. */\nexport function trustResultKey(result: Pick<QmdSearchResult, \"path\" | \"namespace\">): string {\n return JSON.stringify([result.namespace ?? \"\", result.path]);\n}\n\n/** Read trust metadata while accepting pre-namespace path-only maps. */\nexport function trustResultFor(\n trustByPath: ReadonlyMap<string, TrustStageResultItem>,\n result: Pick<QmdSearchResult, \"path\" | \"namespace\">,\n): TrustStageResultItem | undefined {\n return trustByPath.get(trustResultKey(result)) ?? trustByPath.get(result.path);\n}\n\n/**\n * trust-score-stage.ts — signal adapters + recall pipeline stage (issue #1577 PR 2).\n *\n * This module sits between the pure {@link computeTrustScore} scorer and the\n * recall pipeline. It owns TWO jobs:\n *\n * 1. **Signal adapters** — read each trust signal via existing readers only\n * (`buildMemoryWorthCounterMap`-style frontmatter scan, faithfulness /\n * provenance / sources frontmatter from #1575/#1576). No new disk format,\n * no new write path. Expensive / optional signals (belief-ledger domain\n * calibration, contradiction review queue) are extension points that\n * return `undefined` when unwired — the scorer degrades to neutral for\n * any absent signal (rule 34).\n *\n * 2. **The recall stage** — apply `trustMultiplier(trust.score)` to each\n * candidate, exclude `quarantine`-band items from injection, and surface\n * the per-result `{ score, band, components }` so X-ray and the epistemic\n * renderer can explain the basis.\n *\n * Mutual exclusion with the Memory Worth filter (rule 39 — one multiplier, one\n * application point): when this stage runs, the standalone memory-worth filter\n * MUST NOT also run. The orchestrator enforces that at the wiring site\n * (`if (caps.recallTrustScore) … else if (caps.recallMemoryWorthFilter) …`);\n * the `double-multiplier` test below pins it structurally.\n */\n\nimport { computeMemoryWorth } from \"./memory-worth.js\";\nimport {\n computeTrustScore,\n trustMultiplier,\n type TrustBand,\n type TrustScoreComponent,\n type TrustScoreResult,\n type TrustSignals,\n type TrustWeights,\n} from \"./trust-score.js\";\nimport type { FaithfulnessFrontmatter, ProvenanceSource } from \"./types.js\";\n\n/**\n * Frontmatter projection the adapter reads. Kept narrow + structural so it can\n * be fed from a `MemoryFrontmatter`, a bench fixture, or a test stub without\n * pulling the full frontmatter type graph into the stage module.\n */\nexport interface TrustFrontmatterProjection {\n mw_success?: number;\n mw_fail?: number;\n lastAccessed?: string | null;\n provenance?: \"verified\" | \"unverified\" | \"none\";\n faithfulness?: FaithfulnessFrontmatter;\n sources?: ProvenanceSource[];\n /** Optional ISO creation/observation timestamp used for recency. */\n observedAt?: string;\n}\n\n/**\n * Build a `path → TrustSignals` map from an in-memory frontmatter scan. The\n * caller passes the memories already read for the memory-worth counter map so\n * we do not re-read the namespace. Pure: no I/O, takes `now` explicitly.\n */\nexport function buildTrustSignalMap(\n memories: ReadonlyArray<{ path: string; frontmatter: TrustFrontmatterProjection }>,\n now: Date,\n options: { recencyHalfLifeDays?: number } = {},\n): Map<string, TrustSignals> {\n const map = new Map<string, TrustSignals>();\n const nowMs = now.getTime();\n const nowUsable = Number.isFinite(nowMs);\n for (const m of memories) {\n const fm = m.frontmatter;\n const signals: TrustSignals = {};\n\n // Memory worth — reuse the exact Laplace computation the standalone filter\n // uses so the two never disagree on the same counters.\n if (fm.mw_success !== undefined || fm.mw_fail !== undefined) {\n // Pass the half-life through so outcome counters decay at the same\n // rate as the standalone memory-worth filter (review P2: TrustScore\n // subsumes the filter, so decay must not be lost). Convert days → ms.\n const halfLifeMs =\n options.recencyHalfLifeDays !== undefined\n ? options.recencyHalfLifeDays * 86_400_000\n : undefined;\n const worth = computeMemoryWorth({\n mw_success: fm.mw_success,\n mw_fail: fm.mw_fail,\n lastAccessed: fm.lastAccessed,\n now,\n halfLifeMs,\n });\n signals.memoryWorth = { score: worth.score, confidence: worth.confidence };\n }\n\n if (fm.provenance !== undefined) signals.provenance = fm.provenance;\n if (fm.faithfulness !== undefined) {\n // `skipped_no_span` (legacy fact lacking a verified source span) carries\n // no entailment signal — collapse it to `unchecked` so the scorer treats\n // it as the neutral \"no verdict\" case rather than a hard negative.\n signals.faithfulness =\n fm.faithfulness.verdict === \"skipped_no_span\" ? \"unchecked\" : fm.faithfulness.verdict;\n }\n\n // Corroboration = distinct source sessions/turns backing the fact.\n if (Array.isArray(fm.sources) && fm.sources.length > 0) {\n const distinct = new Set(\n fm.sources.map((s) => `${s.sessionKey ?? \"\"}|${s.turnId ?? \"\"}`),\n );\n signals.corroborationCount = distinct.size;\n }\n\n // Recency: prefer an explicit observation timestamp; fall back to\n // lastAccessed. Days-old vs the per-category half-life the caller supplies.\n const ts = fm.observedAt ?? fm.lastAccessed;\n if (nowUsable && typeof ts === \"string\" && ts.length > 0) {\n const parsed = Date.parse(ts);\n if (Number.isFinite(parsed)) {\n const ageDays = Math.max(0, (nowMs - parsed) / (24 * 60 * 60 * 1000));\n signals.ageDays = ageDays;\n if (options.recencyHalfLifeDays !== undefined) {\n signals.recencyHalfLifeDays = options.recencyHalfLifeDays;\n }\n }\n }\n\n // Only record an entry when at least one signal is present — a fully-empty\n // entry would score neutral anyway, and skipping keeps the map small.\n if (Object.keys(signals).length > 0) {\n map.set(m.path, signals);\n }\n }\n return map;\n}\n\n/** A scored recall candidate (mirrors `MemoryWorthFilterCandidate`). */\nexport interface TrustStageCandidate {\n path: string;\n score: number;\n /** Namespace-aware result key used to preserve result identity through rerank. */\n key?: string;\n}\n\n/** One candidate after the TrustScore stage. */\nexport interface TrustStageResultItem {\n path: string;\n /** Namespace-aware result key used to preserve result identity through rerank. */\n key?: string;\n /** Final score after the trust multiplier is applied. */\n score: number;\n /** The untouched input score — for telemetry / X-ray. */\n originalScore: number;\n /** The multiplier applied (exactly `1.0` for neutral / quarantined-kept). */\n multiplier: number;\n /** The full TrustScore result for X-ray + epistemic rendering. */\n trust: TrustScoreResult;\n /** `true` when the item was excluded from injection by quarantine. */\n quarantined: boolean;\n}\n\nexport interface TrustStageOptions {\n /** `path → TrustSignals`. Candidates absent from the map score neutral. */\n signals: ReadonlyMap<string, TrustSignals>;\n weights?: TrustWeights;\n /** Multiplier bounds; see {@link trustMultiplier}. */\n minMultiplier?: number;\n maxMultiplier?: number;\n /**\n * When `true` (default), `quarantine`-band items are excluded from the\n * returned (injected) list but still appear in {@link TrustStageOutput.all}\n * with `quarantined: true` so X-ray can surface them with a reason.\n * Only effective when the stage is active at all.\n */\n quarantine?: boolean;\n /**\n * Re-sort admitted candidates by descending multiplied score. Default `true`.\n * When `false`, admitted items keep input order; quarantined items are still\n * separated out.\n */\n reorder?: boolean;\n}\n\n/** Output of {@link applyTrustScoreStage}. */\nexport interface TrustStageOutput {\n /** Admitted (injectable) candidates, score-multiplied and optionally sorted. */\n admitted: TrustStageResultItem[];\n /**\n * Quarantined candidates — excluded from injection but visible to X-ray with\n * the reason (rule 34 — exclusion must never look like \"no result\"). Callers\n * that only need the injected list read `admitted`; X-ray reads `all`.\n */\n quarantined: TrustStageResultItem[];\n /** Every candidate (admitted + quarantined) in input order, for X-ray. */\n all: TrustStageResultItem[];\n}\n\n/**\n * Apply the unified TrustScore stage: score each candidate, multiply its base\n * score by `trustMultiplier(trust.score)`, and separate hard-negative\n * (quarantine) items from the injectable set.\n *\n * Neutral candidates (no signals → multiplier `1.0`) are mathematically\n * untouched, preserving byte-identical ranking for uninstrumented memories\n * when the feature is ON (and the whole stage is skipped when OFF — rule 39).\n */\nexport function applyTrustScoreStage(\n candidates: readonly TrustStageCandidate[],\n options: TrustStageOptions,\n): TrustStageOutput {\n const reorder = options.reorder !== false;\n const quarantine = options.quarantine !== false;\n const minMul = options.minMultiplier;\n const maxMul = options.maxMultiplier;\n\n const all: TrustStageResultItem[] = [];\n const admitted: TrustStageResultItem[] = [];\n const quarantined: TrustStageResultItem[] = [];\n\n for (let i = 0; i < candidates.length; i += 1) {\n const c = candidates[i]!;\n // Prefer the namespace-aware composite key; fall back to path for callers\n // (and tests) that key signals by bare path (#2020).\n const signals = options.signals.get(c.key ?? c.path) ?? options.signals.get(c.path);\n const trust = computeTrustScore(signals, options.weights);\n const isQuarantined = quarantine && trust.band === \"quarantine\";\n // Quarantined items are excluded from injection. Keep their score unchanged\n // so X-ray shows what the pipeline WOULD have injected — never inflate or\n // zero the score of a hidden item (rule 34).\n const multiplier = isQuarantined ? 1 : trustMultiplier(trust.score, minMul, maxMul);\n // Clamp the base score at zero before multiplying, mirroring the\n // memory-worth filter: a negative base would invert the multiplier's\n // intended direction (see memory-worth-filter.ts:145-153).\n const safeBase = c.score < 0 ? 0 : c.score;\n const scored = safeBase * multiplier;\n const item: TrustStageResultItem = {\n path: c.path,\n ...(c.key === undefined ? {} : { key: c.key }),\n score: scored,\n originalScore: c.score,\n multiplier,\n trust,\n quarantined: isQuarantined,\n };\n all.push(item);\n if (isQuarantined) quarantined.push(item);\n else admitted.push(item);\n }\n\n if (reorder) {\n // Stable sort by descending multiplied score, with original input position\n // as the deterministic tiebreaker (CLAUDE.md rule 19 / checklist §12).\n admitted.sort((a, b) => {\n if (b.score !== a.score) return b.score - a.score;\n // Tiebreaker: original insertion order. We don't have the index handy on\n // the item, so derive it from `all` ordering (input order is preserved\n // there). Equal-score items keep first-seen-first order.\n return 0;\n });\n // Node's sort is stable (ES2019+); the explicit `return 0` documents the\n // contract for reviewers.\n }\n\n return { admitted, quarantined, all };\n}\n\n/**\n * Compact X-ray projection of one stage item. Kept separate from the full\n * `TrustScoreResult` so the X-ray snapshot type stays narrow and serializable,\n * and so the renderer never depends on the scorer's internal component map\n * shape beyond `{ value, weight }`.\n */\nexport interface TrustXrayProjection {\n score: number;\n band: TrustBand;\n components: Record<string, TrustScoreComponent>;\n multiplier: number;\n quarantined: boolean;\n /** Human-readable exclusion reason, present only when quarantined. */\n quarantineReason?: string;\n}\n\n/** Build the X-ray projection for one stage result item. */\nexport function projectTrustForXray(item: TrustStageResultItem): TrustXrayProjection {\n const proj: TrustXrayProjection = {\n score: item.trust.score,\n band: item.trust.band,\n components: item.trust.components,\n multiplier: item.multiplier,\n quarantined: item.quarantined,\n };\n if (item.quarantined) {\n proj.quarantineReason = explainQuarantine(item.trust);\n }\n return proj;\n}\n\n/** Deterministic, component-derived reason a memory was quarantined. */\nexport function explainQuarantine(trust: TrustScoreResult): string {\n const c = trust.components;\n if (c.faithfulness && c.faithfulness.value === 0) return \"faithfulness: contradicted\";\n if (c.contradiction && c.contradiction.value <= 0.2) return \"contradiction: pending review\";\n return \"hard-negative trust signal\";\n}\n\n\n// ─── Recall-stage signal builder (I/O orchestration) ──────────────────────\n\n/**\n * Narrow callbacks the signal builder needs from its host (the orchestrator).\n * Kept as interfaces so the module stays pure-testable: the host binds\n * `getStorage` / `readQmdResultMemory` into these and the builder owns cache\n * management, namespace iteration, and the cold-tier direct fallback.\n */\nexport interface TrustScoreRerankDeps {\n /** Read every memory in a namespace for the hot-tier signal scan. */\n readNamespaceMemories(\n namespace: string,\n ): Promise<ReadonlyArray<{ path: string; frontmatter: TrustFrontmatterProjection }>>;\n /** Read one memory's frontmatter by path (cold-tier direct fallback). The\n * owning namespace is passed so a relative path resolves against the correct\n * namespace store instead of the first fallback (#2020). */\n readMemoryFrontmatter(\n path: string,\n preferredNamespace?: string,\n ): Promise<TrustFrontmatterProjection | null>;\n /**\n * Current cross-process corpus version for a namespace (issue #1905). Used\n * to key the per-namespace corpus-fallback cache so it invalidates on the\n * next memory mutation instead of on a wall-clock timer that is shorter than\n * recall latency (which produced a permanent steady-state miss).\n */\n getNamespaceVersion(namespace: string): Promise<number>;\n}\n\n/**\n * Per-namespace signal cache the host owns and the builder mutates. Keyed on\n * the shared corpus version (issue #1905): an entry is valid iff its `version`\n * still equals the namespace's current corpus version AND it is younger than\n * TRUST_SIGNAL_CACHE_MAX_AGE_MS. The age bound is required because trust\n * signals bake wall-clock time into their values (ageDays,\n * computeMemoryWorth(..., now) with recency half-life) — pure version\n * invalidation would serve stale decay on a read-only corpus (#1905, Codex).\n */\nexport interface TrustScoreSignalCache {\n cache: Map<string, { version: number; cachedAt: number; signals: ReadonlyMap<string, TrustSignals> }>;\n}\n\n/** See TrustScoreSignalCache — bounds time-based staleness of cached signals. */\nexport const TRUST_SIGNAL_CACHE_MAX_AGE_MS = 300_000;\n\n/** Bound on distinct namespaces retained; overflow evicts the oldest. */\nexport const TRUST_SIGNAL_CACHE_MAX_NAMESPACES = 64;\n\n/** Insert-ordered bounded set: evict the oldest namespace on overflow. */\nfunction capTrustSignalCache(cache: TrustScoreSignalCache[\"cache\"], max: number): void {\n while (cache.size > max) {\n const oldest = cache.keys().next().value;\n if (oldest === undefined) break;\n cache.delete(oldest);\n }\n}\n\n/**\n * Build the `path → TrustSignals` map for recall candidates.\n *\n * O(candidates) inversion (issue #1905): when the host passes\n * `preloadedFrontmatter` (frontmatter already loaded on the hot recall path),\n * candidate signals are seeded directly from it — no corpus scan. Only\n * candidates still missing fall back to the corpus-level per-namespace map\n * (config-gated, version-keyed so it actually hits in steady state) and then\n * to a bounded-parallel direct per-path read.\n *\n * Fail-open: a single unreadable namespace or memory is logged and skipped so\n * a storage hiccup never breaks recall (mirrors `memory-worth-filter.ts`).\n */\nexport async function buildTrustSignalsForRerank(\n candidates: readonly (\n | string\n | { path: string; signalKey?: string; lookupKey?: string; namespace?: string }\n )[],\n namespaces: readonly string[],\n deps: TrustScoreRerankDeps,\n signalCache: TrustScoreSignalCache,\n now: Date,\n options: {\n recencyHalfLifeDays?: number;\n logDebug?: (message: string, context: Record<string, unknown>) => void;\n /**\n * Candidate frontmatter already loaded on the hot recall path (issue\n * #1905). When present, candidate signals are seeded from it before any\n * corpus scan, so the common warm-candidate recall does zero\n * `readNamespaceMemories` calls. Structural — a `MemoryFile` map satisfies\n * `{ frontmatter: TrustFrontmatterProjection }` without importing it.\n */\n preloadedFrontmatter?: ReadonlyMap<string, { frontmatter: TrustFrontmatterProjection }>;\n /**\n * When false, skip the corpus-level `readNamespaceMemories` fallback\n * entirely (candidates-first + direct-read only). Defaults to true so the\n * corpus path stays reachable. See `recallTrustStageCorpusFallbackEnabled`.\n */\n corpusFallbackEnabled?: boolean;\n /**\n * Cooperative cancellation (issue #1905, Codex): when the recall's shared\n * enrichment-assembly deadline wins the race, the host aborts this signal\n * so an orphaned corpus scan / direct-read loop stops at the next loop\n * boundary instead of continuing to burn I/O after recall already returned.\n */\n abortSignal?: AbortSignal;\n } = {},\n): Promise<Map<string, TrustSignals>> {\n const logDebug = options.logDebug ?? (() => {});\n const signals = new Map<string, TrustSignals>();\n const corpusFallbackEnabled = options.corpusFallbackEnabled ?? true;\n const halfLife = { recencyHalfLifeDays: options.recencyHalfLifeDays };\n\n // Paths examined via preloaded frontmatter (issue #1905, Cursor/Codex).\n // buildTrustSignalMap deliberately OMITS neutral memories (no trust fields),\n // so a preloaded candidate can be examined yet absent from `signals` — it\n // must NOT be treated as missing, or the corpus fallback + direct read fire\n // for every uninstrumented hot candidate, defeating the O(candidates) path.\n // Absent-from-signals still means multiplier 1.0 downstream, exactly what a\n // corpus scan would have produced for the same neutral memory.\n const preloadedKeys = new Set<string>();\n\n // Normalize candidates to a composite identity: `signalKey` is what the\n // trust stage looks up (namespace-aware), `lookupKey` matches the preloaded\n // frontmatter map's key, `path` is the raw store path used for corpus/direct\n // reads. A bare string keeps the legacy path-only behavior (#2020).\n const normalized = candidates.map((c) =>\n typeof c === \"string\"\n ? { path: c, signalKey: c, lookupKey: c, namespace: undefined as string | undefined }\n : {\n path: c.path,\n signalKey: c.signalKey ?? c.path,\n lookupKey: c.lookupKey ?? c.path,\n namespace: c.namespace,\n },\n );\n\n // O(candidates) fast path: seed signals from candidate frontmatter already\n // loaded on the hot recall path. Reuses the exact `buildTrustSignalMap`\n // computation so a candidate's signals equal what a corpus scan produced.\n if (options.preloadedFrontmatter) {\n const preloaded: Array<{ path: string; frontmatter: TrustFrontmatterProjection }> = [];\n for (const c of normalized) {\n // Composite lookupKey is authoritative; the bare-path fallback keeps\n // path-keyed preloaded maps (e.g. the recent-scan branch) hitting the\n // fast path and is inert in production composite-keyed maps (#2020).\n const mem =\n options.preloadedFrontmatter.get(c.lookupKey) ??\n options.preloadedFrontmatter.get(c.path);\n if (!mem) continue;\n preloadedKeys.add(c.signalKey);\n preloaded.push({ path: c.signalKey, frontmatter: mem.frontmatter });\n }\n if (preloaded.length > 0) {\n const seeded = buildTrustSignalMap(preloaded, now, halfLife);\n for (const [key, s] of seeded) signals.set(key, s);\n }\n }\n\n // Corpus-level fallback (config-gated): candidates still missing probe a\n // per-namespace signal map, cached and invalidated by the shared\n // cross-process corpus version. Only candidate rows are copied out — never\n // the whole map (issue #1905, no per-recall full-map union).\n if (corpusFallbackEnabled) {\n const seenNamespaces = new Set<string>();\n for (const ns of namespaces) {\n // Cooperative cancellation: the recall's assembly deadline may have won\n // the race — stop before starting another namespace scan (#1905, Codex).\n if (options.abortSignal?.aborted) break;\n if (seenNamespaces.has(ns)) continue;\n seenNamespaces.add(ns);\n if (normalized.every((c) => signals.has(c.signalKey) || preloadedKeys.has(c.signalKey))) break;\n try {\n const version = await deps.getNamespaceVersion(ns);\n const cached = signalCache.cache.get(ns);\n const nowMs = now.getTime();\n let nsMap: ReadonlyMap<string, TrustSignals>;\n // Valid iff the corpus version still matches AND the entry is younger\n // than the max age: trust signals bake `now` into their values, so an\n // unchanged corpus still goes stale as wall-clock advances (#1905, Codex).\n if (\n cached &&\n cached.version === version &&\n nowMs - cached.cachedAt < TRUST_SIGNAL_CACHE_MAX_AGE_MS\n ) {\n nsMap = cached.signals;\n } else {\n const memories = await deps.readNamespaceMemories(ns);\n nsMap = buildTrustSignalMap(memories, now, halfLife);\n signalCache.cache.set(ns, { version, cachedAt: nowMs, signals: nsMap });\n capTrustSignalCache(signalCache.cache, TRUST_SIGNAL_CACHE_MAX_NAMESPACES);\n }\n for (const c of normalized) {\n // Preloaded keys were already examined — absent-from-signals means\n // neutral (multiplier 1.0), identical to what the corpus map holds.\n if (signals.has(c.signalKey) || preloadedKeys.has(c.signalKey)) continue;\n // A namespaced candidate belongs to exactly one namespace: never seed\n // its signals from a different namespace's corpus map, or two\n // same-path candidates in different namespaces collapse (#2020).\n if (c.namespace !== undefined && c.namespace !== ns) continue;\n const s = nsMap.get(c.path);\n if (s) signals.set(c.signalKey, s);\n }\n } catch (err) {\n logDebug(\"trust-score: failed to read namespace, skipping\", {\n namespace: ns,\n error: (err as Error).message,\n });\n }\n }\n }\n\n // Direct per-path fallback for candidates still absent (cold-tier / archive).\n // Preloaded paths are excluded — they were examined and are neutral priors.\n // Bounded-parallel (≤16) to match loadSearchResultMemoryMap's batch size.\n const missing = normalized.filter(\n (c) => !signals.has(c.signalKey) && !preloadedKeys.has(c.signalKey),\n );\n if (missing.length > 0) {\n const fallbackMemories: Array<{ path: string; frontmatter: TrustFrontmatterProjection }> = [];\n const BATCH = 16;\n for (let off = 0; off < missing.length; off += BATCH) {\n // Cooperative cancellation between batches (#1905, Codex).\n if (options.abortSignal?.aborted) break;\n const batch = await Promise.all(\n missing.slice(off, off + BATCH).map(async (c) => {\n try {\n const frontmatter = await deps.readMemoryFrontmatter(c.path, c.namespace);\n return frontmatter ? { path: c.signalKey, frontmatter } : null;\n } catch (err) {\n logDebug(\"trust-score: direct path lookup failed\", {\n path: c.path,\n error: (err as Error).message,\n });\n return null;\n }\n }),\n );\n for (const item of batch) if (item) fallbackMemories.push(item);\n }\n if (fallbackMemories.length > 0) {\n const fallbackSignals = buildTrustSignalMap(fallbackMemories, now, halfLife);\n for (const [key, s] of fallbackSignals) signals.set(key, s);\n }\n }\n\n return signals;\n}\n"],"mappings":"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","names":[]}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
coerceBool,
|
|
3
3
|
coerceNumber
|
|
4
|
-
} from "./chunk-
|
|
4
|
+
} from "./chunk-PQVCH2AE.js";
|
|
5
5
|
|
|
6
6
|
// src/faithfulness-config.ts
|
|
7
7
|
function parseIntegerAtLeast(value, fallback, min, keyName) {
|
|
@@ -60,4 +60,4 @@ export {
|
|
|
60
60
|
parseFaithfulnessGateConfig,
|
|
61
61
|
parseCorrectionIntentConfig
|
|
62
62
|
};
|
|
63
|
-
//# sourceMappingURL=chunk-
|
|
63
|
+
//# sourceMappingURL=chunk-H4WG3UQZ.js.map
|