neuronlayer 0.1.9 → 0.2.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.

Potentially problematic release.


This version of neuronlayer might be problematic. Click here for more details.

Files changed (81) hide show
  1. package/README.md +3 -2
  2. package/dist/index.js +172 -90
  3. package/dist/index.js.map +7 -0
  4. package/package.json +6 -1
  5. package/esbuild.config.js +0 -26
  6. package/src/cli/commands.ts +0 -573
  7. package/src/core/adr-exporter.ts +0 -253
  8. package/src/core/architecture/architecture-enforcement.ts +0 -228
  9. package/src/core/architecture/duplicate-detector.ts +0 -288
  10. package/src/core/architecture/index.ts +0 -6
  11. package/src/core/architecture/pattern-learner.ts +0 -306
  12. package/src/core/architecture/pattern-library.ts +0 -403
  13. package/src/core/architecture/pattern-validator.ts +0 -324
  14. package/src/core/change-intelligence/bug-correlator.ts +0 -544
  15. package/src/core/change-intelligence/change-intelligence.ts +0 -264
  16. package/src/core/change-intelligence/change-tracker.ts +0 -334
  17. package/src/core/change-intelligence/fix-suggester.ts +0 -340
  18. package/src/core/change-intelligence/index.ts +0 -5
  19. package/src/core/code-verifier.ts +0 -843
  20. package/src/core/confidence/confidence-scorer.ts +0 -251
  21. package/src/core/confidence/conflict-checker.ts +0 -289
  22. package/src/core/confidence/index.ts +0 -5
  23. package/src/core/confidence/source-tracker.ts +0 -263
  24. package/src/core/confidence/warning-detector.ts +0 -241
  25. package/src/core/context-rot/compaction.ts +0 -284
  26. package/src/core/context-rot/context-health.ts +0 -243
  27. package/src/core/context-rot/context-rot-prevention.ts +0 -213
  28. package/src/core/context-rot/critical-context.ts +0 -221
  29. package/src/core/context-rot/drift-detector.ts +0 -255
  30. package/src/core/context-rot/index.ts +0 -7
  31. package/src/core/context.ts +0 -263
  32. package/src/core/decision-extractor.ts +0 -339
  33. package/src/core/decisions.ts +0 -69
  34. package/src/core/deja-vu.ts +0 -421
  35. package/src/core/engine.ts +0 -1646
  36. package/src/core/feature-context.ts +0 -726
  37. package/src/core/ghost-mode.ts +0 -465
  38. package/src/core/learning.ts +0 -519
  39. package/src/core/living-docs/activity-tracker.ts +0 -296
  40. package/src/core/living-docs/architecture-generator.ts +0 -428
  41. package/src/core/living-docs/changelog-generator.ts +0 -348
  42. package/src/core/living-docs/component-generator.ts +0 -230
  43. package/src/core/living-docs/doc-engine.ts +0 -134
  44. package/src/core/living-docs/doc-validator.ts +0 -282
  45. package/src/core/living-docs/index.ts +0 -8
  46. package/src/core/project-manager.ts +0 -301
  47. package/src/core/refresh/activity-gate.ts +0 -256
  48. package/src/core/refresh/git-staleness-checker.ts +0 -108
  49. package/src/core/refresh/index.ts +0 -27
  50. package/src/core/summarizer.ts +0 -290
  51. package/src/core/test-awareness/change-validator.ts +0 -499
  52. package/src/core/test-awareness/index.ts +0 -5
  53. package/src/index.ts +0 -90
  54. package/src/indexing/ast.ts +0 -868
  55. package/src/indexing/embeddings.ts +0 -85
  56. package/src/indexing/indexer.ts +0 -270
  57. package/src/indexing/watcher.ts +0 -78
  58. package/src/server/gateways/aggregator.ts +0 -374
  59. package/src/server/gateways/index.ts +0 -473
  60. package/src/server/gateways/memory-ghost.ts +0 -343
  61. package/src/server/gateways/memory-query.ts +0 -452
  62. package/src/server/gateways/memory-record.ts +0 -346
  63. package/src/server/gateways/memory-review.ts +0 -410
  64. package/src/server/gateways/memory-status.ts +0 -517
  65. package/src/server/gateways/memory-verify.ts +0 -392
  66. package/src/server/gateways/router.ts +0 -434
  67. package/src/server/gateways/types.ts +0 -610
  68. package/src/server/http.ts +0 -228
  69. package/src/server/mcp.ts +0 -154
  70. package/src/server/resources.ts +0 -85
  71. package/src/server/tools.ts +0 -2460
  72. package/src/storage/database.ts +0 -271
  73. package/src/storage/tier1.ts +0 -135
  74. package/src/storage/tier2.ts +0 -972
  75. package/src/storage/tier3.ts +0 -123
  76. package/src/types/documentation.ts +0 -619
  77. package/src/types/index.ts +0 -222
  78. package/src/utils/config.ts +0 -194
  79. package/src/utils/files.ts +0 -117
  80. package/src/utils/time.ts +0 -37
  81. package/src/utils/tokens.ts +0 -52
