sdd-mcp-server 2.1.0 → 2.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,324 @@
1
+ # Test-Driven Development (TDD) Guidelines
2
+
3
+ ## Overview
4
+
5
+ All new features and specifications MUST follow Test-Driven Development (TDD) methodology. This ensures code quality, maintainability, and adherence to requirements from the start.
6
+
7
+ ## TDD Cycle: Red → Green → Refactor
8
+
9
+ ### 1. RED Phase: Write Failing Tests First
10
+ **Goal**: Define expected behavior through tests before writing any implementation code.
11
+
12
+ **Process**:
13
+ 1. Read and understand the requirement
14
+ 2. Write a test that describes the expected behavior
15
+ 3. Run the test and confirm it fails (RED)
16
+ 4. Commit: `test: add failing test for [feature]`
17
+
18
+ **Example**:
19
+ ```typescript
20
+ // ❌ Test fails because implementation doesn't exist yet
21
+ describe('UserService', () => {
22
+ it('should create user with valid email', async () => {
23
+ const result = await userService.create({ email: 'test@example.com' });
24
+ expect(result.success).toBe(true);
25
+ });
26
+ });
27
+ ```
28
+
29
+ **Test Requirements**:
30
+ - Test MUST fail initially (if it passes, you're not testing new functionality)
31
+ - Test MUST be specific and focused on ONE behavior
32
+ - Test name MUST clearly describe the expected behavior
33
+ - Test MUST use realistic test data
34
+
35
+ ### 2. GREEN Phase: Write Minimal Code to Pass
36
+ **Goal**: Write the simplest code possible to make the test pass.
37
+
38
+ **Process**:
39
+ 1. Write only enough code to make the failing test pass
40
+ 2. Avoid premature optimization or extra features
41
+ 3. Run tests and confirm they pass (GREEN)
42
+ 4. Commit: `feat: implement [feature] to pass tests`
43
+
44
+ **Example**:
45
+ ```typescript
46
+ // ✅ Minimal implementation to make test pass
47
+ class UserService {
48
+ async create(data: { email: string }) {
49
+ if (!data.email.includes('@')) {
50
+ return { success: false, error: 'Invalid email' };
51
+ }
52
+ return { success: true, user: { email: data.email } };
53
+ }
54
+ }
55
+ ```
56
+
57
+ **Implementation Requirements**:
58
+ - Code MUST make all tests pass
59
+ - Code SHOULD be minimal (no over-engineering)
60
+ - Code MUST be understandable and clear
61
+ - Add more tests if edge cases are discovered
62
+
63
+ ### 3. REFACTOR Phase: Improve Code Quality
64
+ **Goal**: Improve code structure, readability, and performance while keeping tests green.
65
+
66
+ **Process**:
67
+ 1. Review code for duplication, complexity, or unclear logic
68
+ 2. Refactor while keeping tests passing
69
+ 3. Run tests after each refactor to ensure nothing breaks
70
+ 4. Commit: `refactor: improve [component] structure`
71
+
72
+ **Example**:
73
+ ```typescript
74
+ // ✅ Refactored for better structure
75
+ class UserService {
76
+ async create(data: UserInput): Promise<Result<User>> {
77
+ const validation = this.validateEmail(data.email);
78
+ if (!validation.valid) {
79
+ return Result.failure(validation.error);
80
+ }
81
+
82
+ const user = await this.repository.save(data);
83
+ return Result.success(user);
84
+ }
85
+
86
+ private validateEmail(email: string): ValidationResult {
87
+ return EmailValidator.validate(email);
88
+ }
89
+ }
90
+ ```
91
+
92
+ **Refactoring Checklist**:
93
+ - [ ] Remove code duplication
94
+ - [ ] Extract methods for clarity
95
+ - [ ] Improve naming (variables, functions, classes)
96
+ - [ ] Optimize performance (if needed)
97
+ - [ ] Add inline documentation for complex logic
98
+ - [ ] All tests still pass
99
+
100
+ ## Task Order for TDD Implementation
101
+
102
+ When generating tasks for new features, ALWAYS follow this order:
103
+
104
+ ### Phase 1: Test Setup (RED)
105
+ ```markdown
106
+ - [ ] 1. Set up test infrastructure
107
+ - Install/configure test framework (Jest, Mocha, pytest, JUnit, etc.)
108
+ - Create test directory structure
109
+ - Configure test runner and coverage tools
110
+ - _Requirements: NFR-3 (Quality Standards)_
111
+
112
+ - [ ] 2. Write failing tests for [Feature Name]
113
+ - Write unit tests for core functionality
114
+ - Write integration tests for system interactions
115
+ - Write edge case and error handling tests
116
+ - Confirm all tests fail (RED phase)
117
+ - _Requirements: FR-1 (Core Functionality)_
118
+ ```
119
+
120
+ ### Phase 2: Implementation (GREEN)
121
+ ```markdown
122
+ - [ ] 3. Implement minimal code to pass tests
123
+ - Implement core feature logic to satisfy tests
124
+ - Add necessary dependencies and modules
125
+ - Ensure all tests pass (GREEN phase)
126
+ - _Requirements: FR-1, FR-2 (Technology Integration)_
127
+
128
+ - [ ] 4. Verify test coverage
129
+ - Run coverage report
130
+ - Ensure minimum 80% code coverage
131
+ - Add tests for uncovered branches
132
+ - _Requirements: NFR-3 (Quality Standards)_
133
+ ```
134
+
135
+ ### Phase 3: Refactoring (REFACTOR)
136
+ ```markdown
137
+ - [ ] 5. Refactor for code quality
138
+ - Extract reusable components/functions
139
+ - Improve naming and code clarity
140
+ - Remove duplication (DRY principle)
141
+ - Apply design patterns where appropriate
142
+ - All tests must still pass
143
+ - _Requirements: NFR-3 (Maintainability)_
144
+
145
+ - [ ] 6. Code quality validation
146
+ - Run linter and fix issues
147
+ - Run type checker (if TypeScript/typed language)
148
+ - Apply Linus-style code review principles
149
+ - _Requirements: NFR-3 (Quality Standards)_
150
+ ```
151
+
152
+ ### Phase 4: Integration & Documentation
153
+ ```markdown
154
+ - [ ] 7. Integration with existing system
155
+ - Integrate with build system
156
+ - Update configuration files
157
+ - Test in development environment
158
+ - _Requirements: FR-2, NFR-2 (Reliability)_
159
+
160
+ - [ ] 8. Documentation and deployment prep
161
+ - Update API documentation
162
+ - Add inline code comments for complex logic
163
+ - Update README/CHANGELOG if needed
164
+ - Prepare for deployment
165
+ - _Requirements: NFR-3 (Maintainability)_
166
+ ```
167
+
168
+ ## TDD Best Practices
169
+
170
+ ### Test Quality
171
+ 1. **AAA Pattern**: Arrange, Act, Assert
172
+ ```typescript
173
+ it('should validate email format', () => {
174
+ // Arrange: Set up test data
175
+ const email = 'invalid-email';
176
+
177
+ // Act: Execute the functionality
178
+ const result = validator.validate(email);
179
+
180
+ // Assert: Verify the outcome
181
+ expect(result.valid).toBe(false);
182
+ });
183
+ ```
184
+
185
+ 2. **One Assertion Per Test** (when possible)
186
+ - Each test should verify ONE specific behavior
187
+ - Makes failures easier to diagnose
188
+ - Keeps tests focused and maintainable
189
+
190
+ 3. **Test Independence**
191
+ - Tests should not depend on each other
192
+ - Tests should be able to run in any order
193
+ - Use setup/teardown for test isolation
194
+
195
+ 4. **Meaningful Test Names**
196
+ - ✅ `should return error when email is missing @symbol`
197
+ - ❌ `test1`, `testEmail`, `checkValidation`
198
+
199
+ ### Coverage Targets
200
+ - **Minimum**: 80% code coverage
201
+ - **Target**: 90%+ code coverage for critical paths
202
+ - **Focus**: All public APIs must have tests
203
+ - **Edge Cases**: Always test boundary conditions and error paths
204
+
205
+ ### Test Types by Phase
206
+
207
+ #### Unit Tests (RED/GREEN)
208
+ - Test individual functions/methods in isolation
209
+ - Mock external dependencies
210
+ - Fast execution (milliseconds)
211
+ - Should be 70-80% of all tests
212
+
213
+ #### Integration Tests (GREEN/REFACTOR)
214
+ - Test interaction between components
215
+ - Use real or realistic dependencies
216
+ - Test database/API integrations
217
+ - Should be 15-20% of all tests
218
+
219
+ #### End-to-End Tests (REFACTOR/Integration)
220
+ - Test complete user workflows
221
+ - Test through actual interfaces (CLI, API, UI)
222
+ - Slower but validate full system behavior
223
+ - Should be 5-10% of all tests
224
+
225
+ ## Anti-Patterns to Avoid
226
+
227
+ ### ❌ Implementation-First Development
228
+ ```markdown
229
+ # WRONG - Implementation before tests
230
+ - [ ] 1. Implement feature
231
+ - [ ] 2. Write tests for feature
232
+ ```
233
+
234
+ ### ❌ Skipping Tests for "Simple" Code
235
+ Every feature needs tests, regardless of perceived simplicity.
236
+
237
+ ### ❌ Writing Tests After Implementation
238
+ This leads to tests that just verify what code does, not what it SHOULD do.
239
+
240
+ ### ❌ Testing Implementation Details
241
+ Test behavior and outcomes, not internal implementation.
242
+
243
+ ```typescript
244
+ // ❌ BAD: Testing implementation details
245
+ expect(service.internalCache.size).toBe(0);
246
+
247
+ // ✅ GOOD: Testing behavior
248
+ expect(await service.getUser(id)).toBeNull();
249
+ ```
250
+
251
+ ### ❌ Large, Monolithic Tests
252
+ Break down tests into small, focused units.
253
+
254
+ ## Language-Specific TDD Tools
255
+
256
+ ### TypeScript/JavaScript
257
+ - **Framework**: Jest, Mocha, Vitest
258
+ - **Assertions**: expect, chai
259
+ - **Mocking**: jest.mock(), sinon
260
+ - **Coverage**: Jest --coverage, nyc
261
+
262
+ ### Java
263
+ - **Framework**: JUnit 5, TestNG
264
+ - **Assertions**: AssertJ, Hamcrest
265
+ - **Mocking**: Mockito, EasyMock
266
+ - **Coverage**: JaCoCo, Cobertura
267
+
268
+ ### Python
269
+ - **Framework**: pytest, unittest
270
+ - **Assertions**: assert, pytest fixtures
271
+ - **Mocking**: unittest.mock, pytest-mock
272
+ - **Coverage**: pytest-cov, coverage.py
273
+
274
+ ### Go
275
+ - **Framework**: testing package, Testify
276
+ - **Assertions**: testify/assert
277
+ - **Mocking**: testify/mock, gomock
278
+ - **Coverage**: go test -cover
279
+
280
+ ### Ruby
281
+ - **Framework**: RSpec, Minitest
282
+ - **Assertions**: expect(), assert_equal
283
+ - **Mocking**: rspec-mocks, mocha
284
+ - **Coverage**: SimpleCov
285
+
286
+ ### PHP
287
+ - **Framework**: PHPUnit
288
+ - **Assertions**: assertEquals(), assertTrue()
289
+ - **Mocking**: Mockery, Prophecy
290
+ - **Coverage**: PHPUnit --coverage-html
291
+
292
+ ## Enforcement
293
+
294
+ ### Code Review Checklist
295
+ - [ ] All new features have tests written BEFORE implementation
296
+ - [ ] Tests follow RED → GREEN → REFACTOR cycle
297
+ - [ ] Test coverage meets minimum 80% threshold
298
+ - [ ] Tests are independent and can run in any order
299
+ - [ ] Test names clearly describe expected behavior
300
+ - [ ] Edge cases and error paths are tested
301
+ - [ ] Refactoring maintained green tests
302
+
303
+ ### CI/CD Integration
304
+ - Tests MUST pass before merge
305
+ - Coverage MUST meet threshold (80% minimum)
306
+ - No commits with failing tests to main/develop branches
307
+ - Pre-commit hooks to run tests locally
308
+
309
+ ## Summary
310
+
311
+ **Golden Rule**: Never write production code without a failing test first.
312
+
313
+ **TDD Workflow**:
314
+ 1. 🔴 RED: Write a failing test
315
+ 2. 🟢 GREEN: Write minimal code to pass
316
+ 3. 🔵 REFACTOR: Improve code quality
317
+ 4. ↻ Repeat for next feature
318
+
319
+ **Benefits**:
320
+ - ✅ Code meets requirements by design
321
+ - ✅ Refactoring is safe (tests catch regressions)
322
+ - ✅ Better code design (testable code is often better structured)
323
+ - ✅ Living documentation (tests show how code should work)
324
+ - ✅ Fewer bugs in production
@@ -1,69 +0,0 @@
1
- /**
2
- * SDD directory names
3
- * .spec is the new standard (v2.1.0+)
4
- * .kiro is legacy (for backwards compatibility)
5
- */
6
- export declare const SDD_DIR = ".spec";
7
- export declare const SDD_DIR_LEGACY = ".kiro";
8
- /**
9
- * Get the SDD root directory for a project
10
- * Prefers .spec, falls back to .kiro for legacy projects
11
- *
12
- * @param projectPath - Project root path
13
- * @returns SDD root directory path (.spec or .kiro)
14
- */
15
- export declare function getSddRoot(projectPath: string): string;
16
- /**
17
- * Get the SDD directory name for a project
18
- * Returns the actual directory name used (.spec or .kiro)
19
- *
20
- * @param projectPath - Project root path
21
- * @returns Directory name (.spec or .kiro)
22
- */
23
- export declare function getSddDirName(projectPath: string): string;
24
- /**
25
- * Get the specs directory path
26
- * @param projectPath - Project root path
27
- * @returns Specs directory path
28
- */
29
- export declare function getSpecsPath(projectPath: string): string;
30
- /**
31
- * Get the steering directory path
32
- * @param projectPath - Project root path
33
- * @returns Steering directory path
34
- */
35
- export declare function getSteeringPath(projectPath: string): string;
36
- /**
37
- * Get a feature's spec directory path
38
- * @param projectPath - Project root path
39
- * @param featureName - Feature name
40
- * @returns Feature spec directory path
41
- */
42
- export declare function getFeatureSpecPath(projectPath: string, featureName: string): string;
43
- /**
44
- * Get the spec.json file path for a feature
45
- * @param projectPath - Project root path
46
- * @param featureName - Feature name
47
- * @returns spec.json file path
48
- */
49
- export declare function getSpecJsonPath(projectPath: string, featureName: string): string;
50
- /**
51
- * Check if this is a legacy project (using .kiro instead of .spec)
52
- * @param projectPath - Project root path
53
- * @returns true if project uses .kiro
54
- */
55
- export declare function isLegacyProject(projectPath: string): boolean;
56
- /**
57
- * Get the appropriate SDD directory for new projects
58
- * Always returns .spec for new projects
59
- *
60
- * @param projectPath - Project root path
61
- * @returns Path to create SDD directory (.spec)
62
- */
63
- export declare function getNewSddRoot(projectPath: string): string;
64
- /**
65
- * Create all required SDD directories for a new project
66
- * @param projectPath - Project root path
67
- * @returns Created paths
68
- */
69
- export declare function createSddDirectories(projectPath: string): string[];
@@ -1,138 +0,0 @@
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
@@ -1 +0,0 @@
1
- {"version":3,"file":"sddPaths.js","sourceRoot":"","sources":["../../src/utils/sddPaths.ts"],"names":[],"mappings":"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"}