@sdsrs/code-graph
Advanced tools
@@ -7,3 +7,3 @@ { | ||
| }, | ||
| "version": "0.24.0", | ||
| "version": "0.24.1", | ||
| "keywords": [ | ||
@@ -10,0 +10,0 @@ "code-graph", |
@@ -36,5 +36,12 @@ #!/usr/bin/env node | ||
| // the typed variant; everyone else falls back to this canonical line. | ||
| // Tags MUST be ≥4 chars and topic-specific (per claudemd §11-EXT Tag-specificity). | ||
| // Generic single-word English tags (impact / refs / overview / semantic / deps / | ||
| // trace / route / similar) substring-match release-notes / commit-message prose | ||
| // via the §11 read-the-file hook regex (word-boundary + 0–2 declension chars), | ||
| // producing false-positive denies. Each tag below aligns with its MCP tool name | ||
| // (impact_analysis / find_references / module_overview / …) so hyphenated literals | ||
| // never collide with natural prose. | ||
| const INDEX_LINE = | ||
| '- [code-graph-mcp](plugin_code_graph_mcp.md) ' + | ||
| '[impact, callgraph, refs, overview, semantic, ast-search, dead-code, similar, deps, trace] — ' + | ||
| '[impact-analysis, callgraph, find-references, module-overview, semantic-search, ast-search, dead-code, find-similar-code, dependency-graph, trace-http-chain] — ' + | ||
| '改 X 影响面/谁调用 X/X 被谁用/看 X 源码/Y 模块长啥样/概念查询 优先于 Grep;字面匹配走 Grep。' + | ||
@@ -239,3 +246,3 @@ '核心 7(get_call_graph/module_overview/semantic_code_search/ast_search/find_references/get_ast_node/project_map)' + | ||
| return prefix + | ||
| '[trace, route, callgraph, impact, refs, overview, semantic, deps] — ' + | ||
| '[trace-http-chain, http-route, callgraph, impact-analysis, find-references, module-overview, semantic-search, dependency-graph] — ' + | ||
| 'HTTP 路由→handler 链路用 trace_http_chain(或 get_call_graph route_path=);改 handler 影响面用 impact;' + | ||
@@ -245,3 +252,3 @@ '其他结构化查询同上 优先于 Grep。' + coreSuffix; | ||
| return prefix + | ||
| '[refs, overview, semantic, callgraph, impact, ast-search] — ' + | ||
| '[find-references, module-overview, semantic-search, callgraph, impact-analysis, ast-search] — ' + | ||
| '组件重命名/重构用 find_references(含 imports/inherits);模块层级用 module_overview;' + | ||
@@ -254,3 +261,3 @@ '改 props/接口前用 impact 看下游;HTTP route 通常不适用。' + coreSuffix; | ||
| return prefix + | ||
| '[callgraph, impact, refs, overview, semantic, ast-search, dead-code, deps] — ' + | ||
| '[callgraph, impact-analysis, find-references, module-overview, semantic-search, ast-search, dead-code, dependency-graph] — ' + | ||
| '改 X 影响面/谁调用 X/Y 模块 优先于 Grep;HTTP route 追踪通常不适用(无 web 框架);' + | ||
@@ -257,0 +264,0 @@ '字面匹配走 Grep。' + coreSuffix; |
@@ -651,3 +651,3 @@ 'use strict'; | ||
| const line = buildIndexLine('web-rs'); | ||
| assert.match(line, /\[trace, route,/, 'web-rs index line should lead with trace/route tags'); | ||
| assert.match(line, /\[trace-http-chain, http-route,/, 'web-rs index line should lead with trace-http-chain/http-route tags'); | ||
| assert.match(line, /HTTP 路由/, 'lead sentence should mention HTTP routes'); | ||
@@ -679,2 +679,53 @@ }); | ||
| test('stale INDEX_LINE → adopt rewrites in place without duplicating sentinel blocks', () => { | ||
| // Regression for the v0.24+ tag-rename fix (feedback_adoption_tag_specificity). | ||
| // If a user's MEMORY.md was written by an older code-graph-mcp (pre-rename), | ||
| // SessionStart → maybeAutoAdopt → needsRefresh must detect the drift, | ||
| // stripSentinelBlock must locate the old v1 block by sentinel marker, and | ||
| // the rewrite must end with exactly one BEGIN/END pair. Breaks if anyone | ||
| // bumps SENTINEL_BEGIN without teaching stripSentinelBlock to also match | ||
| // the prior version — would leave an orphan v1 block plus a new v2 block. | ||
| const sb = makeSandbox(); | ||
| try { | ||
| fs.writeFileSync(path.join(sb.cwd, 'Cargo.toml'), '[package]\nname="x"\n'); | ||
| // Plant pre-rename MEMORY.md: well-formed v1 sentinel + an obsolete tag | ||
| // line that no current buildIndexLine variant produces. Exact prior bytes | ||
| // don't matter — only that it differs from today's desiredBlock. | ||
| const stalePayload = | ||
| '- [code-graph-mcp](plugin_code_graph_mcp.md) [obsolete-tag, another-stale] — stale lead sentence kept for drift detection.'; | ||
| const indexPath = path.join(sb.dir, 'MEMORY.md'); | ||
| const neighbor = '- [user_profile.md](user_profile.md) — neighbor (must survive)'; | ||
| fs.writeFileSync( | ||
| indexPath, | ||
| `# Memory Index\n\n${neighbor}\n\n${SENTINEL_BEGIN}\n${stalePayload}\n${SENTINEL_END}\n` | ||
| ); | ||
| // Plant target file so isAdopted/needsRefresh treat this as a real prior | ||
| // adoption (body bytewise-identical to shipped template — drift is only | ||
| // in MEMORY.md, not the template body). | ||
| const tplBody = fs.readFileSync(TEMPLATE_PATH); | ||
| const marker = Buffer.from(`<!-- adopted-by: ${sb.cwd} -->\n`); | ||
| fs.writeFileSync(path.join(sb.dir, TARGET_NAME), Buffer.concat([marker, tplBody])); | ||
| assert.strictEqual(isAdopted({ cwd: sb.cwd, home: sb.home }), true, | ||
| 'precondition: planted state should look adopted'); | ||
| assert.strictEqual(needsRefresh({ cwd: sb.cwd, home: sb.home }), true, | ||
| 'tag-list drift must trigger refresh'); | ||
| adopt({ cwd: sb.cwd, home: sb.home }); | ||
| const after = fs.readFileSync(indexPath, 'utf8'); | ||
| const escBegin = SENTINEL_BEGIN.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); | ||
| const escEnd = SENTINEL_END.replace(/[-/\\^$*+?.()|[\]{}]/g, '\\$&'); | ||
| const beginHits = (after.match(new RegExp(escBegin, 'g')) || []).length; | ||
| const endHits = (after.match(new RegExp(escEnd, 'g')) || []).length; | ||
| assert.strictEqual(beginHits, 1, 'exactly one sentinel BEGIN after rewrite (no duplicate blocks)'); | ||
| assert.strictEqual(endHits, 1, 'exactly one sentinel END after rewrite'); | ||
| assert.ok(!after.includes('obsolete-tag'), 'stale tag list must be gone'); | ||
| assert.ok(!after.includes('another-stale'), 'stale tag list must be gone'); | ||
| assert.ok(after.includes(neighbor), 'neighbor entry preserved'); | ||
| assert.strictEqual(needsRefresh({ cwd: sb.cwd, home: sb.home }), false, | ||
| 'post-refresh needsRefresh must be false (no SessionStart refresh loop)'); | ||
| } finally { sb.cleanup(); } | ||
| }); | ||
| // 2A — false-positive hardening: comment-strip + section-aware scan. | ||
@@ -681,0 +732,0 @@ |
+6
-6
| { | ||
| "name": "@sdsrs/code-graph", | ||
| "version": "0.24.0", | ||
| "version": "0.24.1", | ||
| "description": "MCP server that indexes codebases into an AST knowledge graph with semantic search, call graph traversal, and HTTP route tracing", | ||
@@ -38,8 +38,8 @@ "license": "MIT", | ||
| "optionalDependencies": { | ||
| "@sdsrs/code-graph-linux-x64": "0.24.0", | ||
| "@sdsrs/code-graph-linux-arm64": "0.24.0", | ||
| "@sdsrs/code-graph-darwin-x64": "0.24.0", | ||
| "@sdsrs/code-graph-darwin-arm64": "0.24.0", | ||
| "@sdsrs/code-graph-win32-x64": "0.24.0" | ||
| "@sdsrs/code-graph-linux-x64": "0.24.1", | ||
| "@sdsrs/code-graph-linux-arm64": "0.24.1", | ||
| "@sdsrs/code-graph-darwin-x64": "0.24.1", | ||
| "@sdsrs/code-graph-darwin-arm64": "0.24.1", | ||
| "@sdsrs/code-graph-win32-x64": "0.24.1" | ||
| } | ||
| } |
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
AI-detected potential code anomaly
Supply chain riskAI has identified unusual behaviors that may pose a security risk.
Found 1 instance in 1 package
URL strings
Supply chain riskPackage contains fragments of external URLs or IP addresses, which the package may be accessing at runtime.
Found 1 instance in 1 package
289317
1.36%5831
0.93%