sdd-mcp-server 1.0.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 (165) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +256 -0
  3. package/dist/__tests__/setup.d.ts +44 -0
  4. package/dist/__tests__/setup.js +178 -0
  5. package/dist/__tests__/setup.js.map +1 -0
  6. package/dist/__tests__/test-helpers/mock-factories.d.ts +26 -0
  7. package/dist/__tests__/test-helpers/mock-factories.js +466 -0
  8. package/dist/__tests__/test-helpers/mock-factories.js.map +1 -0
  9. package/dist/adapters/cli/SDDToolAdapter.d.ts +26 -0
  10. package/dist/adapters/cli/SDDToolAdapter.js +273 -0
  11. package/dist/adapters/cli/SDDToolAdapter.js.map +1 -0
  12. package/dist/application/services/CodebaseAnalysisService.d.ts +38 -0
  13. package/dist/application/services/CodebaseAnalysisService.js +737 -0
  14. package/dist/application/services/CodebaseAnalysisService.js.map +1 -0
  15. package/dist/application/services/LocalizationService.d.ts +184 -0
  16. package/dist/application/services/LocalizationService.js +536 -0
  17. package/dist/application/services/LocalizationService.js.map +1 -0
  18. package/dist/application/services/ProjectContextService.d.ts +61 -0
  19. package/dist/application/services/ProjectContextService.js +550 -0
  20. package/dist/application/services/ProjectContextService.js.map +1 -0
  21. package/dist/application/services/ProjectInitializationService.d.ts +57 -0
  22. package/dist/application/services/ProjectInitializationService.js +485 -0
  23. package/dist/application/services/ProjectInitializationService.js.map +1 -0
  24. package/dist/application/services/ProjectService.d.ts +19 -0
  25. package/dist/application/services/ProjectService.js +159 -0
  26. package/dist/application/services/ProjectService.js.map +1 -0
  27. package/dist/application/services/QualityGateService.d.ts +62 -0
  28. package/dist/application/services/QualityGateService.js +428 -0
  29. package/dist/application/services/QualityGateService.js.map +1 -0
  30. package/dist/application/services/QualityService.d.ts +43 -0
  31. package/dist/application/services/QualityService.js +245 -0
  32. package/dist/application/services/QualityService.js.map +1 -0
  33. package/dist/application/services/SteeringDocumentService.d.ts +62 -0
  34. package/dist/application/services/SteeringDocumentService.js +694 -0
  35. package/dist/application/services/SteeringDocumentService.js.map +1 -0
  36. package/dist/application/services/TemplateService.d.ts +47 -0
  37. package/dist/application/services/TemplateService.js +438 -0
  38. package/dist/application/services/TemplateService.js.map +1 -0
  39. package/dist/application/services/WorkflowEngineService.d.ts +56 -0
  40. package/dist/application/services/WorkflowEngineService.js +348 -0
  41. package/dist/application/services/WorkflowEngineService.js.map +1 -0
  42. package/dist/application/services/WorkflowService.d.ts +22 -0
  43. package/dist/application/services/WorkflowService.js +147 -0
  44. package/dist/application/services/WorkflowService.js.map +1 -0
  45. package/dist/application/services/WorkflowValidationService.d.ts +51 -0
  46. package/dist/application/services/WorkflowValidationService.js +665 -0
  47. package/dist/application/services/WorkflowValidationService.js.map +1 -0
  48. package/dist/domain/context/ProjectContext.d.ts +350 -0
  49. package/dist/domain/context/ProjectContext.js +138 -0
  50. package/dist/domain/context/ProjectContext.js.map +1 -0
  51. package/dist/domain/i18n/index.d.ts +286 -0
  52. package/dist/domain/i18n/index.js +97 -0
  53. package/dist/domain/i18n/index.js.map +1 -0
  54. package/dist/domain/plugins/index.d.ts +498 -0
  55. package/dist/domain/plugins/index.js +157 -0
  56. package/dist/domain/plugins/index.js.map +1 -0
  57. package/dist/domain/ports.d.ts +54 -0
  58. package/dist/domain/ports.js +3 -0
  59. package/dist/domain/ports.js.map +1 -0
  60. package/dist/domain/quality/index.d.ts +361 -0
  61. package/dist/domain/quality/index.js +113 -0
  62. package/dist/domain/quality/index.js.map +1 -0
  63. package/dist/domain/services/DomainService.d.ts +18 -0
  64. package/dist/domain/services/DomainService.js +71 -0
  65. package/dist/domain/services/DomainService.js.map +1 -0
  66. package/dist/domain/templates/index.d.ts +158 -0
  67. package/dist/domain/templates/index.js +22 -0
  68. package/dist/domain/templates/index.js.map +1 -0
  69. package/dist/domain/types.d.ts +115 -0
  70. package/dist/domain/types.js +37 -0
  71. package/dist/domain/types.js.map +1 -0
  72. package/dist/domain/workflow/WorkflowStateMachine.d.ts +62 -0
  73. package/dist/domain/workflow/WorkflowStateMachine.js +286 -0
  74. package/dist/domain/workflow/WorkflowStateMachine.js.map +1 -0
  75. package/dist/index.d.ts +19 -0
  76. package/dist/index.js +97 -0
  77. package/dist/index.js.map +1 -0
  78. package/dist/infrastructure/adapters/AjvValidationAdapter.d.ts +7 -0
  79. package/dist/infrastructure/adapters/AjvValidationAdapter.js +37 -0
  80. package/dist/infrastructure/adapters/AjvValidationAdapter.js.map +1 -0
  81. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.d.ts +8 -0
  82. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.js +41 -0
  83. package/dist/infrastructure/adapters/ConsoleLoggerAdapter.js.map +1 -0
  84. package/dist/infrastructure/adapters/FileBasedTaskTracker.d.ts +9 -0
  85. package/dist/infrastructure/adapters/FileBasedTaskTracker.js +41 -0
  86. package/dist/infrastructure/adapters/FileBasedTaskTracker.js.map +1 -0
  87. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.d.ts +8 -0
  88. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.js +38 -0
  89. package/dist/infrastructure/adapters/HandlebarsTemplateEngine.js.map +1 -0
  90. package/dist/infrastructure/adapters/JsonConfigurationAdapter.d.ts +7 -0
  91. package/dist/infrastructure/adapters/JsonConfigurationAdapter.js +24 -0
  92. package/dist/infrastructure/adapters/JsonConfigurationAdapter.js.map +1 -0
  93. package/dist/infrastructure/adapters/LinusQualityAnalyzer.d.ts +9 -0
  94. package/dist/infrastructure/adapters/LinusQualityAnalyzer.js +75 -0
  95. package/dist/infrastructure/adapters/LinusQualityAnalyzer.js.map +1 -0
  96. package/dist/infrastructure/adapters/NodeFileSystemAdapter.d.ts +12 -0
  97. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js +39 -0
  98. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js.map +1 -0
  99. package/dist/infrastructure/di/container.d.ts +3 -0
  100. package/dist/infrastructure/di/container.js +98 -0
  101. package/dist/infrastructure/di/container.js.map +1 -0
  102. package/dist/infrastructure/di/types.d.ts +39 -0
  103. package/dist/infrastructure/di/types.js +45 -0
  104. package/dist/infrastructure/di/types.js.map +1 -0
  105. package/dist/infrastructure/i18n/I18nextService.d.ts +27 -0
  106. package/dist/infrastructure/i18n/I18nextService.js +357 -0
  107. package/dist/infrastructure/i18n/I18nextService.js.map +1 -0
  108. package/dist/infrastructure/mcp/CapabilityNegotiator.d.ts +21 -0
  109. package/dist/infrastructure/mcp/CapabilityNegotiator.js +75 -0
  110. package/dist/infrastructure/mcp/CapabilityNegotiator.js.map +1 -0
  111. package/dist/infrastructure/mcp/ErrorHandler.d.ts +29 -0
  112. package/dist/infrastructure/mcp/ErrorHandler.js +101 -0
  113. package/dist/infrastructure/mcp/ErrorHandler.js.map +1 -0
  114. package/dist/infrastructure/mcp/MCPServer.d.ts +25 -0
  115. package/dist/infrastructure/mcp/MCPServer.js +246 -0
  116. package/dist/infrastructure/mcp/MCPServer.js.map +1 -0
  117. package/dist/infrastructure/mcp/PromptManager.d.ts +18 -0
  118. package/dist/infrastructure/mcp/PromptManager.js +373 -0
  119. package/dist/infrastructure/mcp/PromptManager.js.map +1 -0
  120. package/dist/infrastructure/mcp/ResourceManager.d.ts +15 -0
  121. package/dist/infrastructure/mcp/ResourceManager.js +229 -0
  122. package/dist/infrastructure/mcp/ResourceManager.js.map +1 -0
  123. package/dist/infrastructure/mcp/SessionManager.d.ts +64 -0
  124. package/dist/infrastructure/mcp/SessionManager.js +221 -0
  125. package/dist/infrastructure/mcp/SessionManager.js.map +1 -0
  126. package/dist/infrastructure/mcp/ToolRegistry.d.ts +48 -0
  127. package/dist/infrastructure/mcp/ToolRegistry.js +235 -0
  128. package/dist/infrastructure/mcp/ToolRegistry.js.map +1 -0
  129. package/dist/infrastructure/platform/PlatformAdapter.d.ts +46 -0
  130. package/dist/infrastructure/platform/PlatformAdapter.js +355 -0
  131. package/dist/infrastructure/platform/PlatformAdapter.js.map +1 -0
  132. package/dist/infrastructure/plugins/HookSystem.d.ts +40 -0
  133. package/dist/infrastructure/plugins/HookSystem.js +415 -0
  134. package/dist/infrastructure/plugins/HookSystem.js.map +1 -0
  135. package/dist/infrastructure/plugins/PluginManager.d.ts +51 -0
  136. package/dist/infrastructure/plugins/PluginManager.js +650 -0
  137. package/dist/infrastructure/plugins/PluginManager.js.map +1 -0
  138. package/dist/infrastructure/plugins/PluginSteeringRegistry.d.ts +63 -0
  139. package/dist/infrastructure/plugins/PluginSteeringRegistry.js +439 -0
  140. package/dist/infrastructure/plugins/PluginSteeringRegistry.js.map +1 -0
  141. package/dist/infrastructure/plugins/PluginToolRegistry.d.ts +54 -0
  142. package/dist/infrastructure/plugins/PluginToolRegistry.js +490 -0
  143. package/dist/infrastructure/plugins/PluginToolRegistry.js.map +1 -0
  144. package/dist/infrastructure/quality/ASTAnalyzer.d.ts +65 -0
  145. package/dist/infrastructure/quality/ASTAnalyzer.js +439 -0
  146. package/dist/infrastructure/quality/ASTAnalyzer.js.map +1 -0
  147. package/dist/infrastructure/quality/LinusCodeReviewer.d.ts +52 -0
  148. package/dist/infrastructure/quality/LinusCodeReviewer.js +551 -0
  149. package/dist/infrastructure/quality/LinusCodeReviewer.js.map +1 -0
  150. package/dist/infrastructure/repositories/InMemoryProjectRepository.d.ts +10 -0
  151. package/dist/infrastructure/repositories/InMemoryProjectRepository.js +35 -0
  152. package/dist/infrastructure/repositories/InMemoryProjectRepository.js.map +1 -0
  153. package/dist/infrastructure/schemas/project.schema.d.ts +192 -0
  154. package/dist/infrastructure/schemas/project.schema.js +114 -0
  155. package/dist/infrastructure/schemas/project.schema.js.map +1 -0
  156. package/dist/infrastructure/templates/FileGenerator.d.ts +15 -0
  157. package/dist/infrastructure/templates/FileGenerator.js +385 -0
  158. package/dist/infrastructure/templates/FileGenerator.js.map +1 -0
  159. package/dist/infrastructure/templates/HandlebarsRenderer.d.ts +16 -0
  160. package/dist/infrastructure/templates/HandlebarsRenderer.js +252 -0
  161. package/dist/infrastructure/templates/HandlebarsRenderer.js.map +1 -0
  162. package/dist/infrastructure/templates/TemplateManager.d.ts +36 -0
  163. package/dist/infrastructure/templates/TemplateManager.js +777 -0
  164. package/dist/infrastructure/templates/TemplateManager.js.map +1 -0
  165. package/package.json +89 -0
