neuronlayer 0.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/CONTRIBUTING.md +127 -0
- package/LICENSE +21 -0
- package/README.md +305 -0
- package/dist/index.js +38016 -0
- package/esbuild.config.js +26 -0
- package/package.json +63 -0
- package/src/cli/commands.ts +382 -0
- package/src/core/adr-exporter.ts +253 -0
- package/src/core/architecture/architecture-enforcement.ts +228 -0
- package/src/core/architecture/duplicate-detector.ts +288 -0
- package/src/core/architecture/index.ts +6 -0
- package/src/core/architecture/pattern-learner.ts +306 -0
- package/src/core/architecture/pattern-library.ts +403 -0
- package/src/core/architecture/pattern-validator.ts +324 -0
- package/src/core/change-intelligence/bug-correlator.ts +444 -0
- package/src/core/change-intelligence/change-intelligence.ts +221 -0
- package/src/core/change-intelligence/change-tracker.ts +334 -0
- package/src/core/change-intelligence/fix-suggester.ts +340 -0
- package/src/core/change-intelligence/index.ts +5 -0
- package/src/core/code-verifier.ts +843 -0
- package/src/core/confidence/confidence-scorer.ts +251 -0
- package/src/core/confidence/conflict-checker.ts +289 -0
- package/src/core/confidence/index.ts +5 -0
- package/src/core/confidence/source-tracker.ts +263 -0
- package/src/core/confidence/warning-detector.ts +241 -0
- package/src/core/context-rot/compaction.ts +284 -0
- package/src/core/context-rot/context-health.ts +243 -0
- package/src/core/context-rot/context-rot-prevention.ts +213 -0
- package/src/core/context-rot/critical-context.ts +221 -0
- package/src/core/context-rot/drift-detector.ts +255 -0
- package/src/core/context-rot/index.ts +7 -0
- package/src/core/context.ts +263 -0
- package/src/core/decision-extractor.ts +339 -0
- package/src/core/decisions.ts +69 -0
- package/src/core/deja-vu.ts +421 -0
- package/src/core/engine.ts +1455 -0
- package/src/core/feature-context.ts +726 -0
- package/src/core/ghost-mode.ts +412 -0
- package/src/core/learning.ts +485 -0
- package/src/core/living-docs/activity-tracker.ts +296 -0
- package/src/core/living-docs/architecture-generator.ts +428 -0
- package/src/core/living-docs/changelog-generator.ts +348 -0
- package/src/core/living-docs/component-generator.ts +230 -0
- package/src/core/living-docs/doc-engine.ts +110 -0
- package/src/core/living-docs/doc-validator.ts +282 -0
- package/src/core/living-docs/index.ts +8 -0
- package/src/core/project-manager.ts +297 -0
- package/src/core/summarizer.ts +267 -0
- package/src/core/test-awareness/change-validator.ts +499 -0
- package/src/core/test-awareness/index.ts +5 -0
- package/src/index.ts +49 -0
- package/src/indexing/ast.ts +563 -0
- package/src/indexing/embeddings.ts +85 -0
- package/src/indexing/indexer.ts +245 -0
- package/src/indexing/watcher.ts +78 -0
- package/src/server/gateways/aggregator.ts +374 -0
- package/src/server/gateways/index.ts +473 -0
- package/src/server/gateways/memory-ghost.ts +343 -0
- package/src/server/gateways/memory-query.ts +452 -0
- package/src/server/gateways/memory-record.ts +346 -0
- package/src/server/gateways/memory-review.ts +410 -0
- package/src/server/gateways/memory-status.ts +517 -0
- package/src/server/gateways/memory-verify.ts +392 -0
- package/src/server/gateways/router.ts +434 -0
- package/src/server/gateways/types.ts +610 -0
- package/src/server/mcp.ts +154 -0
- package/src/server/resources.ts +85 -0
- package/src/server/tools.ts +2261 -0
- package/src/storage/database.ts +262 -0
- package/src/storage/tier1.ts +135 -0
- package/src/storage/tier2.ts +764 -0
- package/src/storage/tier3.ts +123 -0
- package/src/types/documentation.ts +619 -0
- package/src/types/index.ts +222 -0
- package/src/utils/config.ts +193 -0
- package/src/utils/files.ts +117 -0
- package/src/utils/time.ts +37 -0
- package/src/utils/tokens.ts +52 -0
|
@@ -0,0 +1,403 @@
|
|
|
1
|
+
import { randomUUID } from 'crypto';
|
|
2
|
+
import type Database from 'better-sqlite3';
|
|
3
|
+
import type { Pattern, PatternCategory, CodeExample, PatternRule } from '../../types/documentation.js';
|
|
4
|
+
|
|
5
|
+
export class PatternLibrary {
|
|
6
|
+
private db: Database.Database;
|
|
7
|
+
|
|
8
|
+
constructor(db: Database.Database) {
|
|
9
|
+
this.db = db;
|
|
10
|
+
this.ensureTable();
|
|
11
|
+
this.seedDefaultPatterns();
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
private ensureTable(): void {
|
|
15
|
+
this.db.exec(`
|
|
16
|
+
CREATE TABLE IF NOT EXISTS patterns (
|
|
17
|
+
id TEXT PRIMARY KEY,
|
|
18
|
+
name TEXT NOT NULL,
|
|
19
|
+
category TEXT NOT NULL,
|
|
20
|
+
description TEXT,
|
|
21
|
+
examples TEXT,
|
|
22
|
+
anti_patterns TEXT,
|
|
23
|
+
rules TEXT,
|
|
24
|
+
created_at INTEGER DEFAULT (unixepoch()),
|
|
25
|
+
usage_count INTEGER DEFAULT 0
|
|
26
|
+
);
|
|
27
|
+
CREATE INDEX IF NOT EXISTS idx_patterns_category ON patterns(category);
|
|
28
|
+
CREATE INDEX IF NOT EXISTS idx_patterns_name ON patterns(name);
|
|
29
|
+
`);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private seedDefaultPatterns(): void {
|
|
33
|
+
// Check if we already have patterns
|
|
34
|
+
const count = this.db.prepare('SELECT COUNT(*) as count FROM patterns').get() as { count: number };
|
|
35
|
+
if (count.count > 0) return;
|
|
36
|
+
|
|
37
|
+
// Seed default patterns
|
|
38
|
+
const defaultPatterns: Omit<Pattern, 'id' | 'createdAt' | 'usageCount'>[] = [
|
|
39
|
+
{
|
|
40
|
+
name: 'Error Handling',
|
|
41
|
+
category: 'error_handling',
|
|
42
|
+
description: 'Standard error handling with try-catch, logging, and proper error types',
|
|
43
|
+
examples: [
|
|
44
|
+
{
|
|
45
|
+
code: `try {
|
|
46
|
+
const result = await operation();
|
|
47
|
+
return result;
|
|
48
|
+
} catch (error) {
|
|
49
|
+
console.error('Operation failed:', error);
|
|
50
|
+
throw new Error(\`Operation failed: \${error.message}\`);
|
|
51
|
+
}`,
|
|
52
|
+
explanation: 'Uses try-catch, logs error with context, rethrows with message'
|
|
53
|
+
}
|
|
54
|
+
],
|
|
55
|
+
antiPatterns: [
|
|
56
|
+
{
|
|
57
|
+
code: `try {
|
|
58
|
+
return await operation();
|
|
59
|
+
} catch (e) {
|
|
60
|
+
return null;
|
|
61
|
+
}`,
|
|
62
|
+
explanation: 'Swallows error silently, returns null instead of handling'
|
|
63
|
+
}
|
|
64
|
+
],
|
|
65
|
+
rules: [
|
|
66
|
+
{ rule: 'Always use try-catch for async operations', severity: 'warning' },
|
|
67
|
+
{ rule: 'Log errors with context', severity: 'warning' },
|
|
68
|
+
{ rule: 'Never swallow errors silently', severity: 'critical' },
|
|
69
|
+
{ rule: 'Rethrow or handle errors explicitly', severity: 'warning' }
|
|
70
|
+
]
|
|
71
|
+
},
|
|
72
|
+
{
|
|
73
|
+
name: 'API Calls',
|
|
74
|
+
category: 'api_call',
|
|
75
|
+
description: 'Standard API call pattern with error handling and typing',
|
|
76
|
+
examples: [
|
|
77
|
+
{
|
|
78
|
+
code: `const response = await fetch(url, {
|
|
79
|
+
method: 'GET',
|
|
80
|
+
headers: { 'Content-Type': 'application/json' }
|
|
81
|
+
});
|
|
82
|
+
if (!response.ok) {
|
|
83
|
+
throw new Error(\`API error: \${response.status}\`);
|
|
84
|
+
}
|
|
85
|
+
return await response.json();`,
|
|
86
|
+
explanation: 'Includes headers, checks response status, parses JSON'
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
antiPatterns: [
|
|
90
|
+
{
|
|
91
|
+
code: `const data = await fetch(url).then(r => r.json());`,
|
|
92
|
+
explanation: 'No error handling, no status check'
|
|
93
|
+
}
|
|
94
|
+
],
|
|
95
|
+
rules: [
|
|
96
|
+
{ rule: 'Always check response status', severity: 'critical' },
|
|
97
|
+
{ rule: 'Include Content-Type header', severity: 'warning' },
|
|
98
|
+
{ rule: 'Handle network errors', severity: 'critical' },
|
|
99
|
+
{ rule: 'Use typed responses when possible', severity: 'info' }
|
|
100
|
+
]
|
|
101
|
+
},
|
|
102
|
+
{
|
|
103
|
+
name: 'Component Structure',
|
|
104
|
+
category: 'component',
|
|
105
|
+
description: 'React/Vue component structure with props typing and state management',
|
|
106
|
+
examples: [
|
|
107
|
+
{
|
|
108
|
+
code: `interface Props {
|
|
109
|
+
value: string;
|
|
110
|
+
onChange: (value: string) => void;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
export function MyComponent({ value, onChange }: Props) {
|
|
114
|
+
return <div>{value}</div>;
|
|
115
|
+
}`,
|
|
116
|
+
explanation: 'Props interface, destructured props, typed callback'
|
|
117
|
+
}
|
|
118
|
+
],
|
|
119
|
+
antiPatterns: [
|
|
120
|
+
{
|
|
121
|
+
code: `export function MyComponent(props) {
|
|
122
|
+
return <div>{props.value}</div>;
|
|
123
|
+
}`,
|
|
124
|
+
explanation: 'No prop types, no destructuring'
|
|
125
|
+
}
|
|
126
|
+
],
|
|
127
|
+
rules: [
|
|
128
|
+
{ rule: 'Define Props interface for components', severity: 'warning' },
|
|
129
|
+
{ rule: 'Destructure props in function signature', severity: 'info' },
|
|
130
|
+
{ rule: 'Export components explicitly', severity: 'info' }
|
|
131
|
+
]
|
|
132
|
+
},
|
|
133
|
+
{
|
|
134
|
+
name: 'Null Checking',
|
|
135
|
+
category: 'validation',
|
|
136
|
+
description: 'Proper null/undefined checking patterns',
|
|
137
|
+
examples: [
|
|
138
|
+
{
|
|
139
|
+
code: `const value = obj?.property ?? defaultValue;`,
|
|
140
|
+
explanation: 'Uses optional chaining and nullish coalescing'
|
|
141
|
+
},
|
|
142
|
+
{
|
|
143
|
+
code: `if (value != null) {
|
|
144
|
+
// Safe to use value
|
|
145
|
+
}`,
|
|
146
|
+
explanation: 'Explicit null check before use'
|
|
147
|
+
}
|
|
148
|
+
],
|
|
149
|
+
antiPatterns: [
|
|
150
|
+
{
|
|
151
|
+
code: `const value = obj.property || defaultValue;`,
|
|
152
|
+
explanation: 'Using || treats 0, "", false as falsy'
|
|
153
|
+
}
|
|
154
|
+
],
|
|
155
|
+
rules: [
|
|
156
|
+
{ rule: 'Use optional chaining (?.) for nested access', severity: 'warning' },
|
|
157
|
+
{ rule: 'Use nullish coalescing (??) instead of ||', severity: 'info' },
|
|
158
|
+
{ rule: 'Check for null before accessing properties', severity: 'critical' }
|
|
159
|
+
]
|
|
160
|
+
},
|
|
161
|
+
{
|
|
162
|
+
name: 'Async/Await',
|
|
163
|
+
category: 'data_fetching',
|
|
164
|
+
description: 'Proper async/await patterns',
|
|
165
|
+
examples: [
|
|
166
|
+
{
|
|
167
|
+
code: `async function fetchData() {
|
|
168
|
+
try {
|
|
169
|
+
const data = await fetch(url);
|
|
170
|
+
return await data.json();
|
|
171
|
+
} catch (error) {
|
|
172
|
+
console.error('Fetch failed:', error);
|
|
173
|
+
throw error;
|
|
174
|
+
}
|
|
175
|
+
}`,
|
|
176
|
+
explanation: 'Uses async/await with try-catch'
|
|
177
|
+
}
|
|
178
|
+
],
|
|
179
|
+
antiPatterns: [
|
|
180
|
+
{
|
|
181
|
+
code: `function fetchData() {
|
|
182
|
+
return fetch(url).then(r => r.json()).catch(console.log);
|
|
183
|
+
}`,
|
|
184
|
+
explanation: 'Using .then() instead of async/await, weak error handling'
|
|
185
|
+
}
|
|
186
|
+
],
|
|
187
|
+
rules: [
|
|
188
|
+
{ rule: 'Prefer async/await over .then() chains', severity: 'info' },
|
|
189
|
+
{ rule: 'Always await promises', severity: 'warning' },
|
|
190
|
+
{ rule: 'Handle promise rejections', severity: 'critical' }
|
|
191
|
+
]
|
|
192
|
+
}
|
|
193
|
+
];
|
|
194
|
+
|
|
195
|
+
const stmt = this.db.prepare(`
|
|
196
|
+
INSERT INTO patterns (id, name, category, description, examples, anti_patterns, rules)
|
|
197
|
+
VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
198
|
+
`);
|
|
199
|
+
|
|
200
|
+
for (const pattern of defaultPatterns) {
|
|
201
|
+
stmt.run(
|
|
202
|
+
randomUUID(),
|
|
203
|
+
pattern.name,
|
|
204
|
+
pattern.category,
|
|
205
|
+
pattern.description,
|
|
206
|
+
JSON.stringify(pattern.examples),
|
|
207
|
+
JSON.stringify(pattern.antiPatterns),
|
|
208
|
+
JSON.stringify(pattern.rules)
|
|
209
|
+
);
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
// Get all patterns
|
|
214
|
+
getAllPatterns(): Pattern[] {
|
|
215
|
+
const rows = this.db.prepare(`
|
|
216
|
+
SELECT id, name, category, description, examples, anti_patterns, rules, created_at, usage_count
|
|
217
|
+
FROM patterns
|
|
218
|
+
ORDER BY usage_count DESC
|
|
219
|
+
`).all() as Array<{
|
|
220
|
+
id: string;
|
|
221
|
+
name: string;
|
|
222
|
+
category: string;
|
|
223
|
+
description: string;
|
|
224
|
+
examples: string;
|
|
225
|
+
anti_patterns: string;
|
|
226
|
+
rules: string;
|
|
227
|
+
created_at: number;
|
|
228
|
+
usage_count: number;
|
|
229
|
+
}>;
|
|
230
|
+
|
|
231
|
+
return rows.map(row => this.rowToPattern(row));
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// Get patterns by category
|
|
235
|
+
getPatternsByCategory(category: PatternCategory): Pattern[] {
|
|
236
|
+
const rows = this.db.prepare(`
|
|
237
|
+
SELECT id, name, category, description, examples, anti_patterns, rules, created_at, usage_count
|
|
238
|
+
FROM patterns
|
|
239
|
+
WHERE category = ?
|
|
240
|
+
ORDER BY usage_count DESC
|
|
241
|
+
`).all(category) as Array<{
|
|
242
|
+
id: string;
|
|
243
|
+
name: string;
|
|
244
|
+
category: string;
|
|
245
|
+
description: string;
|
|
246
|
+
examples: string;
|
|
247
|
+
anti_patterns: string;
|
|
248
|
+
rules: string;
|
|
249
|
+
created_at: number;
|
|
250
|
+
usage_count: number;
|
|
251
|
+
}>;
|
|
252
|
+
|
|
253
|
+
return rows.map(row => this.rowToPattern(row));
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// Get pattern by ID
|
|
257
|
+
getPattern(id: string): Pattern | null {
|
|
258
|
+
const row = this.db.prepare(`
|
|
259
|
+
SELECT id, name, category, description, examples, anti_patterns, rules, created_at, usage_count
|
|
260
|
+
FROM patterns
|
|
261
|
+
WHERE id = ?
|
|
262
|
+
`).get(id) as {
|
|
263
|
+
id: string;
|
|
264
|
+
name: string;
|
|
265
|
+
category: string;
|
|
266
|
+
description: string;
|
|
267
|
+
examples: string;
|
|
268
|
+
anti_patterns: string;
|
|
269
|
+
rules: string;
|
|
270
|
+
created_at: number;
|
|
271
|
+
usage_count: number;
|
|
272
|
+
} | undefined;
|
|
273
|
+
|
|
274
|
+
return row ? this.rowToPattern(row) : null;
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// Add a new pattern
|
|
278
|
+
addPattern(
|
|
279
|
+
name: string,
|
|
280
|
+
category: PatternCategory,
|
|
281
|
+
description: string,
|
|
282
|
+
examples: CodeExample[] = [],
|
|
283
|
+
antiPatterns: CodeExample[] = [],
|
|
284
|
+
rules: PatternRule[] = []
|
|
285
|
+
): Pattern {
|
|
286
|
+
const id = randomUUID();
|
|
287
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
288
|
+
|
|
289
|
+
this.db.prepare(`
|
|
290
|
+
INSERT INTO patterns (id, name, category, description, examples, anti_patterns, rules, created_at)
|
|
291
|
+
VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
|
292
|
+
`).run(
|
|
293
|
+
id,
|
|
294
|
+
name,
|
|
295
|
+
category,
|
|
296
|
+
description,
|
|
297
|
+
JSON.stringify(examples),
|
|
298
|
+
JSON.stringify(antiPatterns),
|
|
299
|
+
JSON.stringify(rules),
|
|
300
|
+
timestamp
|
|
301
|
+
);
|
|
302
|
+
|
|
303
|
+
return {
|
|
304
|
+
id,
|
|
305
|
+
name,
|
|
306
|
+
category,
|
|
307
|
+
description,
|
|
308
|
+
examples,
|
|
309
|
+
antiPatterns,
|
|
310
|
+
rules,
|
|
311
|
+
createdAt: new Date(timestamp * 1000),
|
|
312
|
+
usageCount: 0
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
|
|
316
|
+
// Update pattern usage count
|
|
317
|
+
incrementUsage(id: string): void {
|
|
318
|
+
this.db.prepare('UPDATE patterns SET usage_count = usage_count + 1 WHERE id = ?').run(id);
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
// Add example to pattern
|
|
322
|
+
addExample(id: string, example: CodeExample, isAntiPattern: boolean = false): boolean {
|
|
323
|
+
const pattern = this.getPattern(id);
|
|
324
|
+
if (!pattern) return false;
|
|
325
|
+
|
|
326
|
+
const field = isAntiPattern ? 'anti_patterns' : 'examples';
|
|
327
|
+
const current = isAntiPattern ? pattern.antiPatterns : pattern.examples;
|
|
328
|
+
current.push(example);
|
|
329
|
+
|
|
330
|
+
this.db.prepare(`UPDATE patterns SET ${field} = ? WHERE id = ?`).run(
|
|
331
|
+
JSON.stringify(current),
|
|
332
|
+
id
|
|
333
|
+
);
|
|
334
|
+
|
|
335
|
+
return true;
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
// Add rule to pattern
|
|
339
|
+
addRule(id: string, rule: PatternRule): boolean {
|
|
340
|
+
const pattern = this.getPattern(id);
|
|
341
|
+
if (!pattern) return false;
|
|
342
|
+
|
|
343
|
+
pattern.rules.push(rule);
|
|
344
|
+
this.db.prepare('UPDATE patterns SET rules = ? WHERE id = ?').run(
|
|
345
|
+
JSON.stringify(pattern.rules),
|
|
346
|
+
id
|
|
347
|
+
);
|
|
348
|
+
|
|
349
|
+
return true;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
// Delete pattern
|
|
353
|
+
deletePattern(id: string): boolean {
|
|
354
|
+
const result = this.db.prepare('DELETE FROM patterns WHERE id = ?').run(id);
|
|
355
|
+
return result.changes > 0;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
// Search patterns
|
|
359
|
+
searchPatterns(query: string): Pattern[] {
|
|
360
|
+
const rows = this.db.prepare(`
|
|
361
|
+
SELECT id, name, category, description, examples, anti_patterns, rules, created_at, usage_count
|
|
362
|
+
FROM patterns
|
|
363
|
+
WHERE name LIKE ? OR description LIKE ? OR category LIKE ?
|
|
364
|
+
ORDER BY usage_count DESC
|
|
365
|
+
`).all(`%${query}%`, `%${query}%`, `%${query}%`) as Array<{
|
|
366
|
+
id: string;
|
|
367
|
+
name: string;
|
|
368
|
+
category: string;
|
|
369
|
+
description: string;
|
|
370
|
+
examples: string;
|
|
371
|
+
anti_patterns: string;
|
|
372
|
+
rules: string;
|
|
373
|
+
created_at: number;
|
|
374
|
+
usage_count: number;
|
|
375
|
+
}>;
|
|
376
|
+
|
|
377
|
+
return rows.map(row => this.rowToPattern(row));
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
private rowToPattern(row: {
|
|
381
|
+
id: string;
|
|
382
|
+
name: string;
|
|
383
|
+
category: string;
|
|
384
|
+
description: string;
|
|
385
|
+
examples: string;
|
|
386
|
+
anti_patterns: string;
|
|
387
|
+
rules: string;
|
|
388
|
+
created_at: number;
|
|
389
|
+
usage_count: number;
|
|
390
|
+
}): Pattern {
|
|
391
|
+
return {
|
|
392
|
+
id: row.id,
|
|
393
|
+
name: row.name,
|
|
394
|
+
category: row.category as PatternCategory,
|
|
395
|
+
description: row.description,
|
|
396
|
+
examples: JSON.parse(row.examples || '[]'),
|
|
397
|
+
antiPatterns: JSON.parse(row.anti_patterns || '[]'),
|
|
398
|
+
rules: JSON.parse(row.rules || '[]'),
|
|
399
|
+
createdAt: new Date(row.created_at * 1000),
|
|
400
|
+
usageCount: row.usage_count
|
|
401
|
+
};
|
|
402
|
+
}
|
|
403
|
+
}
|