sdd-mcp-server 2.2.1 → 3.0.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 (48) hide show
  1. package/README.md +93 -33
  2. package/dist/agents/AgentManager.d.ts +61 -0
  3. package/dist/agents/AgentManager.js +75 -0
  4. package/dist/agents/AgentManager.js.map +1 -0
  5. package/dist/agents/index.d.ts +1 -0
  6. package/dist/agents/index.js +3 -0
  7. package/dist/agents/index.js.map +1 -0
  8. package/dist/cli/install-skills.d.ts +56 -11
  9. package/dist/cli/install-skills.js +311 -122
  10. package/dist/cli/install-skills.js.map +1 -1
  11. package/dist/cli/sdd-mcp-cli.js +0 -0
  12. package/dist/contexts/ContextManager.d.ts +53 -0
  13. package/dist/contexts/ContextManager.js +64 -0
  14. package/dist/contexts/ContextManager.js.map +1 -0
  15. package/dist/contexts/index.d.ts +1 -0
  16. package/dist/contexts/index.js +3 -0
  17. package/dist/contexts/index.js.map +1 -0
  18. package/dist/hooks/HookLoader.d.ts +67 -0
  19. package/dist/hooks/HookLoader.js +180 -0
  20. package/dist/hooks/HookLoader.js.map +1 -0
  21. package/dist/index.js +5 -3
  22. package/dist/index.js.map +1 -1
  23. package/dist/infrastructure/di/container.js +24 -0
  24. package/dist/infrastructure/di/container.js.map +1 -1
  25. package/dist/infrastructure/di/types.d.ts +4 -0
  26. package/dist/infrastructure/di/types.js +5 -0
  27. package/dist/infrastructure/di/types.js.map +1 -1
  28. package/dist/rules/RulesManager.d.ts +53 -0
  29. package/dist/rules/RulesManager.js +62 -0
  30. package/dist/rules/RulesManager.js.map +1 -0
  31. package/dist/rules/index.d.ts +1 -0
  32. package/dist/rules/index.js +3 -0
  33. package/dist/rules/index.js.map +1 -0
  34. package/dist/shared/BaseManager.d.ts +130 -0
  35. package/dist/shared/BaseManager.js +274 -0
  36. package/dist/shared/BaseManager.js.map +1 -0
  37. package/dist/shared/index.d.ts +1 -0
  38. package/dist/shared/index.js +3 -0
  39. package/dist/shared/index.js.map +1 -0
  40. package/dist/utils/sddPaths.d.ts +69 -0
  41. package/dist/utils/sddPaths.js +138 -0
  42. package/dist/utils/sddPaths.js.map +1 -0
  43. package/documentGenerator.js +1 -1
  44. package/mcp-server.js +39 -39
  45. package/package.json +1 -1
  46. package/skills/sdd-review/SKILL.md +191 -0
  47. package/skills/sdd-security-check/SKILL.md +193 -0
  48. package/skills/sdd-test-gen/SKILL.md +295 -0
