@sdsrs/code-graph 0.128.0 → 0.129.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.
package/README.md CHANGED
@@ -55,17 +55,18 @@ Every design decision — from token-aware compression to node_id-based snippet
55
55
  ## Performance
56
56
 
57
57
  Every row below is a line `code-graph-mcp benchmark` prints, measured on this
58
- repository (278 files, 5,065 nodes, 10,731 edges) with a release build. Run the
59
- same command on your own project the numbers that matter are yours, and these
60
- scale with tree size and machine.
58
+ repository (283 files, 5,311 nodes, 11,215 edges) with a release build median
59
+ of three consecutive runs on an otherwise idle machine. Run the same command on
60
+ your own project: the numbers that matter are yours, and these scale with tree
61
+ size and machine.
61
62
 
62
- | `benchmark` line | This repo, v0.123.0 |
63
+ | `benchmark` line | This repo, v0.129.0 |
63
64
  |--------|-------|
64
- | Full index | **~1.9s** (≈145 files/second, single-threaded) |
65
- | Incremental (noop) | **~30ms** no-change detection via BLAKE3 Merkle tree |
66
- | Query latency P50 / P99 | **~575us / ~1.9ms** |
67
- | DB size | **~21.8MB** (≈4.4MB per 1,000 nodes) |
68
- | Avg tokens/node | **~239** |
65
+ | Full index | **~2.0s** (≈139 files/second, single-threaded) |
66
+ | Incremental (noop) | **~28ms** no-change detection via BLAKE3 Merkle tree |
67
+ | Query latency P50 / P99 | **~655us / ~2.1ms** |
68
+ | DB size | **~22.4MB** (≈4.2MB per 1,000 nodes) |
69
+ | Avg tokens/node | **~242** |
69
70
 
70
71
  ## Efficiency: code-graph vs Traditional Tools
71
72
 
@@ -286,6 +287,18 @@ code-graph-mcp uninstall # restore statusline, strip hooks, drop the cache
286
287
  npm uninstall -g @sdsrs/code-graph
