@sdsrs/code-graph 0.25.1 → 0.27.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/claude-plugin/.claude-plugin/plugin.json +1 -1
- package/claude-plugin/scripts/pre-edit-guide.js +7 -2
- package/claude-plugin/scripts/user-prompt-context.js +18 -11
- package/claude-plugin/scripts/user-prompt-context.test.js +24 -38
- package/claude-plugin/templates/plugin_code_graph_mcp.md +12 -7
- package/package.json +6 -6
|
@@ -118,13 +118,18 @@ try {
|
|
|
118
118
|
process.exit(0);
|
|
119
119
|
}
|
|
120
120
|
|
|
121
|
-
// ---
|
|
121
|
+
// --- Inject when the symbol has any caller (1+) ---
|
|
122
|
+
// Earlier gate was 2+ direct callers; reality is that editing a function with
|
|
123
|
+
// even one production caller benefits from a one-line impact summary, and the
|
|
124
|
+
// per-symbol 2-minute cooldown caps frequency. The 2+ floor was a remnant of
|
|
125
|
+
// the v0.21 "agent picks tools without push" assumption — same bias mem #8234
|
|
126
|
+
// records as bounded leverage at the bench level.
|
|
122
127
|
const directCallers = jsonResult.direct_callers || 0;
|
|
123
128
|
const totalCallers = jsonResult.total_callers || 0;
|
|
124
129
|
const affectedFiles = jsonResult.affected_files || 0;
|
|
125
130
|
const risk = jsonResult.risk || 'low';
|
|
126
131
|
|
|
127
|
-
if (directCallers <
|
|
132
|
+
if (directCallers < 1) process.exit(0);
|
|
128
133
|
|
|
129
134
|
// Mark cooldown
|
|
130
135
|
try { fs.writeFileSync(cooldownFile, ''); } catch { /* ok */ }
|
|
@@ -33,23 +33,30 @@ function markCooldown(type) {
|
|
|
33
33
|
} catch { /* ok */ }
|
|
34
34
|
}
|
|
35
35
|
|
|
36
|
-
// v0.21
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
// agent
|
|
40
|
-
//
|
|
36
|
+
// Default ON. The v0.21 opt-in flip relied on routing-bench P@1=100% to argue
|
|
37
|
+
// "Sonnet 4.5 picks tools without push injection." That bench measures *triage
|
|
38
|
+
// accuracy once the agent has decided to query a tool*; it does not measure
|
|
39
|
+
// the prior question — *whether the agent reaches for a tool at all*.
|
|
40
|
+
// pre-grep-guide.js sees the real-world counter-evidence: a 15-day baseline of
|
|
41
|
+
// 429 raw `grep` vs 191 functional CLI calls on the same indexed source tree
|
|
42
|
+
// — a 13× pre-training bias toward grep. Push injection on the relevant turns
|
|
43
|
+
// is the corrective; cooldowns (impact 30s / overview 5min / callgraph 60s /
|
|
44
|
+
// search 60s) already cap per-type frequency. SessionStart `project_map` stays
|
|
45
|
+
// default OFF (lifecycle.js / session-init.js) — that one is a static dump
|
|
46
|
+
// duplicated by MEMORY.md; this hook is reactive and trigger-shaped, so the
|
|
47
|
+
// two defaults diverge intentionally.
|
|
41
48
|
//
|
|
42
49
|
// Priority (high → low):
|
|
43
|
-
// 1. CODE_GRAPH_QUIET_HOOKS=
|
|
44
|
-
// 2. CODE_GRAPH_QUIET_HOOKS=
|
|
45
|
-
// 3. CODE_GRAPH_VERBOSE_HOOKS=1 →
|
|
46
|
-
// 4. default →
|
|
50
|
+
// 1. CODE_GRAPH_QUIET_HOOKS=1 → forced quiet (escape hatch)
|
|
51
|
+
// 2. CODE_GRAPH_QUIET_HOOKS=0 → forced noisy (legacy back-compat, redundant with default)
|
|
52
|
+
// 3. CODE_GRAPH_VERBOSE_HOOKS=1 → noisy (legacy back-compat, redundant with default)
|
|
53
|
+
// 4. default → noisy
|
|
47
54
|
function computeQuietHooks(env = process.env) {
|
|
48
55
|
const envQuiet = env.CODE_GRAPH_QUIET_HOOKS;
|
|
49
|
-
if (envQuiet === '0') return false;
|
|
50
56
|
if (envQuiet === '1') return true;
|
|
57
|
+
if (envQuiet === '0') return false;
|
|
51
58
|
if (env.CODE_GRAPH_VERBOSE_HOOKS === '1') return false;
|
|
52
|
-
return
|
|
59
|
+
return false;
|
|
53
60
|
}
|
|
54
61
|
|
|
55
62
|
// --- Pure logic (exported for testing) ---
|
|
@@ -511,62 +511,48 @@ test('skills: only expected skills exist', () => {
|
|
|
511
511
|
assert.deepEqual(files, ['explore.md', 'index.md']);
|
|
512
512
|
});
|
|
513
513
|
|
|
514
|
-
|
|
515
|
-
const { spawnSync } = require('node:child_process');
|
|
516
|
-
const script = path.join(__dirname, 'user-prompt-context.js');
|
|
517
|
-
const proc = spawnSync(process.execPath, [script], {
|
|
518
|
-
input: JSON.stringify({ message: 'impact analysis for fn_that_would_trigger_search' }),
|
|
519
|
-
env: { ...process.env, CODE_GRAPH_QUIET_HOOKS: '1' },
|
|
520
|
-
encoding: 'utf8',
|
|
521
|
-
timeout: 2000,
|
|
522
|
-
});
|
|
523
|
-
// Quiet mode must be fully silent — any stderr leaks into Claude's display.
|
|
524
|
-
assert.equal(proc.stdout, '', 'stdout must be empty');
|
|
525
|
-
assert.equal(proc.stderr, '', 'stderr must be empty');
|
|
526
|
-
assert.equal(proc.status, 0, 'must exit 0');
|
|
527
|
-
});
|
|
514
|
+
// ── computeQuietHooks priority chain (default-noisy flip) ────────
|
|
528
515
|
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
//
|
|
533
|
-
//
|
|
534
|
-
assert.equal(computeQuietHooks({}),
|
|
516
|
+
test('computeQuietHooks: default (no env) is NOISY', () => {
|
|
517
|
+
// Default flipped back to push-on. The v0.21 opt-in default relied on
|
|
518
|
+
// routing-bench P@1=100% but that measures triage accuracy, not whether
|
|
519
|
+
// the agent reaches for a tool at all. pre-grep-guide.js sees 13× raw-grep
|
|
520
|
+
// bias on the same source tree — push is the corrective.
|
|
521
|
+
assert.equal(computeQuietHooks({}), false);
|
|
535
522
|
});
|
|
536
523
|
|
|
537
|
-
test('computeQuietHooks:
|
|
538
|
-
assert.equal(computeQuietHooks({
|
|
524
|
+
test('computeQuietHooks: CODE_GRAPH_QUIET_HOOKS=1 forces quiet (escape hatch)', () => {
|
|
525
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '1' }), true);
|
|
539
526
|
});
|
|
540
527
|
|
|
541
|
-
test('computeQuietHooks:
|
|
528
|
+
test('computeQuietHooks: CODE_GRAPH_QUIET_HOOKS=0 stays noisy (back-compat, same as default)', () => {
|
|
542
529
|
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0' }), false);
|
|
543
530
|
});
|
|
544
531
|
|
|
545
|
-
test('computeQuietHooks:
|
|
546
|
-
assert.equal(computeQuietHooks({
|
|
532
|
+
test('computeQuietHooks: CODE_GRAPH_VERBOSE_HOOKS=1 stays noisy (back-compat, same as default)', () => {
|
|
533
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_VERBOSE_HOOKS: '1' }), false);
|
|
547
534
|
});
|
|
548
535
|
|
|
549
|
-
test('computeQuietHooks:
|
|
550
|
-
// Priority
|
|
551
|
-
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0', CODE_GRAPH_VERBOSE_HOOKS: '0' }), false);
|
|
536
|
+
test('computeQuietHooks: QUIET_HOOKS=1 wins over VERBOSE_HOOKS=1 (priority chain)', () => {
|
|
537
|
+
// Priority: CODE_GRAPH_QUIET_HOOKS=1 (escape) > QUIET_HOOKS=0 / VERBOSE_HOOKS=1 > default.
|
|
552
538
|
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '1', CODE_GRAPH_VERBOSE_HOOKS: '1' }), true);
|
|
539
|
+
assert.equal(computeQuietHooks({ CODE_GRAPH_QUIET_HOOKS: '0', CODE_GRAPH_VERBOSE_HOOKS: '0' }), false);
|
|
553
540
|
});
|
|
554
541
|
|
|
555
|
-
test('
|
|
556
|
-
// End-to-end
|
|
557
|
-
//
|
|
542
|
+
test('CODE_GRAPH_QUIET_HOOKS=1 short-circuits silently on stdout, stderr, exit 0 (escape hatch verified end-to-end)', () => {
|
|
543
|
+
// End-to-end: the escape hatch must produce zero stdout/stderr noise
|
|
544
|
+
// (any leak would land in Claude's display). Was the only e2e check before
|
|
545
|
+
// the default-noisy flip — kept under the new default to guarantee that
|
|
546
|
+
// setting the env still fully silences the hook.
|
|
558
547
|
const { spawnSync } = require('node:child_process');
|
|
559
548
|
const script = path.join(__dirname, 'user-prompt-context.js');
|
|
560
|
-
const cleanEnv = { ...process.env };
|
|
561
|
-
delete cleanEnv.CODE_GRAPH_QUIET_HOOKS;
|
|
562
|
-
delete cleanEnv.CODE_GRAPH_VERBOSE_HOOKS;
|
|
563
549
|
const proc = spawnSync(process.execPath, [script], {
|
|
564
550
|
input: JSON.stringify({ message: 'impact of refactoring parse_code function' }),
|
|
565
|
-
env:
|
|
551
|
+
env: { ...process.env, CODE_GRAPH_QUIET_HOOKS: '1' },
|
|
566
552
|
encoding: 'utf8',
|
|
567
553
|
timeout: 2000,
|
|
568
554
|
});
|
|
569
|
-
assert.equal(proc.stdout, '', '
|
|
570
|
-
assert.equal(proc.stderr, '', '
|
|
571
|
-
assert.equal(proc.status, 0, '
|
|
555
|
+
assert.equal(proc.stdout, '', 'quiet must be silent on stdout');
|
|
556
|
+
assert.equal(proc.stderr, '', 'quiet must be silent on stderr');
|
|
557
|
+
assert.equal(proc.status, 0, 'quiet must exit 0');
|
|
572
558
|
});
|
|
@@ -15,12 +15,16 @@ type: reference
|
|
|
15
15
|
> 的最新决策表(本文件 SHA 与 template 差异时覆盖)。手动编辑会被覆盖——
|
|
16
16
|
> 要锁定自己的版本,设 `CODE_GRAPH_NO_TEMPLATE_REFRESH=1`(不影响首次 adopt)。
|
|
17
17
|
>
|
|
18
|
-
> **
|
|
19
|
-
>
|
|
20
|
-
> dump ≈2.3 KB
|
|
21
|
-
>
|
|
22
|
-
>
|
|
23
|
-
>
|
|
18
|
+
> **Hook 默认值(两个 hook,默认不同 —— 故意的)**:
|
|
19
|
+
> - **SessionStart `project_map` 注入:默认 OFF**(v0.17.0 起)。本文件 + 7 个
|
|
20
|
+
> 工具描述已经覆盖路由所需决策信息,每次会话再 dump ≈2.3 KB 项目地图是冗余的
|
|
21
|
+
> 常驻上下文。显式启用:`CODE_GRAPH_VERBOSE_HOOKS=1`;或按需 `code-graph-mcp map --compact`。
|
|
22
|
+
> - **UserPromptSubmit context push:默认 ON**。基于用户消息 intent 推 impact /
|
|
23
|
+
> overview / callgraph / search 结果(per-type cooldown 30s–5min)。routing-bench
|
|
24
|
+
> P@1=100% 测的是分诊准确率(已决定查工具时选哪个),不等于触发率(是否
|
|
25
|
+
> 决定查工具)—— 真实 baseline 是 raw-grep ≈13× 偏向于内置 Grep。Push 是
|
|
26
|
+
> pre-training bias 的矫正。Escape hatch:`CODE_GRAPH_QUIET_HOOKS=1`。
|
|
27
|
+
> - 优先级:`CODE_GRAPH_QUIET_HOOKS=1` (escape) > 其他 env > 默认。
|
|
24
28
|
>
|
|
25
29
|
> **v0.18.4 起**:原"进阶 5"(impact / similar / deps / dead-code / trace)已折叠
|
|
26
30
|
> 进核心 7 的 flag —— Claude Code 现在能直接通过 MCP 调用,不必落到 CLI:
|
|
@@ -122,4 +126,5 @@ code-graph-mcp health-check # 索引健康
|
|
|
122
126
|
- `CODE_GRAPH_NO_AUTO_ADOPT=1`(`~/.claude/settings.json` env) — 阻止未来自动 adopt,不影响已 adopted 状态。
|
|
123
127
|
- `CODE_GRAPH_NO_TEMPLATE_REFRESH=1`(v0.11.0+) — 锁定本文件不随插件升级刷新;允许手动编辑长久保留。
|
|
124
128
|
- `CODE_GRAPH_VERBOSE_HOOKS=1`(v0.17.0+) — opt in 到 SessionStart `project_map` 注入(默认 OFF)。
|
|
125
|
-
- `CODE_GRAPH_QUIET_HOOKS=
|
|
129
|
+
- `CODE_GRAPH_QUIET_HOOKS=1` — UserPromptSubmit context push 的 escape hatch(默认 ON);同时强制 SessionStart `project_map` quiet。
|
|
130
|
+
- `CODE_GRAPH_QUIET_HOOKS=0` — 强制恢复 SessionStart `project_map` 注入(向后兼容路径)。
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sdsrs/code-graph",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.27.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.27.0",
|
|
39
|
+
"@sdsrs/code-graph-linux-arm64": "0.27.0",
|
|
40
|
+
"@sdsrs/code-graph-darwin-x64": "0.27.0",
|
|
41
|
+
"@sdsrs/code-graph-darwin-arm64": "0.27.0",
|
|
42
|
+
"@sdsrs/code-graph-win32-x64": "0.27.0"
|
|
43
43
|
}
|
|
44
44
|
}
|