sdd-mcp-server 3.5.1 → 5.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (124) hide show
  1. package/README.md +92 -683
  2. package/agents/architect.md +15 -93
  3. package/agents/implementer.md +16 -141
  4. package/agents/planner.md +16 -84
  5. package/agents/reviewer.md +16 -239
  6. package/agents/security-auditor.md +16 -114
  7. package/agents/tdd-guide.md +17 -228
  8. package/dist/adapters/cli/SDDToolAdapter.d.ts +14 -8
  9. package/dist/adapters/cli/SDDToolAdapter.js +188 -405
  10. package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
  11. package/dist/application/services/ContextCompactionService.d.ts +88 -16
  12. package/dist/application/services/ContextCompactionService.js +474 -187
  13. package/dist/application/services/ContextCompactionService.js.map +1 -1
  14. package/dist/application/services/ProjectService.js +3 -3
  15. package/dist/application/services/ProjectService.js.map +1 -1
  16. package/dist/application/services/SpecPathResolver.d.ts +24 -0
  17. package/dist/application/services/SpecPathResolver.js +70 -0
  18. package/dist/application/services/SpecPathResolver.js.map +1 -0
  19. package/dist/application/services/WorkflowEngineService.d.ts +214 -50
  20. package/dist/application/services/WorkflowEngineService.js +1447 -292
  21. package/dist/application/services/WorkflowEngineService.js.map +1 -1
  22. package/dist/application/services/WorkflowErrors.d.ts +16 -0
  23. package/dist/application/services/WorkflowErrors.js +53 -0
  24. package/dist/application/services/WorkflowErrors.js.map +1 -0
  25. package/dist/application/services/WorkflowValidationService.d.ts +25 -46
  26. package/dist/application/services/WorkflowValidationService.js +284 -627
  27. package/dist/application/services/WorkflowValidationService.js.map +1 -1
  28. package/dist/cli/install-skills.d.ts +3 -9
  29. package/dist/cli/install-skills.js +129 -174
  30. package/dist/cli/install-skills.js.map +1 -1
  31. package/dist/cli/install-target.d.ts +42 -8
  32. package/dist/cli/install-target.js +27 -9
  33. package/dist/cli/install-target.js.map +1 -1
  34. package/dist/cli/sdd-mcp-cli.d.ts +1 -1
  35. package/dist/cli/sdd-mcp-cli.js +7 -6
  36. package/dist/cli/sdd-mcp-cli.js.map +1 -1
  37. package/dist/cli/tool-support/claude-code.js +17 -34
  38. package/dist/cli/tool-support/claude-code.js.map +1 -1
  39. package/dist/cli/tool-support/codex.d.ts +0 -53
  40. package/dist/cli/tool-support/codex.js +10 -94
  41. package/dist/cli/tool-support/codex.js.map +1 -1
  42. package/dist/cli/tool-support/index.d.ts +3 -2
  43. package/dist/cli/tool-support/index.js +3 -1
  44. package/dist/cli/tool-support/index.js.map +1 -1
  45. package/dist/cli/tool-support/mcp-registration.d.ts +22 -0
  46. package/dist/cli/tool-support/mcp-registration.js +275 -0
  47. package/dist/cli/tool-support/mcp-registration.js.map +1 -0
  48. package/dist/cli/tool-support/omp.d.ts +5 -0
  49. package/dist/cli/tool-support/omp.js +47 -0
  50. package/dist/cli/tool-support/omp.js.map +1 -0
  51. package/dist/cli/tool-support/root-guidance.d.ts +2 -9
  52. package/dist/cli/tool-support/root-guidance.js +44 -37
  53. package/dist/cli/tool-support/root-guidance.js.map +1 -1
  54. package/dist/cli/tool-support/target-agent-renderer.d.ts +1 -0
  55. package/dist/cli/tool-support/target-agent-renderer.js +37 -4
  56. package/dist/cli/tool-support/target-agent-renderer.js.map +1 -1
  57. package/dist/cli/tool-support/target-installer.d.ts +9 -3
  58. package/dist/cli/tool-support/target-installer.js +100 -26
  59. package/dist/cli/tool-support/target-installer.js.map +1 -1
  60. package/dist/cli/utils/preserving-writer.d.ts +56 -0
  61. package/dist/cli/utils/preserving-writer.js +603 -10
  62. package/dist/cli/utils/preserving-writer.js.map +1 -1
  63. package/dist/domain/ports.d.ts +4 -0
  64. package/dist/domain/types.d.ts +52 -7
  65. package/dist/domain/types.js +5 -4
  66. package/dist/domain/types.js.map +1 -1
  67. package/dist/index.d.ts +13 -10
  68. package/dist/index.js +16 -1199
  69. package/dist/index.js.map +1 -1
  70. package/dist/infrastructure/adapters/NodeFileSystemAdapter.d.ts +3 -0
  71. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js +10 -0
  72. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js.map +1 -1
  73. package/dist/infrastructure/mcp/CapabilityNegotiator.js +3 -3
  74. package/dist/infrastructure/mcp/CapabilityNegotiator.js.map +1 -1
  75. package/dist/infrastructure/mcp/MCPServer.js +13 -13
  76. package/dist/infrastructure/mcp/MCPServer.js.map +1 -1
  77. package/dist/infrastructure/mcp/ToolRegistry.d.ts +5 -1
  78. package/dist/infrastructure/mcp/ToolRegistry.js +11 -4
  79. package/dist/infrastructure/mcp/ToolRegistry.js.map +1 -1
  80. package/dist/infrastructure/mcp/sddToolDefinitions.d.ts +6 -0
  81. package/dist/infrastructure/mcp/sddToolDefinitions.js +110 -0
  82. package/dist/infrastructure/mcp/sddToolDefinitions.js.map +1 -0
  83. package/dist/infrastructure/schemas/project.schema.d.ts +2 -2
  84. package/dist/infrastructure/schemas/project.schema.js +2 -2
  85. package/dist/infrastructure/schemas/project.schema.js.map +1 -1
  86. package/dist/shared/version.d.ts +3 -0
  87. package/dist/shared/version.js +4 -0
  88. package/dist/shared/version.js.map +1 -0
  89. package/dist/utils/atomicWrite.d.ts +8 -35
  90. package/dist/utils/atomicWrite.js +24 -57
  91. package/dist/utils/atomicWrite.js.map +1 -1
  92. package/dist/utils/withFilesystemLock.d.ts +22 -0
  93. package/dist/utils/withFilesystemLock.js +219 -0
  94. package/dist/utils/withFilesystemLock.js.map +1 -0
  95. package/mcp-server.js +5 -2883
  96. package/package.json +8 -3
  97. package/scripts/context-usage-report.mjs +602 -0
  98. package/sdd-entry.js +17 -6
  99. package/skills/sdd-commit/REFERENCE.md +31 -0
  100. package/skills/sdd-commit/SKILL.md +17 -273
  101. package/skills/sdd-design/REFERENCE.md +51 -0
  102. package/skills/sdd-design/SKILL.md +25 -262
  103. package/skills/sdd-implement/REFERENCE.md +30 -0
  104. package/skills/sdd-implement/SKILL.md +27 -284
  105. package/skills/sdd-requirements/REFERENCE.md +39 -0
  106. package/skills/sdd-requirements/SKILL.md +28 -132
  107. package/skills/sdd-review/REFERENCE.md +26 -0
  108. package/skills/sdd-review/SKILL.md +17 -181
  109. package/skills/sdd-security-check/REFERENCE.md +19 -0
  110. package/skills/sdd-security-check/SKILL.md +18 -184
  111. package/skills/sdd-steering/REFERENCE.md +25 -0
  112. package/skills/sdd-steering/SKILL.md +18 -216
  113. package/skills/sdd-steering-custom/REFERENCE.md +27 -0
  114. package/skills/sdd-steering-custom/SKILL.md +19 -203
  115. package/skills/sdd-tasks/REFERENCE.md +25 -0
  116. package/skills/sdd-tasks/SKILL.md +27 -244
  117. package/skills/sdd-test-gen/REFERENCE.md +15 -0
  118. package/skills/sdd-test-gen/SKILL.md +17 -287
  119. package/skills/simple-task/REFERENCE.md +22 -0
  120. package/skills/simple-task/SKILL.md +17 -138
  121. package/templates/CLAUDE.md +13 -31
  122. package/templates/codex-AGENTS.md +7 -9
  123. package/rules/git-workflow.md +0 -92
  124. package/rules/sdd-workflow.md +0 -116
