@theihtisham/agent-shadow-brain 1.2.0 → 3.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.
- package/README.md +837 -73
- package/dist/adapters/aider.d.ts +11 -0
- package/dist/adapters/aider.d.ts.map +1 -0
- package/dist/adapters/aider.js +149 -0
- package/dist/adapters/aider.js.map +1 -0
- package/dist/adapters/index.d.ts +3 -1
- package/dist/adapters/index.d.ts.map +1 -1
- package/dist/adapters/index.js +5 -3
- package/dist/adapters/index.js.map +1 -1
- package/dist/adapters/roo-code.d.ts +14 -0
- package/dist/adapters/roo-code.d.ts.map +1 -0
- package/dist/adapters/roo-code.js +186 -0
- package/dist/adapters/roo-code.js.map +1 -0
- package/dist/brain/accessibility-checker.d.ts +10 -0
- package/dist/brain/accessibility-checker.d.ts.map +1 -0
- package/dist/brain/accessibility-checker.js +379 -0
- package/dist/brain/accessibility-checker.js.map +1 -0
- package/dist/brain/adr-engine.d.ts +58 -0
- package/dist/brain/adr-engine.d.ts.map +1 -0
- package/dist/brain/adr-engine.js +400 -0
- package/dist/brain/adr-engine.js.map +1 -0
- package/dist/brain/api-contract-analyzer.d.ts +19 -0
- package/dist/brain/api-contract-analyzer.d.ts.map +1 -0
- package/dist/brain/api-contract-analyzer.js +251 -0
- package/dist/brain/api-contract-analyzer.js.map +1 -0
- package/dist/brain/ast-analyzer.d.ts +23 -0
- package/dist/brain/ast-analyzer.d.ts.map +1 -0
- package/dist/brain/ast-analyzer.js +462 -0
- package/dist/brain/ast-analyzer.js.map +1 -0
- package/dist/brain/code-age-analyzer.d.ts +11 -0
- package/dist/brain/code-age-analyzer.d.ts.map +1 -0
- package/dist/brain/code-age-analyzer.js +152 -0
- package/dist/brain/code-age-analyzer.js.map +1 -0
- package/dist/brain/code-similarity.d.ts +43 -0
- package/dist/brain/code-similarity.d.ts.map +1 -0
- package/dist/brain/code-similarity.js +227 -0
- package/dist/brain/code-similarity.js.map +1 -0
- package/dist/brain/config-drift-detector.d.ts +13 -0
- package/dist/brain/config-drift-detector.d.ts.map +1 -0
- package/dist/brain/config-drift-detector.js +198 -0
- package/dist/brain/config-drift-detector.js.map +1 -0
- package/dist/brain/context-completion.d.ts +39 -0
- package/dist/brain/context-completion.d.ts.map +1 -0
- package/dist/brain/context-completion.js +851 -0
- package/dist/brain/context-completion.js.map +1 -0
- package/dist/brain/dead-code-eliminator.d.ts +16 -0
- package/dist/brain/dead-code-eliminator.d.ts.map +1 -0
- package/dist/brain/dead-code-eliminator.js +359 -0
- package/dist/brain/dead-code-eliminator.js.map +1 -0
- package/dist/brain/dependency-graph.d.ts +35 -0
- package/dist/brain/dependency-graph.d.ts.map +1 -0
- package/dist/brain/dependency-graph.js +310 -0
- package/dist/brain/dependency-graph.js.map +1 -0
- package/dist/brain/env-analyzer.d.ts +13 -0
- package/dist/brain/env-analyzer.d.ts.map +1 -0
- package/dist/brain/env-analyzer.js +277 -0
- package/dist/brain/env-analyzer.js.map +1 -0
- package/dist/brain/i18n-detector.d.ts +12 -0
- package/dist/brain/i18n-detector.d.ts.map +1 -0
- package/dist/brain/i18n-detector.js +242 -0
- package/dist/brain/i18n-detector.js.map +1 -0
- package/dist/brain/learning-engine.d.ts +54 -0
- package/dist/brain/learning-engine.d.ts.map +1 -0
- package/dist/brain/learning-engine.js +855 -0
- package/dist/brain/learning-engine.js.map +1 -0
- package/dist/brain/license-compliance.d.ts +13 -0
- package/dist/brain/license-compliance.d.ts.map +1 -0
- package/dist/brain/license-compliance.js +213 -0
- package/dist/brain/license-compliance.js.map +1 -0
- package/dist/brain/llm-client.d.ts.map +1 -1
- package/dist/brain/llm-client.js +3 -0
- package/dist/brain/llm-client.js.map +1 -1
- package/dist/brain/mcp-server.d.ts +30 -0
- package/dist/brain/mcp-server.d.ts.map +1 -0
- package/dist/brain/mcp-server.js +408 -0
- package/dist/brain/mcp-server.js.map +1 -0
- package/dist/brain/multi-project.d.ts +13 -0
- package/dist/brain/multi-project.d.ts.map +1 -0
- package/dist/brain/multi-project.js +163 -0
- package/dist/brain/multi-project.js.map +1 -0
- package/dist/brain/mutation-advisor.d.ts +11 -0
- package/dist/brain/mutation-advisor.d.ts.map +1 -0
- package/dist/brain/mutation-advisor.js +154 -0
- package/dist/brain/mutation-advisor.js.map +1 -0
- package/dist/brain/neural-mesh.d.ts +69 -0
- package/dist/brain/neural-mesh.d.ts.map +1 -0
- package/dist/brain/neural-mesh.js +677 -0
- package/dist/brain/neural-mesh.js.map +1 -0
- package/dist/brain/orchestrator.d.ts +159 -2
- package/dist/brain/orchestrator.d.ts.map +1 -1
- package/dist/brain/orchestrator.js +478 -0
- package/dist/brain/orchestrator.js.map +1 -1
- package/dist/brain/perf-profiler.d.ts +14 -0
- package/dist/brain/perf-profiler.d.ts.map +1 -0
- package/dist/brain/perf-profiler.js +289 -0
- package/dist/brain/perf-profiler.js.map +1 -0
- package/dist/brain/semantic-analyzer.d.ts +46 -0
- package/dist/brain/semantic-analyzer.d.ts.map +1 -0
- package/dist/brain/semantic-analyzer.js +496 -0
- package/dist/brain/semantic-analyzer.js.map +1 -0
- package/dist/brain/team-mode.d.ts +27 -0
- package/dist/brain/team-mode.d.ts.map +1 -0
- package/dist/brain/team-mode.js +262 -0
- package/dist/brain/team-mode.js.map +1 -0
- package/dist/brain/type-safety.d.ts +13 -0
- package/dist/brain/type-safety.d.ts.map +1 -0
- package/dist/brain/type-safety.js +217 -0
- package/dist/brain/type-safety.js.map +1 -0
- package/dist/cli.js +998 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +25 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +29 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +379 -2
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-age-analyzer.js","sourceRoot":"","sources":["../../src/brain/code-age-analyzer.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { DuplicateGroup } from '../types.js';
|
|
2
|
+
export declare class CodeSimilarityDetector {
|
|
3
|
+
private projectDir;
|
|
4
|
+
constructor(projectDir: string);
|
|
5
|
+
/**
|
|
6
|
+
* Scan all source files for duplicate code blocks.
|
|
7
|
+
* Returns groups of blocks whose pairwise similarity >= minSimilarity.
|
|
8
|
+
*/
|
|
9
|
+
detectDuplicates(minSimilarity?: number): Promise<DuplicateGroup[]>;
|
|
10
|
+
/**
|
|
11
|
+
* Walk the project tree, read each source file, and extract code blocks.
|
|
12
|
+
*/
|
|
13
|
+
private collectAllBlocks;
|
|
14
|
+
/**
|
|
15
|
+
* Split a single file into code blocks by tracking brace depth.
|
|
16
|
+
* Recognises the block type (function, method, class, generic block).
|
|
17
|
+
* Only returns blocks with >= 6 lines.
|
|
18
|
+
*/
|
|
19
|
+
private extractBlocks;
|
|
20
|
+
/**
|
|
21
|
+
* Compute Jaccard similarity between two code blocks.
|
|
22
|
+
* Tokenises content into word tokens, then calculates |intersection| / |union|.
|
|
23
|
+
*/
|
|
24
|
+
private computeSimilarity;
|
|
25
|
+
/**
|
|
26
|
+
* Split content into individual word tokens and return as a Set.
|
|
27
|
+
* Strips punctuation and normalises to lowercase for comparison.
|
|
28
|
+
*/
|
|
29
|
+
private tokenize;
|
|
30
|
+
/**
|
|
31
|
+
* Generate a refactoring suggestion based on the types of the duplicate blocks.
|
|
32
|
+
*/
|
|
33
|
+
private suggestRefactor;
|
|
34
|
+
/**
|
|
35
|
+
* Walk a directory tree, returning full paths of source files.
|
|
36
|
+
*/
|
|
37
|
+
private walkDir;
|
|
38
|
+
/**
|
|
39
|
+
* Produce a unique key for a block (file path + line range).
|
|
40
|
+
*/
|
|
41
|
+
private blockKey;
|
|
42
|
+
}
|
|
43
|
+
//# sourceMappingURL=code-similarity.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-similarity.d.ts","sourceRoot":"","sources":["../../src/brain/code-similarity.ts"],"names":[],"mappings":"AAIA,OAAO,EAAa,cAAc,EAAE,MAAM,aAAa,CAAC;AASxD,qBAAa,sBAAsB;IACjC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAI9B;;;OAGG;IACG,gBAAgB,CAAC,aAAa,GAAE,MAAY,GAAG,OAAO,CAAC,cAAc,EAAE,CAAC;IA6C9E;;OAEG;IACH,OAAO,CAAC,gBAAgB;IAiBxB;;;;OAIG;IACH,OAAO,CAAC,aAAa;IAoErB;;;OAGG;IACH,OAAO,CAAC,iBAAiB;IAgBzB;;;OAGG;IACH,OAAO,CAAC,QAAQ;IAShB;;OAEG;IACH,OAAO,CAAC,eAAe;IA6BvB;;OAEG;IACH,OAAO,CAAC,OAAO;IA2Bf;;OAEG;IACH,OAAO,CAAC,QAAQ;CAGjB"}
|
|
@@ -0,0 +1,227 @@
|
|
|
1
|
+
// src/brain/code-similarity.ts — Detect duplicate/near-duplicate code blocks across a project
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
const SOURCE_EXTENSIONS = new Set(['.ts', '.tsx', '.js', '.jsx']);
|
|
5
|
+
const IGNORE_DIRS = new Set([
|
|
6
|
+
'node_modules', '.git', 'dist', 'build', 'out', 'coverage',
|
|
7
|
+
'.cache', '.next', '.nuxt', 'vendor', '__pycache__',
|
|
8
|
+
]);
|
|
9
|
+
export class CodeSimilarityDetector {
|
|
10
|
+
constructor(projectDir) {
|
|
11
|
+
this.projectDir = projectDir;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Scan all source files for duplicate code blocks.
|
|
15
|
+
* Returns groups of blocks whose pairwise similarity >= minSimilarity.
|
|
16
|
+
*/
|
|
17
|
+
async detectDuplicates(minSimilarity = 0.8) {
|
|
18
|
+
const allBlocks = this.collectAllBlocks();
|
|
19
|
+
const groups = [];
|
|
20
|
+
// Only consider blocks with 6+ lines
|
|
21
|
+
const eligible = allBlocks.filter(b => (b.endLine - b.startLine + 1) >= 6);
|
|
22
|
+
// Track which blocks have already been grouped to avoid duplicates
|
|
23
|
+
const assigned = new Set();
|
|
24
|
+
for (let i = 0; i < eligible.length; i++) {
|
|
25
|
+
const keyA = this.blockKey(eligible[i]);
|
|
26
|
+
if (assigned.has(keyA))
|
|
27
|
+
continue;
|
|
28
|
+
const similar = [eligible[i]];
|
|
29
|
+
for (let j = i + 1; j < eligible.length; j++) {
|
|
30
|
+
const keyB = this.blockKey(eligible[j]);
|
|
31
|
+
if (assigned.has(keyB))
|
|
32
|
+
continue;
|
|
33
|
+
// Skip self-comparison (same file + same line range)
|
|
34
|
+
if (keyA === keyB)
|
|
35
|
+
continue;
|
|
36
|
+
const sim = this.computeSimilarity(eligible[i], eligible[j]);
|
|
37
|
+
if (sim >= minSimilarity) {
|
|
38
|
+
similar.push(eligible[j]);
|
|
39
|
+
assigned.add(keyB);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
if (similar.length > 1) {
|
|
43
|
+
assigned.add(keyA);
|
|
44
|
+
groups.push({
|
|
45
|
+
blocks: similar,
|
|
46
|
+
similarity: minSimilarity,
|
|
47
|
+
suggestedRefactor: this.suggestRefactor(similar),
|
|
48
|
+
});
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return groups;
|
|
52
|
+
}
|
|
53
|
+
// ── Private Helpers ────────────────────────────────────────────────────────
|
|
54
|
+
/**
|
|
55
|
+
* Walk the project tree, read each source file, and extract code blocks.
|
|
56
|
+
*/
|
|
57
|
+
collectAllBlocks() {
|
|
58
|
+
const files = this.walkDir(this.projectDir);
|
|
59
|
+
const blocks = [];
|
|
60
|
+
for (const filePath of files) {
|
|
61
|
+
try {
|
|
62
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
63
|
+
const extracted = this.extractBlocks(filePath, content);
|
|
64
|
+
blocks.push(...extracted);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
// unreadable file — skip
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return blocks;
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Split a single file into code blocks by tracking brace depth.
|
|
74
|
+
* Recognises the block type (function, method, class, generic block).
|
|
75
|
+
* Only returns blocks with >= 6 lines.
|
|
76
|
+
*/
|
|
77
|
+
extractBlocks(filePath, content) {
|
|
78
|
+
const blocks = [];
|
|
79
|
+
const lines = content.split('\n');
|
|
80
|
+
let depth = 0;
|
|
81
|
+
let blockStart = -1;
|
|
82
|
+
let blockType = 'block';
|
|
83
|
+
let pendingType = 'block';
|
|
84
|
+
for (let i = 0; i < lines.length; i++) {
|
|
85
|
+
const line = lines[i];
|
|
86
|
+
// Detect what kind of block is about to open
|
|
87
|
+
if (depth === 0) {
|
|
88
|
+
const trimmed = line.trim();
|
|
89
|
+
if (/\bclass\b/.test(trimmed) && /\{/.test(trimmed)) {
|
|
90
|
+
pendingType = 'class';
|
|
91
|
+
}
|
|
92
|
+
else if (/\b(function\b|=>\s*\{|async\s+function\b|\*\s*\w+\s*\()/.test(trimmed) &&
|
|
93
|
+
/\{/.test(trimmed)) {
|
|
94
|
+
pendingType = 'function';
|
|
95
|
+
}
|
|
96
|
+
else if (/^\s*(public|private|protected|static|async|get|set|readonly)\s.*\{/.test(trimmed) ||
|
|
97
|
+
/^\s*\*?\s*\w+\s*\([^)]*\)\s*(?::\s*\w[^{]*)?\{/.test(trimmed)) {
|
|
98
|
+
pendingType = 'method';
|
|
99
|
+
}
|
|
100
|
+
else if (/\{/.test(trimmed)) {
|
|
101
|
+
pendingType = 'block';
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
// Track brace depth
|
|
105
|
+
const opens = (line.match(/\{/g) || []).length;
|
|
106
|
+
const closes = (line.match(/\}/g) || []).length;
|
|
107
|
+
const prevDepth = depth;
|
|
108
|
+
depth += opens - closes;
|
|
109
|
+
if (opens > 0 && prevDepth === 0) {
|
|
110
|
+
// Entering a top-level block
|
|
111
|
+
blockStart = i;
|
|
112
|
+
blockType = pendingType;
|
|
113
|
+
}
|
|
114
|
+
if (prevDepth > 0 && depth === 0 && blockStart >= 0) {
|
|
115
|
+
// Exiting a block
|
|
116
|
+
const endLine = i;
|
|
117
|
+
const lineCount = endLine - blockStart + 1;
|
|
118
|
+
if (lineCount >= 6) {
|
|
119
|
+
blocks.push({
|
|
120
|
+
file: filePath,
|
|
121
|
+
startLine: blockStart + 1, // 1-based
|
|
122
|
+
endLine: endLine + 1,
|
|
123
|
+
content: lines.slice(blockStart, endLine + 1).join('\n'),
|
|
124
|
+
type: blockType,
|
|
125
|
+
});
|
|
126
|
+
}
|
|
127
|
+
blockStart = -1;
|
|
128
|
+
blockType = 'block';
|
|
129
|
+
}
|
|
130
|
+
}
|
|
131
|
+
return blocks;
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* Compute Jaccard similarity between two code blocks.
|
|
135
|
+
* Tokenises content into word tokens, then calculates |intersection| / |union|.
|
|
136
|
+
*/
|
|
137
|
+
computeSimilarity(a, b) {
|
|
138
|
+
const tokensA = this.tokenize(a.content);
|
|
139
|
+
const tokensB = this.tokenize(b.content);
|
|
140
|
+
if (tokensA.size === 0 && tokensB.size === 0)
|
|
141
|
+
return 1.0;
|
|
142
|
+
if (tokensA.size === 0 || tokensB.size === 0)
|
|
143
|
+
return 0.0;
|
|
144
|
+
let intersectionSize = 0;
|
|
145
|
+
for (const token of tokensA) {
|
|
146
|
+
if (tokensB.has(token))
|
|
147
|
+
intersectionSize++;
|
|
148
|
+
}
|
|
149
|
+
const unionSize = tokensA.size + tokensB.size - intersectionSize;
|
|
150
|
+
return unionSize === 0 ? 0 : intersectionSize / unionSize;
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Split content into individual word tokens and return as a Set.
|
|
154
|
+
* Strips punctuation and normalises to lowercase for comparison.
|
|
155
|
+
*/
|
|
156
|
+
tokenize(content) {
|
|
157
|
+
const words = content
|
|
158
|
+
.replace(/[^\w\s]/g, ' ')
|
|
159
|
+
.split(/\s+/)
|
|
160
|
+
.filter(w => w.length > 0)
|
|
161
|
+
.map(w => w.toLowerCase());
|
|
162
|
+
return new Set(words);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Generate a refactoring suggestion based on the types of the duplicate blocks.
|
|
166
|
+
*/
|
|
167
|
+
suggestRefactor(blocks) {
|
|
168
|
+
const types = new Set(blocks.map(b => b.type));
|
|
169
|
+
const files = new Set(blocks.map(b => b.file));
|
|
170
|
+
if (types.has('class')) {
|
|
171
|
+
return 'Extract a shared base class or compose common behaviour into a mixin/trait';
|
|
172
|
+
}
|
|
173
|
+
if (types.has('method')) {
|
|
174
|
+
if (files.size > 1) {
|
|
175
|
+
return 'Extract shared method logic into a utility module and import it where needed';
|
|
176
|
+
}
|
|
177
|
+
return 'Extract shared method logic into a private helper method within the same class';
|
|
178
|
+
}
|
|
179
|
+
if (types.has('function')) {
|
|
180
|
+
if (files.size > 1) {
|
|
181
|
+
return 'Extract shared logic into a utility function in a common module and import it where needed';
|
|
182
|
+
}
|
|
183
|
+
return 'Extract shared logic into a utility function within the same module';
|
|
184
|
+
}
|
|
185
|
+
// Generic block
|
|
186
|
+
if (files.size > 1) {
|
|
187
|
+
return 'Extract shared logic into a utility function in a shared module';
|
|
188
|
+
}
|
|
189
|
+
return 'Extract shared logic into a utility function to reduce duplication';
|
|
190
|
+
}
|
|
191
|
+
/**
|
|
192
|
+
* Walk a directory tree, returning full paths of source files.
|
|
193
|
+
*/
|
|
194
|
+
walkDir(dir) {
|
|
195
|
+
const results = [];
|
|
196
|
+
try {
|
|
197
|
+
const entries = fs.readdirSync(dir, { withFileTypes: true });
|
|
198
|
+
for (const entry of entries) {
|
|
199
|
+
if (entry.name.startsWith('.'))
|
|
200
|
+
continue;
|
|
201
|
+
const fullPath = path.join(dir, entry.name);
|
|
202
|
+
if (entry.isDirectory()) {
|
|
203
|
+
if (IGNORE_DIRS.has(entry.name))
|
|
204
|
+
continue;
|
|
205
|
+
results.push(...this.walkDir(fullPath));
|
|
206
|
+
}
|
|
207
|
+
else if (entry.isFile()) {
|
|
208
|
+
const ext = path.extname(entry.name);
|
|
209
|
+
if (SOURCE_EXTENSIONS.has(ext)) {
|
|
210
|
+
results.push(fullPath);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
// permission or access error — skip
|
|
217
|
+
}
|
|
218
|
+
return results;
|
|
219
|
+
}
|
|
220
|
+
/**
|
|
221
|
+
* Produce a unique key for a block (file path + line range).
|
|
222
|
+
*/
|
|
223
|
+
blockKey(block) {
|
|
224
|
+
return `${block.file}:${block.startLine}-${block.endLine}`;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
//# sourceMappingURL=code-similarity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"code-similarity.js","sourceRoot":"","sources":["../../src/brain/code-similarity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { BrainInsight } from '../types.js';
|
|
2
|
+
export declare class ConfigDriftDetector {
|
|
3
|
+
private projectDir;
|
|
4
|
+
constructor(projectDir: string);
|
|
5
|
+
analyzeProject(): Promise<BrainInsight[]>;
|
|
6
|
+
private detectMissingConfigs;
|
|
7
|
+
private detectTsconfigDrift;
|
|
8
|
+
private detectGitignoreDrift;
|
|
9
|
+
private detectPackageJsonDrift;
|
|
10
|
+
private detectEditorConfigDrift;
|
|
11
|
+
private driftToInsight;
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=config-drift-detector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-drift-detector.d.ts","sourceRoot":"","sources":["../../src/brain/config-drift-detector.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,YAAY,EAAe,MAAM,aAAa,CAAC;AA0BxD,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAIxB,cAAc,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;IAqB/C,OAAO,CAAC,oBAAoB;IAsB5B,OAAO,CAAC,mBAAmB;IAkD3B,OAAO,CAAC,oBAAoB;IA+B5B,OAAO,CAAC,sBAAsB;IAgC9B,OAAO,CAAC,uBAAuB;IAmB/B,OAAO,CAAC,cAAc;CAkBvB"}
|
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
// src/brain/config-drift-detector.ts — Configuration drift detection
|
|
2
|
+
// v3.0.0 — Detects drift between expected and actual config across environments
|
|
3
|
+
import * as fs from 'fs';
|
|
4
|
+
import * as path from 'path';
|
|
5
|
+
const TEMPLATES = [
|
|
6
|
+
{ path: 'tsconfig.json', required: true },
|
|
7
|
+
{ path: '.eslintrc.json', required: false },
|
|
8
|
+
{ path: '.eslintrc.js', required: false },
|
|
9
|
+
{ path: '.prettierrc', required: false },
|
|
10
|
+
{ path: '.prettierrc.json', required: false },
|
|
11
|
+
{ path: 'jest.config.js', required: false },
|
|
12
|
+
{ path: 'jest.config.ts', required: false },
|
|
13
|
+
{ path: '.gitignore', required: true },
|
|
14
|
+
{ path: '.editorconfig', required: false },
|
|
15
|
+
{ path: '.npmrc', required: false },
|
|
16
|
+
{ path: '.nvmrc', required: false },
|
|
17
|
+
{ path: 'docker-compose.yml', required: false },
|
|
18
|
+
{ path: 'Dockerfile', required: false },
|
|
19
|
+
];
|
|
20
|
+
export class ConfigDriftDetector {
|
|
21
|
+
constructor(projectDir) {
|
|
22
|
+
this.projectDir = projectDir;
|
|
23
|
+
}
|
|
24
|
+
async analyzeProject() {
|
|
25
|
+
const drifts = [];
|
|
26
|
+
// Phase 1: Missing required config files
|
|
27
|
+
drifts.push(...this.detectMissingConfigs());
|
|
28
|
+
// Phase 2: tsconfig.json drift
|
|
29
|
+
drifts.push(...this.detectTsconfigDrift());
|
|
30
|
+
// Phase 3: .gitignore drift
|
|
31
|
+
drifts.push(...this.detectGitignoreDrift());
|
|
32
|
+
// Phase 4: package.json consistency
|
|
33
|
+
drifts.push(...this.detectPackageJsonDrift());
|
|
34
|
+
// Phase 5: Editor config consistency
|
|
35
|
+
drifts.push(...this.detectEditorConfigDrift());
|
|
36
|
+
return drifts.map(d => this.driftToInsight(d));
|
|
37
|
+
}
|
|
38
|
+
detectMissingConfigs() {
|
|
39
|
+
const drifts = [];
|
|
40
|
+
for (const template of TEMPLATES) {
|
|
41
|
+
const fullPath = path.join(this.projectDir, template.path);
|
|
42
|
+
const exists = fs.existsSync(fullPath);
|
|
43
|
+
if (template.required && !exists) {
|
|
44
|
+
drifts.push({
|
|
45
|
+
file: template.path,
|
|
46
|
+
expected: 'File should exist',
|
|
47
|
+
actual: 'File is missing',
|
|
48
|
+
severity: 'high',
|
|
49
|
+
description: `Required config file ${template.path} is missing. This may cause inconsistent behavior across environments.`,
|
|
50
|
+
autoFixable: true,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return drifts;
|
|
55
|
+
}
|
|
56
|
+
detectTsconfigDrift() {
|
|
57
|
+
const drifts = [];
|
|
58
|
+
const tsconfigPath = path.join(this.projectDir, 'tsconfig.json');
|
|
59
|
+
let tsconfig;
|
|
60
|
+
try {
|
|
61
|
+
tsconfig = JSON.parse(fs.readFileSync(tsconfigPath, 'utf-8'));
|
|
62
|
+
}
|
|
63
|
+
catch {
|
|
64
|
+
return drifts; // missing tsconfig handled above
|
|
65
|
+
}
|
|
66
|
+
const compilerOptions = (tsconfig.compilerOptions || {});
|
|
67
|
+
// Check for recommended settings
|
|
68
|
+
const recommended = {
|
|
69
|
+
'strict': { value: true, reason: 'Strict mode catches many common bugs' },
|
|
70
|
+
'esModuleInterop': { value: true, reason: 'Enables proper interop between CJS and ESM' },
|
|
71
|
+
'skipLibCheck': { value: true, reason: 'Speeds up compilation by skipping type checking of .d.ts files' },
|
|
72
|
+
'forceConsistentCasingInFileNames': { value: true, reason: 'Ensures consistent file references across OS' },
|
|
73
|
+
'resolveJsonModule': { value: true, reason: 'Allows importing JSON files' },
|
|
74
|
+
'declaration': { value: true, reason: 'Generates .d.ts files for library consumers' },
|
|
75
|
+
'declarationMap': { value: true, reason: 'Enables source maps for declarations' },
|
|
76
|
+
'sourceMap': { value: true, reason: 'Enables debugging with source maps' },
|
|
77
|
+
};
|
|
78
|
+
for (const [key, { value, reason }] of Object.entries(recommended)) {
|
|
79
|
+
if (compilerOptions[key] === undefined) {
|
|
80
|
+
drifts.push({
|
|
81
|
+
file: 'tsconfig.json',
|
|
82
|
+
expected: `compilerOptions.${key}: ${JSON.stringify(value)}`,
|
|
83
|
+
actual: `${key} is not set`,
|
|
84
|
+
severity: 'medium',
|
|
85
|
+
description: `Missing recommended tsconfig option: ${key}. ${reason}.`,
|
|
86
|
+
autoFixable: true,
|
|
87
|
+
});
|
|
88
|
+
}
|
|
89
|
+
else if (compilerOptions[key] !== value) {
|
|
90
|
+
drifts.push({
|
|
91
|
+
file: 'tsconfig.json',
|
|
92
|
+
expected: `compilerOptions.${key}: ${JSON.stringify(value)}`,
|
|
93
|
+
actual: `compilerOptions.${key}: ${JSON.stringify(compilerOptions[key])}`,
|
|
94
|
+
severity: 'low',
|
|
95
|
+
description: `tsconfig option ${key} is ${JSON.stringify(compilerOptions[key])}, recommended: ${JSON.stringify(value)}. ${reason}.`,
|
|
96
|
+
autoFixable: true,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
return drifts;
|
|
101
|
+
}
|
|
102
|
+
detectGitignoreDrift() {
|
|
103
|
+
const drifts = [];
|
|
104
|
+
const gitignorePath = path.join(this.projectDir, '.gitignore');
|
|
105
|
+
let content;
|
|
106
|
+
try {
|
|
107
|
+
content = fs.readFileSync(gitignorePath, 'utf-8');
|
|
108
|
+
}
|
|
109
|
+
catch {
|
|
110
|
+
return drifts;
|
|
111
|
+
}
|
|
112
|
+
const entries = new Set(content.split('\n').map(l => l.trim()).filter(l => l && !l.startsWith('#')));
|
|
113
|
+
// Recommended gitignore entries
|
|
114
|
+
const recommended = [
|
|
115
|
+
'node_modules', 'dist', 'build', '.env', '.env.local',
|
|
116
|
+
'*.log', 'coverage', '.DS_Store', 'thumbs.db',
|
|
117
|
+
];
|
|
118
|
+
for (const entry of recommended) {
|
|
119
|
+
if (!entries.has(entry) && !entries.has(entry.replace('*', ''))) {
|
|
120
|
+
drifts.push({
|
|
121
|
+
file: '.gitignore',
|
|
122
|
+
expected: `${entry} should be ignored`,
|
|
123
|
+
actual: `${entry} is not in .gitignore`,
|
|
124
|
+
severity: entry === '.env' || entry === '.env.local' ? 'high' : 'medium',
|
|
125
|
+
description: `${entry} is missing from .gitignore. This may result in committing sensitive or generated files.`,
|
|
126
|
+
autoFixable: true,
|
|
127
|
+
});
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
return drifts;
|
|
131
|
+
}
|
|
132
|
+
detectPackageJsonDrift() {
|
|
133
|
+
const drifts = [];
|
|
134
|
+
const pkgPath = path.join(this.projectDir, 'package.json');
|
|
135
|
+
let pkg;
|
|
136
|
+
try {
|
|
137
|
+
pkg = JSON.parse(fs.readFileSync(pkgPath, 'utf-8'));
|
|
138
|
+
}
|
|
139
|
+
catch {
|
|
140
|
+
return drifts;
|
|
141
|
+
}
|
|
142
|
+
// Check for missing recommended fields
|
|
143
|
+
const recommendedFields = {
|
|
144
|
+
'license': { expected: 'MIT or appropriate license', reason: 'Required for npm publishing and legal clarity' },
|
|
145
|
+
'repository': { expected: '{ type: "git", url: "..." }', reason: 'Helps users find the source code' },
|
|
146
|
+
'description': { expected: 'Short project description', reason: 'Improves discoverability on npm' },
|
|
147
|
+
'keywords': { expected: 'Array of keywords', reason: 'Improves npm search results' },
|
|
148
|
+
'engines': { expected: '{ node: ">=18" }', reason: 'Specifies compatible Node.js versions' },
|
|
149
|
+
};
|
|
150
|
+
for (const [field, { expected, reason }] of Object.entries(recommendedFields)) {
|
|
151
|
+
if (!pkg[field]) {
|
|
152
|
+
drifts.push({
|
|
153
|
+
file: 'package.json',
|
|
154
|
+
expected: `${field}: ${expected}`,
|
|
155
|
+
actual: `${field} is missing`,
|
|
156
|
+
severity: 'low',
|
|
157
|
+
description: `Missing package.json field: ${field}. ${reason}.`,
|
|
158
|
+
autoFixable: true,
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
return drifts;
|
|
163
|
+
}
|
|
164
|
+
detectEditorConfigDrift() {
|
|
165
|
+
const drifts = [];
|
|
166
|
+
const editorConfigPath = path.join(this.projectDir, '.editorconfig');
|
|
167
|
+
if (!fs.existsSync(editorConfigPath)) {
|
|
168
|
+
// Not critical, but worth noting
|
|
169
|
+
drifts.push({
|
|
170
|
+
file: '.editorconfig',
|
|
171
|
+
expected: 'Editor config file for consistent formatting',
|
|
172
|
+
actual: 'No .editorconfig file found',
|
|
173
|
+
severity: 'low',
|
|
174
|
+
description: 'Missing .editorconfig. Team members may use different editor settings (indentation, line endings, etc.).',
|
|
175
|
+
autoFixable: true,
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
return drifts;
|
|
179
|
+
}
|
|
180
|
+
driftToInsight(drift) {
|
|
181
|
+
return {
|
|
182
|
+
type: 'config-drift',
|
|
183
|
+
priority: drift.severity === 'high' ? 'high' : drift.severity === 'medium' ? 'medium' : 'low',
|
|
184
|
+
title: `[config-drift] ${drift.file}: ${drift.description.slice(0, 60)}`,
|
|
185
|
+
content: `Configuration drift in ${drift.file}\n` +
|
|
186
|
+
` Expected: ${drift.expected}\n` +
|
|
187
|
+
` Actual: ${drift.actual}\n` +
|
|
188
|
+
` Severity: ${drift.severity}\n` +
|
|
189
|
+
` ${drift.autoFixable ? 'This can be auto-fixed.' : 'Manual review required.'}\n` +
|
|
190
|
+
` Description: ${drift.description}`,
|
|
191
|
+
files: [drift.file],
|
|
192
|
+
timestamp: new Date(),
|
|
193
|
+
confidence: 0.9,
|
|
194
|
+
metadata: { autoFixable: drift.autoFixable, severity: drift.severity },
|
|
195
|
+
};
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
//# sourceMappingURL=config-drift-detector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config-drift-detector.js","sourceRoot":"","sources":["../../src/brain/config-drift-detector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import type { ProjectKnowledge, BrainInsight } from '../types.js';
|
|
2
|
+
export declare class ContextCompletionEngine {
|
|
3
|
+
private projectDir;
|
|
4
|
+
constructor(projectDir: string);
|
|
5
|
+
/**
|
|
6
|
+
* Analyze the project directory to build a comprehensive ProjectKnowledge
|
|
7
|
+
* object containing name, conventions, architecture, patterns, and deps.
|
|
8
|
+
*/
|
|
9
|
+
buildKnowledge(): Promise<ProjectKnowledge>;
|
|
10
|
+
/**
|
|
11
|
+
* Persist the knowledge object to `.shadow-brain/knowledge.json` inside
|
|
12
|
+
* the project directory.
|
|
13
|
+
*/
|
|
14
|
+
saveKnowledge(knowledge: ProjectKnowledge): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Identify missing project context items (README, .gitignore, tsconfig,
|
|
17
|
+
* CI/CD configs, etc.) and return them as prioritised BrainInsight array.
|
|
18
|
+
*/
|
|
19
|
+
getContextGaps(knowledge: ProjectKnowledge): Promise<BrainInsight[]>;
|
|
20
|
+
private detectProjectName;
|
|
21
|
+
private detectConventions;
|
|
22
|
+
private summarizeEslint;
|
|
23
|
+
private summarizePrettier;
|
|
24
|
+
private summarizeEditorConfig;
|
|
25
|
+
private summarizeTsconfig;
|
|
26
|
+
private detectArchitecture;
|
|
27
|
+
private hasFileExtensionSync;
|
|
28
|
+
private detectPatterns;
|
|
29
|
+
private detectDependencies;
|
|
30
|
+
private parseCargoDeps;
|
|
31
|
+
private hasFile;
|
|
32
|
+
private hasFileExtension;
|
|
33
|
+
/**
|
|
34
|
+
* Recursively collect source files up to a limit.
|
|
35
|
+
* Skips node_modules, .git, dist, build, coverage, and hidden directories.
|
|
36
|
+
*/
|
|
37
|
+
private collectSourceFiles;
|
|
38
|
+
}
|
|
39
|
+
//# sourceMappingURL=context-completion.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"context-completion.d.ts","sourceRoot":"","sources":["../../src/brain/context-completion.ts"],"names":[],"mappings":"AAMA,OAAO,KAAK,EAAE,gBAAgB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAuDlE,qBAAa,uBAAuB;IAClC,OAAO,CAAC,UAAU,CAAS;gBAEf,UAAU,EAAE,MAAM;IAM9B;;;OAGG;IACG,cAAc,IAAI,OAAO,CAAC,gBAAgB,CAAC;IAoBjD;;;OAGG;IACG,aAAa,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAS/D;;;OAGG;IACG,cAAc,CAAC,SAAS,EAAE,gBAAgB,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC;YAwM5D,iBAAiB;YAqBjB,iBAAiB;IA0E/B,OAAO,CAAC,eAAe;IAkCvB,OAAO,CAAC,iBAAiB;IAmBzB,OAAO,CAAC,qBAAqB;IAU7B,OAAO,CAAC,iBAAiB;YA6BX,kBAAkB;IA0GhC,OAAO,CAAC,oBAAoB;YAMd,cAAc;YAoId,kBAAkB;IAsChC,OAAO,CAAC,cAAc;YAyBR,OAAO;YAIP,gBAAgB;IA8B9B;;;OAGG;YACW,kBAAkB;CA8CjC"}
|