sdd-mcp-server 2.2.1 → 3.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.
- package/README.md +92 -33
- package/dist/agents/AgentManager.d.ts +61 -0
- package/dist/agents/AgentManager.js +75 -0
- package/dist/agents/AgentManager.js.map +1 -0
- package/dist/agents/index.d.ts +1 -0
- package/dist/agents/index.js +3 -0
- package/dist/agents/index.js.map +1 -0
- package/dist/cli/install-skills.d.ts +52 -9
- package/dist/cli/install-skills.js +324 -72
- package/dist/cli/install-skills.js.map +1 -1
- package/dist/cli/sdd-mcp-cli.js +0 -0
- package/dist/contexts/ContextManager.d.ts +53 -0
- package/dist/contexts/ContextManager.js +64 -0
- package/dist/contexts/ContextManager.js.map +1 -0
- package/dist/contexts/index.d.ts +1 -0
- package/dist/contexts/index.js +3 -0
- package/dist/contexts/index.js.map +1 -0
- package/dist/hooks/HookLoader.d.ts +67 -0
- package/dist/hooks/HookLoader.js +180 -0
- package/dist/hooks/HookLoader.js.map +1 -0
- package/dist/index.js +5 -3
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/di/container.js +24 -0
- package/dist/infrastructure/di/container.js.map +1 -1
- package/dist/infrastructure/di/types.d.ts +4 -0
- package/dist/infrastructure/di/types.js +5 -0
- package/dist/infrastructure/di/types.js.map +1 -1
- package/dist/rules/RulesManager.d.ts +53 -0
- package/dist/rules/RulesManager.js +62 -0
- package/dist/rules/RulesManager.js.map +1 -0
- package/dist/rules/index.d.ts +1 -0
- package/dist/rules/index.js +3 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/shared/BaseManager.d.ts +130 -0
- package/dist/shared/BaseManager.js +274 -0
- package/dist/shared/BaseManager.js.map +1 -0
- package/dist/shared/index.d.ts +1 -0
- package/dist/shared/index.js +3 -0
- package/dist/shared/index.js.map +1 -0
- package/dist/utils/sddPaths.d.ts +69 -0
- package/dist/utils/sddPaths.js +138 -0
- package/dist/utils/sddPaths.js.map +1 -0
- package/documentGenerator.js +1 -1
- package/mcp-server.js +39 -39
- package/package.json +1 -1
- package/skills/sdd-review/SKILL.md +191 -0
- package/skills/sdd-security-check/SKILL.md +193 -0
- 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":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAE7B;;;;GAIG;AACH,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAC/B,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAEtC;;;;GAIG;AACH,SAAS,SAAS,CAAC,OAAe;IAChC,IAAI,CAAC;QACH,OAAO,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,WAAW,EAAE,CAAC;IAC5C,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,UAAU,CAAC,WAAmB;IAC5C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAExD,4BAA4B;IAC5B,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,yCAAyC;IACzC,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED,oCAAoC;IACpC,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAExD,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,OAAO,CAAC;IACjB,CAAC;IAED,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,cAAc,CAAC;IACxB,CAAC;IAED,OAAO,OAAO,CAAC;AACjB,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,YAAY,CAAC,WAAmB;IAC9C,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,OAAO,CAAC,CAAC;AACrD,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,OAAO,IAAI,CAAC,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,UAAU,CAAC,CAAC;AACxD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,kBAAkB,CAAC,WAAmB,EAAE,WAAmB;IACzE,OAAO,IAAI,CAAC,IAAI,CAAC,YAAY,CAAC,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;AAC3D,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB,EAAE,WAAmB;IACtE,OAAO,IAAI,CAAC,IAAI,CAAC,kBAAkB,CAAC,WAAW,EAAE,WAAW,CAAC,EAAE,WAAW,CAAC,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,WAAmB;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;IACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAExD,8BAA8B;IAC9B,IAAI,SAAS,CAAC,QAAQ,CAAC,EAAE,CAAC;QACxB,OAAO,KAAK,CAAC;IACf,CAAC;IAED,oCAAoC;IACpC,OAAO,SAAS,CAAC,QAAQ,CAAC,CAAC;AAC7B,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,aAAa,CAAC,WAAmB;IAC/C,OAAO,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,OAAO,CAAC,CAAC;AACzC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,WAAmB;IACtD,MAAM,OAAO,GAAG,aAAa,CAAC,WAAW,CAAC,CAAC;IAC3C,MAAM,KAAK,GAAG;QACZ,OAAO;QACP,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,OAAO,CAAC;QAC3B,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,UAAU,CAAC;KAC/B,CAAC;IAEF,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;QACtB,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACvC,CAAC;IAED,OAAO,KAAK,CAAC;AACf,CAAC"}
|
package/documentGenerator.js
CHANGED
|
@@ -977,7 +977,7 @@ function generateDeploymentConfig(analysis) {
|
|
|
977
977
|
}
|
|
978
978
|
|
|
979
979
|
function buildDirectoryTree(analysis) {
|
|
980
|
-
let tree = `├── .
|
|
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, ".
|
|
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 .
|
|
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
|
|
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- \`.
|
|
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, ".
|
|
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**: .
|
|
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, ".
|
|
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**: .
|
|
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, ".
|
|
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**: .
|
|
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, ".
|
|
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, ".
|
|
866
|
+
const kiroPath = path.join(currentPath, ".spec");
|
|
867
867
|
|
|
868
|
-
// Check if .
|
|
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, ".
|
|
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, ".
|
|
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, ".
|
|
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, ".
|
|
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: \`.
|
|
1640
|
-
- 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** (\`.
|
|
1646
|
-
**Specs** (\`.
|
|
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 \`.
|
|
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
|
-
- \`.
|
|
2086
|
-
- \`.
|
|
2087
|
-
- \`.
|
|
2088
|
-
- \`.
|
|
2089
|
-
- \`.
|
|
2090
|
-
- \`.
|
|
2091
|
-
- \`.
|
|
2092
|
-
- \`.
|
|
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, ".
|
|
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**: .
|
|
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, ".
|
|
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, ".
|
|
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, ".
|
|
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: .
|
|
2792
|
-
report += `- ✅ Design: .
|
|
2793
|
-
report += `- ✅ Tasks: .
|
|
2794
|
-
report += `- ✅ Metadata: .
|
|
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
|
@@ -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
|
+
```
|