project-graph-mcp 1.3.0 → 2.0.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.
Files changed (113) hide show
  1. package/README.md +223 -17
  2. package/{AGENT_ROLE.md → docs/examples/AGENT_ROLE.md} +87 -30
  3. package/{AGENT_ROLE_MINIMAL.md → docs/examples/AGENT_ROLE_MINIMAL.md} +23 -8
  4. package/package.json +12 -8
  5. package/src/.project-graph-cache.json +1 -0
  6. package/src/analysis/analysis-cache.js +7 -0
  7. package/src/analysis/complexity.js +14 -0
  8. package/src/analysis/custom-rules.js +36 -0
  9. package/src/analysis/db-analysis.js +9 -0
  10. package/src/analysis/dead-code.js +19 -0
  11. package/src/analysis/full-analysis.js +18 -0
  12. package/src/analysis/jsdoc-checker.js +24 -0
  13. package/src/analysis/jsdoc-generator.js +10 -0
  14. package/src/analysis/large-files.js +11 -0
  15. package/src/analysis/outdated-patterns.js +12 -0
  16. package/src/analysis/similar-functions.js +16 -0
  17. package/src/analysis/test-annotations.js +21 -0
  18. package/src/analysis/type-checker.js +8 -0
  19. package/src/analysis/undocumented.js +14 -0
  20. package/src/cli/cli-handlers.js +4 -0
  21. package/src/cli/cli.js +5 -0
  22. package/src/compact/ai-context.js +7 -0
  23. package/src/compact/compact.js +18 -0
  24. package/src/compact/compress.js +13 -0
  25. package/src/compact/ctx-to-jsdoc.js +29 -0
  26. package/src/compact/doc-dialect.js +30 -0
  27. package/src/compact/expand.js +37 -0
  28. package/src/compact/framework-references.js +5 -0
  29. package/src/compact/instructions.js +3 -0
  30. package/src/compact/mode-config.js +8 -0
  31. package/src/compact/validate-pipeline.js +9 -0
  32. package/src/core/event-bus.js +9 -0
  33. package/src/core/filters.js +14 -0
  34. package/src/core/graph-builder.js +12 -0
  35. package/src/core/parser.js +31 -0
  36. package/src/core/workspace.js +8 -0
  37. package/src/lang/lang-go.js +17 -0
  38. package/src/lang/lang-python.js +12 -0
  39. package/src/lang/lang-sql.js +23 -0
  40. package/src/lang/lang-typescript.js +9 -0
  41. package/src/lang/lang-utils.js +4 -0
  42. package/src/mcp/mcp-server.js +17 -0
  43. package/src/mcp/tool-defs.js +3 -0
  44. package/src/mcp/tools.js +25 -0
  45. package/src/network/backend-lifecycle.js +19 -0
  46. package/src/network/backend.js +5 -0
  47. package/src/network/local-gateway.js +23 -0
  48. package/src/network/mdns.js +13 -0
  49. package/src/network/server.js +10 -0
  50. package/src/network/web-server.js +34 -0
  51. package/vendor/terser.mjs +49 -0
  52. package/web/.project-graph-cache.json +1 -0
  53. package/web/app.js +16 -0
  54. package/web/components/code-block.js +3 -0
  55. package/web/components/quick-open.js +5 -0
  56. package/web/dashboard-state.js +3 -0
  57. package/web/dashboard.html +27 -0
  58. package/web/dashboard.js +8 -0
  59. package/web/highlight.js +13 -0
  60. package/web/index.html +35 -0
  61. package/web/panels/ActionBoard/ActionBoard.css.js +1 -0
  62. package/web/panels/ActionBoard/ActionBoard.js +4 -0
  63. package/web/panels/ActionBoard/ActionBoard.tpl.js +1 -0
  64. package/web/panels/EventItem/EventItem.css.js +1 -0
  65. package/web/panels/EventItem/EventItem.js +4 -0
  66. package/web/panels/EventItem/EventItem.tpl.js +1 -0
  67. package/web/panels/ProjectItem/ProjectItem.css.js +1 -0
  68. package/web/panels/ProjectItem/ProjectItem.js +5 -0
  69. package/web/panels/ProjectItem/ProjectItem.tpl.js +1 -0
  70. package/web/panels/ProjectList/ProjectList.css.js +1 -0
  71. package/web/panels/ProjectList/ProjectList.js +4 -0
  72. package/web/panels/ProjectList/ProjectList.tpl.js +1 -0
  73. package/web/panels/SettingsPanel/.project-graph-cache.json +1 -0
  74. package/web/panels/SettingsPanel/SettingsPanel.css.js +1 -0
  75. package/web/panels/SettingsPanel/SettingsPanel.js +7 -0
  76. package/web/panels/SettingsPanel/SettingsPanel.tpl.js +1 -0
  77. package/web/panels/code-viewer.js +5 -0
  78. package/web/panels/ctx-panel.js +4 -0
  79. package/web/panels/dep-graph.js +6 -0
  80. package/web/panels/file-tree.js +188 -0
  81. package/web/panels/health-panel.js +3 -0
  82. package/web/panels/live-monitor.js +3 -0
  83. package/web/state.js +17 -0
  84. package/web/style.css +157 -0
  85. package/references/symbiote-3x.md +0 -834
  86. package/src/cli-handlers.js +0 -140
  87. package/src/cli.js +0 -83
  88. package/src/complexity.js +0 -223
  89. package/src/custom-rules.js +0 -583
  90. package/src/db-analysis.js +0 -194
  91. package/src/dead-code.js +0 -468
  92. package/src/filters.js +0 -227
  93. package/src/framework-references.js +0 -177
  94. package/src/full-analysis.js +0 -174
  95. package/src/graph-builder.js +0 -299
  96. package/src/instructions.js +0 -175
  97. package/src/jsdoc-generator.js +0 -214
  98. package/src/lang-go.js +0 -285
  99. package/src/lang-python.js +0 -197
  100. package/src/lang-sql.js +0 -309
  101. package/src/lang-typescript.js +0 -190
  102. package/src/lang-utils.js +0 -124
  103. package/src/large-files.js +0 -162
  104. package/src/mcp-server.js +0 -468
  105. package/src/outdated-patterns.js +0 -295
  106. package/src/parser.js +0 -452
  107. package/src/server.js +0 -28
  108. package/src/similar-functions.js +0 -278
  109. package/src/test-annotations.js +0 -301
  110. package/src/tool-defs.js +0 -525
  111. package/src/tools.js +0 -470
  112. package/src/undocumented.js +0 -260
  113. package/src/workspace.js +0 -70
