sdd-mcp-server 3.5.0 → 4.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 (95) hide show
  1. package/README.md +97 -671
  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 -5
  9. package/dist/adapters/cli/SDDToolAdapter.js +189 -362
  10. package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
  11. package/dist/application/services/ContextCompactionService.d.ts +81 -16
  12. package/dist/application/services/ContextCompactionService.js +370 -187
  13. package/dist/application/services/ContextCompactionService.js.map +1 -1
  14. package/dist/application/services/SpecPathResolver.d.ts +24 -0
  15. package/dist/application/services/SpecPathResolver.js +70 -0
  16. package/dist/application/services/SpecPathResolver.js.map +1 -0
  17. package/dist/application/services/WorkflowEngineService.d.ts +100 -46
  18. package/dist/application/services/WorkflowEngineService.js +468 -288
  19. package/dist/application/services/WorkflowEngineService.js.map +1 -1
  20. package/dist/cli/install-skills.d.ts +3 -9
  21. package/dist/cli/install-skills.js +130 -175
  22. package/dist/cli/install-skills.js.map +1 -1
  23. package/dist/cli/install-target.d.ts +45 -14
  24. package/dist/cli/install-target.js +26 -12
  25. package/dist/cli/install-target.js.map +1 -1
  26. package/dist/cli/sdd-mcp-cli.d.ts +1 -1
  27. package/dist/cli/sdd-mcp-cli.js +7 -6
  28. package/dist/cli/sdd-mcp-cli.js.map +1 -1
  29. package/dist/cli/tool-support/claude-code.js +13 -34
  30. package/dist/cli/tool-support/claude-code.js.map +1 -1
  31. package/dist/cli/tool-support/codex.d.ts +0 -53
  32. package/dist/cli/tool-support/codex.js +6 -94
  33. package/dist/cli/tool-support/codex.js.map +1 -1
  34. package/dist/cli/tool-support/index.d.ts +3 -2
  35. package/dist/cli/tool-support/index.js +3 -1
  36. package/dist/cli/tool-support/index.js.map +1 -1
  37. package/dist/cli/tool-support/omp.d.ts +5 -0
  38. package/dist/cli/tool-support/omp.js +43 -0
  39. package/dist/cli/tool-support/omp.js.map +1 -0
  40. package/dist/cli/tool-support/root-guidance.d.ts +2 -9
  41. package/dist/cli/tool-support/root-guidance.js +44 -37
  42. package/dist/cli/tool-support/root-guidance.js.map +1 -1
  43. package/dist/cli/tool-support/target-agent-renderer.d.ts +1 -0
  44. package/dist/cli/tool-support/target-agent-renderer.js +37 -4
  45. package/dist/cli/tool-support/target-agent-renderer.js.map +1 -1
  46. package/dist/cli/tool-support/target-installer.d.ts +8 -2
  47. package/dist/cli/tool-support/target-installer.js +94 -26
  48. package/dist/cli/tool-support/target-installer.js.map +1 -1
  49. package/dist/cli/utils/preserving-writer.d.ts +22 -0
  50. package/dist/cli/utils/preserving-writer.js +233 -11
  51. package/dist/cli/utils/preserving-writer.js.map +1 -1
  52. package/dist/domain/ports.d.ts +4 -0
  53. package/dist/index.d.ts +13 -10
  54. package/dist/index.js +16 -1199
  55. package/dist/index.js.map +1 -1
  56. package/dist/infrastructure/adapters/NodeFileSystemAdapter.d.ts +3 -0
  57. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js +10 -0
  58. package/dist/infrastructure/adapters/NodeFileSystemAdapter.js.map +1 -1
  59. package/dist/infrastructure/mcp/CapabilityNegotiator.js +3 -3
  60. package/dist/infrastructure/mcp/CapabilityNegotiator.js.map +1 -1
  61. package/dist/infrastructure/mcp/sddToolDefinitions.d.ts +6 -0
  62. package/dist/infrastructure/mcp/sddToolDefinitions.js +124 -0
  63. package/dist/infrastructure/mcp/sddToolDefinitions.js.map +1 -0
  64. package/dist/utils/atomicWrite.d.ts +8 -35
  65. package/dist/utils/atomicWrite.js +12 -60
  66. package/dist/utils/atomicWrite.js.map +1 -1
  67. package/mcp-server.js +5 -2883
  68. package/package.json +5 -2
  69. package/scripts/context-usage-report.mjs +602 -0
  70. package/sdd-entry.js +17 -6
  71. package/skills/sdd-commit/REFERENCE.md +31 -0
  72. package/skills/sdd-commit/SKILL.md +17 -273
  73. package/skills/sdd-design/REFERENCE.md +35 -0
  74. package/skills/sdd-design/SKILL.md +19 -265
  75. package/skills/sdd-implement/REFERENCE.md +26 -0
  76. package/skills/sdd-implement/SKILL.md +22 -283
  77. package/skills/sdd-requirements/REFERENCE.md +31 -0
  78. package/skills/sdd-requirements/SKILL.md +23 -135
  79. package/skills/sdd-review/REFERENCE.md +26 -0
  80. package/skills/sdd-review/SKILL.md +17 -181
  81. package/skills/sdd-security-check/REFERENCE.md +19 -0
  82. package/skills/sdd-security-check/SKILL.md +18 -184
  83. package/skills/sdd-steering/REFERENCE.md +25 -0
  84. package/skills/sdd-steering/SKILL.md +18 -216
  85. package/skills/sdd-steering-custom/REFERENCE.md +27 -0
  86. package/skills/sdd-steering-custom/SKILL.md +19 -203
  87. package/skills/sdd-tasks/REFERENCE.md +25 -0
  88. package/skills/sdd-tasks/SKILL.md +19 -248
  89. package/skills/sdd-test-gen/REFERENCE.md +15 -0
  90. package/skills/sdd-test-gen/SKILL.md +17 -287
  91. package/skills/simple-task/REFERENCE.md +22 -0
  92. package/skills/simple-task/SKILL.md +17 -138
  93. package/templates/CLAUDE.md +18 -30
  94. package/rules/git-workflow.md +0 -92
  95. package/rules/sdd-workflow.md +0 -116
