@sdsrs/code-graph 0.145.0 → 0.146.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.0",
7
+ "version": "0.146.0",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -1,6 +1,5 @@
1
1
  {
2
- "description": "code-graph-mcp hooks — only SessionStart is loaded by Claude Code from plugin-cache. All other event types are registered by lifecycle.js into ~/.claude/settings.json (v0.32.0+).",
3
- "_note": "Empirical 2026-05-24: current Claude Code only loads SessionStart entries from plugin-cache hooks.json. PreToolUse / PostToolUse / UserPromptSubmit / Stop / SessionEnd entries here are SILENTLY IGNORED. lifecycle.js install/update writes those to ~/.claude/settings.json instead (pattern from claude-mem-lite). Re-adding non-SessionStart entries here would NOT make them fire — they would just be dead config. See feedback_pretooluse_dark_under_green_health.md for the jsonl evidence chain.",
2
+ "description": "code-graph-mcp hooks — only SessionStart is loaded by Claude Code from plugin-cache; PreToolUse / PostToolUse / UserPromptSubmit / Stop / SessionEnd entries here are SILENTLY IGNORED (empirical 2026-05-24). lifecycle.js install/update registers those into ~/.claude/settings.json instead (v0.32.0+), so re-adding them here would be dead config, not a second chance — pinned by the SessionStart-only guard in hooks.test.js. Keep this file to the keys Claude Code's schema allows (description, hooks, modules, surface); anything else is warned about at startup and dropped.",
4
3
  "hooks": {
5
4
  "SessionStart": [
6
5
  {
@@ -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.0 code-graph-mcp snapshot create --out snapshot.db
38
+ npx -y -p @sdsrs/code-graph@0.146.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.0",
3
+ "version": "0.146.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.0",
39
- "@sdsrs/code-graph-linux-arm64": "0.145.0",
40
- "@sdsrs/code-graph-darwin-x64": "0.145.0",
41
- "@sdsrs/code-graph-darwin-arm64": "0.145.0",
42
- "@sdsrs/code-graph-win32-x64": "0.145.0"
38
+ "@sdsrs/code-graph-linux-x64": "0.146.0",
39
+ "@sdsrs/code-graph-linux-arm64": "0.146.0",
40
+ "@sdsrs/code-graph-darwin-x64": "0.146.0",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.146.0",
42
+ "@sdsrs/code-graph-win32-x64": "0.146.0"
43
43
  }
44
44
  }