@noyrax/5d-database-plugin 0.1.8 → 0.1.10-beta.1

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 (92) hide show
  1. package/MCP_SERVER_SETUP.md +14 -0
  2. package/README.md +49 -3
  3. package/SETUP_NEW_PROJECT.md +245 -14
  4. package/out/api/adr-api.d.ts +15 -2
  5. package/out/api/adr-api.d.ts.map +1 -1
  6. package/out/api/adr-api.js +98 -4
  7. package/out/api/adr-api.js.map +1 -1
  8. package/out/api/index.d.ts +1 -0
  9. package/out/api/index.d.ts.map +1 -1
  10. package/out/api/index.js +3 -1
  11. package/out/api/index.js.map +1 -1
  12. package/out/api/ingestion-api.d.ts +42 -0
  13. package/out/api/ingestion-api.d.ts.map +1 -0
  14. package/out/api/ingestion-api.js +148 -0
  15. package/out/api/ingestion-api.js.map +1 -0
  16. package/out/api/module-api.d.ts +11 -1
  17. package/out/api/module-api.d.ts.map +1 -1
  18. package/out/api/module-api.js +54 -2
  19. package/out/api/module-api.js.map +1 -1
  20. package/out/cli/ingest-cli.js +43 -19
  21. package/out/cli/ingest-cli.js.map +1 -1
  22. package/out/cli/merge-workspaces-cli.d.ts +3 -0
  23. package/out/cli/merge-workspaces-cli.d.ts.map +1 -0
  24. package/out/cli/merge-workspaces-cli.js +199 -0
  25. package/out/cli/merge-workspaces-cli.js.map +1 -0
  26. package/out/cli/tool-cli.js +59 -4
  27. package/out/cli/tool-cli.js.map +1 -1
  28. package/out/core/chromadb-vector-database.d.ts.map +1 -1
  29. package/out/core/chromadb-vector-database.js +6 -2
  30. package/out/core/chromadb-vector-database.js.map +1 -1
  31. package/out/core/migration-manager.d.ts +31 -0
  32. package/out/core/migration-manager.d.ts.map +1 -1
  33. package/out/core/migration-manager.js +126 -7
  34. package/out/core/migration-manager.js.map +1 -1
  35. package/out/core/multi-db-manager.d.ts +10 -0
  36. package/out/core/multi-db-manager.d.ts.map +1 -1
  37. package/out/core/multi-db-manager.js +51 -0
  38. package/out/core/multi-db-manager.js.map +1 -1
  39. package/out/ingestors/adr-ingestor.d.ts +7 -0
  40. package/out/ingestors/adr-ingestor.d.ts.map +1 -1
  41. package/out/ingestors/adr-ingestor.js +41 -9
  42. package/out/ingestors/adr-ingestor.js.map +1 -1
  43. package/out/mcp/server.d.ts +3 -0
  44. package/out/mcp/server.d.ts.map +1 -1
  45. package/out/mcp/server.js +106 -2
  46. package/out/mcp/server.js.map +1 -1
  47. package/out/mcp/tools/adr-generator.d.ts +123 -0
  48. package/out/mcp/tools/adr-generator.d.ts.map +1 -0
  49. package/out/mcp/tools/adr-generator.js +1113 -0
  50. package/out/mcp/tools/adr-generator.js.map +1 -0
  51. package/out/mcp/tools/gap-analysis.d.ts +6 -2
  52. package/out/mcp/tools/gap-analysis.d.ts.map +1 -1
  53. package/out/mcp/tools/gap-analysis.js +32 -5
  54. package/out/mcp/tools/gap-analysis.js.map +1 -1
  55. package/out/repositories/module-repository.d.ts +5 -0
  56. package/out/repositories/module-repository.d.ts.map +1 -1
  57. package/out/repositories/module-repository.js +24 -0
  58. package/out/repositories/module-repository.js.map +1 -1
  59. package/out/services/adr-context-builder.d.ts +70 -0
  60. package/out/services/adr-context-builder.d.ts.map +1 -0
  61. package/out/services/adr-context-builder.js +141 -0
  62. package/out/services/adr-context-builder.js.map +1 -0
  63. package/out/services/adr-pattern-analyzer.d.ts +75 -0
  64. package/out/services/adr-pattern-analyzer.d.ts.map +1 -0
  65. package/out/services/adr-pattern-analyzer.js +339 -0
  66. package/out/services/adr-pattern-analyzer.js.map +1 -0
  67. package/out/services/adr-reasoning-service.d.ts +63 -0
  68. package/out/services/adr-reasoning-service.d.ts.map +1 -0
  69. package/out/services/adr-reasoning-service.js +760 -0
  70. package/out/services/adr-reasoning-service.js.map +1 -0
  71. package/out/services/navigation-builder.d.ts.map +1 -1
  72. package/out/services/navigation-builder.js +70 -11
  73. package/out/services/navigation-builder.js.map +1 -1
  74. package/out/services/noyrax-integration-service.d.ts +51 -0
  75. package/out/services/noyrax-integration-service.d.ts.map +1 -0
  76. package/out/services/noyrax-integration-service.js +215 -0
  77. package/out/services/noyrax-integration-service.js.map +1 -0
  78. package/out/services/semantic-pattern-matcher.d.ts +61 -0
  79. package/out/services/semantic-pattern-matcher.d.ts.map +1 -0
  80. package/out/services/semantic-pattern-matcher.js +183 -0
  81. package/out/services/semantic-pattern-matcher.js.map +1 -0
  82. package/out/services/workflow-orchestrator.d.ts +63 -0
  83. package/out/services/workflow-orchestrator.d.ts.map +1 -0
  84. package/out/services/workflow-orchestrator.js +111 -0
  85. package/out/services/workflow-orchestrator.js.map +1 -0
  86. package/out/ui/commands.d.ts.map +1 -1
  87. package/out/ui/commands.js +112 -1
  88. package/out/ui/commands.js.map +1 -1
  89. package/out/ui/database-explorer.d.ts.map +1 -1
  90. package/out/ui/database-explorer.js +47 -1
  91. package/out/ui/database-explorer.js.map +1 -1
  92. package/package.json +22 -4
