@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
|
@@ -21,6 +21,7 @@ function baseConfig(overrides: Partial<ActiveRecallConfig> = {}): ActiveRecallCo
|
|
|
21
21
|
queryMode: "recent",
|
|
22
22
|
promptStyle: "balanced",
|
|
23
23
|
customInstruction: null,
|
|
24
|
+
promptReplacement: null,
|
|
24
25
|
promptAppend: null,
|
|
25
26
|
maxSummaryChars: 64,
|
|
26
27
|
recentUserTurns: 2,
|
|
@@ -130,6 +131,40 @@ test("buildActiveRecallPrompt varies by prompt style and optional sections", ()
|
|
|
130
131
|
assert.match(prompt, /Prefer hard evidence/);
|
|
131
132
|
});
|
|
132
133
|
|
|
134
|
+
test("buildActiveRecallPrompt treats prompt replacement as a complete replacement", () => {
|
|
135
|
+
const prompt = buildActiveRecallPrompt({
|
|
136
|
+
config: baseConfig({
|
|
137
|
+
customInstruction: "ignored custom instruction",
|
|
138
|
+
promptReplacement: "Use only the supplied evidence.",
|
|
139
|
+
promptAppend: "ignored append",
|
|
140
|
+
}),
|
|
141
|
+
queryBundle: "current: What happened?",
|
|
142
|
+
recallContext: "The deploy was rolled back.",
|
|
143
|
+
graphContext: ["entity edge"],
|
|
144
|
+
causalContext: ["causal link"],
|
|
145
|
+
daySummary: "Debugged worker drain all morning.",
|
|
146
|
+
recallExplain: "graph_mode",
|
|
147
|
+
});
|
|
148
|
+
assert.equal(prompt, "Use only the supplied evidence.");
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
test("buildActiveRecallPrompt gives replacement precedence over legacy custom instruction", () => {
|
|
152
|
+
const prompt = buildActiveRecallPrompt({
|
|
153
|
+
config: baseConfig({
|
|
154
|
+
customInstruction: "legacy guidance",
|
|
155
|
+
promptReplacement: "Use only the supplied evidence.",
|
|
156
|
+
}),
|
|
157
|
+
queryBundle: "current: What happened?",
|
|
158
|
+
recallContext: "The deploy was rolled back.",
|
|
159
|
+
graphContext: [],
|
|
160
|
+
causalContext: [],
|
|
161
|
+
daySummary: null,
|
|
162
|
+
recallExplain: null,
|
|
163
|
+
});
|
|
164
|
+
|
|
165
|
+
assert.equal(prompt, "Use only the supplied evidence.");
|
|
166
|
+
});
|
|
167
|
+
|
|
133
168
|
test("normalizeActiveRecallSummary collapses NONE variants and truncates codepoint-safe", () => {
|
|
134
169
|
assert.equal(normalizeActiveRecallSummary("NONE", 20), null);
|
|
135
170
|
assert.equal(normalizeActiveRecallSummary(" no relevant memory ", 20), null);
|
package/src/active-recall.ts
CHANGED
|
@@ -30,6 +30,7 @@ export interface ActiveRecallConfig {
|
|
|
30
30
|
queryMode: ActiveRecallQueryMode;
|
|
31
31
|
promptStyle: ActiveRecallPromptStyle;
|
|
32
32
|
customInstruction: string | null;
|
|
33
|
+
promptReplacement: string | null;
|
|
33
34
|
promptAppend: string | null;
|
|
34
35
|
maxSummaryChars: number;
|
|
35
36
|
recentUserTurns: number;
|
|
@@ -133,6 +134,7 @@ function buildCacheKey(input: ActiveRecallInput, config: ActiveRecallConfig, que
|
|
|
133
134
|
queryMode: config.queryMode,
|
|
134
135
|
promptStyle: config.promptStyle,
|
|
135
136
|
customInstruction: config.customInstruction,
|
|
137
|
+
promptReplacement: config.promptReplacement,
|
|
136
138
|
promptAppend: config.promptAppend,
|
|
137
139
|
maxSummaryChars: config.maxSummaryChars,
|
|
138
140
|
entityGraphDepth: config.entityGraphDepth,
|
|
@@ -262,6 +264,11 @@ export function buildActiveRecallPrompt(params: {
|
|
|
262
264
|
daySummary: string | null;
|
|
263
265
|
recallExplain: string | null;
|
|
264
266
|
}): string {
|
|
267
|
+
const promptReplacement = params.config.promptReplacement?.trim();
|
|
268
|
+
if (promptReplacement) {
|
|
269
|
+
return promptReplacement;
|
|
270
|
+
}
|
|
271
|
+
|
|
265
272
|
const sections = [
|
|
266
273
|
params.config.customInstruction?.trim() || STYLE_INSTRUCTIONS[params.config.promptStyle],
|
|
267
274
|
`Query bundle:\n${params.queryBundle}`,
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bounded JSONL state configuration (issue #1910).
|
|
3
|
+
*
|
|
4
|
+
* Extracted from `config.ts`/`types.ts` so the god-file line-count ratchets
|
|
5
|
+
* (issue #1995) do not grow: `PluginConfig` extends the interface below and
|
|
6
|
+
* `parseConfig` spreads `parseBoundedJsonlStateConfig`. No behavior change —
|
|
7
|
+
* the knobs, defaults, and coercion rules are identical to the inline forms.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** Knobs that bound the unbounded JSONL state files (issue #1910). */
|
|
11
|
+
export interface BoundedJsonlStateConfig {
|
|
12
|
+
/**
|
|
13
|
+
* Auto-compact `state/memory-lifecycle-ledger.jsonl` when it exceeds this many
|
|
14
|
+
* bytes, triggered off the debounced maintenance path. `0` disables. Default
|
|
15
|
+
* 64MB.
|
|
16
|
+
*/
|
|
17
|
+
memoryLifecycleLedgerCompactBytes: number;
|
|
18
|
+
/**
|
|
19
|
+
* Minimum interval between auto-compactions of the lifecycle ledger, so a
|
|
20
|
+
* heavy rebuild cannot run back-to-back. Floored at 60s. Default 6h.
|
|
21
|
+
*/
|
|
22
|
+
memoryLifecycleLedgerCompactMinIntervalMs: number;
|
|
23
|
+
/**
|
|
24
|
+
* Rotate `state/recall_impressions.jsonl` to `.1..N` when it exceeds this many
|
|
25
|
+
* bytes. `0` disables. Default 32MB.
|
|
26
|
+
*/
|
|
27
|
+
recallImpressionsRotateBytes: number;
|
|
28
|
+
/**
|
|
29
|
+
* Number of rotated recall-impression archives to keep (`.1 .. .N`). Floored
|
|
30
|
+
* at 1 when rotation is enabled. Default 5.
|
|
31
|
+
*/
|
|
32
|
+
recallImpressionsRotateKeep: number;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/** Integer coercion contract shared with `config.ts` (`parseIntegerAtLeast`). */
|
|
36
|
+
type IntegerParser = (value: unknown, fallback: number, min: number, keyName: string) => number;
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Upper bound for `recallImpressionsRotateKeep`. Each retained slot costs one
|
|
40
|
+
* rename under the held cross-process impressions lock on every rotation, so an
|
|
41
|
+
* accidentally huge value (a `1000000` typo) would stall recall recording and
|
|
42
|
+
* block other writers. 1000 archives is already far past any real retention
|
|
43
|
+
* need; a larger request is REJECTED before it reaches the rotation loop (#2033).
|
|
44
|
+
*/
|
|
45
|
+
export const RECALL_IMPRESSIONS_ROTATE_KEEP_MAX = 1000;
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
* Parse the bounded-state knobs. Numeric knobs accept CLI/overlay string forms
|
|
49
|
+
* (Gotcha #28) via `coerceNumber`, then require an integer >= min. A
|
|
50
|
+
* present-but-malformed or fractional value is REJECTED (throws) rather than
|
|
51
|
+
* silently taking the default; only an absent value falls back. `0` survives
|
|
52
|
+
* when `min` is 0, so the documented disable stays effective on every surface
|
|
53
|
+
* (byte thresholds floor at 0, the min-interval at 60s, and the keep count at 1
|
|
54
|
+
* so rotation always retains at least one archive).
|
|
55
|
+
*/
|
|
56
|
+
export function parseBoundedJsonlStateConfig(
|
|
57
|
+
cfg: Record<string, unknown>,
|
|
58
|
+
parseIntegerAtLeast: IntegerParser,
|
|
59
|
+
): BoundedJsonlStateConfig {
|
|
60
|
+
const recallImpressionsRotateKeep = parseIntegerAtLeast(
|
|
61
|
+
cfg.recallImpressionsRotateKeep,
|
|
62
|
+
5,
|
|
63
|
+
1,
|
|
64
|
+
"recallImpressionsRotateKeep",
|
|
65
|
+
);
|
|
66
|
+
if (recallImpressionsRotateKeep > RECALL_IMPRESSIONS_ROTATE_KEEP_MAX) {
|
|
67
|
+
throw new Error(
|
|
68
|
+
`recallImpressionsRotateKeep must be an integer between 1 and `
|
|
69
|
+
+ `${RECALL_IMPRESSIONS_ROTATE_KEEP_MAX}; got ${JSON.stringify(cfg.recallImpressionsRotateKeep)}`,
|
|
70
|
+
);
|
|
71
|
+
}
|
|
72
|
+
return {
|
|
73
|
+
memoryLifecycleLedgerCompactBytes: parseIntegerAtLeast(
|
|
74
|
+
cfg.memoryLifecycleLedgerCompactBytes,
|
|
75
|
+
64 * 1024 * 1024,
|
|
76
|
+
0,
|
|
77
|
+
"memoryLifecycleLedgerCompactBytes",
|
|
78
|
+
),
|
|
79
|
+
memoryLifecycleLedgerCompactMinIntervalMs: parseIntegerAtLeast(
|
|
80
|
+
cfg.memoryLifecycleLedgerCompactMinIntervalMs,
|
|
81
|
+
6 * 60 * 60 * 1000,
|
|
82
|
+
60_000,
|
|
83
|
+
"memoryLifecycleLedgerCompactMinIntervalMs",
|
|
84
|
+
),
|
|
85
|
+
recallImpressionsRotateBytes: parseIntegerAtLeast(
|
|
86
|
+
cfg.recallImpressionsRotateBytes,
|
|
87
|
+
32 * 1024 * 1024,
|
|
88
|
+
0,
|
|
89
|
+
"recallImpressionsRotateBytes",
|
|
90
|
+
),
|
|
91
|
+
recallImpressionsRotateKeep,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
@@ -7,6 +7,7 @@ import type { BufferState, BufferTurn } from "./types.js";
|
|
|
7
7
|
|
|
8
8
|
class FakeStorage {
|
|
9
9
|
public saved: BufferState | null = null;
|
|
10
|
+
public saveCount = 0;
|
|
10
11
|
|
|
11
12
|
constructor(private readonly initial: BufferState) {}
|
|
12
13
|
|
|
@@ -15,6 +16,7 @@ class FakeStorage {
|
|
|
15
16
|
}
|
|
16
17
|
|
|
17
18
|
async saveBuffer(state: BufferState): Promise<void> {
|
|
19
|
+
this.saveCount += 1;
|
|
18
20
|
this.saved = structuredClone(state);
|
|
19
21
|
}
|
|
20
22
|
}
|
|
@@ -97,7 +99,7 @@ test("SmartBuffer keeps dangerous keys isolated from safe-prefix lookalikes", as
|
|
|
97
99
|
|
|
98
100
|
test("SmartBuffer serializes concurrent addTurn mutations", async () => {
|
|
99
101
|
const storage = new DelayedBufferStorage();
|
|
100
|
-
const buffer = new SmartBuffer(parseConfig({}), storage as
|
|
102
|
+
const buffer = new SmartBuffer(parseConfig({ bufferSaveDebounceMs: 0 }), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
101
103
|
|
|
102
104
|
await Promise.all([
|
|
103
105
|
buffer.addTurn("thread-a", makeTurn("thread-a", "alpha memory")),
|
|
@@ -270,7 +272,7 @@ test("SmartBuffer read-only accessors do not persist phantom entries for unknown
|
|
|
270
272
|
lastExtractionAt: null,
|
|
271
273
|
extractionCount: 0,
|
|
272
274
|
});
|
|
273
|
-
const buffer = new SmartBuffer(parseConfig({}), storage as
|
|
275
|
+
const buffer = new SmartBuffer(parseConfig({ bufferSaveDebounceMs: 0 }), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
274
276
|
|
|
275
277
|
assert.deepEqual(buffer.getTurns("missing-thread"), []);
|
|
276
278
|
assert.equal(buffer.getExtractionCount("missing-thread"), 0);
|
|
@@ -373,7 +375,7 @@ test("SmartBuffer prunes stale logical session buffers to a bounded entry set",
|
|
|
373
375
|
...entries,
|
|
374
376
|
},
|
|
375
377
|
});
|
|
376
|
-
const buffer = new SmartBuffer(parseConfig({}), storage as
|
|
378
|
+
const buffer = new SmartBuffer(parseConfig({ bufferSaveDebounceMs: 0 }), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
377
379
|
|
|
378
380
|
await buffer.addTurn("active-thread", makeTurn("active-thread", "pending memory"));
|
|
379
381
|
|
|
@@ -522,7 +524,7 @@ test("SmartBuffer prefers pruning empty entries and bounds pending-turn buffers
|
|
|
522
524
|
...entries,
|
|
523
525
|
},
|
|
524
526
|
});
|
|
525
|
-
const buffer = new SmartBuffer(parseConfig({}), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
527
|
+
const buffer = new SmartBuffer(parseConfig({ bufferSaveDebounceMs: 0 }), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
526
528
|
|
|
527
529
|
await buffer.addTurn("active-thread", makeTurn("active-thread", "pending memory"));
|
|
528
530
|
|
|
@@ -549,7 +551,7 @@ test("pruneEntries evicts oldest NON-empty session entries past the cap (#1908 r
|
|
|
549
551
|
};
|
|
550
552
|
}
|
|
551
553
|
const storage = new FakeStorage({ turns: [], lastExtractionAt: null, extractionCount: 0, entries });
|
|
552
|
-
const buffer = new SmartBuffer(parseConfig({}), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
554
|
+
const buffer = new SmartBuffer(parseConfig({ bufferSaveDebounceMs: 0 }), storage as unknown as ConstructorParameters<typeof SmartBuffer>[1]);
|
|
553
555
|
await buffer.load();
|
|
554
556
|
await buffer.addTurn("session-newest", makeTurn("session-newest", "new turn"));
|
|
555
557
|
|
|
@@ -559,3 +561,418 @@ test("pruneEntries evicts oldest NON-empty session entries past the cap (#1908 r
|
|
|
559
561
|
assert.equal(buffer.getTurns("session-000").length, 0, "oldest non-empty entry was evicted");
|
|
560
562
|
assert.ok(buffer.getTurns("session-209").length > 0, "newest pre-existing entry survives");
|
|
561
563
|
});
|
|
564
|
+
|
|
565
|
+
// ---------------------------------------------------------------------------
|
|
566
|
+
// Issue #1909 (Part D) — debounced buffer save
|
|
567
|
+
// ---------------------------------------------------------------------------
|
|
568
|
+
|
|
569
|
+
function emptyBufferState(): BufferState {
|
|
570
|
+
return { turns: [], lastExtractionAt: null, extractionCount: 0 };
|
|
571
|
+
}
|
|
572
|
+
|
|
573
|
+
interface DebouncedBufferInternals {
|
|
574
|
+
saveTimer: NodeJS.Timeout | null;
|
|
575
|
+
pendingSave: boolean;
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
test("debounce on: N keep_buffering turns coalesce into one save on flush", async () => {
|
|
579
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
580
|
+
// Large window + high turn cap so every turn keeps buffering (no trigger).
|
|
581
|
+
const buffer = new SmartBuffer(
|
|
582
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 100 }),
|
|
583
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
584
|
+
);
|
|
585
|
+
|
|
586
|
+
for (let i = 0; i < 5; i += 1) {
|
|
587
|
+
const decision = await buffer.addTurn("thread-a", makeTurn("thread-a", `turn ${i}`));
|
|
588
|
+
assert.equal(decision, "keep_buffering");
|
|
589
|
+
}
|
|
590
|
+
assert.equal(storage.saveCount, 0, "steady-state buffering does zero full serializations");
|
|
591
|
+
|
|
592
|
+
await buffer.flushPendingSave();
|
|
593
|
+
assert.equal(storage.saveCount, 1, "the trailing-edge flush writes exactly once");
|
|
594
|
+
assert.equal(storage.saved?.entries?.["thread-a"]?.turns.length, 5, "flush persists all buffered turns");
|
|
595
|
+
|
|
596
|
+
// Idempotent: a second flush with nothing pending does not write again.
|
|
597
|
+
await buffer.flushPendingSave();
|
|
598
|
+
assert.equal(storage.saveCount, 1, "flushPendingSave is idempotent");
|
|
599
|
+
});
|
|
600
|
+
|
|
601
|
+
test("debounce on: an extraction-triggering turn forces an immediate save", async () => {
|
|
602
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
603
|
+
const buffer = new SmartBuffer(
|
|
604
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 1 }),
|
|
605
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
606
|
+
);
|
|
607
|
+
|
|
608
|
+
const decision = await buffer.addTurn("thread-a", makeTurn("thread-a", "trigger"));
|
|
609
|
+
assert.notEqual(decision, "keep_buffering", "the turn triggers extraction");
|
|
610
|
+
assert.equal(storage.saveCount, 1, "the triggering turn is durable immediately, not on the debounce edge");
|
|
611
|
+
assert.equal(storage.saved?.entries?.["thread-a"]?.turns.length, 1);
|
|
612
|
+
});
|
|
613
|
+
|
|
614
|
+
test("debounce on: clearAfterExtraction cancels the pending timer and persists post-clear state", async () => {
|
|
615
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
616
|
+
const buffer = new SmartBuffer(
|
|
617
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 100 }),
|
|
618
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
619
|
+
);
|
|
620
|
+
|
|
621
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "buffered turn"));
|
|
622
|
+
assert.equal(storage.saveCount, 0, "the buffered turn's save is still pending on the timer");
|
|
623
|
+
|
|
624
|
+
await buffer.clearAfterExtraction("thread-a");
|
|
625
|
+
assert.equal(storage.saveCount, 1, "clearAfterExtraction persists exactly once (post-clear state)");
|
|
626
|
+
assert.equal(storage.saved?.entries?.["thread-a"]?.turns.length, 0, "the persisted state is cleared");
|
|
627
|
+
|
|
628
|
+
// The pending debounce timer was cancelled — it must not fire a stale write.
|
|
629
|
+
const internals = buffer as unknown as DebouncedBufferInternals;
|
|
630
|
+
assert.equal(internals.saveTimer, null, "no armed timer remains after clear");
|
|
631
|
+
assert.equal(internals.pendingSave, false, "no pending save remains after clear");
|
|
632
|
+
});
|
|
633
|
+
|
|
634
|
+
test("debounce off (bufferSaveDebounceMs: 0) reproduces save-every-turn", async () => {
|
|
635
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
636
|
+
const buffer = new SmartBuffer(
|
|
637
|
+
parseConfig({ bufferSaveDebounceMs: 0, triggerMode: "smart", bufferMaxTurns: 100 }),
|
|
638
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
639
|
+
);
|
|
640
|
+
|
|
641
|
+
for (let i = 0; i < 4; i += 1) {
|
|
642
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", `turn ${i}`));
|
|
643
|
+
}
|
|
644
|
+
assert.equal(storage.saveCount, 4, "with debounce disabled every turn saves immediately");
|
|
645
|
+
assert.equal(storage.saved?.entries?.["thread-a"]?.turns.length, 4);
|
|
646
|
+
});
|
|
647
|
+
|
|
648
|
+
test("parseConfig validates bufferSaveDebounceMs (accepts valid, defaults undefined)", () => {
|
|
649
|
+
assert.equal(parseConfig({}).bufferSaveDebounceMs, 3_000, "undefined → default 3000ms");
|
|
650
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: 0 }).bufferSaveDebounceMs, 0, "0 = save every turn");
|
|
651
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: 5_000 }).bufferSaveDebounceMs, 5_000);
|
|
652
|
+
assert.equal(
|
|
653
|
+
parseConfig({ bufferSaveDebounceMs: 2_147_483_647 }).bufferSaveDebounceMs,
|
|
654
|
+
2_147_483_647,
|
|
655
|
+
"max (32-bit setTimeout limit) accepted",
|
|
656
|
+
);
|
|
657
|
+
// CLI numeric strings coerce, then validate.
|
|
658
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: "5000" }).bufferSaveDebounceMs, 5_000, "numeric string coerces");
|
|
659
|
+
});
|
|
660
|
+
|
|
661
|
+
test("debounce on: each turn re-arms the trailing edge (save fires one window after the LAST turn)", async (t) => {
|
|
662
|
+
t.mock.timers.enable({ apis: ["setTimeout", "Date"], now: 0 });
|
|
663
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
664
|
+
const buffer = new SmartBuffer(
|
|
665
|
+
parseConfig({ bufferSaveDebounceMs: 100, triggerMode: "smart", bufferMaxTurns: 10_000 }),
|
|
666
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
667
|
+
);
|
|
668
|
+
const settle = () => new Promise<void>((resolve) => setImmediate(resolve));
|
|
669
|
+
|
|
670
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "turn 0")); // schedules save at t=100
|
|
671
|
+
t.mock.timers.tick(90); // t=90, before the first window closes
|
|
672
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "turn 1")); // re-arms to t=190
|
|
673
|
+
t.mock.timers.tick(90); // t=180 — the ORIGINAL 100ms deadline is past
|
|
674
|
+
await settle();
|
|
675
|
+
assert.equal(storage.saveCount, 0, "re-arm pushed the deadline; no save at the original window");
|
|
676
|
+
|
|
677
|
+
t.mock.timers.tick(20); // t=200 — 110ms after the last turn (past the re-armed 190)
|
|
678
|
+
await settle();
|
|
679
|
+
assert.equal(storage.saveCount, 1, "the save fires one window after the LAST turn (true trailing edge)");
|
|
680
|
+
assert.equal(storage.saved?.entries?.["thread-a"]?.turns.length, 2);
|
|
681
|
+
});
|
|
682
|
+
|
|
683
|
+
test("debounce on: sustained activity forces an inline save at the 5x staleness cap", async (t) => {
|
|
684
|
+
t.mock.timers.enable({ apis: ["setTimeout", "Date"], now: 0 });
|
|
685
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
686
|
+
// Window 100ms → cap at 5x = 500ms of continuously-deferred pending state.
|
|
687
|
+
const buffer = new SmartBuffer(
|
|
688
|
+
parseConfig({ bufferSaveDebounceMs: 100, triggerMode: "smart", bufferMaxTurns: 10_000 }),
|
|
689
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
690
|
+
);
|
|
691
|
+
|
|
692
|
+
// Add a turn every 80ms (< window) so the trailing-edge timer never fires —
|
|
693
|
+
// each turn re-arms it. The pending save is deferred continuously.
|
|
694
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "turn 0")); // firstPendingAt = 0
|
|
695
|
+
for (let elapsed = 80; elapsed <= 480; elapsed += 80) {
|
|
696
|
+
t.mock.timers.tick(80);
|
|
697
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", `turn @${elapsed}`));
|
|
698
|
+
assert.equal(storage.saveCount, 0, `still deferred at t=${elapsed} (< 5x window)`);
|
|
699
|
+
}
|
|
700
|
+
|
|
701
|
+
// Next turn crosses t=560 (>= 500ms cap): scheduleSave forces an inline save.
|
|
702
|
+
t.mock.timers.tick(80); // t=560
|
|
703
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "turn @560"));
|
|
704
|
+
assert.equal(storage.saveCount, 1, "the 5x staleness cap forced an inline save mid-activity");
|
|
705
|
+
});
|
|
706
|
+
|
|
707
|
+
class FailOnceBufferStorage {
|
|
708
|
+
public saved: BufferState | null = null;
|
|
709
|
+
public saveCount = 0;
|
|
710
|
+
public failNext = true;
|
|
711
|
+
|
|
712
|
+
async loadBuffer(): Promise<BufferState> {
|
|
713
|
+
return emptyBufferState();
|
|
714
|
+
}
|
|
715
|
+
|
|
716
|
+
async saveBuffer(state: BufferState): Promise<void> {
|
|
717
|
+
if (this.failNext) {
|
|
718
|
+
this.failNext = false;
|
|
719
|
+
throw new Error("simulated buffer write failure");
|
|
720
|
+
}
|
|
721
|
+
this.saveCount += 1;
|
|
722
|
+
this.saved = structuredClone(state);
|
|
723
|
+
}
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
test("debounce on: a failed flush keeps the save pending so a retry (or shutdown) persists", async () => {
|
|
727
|
+
// Issue #1909 review round 2 finding 1: flushPendingSave must not clear
|
|
728
|
+
// pendingSave until the write SUCCEEDS — otherwise a failed write diverges
|
|
729
|
+
// memory from disk and a later shutdown flush early-returns, dropping turns.
|
|
730
|
+
const storage = new FailOnceBufferStorage();
|
|
731
|
+
const buffer = new SmartBuffer(
|
|
732
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 10_000 }),
|
|
733
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
734
|
+
);
|
|
735
|
+
|
|
736
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "buffered turn")); // schedules a save
|
|
737
|
+
// First flush: the underlying write throws (swallowed, fail-open).
|
|
738
|
+
await buffer.flushPendingSave();
|
|
739
|
+
const internals = buffer as unknown as DebouncedBufferInternals;
|
|
740
|
+
assert.equal(internals.pendingSave, true, "a failed save leaves the save pending for retry");
|
|
741
|
+
assert.equal(storage.saveCount, 0, "nothing was persisted on the failed attempt");
|
|
742
|
+
|
|
743
|
+
// Retry (mirrors the re-armed timer or graceful-shutdown flush) succeeds.
|
|
744
|
+
await buffer.flushPendingSave();
|
|
745
|
+
assert.equal(storage.saveCount, 1, "the retry performed exactly one successful write");
|
|
746
|
+
assert.equal(
|
|
747
|
+
storage.saved?.entries?.["thread-a"]?.turns.length,
|
|
748
|
+
1,
|
|
749
|
+
"the previously-unpersisted turn is now durable",
|
|
750
|
+
);
|
|
751
|
+
assert.equal(internals.pendingSave, false, "pending is cleared only after the write succeeds");
|
|
752
|
+
});
|
|
753
|
+
|
|
754
|
+
test("parseConfig rejects invalid bufferSaveDebounceMs (round 8: throw, do not clamp/floor)", () => {
|
|
755
|
+
// Review round 8: reject invalid user input explicitly instead of silently
|
|
756
|
+
// flooring fractions / clamping negatives to 0 / clamping oversized to the
|
|
757
|
+
// timer max (AGENTS.md #1/#39).
|
|
758
|
+
const cases: unknown[] = [
|
|
759
|
+
-1, // negative
|
|
760
|
+
0.5, // fraction
|
|
761
|
+
3_000_000_000, // above the 32-bit setTimeout limit
|
|
762
|
+
Number.NaN,
|
|
763
|
+
Number.POSITIVE_INFINITY,
|
|
764
|
+
"abc", // non-numeric string
|
|
765
|
+
-0.0001,
|
|
766
|
+
2_147_483_648, // one past max
|
|
767
|
+
null, // explicit null is invalid (only undefined defaults) — round 9 finding 1
|
|
768
|
+
];
|
|
769
|
+
for (const value of cases) {
|
|
770
|
+
assert.throws(
|
|
771
|
+
() => parseConfig({ bufferSaveDebounceMs: value }),
|
|
772
|
+
/bufferSaveDebounceMs must be an integer in \[0, 2147483647\]/,
|
|
773
|
+
`expected ${JSON.stringify(value)} to be rejected`,
|
|
774
|
+
);
|
|
775
|
+
}
|
|
776
|
+
// Boundary + coercion: valid inputs pass.
|
|
777
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: 0 }).bufferSaveDebounceMs, 0);
|
|
778
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: 2_147_483_647 }).bufferSaveDebounceMs, 2_147_483_647);
|
|
779
|
+
assert.equal(parseConfig({ bufferSaveDebounceMs: "5000" }).bufferSaveDebounceMs, 5_000);
|
|
780
|
+
assert.equal(parseConfig({}).bufferSaveDebounceMs, 3_000, "undefined → default");
|
|
781
|
+
});
|
|
782
|
+
|
|
783
|
+
test("debounce cap: the buffer never arms setTimeout above the 32-bit limit", async () => {
|
|
784
|
+
// Deterministic (no real waiting): capture the delay the buffer passes to
|
|
785
|
+
// setTimeout. An unclamped value > 2^31-1 is overflow-clamped by Node to 1ms;
|
|
786
|
+
// the buffer-side Math.min prevents that even when a directly-constructed
|
|
787
|
+
// config bypassed parseConfig's cap.
|
|
788
|
+
const config = parseConfig({ triggerMode: "smart", bufferMaxTurns: 10_000 });
|
|
789
|
+
config.bufferSaveDebounceMs = 3_000_000_000;
|
|
790
|
+
const storage = new FakeStorage(emptyBufferState());
|
|
791
|
+
const buffer = new SmartBuffer(
|
|
792
|
+
config,
|
|
793
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
794
|
+
);
|
|
795
|
+
|
|
796
|
+
const timerGlobal = globalThis as unknown as { setTimeout: typeof setTimeout };
|
|
797
|
+
const realSetTimeout = timerGlobal.setTimeout;
|
|
798
|
+
const armedDelays: number[] = [];
|
|
799
|
+
const fakeHandle = { unref() {}, ref() {} } as unknown as NodeJS.Timeout;
|
|
800
|
+
timerGlobal.setTimeout = ((_fn: (...a: unknown[]) => void, delay?: number) => {
|
|
801
|
+
if (typeof delay === "number") armedDelays.push(delay);
|
|
802
|
+
// Do not schedule the real callback — we only assert on the delay argument.
|
|
803
|
+
return fakeHandle;
|
|
804
|
+
}) as typeof setTimeout;
|
|
805
|
+
try {
|
|
806
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "x")); // arms the debounced save
|
|
807
|
+
} finally {
|
|
808
|
+
timerGlobal.setTimeout = realSetTimeout;
|
|
809
|
+
}
|
|
810
|
+
|
|
811
|
+
assert.ok(armedDelays.length >= 1, "a debounced save timer was armed");
|
|
812
|
+
for (const delay of armedDelays) {
|
|
813
|
+
assert.ok(
|
|
814
|
+
delay <= 2_147_483_647,
|
|
815
|
+
`armed setTimeout delay ${delay} must be clamped to the 32-bit limit`,
|
|
816
|
+
);
|
|
817
|
+
}
|
|
818
|
+
});
|
|
819
|
+
|
|
820
|
+
test("debounce on: a failed clearAfterExtraction save keeps pending so other sessions' turns are not lost", async () => {
|
|
821
|
+
// Issue #1909 review round 13: clearAfterExtraction must NOT clear the global
|
|
822
|
+
// pending-save state/timer before its post-clear save is durable. If any
|
|
823
|
+
// session has a debounced save pending and the post-clear write throws, the
|
|
824
|
+
// pending state must be retained + re-armed so shutdown/the timer retries —
|
|
825
|
+
// otherwise buffered turns from OTHER sessions that only ever existed in the
|
|
826
|
+
// debounced state are lost.
|
|
827
|
+
const storage = new FailOnceBufferStorage();
|
|
828
|
+
const buffer = new SmartBuffer(
|
|
829
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 10_000 }),
|
|
830
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
831
|
+
);
|
|
832
|
+
|
|
833
|
+
// Session A buffers a turn — only a debounced save is pending (nothing on disk).
|
|
834
|
+
await buffer.addTurn("session-a", makeTurn("session-a", "A only lives in the pending save"));
|
|
835
|
+
// Session B buffers a turn too — the pending debounced save now covers A + B.
|
|
836
|
+
await buffer.addTurn("session-b", makeTurn("session-b", "B is about to be extracted"));
|
|
837
|
+
assert.equal(storage.saveCount, 0, "both turns are still only in the debounced pending save");
|
|
838
|
+
|
|
839
|
+
const internals = buffer as unknown as DebouncedBufferInternals;
|
|
840
|
+
|
|
841
|
+
// Extract + clear session B. The post-clear save FAILS (FailOnce). The global
|
|
842
|
+
// pending state must survive so A (and the cleared-B state) can still land.
|
|
843
|
+
await assert.rejects(
|
|
844
|
+
() => buffer.clearAfterExtraction("session-b"),
|
|
845
|
+
/simulated buffer write failure/,
|
|
846
|
+
"the failed post-clear save propagates (matching the inline-write guarantee)",
|
|
847
|
+
);
|
|
848
|
+
assert.equal(storage.saveCount, 0, "nothing was persisted on the failed clear");
|
|
849
|
+
assert.equal(
|
|
850
|
+
internals.pendingSave,
|
|
851
|
+
true,
|
|
852
|
+
"a failed clear keeps the save pending (would be false + lost without the round 13 fix)",
|
|
853
|
+
);
|
|
854
|
+
assert.notEqual(internals.saveTimer, null, "a background retry timer is re-armed after the failure");
|
|
855
|
+
|
|
856
|
+
// Retry (mirrors the re-armed timer or graceful shutdown) succeeds.
|
|
857
|
+
await buffer.flushPendingSave();
|
|
858
|
+
assert.equal(storage.saveCount, 1, "the retry performed exactly one successful write");
|
|
859
|
+
assert.equal(internals.pendingSave, false, "pending is cleared only after the durable write");
|
|
860
|
+
assert.equal(
|
|
861
|
+
storage.saved?.entries?.["session-a"]?.turns.length,
|
|
862
|
+
1,
|
|
863
|
+
"session A's turn is retained through the failed clear and later persisted",
|
|
864
|
+
);
|
|
865
|
+
assert.equal(
|
|
866
|
+
storage.saved?.entries?.["session-b"]?.turns.length ?? 0,
|
|
867
|
+
0,
|
|
868
|
+
"session B's turns were cleared by the extraction",
|
|
869
|
+
);
|
|
870
|
+
});
|
|
871
|
+
|
|
872
|
+
/**
|
|
873
|
+
* Storage that can hold ONE saveBuffer call open on a gate so a test can
|
|
874
|
+
* interleave other buffer mutations while a flush's write is in flight. The
|
|
875
|
+
* persisted snapshot is captured at call time (matching FakeStorage), so it
|
|
876
|
+
* reflects exactly the state the flush intended to write.
|
|
877
|
+
*/
|
|
878
|
+
class GatedSaveStorage {
|
|
879
|
+
public saved: BufferState | null = null;
|
|
880
|
+
public saveCount = 0;
|
|
881
|
+
private blockNext = false;
|
|
882
|
+
private release: (() => void) | null = null;
|
|
883
|
+
private signalStarted: (() => void) | null = null;
|
|
884
|
+
private startedPromise: Promise<void> | null = null;
|
|
885
|
+
|
|
886
|
+
constructor(private readonly initial: BufferState) {}
|
|
887
|
+
|
|
888
|
+
async loadBuffer(): Promise<BufferState> {
|
|
889
|
+
return structuredClone(this.initial);
|
|
890
|
+
}
|
|
891
|
+
|
|
892
|
+
blockNextSave(): void {
|
|
893
|
+
this.blockNext = true;
|
|
894
|
+
this.startedPromise = new Promise<void>((resolve) => {
|
|
895
|
+
this.signalStarted = resolve;
|
|
896
|
+
});
|
|
897
|
+
}
|
|
898
|
+
|
|
899
|
+
saveStarted(): Promise<void> {
|
|
900
|
+
return this.startedPromise ?? Promise.resolve();
|
|
901
|
+
}
|
|
902
|
+
|
|
903
|
+
releaseSave(): void {
|
|
904
|
+
this.release?.();
|
|
905
|
+
this.release = null;
|
|
906
|
+
}
|
|
907
|
+
|
|
908
|
+
async saveBuffer(state: BufferState): Promise<void> {
|
|
909
|
+
this.saveCount += 1;
|
|
910
|
+
const snapshot = structuredClone(state);
|
|
911
|
+
if (this.blockNext) {
|
|
912
|
+
this.blockNext = false;
|
|
913
|
+
const gate = new Promise<void>((resolve) => {
|
|
914
|
+
this.release = resolve;
|
|
915
|
+
});
|
|
916
|
+
this.signalStarted?.();
|
|
917
|
+
await gate;
|
|
918
|
+
}
|
|
919
|
+
this.saved = snapshot;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
|
|
923
|
+
test("debounce on: a turn recorded around a forced flush is not dropped by the flush's clear (PR #2016)", async () => {
|
|
924
|
+
// Issue #1909 PR #2016 review: flushPendingSave used to clear
|
|
925
|
+
// pendingSave/firstPendingAtMs AFTER the serialized write mutation resolved,
|
|
926
|
+
// i.e. OUTSIDE the serializer. A turn recorded around that flush re-arms a
|
|
927
|
+
// debounced save (pendingSave = true); if the flush's late clear then wiped
|
|
928
|
+
// that flag, the interleaved turn's own scheduled flush would early-return
|
|
929
|
+
// and its persistence would be lost. The fix makes write + clear atomic on
|
|
930
|
+
// the existing serializer mutex. This drives the interleave deterministically
|
|
931
|
+
// and proves BOTH the pre-flush turn and the interleaved turn reach disk.
|
|
932
|
+
const storage = new GatedSaveStorage(emptyBufferState());
|
|
933
|
+
const buffer = new SmartBuffer(
|
|
934
|
+
parseConfig({ bufferSaveDebounceMs: 10_000, triggerMode: "smart", bufferMaxTurns: 10_000 }),
|
|
935
|
+
storage as unknown as ConstructorParameters<typeof SmartBuffer>[1],
|
|
936
|
+
);
|
|
937
|
+
|
|
938
|
+
// Pre-flush turn: schedules a debounced save (pendingSave = true, timer armed).
|
|
939
|
+
assert.equal(
|
|
940
|
+
await buffer.addTurn("thread-a", makeTurn("thread-a", "pre-flush")),
|
|
941
|
+
"keep_buffering",
|
|
942
|
+
);
|
|
943
|
+
|
|
944
|
+
// Force a flush whose write blocks mid-flight, holding the serializer.
|
|
945
|
+
storage.blockNextSave();
|
|
946
|
+
const flushP = buffer.flushPendingSave();
|
|
947
|
+
await storage.saveStarted();
|
|
948
|
+
|
|
949
|
+
// Interleave a turn while the flush write is in flight. It queues behind the
|
|
950
|
+
// flush's write mutation on the serializer and records only after it settles.
|
|
951
|
+
const addP = buffer.addTurn("thread-a", makeTurn("thread-a", "post-flush"));
|
|
952
|
+
|
|
953
|
+
// Let the flush write land and everything settle.
|
|
954
|
+
storage.releaseSave();
|
|
955
|
+
await Promise.all([flushP, addP]);
|
|
956
|
+
|
|
957
|
+
const internals = buffer as unknown as DebouncedBufferInternals;
|
|
958
|
+
assert.deepEqual(
|
|
959
|
+
buffer.getTurns("thread-a").map((t) => t.content),
|
|
960
|
+
["pre-flush", "post-flush"],
|
|
961
|
+
"both turns are held in memory",
|
|
962
|
+
);
|
|
963
|
+
assert.equal(
|
|
964
|
+
internals.pendingSave,
|
|
965
|
+
true,
|
|
966
|
+
"the interleaved turn's debounced save survives the flush's clear (owns its own flush)",
|
|
967
|
+
);
|
|
968
|
+
|
|
969
|
+
// The interleaved turn's pending save must still land — the flush's clear must
|
|
970
|
+
// not have silently dropped it.
|
|
971
|
+
await buffer.flushPendingSave();
|
|
972
|
+
assert.deepEqual(
|
|
973
|
+
storage.saved?.entries?.["thread-a"]?.turns.map((t) => t.content) ?? [],
|
|
974
|
+
["pre-flush", "post-flush"],
|
|
975
|
+
"the pre-flush turn and the interleaved turn both persist",
|
|
976
|
+
);
|
|
977
|
+
assert.equal(internals.pendingSave, false, "pending is cleared only after the durable write");
|
|
978
|
+
});
|