@@ -0,0 +1,138 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+ /**
4
+ * SDD directory names
5
+ * .spec is the new standard (v2.1.0+)
6
+ * .kiro is legacy (for backwards compatibility)
7
+ */
8
+ export const SDD_DIR = '.spec';
9
+ export const SDD_DIR_LEGACY = '.kiro';
10
+ /**
11
+ * Check if a directory exists
12
+ * @param dirPath - Directory path to check
13
+ * @returns true if directory exists
14
+ */
15
+ function dirExists(dirPath) {
16
+ try {
17
+ return fs.statSync(dirPath).isDirectory();
18
+ }
19
+ catch {
20
+ return false;
21
+ }
22
+ }
23
+ /**
24
+ * Get the SDD root directory for a project
25
+ * Prefers .spec, falls back to .kiro for legacy projects
26
+ *
27
+ * @param projectPath - Project root path
28
+ * @returns SDD root directory path (.spec or .kiro)
29
+ */
30
+ export function getSddRoot(projectPath) {
31
+ const specPath = path.join(projectPath, SDD_DIR);
32
+ const kiroPath = path.join(projectPath, SDD_DIR_LEGACY);
33
+ // Prefer .spec if it exists
34
+ if (dirExists(specPath)) {
35
+ return specPath;
36
+ }
37
+ // Fall back to .kiro for legacy projects
38
+ if (dirExists(kiroPath)) {
39
+ return kiroPath;
40
+ }
41
+ // Default to .spec for new projects
42
+ return specPath;
43
+ }
44
+ /**
45
+ * Get the SDD directory name for a project
46
+ * Returns the actual directory name used (.spec or .kiro)
47
+ *
48
+ * @param projectPath - Project root path
49
+ * @returns Directory name (.spec or .kiro)
50
+ */
51
+ export function getSddDirName(projectPath) {
52
+ const specPath = path.join(projectPath, SDD_DIR);
53
+ const kiroPath = path.join(projectPath, SDD_DIR_LEGACY);
54
+ if (dirExists(specPath)) {
55
+ return SDD_DIR;
56
+ }
57
+ if (dirExists(kiroPath)) {
58
+ return SDD_DIR_LEGACY;
59
+ }
60
+ return SDD_DIR;
61
+ }
62
+ /**
63
+ * Get the specs directory path
64
+ * @param projectPath - Project root path
65
+ * @returns Specs directory path
66
+ */
67
+ export function getSpecsPath(projectPath) {
68
+ return path.join(getSddRoot(projectPath), 'specs');
69
+ }
70
+ /**
71
+ * Get the steering directory path
72
+ * @param projectPath - Project root path
73
+ * @returns Steering directory path
74
+ */
75
+ export function getSteeringPath(projectPath) {
76
+ return path.join(getSddRoot(projectPath), 'steering');
77
+ }
78
+ /**
79
+ * Get a feature's spec directory path
80
+ * @param projectPath - Project root path
81
+ * @param featureName - Feature name
82
+ * @returns Feature spec directory path
83
+ */
84
+ export function getFeatureSpecPath(projectPath, featureName) {
85
+ return path.join(getSpecsPath(projectPath), featureName);
86
+ }
87
+ /**
88
+ * Get the spec.json file path for a feature
89
+ * @param projectPath - Project root path
90
+ * @param featureName - Feature name
91
+ * @returns spec.json file path
92
+ */
93
+ export function getSpecJsonPath(projectPath, featureName) {
94
+ return path.join(getFeatureSpecPath(projectPath, featureName), 'spec.json');
95
+ }
96
+ /**
97
+ * Check if this is a legacy project (using .kiro instead of .spec)
98
+ * @param projectPath - Project root path
99
+ * @returns true if project uses .kiro
100
+ */
101
+ export function isLegacyProject(projectPath) {
102
+ const specPath = path.join(projectPath, SDD_DIR);
103
+ const kiroPath = path.join(projectPath, SDD_DIR_LEGACY);
104
+ // If .spec exists, not legacy
105
+ if (dirExists(specPath)) {
106
+ return false;
107
+ }
108
+ // If only .kiro exists, it's legacy
109
+ return dirExists(kiroPath);
110
+ }
111
+ /**
112
+ * Get the appropriate SDD directory for new projects
113
+ * Always returns .spec for new projects
114
+ *
115
+ * @param projectPath - Project root path
116
+ * @returns Path to create SDD directory (.spec)
117
+ */
118
+ export function getNewSddRoot(projectPath) {
119
+ return path.join(projectPath, SDD_DIR);
120
+ }
121
+ /**
122
+ * Create all required SDD directories for a new project
123
+ * @param projectPath - Project root path
124
+ * @returns Created paths
125
+ */
126
+ export function createSddDirectories(projectPath) {
127
+ const sddRoot = getNewSddRoot(projectPath);
128
+ const paths = [
129
+ sddRoot,
130
+ path.join(sddRoot, 'specs'),
131
+ path.join(sddRoot, 'steering'),
132
+ ];
133
+ for (const p of paths) {
134
+ fs.mkdirSync(p, { recursive: true });
135
+ }
136
+ return paths;
137
+ }
138
+ //# sourceMappingURL=sddPaths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sddPaths.js","sourceRoot":"","sources":["../../src/utils/sddPaths.ts"],"names":[],"mappings":"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"}
@@ -977,7 +977,7 @@ function generateDeploymentConfig(analysis) {
977
977
  }
