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,410 @@
1
+ /**
2
+ * Memory Review Gateway
3
+ *
4
+ * Routes to: validate_pattern, check_conflicts, suggest_existing, check_tests,
5
+ * get_confidence, find_similar_bugs, suggest_test_update, get_related_tests,
6
+ * get_test_coverage
7
+ */
8
+
9
+ import type { MemoryLayerEngine } from '../../core/engine.js';
10
+ import type { MemoryReviewInput, MemoryReviewResponse } from './types.js';
11
+ import { detectReviewAction, getReviewChecks, isErrorMessage } from './router.js';
12
+ import {
13
+ aggregateReviewResults,
14
+ calculateRiskScore,
15
+ getVerdict,
16
+ type PatternValidationResult,
17
+ type ConflictCheckResult,
18
+ type ConfidenceCheckResult,
19
+ type TestCheckResult,
20
+ type ExistingFunctionResult,
21
+ } from './aggregator.js';
22
+
23
+ /**
24
+ * Handle a memory_review gateway call
25
+ */
26
+ export async function handleMemoryReview(
27
+ engine: MemoryLayerEngine,
28
+ input: MemoryReviewInput
29
+ ): Promise<MemoryReviewResponse> {
30
+ const action = detectReviewAction(input);
31
+ const sourcesUsed: string[] = [];
32
+
33
+ // Handle specific actions
34
+ if (action !== 'full') {
35
+ switch (action) {
36
+ case 'pattern':
37
+ return handlePatternOnly(engine, input, sourcesUsed);
38
+
39
+ case 'conflicts':
40
+ return handleConflictsOnly(engine, input, sourcesUsed);
41
+
42
+ case 'tests':
43
+ return handleTestsOnly(engine, input, sourcesUsed);
44
+
45
+ case 'confidence':
46
+ return handleConfidenceOnly(engine, input, sourcesUsed);
47
+
48
+ case 'bugs':
49
+ return handleBugsOnly(engine, input, sourcesUsed);
50
+
51
+ case 'coverage':
52
+ return handleCoverageOnly(engine, input, sourcesUsed);
53
+ }
54
+ }
55
+
56
+ // Full review - run applicable checks in parallel
57
+ return handleFullReview(engine, input, sourcesUsed);
58
+ }
59
+
60
+ /**
61
+ * Full comprehensive review
62
+ * Enhanced with Ghost Mode conflict detection
63
+ */
64
+ async function handleFullReview(
65
+ engine: MemoryLayerEngine,
66
+ input: MemoryReviewInput,
67
+ sourcesUsed: string[]
68
+ ): Promise<MemoryReviewResponse> {
69
+ const checks = getReviewChecks(input);
70
+
71
+ // Notify ghost mode of file access for silent tracking
72
+ if (input.file) {
73
+ engine.notifyFileAccess(input.file).catch(() => {});
74
+ }
75
+
76
+ // Build parallel operations
77
+ const operations: Promise<unknown>[] = [];
78
+ const operationKeys: string[] = [];
79
+
80
+ if (checks.runPatterns) {
81
+ sourcesUsed.push('validate_pattern');
82
+ operations.push(Promise.resolve(engine.validatePattern(input.code)));
83
+ operationKeys.push('pattern');
84
+ }
85
+
86
+ if (checks.runConflicts) {
87
+ sourcesUsed.push('check_conflicts');
88
+ operations.push(engine.checkCodeConflicts(input.code));
89
+ operationKeys.push('conflicts');
90
+ }
91
+
92
+ // Always run ghost mode conflict check for proactive intelligence
93
+ sourcesUsed.push('ghost_conflicts');
94
+ operations.push(Promise.resolve(engine.checkGhostConflicts(input.code, input.file)));
95
+ operationKeys.push('ghost');
96
+
97
+ if (checks.runConfidence) {
98
+ sourcesUsed.push('get_confidence');
99
+ operations.push(engine.getConfidence(input.code, input.intent));
100
+ operationKeys.push('confidence');
101
+ }
102
+
103
+ if (checks.runExisting && input.intent) {
104
+ sourcesUsed.push('suggest_existing');
105
+ operations.push(Promise.resolve(engine.suggestExisting(input.intent, 5)));
106
+ operationKeys.push('existing');
107
+ }
108
+
109
+ if (checks.runTests && input.file) {
110
+ sourcesUsed.push('check_tests');
111
+ operations.push(Promise.resolve(engine.checkTests(input.code, input.file)));
112
+ operationKeys.push('tests');
113
+ }
114
+
115
+ if (checks.runBugs && input.error) {
116
+ sourcesUsed.push('find_similar_bugs');
117
+ operations.push(Promise.resolve(engine.findSimilarBugs(input.error, 5)));
118
+ operationKeys.push('bugs');
119
+ }
120
+
121
+ // Run all checks in parallel
122
+ const results = await Promise.all(operations);
123
+
124
+ // Map results to their keys
125
+ const resultMap: Record<string, unknown> = {};
126
+ operationKeys.forEach((key, index) => {
127
+ resultMap[key] = results[index];
128
+ });
129
+
130
+ // Extract typed results
131
+ const patternResult = resultMap.pattern as PatternValidationResult | undefined;
132
+ const conflictsResult = resultMap.conflicts as ConflictCheckResult | undefined;
133
+ const confidenceResult = resultMap.confidence as ConfidenceCheckResult | undefined;
134
+ const existingResult = resultMap.existing as ExistingFunctionResult[] | undefined;
135
+ const testsResult = resultMap.tests as TestCheckResult | undefined;
136
+ const bugsResult = resultMap.bugs as Array<{
137
+ error: string;
138
+ similarity: number;
139
+ fix: string;
140
+ file?: string;
141
+ }> | undefined;
142
+ const ghostResult = resultMap.ghost as Array<{
143
+ decision: { id: string; title: string };
144
+ warning: string;
145
+ severity: 'low' | 'medium' | 'high';
146
+ matchedTerms: string[];
147
+ }> | undefined;
148
+
149
+ // Calculate risk score and aggregate
150
+ const response = aggregateReviewResults(
151
+ patternResult || null,
152
+ conflictsResult ? {
153
+ hasConflicts: conflictsResult.hasConflicts,
154
+ conflicts: conflictsResult.conflicts,
155
+ } : null,
156
+ confidenceResult || null,
157
+ existingResult || null,
158
+ testsResult || null,
159
+ sourcesUsed
160
+ );
161
+
162
+ // Add ghost mode conflict warnings (proactive intelligence)
163
+ if (ghostResult && ghostResult.length > 0) {
164
+ // Merge ghost conflicts into the conflicts response
165
+ const ghostConflicts = ghostResult.map(g => ({
166
+ decision_id: g.decision.id,
167
+ decision_title: g.decision.title,
168
+ conflict_description: g.warning,
169
+ severity: g.severity,
170
+ }));
171
+
172
+ if (response.conflicts) {
173
+ // Add ghost conflicts that aren't already in the regular conflicts
174
+ const existingIds = new Set(response.conflicts.conflicts.map(c => c.decision_id));
175
+ const newConflicts = ghostConflicts.filter(c => !existingIds.has(c.decision_id));
176
+ response.conflicts.conflicts.push(...newConflicts);
177
+ response.conflicts.has_conflicts = response.conflicts.conflicts.length > 0;
178
+ } else if (ghostConflicts.length > 0) {
179
+ response.conflicts = {
180
+ has_conflicts: true,
181
+ conflicts: ghostConflicts,
182
+ };
183
+
184
+ // Increase risk score for ghost conflicts
185
+ const highSeverity = ghostConflicts.filter(c => c.severity === 'high').length;
186
+ const mediumSeverity = ghostConflicts.filter(c => c.severity === 'medium').length;
187
+ response.risk_score = Math.min(100, response.risk_score + highSeverity * 20 + mediumSeverity * 10);
188
+
189
+ // Update verdict if needed
190
+ if (response.risk_score >= 70) {
191
+ response.verdict = 'reject';
192
+ } else if (response.risk_score >= 30) {
193
+ response.verdict = 'warning';
194
+ }
195
+ }
196
+ }
197
+
198
+ // Add similar bugs if found
199
+ if (bugsResult && bugsResult.length > 0) {
200
+ response.similar_bugs = bugsResult.map(b => ({
201
+ error: b.error.slice(0, 100),
202
+ similarity: b.similarity,
203
+ fix: b.fix,
204
+ file: b.file,
205
+ }));
206
+ }
207
+
208
+ return response;
209
+ }
210
+
211
+ /**
212
+ * Pattern validation only
213
+ */
214
+ async function handlePatternOnly(
215
+ engine: MemoryLayerEngine,
216
+ input: MemoryReviewInput,
217
+ sourcesUsed: string[]
218
+ ): Promise<MemoryReviewResponse> {
219
+ sourcesUsed.push('validate_pattern');
220
+
221
+ const result = engine.validatePattern(input.code);
222
+
223
+ const riskScore = calculateRiskScore(result, null, null, null);
224
+
225
+ return {
226
+ verdict: getVerdict(riskScore),
227
+ risk_score: riskScore,
228
+ sources_used: sourcesUsed,
229
+ patterns: {
230
+ valid: result.valid,
231
+ score: result.score,
232
+ matched_pattern: result.matchedPattern,
233
+ violations: result.violations,
234
+ },
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Conflict check only
240
+ */
241
+ async function handleConflictsOnly(
242
+ engine: MemoryLayerEngine,
243
+ input: MemoryReviewInput,
244
+ sourcesUsed: string[]
245
+ ): Promise<MemoryReviewResponse> {
246
+ sourcesUsed.push('check_conflicts');
247
+
248
+ const result = await engine.checkCodeConflicts(input.code);
249
+
250
+ const riskScore = calculateRiskScore(null, {
251
+ hasConflicts: result.hasConflicts,
252
+ conflicts: result.conflicts,
253
+ }, null, null);
254
+
255
+ return {
256
+ verdict: getVerdict(riskScore),
257
+ risk_score: riskScore,
258
+ sources_used: sourcesUsed,
259
+ conflicts: {
260
+ has_conflicts: result.hasConflicts,
261
+ conflicts: result.conflicts.map(c => ({
262
+ decision_id: c.decisionId,
263
+ decision_title: c.decisionTitle,
264
+ conflict_description: c.conflictDescription,
265
+ severity: c.severity,
266
+ })),
267
+ },
268
+ };
269
+ }
270
+
271
+ /**
272
+ * Test check only
273
+ */
274
+ async function handleTestsOnly(
275
+ engine: MemoryLayerEngine,
276
+ input: MemoryReviewInput,
277
+ sourcesUsed: string[]
278
+ ): Promise<MemoryReviewResponse> {
279
+ if (!input.file) {
280
+ return {
281
+ verdict: 'warning',
282
+ risk_score: 50,
283
+ sources_used: sourcesUsed,
284
+ };
285
+ }
286
+
287
+ sourcesUsed.push('check_tests');
288
+
289
+ const result = engine.checkTests(input.code, input.file);
290
+
291
+ const riskScore = calculateRiskScore(null, null, result, null);
292
+
293
+ return {
294
+ verdict: getVerdict(riskScore),
295
+ risk_score: riskScore,
296
+ sources_used: sourcesUsed,
297
+ test_impact: {
298
+ safe: result.safe,
299
+ coverage_percent: result.coveragePercent,
300
+ would_fail: result.wouldFail.map(f => ({
301
+ test_name: f.test.name,
302
+ test_file: f.test.file,
303
+ reason: f.reason,
304
+ suggested_fix: f.suggestedFix,
305
+ })),
306
+ suggested_updates: result.suggestedTestUpdates.map(u => ({
307
+ file: u.file,
308
+ test_name: u.testName,
309
+ before: u.before,
310
+ after: u.after,
311
+ reason: u.reason,
312
+ })),
313
+ },
314
+ };
315
+ }
316
+
317
+ /**
318
+ * Confidence check only
319
+ */
320
+ async function handleConfidenceOnly(
321
+ engine: MemoryLayerEngine,
322
+ input: MemoryReviewInput,
323
+ sourcesUsed: string[]
324
+ ): Promise<MemoryReviewResponse> {
325
+ sourcesUsed.push('get_confidence');
326
+
327
+ const result = await engine.getConfidence(input.code, input.intent);
328
+
329
+ const riskScore = calculateRiskScore(null, null, null, result);
330
+
331
+ return {
332
+ verdict: getVerdict(riskScore),
333
+ risk_score: riskScore,
334
+ sources_used: sourcesUsed,
335
+ confidence: {
336
+ level: result.confidence,
337
+ score: result.score,
338
+ reasoning: result.reasoning,
339
+ },
340
+ };
341
+ }
342
+
343
+ /**
344
+ * Bug search only
345
+ */
346
+ async function handleBugsOnly(
347
+ engine: MemoryLayerEngine,
348
+ input: MemoryReviewInput,
349
+ sourcesUsed: string[]
350
+ ): Promise<MemoryReviewResponse> {
351
+ if (!input.error) {
352
+ return {
353
+ verdict: 'approve',
354
+ risk_score: 0,
355
+ sources_used: sourcesUsed,
356
+ };
357
+ }
358
+
359
+ sourcesUsed.push('find_similar_bugs');
360
+
361
+ const bugs = engine.findSimilarBugs(input.error, 5);
362
+
363
+ return {
364
+ verdict: bugs.length > 0 ? 'warning' : 'approve',
365
+ risk_score: bugs.length > 0 ? 30 : 0,
366
+ sources_used: sourcesUsed,
367
+ similar_bugs: bugs.map(b => ({
368
+ error: b.error.slice(0, 100),
369
+ similarity: b.similarity,
370
+ fix: b.fix,
371
+ file: b.file,
372
+ })),
373
+ };
374
+ }
375
+
376
+ /**
377
+ * Coverage check only
378
+ */
379
+ async function handleCoverageOnly(
380
+ engine: MemoryLayerEngine,
381
+ input: MemoryReviewInput,
382
+ sourcesUsed: string[]
383
+ ): Promise<MemoryReviewResponse> {
384
+ if (!input.file) {
385
+ return {
386
+ verdict: 'warning',
387
+ risk_score: 50,
388
+ sources_used: sourcesUsed,
389
+ };
390
+ }
391
+
392
+ sourcesUsed.push('get_test_coverage');
393
+
394
+ const coverage = engine.getTestCoverage(input.file);
395
+
396
+ // Risk based on coverage percentage
397
+ const riskScore = Math.max(0, 100 - coverage.coveragePercent);
398
+
399
+ return {
400
+ verdict: getVerdict(riskScore),
401
+ risk_score: riskScore,
402
+ sources_used: sourcesUsed,
403
+ coverage: {
404
+ file: coverage.file,
405
+ total_tests: coverage.totalTests,
406
+ coverage_percent: coverage.coveragePercent,
407
+ uncovered_functions: coverage.uncoveredFunctions,
408
+ },
409
+ };
410
+ }