@sdsrs/code-graph 0.58.0 → 0.59.0
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.
|
@@ -24,6 +24,15 @@ function readAdoptedBy(filePath) {
|
|
|
24
24
|
return m ? m[1] : null;
|
|
25
25
|
} catch { return null; }
|
|
26
26
|
}
|
|
27
|
+
// Atomic write (tmp in same dir → rename) so a crash mid-write can't leave a
|
|
28
|
+
// half-written MEMORY.md / detail file — the dir is shared with claude-mem-lite,
|
|
29
|
+
// which reads MEMORY.md on every keyword match. Mirrors lifecycle.js
|
|
30
|
+
// writeJsonAtomic / auto-update.js binary promote; accepts a string or Buffer.
|
|
31
|
+
function writeFileAtomic(filePath, data) {
|
|
32
|
+
const tmp = filePath + '.tmp.' + process.pid;
|
|
33
|
+
fs.writeFileSync(tmp, data);
|
|
34
|
+
fs.renameSync(tmp, filePath);
|
|
35
|
+
}
|
|
27
36
|
// One-liner per MEMORY.md spec ("each entry should be one line"). All routing
|
|
28
37
|
// triggers from prior multi-line block preserved verbatim — collapsing to single
|
|
29
38
|
// line is a structural fix, not a signal change. Decision table lives in the
|
|
@@ -354,7 +363,7 @@ function adopt({ cwd, home, templatePath } = {}) {
|
|
|
354
363
|
// ADOPTED_BY_RE strip below).
|
|
355
364
|
const tplBody = fs.readFileSync(tpl);
|
|
356
365
|
const marker = Buffer.from(`<!-- adopted-by: ${effectiveCwd} -->\n`);
|
|
357
|
-
|
|
366
|
+
writeFileAtomic(target, Buffer.concat([marker, tplBody]));
|
|
358
367
|
|
|
359
368
|
const indexPath = path.join(dir, 'MEMORY.md');
|
|
360
369
|
const index = fs.existsSync(indexPath) ? fs.readFileSync(indexPath, 'utf8') : '# Memory Index\n';
|
|
@@ -372,7 +381,7 @@ function adopt({ cwd, home, templatePath } = {}) {
|
|
|
372
381
|
const cleaned = stripSentinelBlock(index);
|
|
373
382
|
const healed = cleaned !== index;
|
|
374
383
|
const base = cleaned.endsWith('\n') ? cleaned : cleaned + '\n';
|
|
375
|
-
|
|
384
|
+
writeFileAtomic(indexPath, base + desiredBlock + '\n');
|
|
376
385
|
return { ok: true, target, indexPath, indexed: true, healed, collisionWith };
|
|
377
386
|
}
|
|
378
387
|
|
|
@@ -479,7 +488,7 @@ function unadopt({ cwd, home } = {}) {
|
|
|
479
488
|
const before = fs.readFileSync(indexPath, 'utf8');
|
|
480
489
|
const after = stripSentinelBlock(before);
|
|
481
490
|
if (after !== before) {
|
|
482
|
-
|
|
491
|
+
writeFileAtomic(indexPath, after);
|
|
483
492
|
indexPruned = true;
|
|
484
493
|
}
|
|
485
494
|
}
|
|
@@ -90,6 +90,21 @@ test('adopt preserves existing MEMORY.md content and appends', () => {
|
|
|
90
90
|
} finally { sb.cleanup(); }
|
|
91
91
|
});
|
|
92
92
|
|
|
93
|
+
test('adopt + unadopt write atomically — no .tmp residue in the memory dir', () => {
|
|
94
|
+
// The memory dir is shared with claude-mem-lite, which reads MEMORY.md on
|
|
95
|
+
// every keyword match; a non-atomic write crashing mid-flight would corrupt
|
|
96
|
+
// it. adopt/unadopt now go through writeFileAtomic (tmp + rename). Proof the
|
|
97
|
+
// rename completed cleanly across all three write sites (detail file + adopt
|
|
98
|
+
// index + unadopt prune): no leftover `*.tmp.<pid>` entries.
|
|
99
|
+
const sb = makeSandbox();
|
|
100
|
+
try {
|
|
101
|
+
adopt({ cwd: sb.cwd, home: sb.home });
|
|
102
|
+
unadopt({ cwd: sb.cwd, home: sb.home });
|
|
103
|
+
const residue = fs.readdirSync(sb.dir).filter((f) => f.includes('.tmp.'));
|
|
104
|
+
assert.deepStrictEqual(residue, [], `no atomic-write tmp residue; found: ${residue}`);
|
|
105
|
+
} finally { sb.cleanup(); }
|
|
106
|
+
});
|
|
107
|
+
|
|
93
108
|
test('adopt refuses a non-project cwd even when the memory dir already exists (regression: /tmp adoption)', () => {
|
|
94
109
|
// Bug: the isProjectRoot guard was nested inside `if (!fs.existsSync(dir))`,
|
|
95
110
|
// so when Claude Code had already created ~/.claude/projects/<slug>/memory
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.59.0",
|
|
4
4
|
"description": "MCP server that indexes codebases into an AST knowledge graph with semantic search, call graph traversal, and HTTP route tracing",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"repository": {
|
|
@@ -35,10 +35,10 @@
|
|
|
35
35
|
"node": ">=16"
|
|
36
36
|
},
|
|
37
37
|
"optionalDependencies": {
|
|
38
|
-
"@sdsrs/code-graph-linux-x64": "0.
|
|
39
|
-
"@sdsrs/code-graph-linux-arm64": "0.
|
|
40
|
-
"@sdsrs/code-graph-darwin-x64": "0.
|
|
41
|
-
"@sdsrs/code-graph-darwin-arm64": "0.
|
|
42
|
-
"@sdsrs/code-graph-win32-x64": "0.
|
|
38
|
+
"@sdsrs/code-graph-linux-x64": "0.59.0",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.59.0",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.59.0",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.59.0",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.59.0"
|
|
43
43
|
}
|
|
44
44
|
}
|