978
978
 
979
979
  function buildDirectoryTree(analysis) {
980
- let tree = `├── .kiro/ # SDD workflow files
980
+ let tree = `├── .spec/ # SDD workflow files
981
981
  │ ├── steering/ # Project steering documents
982
982
  │ └── specs/ # Feature specifications\n`;
983
983
 
package/mcp-server.js CHANGED
@@ -58,7 +58,7 @@ const server = new McpServer(
58
58
 
59
59
  // Helper functions for file operations
60
60
  async function createKiroDirectory(projectPath) {
61
- const kiroPath = path.join(projectPath, ".kiro");
61
+ const kiroPath = path.join(projectPath, ".spec");
62
62
  const specsPath = path.join(kiroPath, "specs");
63
63
  const steeringPath = path.join(kiroPath, "steering");
64
64
 
@@ -393,12 +393,12 @@ server.registerTool(
393
393
  }
394
394
 
395
395
  // Proceed with spec creation (either quality is good or answers were provided)
396
- // Create .kiro directory structure in current directory (not in a subdirectory)
396
+ // Create .spec directory structure in current directory (not in a subdirectory)
397
397
  const { specsPath, steeringPath } =
398
398
  await createKiroDirectory(currentPath);
399
399
 
400
400
  // Generate feature name from description
401
- const featureName = await generateFeatureName(description || projectName);
401
+ const featureName = projectName || await generateFeatureName(description);
402
402
  const featurePath = path.join(specsPath, featureName);
403
403
  await fs.mkdir(featurePath, { recursive: true });
404
404
 
@@ -477,7 +477,7 @@ server.registerTool(
477
477
  content: [
478
478
  {
479
479
  type: "text",
480
- text: `## Spec Initialization Complete\n\n**Generated Feature Name**: ${featureName}\n**Project Name**: ${projectName}\n**Project Description**: ${description}${clarificationNote}\n\n**Created Files**:\n- \`.kiro/specs/${featureName}/spec.json\` - Metadata and approval tracking\n- \`.kiro/specs/${featureName}/requirements.md\` - Requirements template with enriched description\n\n**Next Step**: Use \`sdd-requirements ${featureName}\` to generate comprehensive requirements\n\nThe spec has been initialized following stage-by-stage development principles.`,
480
+ text: `## Spec Initialization Complete\n\n**Generated Feature Name**: ${featureName}\n**Project Name**: ${projectName}\n**Project Description**: ${description}${clarificationNote}\n\n**Created Files**:\n- \`.spec/specs/${featureName}/spec.json\` - Metadata and approval tracking\n- \`.spec/specs/${featureName}/requirements.md\` - Requirements template with enriched description\n\n**Next Step**: Use \`sdd-requirements ${featureName}\` to generate comprehensive requirements\n\nThe spec has been initialized following stage-by-stage development principles.`,
481
481
  },
482
482
  ],
483
483
  };
@@ -507,7 +507,7 @@ server.registerTool(
507
507
  async ({ featureName }) => {
508
508
  try {
509
509
  const currentPath = process.cwd();
510
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
510
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
511
511
 
512
512
  // Check if spec exists
513
513
  const specPath = path.join(featurePath, "spec.json");
@@ -558,7 +558,7 @@ server.registerTool(
558
558
  content: [
559
559
  {
560
560
  type: "text",
561
- text: `## Requirements Generated\n\nRequirements document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/requirements.md\n**Status**: Requirements phase completed\n\n**Next Step**: Review the requirements, then use \`sdd-design\` to proceed to design phase`,
561
+ text: `## Requirements Generated\n\nRequirements document generated for feature: **${featureName}**\n\n**Generated**: .spec/specs/${featureName}/requirements.md\n**Status**: Requirements phase completed\n\n**Next Step**: Review the requirements, then use \`sdd-design\` to proceed to design phase`,
562
562
  },
563
563
  ],
564
564
  };
@@ -588,7 +588,7 @@ server.registerTool(
588
588
  async ({ featureName }) => {
589
589
  try {
590
590
  const currentPath = process.cwd();
591
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
591
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
592
592
  const specPath = path.join(featurePath, "spec.json");
593
593
 
594
594
  // Read and validate spec
@@ -640,7 +640,7 @@ server.registerTool(
640
640
  content: [
641
641
  {
642
642
  type: "text",
643
- text: `## Design Generated\n\nTechnical design document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/design.md\n**Status**: Design phase completed\n\n**Next Step**: Review the design document, then use \`sdd-tasks\` to proceed to task planning phase`,
643
+ text: `## Design Generated\n\nTechnical design document generated for feature: **${featureName}**\n\n**Generated**: .spec/specs/${featureName}/design.md\n**Status**: Design phase completed\n\n**Next Step**: Review the design document, then use \`sdd-tasks\` to proceed to task planning phase`,
644
644
  },
645
645
  ],
646
646
  };
@@ -670,7 +670,7 @@ server.registerTool(
670
670
  async ({ featureName }) => {
671
671
  try {
672
672
  const currentPath = process.cwd();
673
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
673
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
674
674
  const specPath = path.join(featurePath, "spec.json");
675
675
 
676
676
  // Read and validate spec
@@ -778,7 +778,7 @@ ${designContext.substring(0, 1000)}${designContext.length > 1000 ? "...\n[Design
778
778
  content: [
779
779
  {
780
780
  type: "text",
781
- text: `## Implementation Tasks Generated\n\nImplementation tasks document generated for feature: **${featureName}**\n\n**Generated**: .kiro/specs/${featureName}/tasks.md\n**Status**: Tasks phase completed\n**Ready for Implementation**: Yes\n\n**Next Step**: Review tasks, then use \`sdd-implement\` to begin implementation or \`sdd-status\` to check progress`,
781
+ text: `## Implementation Tasks Generated\n\nImplementation tasks document generated for feature: **${featureName}**\n\n**Generated**: .spec/specs/${featureName}/tasks.md\n**Status**: Tasks phase completed\n**Ready for Implementation**: Yes\n\n**Next Step**: Review tasks, then use \`sdd-implement\` to begin implementation or \`sdd-status\` to check progress`,
782
782
  },
783
783
  ],
784
784
  };
@@ -808,7 +808,7 @@ server.registerTool(
808
808
  async ({ featureName }) => {
809
809
  try {
810
810
  const currentPath = process.cwd();
811
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
811
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
812
812
  const specPath = path.join(featurePath, "spec.json");
813
813
 
814
814
  // Read spec
@@ -863,9 +863,9 @@ server.registerTool(
863
863
  async ({ featureName }) => {
864
864
  try {
865
865
  const currentPath = process.cwd();
866
- const kiroPath = path.join(currentPath, ".kiro");
866
+ const kiroPath = path.join(currentPath, ".spec");
867
867
 
868
- // Check if .kiro directory exists
868
+ // Check if .spec directory exists
869
869
  const kiroExists = await fs
870
870
  .access(kiroPath)
871
871
  .then(() => true)
@@ -1013,7 +1013,7 @@ server.registerTool(
1013
1013
  async ({ featureName, phase }) => {
1014
1014
  try {
1015
1015
  const currentPath = process.cwd();
1016
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
1016
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
1017
1017
  const specPath = path.join(featurePath, "spec.json");
1018
1018
 
1019
1019
  // Read spec
@@ -1165,7 +1165,7 @@ server.registerTool(
1165
1165
  async ({ featureName }) => {
1166
1166
  try {
1167
1167
  const currentPath = process.cwd();
1168
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
1168
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
1169
1169
 
1170
1170
  // Load all context files
1171
1171
  const files = ["spec.json", "requirements.md", "design.md", "tasks.md"];
@@ -1252,7 +1252,7 @@ server.registerTool(
1252
1252
  async ({ templateType, featureName, customTemplate }) => {
1253
1253
  try {
1254
1254
  const currentPath = process.cwd();
1255
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
1255
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
1256
1256
  const specPath = path.join(featurePath, "spec.json");
1257
1257
 
1258
1258
  // Load spec for context
@@ -1335,7 +1335,7 @@ server.registerTool(
1335
1335
  async ({ updateMode }) => {
1336
1336
  try {
1337
1337
  const currentPath = process.cwd();
1338
- const steeringPath = path.join(currentPath, ".kiro", "steering");
1338
+ const steeringPath = path.join(currentPath, ".spec", "steering");
1339
1339
 
1340
1340
  // Create steering directory if it doesn't exist
1341
1341
  await fs.mkdir(steeringPath, { recursive: true });
@@ -1636,17 +1636,17 @@ Kiro-style Spec Driven Development implementation using ai agent slash commands,
1636
1636
  ## Project Context
1637
1637
 
1638
1638
  ### Paths
1639
- - Steering: \`.kiro/steering/\`
1640
- - Specs: \`.kiro/specs/\`
1639
+ - Steering: \`.spec/steering/\`
1640
+ - Specs: \`.spec/specs/\`
1641
1641
  - Commands: \`.ai agent/commands/\`
1642
1642
 
1643
1643
  ### Steering vs Specification
1644
1644
 
1645
- **Steering** (\`.kiro/steering/\`) - Guide AI with project-wide rules and context
1646
- **Specs** (\`.kiro/specs/\`) - Formalize development process for individual features
1645
+ **Steering** (\`.spec/steering/\`) - Guide AI with project-wide rules and context
1646
+ **Specs** (\`.spec/specs/\`) - Formalize development process for individual features
1647
1647
 
1648
1648
  ### Active Specifications
1649
- - Check \`.kiro/specs/\` for active specifications
1649
+ - Check \`.spec/specs/\` for active specifications
1650
1650
  - Use \`/kiro:spec-status [feature-name]\` to check progress
1651
1651
 
1652
1652
  **Current Specifications:**
@@ -2082,14 +2082,14 @@ Refer to full principles.md for detailed examples and language-specific guidance
2082
2082
  **Generated**: ${new Date().toISOString()}
2083
2083
 
2084
2084
  **${mode} Files**:
2085
- - \`.kiro/steering/product.md\` - Product overview and business context (AI analysis template)
2086
- - \`.kiro/steering/tech.md\` - Technology stack and development environment (AI analysis template)
2087
- - \`.kiro/steering/structure.md\` - Project organization and architectural decisions (AI analysis template)
2088
- - \`.kiro/steering/linus-review.md\` - Code review guidelines (full content)
2089
- - \`.kiro/steering/commit.md\` - Commit message standards (full content)
2090
- - \`.kiro/steering/tdd-guideline.md\` - Test-Driven Development practices and workflow (full content)
2091
- - \`.kiro/steering/security-check.md\` - Security checklist aligned to OWASP Top 10 (full content)
2092
- - \`.kiro/steering/AGENTS.md\` - Universal AI agent workflow guidance
2085
+ - \`.spec/steering/product.md\` - Product overview and business context (AI analysis template)
2086
+ - \`.spec/steering/tech.md\` - Technology stack and development environment (AI analysis template)
2087
+ - \`.spec/steering/structure.md\` - Project organization and architectural decisions (AI analysis template)
2088
+ - \`.spec/steering/linus-review.md\` - Code review guidelines (full content)
2089
+ - \`.spec/steering/commit.md\` - Commit message standards (full content)
2090
+ - \`.spec/steering/tdd-guideline.md\` - Test-Driven Development practices and workflow (full content)
2091
+ - \`.spec/steering/security-check.md\` - Security checklist aligned to OWASP Top 10 (full content)
2092
+ - \`.spec/steering/AGENTS.md\` - Universal AI agent workflow guidance
2093
2093
 
2094
2094
  **AI-Driven Approach**:
2095
2095
  The steering documents now contain analysis instructions for AI agents rather than hardcoded templates. This ensures:
@@ -2150,7 +2150,7 @@ server.registerTool(
2150
2150
  async ({ fileName, topic, inclusionMode, filePattern }) => {
2151
2151
  try {
2152
2152
  const currentPath = process.cwd();
2153
- const steeringPath = path.join(currentPath, ".kiro", "steering");
2153
+ const steeringPath = path.join(currentPath, ".spec", "steering");
2154
2154
 
2155
2155
  // Create steering directory if it doesn't exist
2156
2156
  await fs.mkdir(steeringPath, { recursive: true });
@@ -2230,7 +2230,7 @@ ${
2230
2230
  type: "text",
2231
2231
  text: `## Custom Steering Document Created
2232
2232
 
2233
- **File**: .kiro/steering/${fileName}
2233
+ **File**: .spec/steering/${fileName}
2234
2234
  **Topic**: ${topic}
2235
2235
  **Inclusion Mode**: ${inclusionMode}${inclusionMode === "conditional" ? ` (Pattern: "${filePattern}")` : ""}
2236
2236
 
@@ -2273,7 +2273,7 @@ server.registerTool(
2273
2273
  async ({ featureName }) => {
2274
2274
  try {
2275
2275
  const currentPath = process.cwd();
2276
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
2276
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
2277
2277
  const designPath = path.join(featurePath, "design.md");
2278
2278
  const specPath = path.join(featurePath, "spec.json");
2279
2279
 
@@ -2444,7 +2444,7 @@ server.registerTool(
2444
2444
  async ({ featureName }) => {
2445
2445
  try {
2446
2446
  const currentPath = process.cwd();
2447
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
2447
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
2448
2448
  const requirementsPath = path.join(featurePath, "requirements.md");
2449
2449
  const specPath = path.join(featurePath, "spec.json");
2450
2450
 
@@ -2664,7 +2664,7 @@ server.registerTool(
2664
2664
  async ({ featureName, taskNumbers }) => {
2665
2665
  try {
2666
2666
  const currentPath = process.cwd();
2667
- const featurePath = path.join(currentPath, ".kiro", "specs", featureName);
2667
+ const featurePath = path.join(currentPath, ".spec", "specs", featureName);
2668
2668
  const tasksPath = path.join(featurePath, "tasks.md");
2669
2669
  const requirementsPath = path.join(featurePath, "requirements.md");
2670
2670
  const designPath = path.join(featurePath, "design.md");
@@ -2788,10 +2788,10 @@ server.registerTool(
2788
2788
  report += `**TDD Methodology**: Kent Beck's Red → Green → Refactor cycle\n\n`;
2789
2789
 
2790
2790
  report += `### Context Loaded\n`;
2791
- report += `- ✅ Requirements: .kiro/specs/${featureName}/requirements.md\n`;
2792
- report += `- ✅ Design: .kiro/specs/${featureName}/design.md\n`;
2793
- report += `- ✅ Tasks: .kiro/specs/${featureName}/tasks.md\n`;
2794
- report += `- ✅ Metadata: .kiro/specs/${featureName}/spec.json\n\n`;
2791
+ report += `- ✅ Requirements: .spec/specs/${featureName}/requirements.md\n`;
2792
+ report += `- ✅ Design: .spec/specs/${featureName}/design.md\n`;
2793
+ report += `- ✅ Tasks: .spec/specs/${featureName}/tasks.md\n`;
2794
+ report += `- ✅ Metadata: .spec/specs/${featureName}/spec.json\n\n`;
2795
2795
 
2796
2796
  report += `### TDD Implementation Plan\n\n`;
2797
2797
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "sdd-mcp-server",
3
- "version": "2.2.1",
3
+ "version": "3.0.1",
4
4
  "description": "MCP server for spec-driven development workflows across AI-agent CLIs and IDEs",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -0,0 +1,191 @@
1
+ ---
2
+ name: sdd-review
3
+ description: Perform thorough Linus-style code review focusing on correctness, maintainability, and adherence to project conventions. Use after completing implementation to ensure code quality. Invoked via /sdd-review [file-path or PR-number].
4
+ ---
5
+
6
+ # SDD Code Review
7
+
8
+ Perform comprehensive code reviews in the style of Linus Torvalds - direct, thorough, and focused on what matters: correctness, simplicity, and long-term maintainability.
9
+
10
+ ## Review Philosophy
11
+
12
+ > "Talk is cheap. Show me the code."
13
+ > — Linus Torvalds
14
+
15
+ This review focuses on:
16
+ 1. **Correctness** - Does it actually work? Does it handle edge cases?
17
+ 2. **Simplicity** - Is it more complex than necessary?
18
+ 3. **Maintainability** - Will future developers understand this?
19
+ 4. **Convention Adherence** - Does it follow project patterns?
20
+
21
+ ## Workflow
22
+
23
+ ### Step 1: Identify Review Scope
24
+
25
+ Determine what to review:
26
+ - **Single file**: `/sdd-review src/services/UserService.ts`
27
+ - **Directory**: `/sdd-review src/services/`
28
+ - **Git diff**: `/sdd-review HEAD~3..HEAD`
29
+ - **PR/MR**: `/sdd-review PR-123` or `/sdd-review MR-45`
30
+
31
+ ### Step 2: Load Project Context
32
+
33
+ Before reviewing:
34
+ 1. Read project steering documents from `.spec/steering/`
35
+ 2. Understand existing patterns in the codebase
36
+ 3. Check if there's a related spec in `.spec/specs/`
37
+
38
+ ### Step 3: Perform Review
39
+
40
+ #### Code Correctness Checks
41
+
42
+ ```markdown
43
+ ## Correctness Issues
44
+
45
+ ### Critical
46
+ - [ ] Logic errors that will cause bugs
47
+ - [ ] Race conditions or threading issues
48
+ - [ ] Resource leaks (files, connections, memory)
49
+ - [ ] Unhandled error conditions
50
+
51
+ ### Important
52
+ - [ ] Edge cases not handled
53
+ - [ ] Assumptions that may not hold
54
+ - [ ] Off-by-one errors
55
+ - [ ] Type mismatches or unsafe casts
56
+ ```
57
+
58
+ #### Simplicity Assessment
59
+
60
+ Ask these questions:
61
+ - Could this be done with less code?
62
+ - Is there a standard library function for this?
63
+ - Is this abstraction earning its keep?
64
+ - Would a junior developer understand this in 6 months?
65
+
66
+ #### Pattern Violations
67
+
68
+ Check against project conventions:
69
+ ```markdown
70
+ ## Pattern Violations
71
+
72
+ ### Naming
73
+ - [ ] Variables don't follow naming convention
74
+ - [ ] Functions named for implementation, not purpose
75
+
76
+ ### Structure
77
+ - [ ] Logic in wrong layer (controller doing business logic)
78
+ - [ ] Missing separation of concerns
79
+ - [ ] Circular dependencies introduced
80
+
81
+ ### Error Handling
82
+ - [ ] Swallowed exceptions
83
+ - [ ] Generic error messages
84
+ - [ ] Missing error propagation
85
+ ```
86
+
87
+ ### Step 4: Provide Feedback
88
+
89
+ Structure feedback with clear categories:
90
+
91
+ ```markdown
92
+ # Code Review: {file/PR description}
93
+
94
+ ## Summary
95
+ Brief overall assessment (1-2 sentences)
96
+
97
+ ## 🚨 Must Fix (Blocking)
98
+ Issues that must be resolved before merge:
99
+ 1. **Line 42**: Memory leak - connection never closed
100
+ ```diff
101
+ - const conn = await getConnection();
102
+ + const conn = await getConnection();
103
+ + try { ... } finally { conn.close(); }
104
+ ```
105
+
106
+ ## ⚠️ Should Fix (Non-blocking)
107
+ Issues that should be addressed but won't block:
108
+ 1. **Line 78**: Magic number should be a named constant
109
+ 2. **Line 103**: Consider extracting this to a helper function
110
+
111
+ ## 💡 Suggestions (Optional)
112
+ Improvements that would be nice but are truly optional:
113
+ 1. **Line 156**: This could be simplified with `Array.flatMap()`
114
+
115
+ ## ✅ What's Good
116
+ Acknowledge good patterns to reinforce them:
117
+ 1. Good use of dependency injection
118
+ 2. Clear separation of concerns
119
+ 3. Comprehensive error handling in auth module
120
+ ```
121
+
122
+ ### Step 5: Verify Tests
123
+
124
+ For any code changes:
125
+ 1. Check if tests exist for modified code
126
+ 2. Verify edge cases are tested
127
+ 3. Run existing tests to ensure no regressions
128
+
129
+ ```bash
130
+ # Run tests for affected files
131
+ npm test -- --findRelatedTests {changed-files}
132
+ ```
133
+
134
+ ## Review Severity Levels
135
+
136
+ | Level | Meaning | Action Required |
137
+ |-------|---------|-----------------|
138
+ | 🚨 **Critical** | Bug, security issue, data loss risk | Must fix before merge |
139
+ | ⚠️ **Warning** | Code smell, potential issue | Should fix, discuss if disagree |
140
+ | 💡 **Info** | Suggestion, style preference | Optional, author's choice |
141
+
142
+ ## Common Issues to Watch For
143
+
144
+ ### TypeScript/JavaScript Specific
145
+ - `any` type usage without justification
146
+ - Missing null/undefined checks
147
+ - Promises not awaited
148
+ - Event listener memory leaks
149
+ - Mutable shared state
150
+
151
+ ### General
152
+ - Functions doing too much
153
+ - Deep nesting (> 3 levels)
154
+ - Boolean parameters (use options object)
155
+ - Comments explaining *what* instead of *why*
156
+ - Dead code or unused imports
157
+
158
+ ## Integration with SDD Workflow
159
+
160
+ When reviewing implementation:
161
+ 1. Compare against requirements in `.spec/specs/{feature}/requirements.md`
162
+ 2. Verify design patterns from `.spec/specs/{feature}/design.md`
163
+ 3. Check task completion against `.spec/specs/{feature}/tasks.md`
164
+
165
+ ## Example Review
166
+
167
+ ```markdown
168
+ # Code Review: UserAuthService.ts
169
+
170
+ ## Summary
171
+ Good overall structure but has a critical security issue and some error handling gaps.
172
+
173
+ ## 🚨 Must Fix
174
+ 1. **Line 67**: Password stored in plain text in error log
175
+ ```typescript
176
+ // BAD: Leaks credentials
177
+ logger.error(`Login failed for ${email} with password ${password}`);
178
+
179
+ // GOOD: Never log credentials
180
+ logger.error(`Login failed for ${email}`);
181
+ ```
182
+
183
+ ## ⚠️ Should Fix
184
+ 1. **Line 89**: Catch block swallows all errors
185
+ 2. **Line 112-130**: This block should be extracted to a private method
186
+
187
+ ## ✅ What's Good
188
+ - Clean separation between auth logic and data access
189
+ - Good use of TypeScript discriminated unions for auth result
190
+ - Comprehensive input validation
191
+ ```