@theihtisham/agent-shadow-brain 1.2.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 +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/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/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/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/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/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/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/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 +111 -1
- package/dist/brain/orchestrator.d.ts.map +1 -1
- package/dist/brain/orchestrator.js +302 -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 +593 -3
- package/dist/cli.js.map +1 -1
- package/dist/index.d.ts +15 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +18 -1
- package/dist/index.js.map +1 -1
- package/dist/types.d.ts +228 -0
- package/dist/types.d.ts.map +1 -1
- package/package.json +2 -2
|
@@ -0,0 +1,400 @@
|
|
|
1
|
+
// src/brain/adr-engine.ts — Architecture Decision Records engine
|
|
2
|
+
import * as fs from 'fs';
|
|
3
|
+
import * as path from 'path';
|
|
4
|
+
const ADR_HEADER_RE = /^#\s+(.+)$/;
|
|
5
|
+
const ADR_SECTION_RE = /^##\s+(.+)$/;
|
|
6
|
+
export class ADREngine {
|
|
7
|
+
constructor(projectDir, llmClient) {
|
|
8
|
+
this.projectDir = projectDir;
|
|
9
|
+
this.llmClient = llmClient;
|
|
10
|
+
// Prefer docs/adr/, fall back to .shadow-brain/adrs/
|
|
11
|
+
const docsAdr = path.join(projectDir, 'docs', 'adr');
|
|
12
|
+
const shadowAdr = path.join(projectDir, '.shadow-brain', 'adrs');
|
|
13
|
+
if (fs.existsSync(docsAdr)) {
|
|
14
|
+
this.adrDir = docsAdr;
|
|
15
|
+
}
|
|
16
|
+
else if (fs.existsSync(shadowAdr)) {
|
|
17
|
+
this.adrDir = shadowAdr;
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
// Default to docs/adr (will be created on first save)
|
|
21
|
+
this.adrDir = docsAdr;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Load all ADR markdown files from the ADR directory.
|
|
26
|
+
* Returns parsed ADRDecision objects sorted by ID.
|
|
27
|
+
*/
|
|
28
|
+
async loadADRs() {
|
|
29
|
+
if (!fs.existsSync(this.adrDir)) {
|
|
30
|
+
return [];
|
|
31
|
+
}
|
|
32
|
+
const adrs = [];
|
|
33
|
+
const files = fs.readdirSync(this.adrDir)
|
|
34
|
+
.filter(f => f.endsWith('.md'))
|
|
35
|
+
.sort();
|
|
36
|
+
for (const file of files) {
|
|
37
|
+
const fullPath = path.join(this.adrDir, file);
|
|
38
|
+
try {
|
|
39
|
+
const content = fs.readFileSync(fullPath, 'utf-8');
|
|
40
|
+
const adr = this.parseADR(content, file);
|
|
41
|
+
if (adr)
|
|
42
|
+
adrs.push(adr);
|
|
43
|
+
}
|
|
44
|
+
catch {
|
|
45
|
+
// unreadable file — skip
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
return adrs;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Write an ADR to the docs/adr/ directory in standard markdown format.
|
|
52
|
+
* Filename pattern: NNNN-kebab-case-title.md
|
|
53
|
+
*/
|
|
54
|
+
async saveADR(adr) {
|
|
55
|
+
// Ensure the directory exists
|
|
56
|
+
fs.mkdirSync(this.adrDir, { recursive: true });
|
|
57
|
+
// Determine the next sequence number
|
|
58
|
+
const nextNum = await this.getNextNumber();
|
|
59
|
+
const slug = this.slugify(adr.title);
|
|
60
|
+
const filename = `${String(nextNum).padStart(4, '0')}-${slug}.md`;
|
|
61
|
+
const fullPath = path.join(this.adrDir, filename);
|
|
62
|
+
const markdown = this.formatADRMd(adr);
|
|
63
|
+
fs.writeFileSync(fullPath, markdown, 'utf-8');
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Analyse file changes to detect architectural decisions.
|
|
67
|
+
* Uses heuristic rules, and optionally an LLM client for deeper analysis.
|
|
68
|
+
*/
|
|
69
|
+
async detectDecisions(changes) {
|
|
70
|
+
const decisions = [];
|
|
71
|
+
const now = new Date();
|
|
72
|
+
// Gather all diffs for LLM analysis if available
|
|
73
|
+
const allDiffs = [];
|
|
74
|
+
for (const change of changes) {
|
|
75
|
+
const diff = change.diff || '';
|
|
76
|
+
// ── Heuristic: Framework change ───────────────────────────────────────
|
|
77
|
+
if (this.looksLikeFrameworkChange(change.path, diff)) {
|
|
78
|
+
decisions.push({
|
|
79
|
+
id: `adr-auto-${Date.now()}-framework`,
|
|
80
|
+
title: `Framework or library adoption in ${path.basename(change.path)}`,
|
|
81
|
+
status: 'proposed',
|
|
82
|
+
date: now,
|
|
83
|
+
context: `A significant framework or core library change was detected in ${change.path}.`,
|
|
84
|
+
decision: 'Pending review — framework or library change detected automatically.',
|
|
85
|
+
consequences: 'May affect the overall architecture, build pipeline, and dependency tree.',
|
|
86
|
+
alternatives: ['Evaluate alternatives before committing', 'Create a spike/prototype first'],
|
|
87
|
+
files: [change.path],
|
|
88
|
+
});
|
|
89
|
+
continue;
|
|
90
|
+
}
|
|
91
|
+
// ── Heuristic: New architectural pattern ──────────────────────────────
|
|
92
|
+
if (this.looksLikeNewPattern(change.path, diff)) {
|
|
93
|
+
decisions.push({
|
|
94
|
+
id: `adr-auto-${Date.now()}-pattern`,
|
|
95
|
+
title: `New architectural pattern introduced in ${path.basename(change.path)}`,
|
|
96
|
+
status: 'proposed',
|
|
97
|
+
date: now,
|
|
98
|
+
context: `A new structural or architectural pattern was introduced in ${change.path}.`,
|
|
99
|
+
decision: 'Pending review — new pattern detected automatically.',
|
|
100
|
+
consequences: 'May establish a precedent for how similar features are structured.',
|
|
101
|
+
alternatives: ['Document the pattern explicitly', 'Refactor to match existing patterns'],
|
|
102
|
+
files: [change.path],
|
|
103
|
+
});
|
|
104
|
+
continue;
|
|
105
|
+
}
|
|
106
|
+
// ── Heuristic: Significant refactor ───────────────────────────────────
|
|
107
|
+
if (this.looksLikeSignificantRefactor(diff)) {
|
|
108
|
+
decisions.push({
|
|
109
|
+
id: `adr-auto-${Date.now()}-refactor`,
|
|
110
|
+
title: `Significant refactor in ${path.basename(change.path)}`,
|
|
111
|
+
status: 'proposed',
|
|
112
|
+
date: now,
|
|
113
|
+
context: `A large-scale refactoring was detected in ${change.path}. This could indicate an architectural shift.`,
|
|
114
|
+
decision: 'Pending review — significant code restructure detected.',
|
|
115
|
+
consequences: 'Could affect multiple modules, API contracts, or data flows.',
|
|
116
|
+
alternatives: ['Incremental refactor with feature flags', 'Phased rollout'],
|
|
117
|
+
files: [change.path],
|
|
118
|
+
});
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
if (diff) {
|
|
122
|
+
allDiffs.push(`--- ${change.path} ---\n${diff}`);
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
// ── LLM-assisted detection ─────────────────────────────────────────────
|
|
126
|
+
if (this.llmClient && allDiffs.length > 0) {
|
|
127
|
+
try {
|
|
128
|
+
const llmDecisions = await this.detectWithLLM(allDiffs);
|
|
129
|
+
decisions.push(...llmDecisions);
|
|
130
|
+
}
|
|
131
|
+
catch {
|
|
132
|
+
// LLM detection is best-effort — heuristics are the primary path
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return decisions;
|
|
136
|
+
}
|
|
137
|
+
// ── Private Helpers ────────────────────────────────────────────────────────
|
|
138
|
+
/**
|
|
139
|
+
* Format an ADRDecision as a standard ADR markdown document.
|
|
140
|
+
*/
|
|
141
|
+
formatADRMd(adr) {
|
|
142
|
+
let md = `# ${adr.title}\n\n`;
|
|
143
|
+
md += `## Status\n\n${adr.status}\n\n`;
|
|
144
|
+
md += `## Context\n\n${adr.context}\n\n`;
|
|
145
|
+
md += `## Decision\n\n${adr.decision}\n\n`;
|
|
146
|
+
md += `## Consequences\n\n${adr.consequences}\n\n`;
|
|
147
|
+
if (adr.alternatives && adr.alternatives.length > 0) {
|
|
148
|
+
md += `## Alternatives Considered\n\n`;
|
|
149
|
+
for (const alt of adr.alternatives) {
|
|
150
|
+
md += `- ${alt}\n`;
|
|
151
|
+
}
|
|
152
|
+
md += `\n`;
|
|
153
|
+
}
|
|
154
|
+
if (adr.files && adr.files.length > 0) {
|
|
155
|
+
md += `## Files Affected\n\n`;
|
|
156
|
+
for (const file of adr.files) {
|
|
157
|
+
md += `- ${file}\n`;
|
|
158
|
+
}
|
|
159
|
+
md += `\n`;
|
|
160
|
+
}
|
|
161
|
+
md += `## Date\n\n${adr.date.toISOString().split('T')[0]}\n`;
|
|
162
|
+
return md;
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Parse a markdown ADR file into an ADRDecision object.
|
|
166
|
+
*/
|
|
167
|
+
parseADR(content, filename) {
|
|
168
|
+
const lines = content.split('\n');
|
|
169
|
+
// Extract ID from filename (e.g. "0003-use-postgres.md" -> "0003")
|
|
170
|
+
const idMatch = filename.match(/^(\d+)/);
|
|
171
|
+
const id = idMatch ? idMatch[1] : filename.replace('.md', '');
|
|
172
|
+
// Parse title from first H1
|
|
173
|
+
let title = filename.replace(/^\d+-/, '').replace(/\.md$/, '').replace(/-/g, ' ');
|
|
174
|
+
for (const line of lines) {
|
|
175
|
+
const m = line.match(ADR_HEADER_RE);
|
|
176
|
+
if (m) {
|
|
177
|
+
title = m[1].trim();
|
|
178
|
+
break;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
// Parse sections
|
|
182
|
+
let status = 'proposed';
|
|
183
|
+
let context = '';
|
|
184
|
+
let decision = '';
|
|
185
|
+
let consequences = '';
|
|
186
|
+
let alternatives = [];
|
|
187
|
+
let currentSection = '';
|
|
188
|
+
for (const line of lines) {
|
|
189
|
+
const sectionMatch = line.match(ADR_SECTION_RE);
|
|
190
|
+
if (sectionMatch) {
|
|
191
|
+
currentSection = sectionMatch[1].trim().toLowerCase();
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
switch (currentSection) {
|
|
195
|
+
case 'status':
|
|
196
|
+
const statusVal = line.trim().toLowerCase();
|
|
197
|
+
if (['proposed', 'accepted', 'deprecated', 'superseded'].includes(statusVal)) {
|
|
198
|
+
status = statusVal;
|
|
199
|
+
}
|
|
200
|
+
break;
|
|
201
|
+
case 'context':
|
|
202
|
+
context += line + '\n';
|
|
203
|
+
break;
|
|
204
|
+
case 'decision':
|
|
205
|
+
decision += line + '\n';
|
|
206
|
+
break;
|
|
207
|
+
case 'consequences':
|
|
208
|
+
consequences += line + '\n';
|
|
209
|
+
break;
|
|
210
|
+
case 'alternatives considered':
|
|
211
|
+
case 'alternatives':
|
|
212
|
+
const trimmed = line.trim();
|
|
213
|
+
if (trimmed.startsWith('- ') || trimmed.startsWith('* ')) {
|
|
214
|
+
alternatives.push(trimmed.slice(2).trim());
|
|
215
|
+
}
|
|
216
|
+
else if (trimmed && !trimmed.startsWith('#')) {
|
|
217
|
+
alternatives.push(trimmed);
|
|
218
|
+
}
|
|
219
|
+
break;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return {
|
|
223
|
+
id,
|
|
224
|
+
title,
|
|
225
|
+
status,
|
|
226
|
+
date: new Date(), // Files don't carry creation date in content; use mtime if needed
|
|
227
|
+
context: context.trim(),
|
|
228
|
+
decision: decision.trim(),
|
|
229
|
+
consequences: consequences.trim(),
|
|
230
|
+
alternatives: alternatives.length > 0 ? alternatives : undefined,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
/**
|
|
234
|
+
* Get the next sequence number for ADR filenames.
|
|
235
|
+
*/
|
|
236
|
+
async getNextNumber() {
|
|
237
|
+
if (!fs.existsSync(this.adrDir))
|
|
238
|
+
return 1;
|
|
239
|
+
const files = fs.readdirSync(this.adrDir).filter(f => f.endsWith('.md'));
|
|
240
|
+
let maxNum = 0;
|
|
241
|
+
for (const file of files) {
|
|
242
|
+
const match = file.match(/^(\d+)/);
|
|
243
|
+
if (match) {
|
|
244
|
+
const num = parseInt(match[1], 10);
|
|
245
|
+
if (num > maxNum)
|
|
246
|
+
maxNum = num;
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return maxNum + 1;
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Heuristic: detect framework or core library changes.
|
|
253
|
+
*/
|
|
254
|
+
looksLikeFrameworkChange(filePath, diff) {
|
|
255
|
+
const frameworkIndicators = [
|
|
256
|
+
/package\.json/,
|
|
257
|
+
/next\.config/,
|
|
258
|
+
/tsconfig\.json/,
|
|
259
|
+
/webpack\.config/,
|
|
260
|
+
/vite\.config/,
|
|
261
|
+
/angular\.json/,
|
|
262
|
+
/vue\.config/,
|
|
263
|
+
/nuxt\.config/,
|
|
264
|
+
/tailwind\.config/,
|
|
265
|
+
/docker-compose/,
|
|
266
|
+
/Dockerfile/,
|
|
267
|
+
/\.env\.example/,
|
|
268
|
+
/prisma\/schema/,
|
|
269
|
+
/drizzle\.config/,
|
|
270
|
+
];
|
|
271
|
+
const isConfigFile = frameworkIndicators.some(re => re.test(path.basename(filePath)));
|
|
272
|
+
if (isConfigFile && diff.length > 100)
|
|
273
|
+
return true;
|
|
274
|
+
// Check diff for import changes of major frameworks
|
|
275
|
+
const frameworkImports = [
|
|
276
|
+
/from\s+['"]react['"]/,
|
|
277
|
+
/from\s+['"]vue['"]/,
|
|
278
|
+
/from\s+['"]@angular/,
|
|
279
|
+
/from\s+['"]next['"]/,
|
|
280
|
+
/from\s+['"]express['"]/,
|
|
281
|
+
/from\s+['"]fastify['"]/,
|
|
282
|
+
/from\s+['"]nestjs['"]/,
|
|
283
|
+
/from\s+['"]@prisma/,
|
|
284
|
+
/from\s+['"]drizzle-orm/,
|
|
285
|
+
];
|
|
286
|
+
const hasFrameworkImport = frameworkImports.some(re => re.test(diff));
|
|
287
|
+
return hasFrameworkImport && diff.length > 200;
|
|
288
|
+
}
|
|
289
|
+
/**
|
|
290
|
+
* Heuristic: detect introduction of new architectural patterns.
|
|
291
|
+
*/
|
|
292
|
+
looksLikeNewPattern(filePath, diff) {
|
|
293
|
+
if (!diff)
|
|
294
|
+
return false;
|
|
295
|
+
const patternIndicators = [
|
|
296
|
+
// Design patterns
|
|
297
|
+
/\bclass\s+\w+Singleton\b/,
|
|
298
|
+
/\bclass\s+\w+Factory\b/,
|
|
299
|
+
/\bclass\s+\w+Strategy\b/,
|
|
300
|
+
/\bclass\s+\w+Observer\b/,
|
|
301
|
+
/\bclass\s+\w+Adapter\b/,
|
|
302
|
+
/\bimplements\s+\w+Strategy/,
|
|
303
|
+
/\bimplements\s+\w+Repository/,
|
|
304
|
+
/\bimplements\s+\w+Service/,
|
|
305
|
+
// Architectural patterns
|
|
306
|
+
/\buseCase\b|\bUseCase\b/,
|
|
307
|
+
/\brepository\b|\bRepository\b/,
|
|
308
|
+
/\bservice\s+layer\b|\bServiceLayer\b/i,
|
|
309
|
+
/\bclean\s+architecture\b/i,
|
|
310
|
+
/\bhexagonal\b/i,
|
|
311
|
+
/\bmiddleware\b/i,
|
|
312
|
+
/\bplugin\b/i,
|
|
313
|
+
];
|
|
314
|
+
return patternIndicators.some(re => re.test(diff));
|
|
315
|
+
}
|
|
316
|
+
/**
|
|
317
|
+
* Heuristic: detect significant refactoring (large diffs with structural changes).
|
|
318
|
+
*/
|
|
319
|
+
looksLikeSignificantRefactor(diff) {
|
|
320
|
+
if (!diff || diff.length < 500)
|
|
321
|
+
return false;
|
|
322
|
+
// Count structural change indicators
|
|
323
|
+
const addedLines = (diff.match(/^\+/gm) || []).length;
|
|
324
|
+
const removedLines = (diff.match(/^-/gm) || []).length;
|
|
325
|
+
// Significant if lots of additions and removals
|
|
326
|
+
const totalChanges = addedLines + removedLines;
|
|
327
|
+
if (totalChanges < 30)
|
|
328
|
+
return false;
|
|
329
|
+
// Check for structural keywords in the diff
|
|
330
|
+
const structuralKeywords = [
|
|
331
|
+
/\bclass\b.*\bextends\b/,
|
|
332
|
+
/\binterface\b/,
|
|
333
|
+
/\bexport\s+default\b/,
|
|
334
|
+
/\bmodule\.exports\b/,
|
|
335
|
+
/\bimport\s+.*\bfrom\b/,
|
|
336
|
+
/\btype\s+\w+\s*=/,
|
|
337
|
+
/\basync\s+/,
|
|
338
|
+
/\bawait\s+/,
|
|
339
|
+
];
|
|
340
|
+
let keywordHits = 0;
|
|
341
|
+
for (const kw of structuralKeywords) {
|
|
342
|
+
if (kw.test(diff))
|
|
343
|
+
keywordHits++;
|
|
344
|
+
}
|
|
345
|
+
return keywordHits >= 2;
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Use the LLM client to analyse diffs and detect architectural decisions.
|
|
349
|
+
*/
|
|
350
|
+
async detectWithLLM(diffs) {
|
|
351
|
+
if (!this.llmClient)
|
|
352
|
+
return [];
|
|
353
|
+
const combined = diffs.join('\n\n').slice(0, 8000); // truncate to reasonable size
|
|
354
|
+
const prompt = `Analyse the following code diffs and identify any architectural decisions that should be documented as ADRs (Architecture Decision Records).
|
|
355
|
+
For each decision, provide:
|
|
356
|
+
- title: short descriptive title
|
|
357
|
+
- context: what is the situation that necessitates this decision
|
|
358
|
+
- decision: what was decided
|
|
359
|
+
- consequences: what are the resulting consequences
|
|
360
|
+
|
|
361
|
+
Respond with a JSON array of objects with keys: title, context, decision, consequences.
|
|
362
|
+
If no architectural decisions are detected, respond with an empty array: []
|
|
363
|
+
|
|
364
|
+
Diffs:
|
|
365
|
+
${combined}`;
|
|
366
|
+
const response = await this.llmClient.complete(prompt, 'You are a senior software architect. Analyse code changes and identify architectural decisions. Respond with valid JSON only.');
|
|
367
|
+
try {
|
|
368
|
+
const cleaned = response.replace(/```json\n?/g, '').replace(/```\n?/g, '').trim();
|
|
369
|
+
const parsed = JSON.parse(cleaned);
|
|
370
|
+
if (!Array.isArray(parsed))
|
|
371
|
+
return [];
|
|
372
|
+
return parsed.map((item, idx) => ({
|
|
373
|
+
id: `adr-llm-${Date.now()}-${idx}`,
|
|
374
|
+
title: item.title || 'Untitled LLM-detected decision',
|
|
375
|
+
status: 'proposed',
|
|
376
|
+
date: new Date(),
|
|
377
|
+
context: item.context || '',
|
|
378
|
+
decision: item.decision || '',
|
|
379
|
+
consequences: item.consequences || '',
|
|
380
|
+
alternatives: item.alternatives || undefined,
|
|
381
|
+
}));
|
|
382
|
+
}
|
|
383
|
+
catch {
|
|
384
|
+
return [];
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
/**
|
|
388
|
+
* Convert a title string to a kebab-case slug for filenames.
|
|
389
|
+
*/
|
|
390
|
+
slugify(title) {
|
|
391
|
+
return title
|
|
392
|
+
.toLowerCase()
|
|
393
|
+
.replace(/[^a-z0-9\s-]/g, '')
|
|
394
|
+
.replace(/\s+/g, '-')
|
|
395
|
+
.replace(/-+/g, '-')
|
|
396
|
+
.replace(/^-|-$/g, '')
|
|
397
|
+
.slice(0, 60);
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
//# sourceMappingURL=adr-engine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adr-engine.js","sourceRoot":"","sources":["../../src/brain/adr-engine.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"}
|