287
288
  ```
288
289
 
290
+ ### Built from source (cargo)
291
+
292
+ `uninstall` lives in the npm wrapper, so a `cargo install` / `cargo build` binary
293
+ does not carry it — that binary tells you as much and points here. Run the
294
+ teardown through npx without installing globally (npx still downloads the package
295
+ and its platform binary into the npm cache), then remove your binary:
296
+
297
+ ```bash
298
+ npx -y @sdsrs/code-graph uninstall # statusline, hooks, cache
299
+ cargo uninstall code-graph-mcp # or delete the target/release binary
300
+ ```
301
+
289
302
  ## MCP Tools
290
303
 
291
304
  `tools/list` advertises exactly these seven. Several older niche tools were folded into flags on them, so one call now covers what used to take a separate tool:
@@ -338,6 +351,7 @@ All tools are also available as CLI subcommands for shell scripts, hooks, and te
338
351
  | `doctor` | — | Diagnose and repair environment issues |
339
352
  | `adopt` | — | Install the steering block into the project `CLAUDE.md` + detail doc |
340
353
  | `unadopt` | — | Remove the steering block + detail doc |
354
+ | `uninstall` | — | Full local teardown (statusline, hooks, cache). npm/npx installs only — a `cargo install` build prints where to get it |
341
355
  | `serve` | — | Start the MCP JSON-RPC server on stdio (the default with no subcommand) |
342
356
 
343
357
  Common options: `--json` (JSON output), `--compact` (compact output), `--limit N`, `--depth N`, `--file <path>`.
@@ -4,7 +4,7 @@
4
4
  "author": {
5
5
  "name": "sdsrs"
6
6
  },
7
- "version": "0.128.0",
7
+ "version": "0.129.0",
8
8
  "keywords": [
9
9
  "code-graph",
10
10
  "ast",
@@ -1,12 +1,15 @@
1
1
  ---
2
2
  name: code-explorer
3
3
  description: Deep code understanding expert using AST knowledge graph. Use when exploring unfamiliar code, tracing complex relationships, or understanding module architecture.
4
- tools: ["Read", "Grep", "Glob", "Bash", "mcp__code-graph__semantic_code_search", "mcp__code-graph__get_call_graph", "mcp__code-graph__get_ast_node", "mcp__code-graph__project_map", "mcp__code-graph__module_overview", "mcp__code-graph__ast_search", "mcp__code-graph__find_references"]
4
+ tools: ["Read", "Grep", "Glob", "Bash", "mcp__code-graph__semantic_code_search", "mcp__code-graph__get_call_graph", "mcp__code-graph__get_ast_node", "mcp__code-graph__project_map", "mcp__code-graph__module_overview", "mcp__code-graph__ast_search", "mcp__code-graph__find_references", "mcp__plugin_code-graph-mcp_code-graph__semantic_code_search", "mcp__plugin_code-graph-mcp_code-graph__get_call_graph", "mcp__plugin_code-graph-mcp_code-graph__get_ast_node", "mcp__plugin_code-graph-mcp_code-graph__project_map", "mcp__plugin_code-graph-mcp_code-graph__module_overview", "mcp__plugin_code-graph-mcp_code-graph__ast_search", "mcp__plugin_code-graph-mcp_code-graph__find_references"]
5
5
  model: sonnet
6
6
  ---
7
7
 
8
8
  You are a code exploration specialist with access to an AST knowledge graph.
9
9
 
10
+ <!-- The tool allowlist carries both MCP namespace spellings on purpose (DOC-07);
11
+ rationale in CHANGELOG. Delete at most one half, never both. -->
12
+
10
13
  ## Strategy
11
14
 
12
15
  1. **Start with semantic_code_search** to locate relevant code by meaning, or **module_overview** / **project_map** to map an unfamiliar directory or the whole repo
@@ -4,7 +4,7 @@
4
4
  "hooks": {
5
5
  "SessionStart": [
6
6
  {
7
- "matcher": "startup|clear|compact",
7
+ "matcher": "startup|clear|compact|resume",
8
8
  "hooks": [
9
9
  {
10
10
  "type": "command",
@@ -507,9 +507,23 @@ function cachedBinaryStaleVsState(state, { binaryPath = cachedBinaryPath(), read
507
507
  * install dropped the platform package).
508
508
  *
509
509
  * Returns true on successful promote, false otherwise. Never throws.
510
+ *
511
+ * JS-03: gated on `cachedBinaryNeedsUpdate` so an already-current binary is
512
+ * never re-fetched. The gate lives HERE rather than at the call sites because
513
+ * all four of them wanted it: `downloadAndInstall` Step 2 called this
514
+ * unconditionally, and its two early-return arms (no plugin tarball / tarball
515
+ * integrity failure) call it again on the way out. On the normal update path
516
+ * the binary really is behind, so the gate is a no-op; it pays off on every
517
+ * REPEATED round — e.g. the JS-02 treadmill, where a blocked repoint replayed
518
+ * `downloadAndInstall` about every 30 minutes and each replay re-downloaded and
519
+ * re-promoted a ~40 MB binary that was already latest.
520
+ *
521
+ * `needsUpdate` is injectable for tests only; production always uses the real
522
+ * predicate. Returning false on a skip is accurate: nothing was updated.
510
523
  */
511
- async function downloadBinary(latest) {
524
+ async function downloadBinary(latest, { needsUpdate = cachedBinaryNeedsUpdate } = {}) {
512
525
  if (!latest || !latest.binaryUrl) return false;
526
+ if (!needsUpdate(latest)) return false; // already at latest.version — no fetch
513
527
  if (!commandExists('curl')) {
514
528
  console.error('[code-graph] Binary download skipped: curl not on PATH.');
515
529
  return false;
@@ -12,6 +12,10 @@ const { readBinaryVersion, isDevMode, getNewestMtime } = require('./version-util
12
12
  const { maybeAutoAdopt, isAdopted, unadopt } = require('./adopt');
13
13
  const { isNonProjectCwd } = require('./project-detect');
14
14
  const { hidden } = require('./proc-opts');
15
+ // Module scope on purpose: `detectHookDark` reads it inside a try/catch that
16
+ // treats any throw as "nothing to conclude", so a lazy require in there would
17
+ // turn a resolution failure into a silent disable (pre-tag review, JS-08).
18
+ const { resolveProjectRoot } = require('./project-root');
15
19
 
16
20
  // v0.17.0 — quietHooks: unconditional quiet 默认。
17
21
  // 项目地图与 MEMORY.md plugin contract + on-demand `project_map` 工具高度重叠,
@@ -954,7 +958,20 @@ function analyzeHookDark(recText) {
954
958
 
955
959
  function detectHookDark() {
956
960
  try {
957
- const recPath = path.join(process.cwd(), '.code-graph', 'recommendations.jsonl');
961
+ // JS-08 (audit 2026-08-29). Every WRITER of this file records into the
962
+ // RESOLVED root — subdir cwd walks up to the project root, a linked worktree
963
+ // reads the main checkout's index — while this reader used a bare
964
+ // `process.cwd()`. So in exactly the sessions the subdir-cwd fix exists for,
965
+ // the dark DETECTOR was itself dark: no file at that path, no claim made,
966
+ // nothing said. `resolveProjectRoot` returns null when nothing on the walk is
967
+ // indexed; cwd remains the fallback for that case (unchanged behaviour).
968
+ //
969
+ // Required at module scope (see top of file), not here: inside this
970
+ // try/catch a module-resolution failure would be indistinguishable from
971
+ // "no recommendations.jsonl", which is the silent-disable shape this whole
972
+ // finding is about. The sibling hooks all require it at top level too.
973
+ const root = resolveProjectRoot(process.cwd()) || process.cwd();
974
+ const recPath = path.join(root, '.code-graph', 'recommendations.jsonl');
958
975
  return analyzeHookDark(fs.readFileSync(recPath, 'utf8'));
959
976
  } catch { return null; } // no recommendations.jsonl → nothing to conclude
960
977
  }
@@ -2,8 +2,8 @@
2
2
  name: index
3
3
  description: |
4
4
  Diagnose and fix code-graph index issues. Use when: search returns unexpected/empty
5
- results, or after major codebase restructuring. These management commands are NOT
6
- exposed via MCP tools — this skill is the only way to access them.
5
+ results, or after major codebase restructuring. Covers the health check and both
6
+ rebuild paths from the CLI.
7
7
  ---
8
8
 
9
9
  # Index Maintenance
@@ -20,5 +20,15 @@ code-graph-mcp incremental-index
20
20
 
21
21
  ## Full rebuild (when incremental isn't enough)
22
22
  ```bash