@@ -0,0 +1,760 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ var __importDefault = (this && this.__importDefault) || function (mod) {
36
+ return (mod && mod.__esModule) ? mod : { "default": mod };
37
+ };
38
+ Object.defineProperty(exports, "__esModule", { value: true });
39
+ exports.AdrReasoningService = void 0;
40
+ const openai_1 = __importDefault(require("openai"));
41
+ const path = __importStar(require("path"));
42
+ /**
43
+ * Service for reconstructing "Why" (rationale) from module context using LLM.
44
+ * Uses OpenAI API to generate structured reasoning about architectural decisions.
45
+ */
46
+ class AdrReasoningService {
47
+ constructor(apiKey) {
48
+ this.openai = null;
49
+ this.defaultModel = 'gpt-4o-mini';
50
+ this.temperature = 0; // Deterministic output
51
+ if (apiKey) {
52
+ this.openai = new openai_1.default({ apiKey });
53
+ }
54
+ else {
55
+ // Try to get from environment variable
56
+ const envKey = process.env.OPENAI_API_KEY;
57
+ if (envKey) {
58
+ this.openai = new openai_1.default({ apiKey: envKey });
59
+ }
60
+ else {
61
+ console.warn('[AdrReasoningService] OpenAI API key not provided. LLM reasoning will not work.');
62
+ }
63
+ }
64
+ }
65
+ /**
66
+ * Checks if LLM is available.
67
+ */
68
+ isAvailable() {
69
+ return this.openai !== null;
70
+ }
71
+ /**
72
+ * Reconstructs complete reasoning (problems, decision, rationale, alternatives, trade-offs).
73
+ */
74
+ async reconstructWhy(context, similarAdrs, patterns, complexity = 'complex') {
75
+ if (!this.openai) {
76
+ throw new Error('OpenAI API not configured. Set OPENAI_API_KEY environment variable.');
77
+ }
78
+ const prompt = this.buildReasoningPrompt(context, similarAdrs, patterns, complexity);
79
+ try {
80
+ const response = await this.openai.chat.completions.create({
81
+ model: this.defaultModel,
82
+ messages: [
83
+ {
84
+ role: 'system',
85
+ content: `Du bist ein Architektur-Analyst. Analysiere Module und rekonstruiere Architektur-Entscheidungen aus Code-Struktur, Dependencies und Patterns.
86
+
87
+ KRITISCH - Vermeide generische Aussagen:
88
+ ❌ "Die Notwendigkeit, X zu implementieren"
89
+ ❌ "Die Herausforderung, Y zu schaffen"
90
+ ❌ "Die Anforderung, Z zu verwalten"
91
+ ❌ "Ermöglicht eine..."
92
+ ❌ "Bietet eine..."
93
+
94
+ ✅ Stattdessen: Konkrete, spezifische Architektur-Gründe:
95
+ ✅ "VS Code API erfordert activate() in extension.ts"
96
+ ✅ "25 Dependencies wegen Feature-Orchestration bei Extension-Start"
97
+ ✅ "DocumentationProvider implementiert TreeDataProvider für Sidebar"
98
+ ✅ "Repository Pattern wegen konsistenter CRUD-Operationen über 5 Dimensionen"
99
+
100
+ Analysiere Code-Struktur, Dependencies und Patterns.
101
+ Sei SPEZIFISCH, nicht generisch.
102
+ Antworte IMMER im JSON-Format.`
103
+ },
104
+ {
105
+ role: 'user',
106
+ content: prompt
107
+ }
108
+ ],
109
+ temperature: this.temperature,
110
+ response_format: { type: 'json_object' }
111
+ });
112
+ const content = response.choices[0]?.message?.content;
113
+ if (!content) {
114
+ throw new Error('Empty response from OpenAI API');
115
+ }
116
+ const reasoning = JSON.parse(content);
117
+ // Validate structure
118
+ this.validateReasoning(reasoning);
119
+ return reasoning;
120
+ }
121
+ catch (error) {
122
+ const errorMsg = error instanceof Error ? error.message : String(error);
123
+ console.error(`[AdrReasoningService] Failed to reconstruct reasoning: ${errorMsg}`);
124
+ throw error;
125
+ }
126
+ }
127
+ /**
128
+ * Reconstructs problems that this module solves.
129
+ */
130
+ async reconstructProblems(context, similarAdrs) {
131
+ const reasoning = await this.reconstructWhy(context, similarAdrs, []);
132
+ return reasoning.problems;
133
+ }
134
+ /**
135
+ * Reconstructs decision with rationale.
136
+ */
137
+ async reconstructDecision(context, similarAdrs, patterns) {
138
+ const reasoning = await this.reconstructWhy(context, similarAdrs, patterns);
139
+ return {
140
+ decision: reasoning.decision,
141
+ rationale: reasoning.rationale
142
+ };
143
+ }
144
+ /**
145
+ * Reconstructs alternatives that were considered.
146
+ */
147
+ async reconstructAlternatives(context, similarAdrs) {
148
+ const reasoning = await this.reconstructWhy(context, similarAdrs, []);
149
+ return reasoning.alternatives;
150
+ }
151
+ /**
152
+ * Builds structured prompt for reasoning.
153
+ */
154
+ buildReasoningPrompt(context, similarAdrs, patterns, complexity = 'complex') {
155
+ const module = context.module;
156
+ const moduleDoc = this.parseModuleDocumentation(module.content_markdown);
157
+ const moduleName = path.basename(module.file_path, path.extname(module.file_path));
158
+ const moduleDir = path.dirname(module.file_path);
159
+ let prompt = `Analysiere das folgende Modul und rekonstruiere die Architektur-Entscheidungen.\n\n`;
160
+ // Module information
161
+ prompt += `## MODUL\n\n`;
162
+ prompt += `- **Pfad:** \`${module.file_path}\`\n`;
163
+ prompt += `- **Verzeichnis:** \`${moduleDir}\`\n`;
164
+ prompt += `- **Dateiname:** \`${moduleName}\`\n\n`;
165
+ // Classes (limit based on complexity)
166
+ if (moduleDoc.classes.length > 0) {
167
+ const maxClasses = complexity === 'simple' ? 2 : complexity === 'medium' ? 5 : 10;
168
+ prompt += `**Klassen/Interfaces (${moduleDoc.classes.length}):**\n`;
169
+ for (const cls of moduleDoc.classes.slice(0, maxClasses)) {
170
+ prompt += `- \`${cls.name}\` (${cls.role || 'other'})`;
171
+ if (cls.methodCount > 0 && complexity !== 'simple') {
172
+ prompt += ` - ${cls.methodCount} Methoden`;
173
+ }
174
+ prompt += `\n`;
175
+ }
176
+ prompt += `\n`;
177
+ }
178
+ // Key functions (limit based on complexity)
179
+ if (moduleDoc.keyFunctions.length > 0) {
180
+ const maxFunctions = complexity === 'simple' ? 3 : complexity === 'medium' ? 8 : 15;
181
+ prompt += `**Hauptfunktionen (${moduleDoc.keyFunctions.length}):**\n`;
182
+ for (const func of moduleDoc.keyFunctions.slice(0, maxFunctions)) {
183
+ prompt += `- \`${func.name}()\``;
184
+ if (func.role && complexity !== 'simple') {
185
+ prompt += ` (${func.role})`;
186
+ }
187
+ if (func.signature && complexity === 'complex') {
188
+ const sigPreview = func.signature.length > 100 ? func.signature.substring(0, 100) + '...' : func.signature;
189
+ prompt += `\n Signatur: \`${sigPreview}\``;
190
+ }
191
+ prompt += `\n`;
192
+ }
193
+ prompt += `\n`;
194
+ }
195
+ // Dependencies - Group by category for later use
196
+ const coreDeps = [];
197
+ const apiDeps = [];
198
+ const serviceDeps = [];
199
+ const otherDeps = [];
200
+ // Incoming dependencies - calculate early for use in multiple places
201
+ const uniqueIncomingUsers = new Set(context.incomingDependencies.map((d) => d.from_module || d.from));
202
+ if (context.dependencies.length > 0) {
203
+ prompt += `**Dependencies (${context.dependencies.length}):**\n`;
204
+ for (const dep of context.dependencies) {
205
+ const toModule = dep.to_module || '';
206
+ if (toModule.includes('/core/')) {
207
+ coreDeps.push(toModule);
208
+ }
209
+ else if (toModule.includes('/api/')) {
210
+ apiDeps.push(toModule);
211
+ }
212
+ else if (toModule.includes('/services/')) {
213
+ serviceDeps.push(toModule);
214
+ }
215
+ else {
216
+ otherDeps.push(toModule);
217
+ }
218
+ }
219
+ if (coreDeps.length > 0) {
220
+ prompt += `- Core Dependencies (${coreDeps.length}): ${coreDeps.slice(0, 10).map(d => `\`${d}\``).join(', ')}\n`;
221
+ }
222
+ if (apiDeps.length > 0) {
223
+ prompt += `- API Dependencies (${apiDeps.length}): ${apiDeps.slice(0, 10).map(d => `\`${d}\``).join(', ')}\n`;
224
+ }
225
+ if (serviceDeps.length > 0) {
226
+ prompt += `- Service Dependencies (${serviceDeps.length}): ${serviceDeps.slice(0, 10).map(d => `\`${d}\``).join(', ')}\n`;
227
+ }
228
+ if (otherDeps.length > 0 && otherDeps.length <= 20) {
229
+ prompt += `- Weitere Dependencies (${otherDeps.length}): ${otherDeps.slice(0, 10).map(d => `\`${d}\``).join(', ')}\n`;
230
+ }
231
+ prompt += `\n`;
232
+ }
233
+ // Incoming dependencies
234
+ if (context.incomingDependencies.length > 0) {
235
+ const uniqueUsers = new Set(context.incomingDependencies.map((d) => d.from_module || d.from));
236
+ prompt += `**Wird genutzt von (${uniqueUsers.size} Modulen):**\n`;
237
+ for (const user of Array.from(uniqueUsers).slice(0, 10)) {
238
+ prompt += `- \`${user}\`\n`;
239
+ }
240
+ prompt += `\n`;
241
+ }
242
+ // Symbols
243
+ if (context.symbols.length > 0) {
244
+ const symbolKinds = new Map();
245
+ for (const symbol of context.symbols) {
246
+ const kind = symbol.kind || 'unknown';
247
+ symbolKinds.set(kind, (symbolKinds.get(kind) || 0) + 1);
248
+ }
249
+ prompt += `**Symbole (${context.symbols.length}):**\n`;
250
+ for (const [kind, count] of symbolKinds.entries()) {
251
+ prompt += `- ${count} ${kind}\n`;
252
+ }
253
+ prompt += `\n`;
254
+ }
255
+ // Patterns
256
+ if (patterns.length > 0) {
257
+ prompt += `## ERKANNTE PATTERNS\n\n`;
258
+ for (const pattern of patterns.slice(0, 5)) {
259
+ prompt += `- **${pattern.pattern}** (${pattern.confidence} confidence)\n`;
260
+ if (pattern.evidence.length > 0) {
261
+ prompt += ` Evidence: ${pattern.evidence.slice(0, 3).join(', ')}\n`;
262
+ }
263
+ }
264
+ prompt += `\n`;
265
+ }
266
+ // Similar ADRs
267
+ if (similarAdrs.length > 0) {
268
+ prompt += `## ÄHNLICHE ADRs (als Vorlage)\n\n`;
269
+ for (const adr of similarAdrs.slice(0, 3)) {
270
+ prompt += `### ADR-${adr.adr_number}: ${adr.title}\n\n`;
271
+ // Extract key sections
272
+ const contextMatch = adr.content_markdown.match(/##\s+Kontext\s*\n([\s\S]*?)(?=##|$)/i);
273
+ const decisionMatch = adr.content_markdown.match(/##\s+Entscheidung\s*\n([\s\S]*?)(?=##|$)/i);
274
+ if (contextMatch) {
275
+ const contextPreview = contextMatch[1].substring(0, 500).trim();
276
+ prompt += `**Kontext:** ${contextPreview}...\n\n`;
277
+ }
278
+ if (decisionMatch) {
279
+ const decisionPreview = decisionMatch[1].substring(0, 500).trim();
280
+ prompt += `**Entscheidung:** ${decisionPreview}...\n\n`;
281
+ }
282
+ }
283
+ prompt += `\n`;
284
+ }
285
+ // Step-by-step analysis
286
+ prompt += `## ANALYSE-SCHRITTE\n\n`;
287
+ prompt += `Gehe Schritt für Schritt vor:\n\n`;
288
+ prompt += `**SCHRITT 1: Analysiere Dateiname und Pfad**\n`;
289
+ prompt += `- Dateiname: \`${moduleName}\`\n`;
290
+ prompt += `- Pfad: \`${moduleDir}\`\n`;
291
+ prompt += `- Was sagt der Name über die Rolle?\n`;
292
+ prompt += ` - "extension.ts" → VS Code Entry Point (activate/deactivate erforderlich)\n`;
293
+ prompt += ` - "repository.ts" → Data Access Layer (CRUD-Operationen)\n`;
294
+ prompt += ` - "service.ts" → Business Logic (Orchestration)\n`;
295
+ prompt += ` - "api.ts" → Public Interface (Exports)\n\n`;
296
+ prompt += `**SCHRITT 2: Analysiere Funktionen**\n`;
297
+ const hasActivate = moduleDoc.keyFunctions.some(f => f.name.includes('activate'));
298
+ const hasCreate = moduleDoc.keyFunctions.some(f => f.name.includes('create') || f.name.includes('Create'));
299
+ const hasGet = moduleDoc.keyFunctions.some(f => f.name.includes('get') || f.name.includes('Get') || f.name.includes('find') || f.name.includes('Find'));
300
+ if (hasActivate) {
301
+ prompt += `- Gibt es activate/deactivate? → VS Code Entry Point Pattern\n`;
302
+ }
303
+ if (hasCreate && hasGet) {
304
+ prompt += `- Gibt es create/read/update/delete? → Repository Pattern\n`;
305
+ }
306
+ prompt += `- Was ist die Kern-Funktionalität? (Orchestration, Data Access, UI, etc.)\n\n`;
307
+ prompt += `**SCHRITT 3: Analysiere Dependencies**\n`;
308
+ prompt += `- ${context.dependencies.length} Dependencies (ausgehend)\n`;
309
+ prompt += `- Kategorien: ${coreDeps.length} Core, ${apiDeps.length} API, ${serviceDeps.length} Service\n`;
310
+ // Calculate gap score (dependencies * 2 - adrs * 10, min 0)
311
+ const gapScore = Math.max(0, context.dependencies.length * 2 - (similarAdrs.length * 10));
312
+ if (context.dependencies.length > 20) {
313
+ prompt += `- ⚠️ ${context.dependencies.length} Dependencies = GOD OBJECT ANTI-PATTERN!\n`;
314
+ prompt += ` - Gap-Score: ${gapScore} (höchster Wert im System)\n`;
315
+ prompt += ` - Erwähne dies explizit in "Negative Konsequenzen"\n`;
316
+ prompt += ` - Refactoring-Schwelle: Bei >30 Dependencies Plugin-Architektur erwägen\n`;
317
+ }
318
+ else if (context.dependencies.length > 15) {
319
+ prompt += `- ${context.dependencies.length} Dependencies → Feature-Orchestration bei Extension-Start\n`;
320
+ prompt += `- Gap-Score: ${gapScore}\n`;
321
+ }
322
+ else if (context.dependencies.length > 5) {
323
+ prompt += `- Moderate Anzahl → Fokussierte Funktionalität mit klaren Abhängigkeiten\n`;
324
+ }
325
+ else {
326
+ prompt += `- Wenige Dependencies → Isolierte, fokussierte Funktionalität\n`;
327
+ }
328
+ // Incoming dependencies
329
+ if (uniqueIncomingUsers.size > 0) {
330
+ prompt += `- Wird genutzt von: ${uniqueIncomingUsers.size} anderen Modulen (eingehend)\n`;
331
+ if (uniqueIncomingUsers.size > 10) {
332
+ prompt += ` - ⚠️ ${uniqueIncomingUsers.size} Module = SINGLE POINT OF FAILURE!\n`;
333
+ prompt += ` - Erwähne "zentrale Rolle" oder "hoher Impact bei Änderungen"\n`;
334
+ }
335
+ else if (uniqueIncomingUsers.size > 5) {
336
+ prompt += ` - Zeigt zentrale Rolle im System\n`;
337
+ }
338
+ }
339
+ prompt += `\n`;
340
+ // Anti-Pattern recognition (skip for simple modules)
341
+ if (complexity !== 'simple') {
342
+ prompt += `**SCHRITT 4: Erkenne Anti-Patterns**\n`;
343
+ if (context.dependencies.length > 20) {
344
+ prompt += `- ⚠️ ${context.dependencies.length} Dependencies = God Object Anti-Pattern\n`;
345
+ prompt += ` → Erwähne: "Bewusst akzeptiert wegen [Constraint], Refactoring-Schwelle: >30 Dependencies"\n`;
346
+ }
347
+ if (uniqueIncomingUsers.size > 10) {
348
+ prompt += `- ⚠️ ${uniqueIncomingUsers.size} Module nutzen dieses = Single Point of Failure\n`;
349
+ prompt += ` → Erwähne: "Zentrale Rolle, hoher Impact bei Änderungen"\n`;
350
+ }
351
+ if (moduleDoc.classes.length > 3) {
352
+ prompt += `- ⚠️ ${moduleDoc.classes.length} Klassen in einem File = Multiple Responsibilities\n`;
353
+ prompt += ` → Erwähne: "Extrahiere Klassen in separate Files empfohlen"\n`;
354
+ }
355
+ prompt += `\n`;
356
+ }
357
+ prompt += `**SCHRITT 5: Formuliere Probleme basierend auf Analyse**\n`;
358
+ prompt += `- NICHT: "Die Notwendigkeit, X zu tun" oder "X um Y zu ermöglichen"\n`;
359
+ prompt += `- SONDERN: "Framework erfordert X", "System benötigt Y wegen Z"\n`;
360
+ prompt += `- KEINE generischen Endungen:\n`;
361
+ prompt += ` ❌ "um die Funktionalität zu gewährleisten"\n`;
362
+ prompt += ` ❌ "um eine vollständige Integration zu ermöglichen"\n`;
363
+ prompt += ` ❌ "um die Funktionalität bereitzustellen"\n`;
364
+ prompt += ` ❌ "um die Verwaltung zu ermöglichen"\n`;
365
+ prompt += ` ❌ "um die Bereitstellung zu gewährleisten"\n`;
366
+ prompt += ` ❌ "um die Integration zu ermöglichen"\n`;
367
+ prompt += `- PROBLEME SIND KURZ UND PRÄZISE: Maximal 1 Satz, KEINE Erklärungen, KEINE "um...zu"-Konstruktionen\n`;
368
+ prompt += `- PROBLEME ENDEN MIT PUNKT, NICHT MIT "um...zu"-Phrasen\n`;
369
+ // Check for multiple main decisions
370
+ const hasActivateAndProvider = hasActivate && moduleDoc.classes.some(c => c.name.includes('Provider'));
371
+ if (hasActivateAndProvider) {
372
+ prompt += `- ⚠️ WICHTIG: Dieses Modul hat MEHRERE Hauptentscheidungen:\n`;
373
+ prompt += ` - Hauptentscheidung 1: VS Code Entry Point (activate/deactivate)\n`;
374
+ prompt += ` - Hauptentscheidung 2: DocumentationProvider (Tree View)\n`;
375
+ prompt += ` → Erwähne beide getrennt in "Entscheidung"\n`;
376
+ prompt += ` → Problem: Beide in einem File = God Object\n`;
377
+ }
378
+ prompt += `\n`;
379
+ // Few-shot learning examples
380
+ prompt += `## BEISPIELE FÜR GUTE VS. SCHLECHTE ANALYSE\n\n`;
381
+ prompt += `### Beispiel 1: extension.ts (Entry Point)\n\n`;
382
+ prompt += `✅ GUTE Probleme (KURZ, PRÄZISE, KEINE generischen Endungen):\n`;
383
+ prompt += `- "VS Code Extension benötigt Entry Point (extension.ts mit activate/deactivate)"\n`;
384
+ prompt += `- "Alle Commands müssen bei Extension-Start registriert werden"\n`;
385
+ prompt += `- "Extension braucht Sidebar Tree View für Dokumentations-Navigation"\n`;
386
+ prompt += `- "${context.dependencies.length} Features müssen bei Extension-Start orchestriert werden"\n`;
387
+ prompt += `- "VS Code API erfordert activate() in extension.ts"\n\n`;
388
+ prompt += `❌ SCHLECHTE Probleme (mit generischen Endungen - VERBOTEN!):\n`;
389
+ prompt += `- "Alle Commands müssen bei Extension-Start registriert werden, um die Funktionalität zu gewährleisten"\n`;
390
+ prompt += `- "Alle Commands müssen bei Extension-Start registriert werden, um die Funktionalität bereitzustellen"\n`;
391
+ prompt += `- "${context.dependencies.length} Features müssen orchestriert werden, um eine vollständige Integration zu ermöglichen"\n`;
392
+ prompt += `- "Extension benötigt Sidebar, um die Navigation zu ermöglichen"\n\n`;
393
+ prompt += `⚠️ REGEL: Wenn ein Problem mit "um...zu" endet, ist es VERBOTEN!\n`;
394
+ prompt += `→ Entferne die "um...zu"-Phrase komplett oder formuliere um\n\n`;
395
+ prompt += `❌ SCHLECHTE (zu generische) Probleme:\n`;
396
+ prompt += `- "Die Notwendigkeit, Dokumentationsdateien zu verwalten"\n`;
397
+ prompt += `- "Die Herausforderung, eine benutzerfreundliche Schnittstelle zu schaffen"\n`;
398
+ prompt += `- "Die Anforderung, Umgebungsvariablen zu laden"\n\n`;
399
+ prompt += `✅ GUTE Entscheidung:\n`;
400
+ prompt += `"VS Code Entry Point Pattern mit zentraler Feature-Registrierung wurde gewählt weil VS Code API activate() in extension.ts erfordert. ${context.dependencies.length} Dependencies zeigen vollständige Feature-Orchestration bei Extension-Start."\n\n`;
401
+ prompt += `### Beispiel 2: repository.ts (Data Access)\n\n`;
402
+ prompt += `✅ GUTE Probleme:\n`;
403
+ prompt += `- "Konsistente CRUD-Operationen über 5 Dimensionen erforderlich"\n`;
404
+ prompt += `- "Dimension-spezifische Queries (Module nach file_path, Symbols nach symbol_id)"\n`;
405
+ prompt += `- "Type-Safety ohne any für alle Dimensionen"\n\n`;
406
+ prompt += `❌ SCHLECHTE Probleme:\n`;
407
+ prompt += `- "Die Notwendigkeit, Daten zu speichern"\n`;
408
+ prompt += `- "Die Herausforderung, Datenbank-Zugriff zu implementieren"\n\n`;
409
+ // Requirements section
410
+ prompt += `## ANFORDERUNGEN AN DIE ANTWORT\n\n`;
411
+ prompt += `1. **Probleme müssen konkret sein:**\n`;
412
+ prompt += ` ✅ "VS Code API erfordert activate() in extension.ts"\n`;
413
+ prompt += ` ❌ "Die Notwendigkeit, Features zu verwalten"\n\n`;
414
+ prompt += `2. **Anti-Patterns explizit benennen:**\n`;
415
+ if (context.dependencies.length > 20) {
416
+ prompt += ` ⚠️ ${context.dependencies.length} Dependencies = God Object Anti-Pattern!\n`;
417
+ prompt += ` → Erwähne dies explizit in "Negative Konsequenzen"\n`;
418
+ prompt += ` → Format: "${context.dependencies.length} Dependencies = höchster Wert im System (Gap-Score: ${gapScore})"\n`;
419
+ }
420
+ if (uniqueIncomingUsers.size > 10) {
421
+ prompt += ` ⚠️ ${uniqueIncomingUsers.size} Module nutzen dieses = Single Point of Failure!\n`;
422
+ prompt += ` → Erwähne dies explizit in "Negative Konsequenzen"\n`;
423
+ }
424
+ if (moduleDoc.classes.length > 3) {
425
+ prompt += ` ⚠️ ${moduleDoc.classes.length} Klassen in einem File = Multiple Responsibilities\n`;
426
+ prompt += ` → Erwähne: "Extrahiere Klassen in separate Files empfohlen"\n`;
427
+ }
428
+ prompt += `\n`;
429
+ prompt += `3. **Messbare Fakten nutzen:**\n`;
430
+ prompt += ` ✅ "${context.dependencies.length} Dependencies = höchster Wert im System (Gap-Score: ${gapScore})"\n`;
431
+ prompt += ` ✅ "Schwer zu testen (${context.dependencies.length} Mocks nötig für Unit-Tests)"\n`;
432
+ prompt += ` ✅ "Änderungen haben system-weiten Impact (${uniqueIncomingUsers.size} Module betroffen)"\n`;
433
+ prompt += ` ❌ "Kann zu Komplexität führen" (zu vage)\n`;
434
+ prompt += ` ❌ "Schwierig zu warten" (zu vage)\n\n`;
435
+ prompt += `4. **Zentrale Rolle erwähnen:**\n`;
436
+ if (uniqueIncomingUsers.size > 0) {
437
+ prompt += ` → ${uniqueIncomingUsers.size} Module nutzen dieses Modul\n`;
438
+ prompt += ` → Erwähne "zentrale Rolle" oder "hoher Impact bei Änderungen" in Konsequenzen\n`;
439
+ }
440
+ prompt += `\n`;
441
+ prompt += `5. **Refactoring-Empfehlungen:**\n`;
442
+ if (context.dependencies.length > 20) {
443
+ prompt += ` → Bei ${context.dependencies.length} Dependencies: Empfehle Refactoring\n`;
444
+ if (hasActivateAndProvider) {
445
+ prompt += ` → Konkrete Schritte: "Extrahiere DocumentationProvider in separates File"\n`;
446
+ }
447
+ if (context.dependencies.length > 30) {
448
+ prompt += ` → "Plugin-Architektur dringend empfohlen (${context.dependencies.length} > 30)"\n`;
449
+ }
450
+ else {
451
+ prompt += ` → "FeatureRegistry Pattern für Command-Registrierung"\n`;
452
+ }
453
+ }
454
+ if (moduleDoc.classes.length > 3) {
455
+ prompt += ` → "Extrahiere ${moduleDoc.classes.length} Klassen in separate Files"\n`;
456
+ }
457
+ prompt += `\n`;
458
+ // Task (simplified for simple modules)
459
+ prompt += `## AUFGABE\n\n`;
460
+ prompt += `Rekonstruiere die Architektur-Entscheidungen für dieses Modul:\n\n`;
461
+ if (complexity === 'simple') {
462
+ prompt += `1. **Probleme:** Maximal 1-2 konkrete Architektur-Anforderungen (KURZ, PRÄZISE, KEINE generischen Endungen)\n`;
463
+ }
464
+ else if (complexity === 'medium') {
465
+ prompt += `1. **Probleme:** 2-3 konkrete Architektur-Anforderungen (KURZ, PRÄZISE, KEINE generischen Endungen)\n`;
466
+ }
467
+ else {
468
+ prompt += `1. **Probleme:** Welche konkreten Architektur-Anforderungen führten zu diesem Modul?\n`;
469
+ }
470
+ prompt += `
471
+ Analysiere: Dateiname (\`${moduleName}\`), Funktionen (${moduleDoc.keyFunctions.length}), Dependencies (${context.dependencies.length})\n`;
472
+ prompt += `
473
+ Formuliere wie in den Beispielen: Spezifisch, nicht generisch!\n`;
474
+ prompt += `
475
+ ⚠️ KRITISCH: KEINE "um...zu"-Konstruktionen am Ende!\n`;
476
+ prompt += ` ❌ FALSCH: "X muss Y tun, um die Funktionalität zu gewährleisten"\n`;
477
+ prompt += ` ✅ RICHTIG: "X muss Y tun" (Ende mit Punkt, keine Erklärung)\n\n`;
478
+ prompt += `2. **Entscheidung:** Wie wurde es implementiert und WARUM?\n`;
479
+ if (complexity === 'simple') {
480
+ prompt += ` - KURZE Begründung (1-2 Sätze): Nutze Dateiname und Hauptfunktion\n`;
481
+ prompt += ` - Beispiel: "Git-Funktionen wurden implementiert weil System geänderte Dateien überwachen muss"\n`;
482
+ }
483
+ else if (hasActivateAndProvider) {
484
+ prompt += ` - WICHTIG: Dieses Modul hat MEHRERE Hauptentscheidungen - erwähne beide getrennt:\n`;
485
+ prompt += ` - Hauptentscheidung 1: VS Code Entry Point (activate/deactivate)\n`;
486
+ prompt += ` - Hauptentscheidung 2: DocumentationProvider (Tree View)\n`;
487
+ prompt += ` - Problem: Beide in einem File = God Object\n`;
488
+ }
489
+ else {
490
+ prompt += ` - Nutze Dateiname, Funktionen, Dependencies für konkrete Begründung\n`;
491
+ prompt += ` - Nicht: "Das Modul implementiert eine Klasse..."\n`;
492
+ prompt += ` - Sondern: "VS Code Entry Point Pattern wurde gewählt weil VS Code API activate() erfordert"\n`;
493
+ }
494
+ prompt += `\n`;
495
+ prompt += `3. **Rationale:** Warum wurde diese spezifische Struktur gewählt?\n`;
496
+ if (complexity === 'simple') {
497
+ prompt += ` - KURZE Begründung (1 Satz): Konkreter technischer Grund\n`;
498
+ }
499
+ else {
500
+ prompt += ` - Begründung aus Code-Struktur, Dependencies, Patterns\n`;
501
+ prompt += ` - Konkrete technische Gründe, nicht generische Aussagen\n`;
502
+ }
503
+ prompt += `\n`;
504
+ if (complexity === 'simple') {
505
+ prompt += `4. **Alternativen:** Optional - nur wenn es eine offensichtliche Alternative gibt (max. 1)\n`;
506
+ }
507
+ else if (complexity === 'medium') {
508
+ prompt += `4. **Alternativen:** 1-2 Alternativen, die erwogen wurden\n`;
509
+ prompt += ` - Format: "Alternative X: Beschreibung → Abgelehnt weil: konkreter Grund"\n`;
510
+ }
511
+ else {
512
+ prompt += `4. **Alternativen:** Welche Alternativen wurden erwogen?\n`;
513
+ prompt += ` - Basierend auf Patterns (z.B. Repository vs. Direct DB Access)\n`;
514
+ prompt += ` - Für extension.ts: Lazy Loading vs. Eager Loading, Plugin-Architektur vs. Monolith\n`;
515
+ prompt += ` - Format: "Alternative X: Beschreibung → Abgelehnt weil: konkreter Grund"\n`;
516
+ prompt += ` - Beispiel: "Lazy Loading: Features bei Bedarf laden → Abgelehnt: Verschlechtert UX, Features nicht sofort verfügbar"\n`;
517
+ }
518
+ prompt += `\n`;
519
+ if (complexity === 'simple') {
520
+ prompt += `5. **Trade-offs:** Maximal 1-2 positive, 0-1 negative Konsequenzen (KURZ)\n`;
521
+ }
522
+ else if (complexity === 'medium') {
523
+ prompt += `5. **Trade-offs:** 2-3 positive, 1-2 negative Konsequenzen\n`;
524
+ }
525
+ else {
526
+ prompt += `5. **Trade-offs:** Was sind die Vor- und Nachteile?\n`;
527
+ prompt += ` - Nutze MESSBARE FAKTEN:\n`;
528
+ prompt += ` ✅ "${context.dependencies.length} Dependencies = höchster Wert im System (Gap-Score: ${gapScore})"\n`;
529
+ prompt += ` ✅ "Schwer zu testen (${context.dependencies.length} Mocks nötig)"\n`;
530
+ if (uniqueIncomingUsers.size > 0) {
531
+ prompt += ` ✅ "Single Point of Failure (${uniqueIncomingUsers.size} Module betroffen bei Fehler)"\n`;
532
+ }
533
+ prompt += ` ✅ "Extension startet nicht bei Fehler in diesem Modul"\n`;
534
+ }
535
+ prompt += ` - NICHT: "Kann zu Komplexität führen" (zu vage)\n`;
536
+ // Refactoring recommendations (skip for simple modules)
537
+ if (complexity !== 'simple') {
538
+ if (complexity === 'medium') {
539
+ prompt += `\n6. **Refactoring-Empfehlungen:** Optional - max. 1-2 konkrete Empfehlungen\n`;
540
+ }
541
+ else {
542
+ prompt += `\n6. **Refactoring-Empfehlungen:** Konkrete Empfehlungen basierend auf Anti-Patterns\n`;
543
+ if (context.dependencies.length > 20) {
544
+ prompt += ` - Bei ${context.dependencies.length} Dependencies: Empfehle Refactoring\n`;
545
+ if (hasActivateAndProvider) {
546
+ prompt += ` - Konkrete Schritte: "Extrahiere DocumentationProvider in separates File"\n`;
547
+ }
548
+ if (context.dependencies.length > 30) {
549
+ prompt += ` - "Plugin-Architektur dringend empfohlen (${context.dependencies.length} > 30)"\n`;
550
+ }
551
+ else {
552
+ prompt += ` - "FeatureRegistry Pattern für Command-Registrierung"\n`;
553
+ }
554
+ }
555
+ if (moduleDoc.classes.length > 3) {
556
+ prompt += ` - "Extrahiere ${moduleDoc.classes.length} Klassen in separate Files"\n`;
557
+ }
558
+ }
559
+ }
560
+ prompt += `\n`;
561
+ // Response format (simplified for simple modules)
562
+ prompt += `## ANTWORT-FORMAT (JSON)\n\n`;
563
+ prompt += `Antworte IMMER im folgenden JSON-Format:\n\n`;
564
+ prompt += `{\n`;
565
+ if (complexity === 'simple') {
566
+ prompt += ` "problems": ["Problem 1", "Problem 2"], // Maximal 2 Probleme\n`;
567
+ prompt += ` "decision": "Kurze Entscheidung (1-2 Sätze)",\n`;
568
+ prompt += ` "rationale": "Kurze Begründung (1 Satz)",\n`;
569
+ prompt += ` "alternatives": [], // Optional - max. 1 Alternative\n`;
570
+ prompt += ` "tradeoffs": {\n`;
571
+ prompt += ` "positive": ["Vorteil 1", "Vorteil 2"], // Maximal 2\n`;
572
+ prompt += ` "negative": [] // Optional - max. 1\n`;
573
+ prompt += ` }\n`;
574
+ prompt += ` // KEINE refactoring_recommendations für einfache Module!\n`;
575
+ }
576
+ else if (complexity === 'medium') {
577
+ prompt += ` "problems": ["Problem 1", "Problem 2", "Problem 3"], // 2-3 Probleme\n`;
578
+ prompt += ` "decision": "Entscheidung mit Begründung (2-3 Sätze)",\n`;
579
+ prompt += ` "rationale": "Begründung basierend auf Code-Struktur und Dependencies",\n`;
580
+ prompt += ` "alternatives": ["Alternative 1", "Alternative 2"], // 1-2 Alternativen\n`;
581
+ prompt += ` "tradeoffs": {\n`;
582
+ prompt += ` "positive": ["Vorteil 1", "Vorteil 2", "Vorteil 3"], // 2-3\n`;
583
+ prompt += ` "negative": ["Nachteil 1", "Nachteil 2"] // 1-2\n`;
584
+ prompt += ` },\n`;
585
+ prompt += ` "refactoring_recommendations": [] // Optional - max. 1-2\n`;
586
+ }
587
+ else {
588
+ prompt += ` "problems": ["Problem 1", "Problem 2", ...],\n`;
589
+ prompt += ` "decision": "Entscheidung mit detaillierter Begründung",\n`;
590
+ prompt += ` "rationale": "Warum wurde diese Entscheidung getroffen? Detaillierte Erklärung basierend auf Code-Struktur, Dependencies und Patterns.",\n`;
591
+ prompt += ` "alternatives": ["Alternative 1", "Alternative 2", ...],\n`;
592
+ prompt += ` "tradeoffs": {\n`;
593
+ prompt += ` "positive": ["Vorteil 1", "Vorteil 2", ...],\n`;
594
+ prompt += ` "negative": ["Nachteil 1", "Nachteil 2", ...]\n`;
595
+ prompt += ` },\n`;
596
+ prompt += ` "refactoring_recommendations": ["Empfehlung 1", "Empfehlung 2", ...]\n`;
597
+ }
598
+ prompt += `}\n\n`;
599
+ // Refactoring recommendations (only for complex modules)
600
+ if (complexity === 'complex') {
601
+ prompt += `**WICHTIG - Refactoring-Empfehlungen:**\n`;
602
+ if (context.dependencies.length > 20) {
603
+ prompt += `- Bei ${context.dependencies.length} Dependencies: Konkrete Refactoring-Schritte angeben\n`;
604
+ }
605
+ if (hasActivateAndProvider) {
606
+ prompt += `- Extrahiere DocumentationProvider in separates File\n`;
607
+ }
608
+ if (context.dependencies.length > 30) {
609
+ prompt += `- Plugin-Architektur dringend empfohlen\n`;
610
+ }
611
+ prompt += `\n`;
612
+ }
613
+ prompt += `**WICHTIG:**\n`;
614
+ prompt += `- Alle Antworten müssen auf den bereitgestellten Daten basieren\n`;
615
+ prompt += `- Nutze ähnliche ADRs als Vorlage für Struktur und Stil\n`;
616
+ prompt += `- Erkläre das "Warum" detailliert, nicht nur das "Was"\n`;
617
+ prompt += `- Sei spezifisch und konkret, nicht generisch\n`;
618
+ prompt += `- VERMEIDE: "Die Notwendigkeit...", "Die Herausforderung...", "Die Anforderung..."\n`;
619
+ prompt += `- STATTDESSEN: "Framework erfordert...", "System benötigt... wegen...", "API erfordert..."\n`;
620
+ return prompt;
621
+ }
622
+ /**
623
+ * Parses module documentation markdown to extract structured information.
624
+ */
625
+ parseModuleDocumentation(content) {
626
+ const lines = content.split('\n');
627
+ const result = {
628
+ classes: [],
629
+ keyFunctions: []
630
+ };
631
+ let currentClass = null;
632
+ let methodCount = 0;
633
+ for (let i = 0; i < lines.length; i++) {
634
+ const line = lines[i];
635
+ // Extract class information
636
+ const classMatch = line.match(/^###\s+(?:class|interface):\s*(.+)$/);
637
+ if (classMatch) {
638
+ if (currentClass) {
639
+ currentClass.methodCount = methodCount;
640
+ result.classes.push(currentClass);
641
+ }
642
+ const className = classMatch[1].trim();
643
+ const roleMatch = line.match(/Rolle:\s*([^,]+)/);
644
+ const role = roleMatch ? roleMatch[1].trim() : null;
645
+ currentClass = { name: className, role, methodCount: 0 };
646
+ methodCount = 0;
647
+ }
648
+ // Extract method information
649
+ const methodMatch = line.match(/^###\s+(?:method|function):\s*(.+)$/);
650
+ if (methodMatch) {
651
+ methodCount++;
652
+ const methodName = methodMatch[1].trim();
653
+ const roleMatch = line.match(/Rolle:\s*([^,]+)/);
654
+ const role = roleMatch ? roleMatch[1].trim() : null;
655
+ // Try to find signature in next lines
656
+ let signature = null;
657
+ for (let j = i + 1; j < Math.min(i + 10, lines.length); j++) {
658
+ if (lines[j].includes('Signatur:') || lines[j].includes('```')) {
659
+ const sigMatch = lines[j].match(/Signatur:\s*`(.+)`/) ||
660
+ lines[j + 1]?.match(/```ts\n(.+)\n```/);
661
+ if (sigMatch) {
662
+ signature = sigMatch[1].trim();
663
+ break;
664
+ }
665
+ }
666
+ }
667
+ result.keyFunctions.push({ name: methodName, role, signature });
668
+ }
669
+ }
670
+ if (currentClass) {
671
+ currentClass.methodCount = methodCount;
672
+ result.classes.push(currentClass);
673
+ }
674
+ return result;
675
+ }
676
+ /**
677
+ * Validates reasoning structure and checks for generic phrases.
678
+ */
679
+ validateReasoning(reasoning) {
680
+ if (!reasoning.problems || !Array.isArray(reasoning.problems)) {
681
+ throw new Error('Invalid reasoning: problems must be an array');
682
+ }
683
+ if (!reasoning.decision || typeof reasoning.decision !== 'string') {
684
+ throw new Error('Invalid reasoning: decision must be a string');
685
+ }
686
+ if (!reasoning.rationale || typeof reasoning.rationale !== 'string') {
687
+ throw new Error('Invalid reasoning: rationale must be a string');
688
+ }
689
+ if (!reasoning.alternatives || !Array.isArray(reasoning.alternatives)) {
690
+ throw new Error('Invalid reasoning: alternatives must be an array');
691
+ }
692
+ if (!reasoning.tradeoffs || typeof reasoning.tradeoffs !== 'object') {
693
+ throw new Error('Invalid reasoning: tradeoffs must be an object');
694
+ }
695
+ if (!reasoning.tradeoffs.positive || !Array.isArray(reasoning.tradeoffs.positive)) {
696
+ throw new Error('Invalid reasoning: tradeoffs.positive must be an array');
697
+ }
698
+ if (!reasoning.tradeoffs.negative || !Array.isArray(reasoning.tradeoffs.negative)) {
699
+ throw new Error('Invalid reasoning: tradeoffs.negative must be an array');
700
+ }
701
+ // Refactoring recommendations are optional
702
+ if (reasoning.refactoring_recommendations && !Array.isArray(reasoning.refactoring_recommendations)) {
703
+ throw new Error('Invalid reasoning: refactoring_recommendations must be an array if provided');
704
+ }
705
+ // Check for generic phrases
706
+ const genericPhrases = [
707
+ 'die notwendigkeit',
708
+ 'die herausforderung',
709
+ 'die anforderung',
710
+ 'ermöglicht eine',
711
+ 'bietet eine',
712
+ 'schafft eine',
713
+ 'stellt eine',
714
+ 'um die funktionalität',
715
+ 'um eine vollständige',
716
+ 'um die integration',
717
+ 'um die verwaltung',
718
+ 'um die bereitstellung',
719
+ 'um die navigation',
720
+ 'um die verfügbarkeit',
721
+ 'um die gewährleistung',
722
+ 'um die bereitstellung',
723
+ 'um die verwaltung',
724
+ 'um die integration',
725
+ 'um die funktionalität bereitzustellen',
726
+ 'um die funktionalität zu gewährleisten',
727
+ 'um die funktionalität zu ermöglichen'
728
+ ];
729
+ let hasGenericPhrases = false;
730
+ // Check problems - stricter validation
731
+ for (const problem of reasoning.problems) {
732
+ const lower = problem.toLowerCase().trim();
733
+ // Check for "um...zu" constructions (very common generic ending)
734
+ if (lower.match(/um\s+(die|eine|der|das)\s+\w+\s+zu\s+\w+/)) {
735
+ console.warn(`[AdrReasoningService] Warning: Generic "um...zu" construction detected in problem: "${problem.substring(0, 100)}..."`);
736
+ hasGenericPhrases = true;
737
+ }
738
+ // Check for other generic phrases
739
+ for (const phrase of genericPhrases) {
740
+ if (lower.includes(phrase)) {
741
+ console.warn(`[AdrReasoningService] Warning: Generic phrase "${phrase}" detected in problem: "${problem.substring(0, 100)}..."`);
742
+ hasGenericPhrases = true;
743
+ }
744
+ }
745
+ }
746
+ // Check decision
747
+ const decisionLower = reasoning.decision.toLowerCase();
748
+ for (const phrase of genericPhrases) {
749
+ if (decisionLower.includes(phrase)) {
750
+ console.warn(`[AdrReasoningService] Warning: Generic phrase "${phrase}" detected in decision`);
751
+ hasGenericPhrases = true;
752
+ }
753
+ }
754
+ if (hasGenericPhrases) {
755
+ console.warn(`[AdrReasoningService] Warning: Generic phrases detected. Consider regenerating with more specific instructions.`);
756
+ }
757
+ }
758
+ }
759
+ exports.AdrReasoningService = AdrReasoningService;
760
+ //# sourceMappingURL=adr-reasoning-service.js.map