@remnic/core 9.45.4 → 9.45.5
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 +5 -5
- package/dist/access-admin-ops-surface.js +20 -19
- package/dist/access-authorization-probe.d.ts +5 -5
- package/dist/access-authorization-probe.js +21 -20
- package/dist/access-boundary.d.ts +5 -5
- package/dist/access-boundary.js +20 -19
- package/dist/access-cli.js +60 -58
- package/dist/access-cli.js.map +1 -1
- package/dist/access-extraction-force-flush.d.ts +5 -5
- package/dist/access-extraction-force-flush.js +20 -19
- package/dist/access-http-lcm-compaction.d.ts +5 -5
- package/dist/access-http-lifecycle-flush.d.ts +5 -5
- package/dist/access-http-offline-stream.d.ts +5 -5
- package/dist/access-http-offline-stream.js +1 -1
- package/dist/access-http-query.js +20 -19
- package/dist/access-http.d.ts +5 -6
- package/dist/access-http.js +32 -31
- package/dist/access-identity-continuity-surface.d.ts +4 -4
- package/dist/access-identity-continuity-surface.js +20 -19
- package/dist/access-lcm-surface.d.ts +5 -5
- package/dist/access-lcm-surface.js +20 -19
- package/dist/access-mcp.d.ts +5 -5
- package/dist/access-mcp.js +26 -25
- package/dist/access-namespace-preflight.js +20 -19
- package/dist/access-observe-write-surface.d.ts +5 -5
- package/dist/access-observe-write-surface.js +20 -19
- package/dist/access-offline-manifest.d.ts +4 -4
- package/dist/access-operations-batch.js +21 -20
- package/dist/access-operations.d.ts +8 -8
- package/dist/access-operations.js +25 -24
- package/dist/access-recall-concurrency.d.ts +5 -5
- package/dist/access-recall-concurrency.js +20 -19
- package/dist/access-recall-response.d.ts +5 -5
- package/dist/access-recall-response.js +20 -19
- package/dist/access-recall-surface.d.ts +5 -5
- package/dist/access-recall-surface.js +20 -19
- package/dist/access-schema.d.ts +84 -84
- package/dist/{access-service-CsU-ljFD.d.ts → access-service-CNN89xyn.d.ts} +3 -3
- package/dist/access-service-helpers.d.ts +5 -5
- package/dist/access-service.d.ts +5 -5
- package/dist/access-service.js +20 -19
- package/dist/access-surface-catalog.d.ts +5 -5
- package/dist/access-wearables-meetings-surface.d.ts +2 -2
- package/dist/adapters/index.js +4 -4
- package/dist/adapters/registry.js +2 -2
- package/dist/bootstrap.d.ts +4 -4
- package/dist/briefing.d.ts +1 -1
- package/dist/briefing.js +3 -2
- package/dist/buffer.d.ts +1 -1
- package/dist/buffer.js +4 -4
- package/dist/causal-consolidation.js +4 -3
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-7SHJHPTY.js → chunk-2FSTB6BJ.js} +2 -2
- package/dist/{chunk-ULVR5KG7.js → chunk-2X2T2UVE.js} +2 -2
- package/dist/{chunk-QVSBTCVP.js → chunk-3COYXTGM.js} +2 -2
- package/dist/{chunk-XTAUXTDO.js → chunk-4FBVAGV3.js} +2 -2
- package/dist/{chunk-R5RFK3CB.js → chunk-5QJQHBLE.js} +2 -2
- package/dist/{chunk-YMAQDHQM.js → chunk-6ISC4AVB.js} +2 -2
- package/dist/{chunk-7CITSYSH.js → chunk-7T4TOGMS.js} +2 -2
- package/dist/{chunk-ZMAYKGPN.js → chunk-7YQ6ESEA.js} +12 -41
- package/dist/chunk-7YQ6ESEA.js.map +1 -0
- package/dist/{chunk-TYISDI6B.js → chunk-A4IJCD2Z.js} +2 -2
- package/dist/{chunk-JH6BPLOP.js → chunk-AC5OWJLV.js} +4 -4
- package/dist/{chunk-CLB32OHM.js → chunk-AMAUBUKY.js} +2 -2
- package/dist/{chunk-WGP57SR3.js → chunk-CK5KOVHW.js} +3 -2
- package/dist/{chunk-WGP57SR3.js.map → chunk-CK5KOVHW.js.map} +1 -1
- package/dist/{chunk-XSFHWBQO.js → chunk-CX4ZUMC6.js} +7 -61
- package/dist/{chunk-XSFHWBQO.js.map → chunk-CX4ZUMC6.js.map} +1 -1
- package/dist/{chunk-UQWIKLQK.js → chunk-DAJPRXBR.js} +6 -6
- package/dist/{chunk-U2VLVBBH.js → chunk-E5XQIWAL.js} +2 -2
- package/dist/{chunk-NTOIP2E6.js → chunk-ERZ2R42X.js} +2 -2
- package/dist/{chunk-5CEECY6P.js → chunk-FIK3CQNA.js} +3 -3
- package/dist/{chunk-EJHEWCGQ.js → chunk-FR27HBBA.js} +2 -2
- package/dist/{chunk-FZP32336.js → chunk-FUCYDRE5.js} +43 -21
- package/dist/chunk-FUCYDRE5.js.map +1 -0
- package/dist/{chunk-P7NGM24P.js → chunk-GFCVUY6G.js} +2 -2
- package/dist/{chunk-DYVMXPCF.js → chunk-GODSPTOT.js} +41 -41
- package/dist/{chunk-AJQ57VV3.js → chunk-GRUYA45P.js} +4 -4
- package/dist/chunk-GRUYA45P.js.map +1 -0
- package/dist/{chunk-2MRHJNWL.js → chunk-GUAL4PQH.js} +2 -2
- package/dist/{chunk-EITZHSX6.js → chunk-HC3PBX23.js} +2 -2
- package/dist/{chunk-NUEQKLNB.js → chunk-JZH4LWHB.js} +2 -2
- package/dist/{chunk-7RZJWZ46.js → chunk-LEPOP46W.js} +5 -5
- package/dist/{chunk-TQ4GD737.js → chunk-LPYDOLSM.js} +2 -2
- package/dist/{chunk-TN76AKO3.js → chunk-MO4HSXHZ.js} +2 -2
- package/dist/{chunk-WQIHRA5F.js → chunk-N3LL5NEU.js} +2 -2
- package/dist/{chunk-D3I2MCN7.js → chunk-NEF7LR5J.js} +3 -3
- package/dist/{chunk-C26TE27X.js → chunk-QR6G5KF4.js} +3 -3
- package/dist/{chunk-ZI32MKDW.js → chunk-QUENPGWZ.js} +18 -21
- package/dist/chunk-QUENPGWZ.js.map +1 -0
- package/dist/{chunk-5SNZSWWR.js → chunk-QVJPH7SH.js} +21 -21
- package/dist/{chunk-MDISBSYA.js → chunk-R3KHKU7M.js} +2 -2
- package/dist/{chunk-2QSZNTDO.js → chunk-RKNJBZ55.js} +4 -4
- package/dist/{chunk-KXEFRMCF.js → chunk-RNHVVMFN.js} +2 -2
- package/dist/{chunk-QCECHYZL.js → chunk-RVO6TCTU.js} +6 -6
- package/dist/chunk-S2HLHAZ4.js +16 -0
- package/dist/chunk-S2HLHAZ4.js.map +1 -0
- package/dist/{chunk-ZFGZ6PZ2.js → chunk-UW66OZTD.js} +2 -2
- package/dist/{chunk-BGHFOD5A.js → chunk-V2TNYF6Q.js} +3 -3
- package/dist/chunk-VL35ZFSZ.js +102 -0
- package/dist/chunk-VL35ZFSZ.js.map +1 -0
- package/dist/{chunk-Y7HRYCNW.js → chunk-W2V7UESE.js} +2 -2
- package/dist/{chunk-DSUAAZZX.js → chunk-WZ3TOIDW.js} +2 -2
- package/dist/{chunk-7YERSTN7.js → chunk-XAGYS7X6.js} +7 -7
- package/dist/{chunk-VOUOLGIP.js → chunk-YRFAYOFQ.js} +11 -13
- package/dist/chunk-YRFAYOFQ.js.map +1 -0
- package/dist/{chunk-6NNNURLK.js → chunk-Z54EM5YZ.js} +4 -4
- package/dist/{cli-BBHDtG36.d.ts → cli-BHBswmUa.d.ts} +3 -3
- package/dist/cli.d.ts +6 -6
- package/dist/cli.js +43 -42
- package/dist/compounding/engine.d.ts +1 -1
- package/dist/compounding/engine.js +3 -2
- package/dist/connectors/codex-materialize-runner.js +3 -2
- package/dist/connectors/index.js +3 -2
- package/dist/consolidation-provenance-check.d.ts +1 -1
- package/dist/consolidation-undo.d.ts +1 -1
- package/dist/contradiction/index.d.ts +1 -1
- package/dist/convergence-refresh.d.ts +1 -1
- package/dist/convergence-refresh.js +5 -4
- package/dist/conversation-index/backend.js +2 -2
- package/dist/corpus-watermark.js +12 -11
- package/dist/entity-retrieval.d.ts +1 -1
- package/dist/entity-retrieval.js +3 -2
- package/dist/explicit-capture.d.ts +4 -4
- package/dist/external-wiki-access.d.ts +5 -5
- package/dist/external-wiki-access.js +23 -22
- package/dist/external-wiki-cli.js +4 -90
- package/dist/external-wiki-cli.js.map +1 -1
- package/dist/external-wiki-mcp-tools.d.ts +5 -5
- package/dist/external-wiki-search.js +2 -2
- package/dist/external-wiki.d.ts +1 -5
- package/dist/external-wiki.js +1 -3
- package/dist/extraction.js +8 -7
- package/dist/{first-start-migration-F2QJD66E.js → first-start-migration-ZSHEFEI3.js} +10 -12
- package/dist/{first-start-migration-F2QJD66E.js.map → first-start-migration-ZSHEFEI3.js.map} +1 -1
- package/dist/index.d.ts +688 -687
- package/dist/index.js +81 -78
- package/dist/lcm/engine.js +2 -2
- package/dist/lcm/index.js +2 -2
- package/dist/maintenance/memory-governance.js +3 -2
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +3 -2
- package/dist/maintenance/rebuild-memory-projection.d.ts +1 -1
- package/dist/maintenance/rebuild-memory-projection.js +4 -3
- package/dist/{maintenance-D2mveyCd.d.ts → maintenance-CoRikzIt.d.ts} +1 -1
- package/dist/mcp-memory-inspector-app.d.ts +5 -5
- package/dist/memory-snapshot.d.ts +10 -0
- package/dist/memory-snapshot.js +8 -0
- package/dist/memory-snapshot.js.map +1 -0
- package/dist/memory-worth-outcomes.d.ts +1 -1
- package/dist/namespaces/migrate.d.ts +1 -1
- package/dist/namespaces/migrate.js +11 -10
- package/dist/namespaces/search.js +7 -7
- package/dist/namespaces/storage.d.ts +1 -1
- package/dist/namespaces/storage.js +3 -2
- package/dist/operator-doctor-corpus.js +13 -12
- package/dist/operator-toolkit.d.ts +1 -1
- package/dist/operator-toolkit.js +17 -16
- package/dist/orchestration/compression-guideline-coordinator.d.ts +1 -1
- package/dist/orchestration/maintenance.d.ts +2 -2
- package/dist/orchestration/maintenance.js +8 -7
- package/dist/{orchestrator-DJYlwiUv.d.ts → orchestrator-BJeq7Pw1.d.ts} +3 -3
- package/dist/orchestrator.d.ts +4 -4
- package/dist/orchestrator.js +61 -59
- package/dist/qmd.js +4 -4
- package/dist/schemas.d.ts +76 -76
- package/dist/search/factory.js +6 -6
- package/dist/search/index.js +8 -8
- package/dist/semantic-consolidation.js +4 -3
- package/dist/semantic-rule-promotion.js +3 -2
- package/dist/semantic-rule-verifier.js +3 -2
- package/dist/{service-BeDxSqE-.d.ts → service-DWC4tq7p.d.ts} +1 -1
- package/dist/shared-context/manager.d.ts +8 -8
- package/dist/source-agent-qualifier.js +7 -6
- package/dist/{storage-DfjxusTE.d.ts → storage-DPGjB-8e.d.ts} +4 -1
- package/dist/storage.d.ts +1 -1
- package/dist/storage.js +2 -1
- package/dist/temporal-supersession.d.ts +1 -1
- package/dist/tier-migration.d.ts +1 -1
- package/dist/tier-migration.js +1 -1
- package/dist/transfer/types.d.ts +66 -66
- package/dist/verified-recall.js +3 -2
- package/package.json +2 -2
- package/src/access-http-offline-stream.ts +1 -0
- package/src/access-http.ts +0 -57
- package/src/access-operations-batch.ts +1 -1
- package/src/access-service-observe-lcm-parity.test.ts +45 -20
- package/src/access-service.ts +3 -4
- package/src/external-wiki-cli.ts +28 -20
- package/src/external-wiki-search.test.ts +68 -2
- package/src/external-wiki.ts +12 -38
- package/src/index.ts +1 -5
- package/src/maintenance/first-start-migration.ts +11 -11
- package/src/memory-snapshot.ts +15 -0
- package/src/storage-contract/cache-coherence.test.ts +99 -0
- package/src/storage-fact-hash-index-defer.test.ts +14 -7
- package/src/storage.ts +47 -48
- package/src/testing/subjects/first-start-tier-migration.test.ts +75 -0
- package/src/tier-migration.ts +10 -12
- package/dist/chunk-AJQ57VV3.js.map +0 -1
- package/dist/chunk-FZP32336.js.map +0 -1
- package/dist/chunk-VOUOLGIP.js.map +0 -1
- package/dist/chunk-ZI32MKDW.js.map +0 -1
- package/dist/chunk-ZMAYKGPN.js.map +0 -1
- /package/dist/{chunk-7SHJHPTY.js.map → chunk-2FSTB6BJ.js.map} +0 -0
- /package/dist/{chunk-ULVR5KG7.js.map → chunk-2X2T2UVE.js.map} +0 -0
- /package/dist/{chunk-QVSBTCVP.js.map → chunk-3COYXTGM.js.map} +0 -0
- /package/dist/{chunk-XTAUXTDO.js.map → chunk-4FBVAGV3.js.map} +0 -0
- /package/dist/{chunk-R5RFK3CB.js.map → chunk-5QJQHBLE.js.map} +0 -0
- /package/dist/{chunk-YMAQDHQM.js.map → chunk-6ISC4AVB.js.map} +0 -0
- /package/dist/{chunk-7CITSYSH.js.map → chunk-7T4TOGMS.js.map} +0 -0
- /package/dist/{chunk-TYISDI6B.js.map → chunk-A4IJCD2Z.js.map} +0 -0
- /package/dist/{chunk-JH6BPLOP.js.map → chunk-AC5OWJLV.js.map} +0 -0
- /package/dist/{chunk-CLB32OHM.js.map → chunk-AMAUBUKY.js.map} +0 -0
- /package/dist/{chunk-UQWIKLQK.js.map → chunk-DAJPRXBR.js.map} +0 -0
- /package/dist/{chunk-U2VLVBBH.js.map → chunk-E5XQIWAL.js.map} +0 -0
- /package/dist/{chunk-NTOIP2E6.js.map → chunk-ERZ2R42X.js.map} +0 -0
- /package/dist/{chunk-5CEECY6P.js.map → chunk-FIK3CQNA.js.map} +0 -0
- /package/dist/{chunk-EJHEWCGQ.js.map → chunk-FR27HBBA.js.map} +0 -0
- /package/dist/{chunk-P7NGM24P.js.map → chunk-GFCVUY6G.js.map} +0 -0
- /package/dist/{chunk-DYVMXPCF.js.map → chunk-GODSPTOT.js.map} +0 -0
- /package/dist/{chunk-2MRHJNWL.js.map → chunk-GUAL4PQH.js.map} +0 -0
- /package/dist/{chunk-EITZHSX6.js.map → chunk-HC3PBX23.js.map} +0 -0
- /package/dist/{chunk-NUEQKLNB.js.map → chunk-JZH4LWHB.js.map} +0 -0
- /package/dist/{chunk-7RZJWZ46.js.map → chunk-LEPOP46W.js.map} +0 -0
- /package/dist/{chunk-TQ4GD737.js.map → chunk-LPYDOLSM.js.map} +0 -0
- /package/dist/{chunk-TN76AKO3.js.map → chunk-MO4HSXHZ.js.map} +0 -0
- /package/dist/{chunk-WQIHRA5F.js.map → chunk-N3LL5NEU.js.map} +0 -0
- /package/dist/{chunk-D3I2MCN7.js.map → chunk-NEF7LR5J.js.map} +0 -0
- /package/dist/{chunk-C26TE27X.js.map → chunk-QR6G5KF4.js.map} +0 -0
- /package/dist/{chunk-5SNZSWWR.js.map → chunk-QVJPH7SH.js.map} +0 -0
- /package/dist/{chunk-MDISBSYA.js.map → chunk-R3KHKU7M.js.map} +0 -0
- /package/dist/{chunk-2QSZNTDO.js.map → chunk-RKNJBZ55.js.map} +0 -0
- /package/dist/{chunk-KXEFRMCF.js.map → chunk-RNHVVMFN.js.map} +0 -0
- /package/dist/{chunk-QCECHYZL.js.map → chunk-RVO6TCTU.js.map} +0 -0
- /package/dist/{chunk-ZFGZ6PZ2.js.map → chunk-UW66OZTD.js.map} +0 -0
- /package/dist/{chunk-BGHFOD5A.js.map → chunk-V2TNYF6Q.js.map} +0 -0
- /package/dist/{chunk-Y7HRYCNW.js.map → chunk-W2V7UESE.js.map} +0 -0
- /package/dist/{chunk-DSUAAZZX.js.map → chunk-WZ3TOIDW.js.map} +0 -0
- /package/dist/{chunk-7YERSTN7.js.map → chunk-XAGYS7X6.js.map} +0 -0
- /package/dist/{chunk-6NNNURLK.js.map → chunk-Z54EM5YZ.js.map} +0 -0
|
@@ -31,7 +31,7 @@ async function withMemoryDir(run: (dir: string) => Promise<void>): Promise<void>
|
|
|
31
31
|
try {
|
|
32
32
|
await run(dir);
|
|
33
33
|
} finally {
|
|
34
|
-
await rm(dir, { recursive: true, force: true });
|
|
34
|
+
await rm(dir, { recursive: true, force: true, maxRetries: 5, retryDelay: 50 });
|
|
35
35
|
}
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -2532,7 +2532,7 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
|
|
|
2532
2532
|
semanticThreshold: 0.9,
|
|
2533
2533
|
namespace: "default",
|
|
2534
2534
|
});
|
|
2535
|
-
const content =
|
|
2535
|
+
const content = "Oversized frontmatter sync";
|
|
2536
2536
|
const tombstoneId = await storage.appendTombstone({
|
|
2537
2537
|
reason: "correction",
|
|
2538
2538
|
createdBy: "user_correction",
|
|
@@ -2548,7 +2548,7 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
|
|
|
2548
2548
|
const memory = (await storage.readAllMemories()).find((candidate) => candidate.frontmatter.id === result.id);
|
|
2549
2549
|
assert.ok(memory);
|
|
2550
2550
|
|
|
2551
|
-
const largeTags = Array.from({ length:
|
|
2551
|
+
const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
|
|
2552
2552
|
const updatedFile = [
|
|
2553
2553
|
"---",
|
|
2554
2554
|
`id: ${memory.frontmatter.id}`,
|
|
@@ -2567,6 +2567,10 @@ test("chunked offline sync scans oversized frontmatter before locking its identi
|
|
|
2567
2567
|
content,
|
|
2568
2568
|
"",
|
|
2569
2569
|
].join("\n");
|
|
2570
|
+
assert.ok(
|
|
2571
|
+
updatedFile.indexOf("\n---\n") > 1_048_576,
|
|
2572
|
+
"the streamed body delimiter must appear after the chunk buffer limit",
|
|
2573
|
+
);
|
|
2570
2574
|
const chunks = (async function* (): AsyncIterable<Buffer> {
|
|
2571
2575
|
for (let offset = 0; offset < updatedFile.length; offset += 32 * 1024) {
|
|
2572
2576
|
yield Buffer.from(updatedFile.slice(offset, offset + 32 * 1024), "utf8");
|
|
@@ -2651,7 +2655,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
|
|
|
2651
2655
|
semanticThreshold: 0.9,
|
|
2652
2656
|
namespace: "default",
|
|
2653
2657
|
});
|
|
2654
|
-
const content =
|
|
2658
|
+
const content = "Oversized encrypted staging content";
|
|
2655
2659
|
const tombstoneId = await storage.appendTombstone({
|
|
2656
2660
|
reason: "correction",
|
|
2657
2661
|
createdBy: "user_correction",
|
|
@@ -2666,6 +2670,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
|
|
|
2666
2670
|
assert.equal(result.tombstoneBlocked, true);
|
|
2667
2671
|
const memory = (await storage.readAllMemories()).find((candidate) => candidate.frontmatter.id === result.id);
|
|
2668
2672
|
assert.ok(memory);
|
|
2673
|
+
const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
|
|
2669
2674
|
|
|
2670
2675
|
const incomingFile = [
|
|
2671
2676
|
"---",
|
|
@@ -2676,7 +2681,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
|
|
|
2676
2681
|
`source: ${memory.frontmatter.source}`,
|
|
2677
2682
|
`confidence: ${memory.frontmatter.confidence}`,
|
|
2678
2683
|
`confidenceTier: ${memory.frontmatter.confidenceTier}`,
|
|
2679
|
-
|
|
2684
|
+
`tags: [${largeTags}]`,
|
|
2680
2685
|
"sourceConnector: provider-a",
|
|
2681
2686
|
"status: pending_review",
|
|
2682
2687
|
`blockedBy: ${memory.frontmatter.blockedBy}`,
|
|
@@ -2685,6 +2690,7 @@ test("chunked offline sync encrypts oversized staging files when secure storage
|
|
|
2685
2690
|
content,
|
|
2686
2691
|
"",
|
|
2687
2692
|
].join("\n");
|
|
2693
|
+
assert.ok(incomingFile.length > 1_048_576, "the encrypted staging fixture must exceed the chunk buffer limit");
|
|
2688
2694
|
const chunks = (async function* (): AsyncIterable<Buffer> {
|
|
2689
2695
|
for (let offset = 0; offset < incomingFile.length; offset += 32 * 1024) {
|
|
2690
2696
|
yield Buffer.from(incomingFile.slice(offset, offset + 32 * 1024), "utf8");
|
|
@@ -2960,7 +2966,8 @@ test("large blocked offline sync streams through bounded staging and deduplicate
|
|
|
2960
2966
|
semanticThreshold: 0.9,
|
|
2961
2967
|
namespace: "default",
|
|
2962
2968
|
});
|
|
2963
|
-
const largeContent = "large stream duplicate
|
|
2969
|
+
const largeContent = "large stream duplicate";
|
|
2970
|
+
const largeTags = Array.from({ length: 100_000 }, (_, index) => `"tag-${index}"`).join(", ");
|
|
2964
2971
|
const tombstoneId = await storage.appendTombstone({
|
|
2965
2972
|
reason: "correction",
|
|
2966
2973
|
createdBy: "user_correction",
|
|
@@ -2983,7 +2990,7 @@ test("large blocked offline sync streams through bounded staging and deduplicate
|
|
|
2983
2990
|
"source: offline-sync",
|
|
2984
2991
|
"confidence: 0.8",
|
|
2985
2992
|
"confidenceTier: implied",
|
|
2986
|
-
|
|
2993
|
+
`tags: [${largeTags}]`,
|
|
2987
2994
|
"sourceConnector: provider-a",
|
|
2988
2995
|
"status: pending_review",
|
|
2989
2996
|
`blockedBy: ${tombstoneId}`,
|
package/src/storage.ts
CHANGED
|
@@ -18,6 +18,7 @@ import { createHash, randomUUID } from "node:crypto";
|
|
|
18
18
|
import { normalizeContent, computeContentHash } from "./content-hash.js";
|
|
19
19
|
import path from "node:path";
|
|
20
20
|
import { log } from "./logger.js";
|
|
21
|
+
import { createMemorySnapshot } from "./memory-snapshot.js";
|
|
21
22
|
import { assertMemoryFrontmatterId, warnProjectionFallback } from "./storage-guards.js";
|
|
22
23
|
import { MemoryReadStore } from "./storage/memory-read-store.js";
|
|
23
24
|
import { renderProfileWithLastUpdated } from "./storage/profile-header.js";
|
|
@@ -1779,6 +1780,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
1779
1780
|
private knowledgeIndexCache: { result: string; builtAt: number } | null = null;
|
|
1780
1781
|
private artifactIndexCache: { memories: MemoryFile[]; loadedAtMs: number; writeVersion: number } | null = null;
|
|
1781
1782
|
private projectionLedgerLagManager = new ProjectionLedgerLagManager();
|
|
1783
|
+
private static readonly loadedMemorySnapshots = new WeakMap<MemoryFile, string>();
|
|
1782
1784
|
static readonly KNOWLEDGE_INDEX_CACHE_TTL_MS = 600_000; // 10 minutes (entity mutations invalidate)
|
|
1783
1785
|
/** Read by storage/memory-read-store.ts (decomposition). */
|
|
1784
1786
|
static readonly ARTIFACT_INDEX_CACHE_TTL_MS = 60_000; // 1 minute
|
|
@@ -4504,13 +4506,19 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4504
4506
|
return lineCount > threshold;
|
|
4505
4507
|
}
|
|
4506
4508
|
|
|
4509
|
+
private rememberMemorySnapshot<T extends MemoryFile | null>(memory: T): T {
|
|
4510
|
+
if (memory !== null && !StorageManager.loadedMemorySnapshots.has(memory)) {
|
|
4511
|
+
StorageManager.loadedMemorySnapshots.set(memory, createMemorySnapshot(memory));
|
|
4512
|
+
}
|
|
4513
|
+
return memory;
|
|
4514
|
+
}
|
|
4515
|
+
|
|
4516
|
+
private rememberMemorySnapshots(memories: MemoryFile[]): MemoryFile[] {
|
|
4517
|
+
for (const memory of memories) this.rememberMemorySnapshot(memory);
|
|
4518
|
+
return memories;
|
|
4519
|
+
}
|
|
4520
|
+
|
|
4507
4521
|
async readAllMemories(): Promise<MemoryFile[]> {
|
|
4508
|
-
// Version-keyed hot-memories cache (issue #1902): once populated, serve the
|
|
4509
|
-
// full parsed corpus from memory within a version epoch. getCachedMemories
|
|
4510
|
-
// returns null when the sentinel is 0 (fresh/test dirs) or the stored
|
|
4511
|
-
// version differs from the current on-disk sentinel (a peer or local write
|
|
4512
|
-
// bumped it), so a stale entry is never served — the miss falls through to
|
|
4513
|
-
// a fresh disk scan below.
|
|
4514
4522
|
if (this.hotMemoriesCacheEnabled) {
|
|
4515
4523
|
const cached = getCachedMemories(
|
|
4516
4524
|
this.baseDir,
|
|
@@ -4518,13 +4526,8 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4518
4526
|
this.hotCacheKeyId(),
|
|
4519
4527
|
this.hotCacheTtlMs()
|
|
4520
4528
|
);
|
|
4521
|
-
|
|
4522
|
-
// for a cached EMPTY corpus, which is falsy — a truthiness guard would
|
|
4523
|
-
// force a full disk scan on every read of an empty/near-empty store.
|
|
4524
|
-
if (cached !== null) return cached;
|
|
4529
|
+
if (cached !== null) return this.rememberMemorySnapshots(cached);
|
|
4525
4530
|
}
|
|
4526
|
-
// Deduplicate concurrent reads for the same directory so multiple
|
|
4527
|
-
// callers in the same recall share one disk scan.
|
|
4528
4531
|
// Snapshot the secure-store key identity ONCE (issue #1902, Codex Medium):
|
|
4529
4532
|
// hotCacheKeyId() can change mid-scan if setSecureStoreKey(null/other) runs
|
|
4530
4533
|
// during the await. Recomputing it at publish time would store K-decrypted
|
|
@@ -4534,13 +4537,9 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4534
4537
|
// key change can't orphan the slot registered under the old identity.
|
|
4535
4538
|
const keyId = this.hotCacheKeyId();
|
|
4536
4539
|
const inFlight = getInFlightRead(this.baseDir, keyId);
|
|
4537
|
-
if (inFlight) return inFlight;
|
|
4540
|
+
if (inFlight) return this.rememberMemorySnapshots(await inFlight);
|
|
4538
4541
|
|
|
4539
4542
|
const readPromise = (async (): Promise<MemoryFile[]> => {
|
|
4540
|
-
// Capture the version BEFORE the scan and store under it. If a concurrent
|
|
4541
|
-
// bump (peer or local write) lands during the scan, the stored entry's
|
|
4542
|
-
// version is older than the sentinel, so the next getCachedMemories()
|
|
4543
|
-
// rejects it (version mismatch → rescan) — correct, never stale.
|
|
4544
4543
|
const version = this.getMemoryCorpusVersion();
|
|
4545
4544
|
const memories = await this._readAllMemoriesFromDisk();
|
|
4546
4545
|
// Publish only if neither the corpus version NOR the key identity changed
|
|
@@ -4554,11 +4553,8 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4554
4553
|
})();
|
|
4555
4554
|
setInFlightRead(this.baseDir, keyId, readPromise);
|
|
4556
4555
|
try {
|
|
4557
|
-
return await readPromise;
|
|
4556
|
+
return this.rememberMemorySnapshots(await readPromise);
|
|
4558
4557
|
} finally {
|
|
4559
|
-
// Only delete if we still own the slot for our snapshot key identity —
|
|
4560
|
-
// invalidateAllMemoriesCache() may have already cleared it and a new read
|
|
4561
|
-
// may have claimed it (the expected-promise guard enforces owner-only).
|
|
4562
4558
|
deleteInFlightRead(this.baseDir, keyId, readPromise);
|
|
4563
4559
|
}
|
|
4564
4560
|
}
|
|
@@ -4993,7 +4989,7 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
4993
4989
|
}
|
|
4994
4990
|
|
|
4995
4991
|
async readAllColdMemories(): Promise<MemoryFile[]> {
|
|
4996
|
-
return this.memoryReadStore.readAllColdMemories();
|
|
4992
|
+
return this.rememberMemorySnapshots(await this.memoryReadStore.readAllColdMemories());
|
|
4997
4993
|
}
|
|
4998
4994
|
|
|
4999
4995
|
/**
|
|
@@ -5045,11 +5041,11 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5045
5041
|
};
|
|
5046
5042
|
|
|
5047
5043
|
await readDir(root);
|
|
5048
|
-
return memories;
|
|
5044
|
+
return this.rememberMemorySnapshots(memories);
|
|
5049
5045
|
}
|
|
5050
5046
|
|
|
5051
5047
|
async readMemoryByPath(filePath: string): Promise<MemoryFile | null> {
|
|
5052
|
-
return this.memoryReadStore.readMemoryByPath(filePath);
|
|
5048
|
+
return this.rememberMemorySnapshot(await this.memoryReadStore.readMemoryByPath(filePath));
|
|
5053
5049
|
}
|
|
5054
5050
|
|
|
5055
5051
|
private resolveTierRootDir(tier: "hot" | "cold"): string {
|
|
@@ -5077,12 +5073,6 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5077
5073
|
// corrections/ is flat (no date subdir); preserved across tier moves.
|
|
5078
5074
|
return path.join(root, "corrections", `${memory.frontmatter.id}.md`);
|
|
5079
5075
|
}
|
|
5080
|
-
// Every other category — decisions/, preferences/, reasoning-traces/, ...
|
|
5081
|
-
// plus the facts/ fallback for fact/entity/unknown — resolves through the
|
|
5082
|
-
// shared categoryDirName() chokepoint so tier moves land in the SAME dir the
|
|
5083
|
-
// writer used, instead of funneling non-{correction,procedure,reasoning_trace}
|
|
5084
|
-
// categories into facts/ (issue #564 PR 3 preserved reasoning-traces/; #1546
|
|
5085
|
-
// generalizes it to every category dir).
|
|
5086
5076
|
const dir = categoryDirName(memory.frontmatter.category);
|
|
5087
5077
|
return path.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
5088
5078
|
}
|
|
@@ -5137,14 +5127,24 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5137
5127
|
this.invalidateAllMemoriesCache();
|
|
5138
5128
|
this.notifyCatalogWrite();
|
|
5139
5129
|
}
|
|
5140
|
-
async moveMemoryToPath(memory: MemoryFile, targetPath: string): Promise<
|
|
5141
|
-
await this.withTombstoneBlockedMemoryPathLock(
|
|
5130
|
+
async moveMemoryToPath(memory: MemoryFile, targetPath: string): Promise<boolean> {
|
|
5131
|
+
const changed = await this.withTombstoneBlockedMemoryPathLock(
|
|
5142
5132
|
memory.path,
|
|
5143
5133
|
async (current) => {
|
|
5134
|
+
const destination = await this.readMemoryByPath(targetPath);
|
|
5144
5135
|
if (current?.frontmatter.id !== memory.frontmatter.id) {
|
|
5136
|
+
if (current === null && destination?.frontmatter.id === memory.frontmatter.id) return false;
|
|
5137
|
+
throw new Error(`memory ${memory.frontmatter.id} changed before its tier move`);
|
|
5138
|
+
}
|
|
5139
|
+
const callerSnapshot = StorageManager.loadedMemorySnapshots.get(memory);
|
|
5140
|
+
const currentSnapshot = createMemorySnapshot(current);
|
|
5141
|
+
if (
|
|
5142
|
+
callerSnapshot === undefined
|
|
5143
|
+
? current.frontmatter.updated !== memory.frontmatter.updated
|
|
5144
|
+
: currentSnapshot !== callerSnapshot
|
|
5145
|
+
) {
|
|
5145
5146
|
throw new Error(`memory ${memory.frontmatter.id} changed before its tier move`);
|
|
5146
5147
|
}
|
|
5147
|
-
const destination = await this.readMemoryByPath(targetPath);
|
|
5148
5148
|
const coordinate =
|
|
5149
5149
|
tombstoneBlocked(current.frontmatter) ||
|
|
5150
5150
|
isQueuedReviewMemory(current) ||
|
|
@@ -5152,26 +5152,26 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5152
5152
|
isQueuedReviewMemory(destination);
|
|
5153
5153
|
const index = this.getTombstoneBlockedCaptureIndex();
|
|
5154
5154
|
const marker = coordinate ? await index.prepareWrite() : undefined;
|
|
5155
|
+
const projectedPath = toMemoryPathRel(this.baseDir, targetPath);
|
|
5155
5156
|
let durable = false;
|
|
5156
5157
|
try {
|
|
5157
5158
|
if (destination?.frontmatter.id === current.frontmatter.id) {
|
|
5158
5159
|
await this.deleteManagedStorageFile(current.path);
|
|
5159
5160
|
durable = true;
|
|
5160
5161
|
this.invalidateAllMemoriesCache();
|
|
5161
|
-
updateProjectedMemoryPath(this.baseDir, current.frontmatter.id,
|
|
5162
|
+
updateProjectedMemoryPath(this.baseDir, current.frontmatter.id, projectedPath);
|
|
5162
5163
|
} else {
|
|
5163
5164
|
await this.writeMemoryFileAtomic(targetPath, current);
|
|
5165
|
+
if (memory.frontmatter.entityRef !== current.frontmatter.entityRef) {
|
|
5166
|
+
memory.frontmatter.entityRef = current.frontmatter.entityRef;
|
|
5167
|
+
}
|
|
5164
5168
|
durable = true;
|
|
5165
5169
|
const sourcePath = path.resolve(current.path);
|
|
5166
5170
|
const destPath = path.resolve(targetPath);
|
|
5167
5171
|
if (sourcePath !== destPath) {
|
|
5168
5172
|
await this.deleteManagedStorageFile(current.path);
|
|
5169
5173
|
this.invalidateAllMemoriesCache();
|
|
5170
|
-
updateProjectedMemoryPath(
|
|
5171
|
-
this.baseDir,
|
|
5172
|
-
current.frontmatter.id,
|
|
5173
|
-
toMemoryPathRel(this.baseDir, targetPath)
|
|
5174
|
-
);
|
|
5174
|
+
updateProjectedMemoryPath(this.baseDir, current.frontmatter.id, projectedPath);
|
|
5175
5175
|
}
|
|
5176
5176
|
}
|
|
5177
5177
|
if (marker !== undefined) await this.rebuildTombstoneBlockedCaptureAfterInvalidation(marker);
|
|
@@ -5180,9 +5180,14 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5180
5180
|
if (marker !== undefined && durable) index.markUntrusted();
|
|
5181
5181
|
throw error;
|
|
5182
5182
|
}
|
|
5183
|
+
return true;
|
|
5183
5184
|
},
|
|
5184
5185
|
[targetPath]
|
|
5185
5186
|
);
|
|
5187
|
+
if (this.isColdOrArchiveTierPath(memory.path) || this.isColdOrArchiveTierPath(targetPath)) {
|
|
5188
|
+
this.invalidateColdMemoriesCache();
|
|
5189
|
+
}
|
|
5190
|
+
return changed;
|
|
5186
5191
|
}
|
|
5187
5192
|
|
|
5188
5193
|
async migrateMemoryToTier(
|
|
@@ -5195,16 +5200,10 @@ export class StorageManager extends TombstoneBlockedCaptureIndexHost {
|
|
|
5195
5200
|
if (sourcePath === destPath) {
|
|
5196
5201
|
return { changed: false, targetPath };
|
|
5197
5202
|
}
|
|
5198
|
-
|
|
5199
|
-
|
|
5200
|
-
this.invalidateAllMemoriesCache();
|
|
5201
|
-
// If moving to cold, also invalidate the cold-scan cache so the next
|
|
5202
|
-
// readAllColdMemories() call sees the newly-demoted file (Finding UOGi fix).
|
|
5203
|
-
if (targetTier === "cold") {
|
|
5204
|
-
this.invalidateColdMemoriesCache();
|
|
5205
|
-
}
|
|
5203
|
+
const changed = await this.moveMemoryToPath(memory, targetPath);
|
|
5204
|
+
if (!changed) return { changed: false, targetPath };
|
|
5206
5205
|
this.bumpMemoryStatusVersion();
|
|
5207
|
-
return { changed
|
|
5206
|
+
return { changed, targetPath };
|
|
5208
5207
|
}
|
|
5209
5208
|
|
|
5210
5209
|
private get archiveDir(): string {
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
import assert from "node:assert/strict";
|
|
2
|
+
|
|
3
|
+
import { parseConfig } from "../../config.js";
|
|
4
|
+
import {
|
|
5
|
+
type FirstStartMigrationResult,
|
|
6
|
+
runFirstStartMigration,
|
|
7
|
+
} from "../../maintenance/first-start-migration.js";
|
|
8
|
+
import { StorageManager } from "../../storage.js";
|
|
9
|
+
import type { PluginConfig } from "../../types.js";
|
|
10
|
+
import { type LifecycleSubject, type MatrixRow, runLifecycleMatrix } from "../lifecycle-matrix.js";
|
|
11
|
+
import { cleanupDir, mkTempMemoryDir } from "../orchestrator-lite.js";
|
|
12
|
+
|
|
13
|
+
interface FirstStartTierMigrationState {
|
|
14
|
+
dir: string;
|
|
15
|
+
id: string;
|
|
16
|
+
storage: StorageManager;
|
|
17
|
+
config: PluginConfig;
|
|
18
|
+
result?: FirstStartMigrationResult;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
const subject: LifecycleSubject<FirstStartTierMigrationState> = {
|
|
22
|
+
appliesTo(row: MatrixRow): boolean | string {
|
|
23
|
+
return row.id === "restart-reload-recovery"
|
|
24
|
+
? true
|
|
25
|
+
: "first-start tier migration applies only to startup recovery";
|
|
26
|
+
},
|
|
27
|
+
|
|
28
|
+
async setup(row: MatrixRow): Promise<FirstStartTierMigrationState> {
|
|
29
|
+
const dir = await mkTempMemoryDir(`first-start-tier-${row.id}`);
|
|
30
|
+
try {
|
|
31
|
+
const storage = new StorageManager(dir);
|
|
32
|
+
await storage.ensureDirectories();
|
|
33
|
+
const { id } = await storage.writeMemory("fact", "old low-value fact", {
|
|
34
|
+
confidence: 0.01,
|
|
35
|
+
source: "test",
|
|
36
|
+
});
|
|
37
|
+
const memory = await storage.getMemoryById(id);
|
|
38
|
+
assert.ok(memory);
|
|
39
|
+
await storage.writeMemoryFrontmatter(memory, {
|
|
40
|
+
created: "2020-01-01T00:00:00.000Z",
|
|
41
|
+
updated: "2020-01-01T00:00:00.000Z",
|
|
42
|
+
});
|
|
43
|
+
const config = parseConfig({
|
|
44
|
+
openaiApiKey: "sk-test",
|
|
45
|
+
memoryDir: dir,
|
|
46
|
+
workspaceDir: dir,
|
|
47
|
+
qmdEnabled: false,
|
|
48
|
+
lifecyclePolicyEnabled: true,
|
|
49
|
+
qmdTierMigrationEnabled: true,
|
|
50
|
+
qmdTierDemotionMinAgeDays: 1,
|
|
51
|
+
qmdTierDemotionValueThreshold: 0.99,
|
|
52
|
+
});
|
|
53
|
+
return { dir, id, storage: new StorageManager(dir), config };
|
|
54
|
+
} catch (error) {
|
|
55
|
+
await cleanupDir(dir);
|
|
56
|
+
throw error;
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
|
|
60
|
+
async exercise(state: FirstStartTierMigrationState): Promise<void> {
|
|
61
|
+
state.result = await runFirstStartMigration({ storage: state.storage, config: state.config });
|
|
62
|
+
},
|
|
63
|
+
|
|
64
|
+
async invariants(state: FirstStartTierMigrationState): Promise<void> {
|
|
65
|
+
assert.equal(state.result?.demotedCount, 1);
|
|
66
|
+
assert.ok((await state.storage.readAllColdMemories()).some((memory) => memory.frontmatter.id === state.id));
|
|
67
|
+
assert.ok(!(await state.storage.readAllMemories()).some((memory) => memory.frontmatter.id === state.id));
|
|
68
|
+
},
|
|
69
|
+
|
|
70
|
+
async teardown(state: FirstStartTierMigrationState): Promise<void> {
|
|
71
|
+
await cleanupDir(state.dir);
|
|
72
|
+
},
|
|
73
|
+
};
|
|
74
|
+
|
|
75
|
+
runLifecycleMatrix("first-start-tier-migration", subject);
|
package/src/tier-migration.ts
CHANGED
|
@@ -88,18 +88,16 @@ export class TierMigrationExecutor {
|
|
|
88
88
|
|
|
89
89
|
await this.appendJournal(result);
|
|
90
90
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
await this.qmd.embedCollection(sourceCollection);
|
|
102
|
-
}
|
|
91
|
+
const destinationCollection = this.collectionForTier(toTier);
|
|
92
|
+
const sourceCollection = this.collectionForTier(fromTier);
|
|
93
|
+
await this.updateCollectionFromTierRoot(destinationCollection, toTier);
|
|
94
|
+
if (sourceCollection !== destinationCollection && this.qmd.updatesAllCollections?.() !== true) {
|
|
95
|
+
await this.updateCollectionFromTierRoot(sourceCollection, fromTier);
|
|
96
|
+
}
|
|
97
|
+
if (this.autoEmbed) {
|
|
98
|
+
await this.qmd.embedCollection(destinationCollection);
|
|
99
|
+
if (sourceCollection !== destinationCollection) {
|
|
100
|
+
await this.qmd.embedCollection(sourceCollection);
|
|
103
101
|
}
|
|
104
102
|
}
|
|
105
103
|
|