project-graph-mcp 1.5.0 → 2.1.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/README.md +171 -31
- package/docs/img/explorer-compact.jpg +0 -0
- package/docs/img/explorer-expanded.jpg +0 -0
- package/package.json +12 -8
- package/src/.project-graph-cache.json +1 -1
- package/src/analysis/analysis-cache.js +7 -0
- package/src/analysis/complexity.js +14 -0
- package/src/analysis/custom-rules.js +36 -0
- package/src/analysis/db-analysis.js +9 -0
- package/src/analysis/dead-code.js +19 -0
- package/src/analysis/full-analysis.js +18 -0
- package/src/analysis/jsdoc-checker.js +24 -0
- package/src/analysis/jsdoc-generator.js +10 -0
- package/src/analysis/large-files.js +11 -0
- package/src/analysis/outdated-patterns.js +12 -0
- package/src/analysis/similar-functions.js +16 -0
- package/src/analysis/test-annotations.js +21 -0
- package/src/analysis/type-checker.js +8 -0
- package/src/analysis/undocumented.js +14 -0
- package/src/cli/cli-handlers.js +4 -0
- package/src/cli/cli.js +5 -0
- package/src/compact/.project-graph-cache.json +1 -0
- package/src/compact/ai-context.js +7 -0
- package/src/compact/compact-migrate.js +17 -0
- package/src/compact/compact.js +18 -0
- package/src/compact/compress.js +14 -0
- package/src/compact/ctx-to-jsdoc.js +29 -0
- package/src/compact/doc-dialect.js +30 -0
- package/src/compact/expand.js +37 -0
- package/src/compact/framework-references.js +5 -0
- package/src/compact/instructions.js +3 -0
- package/src/compact/mode-config.js +8 -0
- package/src/compact/validate-pipeline.js +9 -0
- package/src/core/event-bus.js +9 -0
- package/src/core/filters.js +14 -0
- package/src/core/graph-builder.js +12 -0
- package/src/core/parser.js +31 -0
- package/src/core/workspace.js +8 -0
- package/src/lang/lang-go.js +17 -0
- package/src/lang/lang-python.js +12 -0
- package/src/lang/lang-sql.js +23 -0
- package/src/lang/lang-typescript.js +9 -0
- package/src/lang/lang-utils.js +4 -0
- package/src/mcp/mcp-server.js +17 -0
- package/src/mcp/tool-defs.js +3 -0
- package/src/mcp/tools.js +25 -0
- package/src/network/backend-lifecycle.js +19 -0
- package/src/network/backend.js +5 -0
- package/src/network/local-gateway.js +23 -0
- package/src/network/mdns.js +13 -0
- package/src/network/server.js +10 -0
- package/src/network/web-server.js +34 -0
- package/web/.project-graph-cache.json +1 -0
- package/web/app.js +17 -0
- package/web/components/code-block.js +3 -0
- package/web/components/quick-open.js +5 -0
- package/web/dashboard-state.js +3 -0
- package/web/dashboard.html +27 -0
- package/web/dashboard.js +8 -0
- package/web/highlight.js +13 -0
- package/web/index.html +35 -0
- package/web/panels/ActionBoard/ActionBoard.css.js +1 -0
- package/web/panels/ActionBoard/ActionBoard.js +4 -0
- package/web/panels/ActionBoard/ActionBoard.tpl.js +1 -0
- package/web/panels/EventItem/EventItem.css.js +1 -0
- package/web/panels/EventItem/EventItem.js +4 -0
- package/web/panels/EventItem/EventItem.tpl.js +1 -0
- package/web/panels/ProjectItem/ProjectItem.css.js +1 -0
- package/web/panels/ProjectItem/ProjectItem.js +5 -0
- package/web/panels/ProjectItem/ProjectItem.tpl.js +1 -0
- package/web/panels/ProjectList/ProjectList.css.js +1 -0
- package/web/panels/ProjectList/ProjectList.js +4 -0
- package/web/panels/ProjectList/ProjectList.tpl.js +1 -0
- package/web/panels/SettingsPanel/.project-graph-cache.json +1 -0
- package/web/panels/SettingsPanel/SettingsPanel.css.js +1 -0
- package/web/panels/SettingsPanel/SettingsPanel.js +7 -0
- package/web/panels/SettingsPanel/SettingsPanel.tpl.js +1 -0
- package/web/panels/code-viewer.js +5 -0
- package/web/panels/ctx-panel.js +4 -0
- package/web/panels/dep-graph.js +6 -0
- package/web/panels/file-tree.js +188 -0
- package/web/panels/health-panel.js +3 -0
- package/web/panels/live-monitor.js +3 -0
- package/web/state.js +17 -0
- package/web/style.css +157 -0
- package/references/symbiote-3x.md +0 -834
- package/src/ai-context.js +0 -113
- package/src/analysis-cache.js +0 -155
- package/src/cli-handlers.js +0 -271
- package/src/cli.js +0 -95
- package/src/compact.js +0 -207
- package/src/complexity.js +0 -237
- package/src/compress.js +0 -319
- package/src/ctx-to-jsdoc.js +0 -514
- package/src/custom-rules.js +0 -584
- package/src/db-analysis.js +0 -194
- package/src/dead-code.js +0 -468
- package/src/doc-dialect.js +0 -716
- package/src/filters.js +0 -227
- package/src/framework-references.js +0 -177
- package/src/full-analysis.js +0 -470
- package/src/graph-builder.js +0 -299
- package/src/instructions.js +0 -73
- package/src/jsdoc-checker.js +0 -351
- package/src/jsdoc-generator.js +0 -203
- package/src/lang-go.js +0 -285
- package/src/lang-python.js +0 -197
- package/src/lang-sql.js +0 -309
- package/src/lang-typescript.js +0 -190
- package/src/lang-utils.js +0 -124
- package/src/large-files.js +0 -163
- package/src/mcp-server.js +0 -675
- package/src/mode-config.js +0 -127
- package/src/outdated-patterns.js +0 -296
- package/src/parser.js +0 -662
- package/src/server.js +0 -28
- package/src/similar-functions.js +0 -279
- package/src/test-annotations.js +0 -323
- package/src/tool-defs.js +0 -793
- package/src/tools.js +0 -470
- package/src/type-checker.js +0 -188
- package/src/undocumented.js +0 -259
- package/src/workspace.js +0 -70
- /package/{AGENT_ROLE.md → docs/examples/AGENT_ROLE.md} +0 -0
- /package/{AGENT_ROLE_MINIMAL.md → docs/examples/AGENT_ROLE_MINIMAL.md} +0 -0
package/src/graph-builder.js
DELETED
|
@@ -1,299 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Graph Builder - Creates minified project graph from parsed data
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
/**
|
|
6
|
-
* @typedef {Object} GraphNode
|
|
7
|
-
* @property {string} t - type (class/func)
|
|
8
|
-
* @property {string} [x] - extends
|
|
9
|
-
* @property {string[]} [m] - methods
|
|
10
|
-
* @property {string[]} [$] - properties (init$)
|
|
11
|
-
* @property {string[]} [i] - imports
|
|
12
|
-
* @property {string[]} [→] - calls (outgoing)
|
|
13
|
-
* @property {string[]} [←] - usedBy (incoming)
|
|
14
|
-
* @property {string} [f] - source file path
|
|
15
|
-
* @property {boolean} [e] - exported flag (functions)
|
|
16
|
-
*/
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @typedef {Object} Graph
|
|
20
|
-
* @property {number} v - version
|
|
21
|
-
* @property {Object<string, string>} legend - minified name → full name
|
|
22
|
-
* @property {Object<string, string>} reverseLegend - full name → minified
|
|
23
|
-
* @property {Object} stats - { files, classes, functions, tables }
|
|
24
|
-
* @property {Object<string, GraphNode>} nodes
|
|
25
|
-
* @property {Array<[string, string, string]>} edges - [from, type, to] where type is →, R→, or W→
|
|
26
|
-
* @property {string[]} orphans
|
|
27
|
-
* @property {Object<string, string[]>} duplicates
|
|
28
|
-
* @property {string[]} files - list of parsed file paths
|
|
29
|
-
*/
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Create minified legend from names
|
|
33
|
-
* Strategy: Use camelCase initials + suffix if collision
|
|
34
|
-
* @param {string[]} names
|
|
35
|
-
* @returns {Object<string, string>}
|
|
36
|
-
*/
|
|
37
|
-
export function minifyLegend(names) {
|
|
38
|
-
const legend = {};
|
|
39
|
-
const used = new Set();
|
|
40
|
-
|
|
41
|
-
for (const name of names) {
|
|
42
|
-
let short = createShortName(name);
|
|
43
|
-
let suffix = 1;
|
|
44
|
-
|
|
45
|
-
while (used.has(short)) {
|
|
46
|
-
short = createShortName(name) + suffix;
|
|
47
|
-
suffix++;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
used.add(short);
|
|
51
|
-
legend[name] = short;
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
return legend;
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
/**
|
|
58
|
-
* Create short name from full name
|
|
59
|
-
* SymNode → SN, togglePin → tP, autoArrange → aA
|
|
60
|
-
* @param {string} name
|
|
61
|
-
* @returns {string}
|
|
62
|
-
*/
|
|
63
|
-
function createShortName(name) {
|
|
64
|
-
// For PascalCase: extract uppercase letters
|
|
65
|
-
const upperOnly = name.replace(/[a-z]/g, '');
|
|
66
|
-
if (upperOnly.length >= 2) {
|
|
67
|
-
return upperOnly.slice(0, 3);
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
// For camelCase: first letter + next uppercase
|
|
71
|
-
const firstUpper = name.match(/[A-Z]/g);
|
|
72
|
-
if (firstUpper && firstUpper.length > 0) {
|
|
73
|
-
return name[0].toLowerCase() + firstUpper[0];
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
// Fallback: first 2 letters
|
|
77
|
-
return name.slice(0, 2);
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Build graph from parsed project data
|
|
82
|
-
* @param {import('./parser.js').ParseResult} parsed
|
|
83
|
-
* @returns {Graph}
|
|
84
|
-
*/
|
|
85
|
-
export function buildGraph(parsed) {
|
|
86
|
-
// Collect all names for legend
|
|
87
|
-
const classes = parsed.classes || [];
|
|
88
|
-
const functions = parsed.functions || [];
|
|
89
|
-
|
|
90
|
-
const allNames = [
|
|
91
|
-
...classes.map(c => c.name),
|
|
92
|
-
...functions.map(f => f.name),
|
|
93
|
-
...classes.flatMap(c => c.methods || []),
|
|
94
|
-
];
|
|
95
|
-
|
|
96
|
-
const legend = minifyLegend([...new Set(allNames)]);
|
|
97
|
-
const reverseLegend = Object.fromEntries(
|
|
98
|
-
Object.entries(legend).map(([k, v]) => [v, k])
|
|
99
|
-
);
|
|
100
|
-
|
|
101
|
-
const graph = {
|
|
102
|
-
v: 1,
|
|
103
|
-
legend,
|
|
104
|
-
reverseLegend,
|
|
105
|
-
stats: {
|
|
106
|
-
files: (parsed.files || []).length,
|
|
107
|
-
classes: classes.length,
|
|
108
|
-
functions: functions.length,
|
|
109
|
-
tables: (parsed.tables || []).length,
|
|
110
|
-
},
|
|
111
|
-
nodes: {},
|
|
112
|
-
edges: [],
|
|
113
|
-
orphans: [],
|
|
114
|
-
duplicates: {},
|
|
115
|
-
files: parsed.files || [],
|
|
116
|
-
};
|
|
117
|
-
|
|
118
|
-
// Build class nodes
|
|
119
|
-
for (const cls of classes) {
|
|
120
|
-
const shortName = legend[cls.name];
|
|
121
|
-
graph.nodes[shortName] = {
|
|
122
|
-
t: 'C',
|
|
123
|
-
x: cls.extends || undefined,
|
|
124
|
-
m: (cls.methods || []).map(m => legend[m] || m),
|
|
125
|
-
$: (cls.properties || []).length ? cls.properties : undefined,
|
|
126
|
-
i: cls.imports?.length ? cls.imports : undefined,
|
|
127
|
-
f: cls.file || undefined,
|
|
128
|
-
};
|
|
129
|
-
|
|
130
|
-
// Build edges from calls
|
|
131
|
-
for (const call of cls.calls || []) {
|
|
132
|
-
if (call.includes('.')) {
|
|
133
|
-
// Class.method() pattern
|
|
134
|
-
const [target, method] = call.split('.');
|
|
135
|
-
if (legend[target]) {
|
|
136
|
-
const edge = [shortName, '→', `${legend[target]}.${legend[method] || method}`];
|
|
137
|
-
graph.edges.push(edge);
|
|
138
|
-
}
|
|
139
|
-
} else {
|
|
140
|
-
// Standalone function call
|
|
141
|
-
if (legend[call]) {
|
|
142
|
-
const edge = [shortName, '→', legend[call]];
|
|
143
|
-
graph.edges.push(edge);
|
|
144
|
-
}
|
|
145
|
-
}
|
|
146
|
-
}
|
|
147
|
-
}
|
|
148
|
-
|
|
149
|
-
// Build function nodes
|
|
150
|
-
for (const func of functions) {
|
|
151
|
-
const shortName = legend[func.name];
|
|
152
|
-
graph.nodes[shortName] = {
|
|
153
|
-
t: 'F',
|
|
154
|
-
e: func.exported,
|
|
155
|
-
f: func.file || undefined,
|
|
156
|
-
};
|
|
157
|
-
|
|
158
|
-
// Build DB edges from function SQL reads/writes
|
|
159
|
-
for (const table of func.dbReads || []) {
|
|
160
|
-
graph.edges.push([shortName, 'R→', table]);
|
|
161
|
-
}
|
|
162
|
-
for (const table of func.dbWrites || []) {
|
|
163
|
-
graph.edges.push([shortName, 'W→', table]);
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
// Build DB edges from class SQL reads/writes
|
|
168
|
-
for (const cls of classes) {
|
|
169
|
-
const shortName = legend[cls.name];
|
|
170
|
-
for (const table of cls.dbReads || []) {
|
|
171
|
-
graph.edges.push([shortName, 'R→', table]);
|
|
172
|
-
}
|
|
173
|
-
for (const table of cls.dbWrites || []) {
|
|
174
|
-
graph.edges.push([shortName, 'W→', table]);
|
|
175
|
-
}
|
|
176
|
-
}
|
|
177
|
-
|
|
178
|
-
// Build table nodes from parsed SQL files
|
|
179
|
-
for (const table of parsed.tables || []) {
|
|
180
|
-
graph.nodes[table.name] = {
|
|
181
|
-
t: 'T',
|
|
182
|
-
cols: table.columns.map(c => c.name),
|
|
183
|
-
f: table.file || undefined,
|
|
184
|
-
};
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Detect orphans (nodes with no incoming edges)
|
|
188
|
-
const hasIncoming = new Set();
|
|
189
|
-
for (const edge of graph.edges) {
|
|
190
|
-
const target = edge[2].split('.')[0];
|
|
191
|
-
hasIncoming.add(target);
|
|
192
|
-
}
|
|
193
|
-
|
|
194
|
-
for (const name of Object.keys(graph.nodes)) {
|
|
195
|
-
if (!hasIncoming.has(name) && graph.nodes[name].t === 'F' && !graph.nodes[name].e) {
|
|
196
|
-
graph.orphans.push(reverseLegend[name]);
|
|
197
|
-
}
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
// Detect duplicates (same method name in multiple classes)
|
|
201
|
-
const methodLocations = Object.create(null);
|
|
202
|
-
for (const cls of classes) {
|
|
203
|
-
for (const method of cls.methods || []) {
|
|
204
|
-
if (!methodLocations[method]) {
|
|
205
|
-
methodLocations[method] = [];
|
|
206
|
-
}
|
|
207
|
-
methodLocations[method].push(`${cls.name}:${cls.line}`);
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
for (const [method, locations] of Object.entries(methodLocations)) {
|
|
212
|
-
if (locations.length > 1) {
|
|
213
|
-
graph.duplicates[method] = locations;
|
|
214
|
-
}
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
return graph;
|
|
218
|
-
}
|
|
219
|
-
|
|
220
|
-
/**
|
|
221
|
-
* Create compact skeleton (minimal tokens)
|
|
222
|
-
* @param {Graph} graph
|
|
223
|
-
* @returns {Object}
|
|
224
|
-
*/
|
|
225
|
-
export function createSkeleton(graph) {
|
|
226
|
-
const legend = {};
|
|
227
|
-
const nodes = {};
|
|
228
|
-
|
|
229
|
-
// Build class nodes with file path
|
|
230
|
-
// graph.legend = {fullName → shortName}
|
|
231
|
-
for (const [full, short] of Object.entries(graph.legend)) {
|
|
232
|
-
const node = graph.nodes[short];
|
|
233
|
-
if (!node) continue;
|
|
234
|
-
|
|
235
|
-
if (node.t === 'C') {
|
|
236
|
-
// Skip empty classes (0 methods, 0 props)
|
|
237
|
-
const methodCount = node.m?.length || 0;
|
|
238
|
-
const propCount = node.$?.length || 0;
|
|
239
|
-
if (methodCount === 0 && propCount === 0) continue;
|
|
240
|
-
|
|
241
|
-
legend[short] = full;
|
|
242
|
-
const entry = { m: methodCount };
|
|
243
|
-
if (propCount > 0) entry.$ = propCount;
|
|
244
|
-
if (node.f) entry.f = node.f;
|
|
245
|
-
nodes[short] = entry;
|
|
246
|
-
}
|
|
247
|
-
// Skip Table nodes (T) — they only appear in dedicated DB tools
|
|
248
|
-
}
|
|
249
|
-
|
|
250
|
-
// Build exported functions grouped by file: { "file.js": ["shortName1", ...] }
|
|
251
|
-
// Also add function names to legend
|
|
252
|
-
const exportsByFile = {};
|
|
253
|
-
for (const [full, short] of Object.entries(graph.legend)) {
|
|
254
|
-
const node = graph.nodes[short];
|
|
255
|
-
if (node?.t === 'F' && node.e) {
|
|
256
|
-
legend[short] = full;
|
|
257
|
-
const file = node.f || '?';
|
|
258
|
-
if (!exportsByFile[file]) exportsByFile[file] = [];
|
|
259
|
-
exportsByFile[file].push(short);
|
|
260
|
-
}
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
// Build file tree grouped by directory (only files not covered by n/X)
|
|
264
|
-
const coveredFiles = new Set();
|
|
265
|
-
for (const v of Object.values(nodes)) {
|
|
266
|
-
if (v.f) coveredFiles.add(v.f);
|
|
267
|
-
}
|
|
268
|
-
for (const file of Object.keys(exportsByFile)) {
|
|
269
|
-
coveredFiles.add(file);
|
|
270
|
-
}
|
|
271
|
-
|
|
272
|
-
const fileTree = {};
|
|
273
|
-
for (const filePath of graph.files || []) {
|
|
274
|
-
if (coveredFiles.has(filePath)) continue;
|
|
275
|
-
const lastSlash = filePath.lastIndexOf('/');
|
|
276
|
-
const dir = lastSlash >= 0 ? filePath.slice(0, lastSlash + 1) : './';
|
|
277
|
-
const file = lastSlash >= 0 ? filePath.slice(lastSlash + 1) : filePath;
|
|
278
|
-
if (!fileTree[dir]) fileTree[dir] = [];
|
|
279
|
-
fileTree[dir].push(file);
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
const result = {
|
|
283
|
-
v: graph.v,
|
|
284
|
-
L: legend,
|
|
285
|
-
s: graph.stats,
|
|
286
|
-
n: nodes,
|
|
287
|
-
X: exportsByFile,
|
|
288
|
-
e: graph.edges.length,
|
|
289
|
-
o: graph.orphans.length,
|
|
290
|
-
d: Object.keys(graph.duplicates).length,
|
|
291
|
-
};
|
|
292
|
-
|
|
293
|
-
// Only add uncovered files if there are any
|
|
294
|
-
if (Object.keys(fileTree).length > 0) {
|
|
295
|
-
result.f = fileTree;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
return result;
|
|
299
|
-
}
|
package/src/instructions.js
DELETED
|
@@ -1,73 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Project Guidelines and Instructions for AI Agents
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
export const AGENT_INSTRUCTIONS = `
|
|
6
|
-
# 🤖 Project Guidelines for AI Agents
|
|
7
|
-
|
|
8
|
-
## 1. Architecture Standards (Symbiote.js)
|
|
9
|
-
- **Component Structure**: Always use Triple-File Partitioning for components:
|
|
10
|
-
- \`MyComponent.js\`: Class logic (extends Symbiote)
|
|
11
|
-
- \`MyComponent.tpl.js\`: HTML template (export template)
|
|
12
|
-
- \`MyComponent.css.js\`: CSS styles (export rootStyles/shadowStyles)
|
|
13
|
-
- **State Management**: Use \`this.init$\` for local state and \`this.sub()\` for reactivity.
|
|
14
|
-
- **Directives**: Use \`itemize\` for lists, \`js-d-kit\` for static generation.
|
|
15
|
-
|
|
16
|
-
## 2. General Coding Rules
|
|
17
|
-
- **ESM Only**: Use \`import\` / \`export\`. No \`require\`.
|
|
18
|
-
- **No Dependencies**: Avoid adding new npm packages unless critical.
|
|
19
|
-
- **Comments**: Write clear JSDoc for all public methods.
|
|
20
|
-
- **Async/Await**: Prefer async/await over promises.
|
|
21
|
-
|
|
22
|
-
## 3. MCP Tools Usage
|
|
23
|
-
- **Graph**: Use \`get_skeleton\` first to map the codebase.
|
|
24
|
-
- **Deep Dive**: Use \`expand\` to read class details.
|
|
25
|
-
- **Tests**: Use \`get_pending_tests\` to see what needs verification.
|
|
26
|
-
- **Guidelines**: Use \`get_agent_instructions\` to refresh these rules.
|
|
27
|
-
|
|
28
|
-
## 4. Custom Rules System
|
|
29
|
-
Configurable code analysis with auto-detection.
|
|
30
|
-
|
|
31
|
-
### Available Tools
|
|
32
|
-
- \`get_custom_rules\`: List all rulesets and their rules
|
|
33
|
-
- \`set_custom_rule\`: Add or update a rule in a ruleset
|
|
34
|
-
- \`check_custom_rules\`: Run analysis (auto-detects applicable rulesets)
|
|
35
|
-
|
|
36
|
-
### Auto-Detection
|
|
37
|
-
Rulesets are applied automatically based on:
|
|
38
|
-
1. \`package.json\` dependencies
|
|
39
|
-
2. Import patterns in source code
|
|
40
|
-
3. Code patterns (e.g., \`extends Symbiote\`)
|
|
41
|
-
|
|
42
|
-
### Creating New Rules
|
|
43
|
-
Use \`set_custom_rule\` to add framework-specific rules:
|
|
44
|
-
\`\`\`json
|
|
45
|
-
{
|
|
46
|
-
"ruleSet": "my-framework-2x",
|
|
47
|
-
"rule": {
|
|
48
|
-
"id": "my-rule-id",
|
|
49
|
-
"name": "Rule Name",
|
|
50
|
-
"description": "What this rule checks",
|
|
51
|
-
"pattern": "badPattern",
|
|
52
|
-
"patternType": "string",
|
|
53
|
-
"replacement": "Use goodPattern instead",
|
|
54
|
-
"severity": "warning",
|
|
55
|
-
"filePattern": "*.js",
|
|
56
|
-
"docs": "https://docs.example.com/rule"
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
\`\`\`
|
|
60
|
-
|
|
61
|
-
### Severity Levels
|
|
62
|
-
- \`error\`: Critical issues that must be fixed
|
|
63
|
-
- \`warning\`: Important but not blocking
|
|
64
|
-
- \`info\`: Suggestions and best practices
|
|
65
|
-
`;
|
|
66
|
-
|
|
67
|
-
/**
|
|
68
|
-
* Get agent instructions
|
|
69
|
-
* @returns {string}
|
|
70
|
-
*/
|
|
71
|
-
export function getInstructions() {
|
|
72
|
-
return AGENT_INSTRUCTIONS;
|
|
73
|
-
}
|