@@ -13,244 +13,78 @@ 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
21
  import { ContextCompactionService } from "../../application/services/ContextCompactionService.js";
24
- import { WorkflowPhase } from "../../domain/types.js";
22
+ import { WorkflowEngineService } from "../../application/services/WorkflowEngineService.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
32
  contextCompactionService;
33
+ workflowEngineService;
35
34
  logger;
36
- constructor(projectService, workflowService, templateService, qualityService, steeringService, codebaseAnalysisService, clarificationService, contextCompactionService, logger) {
37
- this.projectService = projectService;
38
- this.workflowService = workflowService;
35
+ constructor(templateService, qualityService, steeringService, codebaseAnalysisService, clarificationService, contextCompactionService, workflowEngineService, logger) {
39
36
  this.templateService = templateService;
40
37
  this.qualityService = qualityService;
41
38
  this.steeringService = steeringService;
42
39
  this.codebaseAnalysisService = codebaseAnalysisService;
43
40
  this.clarificationService = clarificationService;
44
41
  this.contextCompactionService = contextCompactionService;
42
+ this.workflowEngineService = workflowEngineService;
45
43
  this.logger = logger;
46
44
  }
47
45
  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
- ];
46
+ const handlers = {
47
+ "sdd-init": this.handleProjectInit.bind(this),
48
+ "sdd-requirements": this.handleRequirements.bind(this),
49
+ "sdd-design": this.handleDesign.bind(this),
50
+ "sdd-tasks": this.handleTasks.bind(this),
51
+ "sdd-implement": this.handleImplement.bind(this),
52
+ "sdd-status": this.handleProjectStatus.bind(this),
53
+ "sdd-approve": this.handleApprove.bind(this),
54
+ "sdd-review-test-cases": this.handleReviewTestCases.bind(this),
55
+ "sdd-quality-check": this.handleQualityCheck.bind(this),
56
+ "sdd-context-load": this.handleContextLoad.bind(this),
57
+ "sdd-template-render": this.handleTemplateRender.bind(this),
58
+ "sdd-steering": this.handleSteering.bind(this),
59
+ "sdd-steering-custom": this.handleSteeringCustom.bind(this),
60
+ "sdd-validate-design": this.handleValidateDesign.bind(this),
61
+ "sdd-validate-gap": this.handleValidateGap.bind(this),
62
+ "sdd-spec-impl": this.handleSpecImplementation.bind(this),
63
+ };
64
+ return SDD_TOOL_DEFINITIONS.map((tool) => ({
65
+ name: tool.name,
66
+ tool,
67
+ handler: handlers[tool.name],
68
+ }));
69
+ }
70
+ canonicalFeatureName(projectName) {
71
+ const featureName = projectName
72
+ .trim()
73
+ .toLowerCase()
74
+ .replace(/[^a-z0-9._-]+/g, "-")
75
+ .replace(/^-+|-+$/g, "")
76
+ .slice(0, 80);
77
+ if (!featureName) {
78
+ throw new Error("Invalid argument: projectName must contain a letter or number");
79
+ }
80
+ return featureName;
248
81
  }
