skannr 0.1.3 → 0.1.4

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.
Files changed (88) hide show
  1. package/.eslintrc.js +22 -22
  2. package/README.md +260 -174
  3. package/dist/agent-cli.js +25 -25
  4. package/dist/agent.js +4 -4
  5. package/dist/blast-radius.d.ts +80 -0
  6. package/dist/blast-radius.d.ts.map +1 -0
  7. package/dist/blast-radius.js +545 -0
  8. package/dist/blast-radius.js.map +1 -0
  9. package/dist/cli.js +55 -17
  10. package/dist/cli.js.map +1 -1
  11. package/dist/mcp-server.d.ts.map +1 -1
  12. package/dist/mcp-server.js +98 -24
  13. package/dist/mcp-server.js.map +1 -1
  14. package/dist/telemetry.js +12 -12
  15. package/gemini-extension/GEMINI.md +26 -26
  16. package/gemini-extension/gemini-extension.json +12 -12
  17. package/gemini-extension/package.json +14 -14
  18. package/gemini-extension/src/server.ts +69 -69
  19. package/gemini-extension/tsconfig.json +14 -14
  20. package/jest.config.js +4 -4
  21. package/package.json +54 -53
  22. package/src/agent-cli.ts +397 -397
  23. package/src/agent.ts +344 -344
  24. package/src/benchmark.ts +389 -389
  25. package/src/blast-radius.ts +661 -0
  26. package/src/cache.ts +317 -317
  27. package/src/cli.ts +461 -415
  28. package/src/config.ts +22 -22
  29. package/src/formatter.ts +105 -105
  30. package/src/index.ts +223 -223
  31. package/src/languages/GenericAdapter.ts +44 -44
  32. package/src/languages/LanguageAdapter.ts +21 -21
  33. package/src/languages/PythonAdapter.ts +285 -285
  34. package/src/languages/TypeScriptAdapter.ts +453 -453
  35. package/src/languages/registry.ts +49 -49
  36. package/src/mapper.ts +455 -455
  37. package/src/mcp-cli.ts +8 -8
  38. package/src/mcp-server.ts +151 -103
  39. package/src/ranker-enhanced.ts +514 -514
  40. package/src/ranker.ts +110 -110
  41. package/src/scanner.ts +226 -226
  42. package/src/skeletonizer.ts +22 -22
  43. package/src/telemetry.ts +146 -146
  44. package/src/tokenizer.ts +20 -20
  45. package/src/types.ts +92 -92
  46. package/src/watcher.ts +119 -119
  47. package/src/why.ts +88 -88
  48. package/tests/agent.tools.test.ts +81 -81
  49. package/tests/benchmark.test.ts +30 -30
  50. package/tests/blast-radius.test.ts +290 -0
  51. package/tests/fixtures/sample.py +17 -17
  52. package/tests/fixtures/sample.ts +13 -13
  53. package/tests/fixtures/src/api/routes.ts +1 -1
  54. package/tests/fixtures/src/auth/permission.ts +3 -3
  55. package/tests/python-adapter.test.ts +31 -31
  56. package/tests/ranker-enhanced.test.ts +70 -70
  57. package/tests/ranker.test.ts +79 -79
  58. package/tests/scanner.scope.test.ts +66 -66
  59. package/tests/setup-fixtures.js +28 -28
  60. package/tests/skeletonizer.test.ts +149 -149
  61. package/tsconfig.json +21 -21
  62. package/uca-landing/index.html +17 -17
  63. package/uca-landing/package.json +23 -23
  64. package/uca-landing/postcss.config.js +6 -6
  65. package/uca-landing/src/App.jsx +43 -43
  66. package/uca-landing/src/components/AgentMode.jsx +45 -45
  67. package/uca-landing/src/components/CliReference.jsx +58 -58
  68. package/uca-landing/src/components/Features.jsx +82 -82
  69. package/uca-landing/src/components/Footer.jsx +35 -35
  70. package/uca-landing/src/components/Hero.jsx +125 -125
  71. package/uca-landing/src/components/HowItWorks.jsx +60 -60
  72. package/uca-landing/src/components/Install.jsx +103 -103
  73. package/uca-landing/src/components/LanguageSupport.jsx +63 -63
  74. package/uca-landing/src/components/Navbar.jsx +86 -86
  75. package/uca-landing/src/components/Problem.jsx +51 -51
  76. package/uca-landing/src/components/Reveal.jsx +40 -40
  77. package/uca-landing/src/components/WorksWith.jsx +59 -59
  78. package/uca-landing/src/hooks/useScrollNav.js +13 -13
  79. package/uca-landing/src/hooks/useTypewriter.js +41 -41
  80. package/uca-landing/src/index.css +13 -13
  81. package/uca-landing/src/main.jsx +10 -10
  82. package/uca-landing/tailwind.config.js +68 -68
  83. package/uca-landing/vercel.json +3 -3
  84. package/uca-landing/vite.config.js +6 -6
  85. package/dist/rocket-chat-scope.d.ts +0 -7
  86. package/dist/rocket-chat-scope.d.ts.map +0 -1
  87. package/dist/rocket-chat-scope.js +0 -95
  88. package/dist/rocket-chat-scope.js.map +0 -1