@@ -1,295 +0,0 @@
1
- /**
2
- * Outdated Patterns Detector
3
- * Finds legacy code patterns and redundant npm dependencies
4
- */
5
-
6
- import { readFileSync, readdirSync, statSync, existsSync } from 'fs';
7
- import { join, relative, resolve } from 'path';
8
- import { parse } from '../vendor/acorn.mjs';
9
- import * as walk from '../vendor/walk.mjs';
10
- import { shouldExcludeDir, shouldExcludeFile, parseGitignore } from './filters.js';
11
-
12
- /**
13
- * Redundant npm packages that are now built into Node.js 18+
14
- */
15
- const REDUNDANT_DEPS = {
16
- 'node-fetch': { replacement: 'fetch()', since: 'Node 18' },
17
- 'cross-fetch': { replacement: 'fetch()', since: 'Node 18' },
18
- 'isomorphic-fetch': { replacement: 'fetch()', since: 'Node 18' },
19
- 'uuid': { replacement: 'crypto.randomUUID()', since: 'Node 19' },
20
- 'deep-clone': { replacement: 'structuredClone()', since: 'Node 17' },
21
- 'lodash.clonedeep': { replacement: 'structuredClone()', since: 'Node 17' },
22
- 'abort-controller': { replacement: 'AbortController (global)', since: 'Node 15' },
23
- 'form-data': { replacement: 'FormData (global)', since: 'Node 18' },
24
- 'web-streams-polyfill': { replacement: 'ReadableStream (global)', since: 'Node 18' },
25
- 'url-parse': { replacement: 'URL (global)', since: 'Node 10' },
26
- 'querystring': { replacement: 'URLSearchParams', since: 'Node 10' },
27
- 'rimraf': { replacement: 'fs.rm({ recursive: true })', since: 'Node 14' },
28
- 'mkdirp': { replacement: 'fs.mkdir({ recursive: true })', since: 'Node 10' },
29
- 'recursive-readdir': { replacement: 'fs.readdir({ recursive: true })', since: 'Node 20' },
30
- 'glob': { replacement: 'fs.glob()', since: 'Node 22' },
31
- };
32
-
33
- /**
34
- * Legacy code patterns to detect
35
- */
36
- const CODE_PATTERNS = [
37
- {
38
- name: 'var-usage',
39
- description: 'Use const/let instead of var',
40
- check: (node) => node.type === 'VariableDeclaration' && node.kind === 'var',
41
- severity: 'warning',
42
- replacement: 'const/let',
43
- },
44
- {
45
- name: 'require-usage',
46
- description: 'Use ESM import instead of require()',
47
- check: (node) => node.type === 'CallExpression' &&
48
- node.callee.type === 'Identifier' && node.callee.name === 'require',
49
- severity: 'info',
50
- replacement: 'import ... from',
51
- },
52
- {
53
- name: 'module-exports',
54
- description: 'Use ESM export instead of module.exports',
55
- check: (node) => node.type === 'AssignmentExpression' &&
56
- node.left.type === 'MemberExpression' &&
57
- node.left.object.type === 'Identifier' && node.left.object.name === 'module' &&
58
- node.left.property.type === 'Identifier' && node.left.property.name === 'exports',
59
- severity: 'info',
60
- replacement: 'export default/export',
61
- },
62
- {
63
- name: 'buffer-constructor',
64
- description: 'new Buffer() is deprecated',
65
- check: (node) => node.type === 'NewExpression' &&
66
- node.callee.type === 'Identifier' && node.callee.name === 'Buffer',
67
- severity: 'error',
68
- replacement: 'Buffer.from() / Buffer.alloc()',
69
- },
70
- {
71
- name: 'arguments-usage',
72
- description: 'Use rest parameters instead of arguments',
73
- check: (node) => node.type === 'Identifier' && node.name === 'arguments',
74
- severity: 'warning',
75
- replacement: '...args',
76
- },
77
- {
78
- name: 'promisify-usage',
79
- description: 'Use fs/promises instead of util.promisify',
80
- check: (node) => node.type === 'CallExpression' &&
81
- node.callee.type === 'MemberExpression' &&
82
- node.callee.object.type === 'Identifier' && node.callee.object.name === 'util' &&
83
- node.callee.property.type === 'Identifier' && node.callee.property.name === 'promisify',
84
- severity: 'info',
85
- replacement: 'fs/promises module',
86
- },
87
- {
88
- name: 'sync-in-async',
89
- description: 'Avoid sync methods in async context (readFileSync, etc.)',
90
- check: (node, context) => {
91
- if (node.type !== 'CallExpression') return false;
92
- const callee = node.callee;
93
- if (callee.type === 'MemberExpression' && callee.property.type === 'Identifier') {
94
- const name = callee.property.name;
95
- return name.endsWith('Sync') && context.inAsync;
96
- }
97
- return false;
98
- },
99
- severity: 'warning',
100
- replacement: 'async fs/promises methods',
101
- },
102
- ];
103
-
104
- /**
105
- * @typedef {Object} PatternMatch
106
- * @property {string} pattern
107
- * @property {string} description
108
- * @property {string} file
109
- * @property {number} line
110
- * @property {string} severity
111
- * @property {string} replacement
112
- */
113
-
114
- /**
115
- * @typedef {Object} RedundantDep
116
- * @property {string} name
117
- * @property {string} replacement
118
- * @property {string} since
119
- */
120
-
121
- /**
122
- * Find all JS files
123
- * @param {string} dir
124
- * @param {string} rootDir
125
- * @returns {string[]}
126
- */
127
- function findJSFiles(dir, rootDir = dir) {
128
- if (dir === rootDir) parseGitignore(rootDir);
129
- const files = [];
130
-
131
- try {
132
- for (const entry of readdirSync(dir)) {
133
- const fullPath = join(dir, entry);
134
- const relativePath = relative(rootDir, fullPath);
135
- const stat = statSync(fullPath);
136
-
137
- if (stat.isDirectory()) {
138
- if (!shouldExcludeDir(entry, relativePath)) {
139
- files.push(...findJSFiles(fullPath, rootDir));
140
- }
141
- } else if (entry.endsWith('.js') && !entry.endsWith('.css.js') && !entry.endsWith('.tpl.js')) {
142
- if (!shouldExcludeFile(entry, relativePath)) {
143
- files.push(fullPath);
144
- }
145
- }
146
- }
147
- } catch (e) { }
148
-
149
- return files;
150
- }
151
-
152
- /**
153
- * Analyze file for outdated patterns
154
- * @param {string} filePath
155
- * @returns {PatternMatch[]}
156
- */
157
- function analyzeFilePatterns(filePath, rootDir) {
158
- const code = readFileSync(filePath, 'utf-8');
159
- const relPath = relative(rootDir, filePath);
160
- const matches = [];
161
-
162
- let ast;
163
- try {
164
- ast = parse(code, { ecmaVersion: 'latest', sourceType: 'module', locations: true });
165
- } catch (e) {
166
- return matches;
167
- }
168
-
169
- // Track async context
170
- const context = { inAsync: false };
171
-
172
- walk.simple(ast, {
173
- FunctionDeclaration(node) {
174
- context.inAsync = node.async;
175
- },
176
- ArrowFunctionExpression(node) {
177
- context.inAsync = node.async;
178
- },
179
- });
180
-
181
- // Reset and check patterns
182
- context.inAsync = false;
183
-
184
- walk.ancestor(ast, {
185
- '*'(node, ancestors) {
186
- // Update async context
187
- for (const anc of ancestors) {
188
- if ((anc.type === 'FunctionDeclaration' || anc.type === 'ArrowFunctionExpression' ||
189
- anc.type === 'FunctionExpression') && anc.async) {
190
- context.inAsync = true;
191
- break;
192
- }
193
- }
194
-
195
- for (const pattern of CODE_PATTERNS) {
196
- if (pattern.check(node, context)) {
197
- matches.push({
198
- pattern: pattern.name,
199
- description: pattern.description,
200
- file: relPath,
201
- line: node.loc?.start?.line || 0,
202
- severity: pattern.severity,
203
- replacement: pattern.replacement,
204
- });
205
- }
206
- }
207
- },
208
- });
209
-
210
- return matches;
211
- }
212
-
213
- /**
214
- * Analyze package.json for redundant dependencies
215
- * @param {string} dir
216
- * @returns {RedundantDep[]}
217
- */
218
- function analyzePackageJson(dir) {
219
- const pkgPath = join(dir, 'package.json');
220
- const redundant = [];
221
-
222
- if (!existsSync(pkgPath)) return redundant;
223
-
224
- try {
225
- const pkg = JSON.parse(readFileSync(pkgPath, 'utf-8'));
226
- const allDeps = {
227
- ...pkg.dependencies,
228
- ...pkg.devDependencies,
229
- };
230
-
231
- for (const depName of Object.keys(allDeps)) {
232
- if (REDUNDANT_DEPS[depName]) {
233
- redundant.push({
234
- name: depName,
235
- ...REDUNDANT_DEPS[depName],
236
- });
237
- }
238
- }
239
- } catch (e) { }
240
-
241
- return redundant;
242
- }
243
-
244
- /**
245
- * Get outdated patterns analysis
246
- * @param {string} dir
247
- * @param {Object} [options]
248
- * @param {boolean} [options.codeOnly=false] - Only check code patterns
249
- * @param {boolean} [options.depsOnly=false] - Only check dependencies
250
- * @returns {Promise<{codePatterns: PatternMatch[], redundantDeps: RedundantDep[], stats: Object}>}
251
- */
252
- export async function getOutdatedPatterns(dir, options = {}) {
253
- const codeOnly = options.codeOnly || false;
254
- const depsOnly = options.depsOnly || false;
255
- const resolvedDir = resolve(dir);
256
-
257
- let codePatterns = [];
258
- let redundantDeps = [];
259
-
260
- if (!depsOnly) {
261
- const files = findJSFiles(dir);
262
- for (const file of files) {
263
- codePatterns.push(...analyzeFilePatterns(file, resolvedDir));
264
- }
265
- // Sort by severity
266
- const severityOrder = { error: 0, warning: 1, info: 2 };
267
- codePatterns.sort((a, b) => severityOrder[a.severity] - severityOrder[b.severity]);
268
- }
269
-
270
- if (!codeOnly) {
271
- redundantDeps = analyzePackageJson(dir);
272
- }
273
-
274
- const stats = {
275
- totalPatterns: codePatterns.length,
276
- byPattern: {},
277
- bySeverity: {
278
- error: codePatterns.filter(p => p.severity === 'error').length,
279
- warning: codePatterns.filter(p => p.severity === 'warning').length,
280
- info: codePatterns.filter(p => p.severity === 'info').length,
281
- },
282
- redundantDeps: redundantDeps.length,
283
- };
284
-
285
- // Group by pattern name
286
- for (const p of codePatterns) {
287
- stats.byPattern[p.pattern] = (stats.byPattern[p.pattern] || 0) + 1;
288
- }
289
-
290
- return {
291
- codePatterns: codePatterns.slice(0, 50),
292
- redundantDeps,
293
- stats,
294
- };
295
- }