@remnic/core 10.0.52 → 10.0.53
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 +24 -24
- package/dist/access-authorization-probe.js +25 -25
- package/dist/access-boundary.js +24 -24
- package/dist/access-cli.js +65 -65
- package/dist/access-extraction-force-flush.js +24 -24
- package/dist/access-http-briefing.js +25 -25
- package/dist/access-http-query.js +26 -26
- package/dist/access-http.js +40 -40
- package/dist/access-identity-continuity-surface.js +24 -24
- package/dist/access-lcm-surface.js +24 -24
- package/dist/access-mcp.js +33 -33
- package/dist/access-namespace-preflight.js +24 -24
- package/dist/access-observe-write-surface.js +24 -24
- package/dist/access-operations-batch.js +25 -25
- package/dist/access-operations.js +32 -32
- package/dist/access-recall-concurrency.js +24 -24
- package/dist/access-recall-response.js +24 -24
- package/dist/access-recall-surface.js +24 -24
- package/dist/access-service.js +24 -24
- package/dist/access-surface-catalog.js +26 -26
- package/dist/active-recall.js +9 -9
- package/dist/briefing.js +10 -10
- package/dist/buffer.js +5 -5
- package/dist/causal-consolidation.js +11 -11
- package/dist/{chunk-3NL4ALUP.js → chunk-24SIB3EW.js} +3 -3
- package/dist/{chunk-Y3T5KQCR.js → chunk-2EYCW2ET.js} +2 -2
- package/dist/{chunk-AHGOOZUC.js → chunk-34UVJNSG.js} +2 -2
- package/dist/{chunk-2EXF6IIB.js → chunk-3632XJMR.js} +2 -2
- package/dist/{chunk-KETS5A62.js → chunk-3H3PNQEF.js} +2 -2
- package/dist/{chunk-SFRBUBUZ.js → chunk-3LNAQLW4.js} +3 -3
- package/dist/{chunk-75BK4XGV.js → chunk-4BUJICMI.js} +10 -10
- package/dist/{chunk-KIWO4327.js → chunk-4W5B5Z6P.js} +2 -2
- package/dist/{chunk-B35EQQ7L.js → chunk-53OFDW3P.js} +3 -3
- package/dist/{chunk-2ONKXEC7.js → chunk-5LBBXI2A.js} +2 -2
- package/dist/{chunk-UCLJTGP3.js → chunk-65B5RFKQ.js} +2 -2
- package/dist/{chunk-KAJYSO3U.js → chunk-6CDNOREO.js} +2 -2
- package/dist/{chunk-POJRFSJM.js → chunk-7XGNGLAN.js} +2 -2
- package/dist/{chunk-A6JDT6QF.js → chunk-AO5ZOD32.js} +2 -2
- package/dist/{chunk-RA7YRL6H.js → chunk-AOSCGNIC.js} +3 -3
- package/dist/{chunk-LWMLBVGB.js → chunk-B43P3DTC.js} +2 -2
- package/dist/{chunk-UM3ZLT2X.js → chunk-CA6X37OB.js} +31 -28
- package/dist/chunk-CA6X37OB.js.map +1 -0
- package/dist/{chunk-VUMWVYMR.js → chunk-CIMD2MUR.js} +3 -3
- package/dist/{chunk-XRFLR3XF.js → chunk-DLZGSZVC.js} +22 -9
- package/dist/chunk-DLZGSZVC.js.map +1 -0
- package/dist/{chunk-5CWH2LKL.js → chunk-DOJBV6WR.js} +29 -14
- package/dist/chunk-DOJBV6WR.js.map +1 -0
- package/dist/{chunk-44EUCSG4.js → chunk-FFQNNFHX.js} +2 -2
- package/dist/{chunk-HEF4BRMT.js → chunk-FZLZUDJJ.js} +2 -2
- package/dist/{chunk-L3EFYRYK.js → chunk-GGFQAGOT.js} +7 -7
- package/dist/{chunk-ZLCBLDJO.js → chunk-GIRWNTMV.js} +2 -2
- package/dist/{chunk-EC2KVA27.js → chunk-H4DWSOBQ.js} +169 -105
- package/dist/chunk-H4DWSOBQ.js.map +1 -0
- package/dist/{chunk-SHNM7RIT.js → chunk-HJ4X4BGS.js} +2 -2
- package/dist/{chunk-MUNYUSBU.js → chunk-HJQ4NKKO.js} +2 -2
- package/dist/{chunk-V6Z4NAJZ.js → chunk-HM3ZTDAX.js} +2 -2
- package/dist/{chunk-EZS6QJNC.js → chunk-IFOCK3OJ.js} +2 -2
- package/dist/{chunk-LXXIV7Y2.js → chunk-JEX2JL3U.js} +7 -2
- package/dist/{chunk-LXXIV7Y2.js.map → chunk-JEX2JL3U.js.map} +1 -1
- package/dist/{chunk-DF6ZF2BN.js → chunk-LIVNX7WK.js} +2 -2
- package/dist/{chunk-WY66J4PI.js → chunk-LRVFS4KA.js} +2 -2
- package/dist/{chunk-LMB47UM6.js → chunk-LTDK6HBV.js} +2 -2
- package/dist/{chunk-HCIRR3BA.js → chunk-M4U25HLR.js} +2 -2
- package/dist/{chunk-YK7ZJPQM.js → chunk-MGN2RQRG.js} +2 -2
- package/dist/{chunk-G26YNEOC.js → chunk-NWA6IXR3.js} +1 -1
- package/dist/{chunk-G26YNEOC.js.map → chunk-NWA6IXR3.js.map} +1 -1
- package/dist/{chunk-JIJAWTRK.js → chunk-OCXDZJL4.js} +264 -194
- package/dist/chunk-OCXDZJL4.js.map +1 -0
- package/dist/{chunk-IUQXRRJB.js → chunk-OMWQO7H6.js} +2 -2
- package/dist/{chunk-7VO6E5UD.js → chunk-OVZIYLBZ.js} +6 -2
- package/dist/chunk-OVZIYLBZ.js.map +1 -0
- package/dist/{chunk-SPTPBKZX.js → chunk-OWNAWY6D.js} +2 -2
- package/dist/{chunk-XKDQTDXN.js → chunk-PFUXPTBT.js} +36 -15
- package/dist/chunk-PFUXPTBT.js.map +1 -0
- package/dist/{chunk-DQOGZZJA.js → chunk-QAHP5SBG.js} +3 -3
- package/dist/{chunk-GBGU5OZP.js → chunk-QF5EJ5VP.js} +13 -13
- package/dist/{chunk-FT75AQ74.js → chunk-QS5DUSBM.js} +2 -2
- package/dist/{chunk-72CBJ5VP.js → chunk-R3WZ74B2.js} +3 -3
- package/dist/{chunk-PDTNQLPC.js → chunk-RG3I2663.js} +2 -2
- package/dist/{chunk-CK6GCGMX.js → chunk-RTJJPW3C.js} +2 -2
- package/dist/{chunk-RJDYDF5K.js → chunk-TRAOZ2WP.js} +2 -2
- package/dist/{chunk-6ZAU7LAR.js → chunk-TTTPTQ6S.js} +2 -2
- package/dist/{chunk-JS44PBCM.js → chunk-U2A56LLF.js} +6 -6
- package/dist/{chunk-MC7PXJDP.js → chunk-UBOWDOL5.js} +5 -5
- package/dist/{chunk-4FM35YIA.js → chunk-UQYBPPVC.js} +2 -2
- package/dist/{chunk-OCRLJJOV.js → chunk-V4VCBFAL.js} +3 -3
- package/dist/{chunk-FNNGWN3O.js → chunk-VGE4PUY6.js} +2 -2
- package/dist/{chunk-5DVOBBTV.js → chunk-VV73XT3A.js} +2 -2
- package/dist/{chunk-GE3ZX6YK.js → chunk-W7NKMRAF.js} +2 -2
- package/dist/{chunk-AJJPXUE6.js → chunk-WBN66HPI.js} +2 -2
- package/dist/{chunk-XWJUFER3.js → chunk-WGFEGBFB.js} +2 -2
- package/dist/{chunk-43TUWQNR.js → chunk-XDKEHZUC.js} +2 -2
- package/dist/{chunk-ROAKLYOL.js → chunk-XHEKS4UN.js} +2 -2
- package/dist/{chunk-ZKK3VMWU.js → chunk-XVTB6BZS.js} +2 -2
- package/dist/{chunk-AZLD4CKG.js → chunk-Y56D5FSD.js} +17 -17
- package/dist/{chunk-MPWOAIIH.js → chunk-YDT3OEYF.js} +2 -2
- package/dist/{chunk-IN6U2BS5.js → chunk-YJHOVA42.js} +2 -2
- package/dist/{chunk-TC55M5PO.js → chunk-YLN4ZQV4.js} +2 -2
- package/dist/cli.js +50 -50
- package/dist/coding/export-okf-codegraph.js +9 -9
- package/dist/compounding/engine.js +11 -11
- package/dist/config.js +9 -9
- package/dist/connectors/codex-materialize-runner.js +10 -10
- package/dist/connectors/index.js +10 -10
- package/dist/convergence-refresh.js +12 -12
- package/dist/corpus-watermark.js +12 -12
- package/dist/entity-retrieval.js +10 -10
- package/dist/external-wiki-access.js +25 -25
- package/dist/extraction.js +14 -14
- package/dist/harmonic-retrieval.js +10 -10
- package/dist/index.js +65 -65
- package/dist/location/index.js +12 -12
- package/dist/maintenance/memory-governance.js +10 -10
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +10 -10
- package/dist/maintenance/rebuild-memory-projection-runner.js +12 -12
- package/dist/maintenance/rebuild-memory-projection.js +11 -11
- package/dist/memory-browse-operations.js +25 -25
- package/dist/memory-browse.js +5 -5
- package/dist/namespaces/migrate.js +11 -11
- package/dist/namespaces/search.d.ts.map +1 -1
- package/dist/namespaces/search.js +8 -8
- package/dist/namespaces/storage.js +10 -10
- package/dist/operator-doctor-corpus.js +13 -13
- package/dist/operator-toolkit.js +18 -18
- package/dist/orchestration/lifecycle-pending-fallback-drain.d.ts +18 -0
- package/dist/orchestration/lifecycle-pending-fallback-drain.d.ts.map +1 -0
- package/dist/orchestration/maintenance.d.ts +11 -13
- package/dist/orchestration/maintenance.d.ts.map +1 -1
- package/dist/orchestration/maintenance.js +20 -20
- package/dist/orchestration/qmd-maintenance-completion.d.ts +20 -0
- package/dist/orchestration/qmd-maintenance-completion.d.ts.map +1 -0
- package/dist/orchestrator.d.ts.map +1 -1
- package/dist/orchestrator.js +65 -65
- package/dist/qmd.js +2 -2
- package/dist/recall-composition-decision.js +2 -2
- package/dist/recall-navigation-operations.js +25 -25
- package/dist/recall-navigation.js +24 -24
- package/dist/recall-state-view-admission.js +5 -5
- package/dist/recall-why-service.js +5 -5
- package/dist/resume-bundles.js +9 -9
- package/dist/search/factory.js +7 -7
- package/dist/search/index.js +7 -7
- package/dist/search/lancedb-backend.d.ts +3 -0
- package/dist/search/lancedb-backend.d.ts.map +1 -1
- package/dist/search/lancedb-backend.js +2 -2
- package/dist/search/meilisearch-backend.d.ts +3 -0
- package/dist/search/meilisearch-backend.d.ts.map +1 -1
- package/dist/search/meilisearch-backend.js +2 -2
- package/dist/search/orama-backend.d.ts +3 -0
- package/dist/search/orama-backend.d.ts.map +1 -1
- package/dist/search/orama-backend.js +2 -2
- package/dist/search/port.d.ts +7 -0
- package/dist/search/port.d.ts.map +1 -1
- package/dist/search/port.js +1 -1
- package/dist/search/remote-backend.d.ts +2 -0
- package/dist/search/remote-backend.d.ts.map +1 -1
- package/dist/search/remote-backend.js +2 -2
- package/dist/semantic-consolidation.js +11 -11
- package/dist/semantic-rule-promotion.js +10 -10
- package/dist/semantic-rule-verifier.js +10 -10
- package/dist/source-agent-qualifier.js +13 -13
- package/dist/standup/build.js +10 -10
- package/dist/storage/entity-canonical-id-migration-adapter.d.ts +7 -1
- package/dist/storage/entity-canonical-id-migration-adapter.d.ts.map +1 -1
- package/dist/storage/entity-migration-maintenance-pending.d.ts +31 -0
- package/dist/storage/entity-migration-maintenance-pending.d.ts.map +1 -0
- package/dist/storage.d.ts +2 -2
- package/dist/storage.d.ts.map +1 -1
- package/dist/storage.js +9 -9
- package/dist/support-passport/index.js +27 -27
- package/dist/transfer/export-okf.js +10 -10
- package/dist/verified-recall.js +10 -10
- package/dist/who-knows-cli.js +11 -11
- package/dist/who-knows.js +10 -10
- package/package.json +2 -2
- package/src/namespaces/search.test.ts +121 -0
- package/src/namespaces/search.ts +8 -0
- package/src/orchestration/lifecycle-pending-fallback-drain.ts +97 -0
- package/src/orchestration/maintenance.test.ts +443 -1
- package/src/orchestration/maintenance.ts +73 -95
- package/src/orchestration/qmd-maintenance-completion.ts +32 -0
- package/src/orchestrator.ts +8 -1
- package/src/search/lancedb-backend.ts +29 -12
- package/src/search/meilisearch-backend.test.ts +148 -0
- package/src/search/meilisearch-backend.ts +41 -14
- package/src/search/orama-backend.test.ts +75 -1
- package/src/search/orama-backend.ts +22 -7
- package/src/search/port.ts +7 -0
- package/src/search/remote-backend.ts +4 -0
- package/src/storage/entity-canonical-id-migration-adapter.ts +44 -9
- package/src/storage/entity-migration-maintenance-pending-helpers.test.ts +87 -0
- package/src/storage/entity-migration-maintenance-pending.test.ts +242 -0
- package/src/storage/entity-migration-maintenance-pending.ts +89 -0
- package/src/storage.ts +2 -2
- package/dist/chunk-5CWH2LKL.js.map +0 -1
- package/dist/chunk-7VO6E5UD.js.map +0 -1
- package/dist/chunk-EC2KVA27.js.map +0 -1
- package/dist/chunk-JIJAWTRK.js.map +0 -1
- package/dist/chunk-UM3ZLT2X.js.map +0 -1
- package/dist/chunk-XKDQTDXN.js.map +0 -1
- package/dist/chunk-XRFLR3XF.js.map +0 -1
- /package/dist/{chunk-3NL4ALUP.js.map → chunk-24SIB3EW.js.map} +0 -0
- /package/dist/{chunk-Y3T5KQCR.js.map → chunk-2EYCW2ET.js.map} +0 -0
- /package/dist/{chunk-AHGOOZUC.js.map → chunk-34UVJNSG.js.map} +0 -0
- /package/dist/{chunk-2EXF6IIB.js.map → chunk-3632XJMR.js.map} +0 -0
- /package/dist/{chunk-KETS5A62.js.map → chunk-3H3PNQEF.js.map} +0 -0
- /package/dist/{chunk-SFRBUBUZ.js.map → chunk-3LNAQLW4.js.map} +0 -0
- /package/dist/{chunk-75BK4XGV.js.map → chunk-4BUJICMI.js.map} +0 -0
- /package/dist/{chunk-KIWO4327.js.map → chunk-4W5B5Z6P.js.map} +0 -0
- /package/dist/{chunk-B35EQQ7L.js.map → chunk-53OFDW3P.js.map} +0 -0
- /package/dist/{chunk-2ONKXEC7.js.map → chunk-5LBBXI2A.js.map} +0 -0
- /package/dist/{chunk-UCLJTGP3.js.map → chunk-65B5RFKQ.js.map} +0 -0
- /package/dist/{chunk-KAJYSO3U.js.map → chunk-6CDNOREO.js.map} +0 -0
- /package/dist/{chunk-POJRFSJM.js.map → chunk-7XGNGLAN.js.map} +0 -0
- /package/dist/{chunk-A6JDT6QF.js.map → chunk-AO5ZOD32.js.map} +0 -0
- /package/dist/{chunk-RA7YRL6H.js.map → chunk-AOSCGNIC.js.map} +0 -0
- /package/dist/{chunk-LWMLBVGB.js.map → chunk-B43P3DTC.js.map} +0 -0
- /package/dist/{chunk-VUMWVYMR.js.map → chunk-CIMD2MUR.js.map} +0 -0
- /package/dist/{chunk-44EUCSG4.js.map → chunk-FFQNNFHX.js.map} +0 -0
- /package/dist/{chunk-HEF4BRMT.js.map → chunk-FZLZUDJJ.js.map} +0 -0
- /package/dist/{chunk-L3EFYRYK.js.map → chunk-GGFQAGOT.js.map} +0 -0
- /package/dist/{chunk-ZLCBLDJO.js.map → chunk-GIRWNTMV.js.map} +0 -0
- /package/dist/{chunk-SHNM7RIT.js.map → chunk-HJ4X4BGS.js.map} +0 -0
- /package/dist/{chunk-MUNYUSBU.js.map → chunk-HJQ4NKKO.js.map} +0 -0
- /package/dist/{chunk-V6Z4NAJZ.js.map → chunk-HM3ZTDAX.js.map} +0 -0
- /package/dist/{chunk-EZS6QJNC.js.map → chunk-IFOCK3OJ.js.map} +0 -0
- /package/dist/{chunk-DF6ZF2BN.js.map → chunk-LIVNX7WK.js.map} +0 -0
- /package/dist/{chunk-WY66J4PI.js.map → chunk-LRVFS4KA.js.map} +0 -0
- /package/dist/{chunk-LMB47UM6.js.map → chunk-LTDK6HBV.js.map} +0 -0
- /package/dist/{chunk-HCIRR3BA.js.map → chunk-M4U25HLR.js.map} +0 -0
- /package/dist/{chunk-YK7ZJPQM.js.map → chunk-MGN2RQRG.js.map} +0 -0
- /package/dist/{chunk-IUQXRRJB.js.map → chunk-OMWQO7H6.js.map} +0 -0
- /package/dist/{chunk-SPTPBKZX.js.map → chunk-OWNAWY6D.js.map} +0 -0
- /package/dist/{chunk-DQOGZZJA.js.map → chunk-QAHP5SBG.js.map} +0 -0
- /package/dist/{chunk-GBGU5OZP.js.map → chunk-QF5EJ5VP.js.map} +0 -0
- /package/dist/{chunk-FT75AQ74.js.map → chunk-QS5DUSBM.js.map} +0 -0
- /package/dist/{chunk-72CBJ5VP.js.map → chunk-R3WZ74B2.js.map} +0 -0
- /package/dist/{chunk-PDTNQLPC.js.map → chunk-RG3I2663.js.map} +0 -0
- /package/dist/{chunk-CK6GCGMX.js.map → chunk-RTJJPW3C.js.map} +0 -0
- /package/dist/{chunk-RJDYDF5K.js.map → chunk-TRAOZ2WP.js.map} +0 -0
- /package/dist/{chunk-6ZAU7LAR.js.map → chunk-TTTPTQ6S.js.map} +0 -0
- /package/dist/{chunk-JS44PBCM.js.map → chunk-U2A56LLF.js.map} +0 -0
- /package/dist/{chunk-MC7PXJDP.js.map → chunk-UBOWDOL5.js.map} +0 -0
- /package/dist/{chunk-4FM35YIA.js.map → chunk-UQYBPPVC.js.map} +0 -0
- /package/dist/{chunk-OCRLJJOV.js.map → chunk-V4VCBFAL.js.map} +0 -0
- /package/dist/{chunk-FNNGWN3O.js.map → chunk-VGE4PUY6.js.map} +0 -0
- /package/dist/{chunk-5DVOBBTV.js.map → chunk-VV73XT3A.js.map} +0 -0
- /package/dist/{chunk-GE3ZX6YK.js.map → chunk-W7NKMRAF.js.map} +0 -0
- /package/dist/{chunk-AJJPXUE6.js.map → chunk-WBN66HPI.js.map} +0 -0
- /package/dist/{chunk-XWJUFER3.js.map → chunk-WGFEGBFB.js.map} +0 -0
- /package/dist/{chunk-43TUWQNR.js.map → chunk-XDKEHZUC.js.map} +0 -0
- /package/dist/{chunk-ROAKLYOL.js.map → chunk-XHEKS4UN.js.map} +0 -0
- /package/dist/{chunk-ZKK3VMWU.js.map → chunk-XVTB6BZS.js.map} +0 -0
- /package/dist/{chunk-AZLD4CKG.js.map → chunk-Y56D5FSD.js.map} +0 -0
- /package/dist/{chunk-MPWOAIIH.js.map → chunk-YDT3OEYF.js.map} +0 -0
- /package/dist/{chunk-IN6U2BS5.js.map → chunk-YJHOVA42.js.map} +0 -0
- /package/dist/{chunk-TC55M5PO.js.map → chunk-YLN4ZQV4.js.map} +0 -0
package/dist/who-knows.js
CHANGED
|
@@ -9,19 +9,19 @@ import {
|
|
|
9
9
|
loadWhoKnowsEntities,
|
|
10
10
|
tokenizeTopic,
|
|
11
11
|
validateWhoKnowsInput
|
|
12
|
-
} from "./chunk-
|
|
13
|
-
import "./chunk-
|
|
12
|
+
} from "./chunk-5LBBXI2A.js";
|
|
13
|
+
import "./chunk-OCXDZJL4.js";
|
|
14
14
|
import "./chunk-UHVXE24Y.js";
|
|
15
15
|
import "./chunk-DM5QZ3YU.js";
|
|
16
16
|
import "./chunk-G6A3SGCE.js";
|
|
17
17
|
import "./chunk-G6OFEGUR.js";
|
|
18
|
-
import "./chunk-
|
|
19
|
-
import "./chunk-
|
|
20
|
-
import "./chunk-
|
|
21
|
-
import "./chunk-
|
|
18
|
+
import "./chunk-JEX2JL3U.js";
|
|
19
|
+
import "./chunk-U2A56LLF.js";
|
|
20
|
+
import "./chunk-DOJBV6WR.js";
|
|
21
|
+
import "./chunk-PFUXPTBT.js";
|
|
22
22
|
import "./chunk-CYEPCZN5.js";
|
|
23
|
-
import "./chunk-
|
|
24
|
-
import "./chunk-
|
|
23
|
+
import "./chunk-DLZGSZVC.js";
|
|
24
|
+
import "./chunk-OVZIYLBZ.js";
|
|
25
25
|
import "./chunk-WNEVEMJ3.js";
|
|
26
26
|
import "./chunk-EXYT52NR.js";
|
|
27
27
|
import "./chunk-Y5NLBXPV.js";
|
|
@@ -57,8 +57,8 @@ import "./chunk-7CT3AI52.js";
|
|
|
57
57
|
import "./chunk-G7D6GZ5J.js";
|
|
58
58
|
import "./chunk-7VLBZKNB.js";
|
|
59
59
|
import "./chunk-UUZ7KZAO.js";
|
|
60
|
-
import "./chunk-
|
|
61
|
-
import "./chunk-
|
|
60
|
+
import "./chunk-WBN66HPI.js";
|
|
61
|
+
import "./chunk-NWA6IXR3.js";
|
|
62
62
|
import "./chunk-VILPVT4S.js";
|
|
63
63
|
import "./chunk-AF2XMJKD.js";
|
|
64
64
|
import "./chunk-OR42ZI54.js";
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@remnic/core",
|
|
3
|
-
"version": "10.0.
|
|
3
|
+
"version": "10.0.53",
|
|
4
4
|
"description": "Framework-agnostic Remnic memory engine — orchestrator, storage, extraction, search, trust zones",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "dist/index.js",
|
|
@@ -3346,7 +3346,7 @@
|
|
|
3346
3346
|
"core"
|
|
3347
3347
|
],
|
|
3348
3348
|
"peerDependencies": {
|
|
3349
|
-
"@remnic/coding-graph": "^10.0.
|
|
3349
|
+
"@remnic/coding-graph": "^10.0.53"
|
|
3350
3350
|
},
|
|
3351
3351
|
"peerDependenciesMeta": {
|
|
3352
3352
|
"@remnic/coding-graph": {
|
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import assert from "node:assert/strict";
|
|
2
2
|
import test from "node:test";
|
|
3
|
+
import os from "node:os";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { mkdtemp, rm } from "node:fs/promises";
|
|
3
6
|
import { NamespaceSearchRouter, normalizeQmdResultPath } from "./search.js";
|
|
7
|
+
import { MaintenanceScheduler } from "../orchestration/maintenance.js";
|
|
8
|
+
import type { NamespaceCatalog } from "./catalog.js";
|
|
4
9
|
import type {
|
|
5
10
|
SearchBackend,
|
|
6
11
|
SearchBackendStatus,
|
|
@@ -977,3 +982,119 @@ test("normalizeQmdResultPath strips a real collection prefix but not a category
|
|
|
977
982
|
// A non-category collection prefix on a plain hit is still stripped.
|
|
978
983
|
assert.equal(normalizeQmdResultPath("openclaw-engram/facts/a.md", "openclaw-engram"), "facts/a.md");
|
|
979
984
|
});
|
|
985
|
+
|
|
986
|
+
/**
|
|
987
|
+
* Orama, LanceDB, Meilisearch and remote backends have no updateStrict or
|
|
988
|
+
* updateCollectionStrict; their plain update() is fail-open. They report whether
|
|
989
|
+
* an update ran through updateCompleted() (issue #3286).
|
|
990
|
+
*/
|
|
991
|
+
class NonQmdBackend extends FakeBackend {
|
|
992
|
+
completedCalls = 0;
|
|
993
|
+
|
|
994
|
+
constructor(completed: boolean) {
|
|
995
|
+
super(false);
|
|
996
|
+
// Instance properties shadow the QMD-only strict methods FakeBackend defines.
|
|
997
|
+
Object.defineProperty(this, "updateStrict", { value: undefined });
|
|
998
|
+
Object.defineProperty(this, "updateCollectionStrict", { value: undefined });
|
|
999
|
+
Object.defineProperty(this, "updateCompleted", {
|
|
1000
|
+
value: async (): Promise<boolean> => {
|
|
1001
|
+
this.completedCalls += 1;
|
|
1002
|
+
return completed;
|
|
1003
|
+
},
|
|
1004
|
+
});
|
|
1005
|
+
}
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
function nonQmdRouter(completed: boolean, created: NonQmdBackend[], cfg: PluginConfig = config()): NamespaceSearchRouter {
|
|
1009
|
+
return new NamespaceSearchRouter(
|
|
1010
|
+
cfg,
|
|
1011
|
+
{ storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
|
|
1012
|
+
() => {
|
|
1013
|
+
const backend = new NonQmdBackend(completed);
|
|
1014
|
+
created.push(backend);
|
|
1015
|
+
return backend;
|
|
1016
|
+
},
|
|
1017
|
+
);
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
test("strict updateNamespaces fails for a non-QMD backend whose refresh did not complete", async () => {
|
|
1021
|
+
const created: NonQmdBackend[] = [];
|
|
1022
|
+
const router = nonQmdRouter(false, created);
|
|
1023
|
+
|
|
1024
|
+
await assert.rejects(
|
|
1025
|
+
router.updateNamespaces(["main"], undefined, { strict: true }),
|
|
1026
|
+
/did not complete/,
|
|
1027
|
+
);
|
|
1028
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.updates, 0), 0, "the fail-open update() is not what strict runs");
|
|
1029
|
+
});
|
|
1030
|
+
|
|
1031
|
+
test("strict updateNamespaces succeeds for a non-QMD backend whose refresh completed", async () => {
|
|
1032
|
+
const created: NonQmdBackend[] = [];
|
|
1033
|
+
const router = nonQmdRouter(true, created);
|
|
1034
|
+
|
|
1035
|
+
assert.equal(await router.updateNamespaces(["main", "shared"], undefined, { strict: true }), 2);
|
|
1036
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.completedCalls, 0), 2);
|
|
1037
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.updates, 0), 0);
|
|
1038
|
+
});
|
|
1039
|
+
|
|
1040
|
+
test("non-strict updateNamespaces keeps the fail-open update() for non-QMD backends", async () => {
|
|
1041
|
+
const created: NonQmdBackend[] = [];
|
|
1042
|
+
const router = nonQmdRouter(false, created);
|
|
1043
|
+
|
|
1044
|
+
assert.equal(await router.updateNamespaces(["main"]), 1);
|
|
1045
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.updates, 0), 1);
|
|
1046
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.completedCalls, 0), 0);
|
|
1047
|
+
});
|
|
1048
|
+
|
|
1049
|
+
test("strict updateNamespaces falls back to update() for a backend with no strict or completed variant", async () => {
|
|
1050
|
+
const created: FakeBackend[] = [];
|
|
1051
|
+
const router = new NamespaceSearchRouter(
|
|
1052
|
+
config(),
|
|
1053
|
+
{ storageFor: async (namespace: string) => ({ dir: `/tmp/remnic/${namespace}` }) },
|
|
1054
|
+
() => {
|
|
1055
|
+
const backend = new FakeBackend(false);
|
|
1056
|
+
Object.defineProperty(backend, "updateCollectionStrict", { value: undefined });
|
|
1057
|
+
created.push(backend);
|
|
1058
|
+
return backend;
|
|
1059
|
+
},
|
|
1060
|
+
);
|
|
1061
|
+
|
|
1062
|
+
assert.equal(await router.updateNamespaces(["main"], undefined, { strict: true }), 1);
|
|
1063
|
+
assert.equal(created.reduce((sum, backend) => sum + backend.updates, 0), 1);
|
|
1064
|
+
});
|
|
1065
|
+
|
|
1066
|
+
test("namespace-mode maintenance is served only when a non-QMD backend's refresh completed", async () => {
|
|
1067
|
+
for (const completed of [true, false]) {
|
|
1068
|
+
const memoryDir = await mkdtemp(path.join(os.tmpdir(), "remnic-3286-ns-completion-"));
|
|
1069
|
+
const cfg: PluginConfig = {
|
|
1070
|
+
...config(),
|
|
1071
|
+
memoryDir,
|
|
1072
|
+
sharedNamespace: "shared",
|
|
1073
|
+
namespacePolicies: [],
|
|
1074
|
+
maintenanceNamespaceLockStaleMs: 100,
|
|
1075
|
+
qmdMaintenanceEnabled: true,
|
|
1076
|
+
qmdMaintenanceDebounceMs: 60_000,
|
|
1077
|
+
qmdAutoEmbedEnabled: false,
|
|
1078
|
+
};
|
|
1079
|
+
const created: NonQmdBackend[] = [];
|
|
1080
|
+
const router = nonQmdRouter(completed, created, cfg);
|
|
1081
|
+
const catalog: NamespaceCatalog = Object.assign(Object.create(null), {
|
|
1082
|
+
enabled: true,
|
|
1083
|
+
async listNamespaces() {
|
|
1084
|
+
return [{ namespace: "main" }];
|
|
1085
|
+
},
|
|
1086
|
+
async markMaintenance() {},
|
|
1087
|
+
});
|
|
1088
|
+
const qmd: SearchBackend = Object.assign(Object.create(null), { isAvailable: () => true });
|
|
1089
|
+
const scheduler = new MaintenanceScheduler({ config: cfg, getQmd: () => qmd, namespaceSearchRouter: router, namespaceCatalog: catalog });
|
|
1090
|
+
try {
|
|
1091
|
+
const served = scheduler.requestQmdMaintenanceCompletion();
|
|
1092
|
+
await scheduler.runQmdMaintenance();
|
|
1093
|
+
assert.equal(await served, completed, completed ? "a completed refresh serves the request" : "an incomplete refresh must keep the marker owed");
|
|
1094
|
+
assert.ok(created.some((backend) => backend.completedCalls > 0), "maintenance asked the backend whether it completed");
|
|
1095
|
+
} finally {
|
|
1096
|
+
await scheduler.dispose();
|
|
1097
|
+
await rm(memoryDir, { recursive: true, force: true });
|
|
1098
|
+
}
|
|
1099
|
+
}
|
|
1100
|
+
});
|
package/src/namespaces/search.ts
CHANGED
|
@@ -596,6 +596,14 @@ async function updateBackendRecord(
|
|
|
596
596
|
await record.backend.updateCollectionStrict(record.collection, execution);
|
|
597
597
|
return;
|
|
598
598
|
}
|
|
599
|
+
// Backends with no strict variant (Orama, LanceDB, Meilisearch, remote) have a fail-open
|
|
600
|
+
// update(): it resolves when it returned early or failed. Their updateCompleted() says
|
|
601
|
+
// whether the refresh ran, so strict callers get a failure instead of a fake success.
|
|
602
|
+
const completed = await record.backend.updateCompleted?.(execution);
|
|
603
|
+
if (completed !== undefined) {
|
|
604
|
+
if (!completed) throw new Error("search backend update did not complete");
|
|
605
|
+
return;
|
|
606
|
+
}
|
|
599
607
|
}
|
|
600
608
|
await record.backend.update(execution);
|
|
601
609
|
}
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fallback lifecycle pending-append drain for targets with no secure
|
|
3
|
+
* StorageManager. Moved verbatim out of maintenance.ts (issue #2033) so that
|
|
4
|
+
* file stays under the structural size ceiling; behavior is unchanged.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
import { appendFile, mkdir, readFile, writeFile } from "node:fs/promises";
|
|
8
|
+
import path from "node:path";
|
|
9
|
+
|
|
10
|
+
import { log } from "../logger.js";
|
|
11
|
+
import {
|
|
12
|
+
drainPendingLifecycleLedgerIfAny,
|
|
13
|
+
pendingLifecycleLedgerDir,
|
|
14
|
+
type LifecyclePendingIo,
|
|
15
|
+
} from "../storage/memory-lifecycle-ledger-access.js";
|
|
16
|
+
import { probeEncryptedRegularFileHeader } from "../secure-store/secure-fs.js";
|
|
17
|
+
import { listContainedSpillFiles } from "../utils/path-containment.js";
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* Drain a filesystem-fallback target's pending lifecycle-append spill when no
|
|
21
|
+
* secure StorageManager is available (catalog-disabled namespace; issue
|
|
22
|
+
* #2033). Uses the safe path-scoped PLAINTEXT context this fallback already
|
|
23
|
+
* operates in: a keyless drain can only fold plaintext spills into a plaintext
|
|
24
|
+
* ledger, so it refuses when the ledger or ANY spill is encrypted at rest,
|
|
25
|
+
* leaving those pending for a keyed (catalog-path) drain — exactly mirroring
|
|
26
|
+
* the fallback compaction's encrypted-ledger deferral. Non-fatal; a fast
|
|
27
|
+
* no-op when nothing is pending. The shared spill lister enforces the symlink/
|
|
28
|
+
* containment guard on every spill file it reads or deletes.
|
|
29
|
+
*/
|
|
30
|
+
export async function drainPendingLifecycleAppendsForPath(memoryDir: string): Promise<void> {
|
|
31
|
+
const ledgerPath = path.join(memoryDir, "state", "memory-lifecycle-ledger.jsonl");
|
|
32
|
+
const spillDir = pendingLifecycleLedgerDir(ledgerPath);
|
|
33
|
+
// Enumerate spills through the SAME guarded lister the actual drain uses
|
|
34
|
+
// (listContainedSpillFiles): it rejects a symlinked/non-directory spill dir
|
|
35
|
+
// and skips any symlink/FIFO/device/escaping entry, returning only regular
|
|
36
|
+
// files contained in the dir. Never raw-readdir + open() an untrusted name:
|
|
37
|
+
// opening a FIFO would block until a writer appears and a symlink would
|
|
38
|
+
// redirect the probe outside the dir (#2033). Enumerate BOTH live `*.jsonl`
|
|
39
|
+
// spills and crash-orphaned `*.jsonl.claimed` files: a drain that died
|
|
40
|
+
// between claiming a spill (rename to `.claimed`) and committing it leaves
|
|
41
|
+
// the ONLY copy of those rows as a claimed orphan. Gating solely on live
|
|
42
|
+
// spills would early-return here whenever the pending dir holds nothing but
|
|
43
|
+
// orphans, stranding those rows forever; proceeding lets
|
|
44
|
+
// drainPendingLifecycleLedgerIfAny -> recoverOrphanedClaims restore and
|
|
45
|
+
// re-commit them under the ledger lock (#2033).
|
|
46
|
+
let spillFiles: string[];
|
|
47
|
+
let claimedOrphans: string[];
|
|
48
|
+
try {
|
|
49
|
+
spillFiles = await listContainedSpillFiles(spillDir);
|
|
50
|
+
claimedOrphans = await listContainedSpillFiles(spillDir, ".jsonl.claimed");
|
|
51
|
+
} catch (err) {
|
|
52
|
+
log.debug(`fallback lifecycle pending scan failed (non-fatal) for ${memoryDir}: ${err}`);
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
if (spillFiles.length === 0 && claimedOrphans.length === 0) return;
|
|
56
|
+
// The pending encryption state is authoritative only UNDER the ledger lock:
|
|
57
|
+
// drainPendingLifecycleLedgerIfAny waits for the lock and re-enumerates the
|
|
58
|
+
// pending dir, so a secure-store writer that spills an encrypted file — or a
|
|
59
|
+
// keyed compaction that rewrites the ledger encrypted — while this fallback
|
|
60
|
+
// waits would defeat any pre-lock probe (#2033). Probe each file at the
|
|
61
|
+
// moment of use inside the held lock instead: readSecure refuses an
|
|
62
|
+
// encrypted spill (the fold reads each spill lazily and propagates the throw
|
|
63
|
+
// BEFORE claiming that spill, leaving it intact) and the append refuses a
|
|
64
|
+
// ledger that became encrypted (the fold rolls the claims back). Either way
|
|
65
|
+
// the plaintext IO
|
|
66
|
+
// never reads or writes ciphertext; the keyed catalog-path drain handles the
|
|
67
|
+
// deferred rows.
|
|
68
|
+
const io: LifecyclePendingIo = {
|
|
69
|
+
writeSecure: async (filePath, payload) => {
|
|
70
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
71
|
+
await writeFile(filePath, payload, "utf-8");
|
|
72
|
+
},
|
|
73
|
+
readSecure: async (filePath) => {
|
|
74
|
+
if (await probeEncryptedRegularFileHeader(filePath)) {
|
|
75
|
+
throw new Error(`fallback lifecycle drain deferred: encrypted spill at ${filePath}`);
|
|
76
|
+
}
|
|
77
|
+
return readFile(filePath, "utf-8");
|
|
78
|
+
},
|
|
79
|
+
};
|
|
80
|
+
try {
|
|
81
|
+
await drainPendingLifecycleLedgerIfAny(
|
|
82
|
+
ledgerPath,
|
|
83
|
+
io,
|
|
84
|
+
async (payload) => {
|
|
85
|
+
if (await probeEncryptedRegularFileHeader(ledgerPath)) {
|
|
86
|
+
throw new Error(`fallback lifecycle drain deferred: ledger became encrypted at ${ledgerPath}`);
|
|
87
|
+
}
|
|
88
|
+
await appendFile(ledgerPath, payload, "utf-8");
|
|
89
|
+
},
|
|
90
|
+
async () => {
|
|
91
|
+
await mkdir(path.dirname(ledgerPath), { recursive: true });
|
|
92
|
+
},
|
|
93
|
+
);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
log.debug(`fallback lifecycle pending drain failed (non-fatal) for ${memoryDir}: ${err}`);
|
|
96
|
+
}
|
|
97
|
+
}
|