249
82
  async handleProjectInit(args) {
250
83
  const { projectName, description = "", clarificationAnswers, reviewTestCases = false, } = args;
251
84
  if (typeof projectName !== "string") {
252
85
  throw new Error("Invalid arguments: projectName must be a string");
253
86
  }
87
+ const featureName = this.canonicalFeatureName(projectName);
254
88
  const currentPath = process.cwd();
255
89
  // FIRST PASS: Analyze description quality
256
90
  if (!clarificationAnswers) {
@@ -273,15 +107,22 @@ let SDDToolAdapter = class SDDToolAdapter {
273
107
  enrichedDescription = enriched.enriched;
274
108
  }
275
109
  }
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);
110
+ await this.workflowEngineService.initializeFeature({
111
+ projectRoot: currentPath,
112
+ featureName,
113
+ language: "en",
114
+ reviewTestCases: reviewTestCases === true,
115
+ });
281
116
  const clarificationNote = clarificationAnswers
282
117
  ? "\n\n✅ Requirements Clarification: Your answers have been incorporated into an enriched project description."
283
118
  : "";
284
- return `Project "${projectName}" initialized successfully\nProject ID: ${project.id}\n\nDescription:\n${enrichedDescription}${clarificationNote}`;
119
+ return {
120
+ featureName,
121
+ initialized: true,
122
+ description: enrichedDescription,
123
+ clarificationApplied: Boolean(clarificationAnswers),
124
+ message: `Project "${projectName}" initialized successfully${clarificationNote}`,
125
+ };
285
126
  }
286
127
  formatClarificationQuestions(questions, analysis) {
287
128
  let output = "## Requirements Clarification Needed\n\n";
@@ -306,141 +147,81 @@ let SDDToolAdapter = class SDDToolAdapter {
306
147
  "Call sdd-init again with clarificationAnswers parameter containing your answers.\n";
307
148
  return output;
308
149
  }
150
+ async requireFeatureProject(featureName) {
151
+ return this.workflowEngineService.loadProject({
152
+ projectRoot: process.cwd(),
153
+ featureName: this.requireFeatureName(featureName),
154
+ });
155
+ }
156
+ requireFeatureName(featureName) {
157
+ if (typeof featureName !== "string" || featureName.length === 0) {
158
+ throw new Error("Invalid argument: featureName must be a non-empty string");
159
+ }
160
+ return featureName;
161
+ }
309
162
  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
- }
163
+ const { featureName } = args;
164
+ if (featureName === undefined) {
165
+ const features = await this.workflowEngineService.listFeatureStatuses({
166
+ projectRoot: process.cwd(),
167
+ });
168
+ return { features };
341
169
  }
342
- return output;
170
+ return this.workflowEngineService.getFeatureStatus({
171
+ projectRoot: process.cwd(),
172
+ featureName: this.requireFeatureName(featureName),
173
+ });
343
174
  }
344
175
  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,
176
+ return this.workflowEngineService.generatePhase({
177
+ projectRoot: process.cwd(),
178
+ featureName: this.requireFeatureName(args.featureName),
179
+ phase: "requirements",
366
180
  });
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}"`;
370
181
  }
371
182
  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,
183
+ return this.workflowEngineService.generatePhase({
184
+ projectRoot: process.cwd(),
185
+ featureName: this.requireFeatureName(args.featureName),
186
+ phase: "design",
393
187
  });
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}"`;
397
188
  }
398
189
  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,
190
+ const reviewTestCases = args.reviewTestCases;
191
+ if (reviewTestCases !== undefined && typeof reviewTestCases !== "boolean") {
192
+ throw new Error("Invalid argument: reviewTestCases must be a boolean");
193
+ }
194
+ return this.workflowEngineService.generatePhase({
195
+ projectRoot: process.cwd(),
196
+ featureName: this.requireFeatureName(args.featureName),
197
+ phase: "tasks",
198
+ reviewTestCases: reviewTestCases,
199
+ });
200
+ }
201
+ async handleImplement(args) {
202
+ return this.workflowEngineService.beginImplementation({
203
+ projectRoot: process.cwd(),
204
+ featureName: this.requireFeatureName(args.featureName),
205
+ });
206
+ }
207
+ async handleApprove(args) {
208
+ const featureName = this.requireFeatureName(args.featureName);
209
+ const phase = args.phase;
210
+ if (!["requirements", "design", "tasks"].includes(phase)) {
211
+ throw new Error("Invalid argument: phase must be requirements, design, or tasks");
212
+ }
213
+ return this.workflowEngineService.approve({
214
+ projectRoot: process.cwd(),
215
+ featureName,
216
+ phase: phase,
426
217
  });
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
218
  }
431
219
  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}"`;
220
+ const featureName = this.requireFeatureName(args.featureName);
221
+ return this.workflowEngineService.reviewTestCases({
222
+ projectRoot: process.cwd(),
223
+ featureName,
224
+ });
444
225
  }