package/.eslintrc.js CHANGED
@@ -1,22 +1,22 @@
1
- module.exports = {
2
- parser: '@typescript-eslint/parser',
3
- extends: [
4
- 'eslint:recommended',
5
- 'plugin:@typescript-eslint/recommended',
6
- ],
7
- parserOptions: {
8
- ecmaVersion: 2022,
9
- sourceType: 'module',
10
- },
11
- env: {
12
- node: true,
13
- es6: true,
14
- jest: true,
15
- },
16
- rules: {
17
- '@typescript-eslint/explicit-function-return-type': 'off',
18
- '@typescript-eslint/no-explicit-any': 'warn',
19
- '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
20
- 'no-console': 'off',
21
- },
22
- };
1
+ module.exports = {
2
+ parser: '@typescript-eslint/parser',
3
+ extends: [
4
+ 'eslint:recommended',
5
+ 'plugin:@typescript-eslint/recommended',
6
+ ],
7
+ parserOptions: {
8
+ ecmaVersion: 2022,
9
+ sourceType: 'module',
10
+ },
11
+ env: {
12
+ node: true,
13
+ es6: true,
14
+ jest: true,
15
+ },
16
+ rules: {
17
+ '@typescript-eslint/explicit-function-return-type': 'off',
18
+ '@typescript-eslint/no-explicit-any': 'warn',
19
+ '@typescript-eslint/no-unused-vars': ['error', { argsIgnorePattern: '^_' }],
20
+ 'no-console': 'off',
21
+ },
22
+ };
package/README.md CHANGED
@@ -1,174 +1,260 @@
1
- # Skannr
2
-
3
- A CLI tool and MCP server that helps AI agents understand **any codebase**.
4
- It scans files, generates compressed structural "skeletons", and ranks results
5
- using hybrid retrieval — reducing token usage by ~96% vs full file scans.
6
-
7
- ## How It Works
8
-
9
- 1. You point it at any repo with `--root /path/to/repo`
10
- 2. It auto-detects the language (TypeScript, JavaScript, Python, or generic fallback)
11
- 3. It auto-discovers your project's modules from the folder structure
12
- 4. For your question, it ranks the most relevant files using lexical + structural + dependency-graph analysis
13
- 5. It strips function bodies from files (keeping types, signatures, imports)
14
- 6. Returns compact skeletons an AI can reason over without blowing the context window
15
-
16
- ## Install
17
-
18
- ```bash
19
- npm install -g skannr
20
- ```
21
-
22
- ## Usage
23
-
24
- ### CLI
25
-
26
- ```bash
27
- # Basic
28
- skannr --question "how does authentication work?" --root /path/to/any/repo
29
-
30
- # Limit results
31
- skannr --question "database connection setup" --root . --limit 5
32
-
33
- # Focus on specific modules (auto-discovered if not specified)
34
- skannr --question "permission checks" --root . --modules auth,middleware
35
-
36
- # Force language
37
- skannr --question "class structure" --root /path/to/python/project --lang python
38
-
39
- # Interactive agent mode
40
- skannr-agent --root /path/to/repo
41
-
42
- # Cache management
43
- skannr --cache-stats
44
- skannr --cache-clear
45
- skannr --question "..." --skip-cache
46
-
47
- # Output: human (default), markdown, or json
48
- skannr --question "..." --root . --format markdown
49
- skannr --question "..." --root . --format json
50
-
51
- # Repository health report (JSON on stdout)
52
- skannr --report --root .
53
-
54
- # Re-run analysis when files change (debounced; uses fresh analysis each pass)
55
- skannr --question "..." --root . --watch
56
- ```
57
-
58
- ### Watch mode (`--watch`)
59
-
60
- Use `--watch` when you want Skannr to stay running and **re-analyze after relevant file changes** (large repos you edit often). Changes under common build/vendor dirs are ignored (`node_modules`, `.git`, `dist`, etc.). Press **Ctrl+C** to stop.
61
-
62
- Each run bypasses the analysis cache so results reflect the tree as it is now.
63
-
64
- ### Anonymous telemetry (opt-in)
65
-
66
- Telemetry is **off unless you enable it** (or accept deferred opt-in — see below). It sends **only which CLI flags were used** — never your question text, file paths, or code.
67
-
68
- - Enable: `skannr --telemetry-on`
69
- - Disable: `skannr --telemetry-off`
70
-
71
- Settings are stored under `~/.skannr/config.json`. The first time you run an analyze command with no config yet, Skannr may show a short notice; you can opt in or out anytime with the flags above.
72
-
73
- If you take no action, telemetry may turn on automatically **after 7 days** from that notice unless you explicitly disabled it with `--telemetry-off`.
74
-
75
- ## MCP Server
76
-
77
- `skannr` ships with a built-in MCP server. One-time setup per AI tool:
78
-
79
- ### Cursor
80
-
81
- `~/.cursor/mcp.json`:
82
-
83
- ```json
84
- {
85
- "mcpServers": {
86
- "skannr": {
87
- "command": "npx",
88
- "args": ["-y", "skannr", "--mcp"]
89
- }
90
- }
91
- }
92
- ```
93
-
94
- ### Claude Desktop / Claude Code
95
-
96
- `~/Library/Application Support/Claude/claude_desktop_config.json`:
97
-
98
- ```json
99
- {
100
- "mcpServers": {
101
- "skannr": {
102
- "command": "npx",
103
- "args": ["-y", "skannr", "--mcp"]
104
- }
105
- }
106
- }
107
- ```
108
-
109
- ### Gemini CLI
110
-
111
- `~/.gemini/config.json`:
112
-
113
- ```json
114
- {
115
- "mcpServers": {
116
- "skannr": {
117
- "command": "npx",
118
- "args": ["-y", "skannr", "--mcp"]
119
- }
120
- }
121
- }
122
- ```
123
-
124
- Alternatively run the dedicated binary: `skannr-mcp` (same stdio server).
125
-
126
- ## Config File (optional)
127
-
128
- Drop a `code-analyzer.config.json` in your repo root:
129
-
130
- ```json
131
- {
132
- "modules": {
133
- "auth": ["src/auth", "lib/auth"],
134
- "api": ["src/api", "src/routes"]
135
- },
136
- "exclude": ["**/generated/**", "**/migrations/**"],
137
- "extensions": [".ts", ".js"],
138
- "defaultLimit": 10
139
- }
140
- ```
141
-
142
- ## Supported Languages
143
-
144
- | Language | Skeleton Support |
145
- |---|---|
146
- | TypeScript / TSX | Full AST (ts-morph) |
147
- | JavaScript / JSX | Full AST (ts-morph) |
148
- | Python | Regex-based (signatures + types) |
149
- | Others | First 50 lines (generic fallback) |
150
-
151
- ## Performance
152
-
153
- Benchmarked on large TypeScript monorepo:
154
-
155
- | Metric | Result |
156
- |---|---|
157
- | Token Reduction vs Full Scan | ~96.5% |
158
- | Token Reduction vs Top-N | ~78.2% |
159
- | Avg keyword coverage | ~75% |
160
- | Directory diversity (top-5) | ~80% |
161
- | Average execution time | ~1.2s |
162
-
163
- ## Interactive Agent Commands
164
-
165
- ```
166
- /help Show all commands
167
- /files List retrieved files
168
- /symbols <query> Search for symbols
169
- /symbol <id> Get full implementation
170
- /deps <file> Show imports for a file
171
- /refresh Re-analyze with new context
172
- /stats Show mapping statistics
173
- /exit Quit
174
- ```
1
+ # Skannr
2
+
3
+ A CLI tool and MCP server that helps AI agents understand **any codebase**.
4
+ It scans files, generates compressed structural "skeletons", and ranks results
5
+ using hybrid retrieval — reducing token usage by ~96% vs full file scans.
6
+
7
+ ## How It Works
8
+
9
+ 1. You point it at any repo with `--root /path/to/repo`
10
+ 2. It auto-detects the language (TypeScript, JavaScript, Python, or generic fallback)
11
+ 3. It auto-discovers your project's modules from the folder structure
12
+ 4. For your question, it ranks the most relevant files using lexical + structural + dependency-graph analysis
13
+ 5. It strips function bodies from files (keeping types, signatures, imports)
14
+ 6. Returns compact skeletons an AI can reason over without blowing the context window
15
+
16
+ ## Install
17
+
18
+ ```bash
19
+ npm install -g skannr
20
+ ```
21
+
22
+ ## Usage
23
+
24
+ ### CLI
25
+
26
+ ```bash
27
+ # Basic
28
+ skannr --question "how does authentication work?" --root /path/to/any/repo
29
+
30
+ # Limit results
31
+ skannr --question "database connection setup" --root . --limit 5
32
+
33
+ # Focus on specific modules (auto-discovered if not specified)
34
+ skannr --question "permission checks" --root . --modules auth,middleware
35
+
36
+ # Force language
37
+ skannr --question "class structure" --root /path/to/python/project --lang python
38
+
39
+ # Interactive agent mode
40
+ skannr-agent --root /path/to/repo
41
+
42
+ # Cache management
43
+ skannr --cache-stats
44
+ skannr --cache-clear
45
+ skannr --question "..." --skip-cache
46
+
47
+ # Output: human (default), markdown, or json
48
+ skannr --question "..." --root . --format markdown
49
+ skannr --question "..." --root . --format json
50
+
51
+ # Repository health report (JSON on stdout)
52
+ skannr --report --root .
53
+
54
+ # Re-run analysis when files change (debounced; uses fresh analysis each pass)
55
+ skannr --question "..." --root . --watch
56
+ ```
57
+
58
+ ### Watch mode (`--watch`)
59
+
60
+ Use `--watch` when you want Skannr to stay running and **re-analyze after relevant file changes** (large repos you edit often). Changes under common build/vendor dirs are ignored (`node_modules`, `.git`, `dist`, etc.). Press **Ctrl+C** to stop.
61
+
62
+ Each run bypasses the analysis cache so results reflect the tree as it is now.
63
+
64
+ ### Anonymous telemetry (opt-in)
65
+
66
+ Telemetry is **off unless you enable it** (or accept deferred opt-in — see below). It sends **only which CLI flags were used** — never your question text, file paths, or code.
67
+
68
+ - Enable: `skannr --telemetry-on`
69
+ - Disable: `skannr --telemetry-off`
70
+
71
+ Settings are stored under `~/.skannr/config.json`. The first time you run an analyze command with no config yet, Skannr may show a short notice; you can opt in or out anytime with the flags above.
72
+
73
+ If you take no action, telemetry may turn on automatically **after 7 days** from that notice unless you explicitly disabled it with `--telemetry-off`.
74
+
75
+ ## MCP Server
76
+
77
+ `skannr` ships with a built-in MCP server. One-time setup per AI tool:
78
+
79
+ ### Cursor
80
+
81
+ `~/.cursor/mcp.json`:
82
+
83
+ ```json
84
+ {
85
+ "mcpServers": {
86
+ "skannr": {
87
+ "command": "npx",
88
+ "args": ["-y", "skannr", "--mcp"]
89
+ }
90
+ }
91
+ }
92
+ ```
93
+
94
+ ### Claude Desktop / Claude Code
95
+
96
+ `~/Library/Application Support/Claude/claude_desktop_config.json`:
97
+
98
+ ```json
99
+ {
100
+ "mcpServers": {
101
+ "skannr": {
102
+ "command": "npx",
103
+ "args": ["-y", "skannr", "--mcp"]
104
+ }
105
+ }
106
+ }
107
+ ```
108
+
109
+ ### Gemini CLI
110
+
111
+ `~/.gemini/config.json`:
112
+
113
+ ```json
114
+ {
115
+ "mcpServers": {
116
+ "skannr": {
117
+ "command": "npx",
118
+ "args": ["-y", "skannr", "--mcp"]
119
+ }
120
+ }
121
+ }
122
+ ```
123
+
124
+ Alternatively run the dedicated binary: `skannr-mcp` (same stdio server).
125
+
126
+ ## Config File (optional)
127
+
128
+ Drop a `code-analyzer.config.json` in your repo root:
129
+
130
+ ```json
131
+ {
132
+ "modules": {
133
+ "auth": ["src/auth", "lib/auth"],
134
+ "api": ["src/api", "src/routes"]
135
+ },
136
+ "exclude": ["**/generated/**", "**/migrations/**"],
137
+ "extensions": [".ts", ".js"],
138
+ "defaultLimit": 10
139
+ }
140
+ ```
141
+
142
+ ## Supported Languages
143
+
144
+ | Language | Skeleton Support |
145
+ |---|---|
146
+ | TypeScript / TSX | Full AST (ts-morph) |
147
+ | JavaScript / JSX | Full AST (ts-morph) |
148
+ | Python | Regex-based (signatures + types) |
149
+ | Others | First 50 lines (generic fallback) |
150
+
151
+ ## Performance
152
+
153
+ Benchmarked on large TypeScript monorepo:
154
+
155
+ | Metric | Result |
156
+ |---|---|
157
+ | Token Reduction vs Full Scan | ~96.5% |
158
+ | Token Reduction vs Top-N | ~78.2% |
159
+ | Avg keyword coverage | ~75% |
160
+ | Directory diversity (top-5) | ~80% |
161
+ | Average execution time | ~1.2s |
162
+
163
+ ## Interactive Agent Commands
164
+
165
+ ```
166
+ /help Show all commands
167
+ /files List retrieved files
168
+ /symbols <query> Search for symbols
169
+ /symbol <id> Get full implementation
170
+ /deps <file> Show imports for a file
171
+ /refresh Re-analyze with new context
172
+ /stats Show mapping statistics
173
+ /exit Quit
174
+ ```
175
+
176
+ ## Blast Radius
177
+
178
+ Analyze the downstream impact and risk of a code change. Given a git diff,
179
+ blast-radius identifies which files are affected, how central they are in the
180
+ dependency graph, and whether they have test coverage.
181
+
182
+ **Limitation (v1):** Traversal is computed at file granularity — "file A
183
+ imports file B" — not at function-call level. Function-level resolution is
184
+ planned for a future version.
185
+
186
+ ### CLI
187
+
188
+ ```bash
189
+ # Analyze working tree changes vs HEAD (default)
190
+ skannr blast-radius --root .
191
+
192
+ # Analyze a specific diff file, 3 hops deep
193
+ skannr blast-radius --root . --diff changes.patch --hops 3
194
+
195
+ # JSON output for CI pipelines
196
+ skannr blast-radius --root . --json
197
+ ```
198
+
199
+ Sample terminal output:
200
+
201
+ ```
202
+ Blast Radius Analysis (2-hop traversal)
203
+ ──────────────────────────────────────────────────
204
+
205
+ Risk Score: 5.8/10
206
+ Risk 5.8/10 (moderate): 1 file(s) changed, 4 downstream affected, 3 untested.
207
+
208
+ Changed files:
209
+ src/auth/session.ts
210
+
211
+ Changed symbols:
212
+ function validateToken (src/auth/session.ts)
213
+
214
+ Hop 1 (2 files):
215
+ src/middleware/auth-guard.ts centrality=0.85 [NO TEST]
216
+ src/api/login.ts centrality=0.60
217
+
218
+ Hop 2 (2 files):
219
+ src/routes/index.ts centrality=0.45 [NO TEST]
220
+ src/api/admin.ts centrality=0.30 [NO TEST]
221
+
222
+ Formula inputs:
223
+ affected_count (normalized): 0.080
224
+ avg_centrality: 0.550
225
+ untested_ratio: 0.750
226
+ hop_spread (normalized): 1.000
227
+ ```
228
+
229
+ ### MCP
230
+
231
+ The `blast_radius` tool is exposed via the same MCP server (`skannr --mcp`).
232
+
233
+ Input schema:
234
+
235
+ ```json
236
+ {
237
+ "root": "/path/to/repo",
238
+ "diff": "<optional unified diff content>",
239
+ "hops": 2
240
+ }
241
+ ```
242
+
243
+ If `diff` is omitted, the tool runs `git diff HEAD` in the given root.
244
+ The output is the same JSON structure as `skannr blast-radius --json`.
245
+
246
+ ### Risk Score Formula
247
+
248
+ ```
249
+ risk = 2.5 × normalizedAffectedCount
250
+ + 2.5 × avgCentrality
251
+ + 3.5 × untestedRatio
252
+ + 1.5 × normalizedMaxHopSpread
253
+ ```
254
+
255
+ | Input | Range | Meaning |
256
+ |-------|-------|---------|
257
+ | normalizedAffectedCount | 0–1 | Affected files / total project files |
258
+ | avgCentrality | 0–1 | Mean in-degree centrality of affected files |
259
+ | untestedRatio | 0–1 | Fraction of affected files with no test file |
260
+ | normalizedMaxHopSpread | 0–1 | Deepest hop reached / max configured hops |
package/dist/agent-cli.js CHANGED
@@ -140,31 +140,31 @@ function parseArgs() {
140
140
  * Print help message
141
141
  */
142
142
  function printHelp() {
143
- console.log(`
144
- skannr-agent — AI-powered code analysis (Gemini)
145
-
146
- Usage:
147
- skannr-agent --question "<text>" [options]
148
- skannr-agent --interactive [options]
149
-
150
- Options:
151
- --root <path> Project root directory (default: current directory)
152
- --question "<text>" Question to analyze (required unless --interactive)
153
- --limit <number> Number of top files to analyze (default: 10)
154
- --api-key <key> Gemini API key (or set GEMINI_API_KEY env var)
155
- --model <name> Gemini model name (default: gemini-2.0-flash-exp)
156
- --interactive, -i Start interactive chat mode
157
- --help, -h Show this help message
158
-
159
- Examples:
160
- skannr-agent --question "How does authentication work?"
161
- skannr-agent --interactive --root ./my-project
162
- skannr-agent --question "Find all API endpoints" --limit 15
163
-
164
- Environment variables:
165
- GEMINI_API_KEY Gemini API key (alternative to --api-key)
166
-
167
- Docs: https://skannr-ten.vercel.app
143
+ console.log(`
144
+ skannr-agent — AI-powered code analysis (Gemini)
145
+
146
+ Usage:
147
+ skannr-agent --question "<text>" [options]
148
+ skannr-agent --interactive [options]
149
+
150
+ Options:
151
+ --root <path> Project root directory (default: current directory)
152
+ --question "<text>" Question to analyze (required unless --interactive)
153
+ --limit <number> Number of top files to analyze (default: 10)
154
+ --api-key <key> Gemini API key (or set GEMINI_API_KEY env var)
155
+ --model <name> Gemini model name (default: gemini-2.0-flash-exp)
156
+ --interactive, -i Start interactive chat mode
157
+ --help, -h Show this help message
158
+
159
+ Examples:
160
+ skannr-agent --question "How does authentication work?"
161
+ skannr-agent --interactive --root ./my-project
162
+ skannr-agent --question "Find all API endpoints" --limit 15
163
+
164
+ Environment variables:
165
+ GEMINI_API_KEY Gemini API key (alternative to --api-key)
166
+
167
+ Docs: https://skannr-ten.vercel.app
168
168
  `);
169
169
  }
170
170
  /**
package/dist/agent.js CHANGED
@@ -48,8 +48,8 @@ const path = __importStar(require("path"));
48
48
  */
49
49
  exports.getSymbolDetailsTool = {
50
50
  name: 'get_symbol_details',
51
- description: `Retrieve the full implementation of a code symbol (function, method, class) from the original source file.
52
- Use this when you need to see the actual implementation of a function or method that was marked with [SYMBOL:...] in the skeleton.
51
+ description: `Retrieve the full implementation of a code symbol (function, method, class) from the original source file.
52
+ Use this when you need to see the actual implementation of a function or method that was marked with [SYMBOL:...] in the skeleton.
53
53
  The symbolId is in the format "ClassName.methodName" or "functionName" for top-level functions.`,
54
54
  parameters: {
55
55
  type: generative_ai_1.SchemaType.OBJECT,
@@ -67,7 +67,7 @@ The symbolId is in the format "ClassName.methodName" or "functionName" for top-l
67
67
  */
68
68
  exports.searchSymbolsTool = {
69
69
  name: 'search_symbols',
70
- description: `Search for available symbols in the generated skeletons. Returns a list of matching symbols that can be retrieved using get_symbol_details.
70
+ description: `Search for available symbols in the generated skeletons. Returns a list of matching symbols that can be retrieved using get_symbol_details.
71
71
  Use this to discover what functions/methods are available before requesting their full implementation.`,
72
72
  parameters: {
73
73
  type: generative_ai_1.SchemaType.OBJECT,
@@ -90,7 +90,7 @@ Use this to discover what functions/methods are available before requesting thei
90
90
  */
91
91
  exports.analyzeFileDependenciesTool = {
92
92
  name: 'analyze_file_dependencies',
93
- description: `Analyze import/export relationships for a specific file from the skeleton.
93
+ description: `Analyze import/export relationships for a specific file from the skeleton.
94
94
  Use this to understand what other files a given file depends on.`,
95
95
  parameters: {
96
96
  type: generative_ai_1.SchemaType.OBJECT,
@@ -0,0 +1,80 @@
1
+ /**
2
+ * Blast Radius: determines downstream impact and risk of a git diff.
3
+ *
4
+ * Pipeline: parse diff → identify changed files → traverse reverse dependency
5
+ * graph N hops → score affected nodes by centrality → flag untested nodes →
6
+ * compute aggregate risk score.
7
+ *
8
+ * Limitation (v1): graph traversal is file-level, not symbol-level.
9
+ * A changed file is treated as a unit; individual function-call edges are not
10
+ * tracked. Symbol extraction from diffs is used for reporting only.
11
+ */
12
+ import type { Symbol } from './languages/LanguageAdapter';
13
+ /** A symbol touched by the diff within a single file. */
14
+ export interface ChangedSymbol {
15
+ name: string;
16
+ kind: Symbol['kind'];
17
+ file: string;
18
+ }
19
+ /** A downstream file affected by the change, with metadata. */
20
+ export interface AffectedNode {
21
+ /** Path relative to project root. */
22
+ file: string;
23
+ /** Number of hops from a changed file (1 = direct importer). */
24
+ hopDistance: number;
25
+ /** Normalized centrality score [0,1] — how many files depend on this one. */
26
+ centrality: number;
27
+ /** Whether a corresponding test file was found for this file. */
28
+ hasTest: boolean;
29
+ }
30
+ /** Full blast-radius analysis result (shared between CLI text and JSON output). */
31
+ export interface BlastRadiusResult {
32
+ /** Aggregate risk score (0–10). */
33
+ riskScore: number;
34
+ /** One-line human-readable summary. */
35
+ summary: string;
36
+ /** Files directly modified by the diff (relative paths). */
37
+ changedFiles: string[];
38
+ /** Symbols identified as changed within those files. */
39
+ changedSymbols: ChangedSymbol[];
40
+ /** All downstream affected files grouped by hop distance. */
41
+ affectedNodes: AffectedNode[];
42
+ /** Breakdown of the risk formula inputs (for transparency). */
43
+ formulaInputs: {
44
+ normalizedAffectedCount: number;
45
+ avgCentrality: number;
46
+ untestedRatio: number;
47
+ normalizedMaxHopSpread: number;
48
+ };
49
+ /** Max hops used for this analysis. */
50
+ hops: number;
51
+ }
52
+ /** Options accepted by computeBlastRadius. */
53
+ export interface BlastRadiusOptions {
54
+ /** Absolute path to project root. */
55
+ root: string;
56
+ /** Raw unified diff content. If omitted, working-tree diff against HEAD is used. */
57
+ diffContent?: string;
58
+ /** Path to a diff file on disk. Takes precedence over diffContent if both given. */
59
+ diffPath?: string;
60
+ /** Maximum hop distance for traversal (default: 2). */
61
+ hops?: number;
62
+ }
63
+ /** Compute the blast radius for a diff against a project. */
64
+ export declare function computeBlastRadius(options: BlastRadiusOptions): BlastRadiusResult;
65
+ /**
66
+ * Invert the forward graph (file → imports) into a reverse graph
67
+ * (file → files that import it).
68
+ */
69
+ export declare function buildReverseGraph(forwardGraph: Map<string, string[]>): Map<string, string[]>;
70
+ /**
71
+ * BFS from changed files outward on the reverse graph, up to maxHops.
72
+ * Returns a map of affected file → hop distance (excluding the changed files
73
+ * themselves).
74
+ */
75
+ export declare function traverseAffected(changedFiles: string[], reverseGraph: Map<string, string[]>, maxHops: number): Map<string, number>;
76
+ /** Plain-text report for terminal output. */
77
+ export declare function formatBlastRadiusText(result: BlastRadiusResult): string;
78
+ /** JSON output (for --json flag and MCP). */
79
+ export declare function formatBlastRadiusJson(result: BlastRadiusResult): string;
80
+ //# sourceMappingURL=blast-radius.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"blast-radius.d.ts","sourceRoot":"","sources":["../src/blast-radius.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AAUH,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,6BAA6B,CAAC;AAe1D,yDAAyD;AACzD,MAAM,WAAW,aAAa;IAC5B,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC;IACrB,IAAI,EAAE,MAAM,CAAC;CACd;AAED,+DAA+D;AAC/D,MAAM,WAAW,YAAY;IAC3B,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,gEAAgE;IAChE,WAAW,EAAE,MAAM,CAAC;IACpB,6EAA6E;IAC7E,UAAU,EAAE,MAAM,CAAC;IACnB,iEAAiE;IACjE,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,mFAAmF;AACnF,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,SAAS,EAAE,MAAM,CAAC;IAClB,uCAAuC;IACvC,OAAO,EAAE,MAAM,CAAC;IAChB,4DAA4D;IAC5D,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,wDAAwD;IACxD,cAAc,EAAE,aAAa,EAAE,CAAC;IAChC,6DAA6D;IAC7D,aAAa,EAAE,YAAY,EAAE,CAAC;IAC9B,+DAA+D;IAC/D,aAAa,EAAE;QACb,uBAAuB,EAAE,MAAM,CAAC;QAChC,aAAa,EAAE,MAAM,CAAC;QACtB,aAAa,EAAE,MAAM,CAAC;QACtB,sBAAsB,EAAE,MAAM,CAAC;KAChC,CAAC;IACF,uCAAuC;IACvC,IAAI,EAAE,MAAM,CAAC;CACd;AAED,8CAA8C;AAC9C,MAAM,WAAW,kBAAkB;IACjC,qCAAqC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,oFAAoF;IACpF,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,uDAAuD;IACvD,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAMD,6DAA6D;AAC7D,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,kBAAkB,GAAG,iBAAiB,CA8CjF;AA6GD;;;GAGG;AACH,wBAAgB,iBAAiB,CAC/B,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,GAClC,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,CAcvB;AAMD;;;;GAIG;AACH,wBAAgB,gBAAgB,CAC9B,YAAY,EAAE,MAAM,EAAE,EACtB,YAAY,EAAE,GAAG,CAAC,MAAM,EAAE,MAAM,EAAE,CAAC,EACnC,OAAO,EAAE,MAAM,GACd,GAAG,CAAC,MAAM,EAAE,MAAM,CAAC,CA8BrB;AA4PD,6CAA6C;AAC7C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAyDvE;AAED,6CAA6C;AAC7C,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,iBAAiB,GAAG,MAAM,CAEvE"}