@sdsrs/code-graph 0.59.0 → 0.61.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.
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "sdsrs"
6
6
  },
7
- "version": "0.59.0",
7
+ "version": "0.61.0",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -31,7 +31,15 @@ function readAdoptedBy(filePath) {
31
31
  function writeFileAtomic(filePath, data) {
32
32
  const tmp = filePath + '.tmp.' + process.pid;
33
33
  fs.writeFileSync(tmp, data);
34
- fs.renameSync(tmp, filePath);
34
+ try {
35
+ fs.renameSync(tmp, filePath);
36
+ } catch (e) {
37
+ // rename can fail (ENOSPC / EACCES / EROFS on the dir). Don't orphan the
38
+ // temp in the shared memory dir — mirror auto-update.js's binary promote,
39
+ // which cleans its tmp on failure. Best-effort unlink, then rethrow original.
40
+ try { fs.unlinkSync(tmp); } catch { /* already gone */ }
41
+ throw e;
42
+ }
35
43
  }
36
44
  // One-liner per MEMORY.md spec ("each entry should be one line"). All routing
37
45
  // triggers from prior multi-line block preserved verbatim — collapsing to single
@@ -105,6 +105,24 @@ test('adopt + unadopt write atomically — no .tmp residue in the memory dir', (
105
105
  } finally { sb.cleanup(); }
106
106
  });
107
107
 
108
+ test('writeFileAtomic cleans its temp file when rename fails (no orphaned .tmp)', () => {
109
+ // The success path leaves no residue (above). This pins the FAILURE path: if
110
+ // renameSync throws (ENOSPC/EACCES/EROFS on the shared memory dir) the temp must
111
+ // be unlinked, not orphaned. Force every rename to fail and assert no `.tmp.<pid>`
112
+ // survives the (failed) adopt.
113
+ const sb = makeSandbox();
114
+ const realRename = fs.renameSync;
115
+ try {
116
+ fs.renameSync = () => { const e = new Error('EROFS: simulated read-only fs'); e.code = 'EROFS'; throw e; };
117
+ try { adopt({ cwd: sb.cwd, home: sb.home }); } catch { /* expected — rename failed */ }
118
+ const residue = fs.readdirSync(sb.dir).filter((f) => f.includes('.tmp.'));
119
+ assert.deepStrictEqual(residue, [], `failed rename must not orphan a temp; found: ${residue}`);
120
+ } finally {
121
+ fs.renameSync = realRename;
122
+ sb.cleanup();
123
+ }
124
+ });
125
+
108
126
  test('adopt refuses a non-project cwd even when the memory dir already exists (regression: /tmp adoption)', () => {
109
127
  // Bug: the isProjectRoot guard was nested inside `if (!fs.existsSync(dir))`,
110
128
  // 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.59.0",
3
+ "version": "0.61.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.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"
38
+ "@sdsrs/code-graph-linux-x64": "0.61.0",
39
+ "@sdsrs/code-graph-linux-arm64": "0.61.0",
40
+ "@sdsrs/code-graph-darwin-x64": "0.61.0",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.61.0",
42
+ "@sdsrs/code-graph-win32-x64": "0.61.0"
43
43
  }
44
44
  }