@remnic/core 9.3.658 → 9.3.660
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-cli.js +17 -17
- package/dist/access-http.js +11 -10
- package/dist/access-mcp.js +10 -9
- package/dist/access-service.js +9 -8
- package/dist/briefing.js +4 -3
- package/dist/causal-consolidation.js +5 -4
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-QFKRE7AU.js → chunk-256W7AXC.js} +4 -4
- package/dist/{chunk-5PFIMBJJ.js → chunk-2EVZ5EN6.js} +12 -12
- package/dist/{chunk-SCPFRKIT.js → chunk-42JKGUFJ.js} +6 -2
- package/dist/{chunk-SCPFRKIT.js.map → chunk-42JKGUFJ.js.map} +1 -1
- package/dist/{chunk-2VCTTEJM.js → chunk-7H7J3ZWN.js} +3 -3
- package/dist/{chunk-QRSKPI62.js → chunk-7PCZGNG2.js} +2 -2
- package/dist/{chunk-ZCMO46YY.js → chunk-A7EF2XRO.js} +2 -2
- package/dist/{chunk-BNUAOLDK.js → chunk-ANJOULTP.js} +2 -2
- package/dist/{chunk-CPPS65WS.js → chunk-AWJ2FHCF.js} +84 -17
- package/dist/chunk-AWJ2FHCF.js.map +1 -0
- package/dist/{chunk-4PLOQDBB.js → chunk-AX5O25EF.js} +7 -5
- package/dist/chunk-AX5O25EF.js.map +1 -0
- package/dist/{chunk-7VWDC7AD.js → chunk-B57QYSWN.js} +17 -17
- package/dist/{chunk-BKRIAXTU.js → chunk-D2EFNQMY.js} +2 -2
- package/dist/{chunk-MBZAESQ3.js → chunk-F6O7IOS3.js} +2 -2
- package/dist/{chunk-KI6QM5AV.js → chunk-GY3V3SUI.js} +2 -2
- package/dist/{chunk-GGL7R2L2.js → chunk-MO77TWPS.js} +4 -4
- package/dist/{chunk-VJYFXDCZ.js → chunk-NMPEJV5M.js} +3 -3
- package/dist/{chunk-3R6OP33G.js → chunk-OYXVENIS.js} +3 -3
- package/dist/{chunk-7KSPKZIQ.js → chunk-PXVFMQLD.js} +3 -3
- package/dist/{chunk-FIS5RT6K.js → chunk-QXHBWFR3.js} +2 -2
- package/dist/{chunk-SSSXWIBP.js → chunk-R2EBP6CM.js} +2 -2
- package/dist/{chunk-6M4LYWA2.js → chunk-RP2U54GG.js} +5 -5
- package/dist/{chunk-G2VVBWFU.js → chunk-RQGR3ETH.js} +2 -2
- package/dist/{chunk-JI3LQFJH.js → chunk-TBLGI2LT.js} +2 -2
- package/dist/{chunk-RVT6U6PV.js → chunk-TWAJICBN.js} +2 -2
- package/dist/{chunk-46RXRASB.js → chunk-TYIXG4VR.js} +3 -3
- package/dist/{chunk-EKQMQQ3U.js → chunk-UNLHHTKN.js} +2 -2
- package/dist/cli.js +20 -19
- package/dist/compounding/engine.js +4 -3
- package/dist/connectors/codex-materialize-runner.js +4 -3
- package/dist/connectors/index.js +4 -3
- package/dist/entity-retrieval.js +4 -3
- package/dist/index.js +25 -25
- package/dist/maintenance/memory-governance.js +4 -3
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +4 -3
- package/dist/maintenance/rebuild-memory-projection.js +5 -4
- package/dist/memory-cache.d.ts +43 -1
- package/dist/memory-cache.js +6 -1
- package/dist/namespaces/migrate.js +8 -7
- package/dist/namespaces/search.js +5 -4
- package/dist/namespaces/storage.js +4 -3
- package/dist/operator-toolkit.js +10 -9
- package/dist/orchestrator.js +15 -15
- package/dist/qmd-recall-cache.d.ts +4 -1
- package/dist/qmd-recall-cache.js +3 -1
- package/dist/qmd.js +3 -2
- package/dist/schemas.d.ts +24 -24
- package/dist/search/factory.js +4 -3
- package/dist/search/index.js +4 -3
- package/dist/semantic-consolidation.js +5 -4
- package/dist/semantic-rule-promotion.js +4 -3
- package/dist/semantic-rule-verifier.js +4 -3
- package/dist/storage.js +3 -2
- package/dist/verified-recall.js +4 -3
- package/package.json +1 -1
- package/src/memory-cache.test.ts +30 -0
- package/src/memory-cache.ts +129 -16
- package/src/qmd-recall-cache.ts +6 -0
- package/src/storage.ts +27 -3
- package/dist/chunk-4PLOQDBB.js.map +0 -1
- package/dist/chunk-CPPS65WS.js.map +0 -1
- /package/dist/{chunk-QFKRE7AU.js.map → chunk-256W7AXC.js.map} +0 -0
- /package/dist/{chunk-5PFIMBJJ.js.map → chunk-2EVZ5EN6.js.map} +0 -0
- /package/dist/{chunk-2VCTTEJM.js.map → chunk-7H7J3ZWN.js.map} +0 -0
- /package/dist/{chunk-QRSKPI62.js.map → chunk-7PCZGNG2.js.map} +0 -0
- /package/dist/{chunk-ZCMO46YY.js.map → chunk-A7EF2XRO.js.map} +0 -0
- /package/dist/{chunk-BNUAOLDK.js.map → chunk-ANJOULTP.js.map} +0 -0
- /package/dist/{chunk-7VWDC7AD.js.map → chunk-B57QYSWN.js.map} +0 -0
- /package/dist/{chunk-BKRIAXTU.js.map → chunk-D2EFNQMY.js.map} +0 -0
- /package/dist/{chunk-MBZAESQ3.js.map → chunk-F6O7IOS3.js.map} +0 -0
- /package/dist/{chunk-KI6QM5AV.js.map → chunk-GY3V3SUI.js.map} +0 -0
- /package/dist/{chunk-GGL7R2L2.js.map → chunk-MO77TWPS.js.map} +0 -0
- /package/dist/{chunk-VJYFXDCZ.js.map → chunk-NMPEJV5M.js.map} +0 -0
- /package/dist/{chunk-3R6OP33G.js.map → chunk-OYXVENIS.js.map} +0 -0
- /package/dist/{chunk-7KSPKZIQ.js.map → chunk-PXVFMQLD.js.map} +0 -0
- /package/dist/{chunk-FIS5RT6K.js.map → chunk-QXHBWFR3.js.map} +0 -0
- /package/dist/{chunk-SSSXWIBP.js.map → chunk-R2EBP6CM.js.map} +0 -0
- /package/dist/{chunk-6M4LYWA2.js.map → chunk-RP2U54GG.js.map} +0 -0
- /package/dist/{chunk-G2VVBWFU.js.map → chunk-RQGR3ETH.js.map} +0 -0
- /package/dist/{chunk-JI3LQFJH.js.map → chunk-TBLGI2LT.js.map} +0 -0
- /package/dist/{chunk-RVT6U6PV.js.map → chunk-TWAJICBN.js.map} +0 -0
- /package/dist/{chunk-46RXRASB.js.map → chunk-TYIXG4VR.js.map} +0 -0
- /package/dist/{chunk-EKQMQQ3U.js.map → chunk-UNLHHTKN.js.map} +0 -0
|
@@ -11,13 +11,13 @@ import {
|
|
|
11
11
|
} from "./chunk-D24OXEPB.js";
|
|
12
12
|
import {
|
|
13
13
|
EngramAccessInputError
|
|
14
|
-
} from "./chunk-
|
|
14
|
+
} from "./chunk-RP2U54GG.js";
|
|
15
15
|
import {
|
|
16
16
|
projectTagProjectId
|
|
17
17
|
} from "./chunk-GYSYLGNE.js";
|
|
18
18
|
import {
|
|
19
19
|
validateBriefingFormat
|
|
20
|
-
} from "./chunk-
|
|
20
|
+
} from "./chunk-GY3V3SUI.js";
|
|
21
21
|
import {
|
|
22
22
|
resolvePrincipal
|
|
23
23
|
} from "./chunk-UZYLX7M6.js";
|
|
@@ -3117,4 +3117,4 @@ ${body}`;
|
|
|
3117
3117
|
export {
|
|
3118
3118
|
EngramMcpServer
|
|
3119
3119
|
};
|
|
3120
|
-
//# sourceMappingURL=chunk-
|
|
3120
|
+
//# sourceMappingURL=chunk-7H7J3ZWN.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
import {
|
|
8
8
|
getCachedQmdSearch,
|
|
9
9
|
setCachedQmdSearch
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AWJ2FHCF.js";
|
|
11
11
|
import {
|
|
12
12
|
mergeEnv
|
|
13
13
|
} from "./chunk-JUC24CTX.js";
|
|
@@ -2136,4 +2136,4 @@ export {
|
|
|
2136
2136
|
getQmdCommandName,
|
|
2137
2137
|
QmdClient
|
|
2138
2138
|
};
|
|
2139
|
-
//# sourceMappingURL=chunk-
|
|
2139
|
+
//# sourceMappingURL=chunk-7PCZGNG2.js.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import {
|
|
2
2
|
StorageManager
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-AX5O25EF.js";
|
|
4
4
|
import {
|
|
5
5
|
decideLifecycleTransition
|
|
6
6
|
} from "./chunk-TBBDFYXW.js";
|
|
@@ -729,4 +729,4 @@ export {
|
|
|
729
729
|
listMemoryGovernanceRuns,
|
|
730
730
|
readMemoryGovernanceRunArtifact
|
|
731
731
|
};
|
|
732
|
-
//# sourceMappingURL=chunk-
|
|
732
|
+
//# sourceMappingURL=chunk-A7EF2XRO.js.map
|
|
@@ -7,7 +7,7 @@ import {
|
|
|
7
7
|
} from "./chunk-3UXOZBHV.js";
|
|
8
8
|
import {
|
|
9
9
|
StorageManager
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-AX5O25EF.js";
|
|
11
11
|
import {
|
|
12
12
|
isSafeRouteNamespace
|
|
13
13
|
} from "./chunk-U3PN77QT.js";
|
|
@@ -118,4 +118,4 @@ export {
|
|
|
118
118
|
runCodexMaterialize,
|
|
119
119
|
runPostConsolidationMaterialize
|
|
120
120
|
};
|
|
121
|
-
//# sourceMappingURL=chunk-
|
|
121
|
+
//# sourceMappingURL=chunk-ANJOULTP.js.map
|
|
@@ -1,3 +1,8 @@
|
|
|
1
|
+
import {
|
|
2
|
+
clearQmdRecallCache,
|
|
3
|
+
qmdRecallCacheSize
|
|
4
|
+
} from "./chunk-42JKGUFJ.js";
|
|
5
|
+
|
|
1
6
|
// src/memory-cache.ts
|
|
2
7
|
var hotCacheByDir = /* @__PURE__ */ new Map();
|
|
3
8
|
var archiveCacheByDir = /* @__PURE__ */ new Map();
|
|
@@ -32,8 +37,14 @@ function setCachedArchivedMemories(baseDir, memories, version) {
|
|
|
32
37
|
archiveCacheByDir.set(baseDir, { memories: map, version, loadedAt: Date.now() });
|
|
33
38
|
}
|
|
34
39
|
var entityCacheByDir = /* @__PURE__ */ new Map();
|
|
35
|
-
function
|
|
36
|
-
return
|
|
40
|
+
function normalizeEntitySchemaKey(schemaKey) {
|
|
41
|
+
return schemaKey ?? "";
|
|
42
|
+
}
|
|
43
|
+
function entityCacheKeyPrefix(baseDir) {
|
|
44
|
+
return `${baseDir}\0`;
|
|
45
|
+
}
|
|
46
|
+
function buildEntityCacheKey(baseDir, schemaKey) {
|
|
47
|
+
return `${entityCacheKeyPrefix(baseDir)}${normalizeEntitySchemaKey(schemaKey)}`;
|
|
37
48
|
}
|
|
38
49
|
function getCachedEntities(baseDir, currentVersion, schemaKey = "") {
|
|
39
50
|
if (currentVersion === 0) return null;
|
|
@@ -49,7 +60,7 @@ function setCachedEntities(baseDir, entities, version, schemaKey = "") {
|
|
|
49
60
|
});
|
|
50
61
|
}
|
|
51
62
|
function invalidateCachedEntities(baseDir) {
|
|
52
|
-
const prefix =
|
|
63
|
+
const prefix = entityCacheKeyPrefix(baseDir);
|
|
53
64
|
for (const key of entityCacheByDir.keys()) {
|
|
54
65
|
if (key.startsWith(prefix)) entityCacheByDir.delete(key);
|
|
55
66
|
}
|
|
@@ -111,21 +122,75 @@ function setCachedQmdSearch(cacheKey, results) {
|
|
|
111
122
|
}
|
|
112
123
|
}
|
|
113
124
|
}
|
|
125
|
+
var ALL_CACHE_LAYERS = [
|
|
126
|
+
{
|
|
127
|
+
name: "hot-memories",
|
|
128
|
+
scope: "dir",
|
|
129
|
+
invalidateForDir: (baseDir) => void hotCacheByDir.delete(baseDir),
|
|
130
|
+
clearAll: () => hotCacheByDir.clear(),
|
|
131
|
+
hasEntriesFor: (baseDir) => hotCacheByDir.has(baseDir)
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: "archive-memories",
|
|
135
|
+
scope: "dir",
|
|
136
|
+
invalidateForDir: (baseDir) => void archiveCacheByDir.delete(baseDir),
|
|
137
|
+
clearAll: () => archiveCacheByDir.clear(),
|
|
138
|
+
hasEntriesFor: (baseDir) => archiveCacheByDir.has(baseDir)
|
|
139
|
+
},
|
|
140
|
+
{
|
|
141
|
+
name: "entities",
|
|
142
|
+
scope: "dir",
|
|
143
|
+
invalidateForDir: (baseDir) => invalidateCachedEntities(baseDir),
|
|
144
|
+
clearAll: () => entityCacheByDir.clear(),
|
|
145
|
+
hasEntriesFor: (baseDir) => {
|
|
146
|
+
const prefix = entityCacheKeyPrefix(baseDir);
|
|
147
|
+
for (const key of entityCacheByDir.keys()) {
|
|
148
|
+
if (key.startsWith(prefix)) return true;
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
|
152
|
+
},
|
|
153
|
+
{
|
|
154
|
+
name: "derived-episode-map",
|
|
155
|
+
scope: "dir",
|
|
156
|
+
invalidateForDir: (baseDir) => void episodeMapByDir.delete(baseDir),
|
|
157
|
+
clearAll: () => episodeMapByDir.clear(),
|
|
158
|
+
hasEntriesFor: (baseDir) => episodeMapByDir.has(baseDir)
|
|
159
|
+
},
|
|
160
|
+
{
|
|
161
|
+
name: "derived-rule-memories",
|
|
162
|
+
scope: "dir",
|
|
163
|
+
invalidateForDir: (baseDir) => void ruleMemoriesByDir.delete(baseDir),
|
|
164
|
+
clearAll: () => ruleMemoriesByDir.clear(),
|
|
165
|
+
hasEntriesFor: (baseDir) => ruleMemoriesByDir.has(baseDir)
|
|
166
|
+
},
|
|
167
|
+
{
|
|
168
|
+
name: "qmd-search",
|
|
169
|
+
scope: "global",
|
|
170
|
+
invalidateForDir: () => qmdSearchCache.clear(),
|
|
171
|
+
clearAll: () => qmdSearchCache.clear(),
|
|
172
|
+
hasEntriesFor: () => qmdSearchCache.size > 0
|
|
173
|
+
},
|
|
174
|
+
{
|
|
175
|
+
name: "qmd-recall",
|
|
176
|
+
scope: "global",
|
|
177
|
+
invalidateForDir: () => clearQmdRecallCache(),
|
|
178
|
+
clearAll: () => clearQmdRecallCache(),
|
|
179
|
+
hasEntriesFor: () => qmdRecallCacheSize() > 0
|
|
180
|
+
}
|
|
181
|
+
];
|
|
182
|
+
function invalidateAllForDir(baseDir) {
|
|
183
|
+
for (const layer of ALL_CACHE_LAYERS) {
|
|
184
|
+
layer.invalidateForDir(baseDir);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
114
187
|
function clearMemoryCache(baseDir) {
|
|
115
188
|
if (baseDir) {
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
qmdSearchCache.clear();
|
|
122
|
-
} else {
|
|
123
|
-
hotCacheByDir.clear();
|
|
124
|
-
archiveCacheByDir.clear();
|
|
125
|
-
entityCacheByDir.clear();
|
|
126
|
-
episodeMapByDir.clear();
|
|
127
|
-
ruleMemoriesByDir.clear();
|
|
128
|
-
qmdSearchCache.clear();
|
|
189
|
+
invalidateAllForDir(baseDir);
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
for (const layer of ALL_CACHE_LAYERS) {
|
|
193
|
+
layer.clearAll();
|
|
129
194
|
}
|
|
130
195
|
}
|
|
131
196
|
function getMemoryCacheStats(baseDir) {
|
|
@@ -155,7 +220,9 @@ export {
|
|
|
155
220
|
setCachedRuleMemories,
|
|
156
221
|
getCachedQmdSearch,
|
|
157
222
|
setCachedQmdSearch,
|
|
223
|
+
ALL_CACHE_LAYERS,
|
|
224
|
+
invalidateAllForDir,
|
|
158
225
|
clearMemoryCache,
|
|
159
226
|
getMemoryCacheStats
|
|
160
227
|
};
|
|
161
|
-
//# sourceMappingURL=chunk-
|
|
228
|
+
//# sourceMappingURL=chunk-AWJ2FHCF.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/memory-cache.ts"],"sourcesContent":["import type { EntityFile, MemoryFile } from \"./types.js\";\nimport { clearQmdRecallCache, qmdRecallCacheSize } from \"./qmd-recall-cache.js\";\n\ninterface CacheEntry {\n memories: Map<string, MemoryFile>; // keyed by file path\n version: number;\n loadedAt: number;\n}\n\n// Module-level singleton — shared across all StorageManager instances and sessions\nconst hotCacheByDir = new Map<string, CacheEntry>();\nconst archiveCacheByDir = new Map<string, CacheEntry>();\n\nexport function getCachedMemories(baseDir: string, currentVersion: number): MemoryFile[] | null {\n // Don't serve from cache when version tracking is unavailable (version=0).\n // This ensures tests and fresh installs without a version file always read disk.\n if (currentVersion === 0) return null;\n const entry = hotCacheByDir.get(baseDir);\n if (!entry || entry.version !== currentVersion) return null;\n return [...entry.memories.values()];\n}\n\nexport function setCachedMemories(baseDir: string, memories: MemoryFile[], version: number): void {\n const map = new Map<string, MemoryFile>();\n for (const m of memories) map.set(m.path, m);\n hotCacheByDir.set(baseDir, { memories: map, version, loadedAt: Date.now() });\n}\n\nexport function updateCacheOnWrite(baseDir: string, memory: MemoryFile): void {\n const entry = hotCacheByDir.get(baseDir);\n if (entry) entry.memories.set(memory.path, memory);\n}\n\nexport function updateCacheOnDelete(baseDir: string, filePath: string): void {\n const entry = hotCacheByDir.get(baseDir);\n if (entry) entry.memories.delete(filePath);\n}\n\n// Archive cache — same pattern, separate store\nexport function getCachedArchivedMemories(baseDir: string, currentVersion: number): MemoryFile[] | null {\n if (currentVersion === 0) return null;\n const entry = archiveCacheByDir.get(baseDir);\n if (!entry || entry.version !== currentVersion) return null;\n return [...entry.memories.values()];\n}\n\nexport function setCachedArchivedMemories(baseDir: string, memories: MemoryFile[], version: number): void {\n const map = new Map<string, MemoryFile>();\n for (const m of memories) map.set(m.path, m);\n archiveCacheByDir.set(baseDir, { memories: map, version, loadedAt: Date.now() });\n}\n\n// Entity cache — same pattern as memory cache, but keyed by schema-aware parse inputs.\nconst entityCacheByDir = new Map<string, { entities: EntityFile[]; version: number; loadedAt: number }>();\n\n/**\n * Single normalization point for the entity-cache schema key (issue #1535).\n * BOTH the set/get key builder and the prefix invalidation derive from here so\n * `undefined` vs `\"\"` (or any future normalization rule) can never diverge\n * between the write path and the invalidate path (rule 38 cousin).\n */\nfunction normalizeEntitySchemaKey(schemaKey: string | undefined): string {\n return schemaKey ?? \"\";\n}\n\n/** Prefix shared by every entity-cache key for a dir, regardless of schemaKey. */\nfunction entityCacheKeyPrefix(baseDir: string): string {\n return `${baseDir}\\u0000`;\n}\n\nfunction buildEntityCacheKey(baseDir: string, schemaKey?: string): string {\n return `${entityCacheKeyPrefix(baseDir)}${normalizeEntitySchemaKey(schemaKey)}`;\n}\n\nexport function getCachedEntities(\n baseDir: string,\n currentVersion: number,\n schemaKey: string = \"\",\n): EntityFile[] | null {\n if (currentVersion === 0) return null;\n const entry = entityCacheByDir.get(buildEntityCacheKey(baseDir, schemaKey));\n if (!entry || entry.version !== currentVersion) return null;\n return entry.entities;\n}\n\nexport function setCachedEntities(\n baseDir: string,\n entities: EntityFile[],\n version: number,\n schemaKey: string = \"\",\n): void {\n entityCacheByDir.set(buildEntityCacheKey(baseDir, schemaKey), {\n entities,\n version,\n loadedAt: Date.now(),\n });\n}\n\nexport function invalidateCachedEntities(baseDir: string): void {\n const prefix = entityCacheKeyPrefix(baseDir);\n for (const key of entityCacheByDir.keys()) {\n if (key.startsWith(prefix)) entityCacheByDir.delete(key);\n }\n}\n\n// Derived caches — pre-filtered views invalidated alongside the main cache.\n// These avoid O(146K) filter+map on every verified recall/rules call.\ninterface DerivedCacheEntry<T> {\n data: T;\n sourceVersion: number; // matches the hot cache version it was derived from\n}\n\nconst episodeMapByDir = new Map<string, DerivedCacheEntry<Map<string, MemoryFile>>>();\nconst ruleMemoriesByDir = new Map<string, DerivedCacheEntry<{ all: MemoryFile[]; byId: Map<string, MemoryFile> }>>();\n\n/** Get a pre-filtered Map of episode memories (keyed by ID). Derived from hot cache. */\nexport function getCachedEpisodeMap(baseDir: string, currentVersion: number): Map<string, MemoryFile> | null {\n if (currentVersion === 0) return null;\n const entry = episodeMapByDir.get(baseDir);\n if (!entry || entry.sourceVersion !== currentVersion) return null;\n return entry.data;\n}\n\n/** Build and cache the episode memory map from the full memory list. */\nexport function setCachedEpisodeMap(baseDir: string, memories: MemoryFile[], version: number): Map<string, MemoryFile> {\n const map = new Map<string, MemoryFile>();\n for (const m of memories) {\n if (m.frontmatter.status === \"archived\" || m.frontmatter.status === \"forgotten\") continue;\n if (m.frontmatter.memoryKind !== \"episode\") continue;\n map.set(m.frontmatter.id, m);\n }\n episodeMapByDir.set(baseDir, { data: map, sourceVersion: version });\n return map;\n}\n\n/** Get pre-filtered rule memories. Derived from hot cache. */\nexport function getCachedRuleMemories(baseDir: string, currentVersion: number): { all: MemoryFile[]; byId: Map<string, MemoryFile> } | null {\n if (currentVersion === 0) return null;\n const entry = ruleMemoriesByDir.get(baseDir);\n if (!entry || entry.sourceVersion !== currentVersion) return null;\n return entry.data;\n}\n\n/** Build and cache the rule memories from the full memory list. */\nexport function setCachedRuleMemories(baseDir: string, memories: MemoryFile[], version: number): { all: MemoryFile[]; byId: Map<string, MemoryFile> } {\n const byId = new Map<string, MemoryFile>();\n const all: MemoryFile[] = [];\n for (const m of memories) {\n byId.set(m.frontmatter.id, m);\n if (\n m.frontmatter.category === \"rule\" &&\n m.frontmatter.status !== \"archived\" &&\n m.frontmatter.status !== \"forgotten\"\n ) {\n all.push(m);\n }\n }\n const result = { all, byId };\n ruleMemoriesByDir.set(baseDir, { data: result, sourceVersion: version });\n return result;\n}\n\n// QMD search result cache — short-lived (60s TTL) to avoid stale results\n// while reducing redundant daemon calls for repeated/similar queries.\ninterface QmdCacheEntry {\n results: unknown[];\n cachedAt: number;\n}\nconst QMD_CACHE_TTL_MS = 60_000;\nconst qmdSearchCache = new Map<string, QmdCacheEntry>();\n\nexport function getCachedQmdSearch(cacheKey: string): unknown[] | null {\n const entry = qmdSearchCache.get(cacheKey);\n if (!entry) return null;\n if (Date.now() - entry.cachedAt > QMD_CACHE_TTL_MS) {\n qmdSearchCache.delete(cacheKey);\n return null;\n }\n return entry.results;\n}\n\nexport function setCachedQmdSearch(cacheKey: string, results: unknown[]): void {\n qmdSearchCache.set(cacheKey, { results, cachedAt: Date.now() });\n // Evict old entries to prevent unbounded growth\n if (qmdSearchCache.size > 200) {\n const now = Date.now();\n for (const [key, entry] of qmdSearchCache) {\n if (now - entry.cachedAt > QMD_CACHE_TTL_MS) qmdSearchCache.delete(key);\n }\n }\n}\n\n/**\n * Cache-layer registry (issue #1535).\n *\n * EVERY process-level cache that can serve memory-derived content is\n * enumerated here, and the single invalidation chokepoint\n * (`invalidateAllForDir`) iterates this list. Adding a new cache layer to\n * this module (or qmd-recall-cache.ts) REQUIRES registering it here —\n * otherwise mutations will never invalidate it (the exact bug this registry\n * exists to prevent) and the enumerate-all-layers fitness test in\n * tests/cache-invalidation-coherence.test.ts fails.\n */\nexport interface MemoryCacheLayer {\n /** Stable identifier used by tests and diagnostics. */\n readonly name: string;\n /** \"dir\" layers evict only entries for the given baseDir. \"global\" layers\n * are fully cleared on any mutation: their keys embed queries, namespaces,\n * and strategies rather than a storage dir, so a per-dir selective clear\n * is not possible without recording the dir in each entry. Full clear is\n * the simple-and-correct choice — these caches are re-warmable\n * (issue #1535, implementation guide option (b)). */\n readonly scope: \"dir\" | \"global\";\n /** Evict entries for baseDir (\"dir\" scope) or everything (\"global\" scope). */\n readonly invalidateForDir: (baseDir: string) => void;\n /** Evict every entry across all dirs. */\n readonly clearAll: () => void;\n /** True when the layer still holds entries for baseDir (\"dir\" scope) or\n * any entries at all (\"global\" scope). */\n readonly hasEntriesFor: (baseDir: string) => boolean;\n}\n\nexport const ALL_CACHE_LAYERS: readonly MemoryCacheLayer[] = [\n {\n name: \"hot-memories\",\n scope: \"dir\",\n invalidateForDir: (baseDir) => void hotCacheByDir.delete(baseDir),\n clearAll: () => hotCacheByDir.clear(),\n hasEntriesFor: (baseDir) => hotCacheByDir.has(baseDir),\n },\n {\n name: \"archive-memories\",\n scope: \"dir\",\n invalidateForDir: (baseDir) => void archiveCacheByDir.delete(baseDir),\n clearAll: () => archiveCacheByDir.clear(),\n hasEntriesFor: (baseDir) => archiveCacheByDir.has(baseDir),\n },\n {\n name: \"entities\",\n scope: \"dir\",\n invalidateForDir: (baseDir) => invalidateCachedEntities(baseDir),\n clearAll: () => entityCacheByDir.clear(),\n hasEntriesFor: (baseDir) => {\n const prefix = entityCacheKeyPrefix(baseDir);\n for (const key of entityCacheByDir.keys()) {\n if (key.startsWith(prefix)) return true;\n }\n return false;\n },\n },\n {\n name: \"derived-episode-map\",\n scope: \"dir\",\n invalidateForDir: (baseDir) => void episodeMapByDir.delete(baseDir),\n clearAll: () => episodeMapByDir.clear(),\n hasEntriesFor: (baseDir) => episodeMapByDir.has(baseDir),\n },\n {\n name: \"derived-rule-memories\",\n scope: \"dir\",\n invalidateForDir: (baseDir) => void ruleMemoriesByDir.delete(baseDir),\n clearAll: () => ruleMemoriesByDir.clear(),\n hasEntriesFor: (baseDir) => ruleMemoriesByDir.has(baseDir),\n },\n {\n name: \"qmd-search\",\n scope: \"global\",\n invalidateForDir: () => qmdSearchCache.clear(),\n clearAll: () => qmdSearchCache.clear(),\n hasEntriesFor: () => qmdSearchCache.size > 0,\n },\n {\n name: \"qmd-recall\",\n scope: \"global\",\n invalidateForDir: () => clearQmdRecallCache(),\n clearAll: () => clearQmdRecallCache(),\n hasEntriesFor: () => qmdRecallCacheSize() > 0,\n },\n];\n\n/**\n * The single invalidation chokepoint (issue #1535, rule 37).\n *\n * Every memory/entity mutation path must route through this function —\n * storage.ts calls it from its internal invalidation funnels\n * (invalidateAllMemoriesCache / invalidateColdMemoriesCache /\n * bumpMemoryStatusVersion / setSecureStoreKey). Nothing may clear an\n * individual layer ad hoc: partial clears are how the stale-recall bug\n * happened (qmdRecallCache was never invalidated on mutations, so recall\n * served pre-edit bundles for the remainder of its fresh/stale TTL window).\n */\nexport function invalidateAllForDir(baseDir: string): void {\n for (const layer of ALL_CACHE_LAYERS) {\n layer.invalidateForDir(baseDir);\n }\n}\n\nexport function clearMemoryCache(baseDir?: string): void {\n if (baseDir) {\n invalidateAllForDir(baseDir);\n return;\n }\n for (const layer of ALL_CACHE_LAYERS) {\n layer.clearAll();\n }\n}\n\nexport function getMemoryCacheStats(baseDir: string): {\n hotSize: number;\n archiveSize: number;\n hotVersion: number | null;\n archiveVersion: number | null;\n} {\n const hot = hotCacheByDir.get(baseDir);\n const archive = archiveCacheByDir.get(baseDir);\n return {\n hotSize: hot?.memories.size ?? 0,\n archiveSize: archive?.memories.size ?? 0,\n hotVersion: hot?.version ?? null,\n archiveVersion: archive?.version ?? null,\n };\n}\n"],"mappings":"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","names":[]}
|
|
@@ -16,9 +16,9 @@ import {
|
|
|
16
16
|
} from "./chunk-AZBV4RRY.js";
|
|
17
17
|
import {
|
|
18
18
|
getCachedEntities,
|
|
19
|
-
|
|
19
|
+
invalidateAllForDir,
|
|
20
20
|
setCachedEntities
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-AWJ2FHCF.js";
|
|
22
22
|
import {
|
|
23
23
|
inferMemoryStatus,
|
|
24
24
|
isArchivedMemoryPath,
|
|
@@ -1804,7 +1804,7 @@ var StorageManager = class _StorageManager {
|
|
|
1804
1804
|
setSecureStoreKey(key, encryptOnWrite = true) {
|
|
1805
1805
|
this._secureStoreKey = key;
|
|
1806
1806
|
this._secureStoreEncryptOnWrite = encryptOnWrite;
|
|
1807
|
-
|
|
1807
|
+
invalidateAllForDir(this.baseDir);
|
|
1808
1808
|
this.invalidateKnowledgeIndexCache();
|
|
1809
1809
|
}
|
|
1810
1810
|
getEntityCacheSecureStoreKey() {
|
|
@@ -1941,6 +1941,7 @@ var StorageManager = class _StorageManager {
|
|
|
1941
1941
|
}
|
|
1942
1942
|
bumpMemoryStatusVersion() {
|
|
1943
1943
|
this.bumpSharedVersion("memory-status", _StorageManager.memoryStatusVersionByDir);
|
|
1944
|
+
invalidateAllForDir(this.baseDir);
|
|
1944
1945
|
}
|
|
1945
1946
|
getMemoryStatusVersion() {
|
|
1946
1947
|
return this.readSharedVersion("memory-status", _StorageManager.memoryStatusVersionByDir);
|
|
@@ -2295,7 +2296,6 @@ var StorageManager = class _StorageManager {
|
|
|
2295
2296
|
}
|
|
2296
2297
|
async invalidateAfterOfflineSyncMutation(filePath) {
|
|
2297
2298
|
this.invalidateAllMemoriesCache();
|
|
2298
|
-
invalidateCachedEntities(this.baseDir);
|
|
2299
2299
|
this.invalidateKnowledgeIndexCache();
|
|
2300
2300
|
this.factHashIndexAuthoritative = false;
|
|
2301
2301
|
await unlink(this.factHashIndexReadyPath).catch((error) => {
|
|
@@ -3103,6 +3103,7 @@ ${sanitized.text}
|
|
|
3103
3103
|
* inside cold/, archiveMemory, etc.). */
|
|
3104
3104
|
invalidateAllMemoriesCache() {
|
|
3105
3105
|
_StorageManager.allMemoriesInFlight.delete(this.baseDir);
|
|
3106
|
+
invalidateAllForDir(this.baseDir);
|
|
3106
3107
|
}
|
|
3107
3108
|
/**
|
|
3108
3109
|
* Invalidate the cold-scan cache for this storage root and bump the
|
|
@@ -3120,6 +3121,7 @@ ${sanitized.text}
|
|
|
3120
3121
|
const coldRoot = path2.join(this.baseDir, "cold");
|
|
3121
3122
|
_StorageManager.coldMemoriesCache.delete(coldRoot);
|
|
3122
3123
|
this.bumpColdWriteVersion();
|
|
3124
|
+
invalidateAllForDir(this.baseDir);
|
|
3123
3125
|
}
|
|
3124
3126
|
/** Return the current cold-write version counter for this storage root.
|
|
3125
3127
|
* Reads the on-disk sentinel (state/cold-write.log) so it reflects writes
|
|
@@ -5597,4 +5599,4 @@ export {
|
|
|
5597
5599
|
serializeEntityFile,
|
|
5598
5600
|
StorageManager
|
|
5599
5601
|
};
|
|
5600
|
-
//# sourceMappingURL=chunk-
|
|
5602
|
+
//# sourceMappingURL=chunk-AX5O25EF.js.map
|