23
- rm -rf .code-graph/ && code-graph-mcp incremental-index
23
+ code-graph-mcp rebuild-index --confirm
24
24
  ```
25
+
26
+ This builds the new index in a temporary location and swaps it in with an atomic
27
+ rename, so a running MCP server (and its open WAL) never observes a half-built
28
+ index. Deleting the `.code-graph/` directory by hand skips that swap, which is
29
+ the exact situation the atomic path exists for.
30
+
31
+ `get_index_status` and `rebuild_index` do dispatch over JSON-RPC, but they are
32
+ deliberately kept out of `tools/list` to save tokens (`src/mcp/tools.rs`), so
33
+ they are not in your callable tool set — the CLI above is the surface you have.
34
+ It is also the only one that works with no server running.
@@ -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.128.0 code-graph-mcp snapshot create --out snapshot.db
38
+ npx -y -p @sdsrs/code-graph@0.129.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.128.0",
3
+ "version": "0.129.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.128.0",
39
- "@sdsrs/code-graph-linux-arm64": "0.128.0",
40
- "@sdsrs/code-graph-darwin-x64": "0.128.0",
41
- "@sdsrs/code-graph-darwin-arm64": "0.128.0",
42
- "@sdsrs/code-graph-win32-x64": "0.128.0"
38
+ "@sdsrs/code-graph-linux-x64": "0.129.0",
39
+ "@sdsrs/code-graph-linux-arm64": "0.129.0",
40
+ "@sdsrs/code-graph-darwin-x64": "0.129.0",
41
+ "@sdsrs/code-graph-darwin-arm64": "0.129.0",
42
+ "@sdsrs/code-graph-win32-x64": "0.129.0"
43
43
  }
44
44
  }