445
226
  async handleQualityCheck(args) {
446
227
  const { code, language = "typescript" } = args;
@@ -454,19 +235,61 @@ let SDDToolAdapter = class SDDToolAdapter {
454
235
  return this.qualityService.formatQualityReport(report);
455
236
  }
456
237
  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;
238
+ const featureName = this.requireFeatureName(args.featureName);
239
+ const { mode, phase, maxEstimatedTokens, ifNoneMatch, includeUnapproved, } = args;
240
+ return this.contextCompactionService.loadContext({
241
+ projectRoot: process.cwd(),
242
+ featureName,
243
+ mode: mode,
244
+ phase: phase,
245
+ maxEstimatedTokens: maxEstimatedTokens,
246
+ ifNoneMatch: ifNoneMatch,
247
+ includeUnapproved: includeUnapproved,
248
+ });
249
+ }
250
+ async handleTemplateRender(args) {
251
+ const project = await this.requireFeatureProject(args.featureName);
252
+ const templateType = args.templateType;
253
+ if (args.customTemplate !== undefined) {
254
+ if (typeof args.customTemplate !== "string") {
255
+ throw new Error("Invalid argument: customTemplate must be a string");
256
+ }
257
+ return {
258
+ featureName: project.name,
259
+ templateType,
260
+ content: args.customTemplate,
261
+ };
262
+ }
263
+ let content;
264
+ switch (templateType) {
265
+ case "requirements":
266
+ content = await this.templateService.generateRequirementsTemplate(project);
267
+ break;
268
+ case "design":
269
+ content = await this.templateService.generateDesignTemplate(project);
270
+ break;
271
+ case "tasks":
272
+ content = await this.templateService.generateTasksTemplate(project);
273
+ break;
274
+ default:
275
+ throw new Error("Invalid argument: templateType must be requirements, design, or tasks");
276
+ }
277
+ return { featureName: project.name, templateType, content };
278
+ }
279
+ async handleValidateDesign(args) {
280
+ const project = await this.requireFeatureProject(args.featureName);
281
+ return this.qualityService.validateDesign(project);
282
+ }
283
+ async handleValidateGap(args) {
284
+ const project = await this.requireFeatureProject(args.featureName);
285
+ return {
286
+ featureName: project.name,
287
+ analysis: await this.codebaseAnalysisService.analyzeCodebase(project.path),
288
+ };
289
+ }
290
+ async handleSpecImplementation(args) {
291
+ const result = await this.handleImplement(args);
292
+ return { ...result, taskNumbers: args.taskNumbers ?? null };
470
293
  }
471
294
  async handleSteering(args) {
472
295
  const { updateMode = "update" } = args;
@@ -553,6 +376,12 @@ Choose Codex or Claude Code interactively, or pass \`--target\` explicitly in au
553
376
  typeof inclusionMode !== "string") {
554
377
  throw new Error("Invalid arguments: fileName, topic, and inclusionMode must be strings");
555
378
  }
379
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*\.md$/.test(fileName)) {
380
+ throw new Error("Invalid argument: fileName must be a Markdown basename");
381
+ }
382
+ if (!["always", "conditional", "manual"].includes(inclusionMode)) {
383
+ throw new Error("Invalid argument: inclusionMode must be always, conditional, or manual");
384
+ }
556
385
  const content = `# ${topic}
557
386
 
558
387
  ## Purpose
@@ -858,23 +687,21 @@ ${this.generateWorkflow(analysis)}`;
858
687
  };
859
688
  SDDToolAdapter = __decorate([
860
689
  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,
690
+ __param(0, inject(TYPES.TemplateService)),
691
+ __param(1, inject(TYPES.QualityService)),
692
+ __param(2, inject(TYPES.SteeringDocumentService)),
693
+ __param(3, inject(TYPES.CodebaseAnalysisService)),
694
+ __param(4, inject(TYPES.RequirementsClarificationService)),
695
+ __param(5, inject(TYPES.ContextCompactionService)),
696
+ __param(6, inject(TYPES.WorkflowEngineService)),
697
+ __param(7, inject(TYPES.LoggerPort)),
698
+ __metadata("design:paramtypes", [TemplateService,
873
699
  QualityService,
874
700
  SteeringDocumentService,
875
701
  CodebaseAnalysisService,
876
702
  RequirementsClarificationService,
877
- ContextCompactionService, Object])
703
+ ContextCompactionService,
704
+ WorkflowEngineService, Object])
878
705
  ], SDDToolAdapter);
879
706
  export { SDDToolAdapter };
880
707
  //# sourceMappingURL=SDDToolAdapter.js.map