Skip to content

Commit c20d0ac

Browse files
sdsrssclaude
andcommitted
feat(integration): scene-driven tool descriptions, hook improvements, and UX fixes
- MCP tool descriptions: all 12 tools now have "Use when:" trigger conditions for improved Claude Code auto-invocation (scene-driven > functional descriptions) - MCP instructions: add 7 intent→tool decision rules mapping user goals to tools - Skill/command descriptions: all 5 commands updated with "Use when:" triggers - CLI: add --refs/--impact short aliases for show command - MCP get_ast_node: add include_tests parameter, filter test callers by default (consistent with CLI show --include-refs behavior) - Pre-edit hook: grep-based fallback detects containing function for body edits (previously only triggered on function signature lines) - User-prompt hook: backtick symbol extraction for mixed Chinese+code prompts - JSON safety: replace manual string escaping with serde_json in error responses - Help text: show --refs/--impact as primary flags, expand --include-tests scope Breaking: overview/trace/deps exit code 1 (was 0) when no results found. This is semantically correct (no-match = error) but may affect external scripts. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 3ff2541 commit c20d0ac

22 files changed

Lines changed: 244 additions & 58 deletions

File tree

.claude-plugin/marketplace.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
},
66
"metadata": {
77
"description": "AST knowledge graph plugin for Claude Code — semantic search, call graph, HTTP tracing, impact analysis",
8-
"version": "0.7.13"
8+
"version": "0.7.14"
99
},
1010
"plugins": [
1111
{
1212
"name": "code-graph-mcp",
1313
"source": "./claude-plugin",
1414
"description": "AST knowledge graph for intelligent code navigation — auto-indexes your codebase and provides semantic search, call graph traversal, HTTP route tracing, and impact analysis via MCP tools",
15-
"version": "0.7.13",
15+
"version": "0.7.14",
1616
"author": {
1717
"name": "sdsrs"
1818
},

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "code-graph-mcp"
3-
version = "0.7.13"
3+
version = "0.7.14"
44
edition = "2021"
55

66
[features]

claude-plugin/.claude-plugin/plugin.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
"author": {
55
"name": "sdsrs"
66
},
7-
"version": "0.7.13",
7+
"version": "0.7.14",
88
"keywords": [
99
"code-graph",
1010
"ast",

claude-plugin/commands/impact.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Analyze impact scope before modifying a symbol
2+
description: Analyze blast radius before modifying a symbol. Use when about to edit/rename/remove a function, or asked about change risk and affected callers.
33
argument-hint: <symbol_name>
44
---
55

claude-plugin/commands/rebuild.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Force a full code-graph index rebuild
2+
description: Force code-graph index rebuild. Use when search results seem stale or wrong, after major codebase restructuring, or when index health check reports issues.
33
---
44

55
Run via Bash: `code-graph-mcp incremental-index`

claude-plugin/commands/status.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Show code-graph index status
2+
description: Show code-graph index health and coverage. Use when search returns unexpected results, checking if index is current, or diagnosing code-graph issues.
33
---
44

55
!`code-graph-mcp health-check --format json 2>/dev/null || echo '{"error":"No index found"}'`

claude-plugin/commands/trace.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Trace call flow from a handler or route
2+
description: Trace call flow from a handler or route. Use when debugging API behavior, understanding request processing flow, or asked how an endpoint works.
33
argument-hint: <handler_or_route>
44
---
55

claude-plugin/commands/understand.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
---
2-
description: Deep dive into a module or file's architecture
2+
description: Deep dive into a module's architecture. Use when starting work in an unfamiliar area, asked to explain how code works, or before implementing changes in a module.
33
argument-hint: <file_or_dir_path>
44
---
55

claude-plugin/scripts/pre-edit-guide.js

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,45 @@ for (const pat of fnPatterns) {
4747
}
4848
}
4949

50+
// Fallback: if old_string is inside a function body (not a definition),
51+
// extract a unique identifier from the code and grep for it to find the containing function
52+
if (!symbol || symbol.length < 3) {
53+
const filePath = (input.tool_input && input.tool_input.file_path) || '';
54+
if (filePath && oldStr.length >= 10) {
55+
try {
56+
// Extract identifiers from old_string, try the most specific one first
57+
const identifiers = (oldStr.match(/\b([a-z]\w*(?:_\w+)+|[a-z]\w*(?:[A-Z]\w*)+|[A-Z]\w+\.\w+|[A-Z]\w+::\w+)\b/g) || [])
58+
.filter(id => id.length >= 6);
59+
const skipWords = new Set(['return', 'function', 'default', 'require', 'module', 'exports', 'import', 'console']);
60+
// Sort by length descending (longer = more specific = fewer matches)
61+
const candidates = [...new Set(identifiers)]
62+
.filter(id => !skipWords.has(id.toLowerCase()))
63+
.sort((a, b) => b.length - a.length);
64+
for (const candidate of candidates.slice(0, 5)) {
65+
try {
66+
const raw = execFileSync('code-graph-mcp', ['grep', candidate, filePath, '--json'], {
67+
cwd, timeout: 2000, encoding: 'utf8', stdio: ['pipe', 'pipe', 'pipe'],
68+
});
69+
const grepResult = JSON.parse(raw);
70+
// Pick this candidate if it has few matches (precise location)
71+
const withContainer = (grepResult || []).filter(m => m.container && m.container.name);
72+
if (withContainer.length > 0 && withContainer.length <= 5) {
73+
// If multiple containers, vote for the most common one
74+
const votes = {};
75+
for (const m of withContainer) {
76+
const cn = m.container.name;
77+
votes[cn] = (votes[cn] || 0) + 1;
78+
}
79+
const best = Object.entries(votes).sort((a, b) => b[1] - a[1])[0][0];
80+
symbol = best.includes('.') ? best.split('.').pop() : best.includes('::') ? best.split('::').pop() : best;
81+
break;
82+
}
83+
} catch { /* try next candidate */ }
84+
}
85+
} catch { /* grep failed or no match — fall through */ }
86+
}
87+
}
88+
5089
if (!symbol || symbol.length < 3) process.exit(0);
5190

5291
// Skip common patterns that aren't real function names

claude-plugin/scripts/user-prompt-context.js

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -95,12 +95,20 @@ if (/^(修复|优化|实施|执行|开始|按|实测|帮我|进入|用|重新)/.
9595
const filePaths = (message.match(/(?:src|lib|test|pkg|cmd|internal|app|components?)\/[\w/.-]+/g) || [])
9696
.slice(0, 2);
9797

98-
// Extract potential symbol names (camelCase, snake_case, PascalCase, qualified like Foo::bar)
99-
const symbolCandidates = (message.match(/\b(?:[A-Z]\w*(?:::\w+)+|[a-z]\w*(?:_\w+){1,}|[a-z]\w*(?:[A-Z]\w*)+|[A-Z][a-z]+(?:[A-Z][a-z]+)+)\b/g) || [])
98+
// Extract potential symbol names (camelCase, snake_case, PascalCase, qualified like Foo::bar, Foo.bar, Foo::bar::baz)
99+
const symbolCandidates = (message.match(/\b(?:[A-Z]\w*(?:(?:::|\.)\w+)+|[a-z]\w*(?:_\w+){1,}|[a-z]\w*(?:[A-Z]\w*)+|[A-Z][a-z]+(?:[A-Z][a-z]+)+)\b/g) || [])
100100
.filter(s => s.length > 4)
101101
.filter(s => !STOP_WORDS.has(s.toLowerCase()))
102102
.slice(0, 3);
103103

104+
// Fallback: extract backtick-quoted symbols (common in mixed Chinese+code: "修改 `parse_code` 函数")
105+
if (symbolCandidates.length === 0) {
106+
const backtickSymbols = (message.match(/`([a-zA-Z_]\w{2,})`/g) || [])
107+
.map(s => s.replace(/`/g, ''))
108+
.filter(s => s.length >= 3 && !STOP_WORDS.has(s.toLowerCase()));
109+
symbolCandidates.push(...backtickSymbols.slice(0, 3));
110+
}
111+
104112
// Fallback: plain lowercase words (8+ chars) likely to be function/type names.
105113
// Only when strict patterns found nothing — avoids false positives from English prose.
106114
// Minimum 8 chars filters most common English words while keeping technical terms

0 commit comments

Comments
 (0)