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.
Files changed (78) hide show
  1. package/CONTRIBUTING.md +127 -0
  2. package/LICENSE +21 -0
  3. package/README.md +305 -0
  4. package/dist/index.js +38016 -0
  5. package/esbuild.config.js +26 -0
  6. package/package.json +63 -0
  7. package/src/cli/commands.ts +382 -0
  8. package/src/core/adr-exporter.ts +253 -0
  9. package/src/core/architecture/architecture-enforcement.ts +228 -0
  10. package/src/core/architecture/duplicate-detector.ts +288 -0
  11. package/src/core/architecture/index.ts +6 -0
  12. package/src/core/architecture/pattern-learner.ts +306 -0
  13. package/src/core/architecture/pattern-library.ts +403 -0
  14. package/src/core/architecture/pattern-validator.ts +324 -0
  15. package/src/core/change-intelligence/bug-correlator.ts +444 -0
  16. package/src/core/change-intelligence/change-intelligence.ts +221 -0
  17. package/src/core/change-intelligence/change-tracker.ts +334 -0
  18. package/src/core/change-intelligence/fix-suggester.ts +340 -0
  19. package/src/core/change-intelligence/index.ts +5 -0
  20. package/src/core/code-verifier.ts +843 -0
  21. package/src/core/confidence/confidence-scorer.ts +251 -0
  22. package/src/core/confidence/conflict-checker.ts +289 -0
  23. package/src/core/confidence/index.ts +5 -0
  24. package/src/core/confidence/source-tracker.ts +263 -0
  25. package/src/core/confidence/warning-detector.ts +241 -0
  26. package/src/core/context-rot/compaction.ts +284 -0
  27. package/src/core/context-rot/context-health.ts +243 -0
  28. package/src/core/context-rot/context-rot-prevention.ts +213 -0
  29. package/src/core/context-rot/critical-context.ts +221 -0
  30. package/src/core/context-rot/drift-detector.ts +255 -0
  31. package/src/core/context-rot/index.ts +7 -0
  32. package/src/core/context.ts +263 -0
  33. package/src/core/decision-extractor.ts +339 -0
  34. package/src/core/decisions.ts +69 -0
  35. package/src/core/deja-vu.ts +421 -0
  36. package/src/core/engine.ts +1455 -0
  37. package/src/core/feature-context.ts +726 -0
  38. package/src/core/ghost-mode.ts +412 -0
  39. package/src/core/learning.ts +485 -0
  40. package/src/core/living-docs/activity-tracker.ts +296 -0
  41. package/src/core/living-docs/architecture-generator.ts +428 -0
  42. package/src/core/living-docs/changelog-generator.ts +348 -0
  43. package/src/core/living-docs/component-generator.ts +230 -0
  44. package/src/core/living-docs/doc-engine.ts +110 -0
  45. package/src/core/living-docs/doc-validator.ts +282 -0
  46. package/src/core/living-docs/index.ts +8 -0
  47. package/src/core/project-manager.ts +297 -0
  48. package/src/core/summarizer.ts +267 -0
  49. package/src/core/test-awareness/change-validator.ts +499 -0
  50. package/src/core/test-awareness/index.ts +5 -0
  51. package/src/index.ts +49 -0
  52. package/src/indexing/ast.ts +563 -0
  53. package/src/indexing/embeddings.ts +85 -0
  54. package/src/indexing/indexer.ts +245 -0
  55. package/src/indexing/watcher.ts +78 -0
  56. package/src/server/gateways/aggregator.ts +374 -0
  57. package/src/server/gateways/index.ts +473 -0
  58. package/src/server/gateways/memory-ghost.ts +343 -0
  59. package/src/server/gateways/memory-query.ts +452 -0
  60. package/src/server/gateways/memory-record.ts +346 -0
  61. package/src/server/gateways/memory-review.ts +410 -0
  62. package/src/server/gateways/memory-status.ts +517 -0
  63. package/src/server/gateways/memory-verify.ts +392 -0
  64. package/src/server/gateways/router.ts +434 -0
  65. package/src/server/gateways/types.ts +610 -0
  66. package/src/server/mcp.ts +154 -0
  67. package/src/server/resources.ts +85 -0
  68. package/src/server/tools.ts +2261 -0
  69. package/src/storage/database.ts +262 -0
  70. package/src/storage/tier1.ts +135 -0
  71. package/src/storage/tier2.ts +764 -0
  72. package/src/storage/tier3.ts +123 -0
  73. package/src/types/documentation.ts +619 -0
  74. package/src/types/index.ts +222 -0
  75. package/src/utils/config.ts +193 -0
  76. package/src/utils/files.ts +117 -0
  77. package/src/utils/time.ts +37 -0
  78. 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
+ }