@remnic/core 10.0.3 → 10.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/access-admin-ops-surface.js +37 -37
- package/dist/access-authorization-probe.js +38 -38
- package/dist/access-boundary.js +37 -37
- package/dist/access-cli.js +100 -98
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.js +37 -37
- package/dist/access-http-briefing.js +38 -38
- package/dist/access-http-query.js +39 -39
- package/dist/access-http.js +56 -56
- package/dist/access-identity-continuity-surface.js +37 -37
- package/dist/access-lcm-surface.js +37 -37
- package/dist/access-mcp.js +47 -47
- package/dist/access-namespace-preflight.js +37 -37
- package/dist/access-observe-write-category.js +2 -2
- package/dist/access-observe-write-surface.js +37 -37
- package/dist/access-offline-manifest.js +4 -4
- package/dist/access-operations-batch.js +38 -38
- package/dist/access-operations.js +45 -45
- package/dist/access-recall-concurrency.js +37 -37
- package/dist/access-recall-diagnostics.js +2 -2
- package/dist/access-recall-response.js +37 -37
- package/dist/access-recall-surface.js +37 -37
- package/dist/access-service.js +37 -37
- package/dist/access-surface-catalog.js +39 -39
- package/dist/active-recall.js +17 -16
- 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-PAWBFQWL.js → auto-sync-FN7E3OTO.js} +4 -4
- package/dist/briefing.js +16 -16
- package/dist/buffer.js +7 -7
- package/dist/causal-consolidation.js +17 -17
- package/dist/{chunk-G3T6YMBO.js → chunk-2KB7TTAP.js} +4 -4
- package/dist/{chunk-345MEMRU.js → chunk-3OUGSOJP.js} +2 -2
- package/dist/{chunk-CFCEJNOE.js → chunk-3QAIX7TV.js} +2 -2
- package/dist/{chunk-LMMC55WM.js → chunk-436IRJUD.js} +4 -4
- package/dist/{chunk-G2STTRYB.js → chunk-4D2YH47Z.js} +2 -2
- package/dist/{chunk-RKSGUMVL.js → chunk-4DXVWBDB.js} +2 -2
- package/dist/{chunk-CGOKNQDK.js → chunk-4NFRYOHT.js} +2 -2
- package/dist/{chunk-CHI37EHP.js → chunk-5QHTQMRL.js} +5 -5
- package/dist/{chunk-RFIJRZ4K.js → chunk-5XXTZ4Y7.js} +2 -2
- package/dist/{chunk-YQSWNFZE.js → chunk-5YDWSWBU.js} +2 -2
- package/dist/{chunk-TNVZCLJU.js → chunk-6AH2DDHI.js} +2 -2
- package/dist/{chunk-5GINB5LC.js → chunk-6MKLMEBE.js} +1 -1
- package/dist/{chunk-5GINB5LC.js.map → chunk-6MKLMEBE.js.map} +1 -1
- package/dist/{chunk-JDOBIFBK.js → chunk-7CXL25AA.js} +2 -2
- package/dist/{chunk-YLBE6PLR.js → chunk-7IGMKQWK.js} +2 -2
- package/dist/{chunk-NGOZH7R5.js → chunk-7OOW72QA.js} +21 -21
- package/dist/{chunk-2QZFZNXO.js → chunk-ABDTBGI2.js} +2 -2
- package/dist/{chunk-6JIHC5AS.js → chunk-ABET5LA5.js} +59 -48
- package/dist/chunk-ABET5LA5.js.map +1 -0
- package/dist/{chunk-IB63OVUB.js → chunk-AJ6ORARY.js} +6 -6
- package/dist/{chunk-32HO62I4.js → chunk-BDHWKFGM.js} +2 -2
- package/dist/{chunk-AW4QUFQF.js → chunk-BTNNL7ZW.js} +3 -2
- package/dist/{chunk-AW4QUFQF.js.map → chunk-BTNNL7ZW.js.map} +1 -1
- package/dist/{chunk-MY7B3HYC.js → chunk-CLCMDKTB.js} +2 -2
- package/dist/{chunk-OZVHLBH6.js → chunk-CQQTEDHS.js} +2 -2
- package/dist/{chunk-7KICGR5W.js → chunk-CV5AMCPX.js} +2 -2
- package/dist/{chunk-BTOHGPHC.js → chunk-CXG2T7BJ.js} +3 -3
- package/dist/{chunk-X6X4UASX.js → chunk-DBA2W6VV.js} +230 -81
- package/dist/chunk-DBA2W6VV.js.map +1 -0
- package/dist/{chunk-E7FN5N5E.js → chunk-DQJCQHII.js} +2 -2
- package/dist/{chunk-OWHPA4JS.js → chunk-DYRXRQHV.js} +2 -2
- package/dist/{chunk-IIFFC3RL.js → chunk-EDR6CVWZ.js} +2 -2
- package/dist/{chunk-2JRB3Z5N.js → chunk-EP5WXE2G.js} +3 -3
- package/dist/chunk-EWMRFW3F.js +38 -0
- package/dist/chunk-EWMRFW3F.js.map +1 -0
- package/dist/chunk-FMIVV5SV.js +80 -0
- package/dist/chunk-FMIVV5SV.js.map +1 -0
- package/dist/{chunk-2EZB2DL5.js → chunk-GE6HETIF.js} +3 -3
- package/dist/{chunk-HP4CU2ZA.js → chunk-GLS3A4SQ.js} +2 -2
- package/dist/{chunk-I6WFBNA4.js → chunk-H2XCCUOT.js} +3 -3
- package/dist/{chunk-IXYIW3MZ.js → chunk-H6FA36LC.js} +2 -2
- package/dist/{chunk-NLDMTXWV.js → chunk-HSZBALHV.js} +2 -2
- package/dist/{chunk-XG4XXI66.js → chunk-I25RQA65.js} +2 -2
- package/dist/{chunk-PNFWIB4X.js → chunk-IHIP7TJ3.js} +2 -2
- package/dist/{chunk-4DDIWRT7.js → chunk-IINXHPCV.js} +2 -2
- package/dist/{chunk-EJJMDLVB.js → chunk-IJ4FEGZR.js} +2 -2
- package/dist/{chunk-IHCYCE6D.js → chunk-IRYKRBEX.js} +4 -4
- package/dist/{chunk-MYYHACOW.js → chunk-IVGJXS5F.js} +2 -2
- package/dist/{chunk-Q6GI7HEC.js → chunk-IXF7TRMQ.js} +2 -2
- package/dist/{chunk-O6AYMAPJ.js → chunk-IY7ZISXV.js} +2 -2
- package/dist/{chunk-5FLFPTDK.js → chunk-JA72X46J.js} +2 -2
- package/dist/{chunk-NLYOOGZ7.js → chunk-KE5PWLI6.js} +3 -3
- package/dist/{chunk-6AA7XFMO.js → chunk-LIGP5M2C.js} +2 -2
- package/dist/{chunk-KW77LGDX.js → chunk-MEMH5NKJ.js} +2 -2
- package/dist/{chunk-KRTIHXWC.js → chunk-MEP3POVW.js} +2 -2
- package/dist/{chunk-35A7GCHG.js → chunk-MYBCB4AT.js} +2 -2
- package/dist/{chunk-QPWUG2S3.js → chunk-NSQ3GUVO.js} +2 -2
- package/dist/{chunk-NXVD46HT.js → chunk-O57VUN4U.js} +4 -4
- package/dist/{chunk-L6DJJEFW.js → chunk-OAFRMLL4.js} +2 -2
- package/dist/{chunk-PCO3P7WJ.js → chunk-OGVJXIHX.js} +2 -2
- package/dist/{chunk-JSUA4YFE.js → chunk-ORAL4HJC.js} +2 -2
- package/dist/{chunk-RXT6UB25.js → chunk-P22M3DX3.js} +2 -2
- package/dist/{chunk-I2KEH2LS.js → chunk-PTFL3INS.js} +2 -2
- package/dist/{chunk-5QXMESS7.js → chunk-QDKABMUE.js} +2 -2
- package/dist/{chunk-34G4U6HS.js → chunk-QRZMJ2WN.js} +2 -2
- package/dist/{chunk-GBA4N2SG.js → chunk-QVBB2CLG.js} +13 -13
- package/dist/{chunk-6GU3TNJJ.js → chunk-QWNBQ2T5.js} +244 -47
- package/dist/chunk-QWNBQ2T5.js.map +1 -0
- package/dist/{chunk-GUD6FYQG.js → chunk-R4O2G6ML.js} +2 -2
- package/dist/{chunk-CSLK7BN6.js → chunk-R6EOFKZG.js} +2 -2
- package/dist/{chunk-Y2ADLCB3.js → chunk-RGPPNNDJ.js} +8 -8
- package/dist/{chunk-BLHPADUX.js → chunk-RH6MQ5NG.js} +6 -11
- package/dist/chunk-RH6MQ5NG.js.map +1 -0
- package/dist/{chunk-2NV7MMMM.js → chunk-RZCRXCLI.js} +2 -2
- package/dist/{chunk-WI37MWRZ.js → chunk-SNGNGH53.js} +2 -2
- package/dist/{chunk-R4NGLTUS.js → chunk-TDMNADPI.js} +2 -2
- package/dist/{chunk-UVVSOSHL.js → chunk-TSEUVMJL.js} +44 -44
- package/dist/{chunk-O24EWFPQ.js → chunk-TYOBAFCY.js} +3 -3
- package/dist/{chunk-LI76ESJL.js → chunk-TZQOCQXB.js} +2 -2
- package/dist/{chunk-WHTMVTU4.js → chunk-U3LVARGV.js} +2 -2
- package/dist/{chunk-AUWMKDKL.js → chunk-UCCB7RKF.js} +2 -2
- package/dist/{chunk-OV7EYM6M.js → chunk-VWCFR4NR.js} +9 -9
- package/dist/{chunk-DQTCGVFK.js → chunk-WHCD4Z3D.js} +2 -2
- package/dist/{chunk-ZS7RK6H6.js → chunk-WLC6XA6C.js} +4 -4
- package/dist/{chunk-QCP75JGO.js → chunk-WQUGCOKF.js} +5 -5
- package/dist/{chunk-KATEWTQJ.js → chunk-X7J56GPG.js} +2 -2
- package/dist/{chunk-ME2LMFHF.js → chunk-XTWF5XR6.js} +51 -51
- package/dist/{chunk-22DYJLFN.js → chunk-XVC7JU2N.js} +39 -18
- package/dist/chunk-XVC7JU2N.js.map +1 -0
- package/dist/{chunk-HO7IQP7G.js → chunk-Y7CXM7UM.js} +3 -3
- package/dist/{chunk-44PBRUXB.js → chunk-YMXCJ7SE.js} +2 -2
- package/dist/{chunk-AXFWMRKI.js → chunk-YQJCWR4R.js} +2 -2
- package/dist/{chunk-2DHJTJIY.js → chunk-Z2EVKNZR.js} +2 -2
- package/dist/{chunk-RKDSELA3.js → chunk-Z63GU5NN.js} +1 -1
- package/dist/chunk-Z63GU5NN.js.map +1 -0
- package/dist/{chunk-4NRZ7BRS.js → chunk-ZOGZMAGI.js} +2 -2
- package/dist/cli.js +78 -77
- package/dist/coding/export-okf-codegraph.js +16 -16
- package/dist/compounding/engine.js +16 -16
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +17 -16
- package/dist/connectors/codex-materialize-runner.js +16 -16
- package/dist/connectors/index.js +16 -16
- package/dist/convergence-refresh.js +18 -18
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-read-cancellation.d.ts +7 -0
- package/dist/corpus-read-cancellation.d.ts.map +1 -1
- package/dist/corpus-read-cancellation.js +1 -1
- package/dist/corpus-watermark.js +18 -18
- package/dist/directory-sidecars.js +2 -2
- package/dist/entity-retrieval.js +16 -16
- package/dist/external-wiki-access.js +38 -38
- package/dist/extraction.js +21 -21
- package/dist/harmonic-retrieval.js +16 -16
- package/dist/index.js +102 -100
- package/dist/location/index.js +19 -19
- package/dist/maintenance/archive-observations.js +2 -2
- package/dist/maintenance/atomic-file.d.ts +1 -1
- package/dist/maintenance/atomic-file.d.ts.map +1 -1
- package/dist/maintenance/atomic-file.js +1 -1
- package/dist/maintenance/memory-governance.js +16 -16
- package/dist/maintenance/migrate-observations.js +3 -3
- package/dist/maintenance/observation-ledger-utils.js +2 -2
- package/dist/maintenance/projection-rebuild-abort.d.ts +17 -0
- package/dist/maintenance/projection-rebuild-abort.d.ts.map +1 -0
- package/dist/maintenance/projection-timeline.d.ts +19 -0
- package/dist/maintenance/projection-timeline.d.ts.map +1 -0
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +16 -16
- package/dist/maintenance/rebuild-memory-projection-runner.d.ts +8 -0
- package/dist/maintenance/rebuild-memory-projection-runner.d.ts.map +1 -0
- package/dist/maintenance/rebuild-memory-projection-runner.js +113 -0
- package/dist/maintenance/rebuild-memory-projection-runner.js.map +1 -0
- package/dist/maintenance/rebuild-memory-projection.d.ts +8 -0
- package/dist/maintenance/rebuild-memory-projection.d.ts.map +1 -1
- package/dist/maintenance/rebuild-memory-projection.js +17 -17
- package/dist/maintenance/rebuild-observations.js +3 -3
- package/dist/memory-browse-operations.js +38 -38
- package/dist/memory-browse.js +7 -7
- package/dist/namespaces/migrate.js +17 -17
- package/dist/namespaces/search.js +8 -8
- package/dist/namespaces/storage.js +16 -16
- package/dist/offline-sync-impression-drain.js +3 -3
- package/dist/operator-doctor-corpus.js +19 -19
- package/dist/operator-toolkit.js +26 -25
- package/dist/orchestration/full-corpus-heap-guard.d.ts +25 -0
- package/dist/orchestration/full-corpus-heap-guard.d.ts.map +1 -0
- package/dist/orchestration/maintenance.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +27 -25
- package/dist/orchestration/projection-rebuild-schedule.d.ts +40 -0
- package/dist/orchestration/projection-rebuild-schedule.d.ts.map +1 -1
- package/dist/orchestrator.js +100 -98
- package/dist/projection-rebuild-config.d.ts +52 -0
- package/dist/projection-rebuild-config.d.ts.map +1 -0
- package/dist/projection-rebuild-config.js +14 -0
- package/dist/projection-rebuild-config.js.map +1 -0
- package/dist/qmd.js +4 -4
- package/dist/recall-explain-renderer.js +3 -3
- package/dist/recall-navigate-access.js +2 -2
- package/dist/recall-navigate-disclosure.js +2 -2
- package/dist/recall-navigate.js +2 -2
- package/dist/recall-navigation-operations.js +38 -38
- package/dist/recall-navigation.js +37 -37
- package/dist/recall-state-view-admission.js +7 -7
- package/dist/recall-state.js +2 -2
- package/dist/recall-why-service.js +7 -7
- package/dist/recall-xray-cli.js +4 -4
- package/dist/recall-xray-renderer.js +3 -3
- package/dist/recall-xray.js +2 -2
- package/dist/relevance.js +2 -2
- package/dist/resume-bundles.js +18 -17
- package/dist/search/factory.js +7 -7
- package/dist/search/index.js +11 -11
- package/dist/semantic-consolidation.js +17 -17
- package/dist/semantic-rule-promotion.js +16 -16
- package/dist/semantic-rule-verifier.js +16 -16
- package/dist/source-agent-qualifier.js +20 -20
- package/dist/standup/build.js +16 -16
- package/dist/storage/memory-lifecycle-ledger-access.d.ts +5 -3
- package/dist/storage/memory-lifecycle-ledger-access.d.ts.map +1 -1
- package/dist/storage/memory-read-store.d.ts +2 -2
- package/dist/storage/memory-read-store.d.ts.map +1 -1
- package/dist/storage.d.ts +4 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +15 -15
- package/dist/support-passport/index.js +40 -40
- package/dist/transfer/export-okf.js +17 -17
- package/dist/types.d.ts +2 -17
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +1 -1
- package/dist/verified-recall.js +16 -16
- package/dist/who-knows-cli.js +17 -17
- package/dist/who-knows.js +16 -16
- package/package.json +2 -2
- package/src/config.test.ts +9 -0
- package/src/config.ts +2 -5
- package/src/corpus-read-cancellation.ts +7 -0
- package/src/maintenance/atomic-file.ts +2 -0
- package/src/maintenance/projection-rebuild-abort.ts +40 -0
- package/src/maintenance/projection-timeline.ts +209 -0
- package/src/maintenance/rebuild-memory-projection-runner.ts +94 -0
- package/src/maintenance/rebuild-memory-projection.memory.test.ts +159 -0
- package/src/maintenance/rebuild-memory-projection.retain-raw.test.ts +202 -0
- package/src/maintenance/rebuild-memory-projection.ts +63 -91
- package/src/orchestration/full-corpus-heap-guard.ts +38 -0
- package/src/orchestration/maintenance.test.ts +2 -2
- package/src/orchestration/maintenance.ts +2 -0
- package/src/orchestration/projection-rebuild-schedule.test.ts +498 -0
- package/src/orchestration/projection-rebuild-schedule.ts +280 -9
- package/src/projection-rebuild-config.ts +82 -0
- package/src/storage/memory-lifecycle-ledger-access.ts +61 -33
- package/src/storage/memory-read-store.ts +10 -4
- package/src/storage.ts +45 -33
- package/src/types.ts +2 -18
- package/dist/chunk-22DYJLFN.js.map +0 -1
- package/dist/chunk-6GU3TNJJ.js.map +0 -1
- package/dist/chunk-6JIHC5AS.js.map +0 -1
- package/dist/chunk-BLHPADUX.js.map +0 -1
- package/dist/chunk-RKDSELA3.js.map +0 -1
- package/dist/chunk-X6X4UASX.js.map +0 -1
- /package/dist/{auto-sync-PAWBFQWL.js.map → auto-sync-FN7E3OTO.js.map} +0 -0
- /package/dist/{chunk-G3T6YMBO.js.map → chunk-2KB7TTAP.js.map} +0 -0
- /package/dist/{chunk-345MEMRU.js.map → chunk-3OUGSOJP.js.map} +0 -0
- /package/dist/{chunk-CFCEJNOE.js.map → chunk-3QAIX7TV.js.map} +0 -0
- /package/dist/{chunk-LMMC55WM.js.map → chunk-436IRJUD.js.map} +0 -0
- /package/dist/{chunk-G2STTRYB.js.map → chunk-4D2YH47Z.js.map} +0 -0
- /package/dist/{chunk-RKSGUMVL.js.map → chunk-4DXVWBDB.js.map} +0 -0
- /package/dist/{chunk-CGOKNQDK.js.map → chunk-4NFRYOHT.js.map} +0 -0
- /package/dist/{chunk-CHI37EHP.js.map → chunk-5QHTQMRL.js.map} +0 -0
- /package/dist/{chunk-RFIJRZ4K.js.map → chunk-5XXTZ4Y7.js.map} +0 -0
- /package/dist/{chunk-YQSWNFZE.js.map → chunk-5YDWSWBU.js.map} +0 -0
- /package/dist/{chunk-TNVZCLJU.js.map → chunk-6AH2DDHI.js.map} +0 -0
- /package/dist/{chunk-JDOBIFBK.js.map → chunk-7CXL25AA.js.map} +0 -0
- /package/dist/{chunk-YLBE6PLR.js.map → chunk-7IGMKQWK.js.map} +0 -0
- /package/dist/{chunk-NGOZH7R5.js.map → chunk-7OOW72QA.js.map} +0 -0
- /package/dist/{chunk-2QZFZNXO.js.map → chunk-ABDTBGI2.js.map} +0 -0
- /package/dist/{chunk-IB63OVUB.js.map → chunk-AJ6ORARY.js.map} +0 -0
- /package/dist/{chunk-32HO62I4.js.map → chunk-BDHWKFGM.js.map} +0 -0
- /package/dist/{chunk-MY7B3HYC.js.map → chunk-CLCMDKTB.js.map} +0 -0
- /package/dist/{chunk-OZVHLBH6.js.map → chunk-CQQTEDHS.js.map} +0 -0
- /package/dist/{chunk-7KICGR5W.js.map → chunk-CV5AMCPX.js.map} +0 -0
- /package/dist/{chunk-BTOHGPHC.js.map → chunk-CXG2T7BJ.js.map} +0 -0
- /package/dist/{chunk-E7FN5N5E.js.map → chunk-DQJCQHII.js.map} +0 -0
- /package/dist/{chunk-OWHPA4JS.js.map → chunk-DYRXRQHV.js.map} +0 -0
- /package/dist/{chunk-IIFFC3RL.js.map → chunk-EDR6CVWZ.js.map} +0 -0
- /package/dist/{chunk-2JRB3Z5N.js.map → chunk-EP5WXE2G.js.map} +0 -0
- /package/dist/{chunk-2EZB2DL5.js.map → chunk-GE6HETIF.js.map} +0 -0
- /package/dist/{chunk-HP4CU2ZA.js.map → chunk-GLS3A4SQ.js.map} +0 -0
- /package/dist/{chunk-I6WFBNA4.js.map → chunk-H2XCCUOT.js.map} +0 -0
- /package/dist/{chunk-IXYIW3MZ.js.map → chunk-H6FA36LC.js.map} +0 -0
- /package/dist/{chunk-NLDMTXWV.js.map → chunk-HSZBALHV.js.map} +0 -0
- /package/dist/{chunk-XG4XXI66.js.map → chunk-I25RQA65.js.map} +0 -0
- /package/dist/{chunk-PNFWIB4X.js.map → chunk-IHIP7TJ3.js.map} +0 -0
- /package/dist/{chunk-4DDIWRT7.js.map → chunk-IINXHPCV.js.map} +0 -0
- /package/dist/{chunk-EJJMDLVB.js.map → chunk-IJ4FEGZR.js.map} +0 -0
- /package/dist/{chunk-IHCYCE6D.js.map → chunk-IRYKRBEX.js.map} +0 -0
- /package/dist/{chunk-MYYHACOW.js.map → chunk-IVGJXS5F.js.map} +0 -0
- /package/dist/{chunk-Q6GI7HEC.js.map → chunk-IXF7TRMQ.js.map} +0 -0
- /package/dist/{chunk-O6AYMAPJ.js.map → chunk-IY7ZISXV.js.map} +0 -0
- /package/dist/{chunk-5FLFPTDK.js.map → chunk-JA72X46J.js.map} +0 -0
- /package/dist/{chunk-NLYOOGZ7.js.map → chunk-KE5PWLI6.js.map} +0 -0
- /package/dist/{chunk-6AA7XFMO.js.map → chunk-LIGP5M2C.js.map} +0 -0
- /package/dist/{chunk-KW77LGDX.js.map → chunk-MEMH5NKJ.js.map} +0 -0
- /package/dist/{chunk-KRTIHXWC.js.map → chunk-MEP3POVW.js.map} +0 -0
- /package/dist/{chunk-35A7GCHG.js.map → chunk-MYBCB4AT.js.map} +0 -0
- /package/dist/{chunk-QPWUG2S3.js.map → chunk-NSQ3GUVO.js.map} +0 -0
- /package/dist/{chunk-NXVD46HT.js.map → chunk-O57VUN4U.js.map} +0 -0
- /package/dist/{chunk-L6DJJEFW.js.map → chunk-OAFRMLL4.js.map} +0 -0
- /package/dist/{chunk-PCO3P7WJ.js.map → chunk-OGVJXIHX.js.map} +0 -0
- /package/dist/{chunk-JSUA4YFE.js.map → chunk-ORAL4HJC.js.map} +0 -0
- /package/dist/{chunk-RXT6UB25.js.map → chunk-P22M3DX3.js.map} +0 -0
- /package/dist/{chunk-I2KEH2LS.js.map → chunk-PTFL3INS.js.map} +0 -0
- /package/dist/{chunk-5QXMESS7.js.map → chunk-QDKABMUE.js.map} +0 -0
- /package/dist/{chunk-34G4U6HS.js.map → chunk-QRZMJ2WN.js.map} +0 -0
- /package/dist/{chunk-GBA4N2SG.js.map → chunk-QVBB2CLG.js.map} +0 -0
- /package/dist/{chunk-GUD6FYQG.js.map → chunk-R4O2G6ML.js.map} +0 -0
- /package/dist/{chunk-CSLK7BN6.js.map → chunk-R6EOFKZG.js.map} +0 -0
- /package/dist/{chunk-Y2ADLCB3.js.map → chunk-RGPPNNDJ.js.map} +0 -0
- /package/dist/{chunk-2NV7MMMM.js.map → chunk-RZCRXCLI.js.map} +0 -0
- /package/dist/{chunk-WI37MWRZ.js.map → chunk-SNGNGH53.js.map} +0 -0
- /package/dist/{chunk-R4NGLTUS.js.map → chunk-TDMNADPI.js.map} +0 -0
- /package/dist/{chunk-UVVSOSHL.js.map → chunk-TSEUVMJL.js.map} +0 -0
- /package/dist/{chunk-O24EWFPQ.js.map → chunk-TYOBAFCY.js.map} +0 -0
- /package/dist/{chunk-LI76ESJL.js.map → chunk-TZQOCQXB.js.map} +0 -0
- /package/dist/{chunk-WHTMVTU4.js.map → chunk-U3LVARGV.js.map} +0 -0
- /package/dist/{chunk-AUWMKDKL.js.map → chunk-UCCB7RKF.js.map} +0 -0
- /package/dist/{chunk-OV7EYM6M.js.map → chunk-VWCFR4NR.js.map} +0 -0
- /package/dist/{chunk-DQTCGVFK.js.map → chunk-WHCD4Z3D.js.map} +0 -0
- /package/dist/{chunk-ZS7RK6H6.js.map → chunk-WLC6XA6C.js.map} +0 -0
- /package/dist/{chunk-QCP75JGO.js.map → chunk-WQUGCOKF.js.map} +0 -0
- /package/dist/{chunk-KATEWTQJ.js.map → chunk-X7J56GPG.js.map} +0 -0
- /package/dist/{chunk-ME2LMFHF.js.map → chunk-XTWF5XR6.js.map} +0 -0
- /package/dist/{chunk-HO7IQP7G.js.map → chunk-Y7CXM7UM.js.map} +0 -0
- /package/dist/{chunk-44PBRUXB.js.map → chunk-YMXCJ7SE.js.map} +0 -0
- /package/dist/{chunk-AXFWMRKI.js.map → chunk-YQJCWR4R.js.map} +0 -0
- /package/dist/{chunk-2DHJTJIY.js.map → chunk-Z2EVKNZR.js.map} +0 -0
- /package/dist/{chunk-4NRZ7BRS.js.map → chunk-ZOGZMAGI.js.map} +0 -0
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { mkdir, mkdtemp, rm, writeFile } from "node:fs/promises";
|
|
4
|
+
import os from "node:os";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
import test from "node:test";
|
|
7
|
+
import {
|
|
8
|
+
compareMemoryLifecycleEvents,
|
|
9
|
+
memoryLifecycleEventProjectionIdentity,
|
|
10
|
+
} from "../memory-lifecycle-ledger-utils.js";
|
|
11
|
+
import { getMemoryProjectionPath, openProjectionReadonly } from "../memory-projection-store.js";
|
|
12
|
+
import { readRawMemoryDocument } from "../storage/memory-frontmatter-metadata.js";
|
|
13
|
+
import { StorageManager } from "../storage.js";
|
|
14
|
+
import type { MemoryLifecycleEvent } from "../types.js";
|
|
15
|
+
import { rebuildMemoryProjection } from "./rebuild-memory-projection.js";
|
|
16
|
+
|
|
17
|
+
const FIXED_NOW = new Date("2026-06-01T00:00:00.000Z");
|
|
18
|
+
|
|
19
|
+
function fact(id: string, body: string): string {
|
|
20
|
+
return [
|
|
21
|
+
"---",
|
|
22
|
+
`id: ${id}`,
|
|
23
|
+
"category: fact",
|
|
24
|
+
"confidence: 0.8",
|
|
25
|
+
"created: 2026-01-01T00:00:00.000Z",
|
|
26
|
+
"updated: 2026-01-02T00:00:00.000Z",
|
|
27
|
+
"status: active",
|
|
28
|
+
"source: test",
|
|
29
|
+
"entityRef: project-alpha",
|
|
30
|
+
"tags:",
|
|
31
|
+
" - topic:alpha",
|
|
32
|
+
"---",
|
|
33
|
+
"",
|
|
34
|
+
body,
|
|
35
|
+
"",
|
|
36
|
+
].join("\n");
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
function ledgerEvent(partial: Pick<MemoryLifecycleEvent, "eventId" | "memoryId" | "eventType" | "timestamp">): MemoryLifecycleEvent {
|
|
40
|
+
return {
|
|
41
|
+
actor: "test",
|
|
42
|
+
ruleVersion: "1",
|
|
43
|
+
...partial,
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
async function seedCorpus(memoryDir: string, events: MemoryLifecycleEvent[]): Promise<void> {
|
|
48
|
+
await mkdir(path.join(memoryDir, "facts", "2026-01-01"), { recursive: true });
|
|
49
|
+
await mkdir(path.join(memoryDir, "cold", "facts", "2026-01-01"), { recursive: true });
|
|
50
|
+
await mkdir(path.join(memoryDir, "archive", "facts", "2026-01-01"), { recursive: true });
|
|
51
|
+
await mkdir(path.join(memoryDir, "state"), { recursive: true });
|
|
52
|
+
await writeFile(path.join(memoryDir, "facts", "2026-01-01", "hot-1.md"), fact("hot-1", "HOTBODY unique hot text"));
|
|
53
|
+
await writeFile(path.join(memoryDir, "facts", "2026-01-01", "blank.md"), fact(" ", "blank id body"));
|
|
54
|
+
await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "hot-1.md"), fact("hot-1", "COLDBODY should lose to hot"));
|
|
55
|
+
await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "cold-only.md"), fact("cold-only", "COLDONLY body"));
|
|
56
|
+
await writeFile(path.join(memoryDir, "archive", "facts", "2026-01-01", "arch-1.md"), fact("arch-1", "ARCHBODY archived text"));
|
|
57
|
+
const lines = [
|
|
58
|
+
...events.map((event) => JSON.stringify(event)),
|
|
59
|
+
"{not-json",
|
|
60
|
+
];
|
|
61
|
+
await writeFile(
|
|
62
|
+
path.join(memoryDir, "state", "memory-lifecycle-ledger.jsonl"),
|
|
63
|
+
`${lines.join("\n")}\n`,
|
|
64
|
+
"utf8",
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function expectedKeptEventIds(events: MemoryLifecycleEvent[]): string[] {
|
|
69
|
+
const kept: string[] = [];
|
|
70
|
+
const seen = new Set<string>();
|
|
71
|
+
const sorted = [...events].sort(compareMemoryLifecycleEvents);
|
|
72
|
+
for (const event of sorted) {
|
|
73
|
+
if (!event.memoryId.trim()) continue;
|
|
74
|
+
if (seen.has(event.eventId)) continue;
|
|
75
|
+
seen.add(event.eventId);
|
|
76
|
+
kept.push(event.eventId);
|
|
77
|
+
}
|
|
78
|
+
return kept.sort();
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function projectionDigest(memoryDir: string): { hash: string; counts: Record<string, number>; eventIds: string[]; previews: Record<string, string>; ledgerCount: string | undefined } {
|
|
82
|
+
const db = openProjectionReadonly(memoryDir);
|
|
83
|
+
assert.ok(db, "projection opens");
|
|
84
|
+
try {
|
|
85
|
+
const hash = createHash("sha256");
|
|
86
|
+
const counts: Record<string, number> = {};
|
|
87
|
+
const queries: Array<[string, string]> = [
|
|
88
|
+
["memory_current", "SELECT * FROM memory_current ORDER BY memory_id"],
|
|
89
|
+
["memory_timeline", "SELECT * FROM memory_timeline ORDER BY event_id"],
|
|
90
|
+
["memory_entity_mentions", "SELECT * FROM memory_entity_mentions ORDER BY memory_id, entity_ref, mention_source"],
|
|
91
|
+
];
|
|
92
|
+
for (const [name, sql] of queries) {
|
|
93
|
+
hash.update(name);
|
|
94
|
+
hash.update("\n");
|
|
95
|
+
let count = 0;
|
|
96
|
+
for (const row of db.prepare(sql).iterate()) {
|
|
97
|
+
count += 1;
|
|
98
|
+
hash.update(JSON.stringify(row));
|
|
99
|
+
hash.update("\n");
|
|
100
|
+
}
|
|
101
|
+
counts[name] = count;
|
|
102
|
+
}
|
|
103
|
+
const eventIds = (db.prepare("SELECT event_id FROM memory_timeline ORDER BY event_id").all() as Array<{ event_id: string }>)
|
|
104
|
+
.map((row) => row.event_id);
|
|
105
|
+
const previews: Record<string, string> = {};
|
|
106
|
+
for (const row of db.prepare("SELECT memory_id, preview_text FROM memory_current").all() as Array<{ memory_id: string; preview_text: string }>) {
|
|
107
|
+
previews[row.memory_id] = row.preview_text;
|
|
108
|
+
}
|
|
109
|
+
const ledgerCount = (db.prepare("SELECT value FROM meta WHERE key = 'sourceLifecycleLedgerEventCount'").get() as { value?: string } | undefined)?.value;
|
|
110
|
+
return { hash: hash.digest("hex"), counts, eventIds, previews, ledgerCount };
|
|
111
|
+
} finally {
|
|
112
|
+
db.close();
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
test("retainRaw false skips the raw copy and does not poison the corpus cache", async () => {
|
|
117
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-retain-raw-cache-"));
|
|
118
|
+
try {
|
|
119
|
+
await mkdir(path.join(memoryDir, "facts", "2026-01-01"), { recursive: true });
|
|
120
|
+
await mkdir(path.join(memoryDir, "cold", "facts", "2026-01-01"), { recursive: true });
|
|
121
|
+
await mkdir(path.join(memoryDir, "archive", "facts", "2026-01-01"), { recursive: true });
|
|
122
|
+
await writeFile(path.join(memoryDir, "facts", "2026-01-01", "hot.md"), fact("hot", "hot body"));
|
|
123
|
+
await writeFile(path.join(memoryDir, "cold", "facts", "2026-01-01", "cold.md"), fact("cold", "cold body"));
|
|
124
|
+
await writeFile(path.join(memoryDir, "archive", "facts", "2026-01-01", "arch.md"), fact("arch", "arch body"));
|
|
125
|
+
|
|
126
|
+
const storage = new StorageManager(memoryDir);
|
|
127
|
+
const hot = await storage.readAllMemories();
|
|
128
|
+
assert.equal(typeof readRawMemoryDocument(hot[0]!), "string");
|
|
129
|
+
const stripped = await storage.readAllMemories({ retainRaw: false });
|
|
130
|
+
assert.equal(readRawMemoryDocument(stripped[0]!), undefined);
|
|
131
|
+
const again = await storage.readAllMemories();
|
|
132
|
+
assert.equal(typeof readRawMemoryDocument(again[0]!), "string");
|
|
133
|
+
|
|
134
|
+
const coldFirst = await storage.readAllColdMemories({ retainRaw: false });
|
|
135
|
+
assert.equal(readRawMemoryDocument(coldFirst[0]!), undefined);
|
|
136
|
+
const coldRetained = await storage.readAllColdMemories();
|
|
137
|
+
assert.equal(typeof readRawMemoryDocument(coldRetained[0]!), "string");
|
|
138
|
+
const coldAfter = await storage.readAllColdMemories({ retainRaw: false });
|
|
139
|
+
assert.equal(readRawMemoryDocument(coldAfter[0]!), undefined);
|
|
140
|
+
const coldStill = await storage.readAllColdMemories();
|
|
141
|
+
assert.equal(typeof readRawMemoryDocument(coldStill[0]!), "string");
|
|
142
|
+
|
|
143
|
+
const archived = await storage.readArchivedMemories({ retainRaw: false });
|
|
144
|
+
assert.equal(readRawMemoryDocument(archived[0]!), undefined);
|
|
145
|
+
const archivedKept = await storage.readArchivedMemories();
|
|
146
|
+
assert.equal(typeof readRawMemoryDocument(archivedKept[0]!), "string");
|
|
147
|
+
} finally {
|
|
148
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
test("projection rows are byte-identical with retainRaw false", async () => {
|
|
153
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-retain-raw-bytes-"));
|
|
154
|
+
const events = [
|
|
155
|
+
ledgerEvent({
|
|
156
|
+
eventId: "dup-1",
|
|
157
|
+
memoryId: "hot-1",
|
|
158
|
+
eventType: "updated",
|
|
159
|
+
timestamp: "2026-03-01T00:00:00.000Z",
|
|
160
|
+
}),
|
|
161
|
+
ledgerEvent({
|
|
162
|
+
eventId: "dup-1",
|
|
163
|
+
memoryId: "hot-1",
|
|
164
|
+
eventType: "created",
|
|
165
|
+
timestamp: "2026-01-01T00:00:00.000Z",
|
|
166
|
+
}),
|
|
167
|
+
ledgerEvent({
|
|
168
|
+
eventId: "blank-1",
|
|
169
|
+
memoryId: " ",
|
|
170
|
+
eventType: "created",
|
|
171
|
+
timestamp: "2026-01-01T00:00:00.000Z",
|
|
172
|
+
}),
|
|
173
|
+
ledgerEvent({
|
|
174
|
+
eventId: "cold-evt",
|
|
175
|
+
memoryId: "cold-only",
|
|
176
|
+
eventType: "created",
|
|
177
|
+
timestamp: "2026-01-15T00:00:00.000Z",
|
|
178
|
+
}),
|
|
179
|
+
];
|
|
180
|
+
try {
|
|
181
|
+
await seedCorpus(memoryDir, events);
|
|
182
|
+
await rebuildMemoryProjection({ memoryDir, dryRun: false, now: FIXED_NOW, retainRaw: true });
|
|
183
|
+
const withRaw = projectionDigest(memoryDir);
|
|
184
|
+
await rm(getMemoryProjectionPath(memoryDir), { force: true });
|
|
185
|
+
await rebuildMemoryProjection({ memoryDir, dryRun: false, now: FIXED_NOW });
|
|
186
|
+
const withoutRaw = projectionDigest(memoryDir);
|
|
187
|
+
|
|
188
|
+
assert.equal(withoutRaw.hash, withRaw.hash);
|
|
189
|
+
assert.deepEqual(withoutRaw.counts, withRaw.counts);
|
|
190
|
+
assert.deepEqual(withoutRaw.eventIds, expectedKeptEventIds(events));
|
|
191
|
+
assert.match(withoutRaw.previews["hot-1"] ?? "", /HOTBODY/);
|
|
192
|
+
assert.equal((withoutRaw.previews["hot-1"] ?? "").includes("COLDBODY"), false);
|
|
193
|
+
assert.match(withoutRaw.previews["cold-only"] ?? "", /COLDONLY/);
|
|
194
|
+
assert.match(withoutRaw.previews["arch-1"] ?? "", /ARCHBODY/);
|
|
195
|
+
assert.equal(withoutRaw.previews[" "], undefined);
|
|
196
|
+
const identities = new Set(events.map(memoryLifecycleEventProjectionIdentity));
|
|
197
|
+
assert.equal(withoutRaw.ledgerCount, String(identities.size));
|
|
198
|
+
assert.equal(withoutRaw.counts.memory_timeline, expectedKeptEventIds(events).length);
|
|
199
|
+
} finally {
|
|
200
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
201
|
+
}
|
|
202
|
+
});
|
|
@@ -15,13 +15,12 @@ import type {
|
|
|
15
15
|
MemoryStatus,
|
|
16
16
|
} from "../types.js";
|
|
17
17
|
import {
|
|
18
|
-
buildLifecycleEventsForMemory,
|
|
19
18
|
inferMemoryStatus,
|
|
20
19
|
MEMORY_LIFECYCLE_EVENT_SORT_ORDER,
|
|
21
|
-
memoryLifecycleEventProjectionIdentity,
|
|
22
20
|
sortMemoryLifecycleEvents,
|
|
23
21
|
toMemoryPathRel,
|
|
24
22
|
} from "../memory-lifecycle-ledger-utils.js";
|
|
23
|
+
import { loadProjectionTimeline } from "./projection-timeline.js";
|
|
25
24
|
import {
|
|
26
25
|
getMemoryProjectionPath,
|
|
27
26
|
initializeMemoryProjectionDb,
|
|
@@ -44,6 +43,7 @@ import {
|
|
|
44
43
|
} from "../memory-projection-format.js";
|
|
45
44
|
import { openBetterSqlite3 } from "../runtime/better-sqlite.js";
|
|
46
45
|
import { commitPreparedFileAtomically } from "./atomic-file.js";
|
|
46
|
+
import { throwIfProjectionRebuildAborted } from "./projection-rebuild-abort.js";
|
|
47
47
|
import { isSupportPassportPrivateMemory } from "../support-passport/card-projection.js";
|
|
48
48
|
|
|
49
49
|
export interface RebuildMemoryProjectionOptions {
|
|
@@ -55,6 +55,14 @@ export interface RebuildMemoryProjectionOptions {
|
|
|
55
55
|
now?: Date;
|
|
56
56
|
updatedAfter?: string;
|
|
57
57
|
updatedBefore?: string;
|
|
58
|
+
/**
|
|
59
|
+
* When true, corpus reads keep the raw file text. Default false: the
|
|
60
|
+
* projection is built from parsed fields, and skipping the raw copy keeps
|
|
61
|
+
* the rebuild's peak heap down. Output rows stay the same either way.
|
|
62
|
+
*/
|
|
63
|
+
retainRaw?: boolean;
|
|
64
|
+
/** When aborted, the rebuild stops before it publishes the projection file. */
|
|
65
|
+
signal?: AbortSignal;
|
|
58
66
|
}
|
|
59
67
|
|
|
60
68
|
export type {
|
|
@@ -201,7 +209,8 @@ function toCurrentStateRow(memoryDir: string, memory: MemoryFile): MemoryProject
|
|
|
201
209
|
accessCount: memory.frontmatter.accessCount,
|
|
202
210
|
lastAccessed: memory.frontmatter.lastAccessed,
|
|
203
211
|
tags: normalizeProjectionTags(memory.frontmatter.tags),
|
|
204
|
-
preview
|
|
212
|
+
// Copy the preview off the source string so the full document can be collected.
|
|
213
|
+
preview: Buffer.from(normalizeProjectionPreview(memory.content), "utf8").toString("utf8"),
|
|
205
214
|
privateRecord: isSupportPassportPrivateMemory(memory),
|
|
206
215
|
};
|
|
207
216
|
}
|
|
@@ -295,23 +304,6 @@ async function loadLatestGovernanceProjection(memoryDir: string): Promise<{
|
|
|
295
304
|
}
|
|
296
305
|
}
|
|
297
306
|
|
|
298
|
-
function loadTimelineEvents(
|
|
299
|
-
memories: MemoryFile[],
|
|
300
|
-
lifecycleEvents: MemoryLifecycleEvent[],
|
|
301
|
-
): { events: MemoryLifecycleEvent[]; usedLifecycleLedger: boolean } {
|
|
302
|
-
if (lifecycleEvents.length > 0) {
|
|
303
|
-
return {
|
|
304
|
-
events: sortMemoryLifecycleEvents(lifecycleEvents),
|
|
305
|
-
usedLifecycleLedger: true,
|
|
306
|
-
};
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return {
|
|
310
|
-
events: sortMemoryLifecycleEvents(memories.flatMap((memory) => buildLifecycleEventsForMemory(memory))),
|
|
311
|
-
usedLifecycleLedger: false,
|
|
312
|
-
};
|
|
313
|
-
}
|
|
314
|
-
|
|
315
307
|
function normalizeScopedIso(value: string | undefined): string | null {
|
|
316
308
|
if (!value) return null;
|
|
317
309
|
const trimmed = value.trim();
|
|
@@ -509,53 +501,14 @@ function selectProjectionMemories(
|
|
|
509
501
|
return { allMemories, memories, skippedDuplicateMemories, skippedBlankIdMemories };
|
|
510
502
|
}
|
|
511
503
|
|
|
512
|
-
function deduplicateTimelineEvents(
|
|
513
|
-
events: MemoryLifecycleEvent[],
|
|
514
|
-
sourcePathFor: (event: MemoryLifecycleEvent) => string,
|
|
515
|
-
): {
|
|
516
|
-
events: MemoryLifecycleEvent[];
|
|
517
|
-
skipped: SkippedDuplicateTimelineEvent[];
|
|
518
|
-
skippedBlankIds: SkippedBlankIdTimelineEvent[];
|
|
519
|
-
} {
|
|
520
|
-
const keptById = new Map<string, { event: MemoryLifecycleEvent; path: string }>();
|
|
521
|
-
const unique: MemoryLifecycleEvent[] = [];
|
|
522
|
-
const skipped: SkippedDuplicateTimelineEvent[] = [];
|
|
523
|
-
const skippedBlankIds: SkippedBlankIdTimelineEvent[] = [];
|
|
524
|
-
for (const event of sortMemoryLifecycleEvents(events)) {
|
|
525
|
-
const sourcePath = sourcePathFor(event);
|
|
526
|
-
if (!event.memoryId.trim()) {
|
|
527
|
-
skippedBlankIds.push({ eventId: event.eventId, path: sourcePath });
|
|
528
|
-
log.warn(
|
|
529
|
-
`projection rebuild skipped timeline event with blank memory id: `
|
|
530
|
-
+ `event_id=${event.eventId} path=${sourcePath}`,
|
|
531
|
-
);
|
|
532
|
-
continue;
|
|
533
|
-
}
|
|
534
|
-
const kept = keptById.get(event.eventId);
|
|
535
|
-
if (kept) {
|
|
536
|
-
skipped.push({
|
|
537
|
-
eventId: event.eventId,
|
|
538
|
-
keptPath: kept.path,
|
|
539
|
-
skippedPath: sourcePath,
|
|
540
|
-
});
|
|
541
|
-
log.warn(
|
|
542
|
-
`projection rebuild skipped duplicate timeline event_id=${event.eventId}: `
|
|
543
|
-
+ `kept=${kept.path} skipped=${sourcePath}`,
|
|
544
|
-
);
|
|
545
|
-
continue;
|
|
546
|
-
}
|
|
547
|
-
keptById.set(event.eventId, { event, path: sourcePath });
|
|
548
|
-
unique.push(event);
|
|
549
|
-
}
|
|
550
|
-
return { events: unique, skipped, skippedBlankIds };
|
|
551
|
-
}
|
|
552
|
-
|
|
553
504
|
async function loadAuthoritativeProjectionSnapshot(options: {
|
|
554
505
|
memoryDir: string;
|
|
555
506
|
defaultNamespace?: string;
|
|
556
507
|
storage?: StorageManager;
|
|
557
508
|
updatedAfter?: string;
|
|
558
509
|
updatedBefore?: string;
|
|
510
|
+
retainRaw?: boolean;
|
|
511
|
+
signal?: AbortSignal;
|
|
559
512
|
}): Promise<{
|
|
560
513
|
allMemories: MemoryFile[];
|
|
561
514
|
currentRows: MemoryProjectionCurrentState[];
|
|
@@ -590,35 +543,40 @@ async function loadAuthoritativeProjectionSnapshot(options: {
|
|
|
590
543
|
// Force a fresh disk read — projection verify/rebuild must see the true
|
|
591
544
|
// on-disk state, not a potentially stale in-process cache.
|
|
592
545
|
storage.invalidateAllMemoriesCacheForDir({ indexedText: false });
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
546
|
+
const corpusRead = {
|
|
547
|
+
retainRaw: options.retainRaw === true,
|
|
548
|
+
abortSignal: options.signal,
|
|
549
|
+
};
|
|
550
|
+
const hot = await storage.readAllMemories(corpusRead);
|
|
551
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
552
|
+
const cold = await storage.readAllColdMemories(corpusRead);
|
|
553
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
554
|
+
const archived = await storage.readArchivedMemories(corpusRead);
|
|
555
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
556
|
+
const selected = selectProjectionMemories([hot, cold, archived]);
|
|
598
557
|
const allMemories = selected.allMemories;
|
|
599
558
|
const projectionMemories = selected.memories;
|
|
600
|
-
const lifecycleEvents = await storage.readAllMemoryLifecycleEvents();
|
|
601
|
-
const timeline = loadTimelineEvents(projectionMemories, lifecycleEvents);
|
|
602
|
-
const lifecycleLedgerPath = path.join(
|
|
603
|
-
options.memoryDir,
|
|
604
|
-
"state",
|
|
605
|
-
"memory-lifecycle-ledger.jsonl",
|
|
606
|
-
);
|
|
607
|
-
const memoryPathById = new Map(
|
|
608
|
-
projectionMemories.map((memory) => [memory.frontmatter.id, memory.path]),
|
|
609
|
-
);
|
|
610
|
-
const deduplicatedTimeline = deduplicateTimelineEvents(
|
|
611
|
-
timeline.events,
|
|
612
|
-
(event) => timeline.usedLifecycleLedger
|
|
613
|
-
? lifecycleLedgerPath
|
|
614
|
-
: memoryPathById.get(event.memoryId) ?? lifecycleLedgerPath,
|
|
615
|
-
);
|
|
616
|
-
const events = deduplicatedTimeline.events;
|
|
617
|
-
const usedLifecycleLedger = timeline.usedLifecycleLedger;
|
|
618
|
-
const sourceLifecycleLedgerEventCount = new Set(
|
|
619
|
-
lifecycleEvents.map(memoryLifecycleEventProjectionIdentity),
|
|
620
|
-
).size;
|
|
621
559
|
const currentRows = projectionMemories.map((memory) => toCurrentStateRow(options.memoryDir, memory));
|
|
560
|
+
// Preview is already a detached copy. Drop the document bodies before the
|
|
561
|
+
// ledger scan so peak heap is the larger of the corpus and the timeline,
|
|
562
|
+
// not both. These objects bypass the shared caches when retainRaw is off,
|
|
563
|
+
// so clearing them cannot strip a raw copy another caller is holding.
|
|
564
|
+
if (options.retainRaw !== true) {
|
|
565
|
+
for (const memory of allMemories) memory.content = "";
|
|
566
|
+
}
|
|
567
|
+
const {
|
|
568
|
+
events,
|
|
569
|
+
usedLifecycleLedger,
|
|
570
|
+
sourceLifecycleLedgerEventCount,
|
|
571
|
+
skipped: skippedDuplicateTimelineEvents,
|
|
572
|
+
skippedBlankIds: skippedBlankIdTimelineEvents,
|
|
573
|
+
} = await loadProjectionTimeline({
|
|
574
|
+
storage,
|
|
575
|
+
memoryDir: options.memoryDir,
|
|
576
|
+
memories: projectionMemories,
|
|
577
|
+
signal: options.signal,
|
|
578
|
+
});
|
|
579
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
622
580
|
const scope = normalizeProjectionScope(options);
|
|
623
581
|
const scopedMemories = filterMemoriesForProjectionScope(projectionMemories, scope);
|
|
624
582
|
const scopedMemoryIds = new Set(scopedMemories.map((memory) => memory.frontmatter.id));
|
|
@@ -660,8 +618,8 @@ async function loadAuthoritativeProjectionSnapshot(options: {
|
|
|
660
618
|
scope,
|
|
661
619
|
skippedDuplicateMemories: selected.skippedDuplicateMemories,
|
|
662
620
|
skippedBlankIdMemories: selected.skippedBlankIdMemories,
|
|
663
|
-
skippedDuplicateTimelineEvents
|
|
664
|
-
skippedBlankIdTimelineEvents
|
|
621
|
+
skippedDuplicateTimelineEvents,
|
|
622
|
+
skippedBlankIdTimelineEvents,
|
|
665
623
|
};
|
|
666
624
|
}
|
|
667
625
|
|
|
@@ -1058,6 +1016,7 @@ export async function rebuildMemoryProjection(
|
|
|
1058
1016
|
const now = options.now ?? new Date();
|
|
1059
1017
|
const outputPath = getMemoryProjectionPath(options.memoryDir);
|
|
1060
1018
|
const snapshot = await loadAuthoritativeProjectionSnapshot(options);
|
|
1019
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
1061
1020
|
|
|
1062
1021
|
let backupPath: string | undefined;
|
|
1063
1022
|
if (!dryRun) {
|
|
@@ -1117,6 +1076,7 @@ export async function rebuildMemoryProjection(
|
|
|
1117
1076
|
|
|
1118
1077
|
const tempPath = `${outputPath}.tmp`;
|
|
1119
1078
|
await mkdir(path.dirname(outputPath), { recursive: true });
|
|
1079
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
1120
1080
|
await rm(tempPath, { force: true });
|
|
1121
1081
|
writeProjectionDb(
|
|
1122
1082
|
tempPath,
|
|
@@ -1130,8 +1090,20 @@ export async function rebuildMemoryProjection(
|
|
|
1130
1090
|
snapshot.sourceLifecycleLedgerEventCount,
|
|
1131
1091
|
!hasScopedProjectionFilter(snapshot.scope),
|
|
1132
1092
|
);
|
|
1133
|
-
|
|
1134
|
-
|
|
1093
|
+
try {
|
|
1094
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
1095
|
+
backupPath = await backupExistingProjection(options.memoryDir, outputPath, now);
|
|
1096
|
+
await throwIfProjectionRebuildAborted(options.signal);
|
|
1097
|
+
backupPath = await commitPreparedFileAtomically(
|
|
1098
|
+
tempPath,
|
|
1099
|
+
outputPath,
|
|
1100
|
+
backupPath,
|
|
1101
|
+
() => throwIfProjectionRebuildAborted(options.signal),
|
|
1102
|
+
);
|
|
1103
|
+
} catch (err) {
|
|
1104
|
+
if (options.signal?.aborted) await rm(tempPath, { force: true });
|
|
1105
|
+
throw err;
|
|
1106
|
+
}
|
|
1135
1107
|
}
|
|
1136
1108
|
|
|
1137
1109
|
return {
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Heap guard for scheduled full-corpus work.
|
|
3
|
+
*
|
|
4
|
+
* A daemon already near Node's default heap limit must not start another
|
|
5
|
+
* multi-GB allocation (the scheduled projection rebuild loads hot, cold, and
|
|
6
|
+
* archived memories plus the lifecycle ledger). Callers postpone the job and
|
|
7
|
+
* arm their existing failure backoff instead.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
export interface HeapLimitStatistics {
|
|
11
|
+
used_heap_size: number;
|
|
12
|
+
heap_size_limit: number;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
export interface FullCorpusHeapPressure {
|
|
16
|
+
/** True when usage is strictly above `limitRatio`. */
|
|
17
|
+
postpone: boolean;
|
|
18
|
+
/** `used_heap_size / heap_size_limit`, or 0 when the statistics are unusable. */
|
|
19
|
+
ratio: number;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Decide whether a scheduled full-corpus job should wait. Non-finite or
|
|
24
|
+
* non-positive heap limits do not postpone (there is no ratio to trust).
|
|
25
|
+
* Comparison is strict `>` so a limit of `1` never fires.
|
|
26
|
+
*/
|
|
27
|
+
export function fullCorpusHeapPressure(
|
|
28
|
+
stats: HeapLimitStatistics,
|
|
29
|
+
limitRatio: number,
|
|
30
|
+
): FullCorpusHeapPressure {
|
|
31
|
+
const used = stats.used_heap_size;
|
|
32
|
+
const cap = stats.heap_size_limit;
|
|
33
|
+
if (!Number.isFinite(used) || used < 0 || !Number.isFinite(cap) || cap <= 0 || !Number.isFinite(limitRatio)) {
|
|
34
|
+
return { postpone: false, ratio: 0 };
|
|
35
|
+
}
|
|
36
|
+
const ratio = used / cap;
|
|
37
|
+
return { postpone: ratio > limitRatio, ratio };
|
|
38
|
+
}
|
|
@@ -2968,8 +2968,8 @@ test("maintenance tool request invokes the scheduled projection rebuild wiring (
|
|
|
2968
2968
|
});
|
|
2969
2969
|
try {
|
|
2970
2970
|
scheduler.requestQmdMaintenanceForTool("test");
|
|
2971
|
-
for (let attempt = 0; attempt <
|
|
2972
|
-
await delay(
|
|
2971
|
+
for (let attempt = 0; attempt < 60 && probeProjectionHealth(memoryDir).state === "absent"; attempt += 1) {
|
|
2972
|
+
await delay(500);
|
|
2973
2973
|
}
|
|
2974
2974
|
assert.equal(
|
|
2975
2975
|
probeProjectionHealth(memoryDir).state,
|
|
@@ -55,6 +55,7 @@ import { resolveDaySummaryCronModel } from "../maintenance/day-summary-cron.js";
|
|
|
55
55
|
import {
|
|
56
56
|
createProjectionRebuildScheduleState,
|
|
57
57
|
maybeRebuildMemoryProjectionScheduled,
|
|
58
|
+
terminateScheduledProjectionRebuilds,
|
|
58
59
|
} from "./projection-rebuild-schedule.js";
|
|
59
60
|
import {
|
|
60
61
|
drainPendingLifecycleLedgerIfAny,
|
|
@@ -1168,6 +1169,7 @@ export class MaintenanceScheduler {
|
|
|
1168
1169
|
*/
|
|
1169
1170
|
async dispose(): Promise<void> {
|
|
1170
1171
|
this.disposed = true;
|
|
1172
|
+
terminateScheduledProjectionRebuilds(this.projectionRebuild);
|
|
1171
1173
|
const consolidationDrain = this.consolidationRunPromise;
|
|
1172
1174
|
// The registrar latches teardown first (so a draining tick's onRun cannot
|
|
1173
1175
|
// re-arm QMD maintenance) and aborts+drains the sync. Capture its drain and
|