@remnic/core 9.3.663 → 9.3.664
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 +25 -23
- package/dist/access-cli.js.map +1 -1
- package/dist/access-http.js +20 -18
- package/dist/access-mcp.js +19 -17
- package/dist/access-schema.js +4 -3
- package/dist/access-service.js +17 -15
- package/dist/briefing.js +5 -4
- package/dist/{capsule-merge-T2JRE46P.js → capsule-merge-GK5E647P.js} +3 -2
- package/dist/{capsule-merge-T2JRE46P.js.map → capsule-merge-GK5E647P.js.map} +1 -1
- package/dist/causal-consolidation.js +6 -5
- package/dist/causal-consolidation.js.map +1 -1
- package/dist/{chunk-2KDQI363.js → chunk-2HEZXPYU.js} +4 -4
- package/dist/chunk-5GPPACXK.js +16 -0
- package/dist/chunk-5GPPACXK.js.map +1 -0
- package/dist/{chunk-F6O7IOS3.js → chunk-6JBKHTQD.js} +2 -2
- package/dist/{chunk-TBLGI2LT.js → chunk-7ILWCUWH.js} +5 -3
- package/dist/{chunk-TBLGI2LT.js.map → chunk-7ILWCUWH.js.map} +1 -1
- package/dist/{chunk-AL4RAJL5.js → chunk-7XH7VJN4.js} +6 -4
- package/dist/chunk-7XH7VJN4.js.map +1 -0
- package/dist/{chunk-Q4CAQGKQ.js → chunk-AER6MT24.js} +12 -21
- package/dist/chunk-AER6MT24.js.map +1 -0
- package/dist/{chunk-DHGSZ3UD.js → chunk-ARV3AUOM.js} +2 -2
- package/dist/{chunk-PXVFMQLD.js → chunk-BZG2CWOQ.js} +3 -3
- package/dist/{chunk-ANJOULTP.js → chunk-C7AF236A.js} +2 -2
- package/dist/{chunk-FZC2WSDB.js → chunk-DOCTITOP.js} +2 -2
- package/dist/{chunk-WOQIHC67.js → chunk-DQY7NJ5L.js} +2 -2
- package/dist/{chunk-NMPEJV5M.js → chunk-DSLUOQDY.js} +2 -2
- package/dist/{chunk-A7EF2XRO.js → chunk-EXXBA5OM.js} +30 -8
- package/dist/chunk-EXXBA5OM.js.map +1 -0
- package/dist/{chunk-QXHBWFR3.js → chunk-IHG6CC7T.js} +2 -2
- package/dist/{chunk-4KDLCMLK.js → chunk-IROWLAWG.js} +5 -5
- package/dist/{chunk-ILXTATKK.js → chunk-J2HSAU72.js} +5 -5
- package/dist/chunk-J2HSAU72.js.map +1 -0
- package/dist/{chunk-DFAXGZKI.js → chunk-JIX3ZL2J.js} +8 -8
- package/dist/{chunk-GY3V3SUI.js → chunk-KHGE6PMF.js} +2 -2
- package/dist/{chunk-TGOOJCGA.js → chunk-LIERUFPO.js} +76 -54
- package/dist/chunk-LIERUFPO.js.map +1 -0
- package/dist/{chunk-HSCJYHYV.js → chunk-NLF54XMD.js} +49 -19
- package/dist/chunk-NLF54XMD.js.map +1 -0
- package/dist/{chunk-TWAJICBN.js → chunk-OHJFJ4HI.js} +2 -2
- package/dist/{chunk-WSQG37DV.js → chunk-OUWAQVDJ.js} +2 -2
- package/dist/{chunk-ZLDUQWT2.js → chunk-PWWWLD7D.js} +2 -2
- package/dist/{chunk-ZJH723NM.js → chunk-Q5ZU3RNY.js} +2 -2
- package/dist/{chunk-35HP3TGR.js → chunk-ROHLEUTH.js} +4 -4
- package/dist/{chunk-5RIRL3XL.js → chunk-RS25QOKZ.js} +2 -2
- package/dist/{chunk-RQGR3ETH.js → chunk-T2AN3BSP.js} +2 -2
- package/dist/{chunk-UAU5U5ML.js → chunk-UDJLF3BO.js} +2 -2
- package/dist/{chunk-ALEPI75L.js → chunk-VF4XKTX3.js} +6 -4
- package/dist/{chunk-ALEPI75L.js.map → chunk-VF4XKTX3.js.map} +1 -1
- package/dist/{chunk-AX5O25EF.js → chunk-VH6EIKVS.js} +152 -190
- package/dist/chunk-VH6EIKVS.js.map +1 -0
- package/dist/chunk-VS2IYZRU.js +43 -0
- package/dist/chunk-VS2IYZRU.js.map +1 -0
- package/dist/{chunk-YYQRVNSV.js → chunk-XB5P5P2L.js} +6 -6
- package/dist/{chunk-D2EFNQMY.js → chunk-XW3W4PV4.js} +2 -2
- package/dist/{chunk-5AYAZN45.js → chunk-YKX63GBK.js} +5 -5
- package/dist/{chunk-TYIXG4VR.js → chunk-YW52BQSU.js} +2 -2
- package/dist/{cli-C6twwe84.d.ts → cli-BQRqR9N-.d.ts} +12 -1
- package/dist/cli.d.ts +1 -1
- package/dist/cli.js +32 -28
- package/dist/compounding/engine.js +5 -4
- package/dist/connectors/codex-materialize-runner.js +5 -4
- package/dist/connectors/index.js +5 -4
- package/dist/consolidation-provenance-check.js +3 -2
- package/dist/consolidation-undo.js +2 -1
- package/dist/consolidation-undo.js.map +1 -1
- package/dist/entity-retrieval.js +5 -4
- package/dist/index.d.ts +1 -1
- package/dist/index.js +39 -36
- package/dist/index.js.map +1 -1
- package/dist/maintenance/memory-governance.js +6 -4
- package/dist/maintenance/rebuild-memory-lifecycle-ledger.js +5 -4
- package/dist/maintenance/rebuild-memory-projection.js +7 -5
- package/dist/namespaces/migrate.js +13 -11
- package/dist/namespaces/search.js +8 -6
- package/dist/namespaces/storage.js +5 -4
- package/dist/offline-sync.js +3 -2
- package/dist/operator-toolkit.js +16 -14
- package/dist/orchestrator.js +21 -19
- package/dist/page-versioning.js +2 -1
- package/dist/schemas.d.ts +22 -22
- package/dist/search/document-scanner.d.ts +11 -7
- package/dist/search/document-scanner.js +3 -1
- package/dist/search/factory.js +7 -5
- package/dist/search/index.js +7 -5
- package/dist/search/lancedb-backend.js +4 -2
- package/dist/search/meilisearch-backend.js +4 -2
- package/dist/search/orama-backend.js +4 -2
- package/dist/secure-store/index.js +3 -2
- package/dist/semantic-consolidation.js +6 -5
- package/dist/semantic-rule-promotion.js +5 -4
- package/dist/semantic-rule-verifier.js +5 -4
- package/dist/storage.d.ts +17 -3
- package/dist/storage.js +4 -3
- package/dist/transfer/capsule-import.js +3 -2
- package/dist/transfer/types.d.ts +12 -12
- package/dist/verified-recall.js +5 -4
- package/package.json +1 -1
- package/src/cli.ts +62 -23
- package/src/consolidation-provenance-check.ts +7 -6
- package/src/maintenance/memory-governance.ts +47 -7
- package/src/orchestrator.ts +84 -58
- package/src/page-versioning.ts +7 -4
- package/src/search/document-scanner.test.ts +29 -0
- package/src/search/document-scanner.ts +17 -29
- package/src/secure-store/secure-fs.ts +19 -5
- package/src/secure-store/secure-store.test.ts +28 -0
- package/src/storage.ts +42 -43
- package/src/training-export/converter.test.ts +19 -0
- package/src/training-export/converter.ts +8 -5
- package/src/utils/category-dir.ts +10 -4
- package/src/utils/path-containment.ts +40 -0
- package/dist/chunk-A7EF2XRO.js.map +0 -1
- package/dist/chunk-AL4RAJL5.js.map +0 -1
- package/dist/chunk-AX5O25EF.js.map +0 -1
- package/dist/chunk-HSCJYHYV.js.map +0 -1
- package/dist/chunk-ILXTATKK.js.map +0 -1
- package/dist/chunk-Q4CAQGKQ.js.map +0 -1
- package/dist/chunk-TGOOJCGA.js.map +0 -1
- /package/dist/{chunk-2KDQI363.js.map → chunk-2HEZXPYU.js.map} +0 -0
- /package/dist/{chunk-F6O7IOS3.js.map → chunk-6JBKHTQD.js.map} +0 -0
- /package/dist/{chunk-DHGSZ3UD.js.map → chunk-ARV3AUOM.js.map} +0 -0
- /package/dist/{chunk-PXVFMQLD.js.map → chunk-BZG2CWOQ.js.map} +0 -0
- /package/dist/{chunk-ANJOULTP.js.map → chunk-C7AF236A.js.map} +0 -0
- /package/dist/{chunk-FZC2WSDB.js.map → chunk-DOCTITOP.js.map} +0 -0
- /package/dist/{chunk-WOQIHC67.js.map → chunk-DQY7NJ5L.js.map} +0 -0
- /package/dist/{chunk-NMPEJV5M.js.map → chunk-DSLUOQDY.js.map} +0 -0
- /package/dist/{chunk-QXHBWFR3.js.map → chunk-IHG6CC7T.js.map} +0 -0
- /package/dist/{chunk-4KDLCMLK.js.map → chunk-IROWLAWG.js.map} +0 -0
- /package/dist/{chunk-DFAXGZKI.js.map → chunk-JIX3ZL2J.js.map} +0 -0
- /package/dist/{chunk-GY3V3SUI.js.map → chunk-KHGE6PMF.js.map} +0 -0
- /package/dist/{chunk-TWAJICBN.js.map → chunk-OHJFJ4HI.js.map} +0 -0
- /package/dist/{chunk-WSQG37DV.js.map → chunk-OUWAQVDJ.js.map} +0 -0
- /package/dist/{chunk-ZLDUQWT2.js.map → chunk-PWWWLD7D.js.map} +0 -0
- /package/dist/{chunk-ZJH723NM.js.map → chunk-Q5ZU3RNY.js.map} +0 -0
- /package/dist/{chunk-35HP3TGR.js.map → chunk-ROHLEUTH.js.map} +0 -0
- /package/dist/{chunk-5RIRL3XL.js.map → chunk-RS25QOKZ.js.map} +0 -0
- /package/dist/{chunk-RQGR3ETH.js.map → chunk-T2AN3BSP.js.map} +0 -0
- /package/dist/{chunk-UAU5U5ML.js.map → chunk-UDJLF3BO.js.map} +0 -0
- /package/dist/{chunk-YYQRVNSV.js.map → chunk-XB5P5P2L.js.map} +0 -0
- /package/dist/{chunk-D2EFNQMY.js.map → chunk-XW3W4PV4.js.map} +0 -0
- /package/dist/{chunk-5AYAZN45.js.map → chunk-YKX63GBK.js.map} +0 -0
- /package/dist/{chunk-TYIXG4VR.js.map → chunk-YW52BQSU.js.map} +0 -0
|
@@ -56,7 +56,7 @@ import {
|
|
|
56
56
|
} from "./chunk-G7D6GZ5J.js";
|
|
57
57
|
import {
|
|
58
58
|
createVersion
|
|
59
|
-
} from "./chunk-
|
|
59
|
+
} from "./chunk-VF4XKTX3.js";
|
|
60
60
|
import {
|
|
61
61
|
matchEntitySchemaSection,
|
|
62
62
|
normalizeEntityStructuredSection,
|
|
@@ -73,51 +73,21 @@ import {
|
|
|
73
73
|
readMaybeEncryptedFileBuffer,
|
|
74
74
|
writeMaybeEncryptedFile,
|
|
75
75
|
writeMaybeEncryptedFileFromChunks
|
|
76
|
-
} from "./chunk-
|
|
76
|
+
} from "./chunk-J2HSAU72.js";
|
|
77
77
|
import {
|
|
78
78
|
parseFlexibleIsoTimestamp
|
|
79
79
|
} from "./chunk-P7FMDTKL.js";
|
|
80
|
+
import {
|
|
81
|
+
RECALL_FALLBACK_DIRS,
|
|
82
|
+
categoryDirName,
|
|
83
|
+
getCategoryDir
|
|
84
|
+
} from "./chunk-VS2IYZRU.js";
|
|
80
85
|
|
|
81
86
|
// src/storage.ts
|
|
82
87
|
import { access, readdir, readFile, stat, writeFile, mkdir, unlink, appendFile, open } from "fs/promises";
|
|
83
88
|
import { appendFileSync, createReadStream, mkdirSync, readFileSync, statSync } from "fs";
|
|
84
89
|
import { createHash } from "crypto";
|
|
85
|
-
import path2 from "path";
|
|
86
|
-
|
|
87
|
-
// src/utils/category-dir.ts
|
|
88
90
|
import path from "path";
|
|
89
|
-
var CATEGORY_DIR_MAP = {
|
|
90
|
-
correction: "corrections",
|
|
91
|
-
question: "questions",
|
|
92
|
-
preference: "preferences",
|
|
93
|
-
decision: "decisions",
|
|
94
|
-
moment: "moments",
|
|
95
|
-
commitment: "commitments",
|
|
96
|
-
principle: "principles",
|
|
97
|
-
rule: "rules",
|
|
98
|
-
skill: "skills",
|
|
99
|
-
relationship: "relationships",
|
|
100
|
-
procedure: "procedures",
|
|
101
|
-
reasoning_trace: "reasoning-traces"
|
|
102
|
-
};
|
|
103
|
-
var ALL_CATEGORY_DIRS = [
|
|
104
|
-
"facts",
|
|
105
|
-
...Object.values(CATEGORY_DIR_MAP)
|
|
106
|
-
];
|
|
107
|
-
var RECALL_NON_MEMORY_DIRS = /* @__PURE__ */ new Set(["questions"]);
|
|
108
|
-
var RECALL_FALLBACK_DIRS = ALL_CATEGORY_DIRS.filter(
|
|
109
|
-
(dir) => !RECALL_NON_MEMORY_DIRS.has(dir)
|
|
110
|
-
);
|
|
111
|
-
var ALL_CATEGORY_KEYS = [
|
|
112
|
-
"fact",
|
|
113
|
-
...Object.keys(CATEGORY_DIR_MAP)
|
|
114
|
-
];
|
|
115
|
-
function getCategoryDir(memoryDir, category) {
|
|
116
|
-
const dir = Object.hasOwn(CATEGORY_DIR_MAP, category) ? CATEGORY_DIR_MAP[category] : void 0;
|
|
117
|
-
return dir ? path.join(memoryDir, dir) : path.join(memoryDir, "facts");
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
// src/storage.ts
|
|
121
91
|
var ARTIFACT_SEARCH_STOPWORDS = /* @__PURE__ */ new Set([
|
|
122
92
|
"a",
|
|
123
93
|
"an",
|
|
@@ -701,17 +671,17 @@ var KNOWN_ENTITY_FILENAME_PREFIXES = /* @__PURE__ */ new Set([
|
|
|
701
671
|
"topic"
|
|
702
672
|
]);
|
|
703
673
|
function inferEntityTypeFromFilename(pathRel) {
|
|
704
|
-
const basename =
|
|
674
|
+
const basename = path.basename(pathRel, ".md").toLowerCase();
|
|
705
675
|
const separator = basename.indexOf("-");
|
|
706
676
|
if (separator <= 0) return void 0;
|
|
707
677
|
const candidate = basename.slice(0, separator);
|
|
708
678
|
return KNOWN_ENTITY_FILENAME_PREFIXES.has(candidate) ? candidate : void 0;
|
|
709
679
|
}
|
|
710
680
|
function normalizeFrontmatterForPath(frontmatter, pathRel, content = "") {
|
|
711
|
-
const normalizedPath = pathRel.split(
|
|
681
|
+
const normalizedPath = pathRel.split(path.sep).join("/");
|
|
712
682
|
let normalizedFrontmatter = frontmatter;
|
|
713
683
|
if (normalizedPath === "entities" || normalizedPath.startsWith("entities/") || normalizedPath.includes("/entities/")) {
|
|
714
|
-
const basename =
|
|
684
|
+
const basename = path.basename(pathRel, ".md");
|
|
715
685
|
const inferredType = inferEntityTypeFromContent(content) || inferEntityTypeFromFilename(pathRel) || "entity";
|
|
716
686
|
const existingTags = Array.isArray(frontmatter.tags) ? frontmatter.tags : [];
|
|
717
687
|
normalizedFrontmatter = {
|
|
@@ -778,8 +748,8 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
778
748
|
secureStoreKeyProvider;
|
|
779
749
|
secureStoreWriteKeyProvider;
|
|
780
750
|
memoryDir;
|
|
781
|
-
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir =
|
|
782
|
-
this.filePath =
|
|
751
|
+
constructor(stateDir, secureStoreKeyProvider = () => null, secureStoreWriteKeyProvider = secureStoreKeyProvider, memoryDir = path.dirname(stateDir)) {
|
|
752
|
+
this.filePath = path.join(stateDir, "fact-hashes.txt");
|
|
783
753
|
this.secureStoreKeyProvider = secureStoreKeyProvider;
|
|
784
754
|
this.secureStoreWriteKeyProvider = secureStoreWriteKeyProvider;
|
|
785
755
|
this.memoryDir = memoryDir;
|
|
@@ -826,7 +796,7 @@ var ContentHashIndex = class _ContentHashIndex {
|
|
|
826
796
|
/** Persist index to disk if changed. */
|
|
827
797
|
async save() {
|
|
828
798
|
if (!this.dirty) return;
|
|
829
|
-
await mkdir(
|
|
799
|
+
await mkdir(path.dirname(this.filePath), { recursive: true });
|
|
830
800
|
await writeMaybeEncryptedFile(
|
|
831
801
|
this.filePath,
|
|
832
802
|
[...this.hashes].join("\n") + "\n",
|
|
@@ -1894,7 +1864,7 @@ var StorageManager = class _StorageManager {
|
|
|
1894
1864
|
void 0,
|
|
1895
1865
|
this.baseDir
|
|
1896
1866
|
);
|
|
1897
|
-
const rel =
|
|
1867
|
+
const rel = path.relative(this.baseDir, filePath).split(path.sep).join("/");
|
|
1898
1868
|
return `${rel}:${version.versionId}`;
|
|
1899
1869
|
} catch (err) {
|
|
1900
1870
|
log.warn(
|
|
@@ -1909,13 +1879,13 @@ var StorageManager = class _StorageManager {
|
|
|
1909
1879
|
}
|
|
1910
1880
|
identityFilePath(workspaceDir, namespace) {
|
|
1911
1881
|
const rawNamespace = typeof namespace === "string" ? namespace.trim() : "";
|
|
1912
|
-
if (!rawNamespace) return
|
|
1882
|
+
if (!rawNamespace) return path.join(workspaceDir, "IDENTITY.md");
|
|
1913
1883
|
const safeNamespace = rawNamespace.replace(/[^a-zA-Z0-9._-]/g, "-");
|
|
1914
|
-
return
|
|
1884
|
+
return path.join(workspaceDir, `IDENTITY.${safeNamespace}.md`);
|
|
1915
1885
|
}
|
|
1916
1886
|
versionFilePath(kind) {
|
|
1917
1887
|
const fileName = kind === "memory-status" ? ".memory-status-version.log" : kind === "artifact-write" ? ".artifact-write-version.log" : ".cold-write-version.log";
|
|
1918
|
-
return
|
|
1888
|
+
return path.join(this.stateDir, fileName);
|
|
1919
1889
|
}
|
|
1920
1890
|
bumpSharedVersion(kind, fallbackMap) {
|
|
1921
1891
|
const filePath = this.versionFilePath(kind);
|
|
@@ -1962,7 +1932,7 @@ var StorageManager = class _StorageManager {
|
|
|
1962
1932
|
// memories.
|
|
1963
1933
|
// -------------------------------------------------------------------------
|
|
1964
1934
|
get wearablesDir() {
|
|
1965
|
-
return
|
|
1935
|
+
return path.join(this.baseDir, WEARABLES_DIR_NAME);
|
|
1966
1936
|
}
|
|
1967
1937
|
/**
|
|
1968
1938
|
* Resolve the on-disk path for a source/day transcript. Throws on
|
|
@@ -1980,7 +1950,7 @@ var StorageManager = class _StorageManager {
|
|
|
1980
1950
|
`invalid wearable transcript date '${String(date)}' \u2014 expected YYYY-MM-DD`
|
|
1981
1951
|
);
|
|
1982
1952
|
}
|
|
1983
|
-
return
|
|
1953
|
+
return path.join(this.wearablesDir, sourceId, `${date}.md`);
|
|
1984
1954
|
}
|
|
1985
1955
|
async writeWearableDayTranscript(sourceId, date, serialized) {
|
|
1986
1956
|
const targetPath = this.wearableTranscriptPath(sourceId, date);
|
|
@@ -2018,7 +1988,7 @@ var StorageManager = class _StorageManager {
|
|
|
2018
1988
|
if (!/^[a-z][a-z0-9-]{0,63}$/.test(source)) continue;
|
|
2019
1989
|
let entries;
|
|
2020
1990
|
try {
|
|
2021
|
-
entries = await readdir(
|
|
1991
|
+
entries = await readdir(path.join(this.wearablesDir, source));
|
|
2022
1992
|
} catch (err) {
|
|
2023
1993
|
if (err.code === "ENOENT") continue;
|
|
2024
1994
|
throw err;
|
|
@@ -2101,25 +2071,25 @@ var StorageManager = class _StorageManager {
|
|
|
2101
2071
|
});
|
|
2102
2072
|
}
|
|
2103
2073
|
get factsDir() {
|
|
2104
|
-
return
|
|
2074
|
+
return path.join(this.baseDir, "facts");
|
|
2105
2075
|
}
|
|
2106
2076
|
get correctionsDir() {
|
|
2107
|
-
return
|
|
2077
|
+
return path.join(this.baseDir, "corrections");
|
|
2108
2078
|
}
|
|
2109
2079
|
get proceduresDir() {
|
|
2110
|
-
return
|
|
2080
|
+
return path.join(this.baseDir, "procedures");
|
|
2111
2081
|
}
|
|
2112
2082
|
get reasoningTracesDir() {
|
|
2113
|
-
return
|
|
2083
|
+
return path.join(this.baseDir, "reasoning-traces");
|
|
2114
2084
|
}
|
|
2115
2085
|
get entitiesDir() {
|
|
2116
|
-
return
|
|
2086
|
+
return path.join(this.baseDir, "entities");
|
|
2117
2087
|
}
|
|
2118
2088
|
resolveEntityFilePath(name) {
|
|
2119
2089
|
if (typeof name !== "string") return null;
|
|
2120
|
-
const filePath =
|
|
2121
|
-
const relative =
|
|
2122
|
-
if (relative === "" || relative.startsWith("..") ||
|
|
2090
|
+
const filePath = path.resolve(this.entitiesDir, `${name}.md`);
|
|
2091
|
+
const relative = path.relative(this.entitiesDir, filePath);
|
|
2092
|
+
if (relative === "" || relative.startsWith("..") || path.isAbsolute(relative)) {
|
|
2123
2093
|
return null;
|
|
2124
2094
|
}
|
|
2125
2095
|
return filePath;
|
|
@@ -2131,10 +2101,10 @@ var StorageManager = class _StorageManager {
|
|
|
2131
2101
|
return writeMaybeEncryptedFile(filePath, content, this.resolveWriteKey(), {}, this.baseDir);
|
|
2132
2102
|
}
|
|
2133
2103
|
assertManagedStoragePath(filePath, method) {
|
|
2134
|
-
const resolved =
|
|
2135
|
-
const base =
|
|
2136
|
-
const rel =
|
|
2137
|
-
if (rel === "" || rel === ".." || rel.startsWith(`..${
|
|
2104
|
+
const resolved = path.resolve(filePath);
|
|
2105
|
+
const base = path.resolve(this.baseDir);
|
|
2106
|
+
const rel = path.relative(base, resolved);
|
|
2107
|
+
if (rel === "" || rel === ".." || rel.startsWith(`..${path.sep}`) || path.isAbsolute(rel)) {
|
|
2138
2108
|
throw new Error(`${method}: file path escapes memory dir`);
|
|
2139
2109
|
}
|
|
2140
2110
|
return resolved;
|
|
@@ -2146,7 +2116,7 @@ var StorageManager = class _StorageManager {
|
|
|
2146
2116
|
async digestOfflineSyncFile(filePath) {
|
|
2147
2117
|
const target = this.assertManagedStoragePath(filePath, "storage.digestOfflineSyncFile");
|
|
2148
2118
|
const st = await stat(target);
|
|
2149
|
-
const relPath =
|
|
2119
|
+
const relPath = path.relative(this.baseDir, target).split(path.sep).join("/");
|
|
2150
2120
|
const cache = await this.loadOfflineSyncDigestCache();
|
|
2151
2121
|
const cached = cache.get(relPath);
|
|
2152
2122
|
if (cached && cached.statBytes === st.size && cached.mtimeMs === st.mtimeMs && cached.ctimeMs === st.ctimeMs && !cached.encrypted) {
|
|
@@ -2207,7 +2177,7 @@ var StorageManager = class _StorageManager {
|
|
|
2207
2177
|
const bytes = typeof record.bytes === "number" ? record.bytes : NaN;
|
|
2208
2178
|
const sha256 = typeof record.sha256 === "string" ? record.sha256 : "";
|
|
2209
2179
|
const encrypted = record.encrypted === true;
|
|
2210
|
-
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") ||
|
|
2180
|
+
if (cachePath.length === 0 || cachePath === ".." || cachePath.startsWith("../") || path.isAbsolute(cachePath) || !Number.isFinite(statBytes) || !Number.isFinite(mtimeMs) || !Number.isFinite(ctimeMs) || !Number.isFinite(bytes) || !/^[a-f0-9]{64}$/i.test(sha256)) {
|
|
2211
2181
|
continue;
|
|
2212
2182
|
}
|
|
2213
2183
|
cache.set(cachePath, { statBytes, mtimeMs, ctimeMs, encrypted, sha256, bytes });
|
|
@@ -2249,7 +2219,7 @@ var StorageManager = class _StorageManager {
|
|
|
2249
2219
|
const cache = this.offlineSyncDigestCache;
|
|
2250
2220
|
if (!cache) return;
|
|
2251
2221
|
const entries = [...cache.entries()].sort(([a], [b]) => a.localeCompare(b)).map(([entryPath, entry]) => ({ path: entryPath, ...entry }));
|
|
2252
|
-
await mkdir(
|
|
2222
|
+
await mkdir(path.dirname(this.offlineSyncDigestCachePath), { recursive: true });
|
|
2253
2223
|
await writeFile(
|
|
2254
2224
|
this.offlineSyncDigestCachePath,
|
|
2255
2225
|
`${JSON.stringify({ version: 1, entries })}
|
|
@@ -2302,10 +2272,10 @@ var StorageManager = class _StorageManager {
|
|
|
2302
2272
|
if (isErrnoCode(error, "ENOENT")) return;
|
|
2303
2273
|
throw error;
|
|
2304
2274
|
});
|
|
2305
|
-
if (filePath.includes(`${
|
|
2275
|
+
if (filePath.includes(`${path.sep}cold${path.sep}`)) {
|
|
2306
2276
|
this.invalidateColdMemoriesCache();
|
|
2307
2277
|
}
|
|
2308
|
-
if (filePath.includes(`${
|
|
2278
|
+
if (filePath.includes(`${path.sep}artifacts${path.sep}`)) {
|
|
2309
2279
|
this.bumpArtifactWriteVersion();
|
|
2310
2280
|
}
|
|
2311
2281
|
this.bumpMemoryStatusVersion();
|
|
@@ -2333,7 +2303,7 @@ var StorageManager = class _StorageManager {
|
|
|
2333
2303
|
}
|
|
2334
2304
|
async appendStorageSecureFileUnlocked(filePath, content) {
|
|
2335
2305
|
const writeKey = this.resolveWriteKey();
|
|
2336
|
-
await mkdir(
|
|
2306
|
+
await mkdir(path.dirname(filePath), { recursive: true });
|
|
2337
2307
|
if (writeKey === null) {
|
|
2338
2308
|
try {
|
|
2339
2309
|
if (isEncryptedFile(await readFile(filePath))) {
|
|
@@ -2356,16 +2326,16 @@ var StorageManager = class _StorageManager {
|
|
|
2356
2326
|
await writeMaybeEncryptedFile(filePath, `${existing}${content}`, writeKey, {}, this.baseDir);
|
|
2357
2327
|
}
|
|
2358
2328
|
get stateDir() {
|
|
2359
|
-
return
|
|
2329
|
+
return path.join(this.baseDir, "state");
|
|
2360
2330
|
}
|
|
2361
2331
|
get offlineSyncDigestCachePath() {
|
|
2362
|
-
return
|
|
2332
|
+
return path.join(this.baseDir, ".offline-sync", "digest-cache.v1.json");
|
|
2363
2333
|
}
|
|
2364
2334
|
get entitySynthesisQueuePath() {
|
|
2365
|
-
return
|
|
2335
|
+
return path.join(this.stateDir, "entity-synthesis-queue.json");
|
|
2366
2336
|
}
|
|
2367
2337
|
get factHashIndexReadyPath() {
|
|
2368
|
-
return
|
|
2338
|
+
return path.join(this.stateDir, "fact-hashes.ready");
|
|
2369
2339
|
}
|
|
2370
2340
|
async getFactHashIndex() {
|
|
2371
2341
|
if (this.factHashIndex) {
|
|
@@ -2432,7 +2402,7 @@ var StorageManager = class _StorageManager {
|
|
|
2432
2402
|
);
|
|
2433
2403
|
}
|
|
2434
2404
|
await factHashIndex.save();
|
|
2435
|
-
await mkdir(
|
|
2405
|
+
await mkdir(path.dirname(this.factHashIndexReadyPath), { recursive: true });
|
|
2436
2406
|
await writeFile(this.factHashIndexReadyPath, "v1\n", "utf-8");
|
|
2437
2407
|
this.factHashIndexAuthoritative = true;
|
|
2438
2408
|
})().finally(() => {
|
|
@@ -2441,55 +2411,55 @@ var StorageManager = class _StorageManager {
|
|
|
2441
2411
|
await this.factHashIndexAuthoritativePromise;
|
|
2442
2412
|
}
|
|
2443
2413
|
get questionsDir() {
|
|
2444
|
-
return
|
|
2414
|
+
return path.join(this.baseDir, "questions");
|
|
2445
2415
|
}
|
|
2446
2416
|
get artifactsDir() {
|
|
2447
|
-
return
|
|
2417
|
+
return path.join(this.baseDir, "artifacts");
|
|
2448
2418
|
}
|
|
2449
2419
|
get identityDir() {
|
|
2450
|
-
return
|
|
2420
|
+
return path.join(this.baseDir, "identity");
|
|
2451
2421
|
}
|
|
2452
2422
|
get identityAnchorPath() {
|
|
2453
|
-
return
|
|
2423
|
+
return path.join(this.identityDir, "identity-anchor.md");
|
|
2454
2424
|
}
|
|
2455
2425
|
get identityIncidentsDir() {
|
|
2456
|
-
return
|
|
2426
|
+
return path.join(this.identityDir, "incidents");
|
|
2457
2427
|
}
|
|
2458
2428
|
get identityAuditsWeeklyDir() {
|
|
2459
|
-
return
|
|
2429
|
+
return path.join(this.identityDir, "audits", "weekly");
|
|
2460
2430
|
}
|
|
2461
2431
|
get identityAuditsMonthlyDir() {
|
|
2462
|
-
return
|
|
2432
|
+
return path.join(this.identityDir, "audits", "monthly");
|
|
2463
2433
|
}
|
|
2464
2434
|
get identityImprovementLoopsPath() {
|
|
2465
|
-
return
|
|
2435
|
+
return path.join(this.identityDir, "improvement-loops.md");
|
|
2466
2436
|
}
|
|
2467
2437
|
get identityReflectionsPath() {
|
|
2468
|
-
return
|
|
2438
|
+
return path.join(this.identityDir, "reflections.md");
|
|
2469
2439
|
}
|
|
2470
2440
|
get profilePath() {
|
|
2471
|
-
return
|
|
2441
|
+
return path.join(this.baseDir, "profile.md");
|
|
2472
2442
|
}
|
|
2473
2443
|
get memoryActionsPath() {
|
|
2474
|
-
return
|
|
2444
|
+
return path.join(this.stateDir, "memory-actions.jsonl");
|
|
2475
2445
|
}
|
|
2476
2446
|
get memoryLifecycleLedgerPath() {
|
|
2477
|
-
return
|
|
2447
|
+
return path.join(this.stateDir, "memory-lifecycle-ledger.jsonl");
|
|
2478
2448
|
}
|
|
2479
2449
|
get compressionGuidelinesPath() {
|
|
2480
|
-
return
|
|
2450
|
+
return path.join(this.stateDir, "compression-guidelines.md");
|
|
2481
2451
|
}
|
|
2482
2452
|
get compressionGuidelineDraftPath() {
|
|
2483
|
-
return
|
|
2453
|
+
return path.join(this.stateDir, "compression-guidelines.draft.md");
|
|
2484
2454
|
}
|
|
2485
2455
|
get compressionGuidelineStatePath() {
|
|
2486
|
-
return
|
|
2456
|
+
return path.join(this.stateDir, "compression-guideline-state.json");
|
|
2487
2457
|
}
|
|
2488
2458
|
get compressionGuidelineDraftStatePath() {
|
|
2489
|
-
return
|
|
2459
|
+
return path.join(this.stateDir, "compression-guideline-draft-state.json");
|
|
2490
2460
|
}
|
|
2491
2461
|
get behaviorSignalsPath() {
|
|
2492
|
-
return
|
|
2462
|
+
return path.join(this.stateDir, "behavior-signals.jsonl");
|
|
2493
2463
|
}
|
|
2494
2464
|
/**
|
|
2495
2465
|
* Buffer surprise telemetry ledger (issue #563 PR 3).
|
|
@@ -2502,7 +2472,7 @@ var StorageManager = class _StorageManager {
|
|
|
2502
2472
|
* governance sweeps can treat it uniformly.
|
|
2503
2473
|
*/
|
|
2504
2474
|
get bufferSurpriseLedgerPath() {
|
|
2505
|
-
return
|
|
2475
|
+
return path.join(this.stateDir, "buffer-surprise-ledger.jsonl");
|
|
2506
2476
|
}
|
|
2507
2477
|
/**
|
|
2508
2478
|
* Entity alias table loaded from THIS store's config/aliases.json.
|
|
@@ -2534,7 +2504,7 @@ var StorageManager = class _StorageManager {
|
|
|
2534
2504
|
this.loadAliasesSync();
|
|
2535
2505
|
}
|
|
2536
2506
|
loadAliasesSync() {
|
|
2537
|
-
const aliasPath =
|
|
2507
|
+
const aliasPath = path.join(this.baseDir, "config", "aliases.json");
|
|
2538
2508
|
this.userAliases = {};
|
|
2539
2509
|
try {
|
|
2540
2510
|
const raw = readFileSync(aliasPath, "utf-8");
|
|
@@ -2559,9 +2529,9 @@ var StorageManager = class _StorageManager {
|
|
|
2559
2529
|
}
|
|
2560
2530
|
async ensureDirectories() {
|
|
2561
2531
|
const today = (/* @__PURE__ */ new Date()).toISOString().slice(0, 10);
|
|
2562
|
-
await mkdir(
|
|
2563
|
-
await mkdir(
|
|
2564
|
-
await mkdir(
|
|
2532
|
+
await mkdir(path.join(this.factsDir, today), { recursive: true });
|
|
2533
|
+
await mkdir(path.join(this.proceduresDir, today), { recursive: true });
|
|
2534
|
+
await mkdir(path.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2565
2535
|
await mkdir(this.correctionsDir, { recursive: true });
|
|
2566
2536
|
await mkdir(this.entitiesDir, { recursive: true });
|
|
2567
2537
|
await mkdir(this.stateDir, { recursive: true });
|
|
@@ -2571,7 +2541,28 @@ var StorageManager = class _StorageManager {
|
|
|
2571
2541
|
await mkdir(this.identityIncidentsDir, { recursive: true });
|
|
2572
2542
|
await mkdir(this.identityAuditsWeeklyDir, { recursive: true });
|
|
2573
2543
|
await mkdir(this.identityAuditsMonthlyDir, { recursive: true });
|
|
2574
|
-
await mkdir(
|
|
2544
|
+
await mkdir(path.join(this.baseDir, "config"), { recursive: true });
|
|
2545
|
+
}
|
|
2546
|
+
/**
|
|
2547
|
+
* Resolve the on-disk write path for a memory of the given category, creating
|
|
2548
|
+
* the target directory. Category routing goes through the shared
|
|
2549
|
+
* `getCategoryDir()` chokepoint (utils/category-dir.ts → CATEGORY_DIR_MAP) so
|
|
2550
|
+
* decision/preference/moment/etc. outputs land in their dedicated dirs
|
|
2551
|
+
* (`decisions/`, `preferences/`, ...) instead of collapsing into `facts/`
|
|
2552
|
+
* (issue #1546; CLAUDE.md rule 39). `correction` keeps its historical flat
|
|
2553
|
+
* layout (no `<date>` subdir) as the corrections pipeline expects; every other
|
|
2554
|
+
* category — including `fact`/`entity`, which fall back to `facts/` — is dated
|
|
2555
|
+
* as `<dir>/<date>/`. Read/scan/reindex already iterate every category dir
|
|
2556
|
+
* (RECALL_FALLBACK_DIRS; QMD scans baseDir recursively), so writes stay found.
|
|
2557
|
+
*/
|
|
2558
|
+
async resolveCategoryWritePath(category, id, today) {
|
|
2559
|
+
if (category === "correction") {
|
|
2560
|
+
await mkdir(this.correctionsDir, { recursive: true });
|
|
2561
|
+
return path.join(this.correctionsDir, `${id}.md`);
|
|
2562
|
+
}
|
|
2563
|
+
const datedDir = path.join(getCategoryDir(this.baseDir, category), today);
|
|
2564
|
+
await mkdir(datedDir, { recursive: true });
|
|
2565
|
+
return path.join(datedDir, `${id}.md`);
|
|
2575
2566
|
}
|
|
2576
2567
|
async writeMemory(category, content, options = {}) {
|
|
2577
2568
|
await this.ensureDirectories();
|
|
@@ -2639,18 +2630,7 @@ var StorageManager = class _StorageManager {
|
|
|
2639
2630
|
|
|
2640
2631
|
${sanitized.text}
|
|
2641
2632
|
`;
|
|
2642
|
-
|
|
2643
|
-
if (category === "correction") {
|
|
2644
|
-
filePath = path2.join(this.correctionsDir, `${id}.md`);
|
|
2645
|
-
} else if (category === "procedure") {
|
|
2646
|
-
await mkdir(path2.join(this.proceduresDir, today), { recursive: true });
|
|
2647
|
-
filePath = path2.join(this.proceduresDir, today, `${id}.md`);
|
|
2648
|
-
} else if (category === "reasoning_trace") {
|
|
2649
|
-
await mkdir(path2.join(this.reasoningTracesDir, today), { recursive: true });
|
|
2650
|
-
filePath = path2.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
2651
|
-
} else {
|
|
2652
|
-
filePath = path2.join(this.factsDir, today, `${id}.md`);
|
|
2653
|
-
}
|
|
2633
|
+
const filePath = await this.resolveCategoryWritePath(category, id, today);
|
|
2654
2634
|
await this.snapshotBeforeWrite(filePath, "write");
|
|
2655
2635
|
await writeMaybeEncryptedFile(filePath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
2656
2636
|
this.invalidateAllMemoriesCache();
|
|
@@ -2764,7 +2744,7 @@ ${sanitized.text}
|
|
|
2764
2744
|
await this.ensureDirectories();
|
|
2765
2745
|
const now = /* @__PURE__ */ new Date();
|
|
2766
2746
|
const day = now.toISOString().slice(0, 10);
|
|
2767
|
-
const dir =
|
|
2747
|
+
const dir = path.join(this.artifactsDir, day);
|
|
2768
2748
|
await mkdir(dir, { recursive: true });
|
|
2769
2749
|
const id = `artifact-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`;
|
|
2770
2750
|
const fm = {
|
|
@@ -2788,7 +2768,7 @@ ${sanitized.text}
|
|
|
2788
2768
|
log.warn(`artifact content rejected for ${id}; violations=${sanitized.violations.join(", ")}`);
|
|
2789
2769
|
return "";
|
|
2790
2770
|
}
|
|
2791
|
-
const filePath =
|
|
2771
|
+
const filePath = path.join(dir, `${id}.md`);
|
|
2792
2772
|
await writeMaybeEncryptedFile(filePath, `${serializeFrontmatter(fm)}
|
|
2793
2773
|
|
|
2794
2774
|
${sanitized.text}
|
|
@@ -2816,7 +2796,7 @@ ${sanitized.text}
|
|
|
2816
2796
|
try {
|
|
2817
2797
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
2818
2798
|
for (const entry of entries) {
|
|
2819
|
-
const fullPath =
|
|
2799
|
+
const fullPath = path.join(dir, entry.name);
|
|
2820
2800
|
if (entry.isDirectory()) {
|
|
2821
2801
|
await readDir(fullPath);
|
|
2822
2802
|
continue;
|
|
@@ -2882,7 +2862,7 @@ ${sanitized.text}
|
|
|
2882
2862
|
log.debug(`fuzzy match: "${normalized}" \u2192 existing "${match}"`);
|
|
2883
2863
|
normalized = match;
|
|
2884
2864
|
}
|
|
2885
|
-
const filePath =
|
|
2865
|
+
const filePath = path.join(this.entitiesDir, `${normalized}.md`);
|
|
2886
2866
|
let entity = {
|
|
2887
2867
|
name,
|
|
2888
2868
|
type,
|
|
@@ -3118,7 +3098,7 @@ ${sanitized.text}
|
|
|
3118
3098
|
* per-process in-memory cache safe across process boundaries.
|
|
3119
3099
|
*/
|
|
3120
3100
|
invalidateColdMemoriesCache() {
|
|
3121
|
-
const coldRoot =
|
|
3101
|
+
const coldRoot = path.join(this.baseDir, "cold");
|
|
3122
3102
|
_StorageManager.coldMemoriesCache.delete(coldRoot);
|
|
3123
3103
|
this.bumpColdWriteVersion();
|
|
3124
3104
|
invalidateAllForDir(this.baseDir);
|
|
@@ -3147,7 +3127,7 @@ ${sanitized.text}
|
|
|
3147
3127
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3148
3128
|
const subdirs = [];
|
|
3149
3129
|
for (const entry of entries) {
|
|
3150
|
-
const fullPath =
|
|
3130
|
+
const fullPath = path.join(dir, entry.name);
|
|
3151
3131
|
if (entry.isDirectory()) {
|
|
3152
3132
|
subdirs.push(fullPath);
|
|
3153
3133
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3161,7 +3141,7 @@ ${sanitized.text}
|
|
|
3161
3141
|
}
|
|
3162
3142
|
};
|
|
3163
3143
|
for (const dir of RECALL_FALLBACK_DIRS) {
|
|
3164
|
-
await collectPaths(
|
|
3144
|
+
await collectPaths(path.join(this.baseDir, dir));
|
|
3165
3145
|
}
|
|
3166
3146
|
return filePaths;
|
|
3167
3147
|
}
|
|
@@ -3230,7 +3210,7 @@ ${sanitized.text}
|
|
|
3230
3210
|
const correctionPaths = [];
|
|
3231
3211
|
const factPaths = [];
|
|
3232
3212
|
for (const filePath of filePaths) {
|
|
3233
|
-
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${
|
|
3213
|
+
if (filePath === this.correctionsDir || filePath.startsWith(`${this.correctionsDir}${path.sep}`)) {
|
|
3234
3214
|
correctionPaths.push(filePath);
|
|
3235
3215
|
} else {
|
|
3236
3216
|
factPaths.push(filePath);
|
|
@@ -3316,9 +3296,10 @@ ${sanitized.text}
|
|
|
3316
3296
|
* Read all memories from the cold tier by scanning the entire cold/ root
|
|
3317
3297
|
* tree. Previously this only scanned cold/facts/ and cold/corrections/, but
|
|
3318
3298
|
* structuredAttributes can appear on any MemoryCategory (preference, decision,
|
|
3319
|
-
* entity, etc.).
|
|
3320
|
-
*
|
|
3321
|
-
*
|
|
3299
|
+
* entity, etc.). buildTierMemoryPath now routes each category to its own
|
|
3300
|
+
* cold/<dir>/ subtree via the shared categoryDirName() chokepoint (issue
|
|
3301
|
+
* #1546), so cold decisions/preferences/... live outside cold/facts/.
|
|
3302
|
+
* Scanning the full coldRoot covers every category dir and guards against
|
|
3322
3303
|
* files placed in unexpected subdirectories during manual operations or future
|
|
3323
3304
|
* refactors.
|
|
3324
3305
|
*
|
|
@@ -3350,7 +3331,7 @@ ${sanitized.text}
|
|
|
3350
3331
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3351
3332
|
const subdirs = [];
|
|
3352
3333
|
for (const entry of entries) {
|
|
3353
|
-
const fullPath =
|
|
3334
|
+
const fullPath = path.join(dir, entry.name);
|
|
3354
3335
|
if (entry.isDirectory()) {
|
|
3355
3336
|
subdirs.push(fullPath);
|
|
3356
3337
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3379,7 +3360,7 @@ ${sanitized.text}
|
|
|
3379
3360
|
try {
|
|
3380
3361
|
const entries = await readdir(dir, { withFileTypes: true });
|
|
3381
3362
|
for (const entry of entries) {
|
|
3382
|
-
const fullPath =
|
|
3363
|
+
const fullPath = path.join(dir, entry.name);
|
|
3383
3364
|
if (entry.isDirectory()) {
|
|
3384
3365
|
await readDir(fullPath);
|
|
3385
3366
|
} else if (entry.name.endsWith(".md")) {
|
|
@@ -3424,11 +3405,11 @@ ${sanitized.text}
|
|
|
3424
3405
|
content: parsed.content
|
|
3425
3406
|
};
|
|
3426
3407
|
}
|
|
3427
|
-
const normalizedPath = filePath.split(
|
|
3408
|
+
const normalizedPath = filePath.split(path.sep).join("/");
|
|
3428
3409
|
if (normalizedPath.includes("/entities/") && filePath.endsWith(".md")) {
|
|
3429
3410
|
const entity = parseEntityFile(raw, this.entitySchemas);
|
|
3430
3411
|
if (!entity.name) return null;
|
|
3431
|
-
const nameWithoutExt =
|
|
3412
|
+
const nameWithoutExt = path.basename(filePath, ".md");
|
|
3432
3413
|
const fileMtime = entity.updated || await stat(filePath).then((s) => s.mtime.toISOString()).catch(() => (/* @__PURE__ */ new Date(0)).toISOString());
|
|
3433
3414
|
return {
|
|
3434
3415
|
path: filePath,
|
|
@@ -3452,7 +3433,7 @@ ${sanitized.text}
|
|
|
3452
3433
|
}
|
|
3453
3434
|
}
|
|
3454
3435
|
resolveTierRootDir(tier) {
|
|
3455
|
-
return tier === "cold" ?
|
|
3436
|
+
return tier === "cold" ? path.join(this.baseDir, "cold") : this.baseDir;
|
|
3456
3437
|
}
|
|
3457
3438
|
resolveMemoryDateDir(memory) {
|
|
3458
3439
|
const preferred = memory.frontmatter.created || memory.frontmatter.updated;
|
|
@@ -3467,18 +3448,13 @@ ${sanitized.text}
|
|
|
3467
3448
|
buildTierMemoryPath(memory, tier) {
|
|
3468
3449
|
const root = this.resolveTierRootDir(tier);
|
|
3469
3450
|
if (this.isArtifactMemory(memory)) {
|
|
3470
|
-
return
|
|
3451
|
+
return path.join(root, "artifacts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3471
3452
|
}
|
|
3472
3453
|
if (memory.frontmatter.category === "correction") {
|
|
3473
|
-
return
|
|
3474
|
-
}
|
|
3475
|
-
if (memory.frontmatter.category === "procedure") {
|
|
3476
|
-
return path2.join(root, "procedures", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3454
|
+
return path.join(root, "corrections", `${memory.frontmatter.id}.md`);
|
|
3477
3455
|
}
|
|
3478
|
-
|
|
3479
|
-
|
|
3480
|
-
}
|
|
3481
|
-
return path2.join(root, "facts", this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3456
|
+
const dir = categoryDirName(memory.frontmatter.category);
|
|
3457
|
+
return path.join(root, dir, this.resolveMemoryDateDir(memory), `${memory.frontmatter.id}.md`);
|
|
3482
3458
|
}
|
|
3483
3459
|
async writeMemoryFileAtomic(targetPath, memory) {
|
|
3484
3460
|
const fileContent = `${serializeFrontmatter(memory.frontmatter)}
|
|
@@ -3490,8 +3466,8 @@ ${memory.content}
|
|
|
3490
3466
|
}
|
|
3491
3467
|
async moveMemoryToPath(memory, targetPath) {
|
|
3492
3468
|
await this.writeMemoryFileAtomic(targetPath, memory);
|
|
3493
|
-
const sourcePath =
|
|
3494
|
-
const destPath =
|
|
3469
|
+
const sourcePath = path.resolve(memory.path);
|
|
3470
|
+
const destPath = path.resolve(targetPath);
|
|
3495
3471
|
if (sourcePath !== destPath) {
|
|
3496
3472
|
try {
|
|
3497
3473
|
await unlink(memory.path);
|
|
@@ -3506,8 +3482,8 @@ ${memory.content}
|
|
|
3506
3482
|
}
|
|
3507
3483
|
async migrateMemoryToTier(memory, targetTier) {
|
|
3508
3484
|
const targetPath = this.buildTierMemoryPath(memory, targetTier);
|
|
3509
|
-
const sourcePath =
|
|
3510
|
-
const destPath =
|
|
3485
|
+
const sourcePath = path.resolve(memory.path);
|
|
3486
|
+
const destPath = path.resolve(targetPath);
|
|
3511
3487
|
if (sourcePath === destPath) {
|
|
3512
3488
|
return { changed: false, targetPath };
|
|
3513
3489
|
}
|
|
@@ -3533,7 +3509,7 @@ ${memory.content}
|
|
|
3533
3509
|
return { changed: true, targetPath };
|
|
3534
3510
|
}
|
|
3535
3511
|
get archiveDir() {
|
|
3536
|
-
return
|
|
3512
|
+
return path.join(this.baseDir, "archive");
|
|
3537
3513
|
}
|
|
3538
3514
|
/**
|
|
3539
3515
|
* Archive a memory by moving it from facts/ to archive/YYYY-MM-DD/.
|
|
@@ -3544,7 +3520,7 @@ ${memory.content}
|
|
|
3544
3520
|
try {
|
|
3545
3521
|
const now = lifecycle?.at ?? /* @__PURE__ */ new Date();
|
|
3546
3522
|
const today = now.toISOString().slice(0, 10);
|
|
3547
|
-
const destDir =
|
|
3523
|
+
const destDir = path.join(this.archiveDir, today);
|
|
3548
3524
|
await mkdir(destDir, { recursive: true });
|
|
3549
3525
|
const updatedFm = {
|
|
3550
3526
|
...memory.frontmatter,
|
|
@@ -3556,7 +3532,7 @@ ${memory.content}
|
|
|
3556
3532
|
|
|
3557
3533
|
${memory.content}
|
|
3558
3534
|
`;
|
|
3559
|
-
const destPath =
|
|
3535
|
+
const destPath = path.join(destDir, path.basename(memory.path));
|
|
3560
3536
|
await writeMaybeEncryptedFile(destPath, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3561
3537
|
await unlink(memory.path);
|
|
3562
3538
|
this.invalidateAllMemoriesCache();
|
|
@@ -3718,7 +3694,7 @@ ${memory.content}
|
|
|
3718
3694
|
`;
|
|
3719
3695
|
await writeMaybeEncryptedFile(memory.path, fileContent, this.resolveWriteKey(), {}, this.baseDir);
|
|
3720
3696
|
this.invalidateAllMemoriesCache();
|
|
3721
|
-
if (memory.path.includes(`${
|
|
3697
|
+
if (memory.path.includes(`${path.sep}cold${path.sep}`)) {
|
|
3722
3698
|
this.invalidateColdMemoriesCache();
|
|
3723
3699
|
}
|
|
3724
3700
|
try {
|
|
@@ -3790,7 +3766,7 @@ ${memory.content}
|
|
|
3790
3766
|
return deleted;
|
|
3791
3767
|
}
|
|
3792
3768
|
async loadBuffer() {
|
|
3793
|
-
const bufferPath =
|
|
3769
|
+
const bufferPath = path.join(this.stateDir, "buffer.json");
|
|
3794
3770
|
try {
|
|
3795
3771
|
const raw = await this.readStorageSecureFile(bufferPath);
|
|
3796
3772
|
return JSON.parse(raw);
|
|
@@ -3802,11 +3778,11 @@ ${memory.content}
|
|
|
3802
3778
|
}
|
|
3803
3779
|
async saveBuffer(state) {
|
|
3804
3780
|
await this.ensureDirectories();
|
|
3805
|
-
const bufferPath =
|
|
3781
|
+
const bufferPath = path.join(this.stateDir, "buffer.json");
|
|
3806
3782
|
await this.writeStorageSecureFile(bufferPath, JSON.stringify(state, null, 2));
|
|
3807
3783
|
}
|
|
3808
3784
|
async loadMeta() {
|
|
3809
|
-
const metaPath =
|
|
3785
|
+
const metaPath = path.join(this.stateDir, "meta.json");
|
|
3810
3786
|
try {
|
|
3811
3787
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
3812
3788
|
const parsed = JSON.parse(raw);
|
|
@@ -3840,7 +3816,7 @@ ${memory.content}
|
|
|
3840
3816
|
}
|
|
3841
3817
|
async saveMeta(state) {
|
|
3842
3818
|
await this.ensureDirectories();
|
|
3843
|
-
const metaPath =
|
|
3819
|
+
const metaPath = path.join(this.stateDir, "meta.json");
|
|
3844
3820
|
await this.writeStorageSecureFile(metaPath, JSON.stringify(state, null, 2));
|
|
3845
3821
|
}
|
|
3846
3822
|
async appendMemoryActionEvents(events) {
|
|
@@ -4010,7 +3986,7 @@ ${memory.content}
|
|
|
4010
3986
|
async appendReextractJobs(events) {
|
|
4011
3987
|
if (events.length === 0) return 0;
|
|
4012
3988
|
await this.ensureDirectories();
|
|
4013
|
-
const filePath =
|
|
3989
|
+
const filePath = path.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4014
3990
|
const lines = events.map((event) => JSON.stringify(event)).join("\n") + "\n";
|
|
4015
3991
|
try {
|
|
4016
3992
|
await this.appendStorageSecureFile(filePath, lines);
|
|
@@ -4023,7 +3999,7 @@ ${memory.content}
|
|
|
4023
3999
|
}
|
|
4024
4000
|
async readReextractJobs(limit = 200) {
|
|
4025
4001
|
const safeLimit = Number.isFinite(limit) ? Math.max(1, Math.min(1e3, Math.floor(limit))) : 200;
|
|
4026
|
-
const filePath =
|
|
4002
|
+
const filePath = path.join(this.stateDir, "reextract-jobs.jsonl");
|
|
4027
4003
|
try {
|
|
4028
4004
|
const raw = await this.readStorageSecureFile(filePath);
|
|
4029
4005
|
const lines = raw.split("\n").filter((line) => line.trim().length > 0);
|
|
@@ -4277,7 +4253,7 @@ ${memory.content}
|
|
|
4277
4253
|
const date = nowIso.slice(0, 10);
|
|
4278
4254
|
const id = this.generateId("incident");
|
|
4279
4255
|
const incident = createContinuityIncidentRecord(id, input, nowIso);
|
|
4280
|
-
const filePath =
|
|
4256
|
+
const filePath = path.join(this.identityIncidentsDir, `${date}-${id}.md`);
|
|
4281
4257
|
await this.writeStorageSecureFile(filePath, serializeContinuityIncident(incident));
|
|
4282
4258
|
return { ...incident, filePath };
|
|
4283
4259
|
}
|
|
@@ -4290,7 +4266,7 @@ ${memory.content}
|
|
|
4290
4266
|
const incidents = [];
|
|
4291
4267
|
for (const file of candidates) {
|
|
4292
4268
|
if (incidents.length >= cappedLimit) break;
|
|
4293
|
-
const filePath =
|
|
4269
|
+
const filePath = path.join(this.identityIncidentsDir, file);
|
|
4294
4270
|
try {
|
|
4295
4271
|
const raw = await this.readStorageSecureFile(filePath);
|
|
4296
4272
|
const parsed = parseContinuityIncident(raw);
|
|
@@ -4321,7 +4297,7 @@ ${memory.content}
|
|
|
4321
4297
|
await this.ensureDirectories();
|
|
4322
4298
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4323
4299
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4324
|
-
const filePath =
|
|
4300
|
+
const filePath = path.join(dir, `${safeKey}.md`);
|
|
4325
4301
|
await this.writeStorageSecureFile(filePath, content);
|
|
4326
4302
|
return filePath;
|
|
4327
4303
|
}
|
|
@@ -4329,7 +4305,7 @@ ${memory.content}
|
|
|
4329
4305
|
try {
|
|
4330
4306
|
const safeKey = this.sanitizeIdentityAuditKey(key);
|
|
4331
4307
|
const dir = period === "weekly" ? this.identityAuditsWeeklyDir : this.identityAuditsMonthlyDir;
|
|
4332
|
-
return await this.readStorageSecureFile(
|
|
4308
|
+
return await this.readStorageSecureFile(path.join(dir, `${safeKey}.md`));
|
|
4333
4309
|
} catch (err) {
|
|
4334
4310
|
if (err instanceof Error && err.message === "Invalid identity audit key") return null;
|
|
4335
4311
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -4393,12 +4369,12 @@ ${memory.content}
|
|
|
4393
4369
|
const fileNames = await this.readContinuityIncidentFileNames();
|
|
4394
4370
|
const directMatch = fileNames.find((name) => name.endsWith(`-${id}.md`));
|
|
4395
4371
|
if (directMatch) {
|
|
4396
|
-
const directPath =
|
|
4372
|
+
const directPath = path.join(this.identityIncidentsDir, directMatch);
|
|
4397
4373
|
const parsed = await this.readContinuityIncidentFile(directPath);
|
|
4398
4374
|
if (parsed?.id === id) return directPath;
|
|
4399
4375
|
}
|
|
4400
4376
|
for (const fileName of fileNames) {
|
|
4401
|
-
const filePath =
|
|
4377
|
+
const filePath = path.join(this.identityIncidentsDir, fileName);
|
|
4402
4378
|
const parsed = await this.readContinuityIncidentFile(filePath);
|
|
4403
4379
|
if (parsed?.id === id) return filePath;
|
|
4404
4380
|
}
|
|
@@ -4428,7 +4404,7 @@ ${question}
|
|
|
4428
4404
|
|
|
4429
4405
|
**Context:** ${context}
|
|
4430
4406
|
`;
|
|
4431
|
-
const filePath =
|
|
4407
|
+
const filePath = path.join(this.questionsDir, `${id}.md`);
|
|
4432
4408
|
await writeFile(filePath, content, "utf-8");
|
|
4433
4409
|
log.debug(`wrote question ${id} to ${filePath}`);
|
|
4434
4410
|
this.invalidateQuestionsCache();
|
|
@@ -4452,7 +4428,7 @@ ${question}
|
|
|
4452
4428
|
const questions = [];
|
|
4453
4429
|
for (const file of files) {
|
|
4454
4430
|
if (!file.endsWith(".md")) continue;
|
|
4455
|
-
const filePath =
|
|
4431
|
+
const filePath = path.join(this.questionsDir, file);
|
|
4456
4432
|
const raw = await readMaybeEncryptedFile(filePath, this._secureStoreKey, this.baseDir);
|
|
4457
4433
|
const parsed = this.parseQuestionFile(raw, filePath);
|
|
4458
4434
|
if (parsed) {
|
|
@@ -4475,7 +4451,7 @@ ${question}
|
|
|
4475
4451
|
if (!match) return null;
|
|
4476
4452
|
const frontmatterStr = match[1];
|
|
4477
4453
|
const body = match[2].trim();
|
|
4478
|
-
const id = this.extractFrontmatterValue(frontmatterStr, "id") ??
|
|
4454
|
+
const id = this.extractFrontmatterValue(frontmatterStr, "id") ?? path.basename(filePath, ".md");
|
|
4479
4455
|
const created = this.extractFrontmatterValue(frontmatterStr, "created") ?? "";
|
|
4480
4456
|
const priority = parseFloat(
|
|
4481
4457
|
this.extractFrontmatterValue(frontmatterStr, "priority") ?? "0.5"
|
|
@@ -4537,11 +4513,11 @@ ${question}
|
|
|
4537
4513
|
} catch {
|
|
4538
4514
|
}
|
|
4539
4515
|
const hygiene = opts?.hygiene;
|
|
4540
|
-
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(
|
|
4516
|
+
const rotateEnabled = hygiene?.enabled === true && hygiene.rotateEnabled === true && Array.isArray(hygiene.rotatePaths) && hygiene.rotatePaths.includes(path.basename(identityPath));
|
|
4541
4517
|
if (rotateEnabled) {
|
|
4542
4518
|
const maxBytes = hygiene.rotateMaxBytes;
|
|
4543
4519
|
if (existing.length > maxBytes) {
|
|
4544
|
-
const archiveDir =
|
|
4520
|
+
const archiveDir = path.join(workspaceDir, hygiene.archiveDir);
|
|
4545
4521
|
const { newContent } = await rotateMarkdownFileToArchive({
|
|
4546
4522
|
filePath: identityPath,
|
|
4547
4523
|
archiveDir,
|
|
@@ -4635,7 +4611,7 @@ ${reflection}
|
|
|
4635
4611
|
* Deduplicates by target+label.
|
|
4636
4612
|
*/
|
|
4637
4613
|
async addEntityRelationship(name, rel) {
|
|
4638
|
-
const filePath =
|
|
4614
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4639
4615
|
let entity;
|
|
4640
4616
|
try {
|
|
4641
4617
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4660,7 +4636,7 @@ ${reflection}
|
|
|
4660
4636
|
* Prepends to the beginning, prunes oldest entries beyond maxEntries.
|
|
4661
4637
|
*/
|
|
4662
4638
|
async addEntityActivity(name, entry, maxEntries) {
|
|
4663
|
-
const filePath =
|
|
4639
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4664
4640
|
let entity;
|
|
4665
4641
|
try {
|
|
4666
4642
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4683,7 +4659,7 @@ ${reflection}
|
|
|
4683
4659
|
* Add an alias to an entity file. Deduplicates.
|
|
4684
4660
|
*/
|
|
4685
4661
|
async addEntityAlias(name, alias) {
|
|
4686
|
-
const filePath =
|
|
4662
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4687
4663
|
let entity;
|
|
4688
4664
|
try {
|
|
4689
4665
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4704,7 +4680,7 @@ ${reflection}
|
|
|
4704
4680
|
* Set or rewrite the synthesis layer of an entity file.
|
|
4705
4681
|
*/
|
|
4706
4682
|
async updateEntitySynthesis(name, synthesis, options = {}) {
|
|
4707
|
-
const filePath =
|
|
4683
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4708
4684
|
let entity;
|
|
4709
4685
|
try {
|
|
4710
4686
|
const content = await this.readStorageSecureFile(filePath);
|
|
@@ -4742,7 +4718,7 @@ ${reflection}
|
|
|
4742
4718
|
const updatedAt = (/* @__PURE__ */ new Date()).toISOString();
|
|
4743
4719
|
let synthesisTimelineCount;
|
|
4744
4720
|
try {
|
|
4745
|
-
const filePath =
|
|
4721
|
+
const filePath = path.join(this.entitiesDir, `${name}.md`);
|
|
4746
4722
|
const content = await this.readStorageSecureFile(filePath);
|
|
4747
4723
|
synthesisTimelineCount = parseEntityFile(content, this.entitySchemas).timeline.length;
|
|
4748
4724
|
} catch (err) {
|
|
@@ -4825,7 +4801,7 @@ ${reflection}
|
|
|
4825
4801
|
if (!raw) continue;
|
|
4826
4802
|
const serialized = serializeEntityFile(parseEntityFile(raw, this.entitySchemas), this.entitySchemas);
|
|
4827
4803
|
if (raw.trimEnd() === serialized.trimEnd()) continue;
|
|
4828
|
-
await this.writeStorageSecureFile(
|
|
4804
|
+
await this.writeStorageSecureFile(path.join(this.entitiesDir, `${entityName}.md`), serialized);
|
|
4829
4805
|
migrated += 1;
|
|
4830
4806
|
}
|
|
4831
4807
|
if (migrated > 0) {
|
|
@@ -4861,7 +4837,7 @@ ${reflection}
|
|
|
4861
4837
|
const results = await Promise.all(
|
|
4862
4838
|
batch.map(async (entry) => {
|
|
4863
4839
|
try {
|
|
4864
|
-
return await this.readStorageSecureFile(
|
|
4840
|
+
return await this.readStorageSecureFile(path.join(this.entitiesDir, entry));
|
|
4865
4841
|
} catch (err) {
|
|
4866
4842
|
if (err instanceof SecureStoreLockedError) throw err;
|
|
4867
4843
|
if (!isErrnoCode(err, "ENOENT")) throw err;
|
|
@@ -5007,7 +4983,7 @@ ${rows.join("\n")}
|
|
|
5007
4983
|
extraSections: []
|
|
5008
4984
|
};
|
|
5009
4985
|
for (const file of files) {
|
|
5010
|
-
const filePath =
|
|
4986
|
+
const filePath = path.join(this.entitiesDir, file);
|
|
5011
4987
|
try {
|
|
5012
4988
|
const content = await this.readStorageSecureFile(filePath);
|
|
5013
4989
|
const parsed = parseEntityFile(content, this.entitySchemas);
|
|
@@ -5138,10 +5114,10 @@ ${rows.join("\n")}
|
|
|
5138
5114
|
}
|
|
5139
5115
|
mergedEntity.created = mergedEntity.created || mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
5140
5116
|
mergedEntity.updated = mergedEntity.updated || (/* @__PURE__ */ new Date()).toISOString();
|
|
5141
|
-
const canonicalPath =
|
|
5117
|
+
const canonicalPath = path.join(this.entitiesDir, `${canonical}.md`);
|
|
5142
5118
|
await this.writeStorageSecureFile(canonicalPath, serializeEntityFile(mergedEntity, this.entitySchemas));
|
|
5143
5119
|
for (const file of files) {
|
|
5144
|
-
const filePath =
|
|
5120
|
+
const filePath = path.join(this.entitiesDir, file);
|
|
5145
5121
|
if (filePath !== canonicalPath) {
|
|
5146
5122
|
try {
|
|
5147
5123
|
await unlink(filePath);
|
|
@@ -5240,7 +5216,7 @@ ${memory.content}
|
|
|
5240
5216
|
const filePaths = await this.collectActiveMemoryPaths();
|
|
5241
5217
|
const foundIds = /* @__PURE__ */ new Set();
|
|
5242
5218
|
for (const filePath of filePaths) {
|
|
5243
|
-
const basename =
|
|
5219
|
+
const basename = path.basename(filePath, ".md");
|
|
5244
5220
|
if (wantedIds.has(basename)) {
|
|
5245
5221
|
foundIds.add(basename);
|
|
5246
5222
|
if (foundIds.size === wantedIds.size) break;
|
|
@@ -5338,18 +5314,7 @@ ${memory.content}
|
|
|
5338
5314
|
|
|
5339
5315
|
${sanitized.text}
|
|
5340
5316
|
`;
|
|
5341
|
-
|
|
5342
|
-
if (category === "correction") {
|
|
5343
|
-
filePath = path2.join(this.correctionsDir, `${id}.md`);
|
|
5344
|
-
} else if (category === "procedure") {
|
|
5345
|
-
await mkdir(path2.join(this.proceduresDir, today), { recursive: true });
|
|
5346
|
-
filePath = path2.join(this.proceduresDir, today, `${id}.md`);
|
|
5347
|
-
} else if (category === "reasoning_trace") {
|
|
5348
|
-
await mkdir(path2.join(this.reasoningTracesDir, today), { recursive: true });
|
|
5349
|
-
filePath = path2.join(this.reasoningTracesDir, today, `${id}.md`);
|
|
5350
|
-
} else {
|
|
5351
|
-
filePath = path2.join(this.factsDir, today, `${id}.md`);
|
|
5352
|
-
}
|
|
5317
|
+
const filePath = await this.resolveCategoryWritePath(category, id, today);
|
|
5353
5318
|
await this.writeStorageSecureFile(filePath, fileContent);
|
|
5354
5319
|
log.debug(`wrote chunk ${id} (${chunkIndex + 1}/${chunkTotal}) to ${filePath}`);
|
|
5355
5320
|
return id;
|
|
@@ -5417,14 +5382,14 @@ Reason: ${reason}`, {
|
|
|
5417
5382
|
// Memory Summarization (Phase 4A)
|
|
5418
5383
|
// ---------------------------------------------------------------------------
|
|
5419
5384
|
get summariesDir() {
|
|
5420
|
-
return
|
|
5385
|
+
return path.join(this.baseDir, "summaries");
|
|
5421
5386
|
}
|
|
5422
5387
|
/**
|
|
5423
5388
|
* Write a memory summary.
|
|
5424
5389
|
*/
|
|
5425
5390
|
async writeSummary(summary) {
|
|
5426
5391
|
await mkdir(this.summariesDir, { recursive: true });
|
|
5427
|
-
const filePath =
|
|
5392
|
+
const filePath = path.join(this.summariesDir, `${summary.id}.json`);
|
|
5428
5393
|
await this.writeStorageSecureFile(filePath, JSON.stringify(summary, null, 2));
|
|
5429
5394
|
log.debug(`wrote summary ${summary.id}`);
|
|
5430
5395
|
}
|
|
@@ -5437,7 +5402,7 @@ Reason: ${reason}`, {
|
|
|
5437
5402
|
const summaries = [];
|
|
5438
5403
|
for (const file of files) {
|
|
5439
5404
|
if (!file.endsWith(".json")) continue;
|
|
5440
|
-
const filePath =
|
|
5405
|
+
const filePath = path.join(this.summariesDir, file);
|
|
5441
5406
|
const raw = await this.readStorageSecureFile(filePath);
|
|
5442
5407
|
summaries.push(JSON.parse(raw));
|
|
5443
5408
|
}
|
|
@@ -5498,7 +5463,7 @@ ${memory.content}
|
|
|
5498
5463
|
* Save topic scores to meta.json.
|
|
5499
5464
|
*/
|
|
5500
5465
|
async saveTopics(topics) {
|
|
5501
|
-
const metaPath =
|
|
5466
|
+
const metaPath = path.join(this.stateDir, "topics.json");
|
|
5502
5467
|
await mkdir(this.stateDir, { recursive: true });
|
|
5503
5468
|
await this.writeStorageSecureFile(metaPath, JSON.stringify({ topics, updatedAt: (/* @__PURE__ */ new Date()).toISOString() }, null, 2));
|
|
5504
5469
|
log.debug(`saved ${topics.length} topic scores`);
|
|
@@ -5507,7 +5472,7 @@ ${memory.content}
|
|
|
5507
5472
|
* Load topic scores from meta.json.
|
|
5508
5473
|
*/
|
|
5509
5474
|
async loadTopics() {
|
|
5510
|
-
const metaPath =
|
|
5475
|
+
const metaPath = path.join(this.stateDir, "topics.json");
|
|
5511
5476
|
try {
|
|
5512
5477
|
const raw = await this.readStorageSecureFile(metaPath);
|
|
5513
5478
|
return JSON.parse(raw);
|
|
@@ -5585,9 +5550,6 @@ ${memory.content}
|
|
|
5585
5550
|
};
|
|
5586
5551
|
|
|
5587
5552
|
export {
|
|
5588
|
-
ALL_CATEGORY_DIRS,
|
|
5589
|
-
ALL_CATEGORY_KEYS,
|
|
5590
|
-
getCategoryDir,
|
|
5591
5553
|
normalizeEntityName,
|
|
5592
5554
|
ContentHashIndex,
|
|
5593
5555
|
stripAttributesSuffix,
|
|
@@ -5599,4 +5561,4 @@ export {
|
|
|
5599
5561
|
serializeEntityFile,
|
|
5600
5562
|
StorageManager
|
|
5601
5563
|
};
|
|
5602
|
-
//# sourceMappingURL=chunk-
|
|
5564
|
+
//# sourceMappingURL=chunk-VH6EIKVS.js.map
|