@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
package/src/recall-state.ts
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
1
|
+
import { appendFile, mkdir, readFile, rename, rm, stat, unlink, writeFile } from "node:fs/promises";
|
|
2
2
|
import path from "node:path";
|
|
3
3
|
import { createHash, randomUUID } from "node:crypto";
|
|
4
4
|
import { log } from "./logger.js";
|
|
5
5
|
import { writeFileAtomically } from "./maintenance/atomic-file.js";
|
|
6
|
+
import { isErrnoCode } from "./utils/errno.js";
|
|
7
|
+
import { withHeldFileLock, type HeldFileLockOptions } from "./utils/serialize-mutations.js";
|
|
8
|
+
import { ensureContainedSpillDir, listContainedSpillFiles } from "./utils/path-containment.js";
|
|
6
9
|
import type { SearchDegradation } from "./search/port.js";
|
|
7
10
|
import type {
|
|
8
11
|
IdentityInjectionMode,
|
|
@@ -21,6 +24,10 @@ export interface LastRecallBudgetSummary {
|
|
|
21
24
|
truncated?: boolean;
|
|
22
25
|
includedSections?: string[];
|
|
23
26
|
omittedSections?: string[];
|
|
27
|
+
includedMemoryIds?: string[];
|
|
28
|
+
includedMemoryPaths?: string[];
|
|
29
|
+
includedMemoryNamespaces?: Array<string | undefined>;
|
|
30
|
+
omittedMemoryIds?: string[];
|
|
24
31
|
}
|
|
25
32
|
|
|
26
33
|
export interface LastRecallSnapshot {
|
|
@@ -40,6 +47,7 @@ export interface LastRecallSnapshot {
|
|
|
40
47
|
budgetsApplied?: LastRecallBudgetSummary;
|
|
41
48
|
latencyMs?: number;
|
|
42
49
|
resultPaths?: string[];
|
|
50
|
+
resultNamespaces?: Array<string | undefined>;
|
|
43
51
|
policyVersion?: string;
|
|
44
52
|
identityInjectionMode?: IdentityInjectionMode | "none";
|
|
45
53
|
identityInjectedChars?: number;
|
|
@@ -227,16 +235,67 @@ const DEFAULT_TIER_MIGRATION_STATUS: TierMigrationStatusSnapshot = {
|
|
|
227
235
|
},
|
|
228
236
|
};
|
|
229
237
|
|
|
238
|
+
/**
|
|
239
|
+
* Suffix marking an impression spill CLAIMED for commit but not yet deleted.
|
|
240
|
+
* The crash-safe drain renames `<uuid>.jsonl` -> `<uuid>.jsonl.claimed` before
|
|
241
|
+
* committing its rows, mirroring the lifecycle ledger's claim/commit protocol
|
|
242
|
+
* (#2033).
|
|
243
|
+
*/
|
|
244
|
+
const CLAIMED_IMPRESSION_SPILL_SUFFIX = ".claimed";
|
|
245
|
+
|
|
246
|
+
/**
|
|
247
|
+
* Outcome of {@link LastRecallStore.drainPendingImpressions}. Distinguishes a
|
|
248
|
+
* completed drain (or nothing pending) from a DEFERRED drain that left durable
|
|
249
|
+
* spills in the offline-sync-EXCLUDED queue, so the caller can tell the
|
|
250
|
+
* data-safe cases apart from the one where an offline-sync snapshot would
|
|
251
|
+
* silently omit recorded impressions (#2033).
|
|
252
|
+
*/
|
|
253
|
+
export interface DrainPendingImpressionsResult {
|
|
254
|
+
/** Pending spill rows were folded into the synced active file this call. */
|
|
255
|
+
folded: boolean;
|
|
256
|
+
/**
|
|
257
|
+
* Durable spill rows remain in the offline-sync-EXCLUDED pending queue after
|
|
258
|
+
* this drain: the rotation lock could not be acquired, a spill could not be
|
|
259
|
+
* claimed, or the drain-only fold left rows that would only fit by rotating
|
|
260
|
+
* into a sync-excluded archive. A snapshot taken now would silently omit them
|
|
261
|
+
* (#2033): the caller MUST treat the active file as INCOMPLETE and retry or
|
|
262
|
+
* abort the snapshot rather than report success. `false` means the active file
|
|
263
|
+
* is complete — every pending row was folded or nothing was pending.
|
|
264
|
+
*/
|
|
265
|
+
pendingDeferred: boolean;
|
|
266
|
+
}
|
|
267
|
+
|
|
230
268
|
export class LastRecallStore {
|
|
231
269
|
private readonly statePath: string;
|
|
232
270
|
private readonly impressionsPath: string;
|
|
233
271
|
private readonly writeStateFile: StateFileWriter;
|
|
272
|
+
private readonly impressionsRotateBytes: number;
|
|
273
|
+
private readonly impressionsRotateKeep: number;
|
|
274
|
+
// Lock-acquisition timing for the cross-process impression rotation lock.
|
|
275
|
+
// Only tests set this (small maxWaitMs) to force the acquisition-timeout
|
|
276
|
+
// (`acquired=false`) branch deterministically; production uses the defaults.
|
|
277
|
+
private readonly impressionsLockOptions?: Pick<HeldFileLockOptions, "maxWaitMs" | "pollMs">;
|
|
234
278
|
private state: LastRecallState = {};
|
|
235
279
|
private stateWriteChain: Promise<void> = Promise.resolve();
|
|
236
|
-
|
|
237
|
-
|
|
280
|
+
// Serializes the rotate-then-append critical section so concurrent record()
|
|
281
|
+
// calls never interleave rotation renames with each other's appends (#1910).
|
|
282
|
+
private impressionsWriteChain: Promise<void> = Promise.resolve();
|
|
283
|
+
|
|
284
|
+
constructor(
|
|
285
|
+
memoryDir: string,
|
|
286
|
+
options: {
|
|
287
|
+
writeStateFile?: StateFileWriter;
|
|
288
|
+
impressionsRotateBytes?: number;
|
|
289
|
+
impressionsRotateKeep?: number;
|
|
290
|
+
impressionsLockOptions?: Pick<HeldFileLockOptions, "maxWaitMs" | "pollMs">;
|
|
291
|
+
} = {},
|
|
292
|
+
) {
|
|
238
293
|
this.statePath = path.join(memoryDir, "state", "last_recall.json");
|
|
239
294
|
this.impressionsPath = path.join(memoryDir, "state", "recall_impressions.jsonl");
|
|
295
|
+
// 0 disables rotation (never coerced to a default); keep floors at 1.
|
|
296
|
+
this.impressionsRotateBytes = Math.max(0, Math.floor(options.impressionsRotateBytes ?? 0));
|
|
297
|
+
this.impressionsRotateKeep = Math.max(1, Math.floor(options.impressionsRotateKeep ?? 5));
|
|
298
|
+
this.impressionsLockOptions = options.impressionsLockOptions;
|
|
240
299
|
this.writeStateFile =
|
|
241
300
|
options.writeStateFile ??
|
|
242
301
|
(async (filePath, content) => {
|
|
@@ -292,6 +351,7 @@ export class LastRecallStore {
|
|
|
292
351
|
budgetsApplied?: LastRecallBudgetSummary;
|
|
293
352
|
latencyMs?: number;
|
|
294
353
|
resultPaths?: string[];
|
|
354
|
+
resultNamespaces?: Array<string | undefined>;
|
|
295
355
|
policyVersion?: string;
|
|
296
356
|
appendImpression?: boolean;
|
|
297
357
|
identityInjection?: {
|
|
@@ -318,8 +378,8 @@ export class LastRecallStore {
|
|
|
318
378
|
|
|
319
379
|
// Build the snapshot from opts, then deep-copy it via
|
|
320
380
|
// cloneLastRecallSnapshot so caller arrays/objects passed in
|
|
321
|
-
// `opts` cannot retain a live reference to the persisted state
|
|
322
|
-
//
|
|
381
|
+
// `opts` cannot retain a live reference to the persisted state and
|
|
382
|
+
// tear it after `record()` returns.
|
|
323
383
|
const liveSnapshot: LastRecallSnapshot = {
|
|
324
384
|
sessionKey: opts.sessionKey,
|
|
325
385
|
recordedAt: now,
|
|
@@ -338,6 +398,7 @@ export class LastRecallStore {
|
|
|
338
398
|
budgetsApplied: opts.budgetsApplied,
|
|
339
399
|
latencyMs: opts.latencyMs,
|
|
340
400
|
resultPaths: opts.resultPaths,
|
|
401
|
+
resultNamespaces: opts.resultNamespaces,
|
|
341
402
|
policyVersion: opts.policyVersion,
|
|
342
403
|
identityInjectionMode: opts.identityInjection?.mode,
|
|
343
404
|
identityInjectedChars: opts.identityInjection?.injectedChars,
|
|
@@ -373,15 +434,353 @@ export class LastRecallStore {
|
|
|
373
434
|
}
|
|
374
435
|
|
|
375
436
|
if (opts.appendImpression !== false) {
|
|
437
|
+
const line = JSON.stringify(snapshot) + "\n";
|
|
438
|
+
// Chain onto the previous impression write so rotation + append run as one
|
|
439
|
+
// serialized critical section — concurrent record() calls can never
|
|
440
|
+
// interleave a rename with another call's append (#1910). `.catch` before
|
|
441
|
+
// the link keeps a prior failure from poisoning the chain.
|
|
442
|
+
const chained = this.impressionsWriteChain
|
|
443
|
+
.catch(() => {})
|
|
444
|
+
.then(() => this.appendImpressionSerialized(line));
|
|
445
|
+
this.impressionsWriteChain = chained;
|
|
376
446
|
try {
|
|
377
|
-
await
|
|
378
|
-
await appendFile(this.impressionsPath, JSON.stringify(snapshot) + "\n", "utf-8");
|
|
447
|
+
await chained;
|
|
379
448
|
} catch (err) {
|
|
380
449
|
log.debug(`recall impressions append failed: ${err}`);
|
|
381
450
|
}
|
|
382
451
|
}
|
|
383
452
|
}
|
|
384
453
|
|
|
454
|
+
/**
|
|
455
|
+
* Drain pending spills, rotate (best-effort, sized to the projected payload),
|
|
456
|
+
* then append one impression line under ONE shared cross-process lock (#1910,
|
|
457
|
+
* #2033). Both the archive-shift renames AND the append run inside the same
|
|
458
|
+
* held lock so a peer process holding the lock can never rename the active
|
|
459
|
+
* inode to `.1` between our open and write — which would land the impression in
|
|
460
|
+
* a rotated archive that offline-sync excludes, silently dropping it from
|
|
461
|
+
* active-state/sync consumers.
|
|
462
|
+
*
|
|
463
|
+
* On lock-acquisition timeout the impression is NEVER written to the active
|
|
464
|
+
* file unlocked (#2033): a peer holding the lock is likely mid-rotation, so an
|
|
465
|
+
* unlocked append can land in the inode it is about to rename to `.1` — the
|
|
466
|
+
* exact silent-drop this lock prevents. Instead the row is spilled to a
|
|
467
|
+
* durable node-local per-event file under `<impressions>.pending.d/` and
|
|
468
|
+
* folded back into the active file by the next append that DOES hold the lock,
|
|
469
|
+
* preserving durability without racing rotation. Rotation failure under the
|
|
470
|
+
* held lock is logged and the append still runs. Callers invoke this only
|
|
471
|
+
* through `impressionsWriteChain` so the sequence is serialized in-process.
|
|
472
|
+
*/
|
|
473
|
+
private get impressionsPendingDir(): string {
|
|
474
|
+
return `${this.impressionsPath}.pending.d`;
|
|
475
|
+
}
|
|
476
|
+
|
|
477
|
+
private async spillImpression(line: string): Promise<void> {
|
|
478
|
+
await ensureContainedSpillDir(this.impressionsPendingDir);
|
|
479
|
+
// Write to a temp name the drain's `.jsonl` lister ignores, then atomically
|
|
480
|
+
// rename to the final `<uuid>.jsonl` (#2033). writeFile creates the path
|
|
481
|
+
// before its bytes are durable, so writing straight to the final name lets a
|
|
482
|
+
// concurrent lock holder's drain read/rename/delete a partial spill and
|
|
483
|
+
// append malformed JSON — permanently losing that impression. The temp lives
|
|
484
|
+
// in the SAME contained dir, so the rename is atomic and stays symlink-safe.
|
|
485
|
+
const id = randomUUID();
|
|
486
|
+
const tempPath = path.join(this.impressionsPendingDir, `${id}.jsonl.tmp`);
|
|
487
|
+
const finalPath = path.join(this.impressionsPendingDir, `${id}.jsonl`);
|
|
488
|
+
await writeFile(tempPath, line, "utf-8");
|
|
489
|
+
await rename(tempPath, finalPath);
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* Recover a claim a crashed drain left mid-flight (#2033): the crash-safe
|
|
494
|
+
* drain renames `<uuid>.jsonl` -> `<uuid>.jsonl.claimed` BEFORE committing, so
|
|
495
|
+
* a `.claimed` file with no matching commit is the ONLY durable copy of those
|
|
496
|
+
* rows. Rename each orphan back to `<uuid>.jsonl` so it re-enters the normal
|
|
497
|
+
* collect+claim+commit flow. MUST run under the held rotation lock, before
|
|
498
|
+
* collecting. listContainedSpillFiles skips symlinked/escaping entries.
|
|
499
|
+
*/
|
|
500
|
+
private async recoverOrphanedImpressionClaims(): Promise<void> {
|
|
501
|
+
const orphans = await listContainedSpillFiles(
|
|
502
|
+
this.impressionsPendingDir,
|
|
503
|
+
`.jsonl${CLAIMED_IMPRESSION_SPILL_SUFFIX}`,
|
|
504
|
+
);
|
|
505
|
+
for (const claimedPath of orphans) {
|
|
506
|
+
const original = claimedPath.slice(0, -CLAIMED_IMPRESSION_SPILL_SUFFIX.length);
|
|
507
|
+
await rename(claimedPath, original).catch(() => undefined);
|
|
508
|
+
}
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
/**
|
|
512
|
+
* Recover a crash-orphaned spill temp after its write completed but before
|
|
513
|
+
* the atomic `.tmp` → `.jsonl` rename. Valid JSONL temps are promoted back
|
|
514
|
+
* into the normal queue; incomplete temps remain pending and keep offline sync
|
|
515
|
+
* deferred rather than being discarded.
|
|
516
|
+
*/
|
|
517
|
+
private async recoverOrphanedImpressionTemps(): Promise<void> {
|
|
518
|
+
const temps = await listContainedSpillFiles(this.impressionsPendingDir, ".jsonl.tmp");
|
|
519
|
+
for (const tempPath of temps) {
|
|
520
|
+
let content: string;
|
|
521
|
+
try {
|
|
522
|
+
content = await readFile(tempPath, "utf-8");
|
|
523
|
+
for (const line of content.split("\n")) {
|
|
524
|
+
if (line.trim().length > 0) JSON.parse(line);
|
|
525
|
+
}
|
|
526
|
+
} catch {
|
|
527
|
+
continue;
|
|
528
|
+
}
|
|
529
|
+
const finalPath = tempPath.slice(0, -".tmp".length);
|
|
530
|
+
await rename(tempPath, finalPath).catch(() => undefined);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
|
|
534
|
+
private async appendImpressionSerialized(line: string): Promise<void> {
|
|
535
|
+
await mkdir(path.dirname(this.impressionsPath), { recursive: true });
|
|
536
|
+
// Every active-file write goes under the shared cross-process rotation lock,
|
|
537
|
+
// even when THIS writer's local rotation is disabled (`impressionsRotateBytes
|
|
538
|
+
// <= 0`). A peer process with rotation enabled shares this lock and may
|
|
539
|
+
// rename the active inode to `.1` at any moment, so an unlocked append could
|
|
540
|
+
// land in an offline-sync-excluded archive and be silently dropped (#2033).
|
|
541
|
+
// Only the local rotate DECISION is disabled — the bounded fold skips
|
|
542
|
+
// rotation when this writer's limit is 0 — the lock itself is not.
|
|
543
|
+
const lockPath = `${this.impressionsPath}.lock`;
|
|
544
|
+
await withHeldFileLock(
|
|
545
|
+
lockPath,
|
|
546
|
+
{ staleMs: 30_000, ...this.impressionsLockOptions },
|
|
547
|
+
async (acquired) => {
|
|
548
|
+
// withHeldFileLock falls back to task(false) when it cannot acquire the
|
|
549
|
+
// lock within the budget. Do NOT append to the active file unlocked: a
|
|
550
|
+
// peer holding the lock may be mid-rotation, so an unlocked append could
|
|
551
|
+
// land in the inode it renames to `.1` (an offline-sync-excluded
|
|
552
|
+
// archive), silently dropping the impression. Spill it to the durable
|
|
553
|
+
// pending queue instead — the next lock holder folds it back in (#2033).
|
|
554
|
+
if (!acquired) {
|
|
555
|
+
log.debug("recall impressions rotation lock not acquired; spilling impression to the durable pending queue");
|
|
556
|
+
await this.spillImpression(line);
|
|
557
|
+
return;
|
|
558
|
+
}
|
|
559
|
+
await this.foldPendingImpressionsAndAppend(line);
|
|
560
|
+
},
|
|
561
|
+
);
|
|
562
|
+
}
|
|
563
|
+
|
|
564
|
+
/**
|
|
565
|
+
* Fold any durable pending recall-impression spills into the synced active
|
|
566
|
+
* `recall_impressions.jsonl` WITHOUT recording a new impression (#2033).
|
|
567
|
+
*
|
|
568
|
+
* The pending spill dir is offline-sync-excluded, so an impression that a
|
|
569
|
+
* lock-timed-out `record()` spilled there is absent from an offline-sync
|
|
570
|
+
* snapshot and lost if this node is discarded before the next `record()`
|
|
571
|
+
* folds it back. Offline sync calls this before building a snapshot so a
|
|
572
|
+
* recorded impression always reaches the remote. Fast no-op — no lock and no
|
|
573
|
+
* dir/lock-file creation — when nothing is pending.
|
|
574
|
+
*
|
|
575
|
+
* Returns a {@link DrainPendingImpressionsResult}: `folded` is true when rows
|
|
576
|
+
* were folded into the active file; `pendingDeferred` is true when durable
|
|
577
|
+
* spills still remain in the offline-sync-EXCLUDED queue after this call —
|
|
578
|
+
* because the rotation lock could not be acquired, a spill could not be
|
|
579
|
+
* claimed, or the drain-only fold deferred rows that would only fit by
|
|
580
|
+
* rotating into a sync-excluded archive (#2033). A snapshot taken while
|
|
581
|
+
* `pendingDeferred` is true would silently drop those rows, so the caller MUST
|
|
582
|
+
* NOT report a clean snapshot — it either retries or aborts.
|
|
583
|
+
*/
|
|
584
|
+
async drainPendingImpressions(): Promise<DrainPendingImpressionsResult> {
|
|
585
|
+
if (!(await this.pendingSpillsRemain())) {
|
|
586
|
+
return { folded: false, pendingDeferred: false };
|
|
587
|
+
}
|
|
588
|
+
const lockPath = `${this.impressionsPath}.lock`;
|
|
589
|
+
let folded = false;
|
|
590
|
+
let acquiredLock = false;
|
|
591
|
+
let spillsRemain = false;
|
|
592
|
+
await withHeldFileLock(
|
|
593
|
+
lockPath,
|
|
594
|
+
{ staleMs: 30_000, ...this.impressionsLockOptions },
|
|
595
|
+
async (acquired) => {
|
|
596
|
+
// A peer holds the lock (mid-rotation or mid-append). We MUST NOT touch
|
|
597
|
+
// the active file unlocked (#2033), so the spills stay in the
|
|
598
|
+
// offline-sync-EXCLUDED pending queue. Report the drain as DEFERRED
|
|
599
|
+
// (pendingDeferred=true) so the caller does not build a snapshot that
|
|
600
|
+
// silently omits them; the next lock holder — or a caller retry — folds
|
|
601
|
+
// them in.
|
|
602
|
+
if (!acquired) return;
|
|
603
|
+
acquiredLock = true;
|
|
604
|
+
folded = await this.foldPendingImpressionsAndAppend(null);
|
|
605
|
+
// Even WITH the lock, a spill the fold could not claim or a `.claimed`
|
|
606
|
+
// orphan a failed commit left behind keeps durable rows in the excluded
|
|
607
|
+
// queue. Treat that as an incomplete drain so the caller retries/aborts
|
|
608
|
+
// rather than snapshotting an active file that omits them (#2033).
|
|
609
|
+
spillsRemain = await this.pendingSpillsRemain();
|
|
610
|
+
},
|
|
611
|
+
);
|
|
612
|
+
return { folded, pendingDeferred: !acquiredLock || spillsRemain };
|
|
613
|
+
}
|
|
614
|
+
|
|
615
|
+
/**
|
|
616
|
+
* Claim/commit fold of durable pending impression spills into the active file
|
|
617
|
+
* under the held rotation lock (#2033). `line` is a new impression to append
|
|
618
|
+
* after the drained rows, or null for a drain-only pre-sync fold.
|
|
619
|
+
*
|
|
620
|
+
* Each spill is folded as an INDEPENDENT claim -> append -> finalize unit
|
|
621
|
+
* rather than materializing the whole queue as one joined payload and
|
|
622
|
+
* splitting it in a single synchronous pass (#2033). A multi-hundred-MB drain
|
|
623
|
+
* done as one join/split blocks the event loop long enough for
|
|
624
|
+
* `withHeldFileLock`'s ownership-refresh timer to miss its window, so a peer
|
|
625
|
+
* stale-breaks the 30s lock and rotates/appends concurrently — defeating the
|
|
626
|
+
* rotation lock this drain relies on. The per-file `await`s keep the payload
|
|
627
|
+
* bounded to one spill at a time and let the refresh timer fire between files.
|
|
628
|
+
*
|
|
629
|
+
* The DRAIN-ONLY path (`line === null`, run before an offline-sync snapshot)
|
|
630
|
+
* NEVER rotates a drained row into an archive. `recall_impressions.jsonl.*`
|
|
631
|
+
* is offline-sync-EXCLUDED, so rotating a just-drained row into `.1`/`.2` and
|
|
632
|
+
* then deleting its spill would leave that row only in a path sync omits —
|
|
633
|
+
* silently lost when the node is discarded after a "successful" sync (#2033).
|
|
634
|
+
* It folds only the rows that fit the synced active file under the cap and
|
|
635
|
+
* leaves the rest durable in the pending queue; {@link drainPendingImpressions}
|
|
636
|
+
* then reports the drain DEFERRED so the caller retries or aborts. The
|
|
637
|
+
* record() path (`line !== null`) keeps rotating normally — its archives stay
|
|
638
|
+
* on a live node that is not being discarded.
|
|
639
|
+
*
|
|
640
|
+
* Recovers any crash-orphaned claim first. Each impression carries a unique
|
|
641
|
+
* writeNonce, so a crash-recovered re-commit is a collapsible duplicate, never
|
|
642
|
+
* a lost row. listContainedSpillFiles rejects symlinked/escaping entries; a
|
|
643
|
+
* spill that cannot be claimed is skipped this pass. An append failure rolls
|
|
644
|
+
* that spill's claim back so the row retries on the next lock holder's drain.
|
|
645
|
+
* Returns true when the active file was written. MUST run under the held
|
|
646
|
+
* rotation lock.
|
|
647
|
+
*/
|
|
648
|
+
private async foldPendingImpressionsAndAppend(line: string | null): Promise<boolean> {
|
|
649
|
+
await this.recoverOrphanedImpressionTemps();
|
|
650
|
+
await this.recoverOrphanedImpressionClaims();
|
|
651
|
+
const spillFiles = await listContainedSpillFiles(this.impressionsPendingDir);
|
|
652
|
+
const drainOnly = line === null;
|
|
653
|
+
const cap = this.impressionsRotateBytes;
|
|
654
|
+
let activeSize = 0;
|
|
655
|
+
if (cap > 0) {
|
|
656
|
+
try {
|
|
657
|
+
activeSize = (await stat(this.impressionsPath)).size;
|
|
658
|
+
} catch (err) {
|
|
659
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
660
|
+
}
|
|
661
|
+
}
|
|
662
|
+
let wrote = false;
|
|
663
|
+
for (const filePath of spillFiles) {
|
|
664
|
+
const content = await readFile(filePath, "utf-8");
|
|
665
|
+
const unit = content.length === 0 || content.endsWith("\n") ? content : `${content}\n`;
|
|
666
|
+
const unitBytes = Buffer.byteLength(unit, "utf-8");
|
|
667
|
+
// Drain-only fold must never push a drained row into a sync-excluded
|
|
668
|
+
// archive (#2033). Once the active file cannot take this spill under the
|
|
669
|
+
// cap without rotating, stop: the remaining spills stay durable in the
|
|
670
|
+
// pending queue and the drain reports itself deferred. A lone spill larger
|
|
671
|
+
// than the cap on an empty active file is still folded whole (it cannot be
|
|
672
|
+
// split without corrupting JSONL) so it reaches sync rather than stranding.
|
|
673
|
+
if (drainOnly && cap > 0 && activeSize > 0 && activeSize + unitBytes >= cap) break;
|
|
674
|
+
const claimedPath = `${filePath}${CLAIMED_IMPRESSION_SPILL_SUFFIX}`;
|
|
675
|
+
try {
|
|
676
|
+
await rename(filePath, claimedPath);
|
|
677
|
+
} catch {
|
|
678
|
+
continue; // could not claim → do not commit; a later drain retries it.
|
|
679
|
+
}
|
|
680
|
+
try {
|
|
681
|
+
activeSize = await this.appendImpressionUnit(unit, activeSize, drainOnly);
|
|
682
|
+
} catch (err) {
|
|
683
|
+
// Commit failed: roll this spill's claim back so it retries on the next
|
|
684
|
+
// lock holder's drain instead of being lost.
|
|
685
|
+
await rename(claimedPath, filePath).catch(() => undefined);
|
|
686
|
+
throw err;
|
|
687
|
+
}
|
|
688
|
+
// Commit is durable: delete the claimed file. A delete that fails leaves a
|
|
689
|
+
// `.claimed` orphan the next drain recovers and re-commits — a
|
|
690
|
+
// writeNonce-collapsible duplicate, never a lost row (#2033).
|
|
691
|
+
await unlink(claimedPath).catch(() => undefined);
|
|
692
|
+
wrote = true;
|
|
693
|
+
}
|
|
694
|
+
if (line !== null) {
|
|
695
|
+
activeSize = await this.appendImpressionUnit(line, activeSize, false);
|
|
696
|
+
wrote = true;
|
|
697
|
+
}
|
|
698
|
+
return wrote;
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Append one whole JSONL unit (a claimed spill's rows or a fresh impression
|
|
703
|
+
* line) to the active impressions file, returning the resulting active-file
|
|
704
|
+
* byte size. On the rotating (record) path, when the unit would push the
|
|
705
|
+
* current active generation to/over `impressionsRotateBytes`, the full active
|
|
706
|
+
* file is rotated aside FIRST so no generation exceeds the cap (#2033); a lone
|
|
707
|
+
* unit larger than the cap on an empty active file is written whole because
|
|
708
|
+
* splitting a JSONL row would corrupt it. `drainOnly` and disabled rotation
|
|
709
|
+
* (`impressionsRotateBytes <= 0`) both skip rotation — drain-only defers its
|
|
710
|
+
* overflow in {@link foldPendingImpressionsAndAppend} rather than rotating into
|
|
711
|
+
* a sync-excluded archive. A rotation error is logged and the append still
|
|
712
|
+
* runs so a row is never lost; an append failure propagates so the caller
|
|
713
|
+
* rolls its claim back. MUST run under the held rotation lock.
|
|
714
|
+
*/
|
|
715
|
+
private async appendImpressionUnit(
|
|
716
|
+
unit: string,
|
|
717
|
+
activeSize: number,
|
|
718
|
+
drainOnly: boolean,
|
|
719
|
+
): Promise<number> {
|
|
720
|
+
const cap = this.impressionsRotateBytes;
|
|
721
|
+
const unitBytes = Buffer.byteLength(unit, "utf-8");
|
|
722
|
+
if (cap > 0 && !drainOnly && activeSize > 0 && activeSize + unitBytes >= cap) {
|
|
723
|
+
try {
|
|
724
|
+
await this.shiftImpressionArchives();
|
|
725
|
+
activeSize = 0;
|
|
726
|
+
} catch (err) {
|
|
727
|
+
log.debug(`recall impressions rotation failed (append preserved): ${err}`);
|
|
728
|
+
}
|
|
729
|
+
}
|
|
730
|
+
await appendFile(this.impressionsPath, unit, "utf-8");
|
|
731
|
+
return activeSize + unitBytes;
|
|
732
|
+
}
|
|
733
|
+
|
|
734
|
+
/**
|
|
735
|
+
* True when any live `<uuid>.jsonl` spill, crash-orphaned `.claimed` file,
|
|
736
|
+
* or crash-orphaned `.jsonl.tmp` spill remains in the offline-sync-EXCLUDED
|
|
737
|
+
* pending queue (#2033). After a drain acquires the rotation lock, a spill
|
|
738
|
+
* the fold could not claim (rename race / read-only dir) or a `.claimed`
|
|
739
|
+
* orphan a failed commit left behind means durable rows are STILL excluded
|
|
740
|
+
* from a snapshot — the drain must report itself INCOMPLETE so the caller
|
|
741
|
+
* retries or aborts rather than snapshotting an active file that omits them.
|
|
742
|
+
*/
|
|
743
|
+
private async pendingSpillsRemain(): Promise<boolean> {
|
|
744
|
+
if ((await listContainedSpillFiles(this.impressionsPendingDir, ".jsonl.tmp")).length > 0) {
|
|
745
|
+
return true;
|
|
746
|
+
}
|
|
747
|
+
const liveSpills = await listContainedSpillFiles(this.impressionsPendingDir);
|
|
748
|
+
if (liveSpills.length > 0) return true;
|
|
749
|
+
const claimed = await listContainedSpillFiles(
|
|
750
|
+
this.impressionsPendingDir,
|
|
751
|
+
`.jsonl${CLAIMED_IMPRESSION_SPILL_SUFFIX}`,
|
|
752
|
+
);
|
|
753
|
+
return claimed.length > 0;
|
|
754
|
+
}
|
|
755
|
+
|
|
756
|
+
/**
|
|
757
|
+
* Shift `.1..N` archives down one slot and move the active file to `.1`,
|
|
758
|
+
* dropping anything beyond `keep`. Callers invoke this only while holding the
|
|
759
|
+
* cross-process rotation lock (issue #1910).
|
|
760
|
+
*/
|
|
761
|
+
private async shiftImpressionArchives(): Promise<void> {
|
|
762
|
+
const keep = this.impressionsRotateKeep;
|
|
763
|
+
// Drop the archive that would fall off the end, then shift down: .(keep-1)
|
|
764
|
+
// -> .keep, ..., .1 -> .2, active -> .1.
|
|
765
|
+
try {
|
|
766
|
+
await rm(`${this.impressionsPath}.${keep}`, { force: true });
|
|
767
|
+
} catch {
|
|
768
|
+
// best-effort cleanup of the oldest archive
|
|
769
|
+
}
|
|
770
|
+
for (let i = keep - 1; i >= 1; i -= 1) {
|
|
771
|
+
try {
|
|
772
|
+
await rename(`${this.impressionsPath}.${i}`, `${this.impressionsPath}.${i + 1}`);
|
|
773
|
+
} catch (err) {
|
|
774
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
775
|
+
}
|
|
776
|
+
}
|
|
777
|
+
try {
|
|
778
|
+
await rename(this.impressionsPath, `${this.impressionsPath}.1`);
|
|
779
|
+
} catch (err) {
|
|
780
|
+
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
781
|
+
}
|
|
782
|
+
}
|
|
783
|
+
|
|
385
784
|
/**
|
|
386
785
|
* Attach a RecallTierExplain block to the existing snapshot for a
|
|
387
786
|
* session without rewriting the entire snapshot. Used by the
|
|
@@ -201,6 +201,47 @@ test("recall timing records expose only the fixed telemetry schema", () => {
|
|
|
201
201
|
});
|
|
202
202
|
});
|
|
203
203
|
|
|
204
|
+
test("trustStage is allowlisted and its ms is parsed (issue #1905)", () => {
|
|
205
|
+
const config = makeConfig(path.join(os.tmpdir(), "remnic-recall-timing-trust"));
|
|
206
|
+
recordRecallTiming(config, {
|
|
207
|
+
timestamp: new Date(0).toISOString(),
|
|
208
|
+
namespace: "default",
|
|
209
|
+
total: "10ms",
|
|
210
|
+
trustStage: "3ms",
|
|
211
|
+
recallPlan: "full",
|
|
212
|
+
queryPolicy: "general/full",
|
|
213
|
+
});
|
|
214
|
+
recordRecallTiming(config, {
|
|
215
|
+
timestamp: new Date(1).toISOString(),
|
|
216
|
+
namespace: "default",
|
|
217
|
+
total: "10ms",
|
|
218
|
+
trustStage: "2ms-cache",
|
|
219
|
+
recallPlan: "full",
|
|
220
|
+
queryPolicy: "general/full",
|
|
221
|
+
});
|
|
222
|
+
const records = getRecallTimings(config);
|
|
223
|
+
// newest-first ordering
|
|
224
|
+
assert.equal(records[0]?.timingsMs.trustStage, 2, "\"2ms-cache\" parses to numeric 2");
|
|
225
|
+
assert.equal(records[1]?.timingsMs.trustStage, 3, "\"3ms\" parses to numeric 3");
|
|
226
|
+
});
|
|
227
|
+
|
|
228
|
+
test("queueWaitMs is allowlisted and parsed while a non-allowlisted sibling is dropped (issue #1906)", () => {
|
|
229
|
+
const config = makeConfig(path.join(os.tmpdir(), "remnic-recall-timing-queuewait"));
|
|
230
|
+
recordRecallTiming(config, {
|
|
231
|
+
timestamp: new Date(0).toISOString(),
|
|
232
|
+
namespace: "default",
|
|
233
|
+
total: "42ms",
|
|
234
|
+
queueWaitMs: "12ms",
|
|
235
|
+
queueWaitDebug: "99ms",
|
|
236
|
+
recallPlan: "full",
|
|
237
|
+
queryPolicy: "general/full",
|
|
238
|
+
});
|
|
239
|
+
const record = getRecallTimings(config)[0];
|
|
240
|
+
assert.ok(record);
|
|
241
|
+
assert.equal(record.timingsMs.queueWaitMs, 12);
|
|
242
|
+
assert.equal("queueWaitDebug" in record.timingsMs, false);
|
|
243
|
+
});
|
|
244
|
+
|
|
204
245
|
test("phases that did not run are omitted while measured zeros survive", () => {
|
|
205
246
|
const config = makeConfig(path.join(os.tmpdir(), "remnic-recall-timing-phases"));
|
|
206
247
|
recordRecallTiming(config, {
|
package/src/recall-timings.ts
CHANGED
|
@@ -44,6 +44,8 @@ const TIMING_FIELD_ALLOWLIST = [
|
|
|
44
44
|
"compounding",
|
|
45
45
|
"graphShadow",
|
|
46
46
|
"qmdPost",
|
|
47
|
+
"trustStage",
|
|
48
|
+
"queueWaitMs",
|
|
47
49
|
] as const;
|
|
48
50
|
// The ring buffer is process-local: a daemon restart or haproxy failover to
|
|
49
51
|
// the other backend starts an empty history. processStartedAt lets consumers
|
|
@@ -85,6 +87,20 @@ function sanitizeRecallTiming(
|
|
|
85
87
|
};
|
|
86
88
|
}
|
|
87
89
|
|
|
90
|
+
/**
|
|
91
|
+
* Build the recall `timings` map, seeding the additive queue-wait phase (issue
|
|
92
|
+
* #1906) when the caller measured a real per-principal slot / single-flight
|
|
93
|
+
* wait. `queueWaitMs` 0/undefined/non-finite omits the phase so recall-timings
|
|
94
|
+
* stays byte-identical to the uncontended pre-#1906 path.
|
|
95
|
+
*/
|
|
96
|
+
export function foldQueueWaitTiming(queueWaitMs?: number): Record<string, string> {
|
|
97
|
+
const timings: Record<string, string> = {};
|
|
98
|
+
if (typeof queueWaitMs === "number" && Number.isFinite(queueWaitMs) && queueWaitMs >= 0) {
|
|
99
|
+
timings.queueWaitMs = `${queueWaitMs}ms`;
|
|
100
|
+
}
|
|
101
|
+
return timings;
|
|
102
|
+
}
|
|
103
|
+
|
|
88
104
|
export function recordRecallTiming(
|
|
89
105
|
config: PluginConfig,
|
|
90
106
|
input: Record<string, unknown>,
|
|
@@ -367,25 +367,25 @@ test("Relay write quota releases the exact reservation when timestamps collide",
|
|
|
367
367
|
adminConsoleEnabled: false,
|
|
368
368
|
});
|
|
369
369
|
const internals = server as unknown as {
|
|
370
|
-
|
|
370
|
+
writeLimiter: { slotsFor(principal?: string): ReadonlyArray<{ readonly recordedAt: number }> };
|
|
371
371
|
reserveWriteRateLimitSlot: () => () => void;
|
|
372
372
|
};
|
|
373
373
|
const originalNow = Date.now;
|
|
374
374
|
try {
|
|
375
375
|
Date.now = () => 1_754_000_000_000;
|
|
376
376
|
const releaseCommitted = internals.reserveWriteRateLimitSlot();
|
|
377
|
-
const committedSlot = internals.
|
|
377
|
+
const committedSlot = internals.writeLimiter.slotsFor()[0];
|
|
378
378
|
const releaseFailed = internals.reserveWriteRateLimitSlot();
|
|
379
|
-
const failedSlot = internals.
|
|
379
|
+
const failedSlot = internals.writeLimiter.slotsFor()[1];
|
|
380
380
|
assert.ok(committedSlot);
|
|
381
381
|
assert.ok(failedSlot);
|
|
382
382
|
assert.notEqual(committedSlot, failedSlot);
|
|
383
383
|
|
|
384
384
|
releaseFailed();
|
|
385
|
-
assert.deepEqual(internals.
|
|
385
|
+
assert.deepEqual(internals.writeLimiter.slotsFor(), [committedSlot]);
|
|
386
386
|
|
|
387
387
|
releaseCommitted();
|
|
388
|
-
assert.deepEqual(internals.
|
|
388
|
+
assert.deepEqual(internals.writeLimiter.slotsFor(), []);
|
|
389
389
|
} finally {
|
|
390
390
|
Date.now = originalNow;
|
|
391
391
|
}
|
package/src/rerank.ts
CHANGED
|
@@ -173,3 +173,25 @@ export async function rerankLocalOrNoop(opts: {
|
|
|
173
173
|
|
|
174
174
|
return rankedIds;
|
|
175
175
|
}
|
|
176
|
+
|
|
177
|
+
/**
|
|
178
|
+
* Reorder `results` to match `rankedKeys` (a ranker's output order), keying by
|
|
179
|
+
* `keyOf`. Items not present in `rankedKeys` are appended in their original
|
|
180
|
+
* order. `keyOf` must return a stable identity (e.g. namespace-qualified) so
|
|
181
|
+
* same-relative-path items across namespaces are not conflated.
|
|
182
|
+
*/
|
|
183
|
+
export function reorderByRankedKeys<T>(
|
|
184
|
+
results: readonly T[],
|
|
185
|
+
rankedKeys: readonly string[],
|
|
186
|
+
keyOf: (item: T) => string,
|
|
187
|
+
): T[] {
|
|
188
|
+
const byKey = new Map(results.map((r) => [keyOf(r), r]));
|
|
189
|
+
const reordered: T[] = [];
|
|
190
|
+
for (const key of rankedKeys) {
|
|
191
|
+
const it = byKey.get(key);
|
|
192
|
+
if (it) reordered.push(it);
|
|
193
|
+
}
|
|
194
|
+
const rankedSet = new Set(rankedKeys);
|
|
195
|
+
for (const r of results) if (!rankedSet.has(keyOf(r))) reordered.push(r);
|
|
196
|
+
return reordered;
|
|
197
|
+
}
|