@@ -1,213 +0,0 @@
1
- import type Database from 'better-sqlite3';
2
- import type {
3
- ContextHealth,
4
- CompactionResult,
5
- CompactionOptions,
6
- CompactionSuggestion,
7
- CriticalContext,
8
- DriftResult
9
- } from '../../types/documentation.js';
10
- import { ContextHealthMonitor } from './context-health.js';
11
- import { DriftDetector } from './drift-detector.js';
12
- import { CompactionEngine } from './compaction.js';
13
- import { CriticalContextManager } from './critical-context.js';
14
-
15
- interface Message {
16
- role: 'user' | 'assistant' | 'system';
17
- content: string;
18
- timestamp?: Date;
19
- }
20
-
21
- export class ContextRotPrevention {
22
- private healthMonitor: ContextHealthMonitor;
23
- private driftDetector: DriftDetector;
24
- private compactionEngine: CompactionEngine;
25
- private criticalManager: CriticalContextManager;
26
- private db: Database.Database;
27
-
28
- constructor(db: Database.Database, tokenLimit?: number) {
29
- this.db = db;
30
- this.criticalManager = new CriticalContextManager(db);
31
- this.healthMonitor = new ContextHealthMonitor(db, this.criticalManager, tokenLimit);
32
- this.driftDetector = new DriftDetector(this.criticalManager);
33
- this.compactionEngine = new CompactionEngine(this.healthMonitor, this.criticalManager);
34
- }
35
-
36
- // ========== Context Health ==========
37
-
38
- getContextHealth(): ContextHealth {
39
- const driftResult = this.driftDetector.detectDrift();
40
- return this.healthMonitor.getHealth(driftResult.driftScore);
41
- }
42
-
43
- setTokenLimit(limit: number): void {
44
- this.healthMonitor.setTokenLimit(limit);
45
- }
46
-
47
- setCurrentTokens(tokens: number): void {
48
- this.healthMonitor.setCurrentTokens(tokens);
49
- }
50
-
51
- addContextChunk(content: string, tokens: number, type: 'message' | 'decision' | 'requirement' | 'instruction' | 'code' = 'message'): void {
52
- this.healthMonitor.addChunk({
53
- content,
54
- tokens,
55
- timestamp: new Date(),
56
- type
57
- });
58
- }
59
-
60
- // ========== Message Tracking ==========
61
-
62
- addMessage(message: Message): void {
63
- this.driftDetector.addMessage(message);
64
-
65
- // Also add as context chunk
66
- const tokens = this.healthMonitor.estimateTokens(message.content);
67
- this.addContextChunk(message.content, tokens, 'message');
68
- }
69
-
70
- clearConversation(): void {
71
- this.driftDetector.clearHistory();
72
- this.healthMonitor.clearChunks();
73
- }
74
-
75
- // ========== Drift Detection ==========
76
-
77
- detectDrift(): DriftResult {
78
- return this.driftDetector.detectDrift();
79
- }
80
-
81
- addRequirement(requirement: string): void {
82
- this.driftDetector.addRequirement(requirement);
83
- }
84
-
85
- getRequirements(): string[] {
86
- return this.driftDetector.getInitialRequirements();
87
- }
88
-
89
- // ========== Critical Context ==========
90
-
91
- markCritical(
92
- content: string,
93
- options?: {
94
- type?: CriticalContext['type'];
95
- reason?: string;
96
- source?: string;
97
- }
98
- ): CriticalContext {
99
- return this.criticalManager.markCritical(content, options);
100
- }
101
-
102
- getCriticalContext(type?: CriticalContext['type']): CriticalContext[] {
103
- return this.criticalManager.getCriticalContext(type);
104
- }
105
-
106
- removeCritical(id: string): boolean {
107
- return this.criticalManager.removeCritical(id);
108
- }
109
-
110
- getAllCriticalContent(): string {
111
- return this.criticalManager.getAllCriticalContent();
112
- }
113
-
114
- // ========== Compaction ==========
115
-
116
- suggestCompaction(): CompactionSuggestion {
117
- return this.compactionEngine.suggestCompaction();
118
- }
119
-
120
- triggerCompaction(options: CompactionOptions): CompactionResult {
121
- const result = this.compactionEngine.compact(options);
122
-
123
- // Log compaction event
124
- this.logCompactionEvent(result);
125
-
126
- return result;
127
- }
128
-
129
- autoCompact(): CompactionResult {
130
- const result = this.compactionEngine.autoCompact();
131
- this.logCompactionEvent(result);
132
- return result;
133
- }
134
-
135
- private logCompactionEvent(result: CompactionResult): void {
136
- try {
137
- const stmt = this.db.prepare(`
138
- UPDATE context_health_history
139
- SET compaction_triggered = 1
140
- WHERE id = (SELECT MAX(id) FROM context_health_history)
141
- `);
142
- stmt.run();
143
- } catch {
144
- // Ignore logging errors
145
- }
146
- }
147
-
148
- // ========== Health History ==========
149
-
150
- getHealthHistory(limit: number = 20): Array<{
151
- timestamp: Date;
152
- health: ContextHealth['health'];
153
- utilizationPercent: number;
154
- driftScore: number;
155
- }> {
156
- return this.healthMonitor.getHealthHistory(limit);
157
- }
158
-
159
- // ========== Utilities ==========
160
-
161
- estimateTokens(text: string): number {
162
- return this.healthMonitor.estimateTokens(text);
163
- }
164
-
165
- isCritical(content: string): boolean {
166
- return this.criticalManager.isCritical(content);
167
- }
168
-
169
- extractCriticalFromText(text: string): Array<{ content: string; type: CriticalContext['type'] }> {
170
- return this.criticalManager.extractCriticalFromText(text);
171
- }
172
-
173
- // ========== Summary for AI ==========
174
-
175
- getContextSummaryForAI(): string {
176
- const health = this.getContextHealth();
177
- const critical = this.getAllCriticalContent();
178
- const drift = this.detectDrift();
179
-
180
- const parts: string[] = [];
181
-
182
- // Health status
183
- parts.push(`Context Health: ${health.health.toUpperCase()} (${health.utilizationPercent}% used)`);
184
-
185
- if (health.driftDetected) {
186
- parts.push(`\nWARNING: Drift detected (score: ${health.driftScore})`);
187
-
188
- if (drift.missingRequirements.length > 0) {
189
- parts.push('\nMissing requirements:');
190
- for (const req of drift.missingRequirements.slice(0, 3)) {
191
- parts.push(`- ${req}`);
192
- }
193
- }
194
-
195
- if (drift.suggestedReminders.length > 0) {
196
- parts.push('\nReminders:');
197
- for (const reminder of drift.suggestedReminders.slice(0, 3)) {
198
- parts.push(`- ${reminder}`);
199
- }
200
- }
201
- }
202
-
203
- if (critical) {
204
- parts.push(`\n${critical}`);
205
- }
206
-
207
- if (health.compactionNeeded) {
208
- parts.push(`\nSuggestion: ${health.suggestions[0] || 'Consider compacting context'}`);
209
- }
210
-
211
- return parts.join('\n');
212
- }
213
- }
@@ -1,221 +0,0 @@
1
- import { randomUUID } from 'crypto';
2
- import type Database from 'better-sqlite3';
3
- import type { CriticalContext } from '../../types/documentation.js';
4
-
5
- // Patterns for automatically detecting critical content
6
- const CRITICAL_PATTERNS = [
7
- // Explicit instructions
8
- { pattern: /\b(always|never|must|required|mandatory)\b/i, type: 'instruction' as const },
9
-
10
- // Decisions
11
- { pattern: /\b(we decided|the decision|chose to|decided to|will use)\b/i, type: 'decision' as const },
12
-
13
- // Requirements
14
- { pattern: /\b(requirement|constraint|rule|spec|specification)\b/i, type: 'requirement' as const },
15
-
16
- // User preferences
17
- { pattern: /\b(i prefer|i want|don't want|please don't|make sure)\b/i, type: 'instruction' as const },
18
-
19
- // Technical constraints
20
- { pattern: /\b(cannot|must not|impossible|not allowed|forbidden)\b/i, type: 'requirement' as const },
21
-
22
- // Important markers
23
- { pattern: /\b(important|critical|essential|crucial|key point)\b/i, type: 'instruction' as const }
24
- ];
25
-
26
- export class CriticalContextManager {
27
- private db: Database.Database;
28
-
29
- constructor(db: Database.Database) {
30
- this.db = db;
31
- }
32
-
33
- markCritical(
34
- content: string,
35
- options?: {
36
- type?: CriticalContext['type'];
37
- reason?: string;
38
- source?: string;
39
- neverCompress?: boolean;
40
- }
41
- ): CriticalContext {
42
- const id = randomUUID();
43
- const type = options?.type || this.inferType(content);
44
- const neverCompress = options?.neverCompress ?? true;
45
-
46
- const critical: CriticalContext = {
47
- id,
48
- type,
49
- content,
50
- reason: options?.reason,
51
- source: options?.source,
52
- createdAt: new Date(),
53
- neverCompress
54
- };
55
-
56
- const stmt = this.db.prepare(`
57
- INSERT INTO critical_context (id, type, content, reason, source, never_compress, created_at)
58
- VALUES (?, ?, ?, ?, ?, ?, ?)
59
- `);
60
-
61
- stmt.run(
62
- id,
63
- type,
64
- content,
65
- options?.reason || null,
66
- options?.source || null,
67
- neverCompress ? 1 : 0,
68
- Math.floor(Date.now() / 1000)
69
- );
70
-
71
- return critical;
72
- }
73
-
74
- getCriticalContext(type?: CriticalContext['type']): CriticalContext[] {
75
- let query = `
76
- SELECT id, type, content, reason, source, never_compress, created_at
77
- FROM critical_context
78
- `;
79
- const params: string[] = [];
80
-
81
- if (type) {
82
- query += ' WHERE type = ?';
83
- params.push(type);
84
- }
85
-
86
- query += ' ORDER BY created_at DESC';
87
-
88
- const stmt = this.db.prepare(query);
89
- const rows = (params.length > 0 ? stmt.all(params[0]) : stmt.all()) as Array<{
90
- id: string;
91
- type: string;
92
- content: string;
93
- reason: string | null;
94
- source: string | null;
95
- never_compress: number;
96
- created_at: number;
97
- }>;
98
-
99
- return rows.map(row => ({
100
- id: row.id,
101
- type: row.type as CriticalContext['type'],
102
- content: row.content,
103
- reason: row.reason || undefined,
104
- source: row.source || undefined,
105
- createdAt: new Date(row.created_at * 1000),
106
- neverCompress: row.never_compress === 1
107
- }));
108
- }
109
-
110
- getCriticalById(id: string): CriticalContext | null {
111
- const stmt = this.db.prepare(`
112
- SELECT id, type, content, reason, source, never_compress, created_at
113
- FROM critical_context
114
- WHERE id = ?
115
- `);
116
-
117
- const row = stmt.get(id) as {
118
- id: string;
119
- type: string;
120
- content: string;
121
- reason: string | null;
122
- source: string | null;
123
- never_compress: number;
124
- created_at: number;
125
- } | undefined;
126
-
127
- if (!row) return null;
128
-
129
- return {
130
- id: row.id,
131
- type: row.type as CriticalContext['type'],
132
- content: row.content,
133
- reason: row.reason || undefined,
134
- source: row.source || undefined,
135
- createdAt: new Date(row.created_at * 1000),
136
- neverCompress: row.never_compress === 1
137
- };
138
- }
139
-
140
- removeCritical(id: string): boolean {
141
- const stmt = this.db.prepare('DELETE FROM critical_context WHERE id = ?');
142
- const result = stmt.run(id);
143
- return result.changes > 0;
144
- }
145
-
146
- getCriticalCount(): number {
147
- const stmt = this.db.prepare('SELECT COUNT(*) as count FROM critical_context');
148
- const result = stmt.get() as { count: number };
149
- return result.count;
150
- }
151
-
152
- isCritical(content: string): boolean {
153
- return CRITICAL_PATTERNS.some(p => p.pattern.test(content));
154
- }
155
-
156
- inferType(content: string): CriticalContext['type'] {
157
- for (const { pattern, type } of CRITICAL_PATTERNS) {
158
- if (pattern.test(content)) {
159
- return type;
160
- }
161
- }
162
- return 'custom';
163
- }
164
-
165
- extractCriticalFromText(text: string): Array<{ content: string; type: CriticalContext['type'] }> {
166
- const results: Array<{ content: string; type: CriticalContext['type'] }> = [];
167
-
168
- // Split into sentences
169
- const sentences = text.split(/[.!?]+/).map(s => s.trim()).filter(Boolean);
170
-
171
- for (const sentence of sentences) {
172
- if (this.isCritical(sentence)) {
173
- results.push({
174
- content: sentence,
175
- type: this.inferType(sentence)
176
- });
177
- }
178
- }
179
-
180
- return results;
181
- }
182
-
183
- getAllCriticalContent(): string {
184
- const critical = this.getCriticalContext();
185
-
186
- if (critical.length === 0) {
187
- return '';
188
- }
189
-
190
- const grouped = {
191
- decision: [] as string[],
192
- requirement: [] as string[],
193
- instruction: [] as string[],
194
- custom: [] as string[]
195
- };
196
-
197
- for (const item of critical) {
198
- const arr = grouped[item.type as keyof typeof grouped];
199
- if (arr) {
200
- arr.push(item.content);
201
- }
202
- }
203
-
204
- const parts: string[] = [];
205
-
206
- if (grouped.decision.length > 0) {
207
- parts.push('DECISIONS:\n' + grouped.decision.map(d => `- ${d}`).join('\n'));
208
- }
209
- if (grouped.requirement.length > 0) {
210
- parts.push('REQUIREMENTS:\n' + grouped.requirement.map(r => `- ${r}`).join('\n'));
211
- }
212
- if (grouped.instruction.length > 0) {
213
- parts.push('INSTRUCTIONS:\n' + grouped.instruction.map(i => `- ${i}`).join('\n'));
214
- }
215
- if (grouped.custom.length > 0) {
216
- parts.push('OTHER CRITICAL:\n' + grouped.custom.map(c => `- ${c}`).join('\n'));
217
- }
218
-
219
- return parts.join('\n\n');
220
- }
221
- }
@@ -1,255 +0,0 @@
1
- import type { DriftResult, Contradiction, CriticalContext } from '../../types/documentation.js';
2
- import { CriticalContextManager } from './critical-context.js';
3
-
4
- interface Message {
5
- role: 'user' | 'assistant' | 'system';
6
- content: string;
7
- timestamp?: Date;
8
- }
9
-
10
- // Keywords that indicate topic areas
11
- const TOPIC_KEYWORDS: Record<string, string[]> = {
12
- authentication: ['auth', 'login', 'jwt', 'session', 'token', 'oauth', 'password'],
13
- database: ['database', 'db', 'sql', 'query', 'table', 'schema', 'migration'],
14
- api: ['api', 'endpoint', 'rest', 'graphql', 'route', 'request', 'response'],
15
- frontend: ['react', 'vue', 'component', 'ui', 'css', 'html', 'dom'],
16
- testing: ['test', 'spec', 'mock', 'assert', 'coverage', 'jest', 'vitest'],
17
- deployment: ['deploy', 'docker', 'kubernetes', 'ci', 'cd', 'pipeline'],
18
- security: ['security', 'encrypt', 'hash', 'vulnerability', 'xss', 'csrf'],
19
- performance: ['performance', 'optimize', 'cache', 'speed', 'memory', 'latency']
20
- };
21
-
22
- // Contradiction patterns (earlier statement vs later statement)
23
- const CONTRADICTION_PATTERNS = [
24
- { earlier: /will use (\w+)/i, later: /use (\w+) instead/i },
25
- { earlier: /decided on (\w+)/i, later: /switch(?:ed|ing)? to (\w+)/i },
26
- { earlier: /must (\w+)/i, later: /don't need to (\w+)/i },
27
- { earlier: /always (\w+)/i, later: /never (\w+)/i }
28
- ];
29
-
30
- export class DriftDetector {
31
- private criticalManager: CriticalContextManager;
32
- private conversationHistory: Message[] = [];
33
- private initialRequirements: string[] = [];
34
-
35
- constructor(criticalManager: CriticalContextManager) {
36
- this.criticalManager = criticalManager;
37
- }
38
-
39
- addMessage(message: Message): void {
40
- this.conversationHistory.push({
41
- ...message,
42
- timestamp: message.timestamp || new Date()
43
- });
44
-
45
- // Extract requirements from early user messages
46
- if (message.role === 'user' && this.conversationHistory.length <= 5) {
47
- const extracted = this.extractRequirements(message.content);
48
- this.initialRequirements.push(...extracted);
49
- }
50
- }
51
-
52
- clearHistory(): void {
53
- this.conversationHistory = [];
54
- this.initialRequirements = [];
55
- }
56
-
57
- getHistory(): Message[] {
58
- return [...this.conversationHistory];
59
- }
60
-
61
- detectDrift(): DriftResult {
62
- const criticalContext = this.criticalManager.getCriticalContext();
63
- const recentMessages = this.conversationHistory.slice(-10);
64
- const earlyMessages = this.conversationHistory.slice(0, 10);
65
-
66
- // Calculate drift score based on multiple factors
67
- const requirementAdherence = this.checkRequirementAdherence(recentMessages);
68
- const contradictions = this.findContradictions();
69
- const topicShift = this.calculateTopicShift(earlyMessages, recentMessages);
70
-
71
- // Weighted drift score
72
- const driftScore = Math.min(1, (
73
- (1 - requirementAdherence.score) * 0.4 +
74
- (contradictions.length > 0 ? Math.min(contradictions.length * 0.15, 0.3) : 0) +
75
- topicShift * 0.3
76
- ));
77
-
78
- // Generate suggested reminders
79
- const suggestedReminders = this.generateReminders(
80
- requirementAdherence.missing,
81
- criticalContext
82
- );
83
-
84
- return {
85
- driftScore: Math.round(driftScore * 100) / 100,
86
- driftDetected: driftScore >= 0.3,
87
- missingRequirements: requirementAdherence.missing,
88
- contradictions,
89
- suggestedReminders,
90
- topicShift: Math.round(topicShift * 100) / 100
91
- };
92
- }
93
-
94
- private extractRequirements(text: string): string[] {
95
- const requirements: string[] = [];
96
- const patterns = [
97
- /(?:must|should|need to|have to|required to)\s+(.+?)(?:[.!?]|$)/gi,
98
- /(?:make sure|ensure|always)\s+(.+?)(?:[.!?]|$)/gi,
99
- /(?:don't|never|avoid)\s+(.+?)(?:[.!?]|$)/gi
100
- ];
101
-
102
- for (const pattern of patterns) {
103
- let match;
104
- while ((match = pattern.exec(text)) !== null) {
105
- if (match[1] && match[1].length > 5 && match[1].length < 200) {
106
- requirements.push(match[1].trim());
107
- }
108
- }
109
- }
110
-
111
- return requirements;
112
- }
113
-
114
- private checkRequirementAdherence(recentMessages: Message[]): {
115
- score: number;
116
- missing: string[];
117
- } {
118
- if (this.initialRequirements.length === 0) {
119
- return { score: 1, missing: [] };
120
- }
121
-
122
- const recentText = recentMessages
123
- .filter(m => m.role === 'assistant')
124
- .map(m => m.content.toLowerCase())
125
- .join(' ');
126
-
127
- const missing: string[] = [];
128
- let found = 0;
129
-
130
- for (const req of this.initialRequirements) {
131
- // Check if requirement is being addressed in recent responses
132
- const keywords = req.toLowerCase().split(/\s+/).filter(w => w.length > 3);
133
- const matchCount = keywords.filter(kw => recentText.includes(kw)).length;
134
-
135
- if (matchCount >= keywords.length * 0.5) {
136
- found++;
137
- } else {
138
- missing.push(req);
139
- }
140
- }
141
-
142
- const score = this.initialRequirements.length > 0
143
- ? found / this.initialRequirements.length
144
- : 1;
145
-
146
- return { score, missing };
147
- }
148
-
149
- private findContradictions(): Contradiction[] {
150
- const contradictions: Contradiction[] = [];
151
- const messages = this.conversationHistory;
152
-
153
- // Compare each message with later messages
154
- for (let i = 0; i < messages.length - 1; i++) {
155
- const earlier = messages[i]!;
156
-
157
- for (let j = i + 1; j < messages.length; j++) {
158
- const later = messages[j]!;
159
-
160
- // Only check assistant responses for contradictions
161
- if (earlier.role !== 'assistant' || later.role !== 'assistant') continue;
162
-
163
- for (const pattern of CONTRADICTION_PATTERNS) {
164
- const earlierMatch = earlier.content.match(pattern.earlier);
165
- const laterMatch = later.content.match(pattern.later);
166
-
167
- if (earlierMatch && laterMatch) {
168
- // Check if it's talking about the same thing
169
- const earlierSubject = earlierMatch[1]?.toLowerCase();
170
- const laterSubject = laterMatch[1]?.toLowerCase();
171
-
172
- if (earlierSubject && laterSubject && earlierSubject !== laterSubject) {
173
- contradictions.push({
174
- earlier: earlier.content.slice(0, 100),
175
- later: later.content.slice(0, 100),
176
- severity: j - i > 10 ? 'high' : j - i > 5 ? 'medium' : 'low'
177
- });
178
- }
179
- }
180
- }
181
- }
182
- }
183
-
184
- // Limit to most recent contradictions
185
- return contradictions.slice(-5);
186
- }
187
-
188
- private calculateTopicShift(
189
- earlyMessages: Message[],
190
- recentMessages: Message[]
191
- ): number {
192
- const earlyTopics = this.extractTopics(earlyMessages);
193
- const recentTopics = this.extractTopics(recentMessages);
194
-
195
- if (earlyTopics.size === 0 || recentTopics.size === 0) {
196
- return 0;
197
- }
198
-
199
- // Calculate Jaccard similarity
200
- const intersection = new Set([...earlyTopics].filter(t => recentTopics.has(t)));
201
- const union = new Set([...earlyTopics, ...recentTopics]);
202
-
203
- const similarity = intersection.size / union.size;
204
-
205
- // Topic shift is inverse of similarity
206
- return 1 - similarity;
207
- }
208
-
209
- private extractTopics(messages: Message[]): Set<string> {
210
- const topics = new Set<string>();
211
- const text = messages.map(m => m.content.toLowerCase()).join(' ');
212
-
213
- for (const [topic, keywords] of Object.entries(TOPIC_KEYWORDS)) {
214
- for (const keyword of keywords) {
215
- if (text.includes(keyword)) {
216
- topics.add(topic);
217
- break;
218
- }
219
- }
220
- }
221
-
222
- return topics;
223
- }
224
-
225
- private generateReminders(
226
- missingRequirements: string[],
227
- criticalContext: CriticalContext[]
228
- ): string[] {
229
- const reminders: string[] = [];
230
-
231
- // Add reminders for missing requirements
232
- for (const req of missingRequirements.slice(0, 3)) {
233
- reminders.push(`Remember: ${req}`);
234
- }
235
-
236
- // Add reminders for critical context
237
- for (const critical of criticalContext.slice(0, 3)) {
238
- if (critical.type === 'decision') {
239
- reminders.push(`Decision: ${critical.content}`);
240
- } else if (critical.type === 'requirement') {
241
- reminders.push(`Requirement: ${critical.content}`);
242
- }
243
- }
244
-
245
- return reminders;
246
- }
247
-
248
- getInitialRequirements(): string[] {
249
- return [...this.initialRequirements];
250
- }
251
-
252
- addRequirement(requirement: string): void {
253
- this.initialRequirements.push(requirement);
254
- }
255
- }
@@ -1,7 +0,0 @@
1
- // Context Rot Prevention Module - Barrel Export
2
-
3
- export { ContextRotPrevention } from './context-rot-prevention.js';
4
- export { ContextHealthMonitor } from './context-health.js';
5
- export { DriftDetector } from './drift-detector.js';
6
- export { CompactionEngine } from './compaction.js';
7
- export { CriticalContextManager } from './critical-context.js';