@sdsrs/code-graph 0.145.1 → 0.147.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.145.1",
7
+ "version": "0.147.0",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -18,15 +18,33 @@ const { acquireLock } = require('./install-lock');
18
18
 
19
19
  // ── Environment Checks ────────────────────────────────────
20
20
 
21
+ // `which`/`where` walks every PATH entry, so a slow network mount on PATH drags
22
+ // the probe out with it. Not a hook-budget path, but `downloadAndInstall` holds
23
+ // INSTALL_LOCK_FILE across its probes and that lock is only reclaimed after 10
24
+ // minutes, so an unbounded probe parks installs and self-heal for every other
25
+ // session too. 5s is far above any real PATH walk and far below that window
26
+ // (audit 2026-09-07 JS-21).
27
+ //
28
+ // What this does NOT fix, stated because the first version of this comment
29
+ // claimed it did: a mount that is HUNG rather than slow leaves the child in
30
+ // uninterruptible sleep, where neither the timeout's signal nor anything else
31
+ // in userspace reaches it. The bound covers slow; it cannot cover wedged.
32
+ // `killSignal` is opted in per `proc-opts.js`'s rule — it is deliberately not a
33
+ // `hidden()` default, and a hang-prone child is exactly the case it names — so
34
+ // the probe does not additionally wait out SIGTERM's grace period.
35
+ const PATH_PROBE_TIMEOUT_MS = 5000;
36
+
21
37
  /**
22
38
  * Check if a command-line tool is available on the system PATH.
23
39
  * @param {string} cmd - Command name (e.g., 'curl', 'tar')
40
+ * @param {{exec?: Function, timeoutMs?: number}} [opts] - Injection seam for tests,
41
+ * same shape as `refreshMarketplaceClone`.
24
42
  * @returns {boolean}
25
43
  */
26
- function commandExists(cmd) {
44
+ function commandExists(cmd, { exec = execFileSync, timeoutMs = PATH_PROBE_TIMEOUT_MS } = {}) {
27
45
  try {
28
46
  const whichCmd = process.platform === 'win32' ? 'where' : 'which';
29
- execFileSync(whichCmd, [cmd], hidden({ stdio: 'ignore' }));
47
+ exec(whichCmd, [cmd], hidden({ stdio: 'ignore', timeout: timeoutMs, killSignal: 'SIGKILL' }));
30
48
  return true;
31
49
  } catch {
32
50
  return false;
@@ -249,7 +267,14 @@ function isUpdateSuspended(state) {
249
267
  // keeps the 6h steady-state interval.
250
268
  function shouldCheck(state, { force = false, binaryMissing = false, binaryStale = false } = {}) {
251
269
  if (!state.lastCheck) return true;
252
- const elapsed = Date.now() - new Date(state.lastCheck).getTime();
270
+ // A truncated or hand-edited `lastCheck` that Date cannot parse yields NaN,
271
+ // and NaN fails EVERY `elapsed >= X` below — including the `force` arm, the
272
+ // one bypass a user has. The updater then never checks again while `doctor`,
273
+ // reading the same file, still reports up-to-date. Treat unreadable as "no
274
+ // idea when, assume long ago", which is what a MISSING lastCheck already does
275
+ // one line up (audit 2026-09-07 JS-22).
276
+ const lastCheckMs = new Date(state.lastCheck).getTime();
277
+ const elapsed = Number.isFinite(lastCheckMs) ? Date.now() - lastCheckMs : Infinity;
253
278
  if (state.rateLimited) return elapsed >= RATE_LIMIT_INTERVAL_MS;
254
279
  if (binaryMissing) return true;
255
280
  if (!isUpdateSuspended(state)) {
@@ -35,7 +35,7 @@ jobs:
35
35
  node-version: '20'
36
36
  - name: Build snapshot
37
37
  run: |
38
- npx -y -p @sdsrs/code-graph@0.145.1 code-graph-mcp snapshot create --out snapshot.db
38
+ npx -y -p @sdsrs/code-graph@0.147.0 code-graph-mcp snapshot create --out snapshot.db
39
39
  zstd -9 snapshot.db -o snapshot.db.zst
40
40
  mv snapshot.db.zst "code-graph-snapshot-${GITHUB_SHA:0:7}.db.zst"
41
41
  - name: Upload to release
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@sdsrs/code-graph",
3
- "version": "0.145.1",
3
+ "version": "0.147.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.145.1",
39
- "@sdsrs/code-graph-linux-arm64": "0.145.1",
40
- "@sdsrs/code-graph-darwin-x64": "0.145.1",
41
- "@sdsrs/code-graph-darwin-arm64": "0.145.1",
42
- "@sdsrs/code-graph-win32-x64": "0.145.1"
38
+ "@sdsrs/code-graph-linux-x64": "0.147.0",
39
+ "@sdsrs/code-graph-linux-arm64": "0.147.0",
40
+ "@sdsrs/code-graph-darwin-x64": "0.147.0",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.147.0",
42
+ "@sdsrs/code-graph-win32-x64": "0.147.0"
43
43
  }
44
44
  }