sdd-mcp-server 1.1.22 → 1.3.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.
@@ -17,18 +17,24 @@ import { ProjectService } from '../../application/services/ProjectService.js';
17
17
  import { WorkflowService } from '../../application/services/WorkflowService.js';
18
18
  import { TemplateService } from '../../application/services/TemplateService.js';
19
19
  import { QualityService } from '../../application/services/QualityService.js';
20
+ import { SteeringDocumentService } from '../../application/services/SteeringDocumentService.js';
21
+ import { CodebaseAnalysisService } from '../../application/services/CodebaseAnalysisService.js';
20
22
  import { WorkflowPhase } from '../../domain/types.js';
21
23
  let SDDToolAdapter = class SDDToolAdapter {
22
24
  projectService;
23
25
  workflowService;
24
26
  templateService;
25
27
  qualityService;
28
+ steeringService;
29
+ codebaseAnalysisService;
26
30
  logger;
27
- constructor(projectService, workflowService, templateService, qualityService, logger) {
31
+ constructor(projectService, workflowService, templateService, qualityService, steeringService, codebaseAnalysisService, logger) {
28
32
  this.projectService = projectService;
29
33
  this.workflowService = workflowService;
30
34
  this.templateService = templateService;
31
35
  this.qualityService = qualityService;
36
+ this.steeringService = steeringService;
37
+ this.codebaseAnalysisService = codebaseAnalysisService;
32
38
  this.logger = logger;
33
39
  }
34
40
  getSDDTools() {
@@ -37,15 +43,13 @@ let SDDToolAdapter = class SDDToolAdapter {
37
43
  name: 'sdd-init',
38
44
  tool: {
39
45
  name: 'sdd-init',
40
- description: 'Initialize a new SDD project with directory structure and spec files',
46
+ description: 'Initialize a new SDD project from description',
41
47
  inputSchema: {
42
48
  type: 'object',
43
49
  properties: {
44
- name: { type: 'string', description: 'Project name' },
45
- path: { type: 'string', description: 'Project path' },
46
- language: { type: 'string', enum: ['en', 'ja', 'zh-TW'], default: 'en' }
50
+ description: { type: 'string', description: 'Detailed project description' }
47
51
  },
48
- required: ['name', 'path']
52
+ required: ['description']
49
53
  }
50
54
  },
51
55
  handler: this.handleProjectInit.bind(this)
@@ -69,13 +73,13 @@ let SDDToolAdapter = class SDDToolAdapter {
69
73
  name: 'sdd-requirements',
70
74
  tool: {
71
75
  name: 'sdd-requirements',
72
- description: 'Generate requirements document template',
76
+ description: 'Generate requirements doc',
73
77
  inputSchema: {
74
78
  type: 'object',
75
79
  properties: {
76
- projectId: { type: 'string', description: 'Project ID' }
80
+ featureName: { type: 'string', description: 'Feature name' }
77
81
  },
78
- required: ['projectId']
82
+ required: ['featureName']
79
83
  }
80
84
  },
81
85
  handler: this.handleRequirements.bind(this)
@@ -84,13 +88,13 @@ let SDDToolAdapter = class SDDToolAdapter {
84
88
  name: 'sdd-design',
85
89
  tool: {
86
90
  name: 'sdd-design',
87
- description: 'Generate design document template',
91
+ description: 'Create design specifications',
88
92
  inputSchema: {
89
93
  type: 'object',
90
94
  properties: {
91
- projectId: { type: 'string', description: 'Project ID' }
95
+ featureName: { type: 'string', description: 'Feature name' }
92
96
  },
93
- required: ['projectId']
97
+ required: ['featureName']
94
98
  }
95
99
  },
96
100
  handler: this.handleDesign.bind(this)
@@ -99,13 +103,13 @@ let SDDToolAdapter = class SDDToolAdapter {
99
103
  name: 'sdd-tasks',
100
104
  tool: {
101
105
  name: 'sdd-tasks',
102
- description: 'Generate implementation tasks document',
106
+ description: 'Generate task breakdown',
103
107
  inputSchema: {
104
108
  type: 'object',
105
109
  properties: {
106
- projectId: { type: 'string', description: 'Project ID' }
110
+ featureName: { type: 'string', description: 'Feature name' }
107
111
  },
108
- required: ['projectId']
112
+ required: ['featureName']
109
113
  }
110
114
  },
111
115
  handler: this.handleTasks.bind(this)
@@ -125,6 +129,38 @@ let SDDToolAdapter = class SDDToolAdapter {
125
129
  }
126
130
  },
127
131
  handler: this.handleQualityCheck.bind(this)
132
+ },
133
+ {
134
+ name: 'sdd-steering',
135
+ tool: {
136
+ name: 'sdd-steering',
137
+ description: 'Create/update steering documents with project-specific analysis',
138
+ inputSchema: {
139
+ type: 'object',
140
+ properties: {
141
+ updateMode: { type: 'string', enum: ['create', 'update'], description: 'Whether to create new or update existing documents' }
142
+ }
143
+ }
144
+ },
145
+ handler: this.handleSteering.bind(this)
146
+ },
147
+ {
148
+ name: 'sdd-steering-custom',
149
+ tool: {
150
+ name: 'sdd-steering-custom',
151
+ description: 'Create custom steering documents for specialized contexts',
152
+ inputSchema: {
153
+ type: 'object',
154
+ properties: {
155
+ fileName: { type: 'string', description: 'Filename for the custom steering document' },
156
+ topic: { type: 'string', description: 'Topic/purpose of the custom steering document' },
157
+ inclusionMode: { type: 'string', enum: ['always', 'conditional', 'manual'], description: 'How this steering document should be included' },
158
+ filePattern: { type: 'string', description: 'File pattern for conditional inclusion' }
159
+ },
160
+ required: ['fileName', 'topic', 'inclusionMode']
161
+ }
162
+ },
163
+ handler: this.handleSteeringCustom.bind(this)
128
164
  }
129
165
  ];
130
166
  }
@@ -137,6 +173,8 @@ let SDDToolAdapter = class SDDToolAdapter {
137
173
  // Generate initial spec.json
138
174
  const specContent = await this.templateService.generateSpecJson(project);
139
175
  await this.templateService.writeProjectFile(project, 'spec.json', specContent);
176
+ // Create AGENTS.md if it doesn't exist
177
+ await this.createAgentsFile(path);
140
178
  return `Project "${name}" initialized successfully at ${path}\nProject ID: ${project.id}`;
141
179
  }
142
180
  async handleProjectStatus(args) {
@@ -256,6 +294,694 @@ let SDDToolAdapter = class SDDToolAdapter {
256
294
  });
257
295
  return this.qualityService.formatQualityReport(report);
258
296
  }
297
+ async handleSteering(args) {
298
+ const { updateMode = 'update' } = args;
299
+ const projectPath = process.cwd();
300
+ try {
301
+ // Analyze the project
302
+ const analysis = await this.codebaseAnalysisService.analyzeCodebase(projectPath);
303
+ // Generate steering documents based on project analysis
304
+ const productContent = await this.generateProductSteering(analysis);
305
+ const techContent = await this.generateTechSteering(analysis);
306
+ const structureContent = await this.generateStructureSteering(analysis);
307
+ // Create steering documents
308
+ await this.steeringService.createSteeringDocument(projectPath, {
309
+ name: 'product.md',
310
+ type: 'PRODUCT',
311
+ mode: 'ALWAYS',
312
+ content: productContent
313
+ });
314
+ await this.steeringService.createSteeringDocument(projectPath, {
315
+ name: 'tech.md',
316
+ type: 'TECHNICAL',
317
+ mode: 'ALWAYS',
318
+ content: techContent
319
+ });
320
+ await this.steeringService.createSteeringDocument(projectPath, {
321
+ name: 'structure.md',
322
+ type: 'STRUCTURE',
323
+ mode: 'ALWAYS',
324
+ content: structureContent
325
+ });
326
+ // Create static steering documents if they don't exist
327
+ await this.createStaticSteeringDocuments(projectPath);
328
+ // Create AGENTS.md if it doesn't exist
329
+ await this.createAgentsFile(projectPath);
330
+ // Get project info from package.json
331
+ let packageJson = {};
332
+ try {
333
+ const fs = await import('fs');
334
+ const path = await import('path');
335
+ const packagePath = path.join(projectPath, 'package.json');
336
+ if (fs.existsSync(packagePath)) {
337
+ const packageContent = fs.readFileSync(packagePath, 'utf8');
338
+ packageJson = JSON.parse(packageContent);
339
+ }
340
+ }
341
+ catch (error) {
342
+ // Ignore errors
343
+ }
344
+ return `## Steering Documents Updated
345
+
346
+ **Project**: ${packageJson.name || 'Unknown'}
347
+ **Mode**: ${updateMode}
348
+
349
+ **Updated Files**:
350
+ - \`.kiro/steering/product.md\` - Product overview and business context
351
+ - \`.kiro/steering/tech.md\` - Technology stack and development environment
352
+ - \`.kiro/steering/structure.md\` - Project organization and architectural decisions
353
+
354
+ **Analysis**:
355
+ - Technology stack: ${Object.keys({ ...packageJson.dependencies, ...packageJson.devDependencies }).length} dependencies detected
356
+ - Project type: ${packageJson.type || 'Unknown'}
357
+ - Existing steering: Updated preserving customizations
358
+
359
+ These steering documents provide consistent project context for all AI interactions and spec-driven development workflows.`;
360
+ }
361
+ catch (error) {
362
+ this.logger.error('Failed to generate steering documents', error);
363
+ throw new Error(`Failed to generate steering documents: ${error.message}`);
364
+ }
365
+ }
366
+ async handleSteeringCustom(args) {
367
+ const { fileName, topic, inclusionMode, filePattern } = args;
368
+ const projectPath = process.cwd();
369
+ if (typeof fileName !== 'string' || typeof topic !== 'string' || typeof inclusionMode !== 'string') {
370
+ throw new Error('Invalid arguments: fileName, topic, and inclusionMode must be strings');
371
+ }
372
+ const content = `# ${topic}
373
+
374
+ ## Purpose
375
+ Define the purpose and scope of this steering document.
376
+
377
+ ## Guidelines
378
+ - Guideline 1
379
+ - Guideline 2
380
+
381
+ ## Usage
382
+ Describe when and how this steering document should be applied.
383
+
384
+ ## Inclusion Mode
385
+ Mode: ${inclusionMode}${filePattern ? `
386
+ Pattern: ${filePattern}` : ''}
387
+
388
+ Generated on: ${new Date().toISOString()}
389
+ `;
390
+ await this.steeringService.createSteeringDocument(projectPath, {
391
+ name: fileName,
392
+ type: 'CUSTOM',
393
+ mode: inclusionMode.toUpperCase(),
394
+ patterns: filePattern ? [filePattern] : [],
395
+ content
396
+ });
397
+ return `Custom steering document "${fileName}" created successfully with ${inclusionMode} inclusion mode.`;
398
+ }
399
+ async generateProductSteering(analysis) {
400
+ // Try to read package.json for project info
401
+ let packageJson = {};
402
+ try {
403
+ const fs = await import('fs');
404
+ const path = await import('path');
405
+ const packagePath = path.join(process.cwd(), 'package.json');
406
+ if (fs.existsSync(packagePath)) {
407
+ const packageContent = fs.readFileSync(packagePath, 'utf8');
408
+ packageJson = JSON.parse(packageContent);
409
+ }
410
+ }
411
+ catch (error) {
412
+ // Ignore errors
413
+ }
414
+ return `# Product Overview
415
+
416
+ ## Product Description
417
+ ${packageJson.description || 'No description available'}
418
+
419
+ ## Core Features
420
+ ${this.extractFeatures(packageJson, analysis).map((feature) => `- ${feature}`).join('\n')}
421
+
422
+ ## Target Use Case
423
+ ${this.generateTargetUseCase(packageJson)}
424
+
425
+ ## Key Value Proposition
426
+ ${this.generateValueProposition(packageJson, analysis)}
427
+
428
+ ## Target Users
429
+ ${this.generateTargetUsers(packageJson)}`;
430
+ }
431
+ async generateTechSteering(analysis) {
432
+ // Try to read package.json for project info
433
+ let packageJson = {};
434
+ try {
435
+ const fs = await import('fs');
436
+ const path = await import('path');
437
+ const packagePath = path.join(process.cwd(), 'package.json');
438
+ if (fs.existsSync(packagePath)) {
439
+ const packageContent = fs.readFileSync(packagePath, 'utf8');
440
+ packageJson = JSON.parse(packageContent);
441
+ }
442
+ }
443
+ catch (error) {
444
+ // Ignore errors
445
+ }
446
+ return `# Technology Overview
447
+
448
+ ## Technology Stack
449
+ ${this.generateTechStack(packageJson, analysis)}
450
+
451
+ ## Development Environment
452
+ - Node.js: ${packageJson.engines?.node || 'Unknown'}
453
+ - Package Manager: npm
454
+
455
+ ## Key Dependencies
456
+ ${this.generateDependencyList(packageJson)}
457
+
458
+ ## Architecture Patterns
459
+ ${this.generateArchitecturePatterns(analysis)}
460
+
461
+ ## Quality Standards
462
+ ${this.generateQualityStandards(packageJson)}`;
463
+ }
464
+ async generateStructureSteering(analysis) {
465
+ return `# Project Structure
466
+
467
+ ## Directory Organization
468
+ ${this.generateDirectoryStructure(analysis)}
469
+
470
+ ## File Naming Conventions
471
+ ${this.generateNamingConventions(analysis)}
472
+
473
+ ## Module Organization
474
+ ${this.generateModuleOrganization(analysis)}
475
+
476
+ ## Development Workflow
477
+ ${this.generateWorkflow(analysis)}`;
478
+ }
479
+ extractFeatures(packageJson, analysis) {
480
+ const features = [];
481
+ // Extract features from scripts
482
+ if (packageJson.scripts) {
483
+ if (packageJson.scripts.test)
484
+ features.push('Testing framework');
485
+ if (packageJson.scripts.build)
486
+ features.push('Build system');
487
+ if (packageJson.scripts.dev || packageJson.scripts.start)
488
+ features.push('Development server');
489
+ if (packageJson.scripts.lint)
490
+ features.push('Code linting');
491
+ if (packageJson.scripts.typecheck)
492
+ features.push('Type checking');
493
+ }
494
+ // Extract features from dependencies
495
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
496
+ if (deps?.express || deps?.fastify || deps?.koa)
497
+ features.push('Web server');
498
+ if (deps?.react || deps?.vue || deps?.angular)
499
+ features.push('Frontend framework');
500
+ if (deps?.typescript)
501
+ features.push('TypeScript support');
502
+ if (deps?.jest || deps?.mocha || deps?.vitest)
503
+ features.push('Unit testing');
504
+ if (deps?.eslint)
505
+ features.push('Code quality enforcement');
506
+ return features.length > 0 ? features : ['Core functionality to be defined'];
507
+ }
508
+ generateTargetUseCase(packageJson) {
509
+ if (packageJson.keywords) {
510
+ return `This product is designed for ${packageJson.keywords.join(', ')} use cases.`;
511
+ }
512
+ return 'Target use cases to be defined based on project requirements.';
513
+ }
514
+ generateValueProposition(packageJson, analysis) {
515
+ const features = this.extractFeatures(packageJson, analysis);
516
+ return features.map(feature => `- **${feature}**: Enhanced development experience`).join('\n');
517
+ }
518
+ generateTargetUsers(packageJson) {
519
+ if (packageJson.keywords?.includes('cli')) {
520
+ return '- Command-line tool users\n- Developers and system administrators';
521
+ }
522
+ if (packageJson.keywords?.includes('api')) {
523
+ return '- API consumers\n- Third-party integrators';
524
+ }
525
+ return '- Primary user persona\n- Secondary user persona';
526
+ }
527
+ generateTechStack(packageJson, analysis) {
528
+ const deps = { ...packageJson.dependencies, ...packageJson.devDependencies };
529
+ const stack = [];
530
+ if (deps?.typescript)
531
+ stack.push('TypeScript');
532
+ if (deps?.node || packageJson.engines?.node)
533
+ stack.push('Node.js');
534
+ if (deps?.express)
535
+ stack.push('Express.js');
536
+ if (deps?.react)
537
+ stack.push('React');
538
+ if (deps?.vue)
539
+ stack.push('Vue.js');
540
+ return stack.length > 0 ? stack.join(', ') : 'Technology stack to be defined';
541
+ }
542
+ generateDependencyList(packageJson) {
543
+ const production = Object.keys(packageJson.dependencies || {});
544
+ const development = Object.keys(packageJson.devDependencies || {});
545
+ let list = '';
546
+ if (production.length > 0) {
547
+ list += '### Production Dependencies\n';
548
+ list += production.slice(0, 10).map((dep) => `- ${dep}`).join('\n');
549
+ }
550
+ if (development.length > 0) {
551
+ list += '\n### Development Dependencies\n';
552
+ list += development.slice(0, 10).map((dep) => `- ${dep}`).join('\n');
553
+ }
554
+ return list || 'Dependencies to be analyzed';
555
+ }
556
+ generateArchitecturePatterns(analysis) {
557
+ const patterns = [];
558
+ // Try to analyze directory structure from filesystem
559
+ try {
560
+ const fs = require('fs');
561
+ const projectPath = process.cwd();
562
+ const items = fs.readdirSync(projectPath, { withFileTypes: true });
563
+ const directories = items
564
+ .filter((item) => item.isDirectory())
565
+ .map((item) => item.name);
566
+ if (directories.includes('src'))
567
+ patterns.push('Source code organization');
568
+ if (directories.includes('test') || directories.includes('__tests__'))
569
+ patterns.push('Test-driven development');
570
+ if (directories.includes('dist') || directories.includes('build'))
571
+ patterns.push('Build artifact separation');
572
+ }
573
+ catch (error) {
574
+ // Ignore filesystem errors
575
+ }
576
+ return patterns.length > 0 ? patterns.map(p => `- ${p}`).join('\n') : '- Patterns to be defined';
577
+ }
578
+ generateQualityStandards(packageJson) {
579
+ const standards = [];
580
+ if (packageJson.scripts?.lint)
581
+ standards.push('Code linting with ESLint');
582
+ if (packageJson.scripts?.typecheck)
583
+ standards.push('Type checking with TypeScript');
584
+ if (packageJson.scripts?.test)
585
+ standards.push('Unit testing required');
586
+ return standards.length > 0 ? standards.map(s => `- ${s}`).join('\n') : '- Quality standards to be defined';
587
+ }
588
+ generateDirectoryStructure(analysis) {
589
+ // Try to get directory structure from filesystem
590
+ try {
591
+ const fs = require('fs');
592
+ const projectPath = process.cwd();
593
+ const items = fs.readdirSync(projectPath, { withFileTypes: true });
594
+ const directories = items
595
+ .filter((item) => item.isDirectory() && !item.name.startsWith('.') && item.name !== 'node_modules')
596
+ .map((item) => `- ${item.name}/`)
597
+ .join('\n');
598
+ return directories || 'Directory structure to be analyzed';
599
+ }
600
+ catch (error) {
601
+ return 'Directory structure to be analyzed';
602
+ }
603
+ }
604
+ generateNamingConventions(analysis) {
605
+ return `- Use kebab-case for file names
606
+ - Use PascalCase for class names
607
+ - Use camelCase for variable names
608
+ - Use UPPER_SNAKE_CASE for constants`;
609
+ }
610
+ generateModuleOrganization(analysis) {
611
+ return `- Group related functionality in modules
612
+ - Use barrel exports (index.ts files)
613
+ - Separate business logic from infrastructure
614
+ - Keep dependencies flowing inward`;
615
+ }
616
+ generateWorkflow(analysis) {
617
+ // Try to read package.json for scripts
618
+ let packageJson = {};
619
+ try {
620
+ const fs = require('fs');
621
+ const path = require('path');
622
+ const packagePath = path.join(process.cwd(), 'package.json');
623
+ if (fs.existsSync(packagePath)) {
624
+ const packageContent = fs.readFileSync(packagePath, 'utf8');
625
+ packageJson = JSON.parse(packageContent);
626
+ }
627
+ }
628
+ catch (error) {
629
+ // Ignore errors
630
+ }
631
+ const scripts = packageJson.scripts || {};
632
+ let workflow = '## Development Commands\n';
633
+ if (scripts.dev)
634
+ workflow += `- \`npm run dev\` - Start development server\n`;
635
+ if (scripts.build)
636
+ workflow += `- \`npm run build\` - Build for production\n`;
637
+ if (scripts.test)
638
+ workflow += `- \`npm run test\` - Run tests\n`;
639
+ if (scripts.lint)
640
+ workflow += `- \`npm run lint\` - Check code quality\n`;
641
+ return workflow;
642
+ }
643
+ async createStaticSteeringDocuments(projectPath) {
644
+ const fs = await import('fs');
645
+ const path = await import('path');
646
+ // Check if linus-review.md exists, if not create it
647
+ const linusReviewPath = path.join(projectPath, '.kiro', 'steering', 'linus-review.md');
648
+ if (!fs.existsSync(linusReviewPath)) {
649
+ const linusReviewContent = `# Linus Torvalds Code Review Steering Document
650
+
651
+ ## Role Definition
652
+
653
+ You are channeling Linus Torvalds, creator and chief architect of the Linux kernel. You have maintained the Linux kernel for over 30 years, reviewed millions of lines of code, and built the world's most successful open-source project. Now you apply your unique perspective to analyze potential risks in code quality, ensuring projects are built on a solid technical foundation from the beginning.
654
+
655
+ ## Core Philosophy
656
+
657
+ **1. "Good Taste" - The First Principle**
658
+ "Sometimes you can look at a problem from a different angle, rewrite it to make special cases disappear and become normal cases."
659
+ - Classic example: Linked list deletion, optimized from 10 lines with if statements to 4 lines without conditional branches
660
+ - Good taste is an intuition that requires accumulated experience
661
+ - Eliminating edge cases is always better than adding conditional checks
662
+
663
+ **2. "Never break userspace" - The Iron Rule**
664
+ "We do not break userspace!"
665
+ - Any change that crashes existing programs is a bug, no matter how "theoretically correct"
666
+ - The kernel's duty is to serve users, not educate them
667
+ - Backward compatibility is sacred and inviolable
668
+
669
+ **3. Pragmatism - The Belief**
670
+ "I'm a damn pragmatist."
671
+ - Solve actual problems, not imagined threats
672
+ - Reject "theoretically perfect" but practically complex solutions like microkernels
673
+ - Code should serve reality, not papers
674
+
675
+ **4. Simplicity Obsession - The Standard**
676
+ "If you need more than 3 levels of indentation, you're screwed and should fix your program."
677
+ - Functions must be short and focused, do one thing and do it well
678
+ - C is a Spartan language, naming should be too
679
+ - Complexity is the root of all evil
680
+
681
+ ## Communication Principles
682
+
683
+ ### Basic Communication Standards
684
+
685
+ - **Expression Style**: Direct, sharp, zero nonsense. If code is garbage, call it garbage and explain why.
686
+ - **Technical Priority**: Criticism is always about technical issues, not personal. Don't blur technical judgment for "niceness."
687
+
688
+ ### Requirements Confirmation Process
689
+
690
+ When analyzing any code or technical need, follow these steps:
691
+
692
+ #### 0. **Thinking Premise - Linus's Three Questions**
693
+ Before starting any analysis, ask yourself:
694
+ 1. "Is this a real problem or imagined?" - Reject over-engineering
695
+ 2. "Is there a simpler way?" - Always seek the simplest solution
696
+ 3. "Will it break anything?" - Backward compatibility is the iron rule
697
+
698
+ #### 1. **Requirements Understanding**
699
+ Based on the existing information, understand the requirement and restate it using Linus's thinking/communication style.
700
+
701
+ #### 2. **Linus-style Problem Decomposition Thinking**
702
+
703
+ **First Layer: Data Structure Analysis**
704
+ "Bad programmers worry about the code. Good programmers worry about data structures."
705
+
706
+ - What is the core data? How do they relate?
707
+ - Where does data flow? Who owns it? Who modifies it?
708
+ - Is there unnecessary data copying or transformation?
709
+
710
+ **Second Layer: Special Case Identification**
711
+ "Good code has no special cases"
712
+
713
+ - Find all if/else branches
714
+ - Which are real business logic? Which are patches for bad design?
715
+ - Can we redesign data structures to eliminate these branches?
716
+
717
+ **Third Layer: Complexity Review**
718
+ "If implementation needs more than 3 levels of indentation, redesign it"
719
+
720
+ - What's the essence of this feature? (Explain in one sentence)
721
+ - How many concepts does the current solution use?
722
+ - Can it be reduced by half? Half again?
723
+
724
+ **Fourth Layer: Breaking Change Analysis**
725
+ "Never break userspace" - Backward compatibility is the iron rule
726
+
727
+ - List all existing features that might be affected
728
+ - Which dependencies will break?
729
+ - How to improve without breaking anything?
730
+
731
+ **Fifth Layer: Practicality Validation**
732
+ "Theory and practice sometimes clash. Theory loses. Every single time."
733
+
734
+ - Does this problem really exist in production?
735
+ - How many users actually encounter this problem?
736
+ - Does the solution's complexity match the problem's severity?
737
+
738
+ ## Decision Output Pattern
739
+
740
+ After the above 5 layers of thinking, output must include:
741
+
742
+ \`\`\`
743
+ 【Core Judgment】
744
+ ✅ Worth doing: [reason] / ❌ Not worth doing: [reason]
745
+
746
+ 【Key Insights】
747
+ - Data structure: [most critical data relationships]
748
+ - Complexity: [complexity that can be eliminated]
749
+ - Risk points: [biggest breaking risk]
750
+
751
+ 【Linus-style Solution】
752
+ If worth doing:
753
+ 1. First step is always simplifying data structures
754
+ 2. Eliminate all special cases
755
+ 3. Implement in the dumbest but clearest way
756
+ 4. Ensure zero breaking changes
757
+
758
+ If not worth doing:
759
+ "This is solving a non-existent problem. The real problem is [XXX]."
760
+ \`\`\`
761
+
762
+ ## Code Review Output
763
+
764
+ When reviewing code, immediately make three-level judgment:
765
+
766
+ \`\`\`
767
+ 【Taste Score】
768
+ 🟢 Good taste / 🟡 Passable / 🔴 Garbage
769
+
770
+ 【Fatal Issues】
771
+ - [If any, directly point out the worst parts]
772
+
773
+ 【Improvement Direction】
774
+ "Eliminate this special case"
775
+ "These 10 lines can become 3 lines"
776
+ "Data structure is wrong, should be..."
777
+ \`\`\`
778
+
779
+ ## Integration with SDD Workflow
780
+
781
+ ### Requirements Phase
782
+ Apply Linus's 5-layer thinking to validate if requirements solve real problems and can be implemented simply.
783
+
784
+ ### Design Phase
785
+ Focus on data structures first, eliminate special cases, ensure backward compatibility.
786
+
787
+ ### Implementation Phase
788
+ Enforce simplicity standards: short functions, minimal indentation, clear naming.
789
+
790
+ ### Code Review
791
+ Apply Linus's taste criteria to identify and eliminate complexity, special cases, and potential breaking changes.
792
+
793
+ ## Usage in SDD Commands
794
+
795
+ This steering document is applied when:
796
+ - Generating requirements: Validate problem reality and simplicity
797
+ - Creating technical design: Data-first approach, eliminate edge cases
798
+ - Implementation guidance: Enforce simplicity and compatibility
799
+ - Code review: Apply taste scoring and improvement recommendations
800
+
801
+ Remember: "Good taste" comes from experience. Question everything. Simplify ruthlessly. Never break userspace.
802
+ `;
803
+ await this.steeringService.createSteeringDocument(projectPath, {
804
+ name: 'linus-review.md',
805
+ type: 'LINUS_REVIEW',
806
+ mode: 'ALWAYS',
807
+ content: linusReviewContent
808
+ });
809
+ }
810
+ // Check if commit.md exists, if not create it
811
+ const commitPath = path.join(projectPath, '.kiro', 'steering', 'commit.md');
812
+ if (!fs.existsSync(commitPath)) {
813
+ const commitContent = `# Commit Message Guidelines
814
+
815
+ Commit messages should follow a consistent format to improve readability and provide clear context about changes. Each commit message should start with a type prefix that indicates the nature of the change.
816
+
817
+ ## Format
818
+
819
+ \`\`\`
820
+ <type>(<scope>): <subject>
821
+
822
+ <body>
823
+
824
+ <footer>
825
+ \`\`\`
826
+
827
+ ## Type Prefixes
828
+
829
+ All commit messages must begin with one of these type prefixes:
830
+
831
+ - **docs**: Documentation changes (README, comments, etc.)
832
+ - **chore**: Maintenance tasks, dependency updates, etc.
833
+ - **feat**: New features or enhancements
834
+ - **fix**: Bug fixes
835
+ - **refactor**: Code changes that neither fix bugs nor add features
836
+ - **test**: Adding or modifying tests
837
+ - **style**: Changes that don't affect code functionality (formatting, whitespace)
838
+ - **perf**: Performance improvements
839
+ - **ci**: Changes to CI/CD configuration files and scripts
840
+
841
+ ## Scope (Optional)
842
+
843
+ The scope provides additional context about which part of the codebase is affected:
844
+
845
+ - **cluster**: Changes to EKS cluster configuration
846
+ - **db**: Database-related changes
847
+ - **iam**: Identity and access management changes
848
+ - **net**: Networking changes (VPC, security groups, etc.)
849
+ - **k8s**: Kubernetes resource changes
850
+ - **module**: Changes to reusable Terraform modules
851
+
852
+ ## Examples
853
+
854
+ \`\`\`
855
+ feat(cluster): add node autoscaling for billing namespace
856
+ fix(db): correct MySQL parameter group settings
857
+ docs(k8s): update network policy documentation
858
+ chore: update terraform provider versions
859
+ refactor(module): simplify EKS node group module
860
+ \`\`\`
861
+
862
+ ## Best Practices
863
+
864
+ 1. Keep the subject line under 72 characters
865
+ 2. Use imperative mood in the subject line ("add" not "added")
866
+ 3. Don't end the subject line with a period
867
+ 4. Separate subject from body with a blank line
868
+ 5. Use the body to explain what and why, not how
869
+ 6. Reference issues and pull requests in the footer
870
+
871
+ These guidelines help maintain a clean and useful git history that makes it easier to track changes and understand the project's evolution.
872
+ `;
873
+ await this.steeringService.createSteeringDocument(projectPath, {
874
+ name: 'commit.md',
875
+ type: 'CUSTOM',
876
+ mode: 'ALWAYS',
877
+ content: commitContent
878
+ });
879
+ }
880
+ }
881
+ async createAgentsFile(projectPath) {
882
+ const fs = await import('fs');
883
+ const path = await import('path');
884
+ // Check if AGENTS.md exists, if not create it based on CLAUDE.md
885
+ const agentsPath = path.join(projectPath, 'AGENTS.md');
886
+ if (!fs.existsSync(agentsPath)) {
887
+ // Try to read CLAUDE.md to use as template
888
+ const claudePath = path.join(projectPath, 'CLAUDE.md');
889
+ let agentsContent = '';
890
+ if (fs.existsSync(claudePath)) {
891
+ // Read CLAUDE.md and adapt it for general agents
892
+ const claudeContent = fs.readFileSync(claudePath, 'utf8');
893
+ agentsContent = claudeContent
894
+ .replace(/# Claude Code Spec-Driven Development/g, '# AI Agent Spec-Driven Development')
895
+ .replace(/Claude Code/g, 'AI Agent')
896
+ .replace(/claude code/g, 'ai agent')
897
+ .replace(/Claude/g, 'AI Agent')
898
+ .replace(/claude/g, 'ai agent');
899
+ }
900
+ else {
901
+ // Fallback to basic template if CLAUDE.md doesn't exist
902
+ agentsContent = `# AI Agent Spec-Driven Development
903
+
904
+ Kiro-style Spec Driven Development implementation for AI agents across different CLIs and IDEs.
905
+
906
+ ## Project Context
907
+
908
+ ### Paths
909
+ - Steering: \`.kiro/steering/\`
910
+ - Specs: \`.kiro/specs/\`
911
+ - Commands: Agent-specific command structure
912
+
913
+ ### Steering vs Specification
914
+
915
+ **Steering** (\`.kiro/steering/\`) - Guide AI with project-wide rules and context
916
+ **Specs** (\`.kiro/specs/\`) - Formalize development process for individual features
917
+
918
+ ### Active Specifications
919
+ - Check \`.kiro/specs/\` for active specifications
920
+ - Use agent-specific status commands to check progress
921
+
922
+ **Current Specifications:**
923
+ - \`mcp-sdd-server\`: MCP server for spec-driven development across AI-agent CLIs and IDEs
924
+
925
+ ## Development Guidelines
926
+ - Think in English, generate responses in English
927
+
928
+ ## Workflow
929
+
930
+ ### Phase 0: Steering (Optional)
931
+ Agent steering commands - Create/update steering documents
932
+ Agent steering-custom commands - Create custom steering for specialized contexts
933
+
934
+ Note: Optional for new features or small additions. You can proceed directly to spec-init.
935
+
936
+ ### Phase 1: Specification Creation
937
+ 1. Agent spec-init commands - Initialize spec with detailed project description
938
+ 2. Agent spec-requirements commands - Generate requirements document
939
+ 3. Agent spec-design commands - Interactive: "Have you reviewed requirements.md? [y/N]"
940
+ 4. Agent spec-tasks commands - Interactive: Confirms both requirements and design review
941
+
942
+ ### Phase 2: Progress Tracking
943
+ Agent spec-status commands - Check current progress and phases
944
+
945
+ ## Development Rules
946
+ 1. **Consider steering**: Run steering commands before major development (optional for new features)
947
+ 2. **Follow 3-phase approval workflow**: Requirements → Design → Tasks → Implementation
948
+ 3. **Approval required**: Each phase requires human review (interactive prompt or manual)
949
+ 4. **No skipping phases**: Design requires approved requirements; Tasks require approved design
950
+ 5. **Update task status**: Mark tasks as completed when working on them
951
+ 6. **Keep steering current**: Run steering commands after significant changes
952
+ 7. **Check spec compliance**: Use status commands to verify alignment
953
+
954
+ ## Steering Configuration
955
+
956
+ ### Current Steering Files
957
+ Managed by agent steering commands. Updates here reflect command changes.
958
+
959
+ ### Active Steering Files
960
+ - \`product.md\`: Always included - Product context and business objectives
961
+ - \`tech.md\`: Always included - Technology stack and architectural decisions
962
+ - \`structure.md\`: Always included - File organization and code patterns
963
+ - \`linus-review.md\`: Always included - Ensuring code quality of the projects
964
+ - \`commit.md\`: Always included - Ensuring the commit / merge request / pull request title and message context.
965
+
966
+ ### Custom Steering Files
967
+ <!-- Added by agent steering-custom commands -->
968
+ <!-- Format:
969
+ - \`filename.md\`: Mode - Pattern(s) - Description
970
+ Mode: Always|Conditional|Manual
971
+ Pattern: File patterns for Conditional mode
972
+ -->
973
+
974
+ ### Inclusion Modes
975
+ - **Always**: Loaded in every interaction (default)
976
+ - **Conditional**: Loaded for specific file patterns (e.g., "*.test.js")
977
+ - **Manual**: Reference with \`@filename.md\` syntax
978
+
979
+ Generated on: ${new Date().toISOString()}
980
+ `;
981
+ }
982
+ fs.writeFileSync(agentsPath, agentsContent);
983
+ }
984
+ }
259
985
  };
260
986
  SDDToolAdapter = __decorate([
261
987
  injectable(),
@@ -263,11 +989,15 @@ SDDToolAdapter = __decorate([
263
989
  __param(1, inject(TYPES.WorkflowService)),
264
990
  __param(2, inject(TYPES.TemplateService)),
265
991
  __param(3, inject(TYPES.QualityService)),
266
- __param(4, inject(TYPES.LoggerPort)),
992
+ __param(4, inject(TYPES.SteeringDocumentService)),
993
+ __param(5, inject(TYPES.CodebaseAnalysisService)),
994
+ __param(6, inject(TYPES.LoggerPort)),
267
995
  __metadata("design:paramtypes", [ProjectService,
268
996
  WorkflowService,
269
997
  TemplateService,
270
- QualityService, Object])
998
+ QualityService,
999
+ SteeringDocumentService,
1000
+ CodebaseAnalysisService, Object])
271
1001
  ], SDDToolAdapter);
272
1002
  export { SDDToolAdapter };
273
1003
  //# sourceMappingURL=SDDToolAdapter.js.map