@@ -13,434 +13,163 @@ var __param = (this && this.__param) || function (paramIndex, decorator) {
13
13
  };
14
14
  import { injectable, inject } from "inversify";
15
15
  import { TYPES } from "../../infrastructure/di/types.js";
16
- import { ProjectService } from "../../application/services/ProjectService.js";
17
- import { WorkflowService } from "../../application/services/WorkflowService.js";
18
16
  import { TemplateService } from "../../application/services/TemplateService.js";
19
17
  import { QualityService } from "../../application/services/QualityService.js";
20
18
  import { SteeringDocumentService } from "../../application/services/SteeringDocumentService.js";
21
19
  import { CodebaseAnalysisService } from "../../application/services/CodebaseAnalysisService.js";
22
20
  import { RequirementsClarificationService } from "../../application/services/RequirementsClarificationService.js";
23
- import { ContextCompactionService } from "../../application/services/ContextCompactionService.js";
24
- import { WorkflowPhase } from "../../domain/types.js";
21
+ import { WorkflowEngineService } from "../../application/services/WorkflowEngineService.js";
22
+ import { GovernanceError } from "../../application/services/WorkflowErrors.js";
25
23
  import { ensureStaticSteeringDocuments } from "../../application/services/staticSteering.js";
24
+ import { SDD_TOOL_DEFINITIONS, SDD_TOOL_NAMES, } from "../../infrastructure/mcp/sddToolDefinitions.js";
25
+ export { SDD_TOOL_NAMES };
26
26
  let SDDToolAdapter = class SDDToolAdapter {
27
- projectService;
28
- workflowService;
29
27
  templateService;
30
28
  qualityService;
31
29
  steeringService;
32
30
  codebaseAnalysisService;
33
31
  clarificationService;
34
- contextCompactionService;
32
+ workflowEngineService;
35
33
  logger;
36
- constructor(projectService, workflowService, templateService, qualityService, steeringService, codebaseAnalysisService, clarificationService, contextCompactionService, logger) {
37
- this.projectService = projectService;
38
- this.workflowService = workflowService;
34
+ constructor(templateService, qualityService, steeringService, codebaseAnalysisService, clarificationService, workflowEngineService, logger) {
39
35
  this.templateService = templateService;
40
36
  this.qualityService = qualityService;
41
37
  this.steeringService = steeringService;
42
38
  this.codebaseAnalysisService = codebaseAnalysisService;
43
39
  this.clarificationService = clarificationService;
44
- this.contextCompactionService = contextCompactionService;
40
+ this.workflowEngineService = workflowEngineService;
45
41
  this.logger = logger;
46
42
  }
47
43
  getSDDTools() {
48
- return [
49
- {
50
- name: "sdd-init",
51
- tool: {
52
- name: "sdd-init",
53
- description: "Initialize a new SDD project with interactive requirements clarification",
54
- inputSchema: {
55
- type: "object",
56
- properties: {
57
- projectName: {
58
- type: "string",
59
- description: "The name of the project to initialize",
60
- },
61
- description: {
62
- type: "string",
63
- description: "Project description",
64
- },
65
- clarificationAnswers: {
66
- type: "object",
67
- description: "Answers to clarification questions (second pass)",
68
- additionalProperties: { type: "string" },
69
- },
70
- reviewTestCases: {
71
- type: "boolean",
72
- description: "Enable an optional checkpoint requiring TDD test-case review before implementation",
73
- },
74
- },
75
- required: ["projectName"],
76
- },
77
- },
78
- handler: this.handleProjectInit.bind(this),
79
- },
80
- {
81
- name: "sdd-status",
82
- tool: {
83
- name: "sdd-status",
84
- description: "Get current project status and workflow phase information",
85
- inputSchema: {
86
- type: "object",
87
- properties: {
88
- projectId: { type: "string", description: "Project ID" },
89
- projectPath: {
90
- type: "string",
91
- description: "Project path (alternative to ID)",
92
- },
93
- },
94
- },
95
- },
96
- handler: this.handleProjectStatus.bind(this),
97
- },
98
- {
99
- name: "sdd-requirements",
100
- tool: {
101
- name: "sdd-requirements",
102
- description: "Generate requirements doc",
103
- inputSchema: {
104
- type: "object",
105
- properties: {
106
- projectId: { type: "string", description: "Project ID" },
107
- },
108
- required: ["projectId"],
109
- },
110
- },
111
- handler: this.handleRequirements.bind(this),
112
- },
113
- {
114
- name: "sdd-design",
115
- tool: {
116
- name: "sdd-design",
117
- description: "Create design specifications",
118
- inputSchema: {
119
- type: "object",
120
- properties: {
121
- projectId: { type: "string", description: "Project ID" },
122
- },
123
- required: ["projectId"],
124
- },
125
- },
126
- handler: this.handleDesign.bind(this),
127
- },
128
- {
129
- name: "sdd-tasks",
130
- tool: {
131
- name: "sdd-tasks",
132
- description: "Generate task breakdown",
133
- inputSchema: {
134
- type: "object",
135
- properties: {
136
- projectId: { type: "string", description: "Project ID" },
137
- reviewTestCases: {
138
- type: "boolean",
139
- description: "When true, require an explicit TDD test-case review checkpoint before implementation",
140
- },
141
- },
142
- required: ["projectId"],
143
- },
144
- },
145
- handler: this.handleTasks.bind(this),
146
- },
147
- {
148
- name: "sdd-review-test-cases",
149
- tool: {
150
- name: "sdd-review-test-cases",
151
- description: "Mark the optional TDD test-case review checkpoint as reviewed",
152
- inputSchema: {
153
- type: "object",
154
- properties: {
155
- projectId: { type: "string", description: "Project ID" },
156
- },
157
- required: ["projectId"],
158
- },
159
- },
160
- handler: this.handleReviewTestCases.bind(this),
161
- },
162
- {
163
- name: "sdd-quality-check",
164
- tool: {
165
- name: "sdd-quality-check",
166
- description: "Perform Linus-style code quality analysis",
167
- inputSchema: {
168
- type: "object",
169
- properties: {
170
- code: { type: "string", description: "Code to analyze" },
171
- language: { type: "string", description: "Programming language" },
172
- },
173
- required: ["code"],
174
- },
175
- },
176
- handler: this.handleQualityCheck.bind(this),
177
- },
178
- {
179
- name: "sdd-context-load",
180
- tool: {
181
- name: "sdd-context-load",
182
- description: "Load compact workflow handoff context by default; use mode=full only when necessary",
183
- inputSchema: {
184
- type: "object",
185
- properties: {
186
- projectId: { type: "string", description: "Project ID" },
187
- mode: {
188
- type: "string",
189
- enum: ["compact", "standard", "full"],
190
- description: "Context size mode. compact is default and uses handoff.md.",
191
- },
192
- },
193
- required: ["projectId"],
194
- },
195
- },
196
- handler: this.handleContextLoad.bind(this),
197
- },
198
- {
199
- name: "sdd-steering",
200
- tool: {
201
- name: "sdd-steering",
202
- description: "Create/update steering documents with project-specific analysis",
203
- inputSchema: {
204
- type: "object",
205
- properties: {
206
- updateMode: {
207
- type: "string",
208
- enum: ["create", "update"],
209
- description: "Whether to create new or update existing documents",
210
- },
211
- },
212
- },
213
- },
214
- handler: this.handleSteering.bind(this),
215
- },
216
- {
217
- name: "sdd-steering-custom",
218
- tool: {
219
- name: "sdd-steering-custom",
220
- description: "Create custom steering documents for specialized contexts",
221
- inputSchema: {
222
- type: "object",
223
- properties: {
224
- fileName: {
225
- type: "string",
226
- description: "Filename for the custom steering document",
227
- },
228
- topic: {
229
- type: "string",
230
- description: "Topic/purpose of the custom steering document",
231
- },
232
- inclusionMode: {
233
- type: "string",
234
- enum: ["always", "conditional", "manual"],
235
- description: "How this steering document should be included",
236
- },
237
- filePattern: {
238
- type: "string",
239
- description: "File pattern for conditional inclusion",
240
- },
241
- },
242
- required: ["fileName", "topic", "inclusionMode"],
243
- },
244
- },
245
- handler: this.handleSteeringCustom.bind(this),
246
- },
247
- ];
44
+ const handlers = {
45
+ "sdd-init": this.handleProjectInit.bind(this),
46
+ "sdd-requirements": this.handleRequirements.bind(this),
47
+ "sdd-design": this.handleDesign.bind(this),
48
+ "sdd-tasks": this.handleTasks.bind(this),
49
+ "sdd-implement": this.handleImplement.bind(this),
50
+ "sdd-status": this.handleProjectStatus.bind(this),
51
+ "sdd-approve": this.handleApprove.bind(this),
52
+ "sdd-review-test-cases": this.handleReviewTestCases.bind(this),
53
+ "sdd-quality-check": this.handleQualityCheck.bind(this),
54
+ "sdd-context-load": this.handleContextLoad.bind(this),
55
+ "sdd-template-render": this.handleTemplateRender.bind(this),
56
+ "sdd-steering": this.handleSteering.bind(this),
57
+ "sdd-steering-custom": this.handleSteeringCustom.bind(this),
58
+ "sdd-validate-design": this.handleValidateDesign.bind(this),
59
+ "sdd-validate-gap": this.handleValidateGap.bind(this),
60
+ "sdd-spec-impl": this.handleSpecImplementation.bind(this),
61
+ };
62
+ return SDD_TOOL_DEFINITIONS.map((tool) => ({
63
+ name: tool.name,
64
+ tool,
65
+ handler: handlers[tool.name],
66
+ }));
248
67
  }
249
68
  async handleProjectInit(args) {
250
- const { projectName, description = "", clarificationAnswers, reviewTestCases = false, } = args;
251
- if (typeof projectName !== "string") {
252
- throw new Error("Invalid arguments: projectName must be a string");
69
+ const featureName = this.requireFeatureName(args.featureName);
70
+ const description = args.description;
71
+ if (typeof description !== "string") {
72
+ throw new Error("Invalid argument: description must be a string");
253
73
  }
254
- const currentPath = process.cwd();
255
- // FIRST PASS: Analyze description quality
74
+ const clarificationAnswers = args.clarificationAnswers;
256
75
  if (!clarificationAnswers) {
257
- const result = await this.clarificationService.analyzeDescription(description, currentPath);
258
- // If clarification needed, BLOCK and return questions
76
+ const result = await this.clarificationService.analyzeDescription(description, process.cwd());
259
77
  if (result.needsClarification && result.questions) {
260
- return this.formatClarificationQuestions(result.questions, result.analysis);
78
+ return { status: "clarification-required", featureName, questions: result.questions };
261
79
  }
262
80
  }
263
- // SECOND PASS: Validate and synthesize enriched description
264
81
  let enrichedDescription = description;
265
82
  if (clarificationAnswers && typeof clarificationAnswers === "object") {
266
- const result = await this.clarificationService.analyzeDescription(description, currentPath);
83
+ const result = await this.clarificationService.analyzeDescription(description, process.cwd());
267
84
  if (result.questions) {
268
85
  const validation = this.clarificationService.validateAnswers(result.questions, clarificationAnswers);
269
86
  if (!validation.valid) {
270
- throw new Error(`Missing required answers: ${validation.missingRequired.join(", ")}`);
87
+ throw new GovernanceError('InvalidParams', `Missing required answers: ${validation.missingRequired.join(", ")}`);
271
88
  }
272
- const enriched = this.clarificationService.synthesizeDescription(description, result.questions, clarificationAnswers);
273
- enrichedDescription = enriched.enriched;
89
+ enrichedDescription = this.clarificationService.synthesizeDescription(description, result.questions, clarificationAnswers).enriched;
274
90
  }
275
91
  }
276
- // Create project with enriched description
277
- const project = await this.projectService.createProject(projectName, currentPath, "en", { reviewTestCases: reviewTestCases === true });
278
- // Generate initial spec.json
279
- const specContent = await this.templateService.generateSpecJson(project);
280
- await this.templateService.writeProjectFile(project, "spec.json", specContent);
281
- const clarificationNote = clarificationAnswers
282
- ? "\n\n✅ Requirements Clarification: Your answers have been incorporated into an enriched project description."
283
- : "";
284
- return `Project "${projectName}" initialized successfully\nProject ID: ${project.id}\n\nDescription:\n${enrichedDescription}${clarificationNote}`;
285
- }
286
- formatClarificationQuestions(questions, analysis) {
287
- let output = "## Requirements Clarification Needed\n\n";
288
- output +=
289
- "Your project description needs more detail to ensure we build the right solution.\n\n";
290
- output += `**Quality Score**: ${Math.round(analysis.qualityScore)}/100 (need 70+ to proceed)\n\n`;
291
- output += "### Please answer these questions:\n\n";
292
- let questionNum = 1;
293
- for (const q of questions) {
294
- output += `**${questionNum}. ${q.question}**${q.required ? " *(required)*" : ""}\n`;
295
- if (q.examples && q.examples.length > 0) {
296
- output += ` Examples:\n`;
297
- for (const ex of q.examples) {
298
- output += ` - ${ex}\n`;
299
- }
300
- }
301
- output += ` Answer ID: \`${q.id}\`\n\n`;
302
- questionNum++;
92
+ await this.workflowEngineService.initializeFeature({
93
+ projectRoot: process.cwd(),
94
+ featureName,
95
+ description: enrichedDescription,
96
+ language: args.language ?? "en",
97
+ });
98
+ return { status: "initialized", featureName, revision: 0 };
99
+ }
100
+ async requireFeatureProject(featureName) {
101
+ return this.workflowEngineService.loadProject({
102
+ projectRoot: process.cwd(),
103
+ featureName: this.requireFeatureName(featureName),
104
+ });
105
+ }
106
+ requireFeatureName(featureName) {
107
+ if (typeof featureName !== "string" || featureName.length === 0) {
108
+ throw new Error("Invalid argument: featureName must be a non-empty string");
303
109
  }
304
- output += "\n### How to Provide Answers\n\n";
305
- output +=
306
- "Call sdd-init again with clarificationAnswers parameter containing your answers.\n";
307
- return output;
110
+ return featureName;
308
111
  }
309
112
  async handleProjectStatus(args) {
310
- const { projectId, projectPath } = args;
311
- let project;
312
- if (projectId && typeof projectId === "string") {
313
- project = await this.projectService.getProject(projectId);
314
- }
315
- else if (projectPath && typeof projectPath === "string") {
316
- project = await this.projectService.getProjectByPath(projectPath);
317
- }
318
- else {
319
- throw new Error("Either projectId or projectPath must be provided");
320
- }
321
- if (!project) {
322
- return "Project not found";
323
- }
324
- const status = await this.workflowService.getWorkflowStatus(project.id);
325
- if (!status) {
326
- return "Unable to get workflow status";
327
- }
328
- let output = `Project: ${project.name}\n`;
329
- output += `Current Phase: ${status.currentPhase}\n`;
330
- output += `Next Phase: ${status.nextPhase ?? "Complete"}\n`;
331
- output += `Can Progress: ${status.canProgress ? "Yes" : "No"}\n`;
332
- const testCaseCheckpoint = project.metadata.checkpoints?.testCases;
333
- if (testCaseCheckpoint?.required) {
334
- output += `TDD Test Cases Reviewed: ${testCaseCheckpoint.reviewed ? "Yes" : "No"}\n`;
335
- }
336
- if (status.blockers && status.blockers.length > 0) {
337
- output += `Blockers:\n`;
338
- for (const blocker of status.blockers) {
339
- output += `- ${blocker}\n`;
340
- }
113
+ const { featureName } = args;
114
+ if (featureName === undefined) {
115
+ const features = await this.workflowEngineService.listFeatureStatuses({
116
+ projectRoot: process.cwd(),
117
+ });
118
+ return { features };
341
119
  }
342
- return output;
120
+ return this.workflowEngineService.getFeatureStatus({
121
+ projectRoot: process.cwd(),
122
+ featureName: this.requireFeatureName(featureName),
123
+ });
343
124
  }
344
125
  async handleRequirements(args) {
345
- const { projectId } = args;
346
- if (typeof projectId !== "string") {
347
- throw new Error("Invalid argument: projectId must be a string");
348
- }
349
- const project = await this.projectService.getProject(projectId);
350
- if (!project) {
351
- throw new Error("Project not found");
352
- }
353
- // Check if can transition to requirements phase
354
- const validation = await this.workflowService.validatePhaseTransition(projectId, WorkflowPhase.REQUIREMENTS);
355
- if (!validation.canProgress) {
356
- throw new Error(`Cannot generate requirements: ${validation.reason}`);
357
- }
358
- // Generate requirements template
359
- const content = await this.templateService.generateRequirementsTemplate(project);
360
- await this.templateService.writeProjectFile(project, "requirements.md", content);
361
- // Update project phase and approval status
362
- await this.projectService.updateProjectPhase(projectId, WorkflowPhase.REQUIREMENTS);
363
- const updatedProject = await this.projectService.updateApprovalStatus(projectId, "requirements", {
364
- generated: true,
365
- approved: false,
366
- });
367
- const specContent = await this.templateService.generateSpecJson(updatedProject);
368
- await this.templateService.writeProjectFile(updatedProject, "spec.json", specContent);
369
- return `Requirements document generated for project "${project.name}"`;
126
+ return this.handlePhaseSubmission(args, "requirements");
370
127
  }
371
128
  async handleDesign(args) {
372
- const { projectId } = args;
373
- if (typeof projectId !== "string") {
374
- throw new Error("Invalid argument: projectId must be a string");
375
- }
376
- const project = await this.projectService.getProject(projectId);
377
- if (!project) {
378
- throw new Error("Project not found");
379
- }
380
- // Check if can transition to design phase
381
- const validation = await this.workflowService.validatePhaseTransition(projectId, WorkflowPhase.DESIGN);
382
- if (!validation.canProgress) {
383
- throw new Error(`Cannot generate design: ${validation.reason}`);
384
- }
385
- // Generate design template
386
- const content = await this.templateService.generateDesignTemplate(project);
387
- await this.templateService.writeProjectFile(project, "design.md", content);
388
- // Update project phase and approval status
389
- await this.projectService.updateProjectPhase(projectId, WorkflowPhase.DESIGN);
390
- const updatedProject = await this.projectService.updateApprovalStatus(projectId, "design", {
391
- generated: true,
392
- approved: false,
393
- });
394
- const specContent = await this.templateService.generateSpecJson(updatedProject);
395
- await this.templateService.writeProjectFile(updatedProject, "spec.json", specContent);
396
- return `Design document generated for project "${project.name}"`;
129
+ return this.handlePhaseSubmission(args, "design");
397
130
  }
398
131
  async handleTasks(args) {
399
- const { projectId, reviewTestCases } = args;
400
- if (typeof projectId !== "string") {
401
- throw new Error("Invalid argument: projectId must be a string");
402
- }
403
- const project = await this.projectService.getProject(projectId);
404
- if (!project) {
405
- throw new Error("Project not found");
406
- }
407
- // Check if can transition to tasks phase
408
- const validation = await this.workflowService.validatePhaseTransition(projectId, WorkflowPhase.TASKS);
409
- if (!validation.canProgress) {
410
- throw new Error(`Cannot generate tasks: ${validation.reason}`);
411
- }
412
- // Generate tasks template
413
- const content = await this.templateService.generateTasksTemplate(project);
414
- await this.templateService.writeProjectFile(project, "tasks.md", content);
415
- if (typeof reviewTestCases === "boolean") {
416
- await this.projectService.updateTestCaseReviewCheckpoint(projectId, {
417
- required: reviewTestCases,
418
- reviewed: !reviewTestCases,
419
- });
420
- }
421
- // Update project phase and approval status
422
- await this.projectService.updateProjectPhase(projectId, WorkflowPhase.TASKS);
423
- const updatedProject = await this.projectService.updateApprovalStatus(projectId, "tasks", {
424
- generated: true,
425
- approved: false,
132
+ return this.handlePhaseSubmission(args, "tasks");
133
+ }
134
+ async handlePhaseSubmission(args, phase) {
135
+ return this.workflowEngineService.submitPhaseArtifact({
136
+ projectRoot: process.cwd(),
137
+ featureName: this.requireFeatureName(args.featureName),
138
+ phase,
139
+ content: args.content,
140
+ expectedRevision: args.expectedRevision,
141
+ expectedArtifactSha256: args.expectedArtifactSha256,
142
+ reviewTestCases: phase === "tasks" ? args.reviewTestCases : undefined,
143
+ });
144
+ }
145
+ async handleImplement(args) {
146
+ return this.workflowEngineService.beginImplementation({
147
+ projectRoot: process.cwd(),
148
+ featureName: this.requireFeatureName(args.featureName),
149
+ });
150
+ }
151
+ async handleApprove(args) {
152
+ const featureName = this.requireFeatureName(args.featureName);
153
+ const phase = args.phase;
154
+ if (!["requirements", "design", "tasks"].includes(phase)) {
155
+ throw new Error("Invalid argument: phase must be requirements, design, or tasks");
156
+ }
157
+ return this.workflowEngineService.approve({
158
+ projectRoot: process.cwd(),
159
+ featureName,
160
+ phase: phase,
161
+ expectedRevision: args.expectedRevision,
162
+ expectedArtifactSha256: args.expectedArtifactSha256,
426
163
  });
427
- const specContent = await this.templateService.generateSpecJson(updatedProject);
428
- await this.templateService.writeProjectFile(updatedProject, "spec.json", specContent);
429
- return `Tasks document generated for project "${project.name}"`;
430
164
  }
431
165
  async handleReviewTestCases(args) {
432
- const { projectId } = args;
433
- if (typeof projectId !== "string") {
434
- throw new Error("Invalid argument: projectId must be a string");
435
- }
436
- const project = await this.projectService.getProject(projectId);
437
- if (!project) {
438
- throw new Error("Project not found");
439
- }
440
- const updatedProject = await this.projectService.updateTestCaseReviewCheckpoint(projectId, { required: true, reviewed: true });
441
- const specContent = await this.templateService.generateSpecJson(updatedProject);
442
- await this.templateService.writeProjectFile(updatedProject, "spec.json", specContent);
443
- return `TDD test cases reviewed for project "${project.name}"`;
166
+ const featureName = this.requireFeatureName(args.featureName);
167
+ return this.workflowEngineService.reviewTestCases({
168
+ projectRoot: process.cwd(),
169
+ featureName,
170
+ expectedTasksRevision: args.expectedTasksRevision,
171
+ expectedArtifactSha256: args.expectedArtifactSha256,
172
+ });
444
173
  }
445
174
  async handleQualityCheck(args) {
446
175
  const { code, language = "typescript" } = args;
@@ -454,19 +183,71 @@ let SDDToolAdapter = class SDDToolAdapter {
454
183
  return this.qualityService.formatQualityReport(report);
455
184
  }
456
185
  async handleContextLoad(args) {
457
- const { projectId, mode = "compact" } = args;
458
- if (typeof projectId !== "string") {
459
- throw new Error("Invalid argument: projectId must be a string");
460
- }
461
- if (!["compact", "standard", "full"].includes(mode)) {
462
- throw new Error("Invalid argument: mode must be compact, standard, or full");
463
- }
464
- const project = await this.projectService.getProject(projectId);
465
- if (!project) {
466
- throw new Error("Project not found");
467
- }
468
- const context = await this.contextCompactionService.loadContext(project, mode);
469
- return context;
186
+ const featureName = this.requireFeatureName(args.featureName);
187
+ const { mode, phase, maxEstimatedTokens, ifNoneMatch, includeUnapproved, } = args;
188
+ return this.workflowEngineService.loadFeatureContext({
189
+ projectRoot: process.cwd(),
190
+ featureName,
191
+ mode: mode,
192
+ phase: phase,
193
+ maxEstimatedTokens: maxEstimatedTokens,
194
+ ifNoneMatch: ifNoneMatch,
195
+ includeUnapproved: includeUnapproved,
196
+ });
197
+ }
198
+ async handleTemplateRender(args) {
199
+ const project = await this.requireFeatureProject(args.featureName);
200
+ const templateType = args.templateType;
201
+ if (args.customTemplate !== undefined) {
202
+ if (typeof args.customTemplate !== "string") {
203
+ throw new Error("Invalid argument: customTemplate must be a string");
204
+ }
205
+ return {
206
+ featureName: project.name,
207
+ templateType,
208
+ content: args.customTemplate,
209
+ };
210
+ }
211
+ let content;
212
+ switch (templateType) {
213
+ case "requirements":
214
+ content = await this.templateService.generateRequirementsTemplate(project);
215
+ break;
216
+ case "design":
217
+ content = await this.templateService.generateDesignTemplate(project);
218
+ break;
219
+ case "tasks":
220
+ content = await this.templateService.generateTasksTemplate(project);
221
+ break;
222
+ default:
223
+ throw new Error("Invalid argument: templateType must be requirements, design, or tasks");
224
+ }
225
+ return { featureName: project.name, templateType, content };
226
+ }
227
+ async handleValidateDesign(args) {
228
+ return this.workflowEngineService.validateDesignArtifact({
229
+ projectRoot: process.cwd(),
230
+ featureName: this.requireFeatureName(args.featureName),
231
+ });
232
+ }
233
+ async handleValidateGap(args) {
234
+ const project = await this.requireFeatureProject(args.featureName);
235
+ return {
236
+ featureName: project.name,
237
+ analysis: await this.codebaseAnalysisService.analyzeCodebase(project.path),
238
+ };
239
+ }
240
+ async handleSpecImplementation(args) {
241
+ return this.workflowEngineService.recordTaskProgress({
242
+ projectRoot: process.cwd(),
243
+ featureName: this.requireFeatureName(args.featureName),
244
+ taskNumber: args.taskNumber,
245
+ action: args.action,
246
+ expectedRevision: args.expectedRevision,
247
+ evidence: args.evidence,
248
+ affectedArtifacts: args.affectedArtifacts,
249
+ blocker: args.blocker,
250
+ });
470
251
  }
471
252
  async handleSteering(args) {
472
253
  const { updateMode = "update" } = args;
@@ -553,6 +334,12 @@ Choose Codex or Claude Code interactively, or pass \`--target\` explicitly in au
553
334
  typeof inclusionMode !== "string") {
554
335
  throw new Error("Invalid arguments: fileName, topic, and inclusionMode must be strings");
555
336
  }
337
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*\.md$/.test(fileName)) {
338
+ throw new Error("Invalid argument: fileName must be a Markdown basename");
339
+ }
340
+ if (!["always", "conditional", "manual"].includes(inclusionMode)) {
341
+ throw new Error("Invalid argument: inclusionMode must be always, conditional, or manual");
342
+ }
556
343
  const content = `# ${topic}
557
344
 
558
345
  ## Purpose
@@ -858,23 +645,19 @@ ${this.generateWorkflow(analysis)}`;
858
645
  };
859
646
  SDDToolAdapter = __decorate([
860
647
  injectable(),
861
- __param(0, inject(TYPES.ProjectService)),
862
- __param(1, inject(TYPES.WorkflowService)),
863
- __param(2, inject(TYPES.TemplateService)),
864
- __param(3, inject(TYPES.QualityService)),
865
- __param(4, inject(TYPES.SteeringDocumentService)),
866
- __param(5, inject(TYPES.CodebaseAnalysisService)),
867
- __param(6, inject(TYPES.RequirementsClarificationService)),
868
- __param(7, inject(TYPES.ContextCompactionService)),
869
- __param(8, inject(TYPES.LoggerPort)),
870
- __metadata("design:paramtypes", [ProjectService,
871
- WorkflowService,
872
- TemplateService,
648
+ __param(0, inject(TYPES.TemplateService)),
649
+ __param(1, inject(TYPES.QualityService)),
650
+ __param(2, inject(TYPES.SteeringDocumentService)),
651
+ __param(3, inject(TYPES.CodebaseAnalysisService)),
652
+ __param(4, inject(TYPES.RequirementsClarificationService)),
653
+ __param(5, inject(TYPES.WorkflowEngineService)),
654
+ __param(6, inject(TYPES.LoggerPort)),
655
+ __metadata("design:paramtypes", [TemplateService,
873
656
  QualityService,
874
657
  SteeringDocumentService,
875
658
  CodebaseAnalysisService,
876
659
  RequirementsClarificationService,
877
- ContextCompactionService, Object])
660
+ WorkflowEngineService, Object])
878
661
  ], SDDToolAdapter);
879
662
  export { SDDToolAdapter };
880
663
  //# sourceMappingURL=SDDToolAdapter.js.map