@@ -0,0 +1,777 @@
1
+ // Template library and management system implementation
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ import { injectable, inject } from 'inversify';
15
+ import { promises as fs } from 'fs';
16
+ import path from 'path';
17
+ import { TYPES } from '../di/types.js';
18
+ let TemplateManager = class TemplateManager {
19
+ logger;
20
+ renderer;
21
+ templateCache = new Map();
22
+ templateDirectory;
23
+ cacheInitialized = false;
24
+ constructor(logger, renderer, templateDirectory = './templates') {
25
+ this.logger = logger;
26
+ this.renderer = renderer;
27
+ this.templateDirectory = path.resolve(templateDirectory);
28
+ }
29
+ async getTemplate(id) {
30
+ await this.ensureCacheInitialized();
31
+ const template = this.templateCache.get(id);
32
+ if (template) {
33
+ this.logger.debug('Template retrieved from cache', { id });
34
+ return template;
35
+ }
36
+ // Try to load from disk if not in cache
37
+ try {
38
+ const template = await this.loadTemplateFromDisk(id);
39
+ if (template) {
40
+ this.templateCache.set(id, template);
41
+ this.logger.debug('Template loaded from disk', { id });
42
+ return template;
43
+ }
44
+ }
45
+ catch (error) {
46
+ this.logger.error('Failed to load template from disk', {
47
+ id,
48
+ error: error instanceof Error ? error.message : String(error)
49
+ });
50
+ }
51
+ return null;
52
+ }
53
+ async getTemplatesByCategory(category) {
54
+ await this.ensureCacheInitialized();
55
+ const templates = Array.from(this.templateCache.values())
56
+ .filter(template => template.category === category)
57
+ .sort((a, b) => a.name.localeCompare(b.name));
58
+ this.logger.debug('Templates retrieved by category', { category, count: templates.length });
59
+ return templates;
60
+ }
61
+ async searchTemplates(query, tags) {
62
+ await this.ensureCacheInitialized();
63
+ const queryLower = query.toLowerCase();
64
+ const templates = Array.from(this.templateCache.values()).filter(template => {
65
+ const matchesQuery = template.name.toLowerCase().includes(queryLower) ||
66
+ template.description.toLowerCase().includes(queryLower) ||
67
+ template.tags.some(tag => tag.toLowerCase().includes(queryLower));
68
+ const matchesTags = !tags || tags.length === 0 ||
69
+ tags.every(tag => template.tags.includes(tag));
70
+ return matchesQuery && matchesTags;
71
+ });
72
+ this.logger.debug('Templates searched', { query, tags, count: templates.length });
73
+ return templates.sort((a, b) => a.name.localeCompare(b.name));
74
+ }
75
+ async createTemplate(templateData) {
76
+ const now = new Date();
77
+ const id = this.generateTemplateId(templateData.name, templateData.category);
78
+ const template = {
79
+ ...templateData,
80
+ id,
81
+ createdAt: now,
82
+ updatedAt: now
83
+ };
84
+ // Validate template before saving
85
+ const validation = await this.validateTemplate(template.template, template.variables);
86
+ if (!validation.isValid) {
87
+ throw new Error(`Template validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
88
+ }
89
+ // Save to disk and cache
90
+ await this.saveTemplateToDisk(template);
91
+ this.templateCache.set(id, template);
92
+ this.logger.info('Template created', { id, name: template.name, category: template.category });
93
+ return template;
94
+ }
95
+ async updateTemplate(id, updates) {
96
+ const existing = await this.getTemplate(id);
97
+ if (!existing) {
98
+ throw new Error(`Template with id '${id}' not found`);
99
+ }
100
+ const updated = {
101
+ ...existing,
102
+ ...updates,
103
+ id, // Ensure ID cannot be changed
104
+ createdAt: existing.createdAt, // Preserve creation date
105
+ updatedAt: new Date()
106
+ };
107
+ // Validate updated template
108
+ const validation = await this.validateTemplate(updated.template, updated.variables);
109
+ if (!validation.isValid) {
110
+ throw new Error(`Template validation failed: ${validation.errors.map(e => e.message).join(', ')}`);
111
+ }
112
+ // Save to disk and update cache
113
+ await this.saveTemplateToDisk(updated);
114
+ this.templateCache.set(id, updated);
115
+ this.logger.info('Template updated', { id, name: updated.name });
116
+ return updated;
117
+ }
118
+ async deleteTemplate(id) {
119
+ const template = await this.getTemplate(id);
120
+ if (!template) {
121
+ throw new Error(`Template with id '${id}' not found`);
122
+ }
123
+ // Remove from disk
124
+ const templatePath = this.getTemplatePath(id);
125
+ try {
126
+ await fs.unlink(templatePath);
127
+ this.templateCache.delete(id);
128
+ this.logger.info('Template deleted', { id, name: template.name });
129
+ }
130
+ catch (error) {
131
+ this.logger.error('Failed to delete template file', {
132
+ id,
133
+ path: templatePath,
134
+ error: error instanceof Error ? error.message : String(error)
135
+ });
136
+ throw new Error(`Failed to delete template: ${error instanceof Error ? error.message : String(error)}`);
137
+ }
138
+ }
139
+ async validateTemplate(template, variables) {
140
+ const errors = [];
141
+ const warnings = [];
142
+ try {
143
+ // Try to compile the template with Handlebars
144
+ await this.renderer.compile(template, 'validation_template');
145
+ // Check for required variables
146
+ const templateVariables = this.extractVariablesFromTemplate(template);
147
+ const definedVariables = new Set(variables.map(v => v.name));
148
+ // Check for undefined variables
149
+ for (const usedVar of templateVariables) {
150
+ if (!definedVariables.has(usedVar)) {
151
+ warnings.push({
152
+ message: `Variable '${usedVar}' is used in template but not defined in variables`,
153
+ variable: usedVar,
154
+ suggestion: `Add '${usedVar}' to the template variables`
155
+ });
156
+ }
157
+ }
158
+ // Check for unused defined variables
159
+ for (const variable of variables) {
160
+ if (!templateVariables.has(variable.name)) {
161
+ warnings.push({
162
+ message: `Variable '${variable.name}' is defined but not used in template`,
163
+ variable: variable.name,
164
+ suggestion: `Remove '${variable.name}' from template variables or use it in the template`
165
+ });
166
+ }
167
+ }
168
+ }
169
+ catch (error) {
170
+ errors.push({
171
+ message: `Template compilation error: ${error instanceof Error ? error.message : String(error)}`
172
+ });
173
+ }
174
+ return {
175
+ isValid: errors.length === 0,
176
+ errors,
177
+ warnings
178
+ };
179
+ }
180
+ async getAllTemplates() {
181
+ await this.ensureCacheInitialized();
182
+ return Array.from(this.templateCache.values()).sort((a, b) => a.name.localeCompare(b.name));
183
+ }
184
+ async ensureCacheInitialized() {
185
+ if (this.cacheInitialized)
186
+ return;
187
+ try {
188
+ await this.loadAllTemplates();
189
+ this.cacheInitialized = true;
190
+ this.logger.debug('Template cache initialized');
191
+ }
192
+ catch (error) {
193
+ this.logger.error('Failed to initialize template cache', {
194
+ error: error instanceof Error ? error.message : String(error)
195
+ });
196
+ throw error;
197
+ }
198
+ }
199
+ async loadAllTemplates() {
200
+ try {
201
+ await fs.mkdir(this.templateDirectory, { recursive: true });
202
+ const files = await fs.readdir(this.templateDirectory, { withFileTypes: true });
203
+ const templateFiles = files
204
+ .filter(file => file.isFile() && file.name.endsWith('.json'))
205
+ .map(file => file.name.replace('.json', ''));
206
+ for (const templateId of templateFiles) {
207
+ try {
208
+ const template = await this.loadTemplateFromDisk(templateId);
209
+ if (template) {
210
+ this.templateCache.set(templateId, template);
211
+ }
212
+ }
213
+ catch (error) {
214
+ this.logger.warn('Failed to load template', {
215
+ templateId,
216
+ error: error instanceof Error ? error.message : String(error)
217
+ });
218
+ }
219
+ }
220
+ this.logger.info('Templates loaded from disk', { count: this.templateCache.size });
221
+ }
222
+ catch (error) {
223
+ this.logger.error('Failed to scan template directory', {
224
+ directory: this.templateDirectory,
225
+ error: error instanceof Error ? error.message : String(error)
226
+ });
227
+ // Create built-in templates if directory doesn't exist
228
+ await this.createBuiltInTemplates();
229
+ }
230
+ }
231
+ async loadTemplateFromDisk(id) {
232
+ const templatePath = this.getTemplatePath(id);
233
+ const templateContentPath = this.getTemplateContentPath(id);
234
+ try {
235
+ const [metadataContent, templateContent] = await Promise.all([
236
+ fs.readFile(templatePath, 'utf-8'),
237
+ fs.readFile(templateContentPath, 'utf-8')
238
+ ]);
239
+ const metadata = JSON.parse(metadataContent);
240
+ return {
241
+ ...metadata,
242
+ template: templateContent,
243
+ createdAt: new Date(metadata.createdAt),
244
+ updatedAt: new Date(metadata.updatedAt)
245
+ };
246
+ }
247
+ catch (error) {
248
+ if (error.code !== 'ENOENT') {
249
+ this.logger.error('Error loading template from disk', {
250
+ id,
251
+ path: templatePath,
252
+ error: error instanceof Error ? error.message : String(error)
253
+ });
254
+ }
255
+ return null;
256
+ }
257
+ }
258
+ async saveTemplateToDisk(template) {
259
+ const templatePath = this.getTemplatePath(template.id);
260
+ const templateContentPath = this.getTemplateContentPath(template.id);
261
+ const metadata = {
262
+ id: template.id,
263
+ name: template.name,
264
+ category: template.category,
265
+ description: template.description,
266
+ variables: template.variables,
267
+ version: template.version,
268
+ author: template.author,
269
+ tags: template.tags,
270
+ createdAt: template.createdAt,
271
+ updatedAt: template.updatedAt
272
+ };
273
+ try {
274
+ await fs.mkdir(path.dirname(templatePath), { recursive: true });
275
+ await Promise.all([
276
+ fs.writeFile(templatePath, JSON.stringify(metadata, null, 2)),
277
+ fs.writeFile(templateContentPath, template.template)
278
+ ]);
279
+ }
280
+ catch (error) {
281
+ this.logger.error('Failed to save template to disk', {
282
+ id: template.id,
283
+ path: templatePath,
284
+ error: error instanceof Error ? error.message : String(error)
285
+ });
286
+ throw error;
287
+ }
288
+ }
289
+ getTemplatePath(id) {
290
+ return path.join(this.templateDirectory, `${id}.json`);
291
+ }
292
+ getTemplateContentPath(id) {
293
+ return path.join(this.templateDirectory, `${id}.hbs`);
294
+ }
295
+ generateTemplateId(name, category) {
296
+ const timestamp = Date.now().toString(36);
297
+ const nameSlug = name.toLowerCase().replace(/[^a-z0-9]/g, '-').replace(/-+/g, '-');
298
+ return `${category}-${nameSlug}-${timestamp}`;
299
+ }
300
+ extractVariablesFromTemplate(template) {
301
+ const variables = new Set();
302
+ // Match Handlebars variables: {{variable}}, {{#each items}}, {{#if condition}}, etc.
303
+ const variableRegex = /\{\{(?:#(?:each|if|unless|with)\s+)?([a-zA-Z_][a-zA-Z0-9_.]*)/g;
304
+ let match;
305
+ while ((match = variableRegex.exec(template)) !== null) {
306
+ const variable = match[1].split('.')[0]; // Get root variable name
307
+ if (variable !== 'this' && !variable.startsWith('@')) {
308
+ variables.add(variable);
309
+ }
310
+ }
311
+ return variables;
312
+ }
313
+ async createBuiltInTemplates() {
314
+ const builtInTemplates = await this.getBuiltInTemplates();
315
+ for (const templateData of builtInTemplates) {
316
+ try {
317
+ await this.createTemplate(templateData);
318
+ }
319
+ catch (error) {
320
+ this.logger.warn('Failed to create built-in template', {
321
+ name: templateData.name,
322
+ error: error instanceof Error ? error.message : String(error)
323
+ });
324
+ }
325
+ }
326
+ }
327
+ async getBuiltInTemplates() {
328
+ return [
329
+ {
330
+ name: 'spec-json',
331
+ category: TemplateCategory.SPECIFICATION,
332
+ description: 'SDD specification JSON template',
333
+ template: await this.getSpecJsonTemplate(),
334
+ variables: [
335
+ { name: 'name', type: 'string', description: 'Project name', required: true },
336
+ { name: 'description', type: 'string', description: 'Project description', required: false },
337
+ { name: 'author', type: 'string', description: 'Project author', required: false }
338
+ ],
339
+ version: '1.0.0',
340
+ tags: ['sdd', 'specification', 'json']
341
+ },
342
+ {
343
+ name: 'requirements-md',
344
+ category: TemplateCategory.REQUIREMENTS,
345
+ description: 'SDD requirements document template',
346
+ template: await this.getRequirementsTemplate(),
347
+ variables: [
348
+ { name: 'projectName', type: 'string', description: 'Project name', required: true },
349
+ { name: 'requirements', type: 'array', description: 'List of requirements', required: true }
350
+ ],
351
+ version: '1.0.0',
352
+ tags: ['sdd', 'requirements', 'markdown']
353
+ },
354
+ {
355
+ name: 'design-md',
356
+ category: TemplateCategory.DESIGN,
357
+ description: 'SDD design document template',
358
+ template: await this.getDesignTemplate(),
359
+ variables: [
360
+ { name: 'projectName', type: 'string', description: 'Project name', required: true },
361
+ { name: 'architecture', type: 'string', description: 'Architecture description', required: true },
362
+ { name: 'components', type: 'array', description: 'System components', required: true }
363
+ ],
364
+ version: '1.0.0',
365
+ tags: ['sdd', 'design', 'markdown']
366
+ },
367
+ {
368
+ name: 'tasks-md',
369
+ category: TemplateCategory.TASKS,
370
+ description: 'SDD tasks document template',
371
+ template: await this.getTasksTemplate(),
372
+ variables: [
373
+ { name: 'projectName', type: 'string', description: 'Project name', required: true },
374
+ { name: 'tasks', type: 'array', description: 'List of tasks', required: true }
375
+ ],
376
+ version: '1.0.0',
377
+ tags: ['sdd', 'tasks', 'markdown']
378
+ },
379
+ {
380
+ name: 'product-steering',
381
+ category: TemplateCategory.STEERING,
382
+ description: 'Product steering document template',
383
+ template: await this.getProductSteeringTemplate(),
384
+ variables: [
385
+ { name: 'productName', type: 'string', description: 'Product name', required: true },
386
+ { name: 'vision', type: 'string', description: 'Product vision', required: true },
387
+ { name: 'goals', type: 'array', description: 'Product goals', required: true }
388
+ ],
389
+ version: '1.0.0',
390
+ tags: ['steering', 'product', 'markdown']
391
+ },
392
+ {
393
+ name: 'tech-steering',
394
+ category: TemplateCategory.STEERING,
395
+ description: 'Technical steering document template',
396
+ template: await this.getTechSteeringTemplate(),
397
+ variables: [
398
+ { name: 'projectName', type: 'string', description: 'Project name', required: true },
399
+ { name: 'techStack', type: 'array', description: 'Technology stack', required: true },
400
+ { name: 'architecture', type: 'string', description: 'Architecture pattern', required: true }
401
+ ],
402
+ version: '1.0.0',
403
+ tags: ['steering', 'technical', 'markdown']
404
+ },
405
+ {
406
+ name: 'structure-steering',
407
+ category: TemplateCategory.STEERING,
408
+ description: 'Structure steering document template',
409
+ template: await this.getStructureSteeringTemplate(),
410
+ variables: [
411
+ { name: 'projectName', type: 'string', description: 'Project name', required: true },
412
+ { name: 'structure', type: 'object', description: 'Project structure', required: true }
413
+ ],
414
+ version: '1.0.0',
415
+ tags: ['steering', 'structure', 'markdown']
416
+ },
417
+ {
418
+ name: 'linus-review-steering',
419
+ category: TemplateCategory.STEERING,
420
+ description: 'Linus-style code review steering document template',
421
+ template: await this.getLinusReviewTemplate(),
422
+ variables: [
423
+ { name: 'projectName', type: 'string', description: 'Project name', required: true }
424
+ ],
425
+ version: '1.0.0',
426
+ tags: ['steering', 'code-review', 'linus', 'quality']
427
+ }
428
+ ];
429
+ }
430
+ // Template content methods
431
+ async getSpecJsonTemplate() {
432
+ return `{
433
+ "name": "{{name}}",
434
+ "description": "{{#if description}}{{description}}{{else}}{{name}} specification{{/if}}",
435
+ "version": "1.0.0",
436
+ "author": "{{#if author}}{{author}}{{else}}Unknown{{/if}}",
437
+ "createdAt": "{{formatDate context.timestamp}}",
438
+ "phase": "INIT",
439
+ "approved": {
440
+ "requirements": false,
441
+ "design": false,
442
+ "tasks": false
443
+ },
444
+ "metadata": {
445
+ "projectId": "{{generateId}}",
446
+ "basePath": "{{context.project.basePath}}",
447
+ "technology": [],
448
+ "complexity": "moderate"
449
+ }
450
+ }`;
451
+ }
452
+ async getRequirementsTemplate() {
453
+ return `# {{projectName}} - Requirements
454
+
455
+ ## Overview
456
+ This document outlines the requirements for {{projectName}}.
457
+
458
+ ## Functional Requirements
459
+ {{#each requirements}}
460
+ ### {{@index}}. {{title}}
461
+ {{description}}
462
+
463
+ **Acceptance Criteria:**
464
+ {{#each acceptanceCriteria}}
465
+ - {{this}}
466
+ {{/each}}
467
+
468
+ {{/each}}
469
+
470
+ ## Non-Functional Requirements
471
+ - Performance: Response time under 200ms
472
+ - Scalability: Support 1000+ concurrent users
473
+ - Reliability: 99.9% uptime
474
+ - Security: Secure authentication and authorization
475
+
476
+ ## Dependencies
477
+ {{#if dependencies}}
478
+ {{#each dependencies}}
479
+ - {{name}}: {{description}}
480
+ {{/each}}
481
+ {{else}}
482
+ No external dependencies identified.
483
+ {{/if}}
484
+
485
+ ## Assumptions
486
+ {{#if assumptions}}
487
+ {{#each assumptions}}
488
+ - {{this}}
489
+ {{/each}}
490
+ {{else}}
491
+ No assumptions documented.
492
+ {{/if}}
493
+
494
+ ---
495
+ *Generated on {{formatDate context.timestamp}} using SDD MCP Server*`;
496
+ }
497
+ async getDesignTemplate() {
498
+ return `# {{projectName}} - Design Document
499
+
500
+ ## Architecture Overview
501
+ {{architecture}}
502
+
503
+ ## System Components
504
+ {{#each components}}
505
+ ### {{name}}
506
+ **Purpose:** {{purpose}}
507
+ **Responsibilities:**
508
+ {{#each responsibilities}}
509
+ - {{this}}
510
+ {{/each}}
511
+
512
+ **Interfaces:**
513
+ {{#each interfaces}}
514
+ - {{name}}: {{description}}
515
+ {{/each}}
516
+
517
+ {{/each}}
518
+
519
+ ## Data Models
520
+ {{#if dataModels}}
521
+ {{#each dataModels}}
522
+ ### {{name}}
523
+ \`\`\`typescript
524
+ {{schema}}
525
+ \`\`\`
526
+ {{/each}}
527
+ {{else}}
528
+ Data models to be defined during implementation.
529
+ {{/if}}
530
+
531
+ ## API Design
532
+ {{#if apis}}
533
+ {{#each apis}}
534
+ ### {{name}}
535
+ - **Method:** {{method}}
536
+ - **Path:** {{path}}
537
+ - **Description:** {{description}}
538
+ {{/each}}
539
+ {{else}}
540
+ API design to be defined during implementation.
541
+ {{/if}}
542
+
543
+ ## Security Considerations
544
+ - Authentication and authorization mechanisms
545
+ - Data validation and sanitization
546
+ - Secure communication protocols
547
+
548
+ ## Performance Considerations
549
+ - Caching strategies
550
+ - Database optimization
551
+ - Load balancing
552
+
553
+ ---
554
+ *Generated on {{formatDate context.timestamp}} using SDD MCP Server*`;
555
+ }
556
+ async getTasksTemplate() {
557
+ return `# {{projectName}} - Implementation Tasks
558
+
559
+ ## Task Breakdown
560
+ {{#each tasks}}
561
+ ### {{@index}}. {{title}}
562
+ {{taskStatus completed}} **{{title}}**
563
+
564
+ **Description:** {{description}}
565
+
566
+ **Subtasks:**
567
+ {{#each subtasks}}
568
+ - {{taskStatus completed}} {{title}}
569
+ {{/each}}
570
+
571
+ **Dependencies:**
572
+ {{#if dependencies}}
573
+ {{#each dependencies}}
574
+ - Task {{this}}
575
+ {{/each}}
576
+ {{else}}
577
+ None
578
+ {{/if}}
579
+
580
+ **Estimated Effort:** {{effort}} hours
581
+
582
+ ---
583
+ {{/each}}
584
+
585
+ ## Progress Summary
586
+ - **Total Tasks:** {{length tasks}}
587
+ - **Completed:** {{#each tasks}}{{#if completed}}1{{/if}}{{/each}}
588
+ - **Remaining:** {{#each tasks}}{{#unless completed}}1{{/unless}}{{/each}}
589
+
590
+ ---
591
+ *Generated on {{formatDate context.timestamp}} using SDD MCP Server*`;
592
+ }
593
+ async getProductSteeringTemplate() {
594
+ return `# Product Steering - {{productName}}
595
+
596
+ ## Vision
597
+ {{vision}}
598
+
599
+ ## Goals
600
+ {{#each goals}}
601
+ - {{this}}
602
+ {{/each}}
603
+
604
+ ## Success Metrics
605
+ {{#if metrics}}
606
+ {{#each metrics}}
607
+ - {{name}}: {{target}}
608
+ {{/each}}
609
+ {{else}}
610
+ Success metrics to be defined.
611
+ {{/if}}
612
+
613
+ ## Target Users
614
+ {{#if users}}
615
+ {{#each users}}
616
+ - **{{name}}**: {{description}}
617
+ {{/each}}
618
+ {{else}}
619
+ Target users to be identified.
620
+ {{/if}}
621
+
622
+ ## Constraints
623
+ {{#if constraints}}
624
+ {{#each constraints}}
625
+ - {{this}}
626
+ {{/each}}
627
+ {{else}}
628
+ No constraints identified.
629
+ {{/if}}
630
+
631
+ ---
632
+ *Product steering document for {{productName}}*`;
633
+ }
634
+ async getTechSteeringTemplate() {
635
+ return `# Technical Steering - {{projectName}}
636
+
637
+ ## Technology Stack
638
+ {{#each techStack}}
639
+ - **{{category}}**: {{name}} {{#if version}}({{version}}){{/if}}
640
+ {{/each}}
641
+
642
+ ## Architecture Pattern
643
+ {{architecture}}
644
+
645
+ ## Development Guidelines
646
+ - Follow clean architecture principles
647
+ - Implement comprehensive testing
648
+ - Use TypeScript for type safety
649
+ - Follow SOLID principles
650
+
651
+ ## Code Quality Standards
652
+ - ESLint configuration for code consistency
653
+ - Prettier for code formatting
654
+ - Husky for pre-commit hooks
655
+ - Jest for unit testing
656
+
657
+ ## Performance Requirements
658
+ - Response time: < 200ms
659
+ - Memory usage: < 512MB
660
+ - CPU usage: < 80%
661
+
662
+ ---
663
+ *Technical steering document for {{projectName}}*`;
664
+ }
665
+ async getStructureSteeringTemplate() {
666
+ return `# Structure Steering - {{projectName}}
667
+
668
+ ## Directory Structure
669
+ {{#each structure.directories}}
670
+ - **{{path}}**: {{purpose}}
671
+ {{/each}}
672
+
673
+ ## File Organization
674
+ {{#each structure.fileTypes}}
675
+ - **{{extension}}**: {{location}} - {{purpose}}
676
+ {{/each}}
677
+
678
+ ## Naming Conventions
679
+ - Files: kebab-case
680
+ - Directories: kebab-case
681
+ - Classes: PascalCase
682
+ - Functions: camelCase
683
+ - Constants: UPPER_SNAKE_CASE
684
+
685
+ ## Import/Export Patterns
686
+ - Use absolute imports from src/
687
+ - Export interfaces and types explicitly
688
+ - Barrel exports for public APIs
689
+
690
+ ---
691
+ *Structure steering document for {{projectName}}*`;
692
+ }
693
+ async getLinusReviewTemplate() {
694
+ return `# Linus-Style Code Review Standards - {{projectName}}
695
+
696
+ ## Code Review Philosophy
697
+ "Good code is not just code that works, but code that is readable, maintainable, and elegant."
698
+
699
+ ## Five-Layer Analysis Framework
700
+
701
+ ### 1. Taste (Good/Passable/Garbage)
702
+ - **Good**: Elegant, simple, intuitive
703
+ - **Passable**: Functional but could be better
704
+ - **Garbage**: Overcomplicated, unclear, problematic
705
+
706
+ ### 2. Complexity Analysis
707
+ - Eliminate unnecessary complexity
708
+ - Prefer simple solutions over clever ones
709
+ - Maximum cyclomatic complexity: 10
710
+ - Maximum nesting depth: 4
711
+
712
+ ### 3. Special Cases
713
+ - Identify and eliminate special-case handling
714
+ - Generalize solutions when possible
715
+ - Avoid magic numbers and hard-coded values
716
+
717
+ ### 4. Data Structures
718
+ - Choose appropriate data structures
719
+ - Optimize for access patterns
720
+ - Consider memory usage and performance
721
+
722
+ ### 5. Code Organization
723
+ - Single responsibility principle
724
+ - Clear separation of concerns
725
+ - Intuitive naming and structure
726
+
727
+ ## Review Criteria
728
+
729
+ ### Immediate Rejection
730
+ - Code that doesn't compile
731
+ - Missing tests for new functionality
732
+ - Obvious security vulnerabilities
733
+ - Memory leaks or resource leaks
734
+
735
+ ### Strong Criticism
736
+ - Overly complex solutions
737
+ - Poor error handling
738
+ - Inconsistent coding style
739
+ - Missing documentation
740
+
741
+ ### Feedback Areas
742
+ - Performance optimizations
743
+ - Code readability improvements
744
+ - Architecture suggestions
745
+ - Best practice recommendations
746
+
747
+ ## Standards
748
+
749
+ ### Performance
750
+ - O(n) or better for critical paths
751
+ - Avoid nested loops when possible
752
+ - Profile before optimizing
753
+
754
+ ### Maintainability
755
+ - Self-documenting code
756
+ - Clear variable and function names
757
+ - Minimal cognitive load
758
+
759
+ ### Reliability
760
+ - Comprehensive error handling
761
+ - Input validation
762
+ - Graceful degradation
763
+
764
+ ---
765
+ *"The best code is code that doesn't need to be written, but if it must be written, make it beautiful."*
766
+
767
+ *Linus-style review standards for {{projectName}}*`;
768
+ }
769
+ };
770
+ TemplateManager = __decorate([
771
+ injectable(),
772
+ __param(0, inject(TYPES.LoggerPort)),
773
+ __param(1, inject(TYPES.TemplateRendererPort)),
774
+ __metadata("design:paramtypes", [Object, Object, Object])
775
+ ], TemplateManager);
776
+ export { TemplateManager };
777
+ //# sourceMappingURL=TemplateManager.js.map