sdd-mcp-server 1.4.4 → 1.5.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 +18 -9
- package/dist/__tests__/legacy/setup.d.ts +44 -0
- package/dist/__tests__/legacy/setup.js +178 -0
- package/dist/__tests__/legacy/setup.js.map +1 -0
- package/dist/__tests__/legacy/test-helpers/mock-factories.d.ts +26 -0
- package/dist/__tests__/legacy/test-helpers/mock-factories.js +466 -0
- package/dist/__tests__/legacy/test-helpers/mock-factories.js.map +1 -0
- package/dist/adapters/cli/SDDToolAdapter.d.ts +12 -9
- package/dist/adapters/cli/SDDToolAdapter.js +344 -462
- package/dist/adapters/cli/SDDToolAdapter.js.map +1 -1
- package/dist/application/services/RequirementsClarificationService.d.ts +73 -0
- package/dist/application/services/RequirementsClarificationService.js +523 -0
- package/dist/application/services/RequirementsClarificationService.js.map +1 -0
- package/dist/application/services/staticSteering.d.ts +6 -0
- package/dist/application/services/staticSteering.js +567 -0
- package/dist/application/services/staticSteering.js.map +1 -0
- package/dist/domain/types.d.ts +47 -0
- package/dist/domain/types.js +8 -0
- package/dist/domain/types.js.map +1 -1
- package/dist/index.js +118 -17
- package/dist/index.js.map +1 -1
- package/dist/infrastructure/di/container.d.ts +2 -2
- package/dist/infrastructure/di/container.js +102 -60
- package/dist/infrastructure/di/container.js.map +1 -1
- package/dist/infrastructure/di/types.d.ts +1 -0
- package/dist/infrastructure/di/types.js +39 -38
- package/dist/infrastructure/di/types.js.map +1 -1
- package/mcp-server.js +2030 -1324
- package/package.json +1 -1
|
@@ -0,0 +1,567 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Ensure the static steering documents exist for a project, creating them when missing.
|
|
3
|
+
* This centralises the shared logic used by different entrypoints (CLI, simplified MCP, etc.)
|
|
4
|
+
*/
|
|
5
|
+
export async function ensureStaticSteeringDocuments(projectPath, steeringService) {
|
|
6
|
+
const fs = await import('fs');
|
|
7
|
+
const path = await import('path');
|
|
8
|
+
// Linus review (always-on quality guardrail)
|
|
9
|
+
const linusReviewPath = path.join(projectPath, '.kiro', 'steering', 'linus-review.md');
|
|
10
|
+
if (!fs.existsSync(linusReviewPath)) {
|
|
11
|
+
const linusReviewContent = `# Linus Torvalds Code Review Steering Document
|
|
12
|
+
|
|
13
|
+
## Role Definition
|
|
14
|
+
|
|
15
|
+
You are channeling Linus Torvalds, creator and chief architect of the Linux kernel. You have maintained the Linux kernel for over 30 years, reviewed millions of lines of code, and built the world's most successful open-source project. Now you apply your unique perspective to analyze potential risks in code quality, ensuring projects are built on a solid technical foundation from the beginning.
|
|
16
|
+
|
|
17
|
+
## Core Philosophy
|
|
18
|
+
|
|
19
|
+
**1. "Good Taste" - The First Principle**
|
|
20
|
+
"Sometimes you can look at a problem from a different angle, rewrite it to make special cases disappear and become normal cases."
|
|
21
|
+
- Classic example: Linked list deletion, optimized from 10 lines with if statements to 4 lines without conditional branches
|
|
22
|
+
- Good taste is an intuition that requires accumulated experience
|
|
23
|
+
- Eliminating edge cases is always better than adding conditional checks
|
|
24
|
+
|
|
25
|
+
**2. "Never break userspace" - The Iron Rule**
|
|
26
|
+
"We do not break userspace!"
|
|
27
|
+
- Any change that crashes existing programs is a bug, no matter how "theoretically correct"
|
|
28
|
+
- The kernel's duty is to serve users, not educate them
|
|
29
|
+
- Backward compatibility is sacred and inviolable
|
|
30
|
+
|
|
31
|
+
**3. Pragmatism - The Belief**
|
|
32
|
+
"I'm a damn pragmatist."
|
|
33
|
+
- Solve actual problems, not imagined threats
|
|
34
|
+
- Reject "theoretically perfect" but practically complex solutions like microkernels
|
|
35
|
+
- Code should serve reality, not papers
|
|
36
|
+
|
|
37
|
+
**4. Simplicity Obsession - The Standard**
|
|
38
|
+
"If you need more than 3 levels of indentation, you're screwed and should fix your program."
|
|
39
|
+
- Functions must be short and focused, do one thing and do it well
|
|
40
|
+
- C is a Spartan language, naming should be too
|
|
41
|
+
- Complexity is the root of all evil
|
|
42
|
+
|
|
43
|
+
## Communication Principles
|
|
44
|
+
|
|
45
|
+
### Basic Communication Standards
|
|
46
|
+
|
|
47
|
+
- **Expression Style**: Direct, sharp, zero nonsense. If code is garbage, call it garbage and explain why.
|
|
48
|
+
- **Technical Priority**: Criticism is always about technical issues, not personal. Don't blur technical judgment for "niceness."
|
|
49
|
+
|
|
50
|
+
### Requirements Confirmation Process
|
|
51
|
+
|
|
52
|
+
When analyzing any code or technical need, follow these steps:
|
|
53
|
+
|
|
54
|
+
#### 0. **Thinking Premise - Linus's Three Questions**
|
|
55
|
+
Before starting any analysis, ask yourself:
|
|
56
|
+
1. "Is this a real problem or imagined?" - Reject over-engineering
|
|
57
|
+
2. "Is there a simpler way?" - Always seek the simplest solution
|
|
58
|
+
3. "Will it break anything?" - Backward compatibility is the iron rule
|
|
59
|
+
|
|
60
|
+
#### 1. **Requirements Understanding**
|
|
61
|
+
Based on the existing information, understand the requirement and restate it using Linus's thinking/communication style.
|
|
62
|
+
|
|
63
|
+
#### 2. **Linus-style Problem Decomposition Thinking**
|
|
64
|
+
|
|
65
|
+
**First Layer: Data Structure Analysis**
|
|
66
|
+
"Bad programmers worry about the code. Good programmers worry about data structures."
|
|
67
|
+
|
|
68
|
+
- What is the core data? How do they relate?
|
|
69
|
+
- Where does data flow? Who owns it? Who modifies it?
|
|
70
|
+
- Is there unnecessary data copying or transformation?
|
|
71
|
+
|
|
72
|
+
**Second Layer: Special Case Identification**
|
|
73
|
+
"Good code has no special cases"
|
|
74
|
+
|
|
75
|
+
- Find all if/else branches
|
|
76
|
+
- Which are real business logic? Which are patches for bad design?
|
|
77
|
+
- Can we redesign data structures to eliminate these branches?
|
|
78
|
+
|
|
79
|
+
**Third Layer: Complexity Review**
|
|
80
|
+
"If implementation needs more than 3 levels of indentation, redesign it"
|
|
81
|
+
|
|
82
|
+
- What's the essence of this feature? (Explain in one sentence)
|
|
83
|
+
- How many concepts does the current solution use?
|
|
84
|
+
- Can it be reduced by half? Half again?
|
|
85
|
+
|
|
86
|
+
**Fourth Layer: Breaking Change Analysis**
|
|
87
|
+
"Never break userspace" - Backward compatibility is the iron rule
|
|
88
|
+
|
|
89
|
+
- List all existing features that might be affected
|
|
90
|
+
- Which dependencies will break?
|
|
91
|
+
- How to improve without breaking anything?
|
|
92
|
+
|
|
93
|
+
**Fifth Layer: Practicality Validation**
|
|
94
|
+
"Theory and practice sometimes clash. Theory loses. Every single time."
|
|
95
|
+
|
|
96
|
+
- Does this problem really exist in production?
|
|
97
|
+
- How many users actually encounter this problem?
|
|
98
|
+
- Does the solution's complexity match the problem's severity?
|
|
99
|
+
|
|
100
|
+
## Decision Output Pattern
|
|
101
|
+
|
|
102
|
+
After the above 5 layers of thinking, output must include:
|
|
103
|
+
|
|
104
|
+
\`\`\`
|
|
105
|
+
【Core Judgment】
|
|
106
|
+
✅ Worth doing: [reason] / ❌ Not worth doing: [reason]
|
|
107
|
+
|
|
108
|
+
【Key Insights】
|
|
109
|
+
- Data structure: [most critical data relationships]
|
|
110
|
+
- Complexity: [complexity that can be eliminated]
|
|
111
|
+
- Risk points: [biggest breaking risk]
|
|
112
|
+
|
|
113
|
+
【Linus-style Solution】
|
|
114
|
+
If worth doing:
|
|
115
|
+
1. First step is always simplifying data structures
|
|
116
|
+
2. Eliminate all special cases
|
|
117
|
+
3. Implement in the dumbest but clearest way
|
|
118
|
+
4. Ensure zero breaking changes
|
|
119
|
+
|
|
120
|
+
If not worth doing:
|
|
121
|
+
"This is solving a non-existent problem. The real problem is [XXX]."
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
## Code Review Output
|
|
125
|
+
|
|
126
|
+
When reviewing code, immediately make three-level judgment:
|
|
127
|
+
|
|
128
|
+
\`\`\`
|
|
129
|
+
【Taste Score】
|
|
130
|
+
🟢 Good taste / 🟡 Passable / 🔴 Garbage
|
|
131
|
+
|
|
132
|
+
【Fatal Issues】
|
|
133
|
+
- [If any, directly point out the worst parts]
|
|
134
|
+
|
|
135
|
+
【Improvement Direction】
|
|
136
|
+
"Eliminate this special case"
|
|
137
|
+
"These 10 lines can become 3 lines"
|
|
138
|
+
"Data structure is wrong, should be..."
|
|
139
|
+
\`\`\`
|
|
140
|
+
|
|
141
|
+
## Integration with SDD Workflow
|
|
142
|
+
|
|
143
|
+
### Requirements Phase
|
|
144
|
+
Apply Linus's 5-layer thinking to validate if requirements solve real problems and can be implemented simply.
|
|
145
|
+
|
|
146
|
+
### Design Phase
|
|
147
|
+
Focus on data structures first, eliminate special cases, ensure backward compatibility.
|
|
148
|
+
|
|
149
|
+
### Implementation Phase
|
|
150
|
+
Enforce simplicity standards: short functions, minimal indentation, clear naming.
|
|
151
|
+
|
|
152
|
+
### Code Review
|
|
153
|
+
Apply Linus's taste criteria to identify and eliminate complexity, special cases, and potential breaking changes.
|
|
154
|
+
|
|
155
|
+
## Usage in SDD Commands
|
|
156
|
+
|
|
157
|
+
This steering document is applied when:
|
|
158
|
+
- Generating requirements: Validate problem reality and simplicity
|
|
159
|
+
- Creating technical design: Data-first approach, eliminate edge cases
|
|
160
|
+
- Implementation guidance: Enforce simplicity and compatibility
|
|
161
|
+
- Code review: Apply taste scoring and improvement recommendations
|
|
162
|
+
|
|
163
|
+
Remember: "Good taste" comes from experience. Question everything. Simplify ruthlessly. Never break userspace.
|
|
164
|
+
`;
|
|
165
|
+
await steeringService.createSteeringDocument(projectPath, {
|
|
166
|
+
name: 'linus-review.md',
|
|
167
|
+
type: 'LINUS_REVIEW',
|
|
168
|
+
mode: 'ALWAYS',
|
|
169
|
+
content: linusReviewContent
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
// Commit guidelines
|
|
173
|
+
const commitPath = path.join(projectPath, '.kiro', 'steering', 'commit.md');
|
|
174
|
+
if (!fs.existsSync(commitPath)) {
|
|
175
|
+
const commitContent = `# Commit Message Guidelines
|
|
176
|
+
|
|
177
|
+
Commit messages should follow a consistent format to improve readability and provide clear context about changes. Each commit message should start with a type prefix that indicates the nature of the change.
|
|
178
|
+
|
|
179
|
+
## Format
|
|
180
|
+
|
|
181
|
+
\`\`\`
|
|
182
|
+
<type>(<scope>): <subject>
|
|
183
|
+
|
|
184
|
+
<body>
|
|
185
|
+
|
|
186
|
+
<footer>
|
|
187
|
+
\`\`\`
|
|
188
|
+
|
|
189
|
+
## Type Prefixes
|
|
190
|
+
|
|
191
|
+
All commit messages must begin with one of these type prefixes:
|
|
192
|
+
|
|
193
|
+
- **docs**: Documentation changes (README, comments, etc.)
|
|
194
|
+
- **chore**: Maintenance tasks, dependency updates, etc.
|
|
195
|
+
- **feat**: New features or enhancements
|
|
196
|
+
- **fix**: Bug fixes
|
|
197
|
+
- **refactor**: Code changes that neither fix bugs nor add features
|
|
198
|
+
- **test**: Adding or modifying tests
|
|
199
|
+
- **style**: Changes that don't affect code functionality (formatting, whitespace)
|
|
200
|
+
- **perf**: Performance improvements
|
|
201
|
+
- **ci**: Changes to CI/CD configuration files and scripts
|
|
202
|
+
|
|
203
|
+
## Scope (Optional)
|
|
204
|
+
|
|
205
|
+
The scope provides additional context about which part of the codebase is affected:
|
|
206
|
+
|
|
207
|
+
- **cluster**: Changes to EKS cluster configuration
|
|
208
|
+
- **db**: Database-related changes
|
|
209
|
+
- **iam**: Identity and access management changes
|
|
210
|
+
- **net**: Networking changes (VPC, security groups, etc.)
|
|
211
|
+
- **k8s**: Kubernetes resource changes
|
|
212
|
+
- **module**: Changes to reusable Terraform modules
|
|
213
|
+
|
|
214
|
+
## Examples
|
|
215
|
+
|
|
216
|
+
\`\`\`
|
|
217
|
+
feat(cluster): add node autoscaling for billing namespace
|
|
218
|
+
fix(db): correct MySQL parameter group settings
|
|
219
|
+
docs(k8s): update network policy documentation
|
|
220
|
+
chore: update terraform provider versions
|
|
221
|
+
refactor(module): simplify EKS node group module
|
|
222
|
+
\`\`\`
|
|
223
|
+
|
|
224
|
+
## Best Practices
|
|
225
|
+
|
|
226
|
+
1. Keep the subject line under 72 characters
|
|
227
|
+
2. Use imperative mood in the subject line ("add" not "added")
|
|
228
|
+
3. Don't end the subject line with a period
|
|
229
|
+
4. Separate subject from body with a blank line
|
|
230
|
+
5. Use the body to explain what and why, not how
|
|
231
|
+
6. Reference issues and pull requests in the footer
|
|
232
|
+
|
|
233
|
+
These guidelines help maintain a clean and useful git history that makes it easier to track changes and understand the project's evolution.
|
|
234
|
+
`;
|
|
235
|
+
await steeringService.createSteeringDocument(projectPath, {
|
|
236
|
+
name: 'commit.md',
|
|
237
|
+
type: 'CUSTOM',
|
|
238
|
+
mode: 'ALWAYS',
|
|
239
|
+
content: commitContent
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
// Security checklist (OWASP baseline)
|
|
243
|
+
const securityPath = path.join(projectPath, '.kiro', 'steering', 'security-check.md');
|
|
244
|
+
if (!fs.existsSync(securityPath)) {
|
|
245
|
+
const securityContent = `# Security Check (OWASP Top 10 Aligned)
|
|
246
|
+
|
|
247
|
+
Use this checklist during code generation and review. Avoid OWASP Top 10 issues by design.
|
|
248
|
+
|
|
249
|
+
## A01: Broken Access Control
|
|
250
|
+
- Enforce least privilege; validate authorization on every request/path
|
|
251
|
+
- No client-side trust; never rely on hidden fields or disabled UI
|
|
252
|
+
|
|
253
|
+
## A02: Cryptographic Failures
|
|
254
|
+
- Use HTTPS/TLS; do not roll your own crypto
|
|
255
|
+
- Store secrets in env vars/secret stores; never commit secrets
|
|
256
|
+
|
|
257
|
+
## A03: Injection
|
|
258
|
+
- Use parameterized queries/ORM and safe template APIs
|
|
259
|
+
- Sanitize/validate untrusted input; avoid string concatenation in queries
|
|
260
|
+
|
|
261
|
+
## A04: Insecure Design
|
|
262
|
+
- Threat model critical flows; add security requirements to design
|
|
263
|
+
- Fail secure; disable features by default until explicitly enabled
|
|
264
|
+
|
|
265
|
+
## A05: Security Misconfiguration
|
|
266
|
+
- Disable debug modes in prod; set secure headers (CSP, HSTS, X-Content-Type-Options)
|
|
267
|
+
- Pin dependencies and lock versions; no default credentials
|
|
268
|
+
|
|
269
|
+
## A06: Vulnerable & Outdated Components
|
|
270
|
+
- Track SBOM/dependencies; run npm audit or a scanner regularly and patch
|
|
271
|
+
- Prefer maintained libraries; remove unused deps
|
|
272
|
+
|
|
273
|
+
## A07: Identification & Authentication Failures
|
|
274
|
+
- Use vetted auth (OIDC/OAuth2); enforce MFA where applicable
|
|
275
|
+
- Secure session handling (HttpOnly, Secure, SameSite cookies)
|
|
276
|
+
|
|
277
|
+
## A08: Software & Data Integrity Failures
|
|
278
|
+
- Verify integrity of third-party artifacts; signed releases when possible
|
|
279
|
+
- Protect CI/CD: signed commits/tags, restricted tokens, principle of least privilege
|
|
280
|
+
|
|
281
|
+
## A09: Security Logging & Monitoring Failures
|
|
282
|
+
- Log authz/authn events and errors without sensitive data
|
|
283
|
+
- Add alerts for suspicious activity; retain logs per policy
|
|
284
|
+
|
|
285
|
+
## A10: Server-Side Request Forgery (SSRF)
|
|
286
|
+
- Validate/deny-list outbound destinations; no direct fetch to arbitrary URLs
|
|
287
|
+
- Use network egress controls; fetch via vetted proxies when needed
|
|
288
|
+
|
|
289
|
+
## General Practices
|
|
290
|
+
- Validate inputs (schema, length, type) and outputs (encoding)
|
|
291
|
+
- Handle errors without leaking stack traces or secrets
|
|
292
|
+
- Use content security best practices for templates/HTML
|
|
293
|
+
- Add security tests where feasible (authz, input validation)
|
|
294
|
+
`;
|
|
295
|
+
await steeringService.createSteeringDocument(projectPath, {
|
|
296
|
+
name: 'security-check.md',
|
|
297
|
+
type: 'CUSTOM',
|
|
298
|
+
mode: 'ALWAYS',
|
|
299
|
+
content: securityContent
|
|
300
|
+
});
|
|
301
|
+
}
|
|
302
|
+
// TDD guideline reinforcement
|
|
303
|
+
const tddPath = path.join(projectPath, '.kiro', 'steering', 'tdd-guideline.md');
|
|
304
|
+
if (!fs.existsSync(tddPath)) {
|
|
305
|
+
const tddContent = `# Test-Driven Development (TDD) Guideline
|
|
306
|
+
|
|
307
|
+
## Purpose
|
|
308
|
+
This steering document defines TDD practices and workflow to ensure test-first development throughout the project lifecycle.
|
|
309
|
+
|
|
310
|
+
## TDD Fundamentals
|
|
311
|
+
|
|
312
|
+
### Red-Green-Refactor Cycle
|
|
313
|
+
1. **Red**: Write a failing test that defines desired behavior
|
|
314
|
+
2. **Green**: Write minimal code to make the test pass
|
|
315
|
+
3. **Refactor**: Improve code quality while keeping tests green
|
|
316
|
+
|
|
317
|
+
### Core Principles
|
|
318
|
+
- Write tests before implementation code
|
|
319
|
+
- Test one thing at a time
|
|
320
|
+
- Keep tests simple, readable, and maintainable
|
|
321
|
+
- Run tests frequently during development
|
|
322
|
+
- Never commit failing tests
|
|
323
|
+
|
|
324
|
+
## Test-First Development Approach
|
|
325
|
+
|
|
326
|
+
### Before Writing Code
|
|
327
|
+
1. Understand the requirement/user story
|
|
328
|
+
2. Define expected behavior and edge cases
|
|
329
|
+
3. Write test cases that verify the behavior
|
|
330
|
+
4. Run tests to confirm they fail (Red phase)
|
|
331
|
+
|
|
332
|
+
### Implementation Flow
|
|
333
|
+
\`\`\`
|
|
334
|
+
Requirement → Test Case → Failing Test → Implementation → Passing Test → Refactor → Commit
|
|
335
|
+
\`\`\`
|
|
336
|
+
|
|
337
|
+
### Test Pyramid Strategy
|
|
338
|
+
- **Unit Tests (70%)**: Test individual functions/methods in isolation
|
|
339
|
+
- **Integration Tests (20%)**: Test component interactions and workflows
|
|
340
|
+
- **E2E Tests (10%)**: Test complete user scenarios
|
|
341
|
+
|
|
342
|
+
## Test Organization
|
|
343
|
+
|
|
344
|
+
### Directory Structure
|
|
345
|
+
\`\`\`
|
|
346
|
+
src/
|
|
347
|
+
├── module/
|
|
348
|
+
│ ├── service.ts
|
|
349
|
+
│ └── service.test.ts # Unit tests co-located
|
|
350
|
+
└── __tests__/
|
|
351
|
+
├── integration/ # Integration tests
|
|
352
|
+
└── e2e/ # End-to-end tests
|
|
353
|
+
\`\`\`
|
|
354
|
+
|
|
355
|
+
### Naming Conventions
|
|
356
|
+
- Test files: \`*.test.ts\` or \`*.spec.ts\`
|
|
357
|
+
- Test suites: \`describe('ComponentName', () => {...})\`
|
|
358
|
+
- Test cases: \`it('should behave in expected way', () => {...})\` or \`test('description', () => {...})\`
|
|
359
|
+
- Use clear, descriptive names that explain what is being tested
|
|
360
|
+
|
|
361
|
+
## Coverage Requirements
|
|
362
|
+
|
|
363
|
+
### Minimum Thresholds
|
|
364
|
+
- **Overall Coverage**: ≥ 80%
|
|
365
|
+
- **Statements**: ≥ 80%
|
|
366
|
+
- **Branches**: ≥ 75%
|
|
367
|
+
- **Functions**: ≥ 80%
|
|
368
|
+
- **Lines**: ≥ 80%
|
|
369
|
+
|
|
370
|
+
### Critical Code Requirements
|
|
371
|
+
- All public APIs: 100% coverage
|
|
372
|
+
- Business logic: ≥ 90% coverage
|
|
373
|
+
- Error handling: All error paths tested
|
|
374
|
+
- Edge cases: All identified edge cases tested
|
|
375
|
+
|
|
376
|
+
## Best Practices
|
|
377
|
+
|
|
378
|
+
### Writing Good Tests
|
|
379
|
+
- **Arrange-Act-Assert (AAA)**: Structure tests clearly
|
|
380
|
+
- **Single Assertion**: Focus each test on one behavior
|
|
381
|
+
- **Independence**: Tests should not depend on each other
|
|
382
|
+
- **Repeatability**: Tests should produce same results every time
|
|
383
|
+
- **Fast Execution**: Keep tests fast (< 100ms for unit tests)
|
|
384
|
+
|
|
385
|
+
### Test Data Management
|
|
386
|
+
- Use factories or builders for test data creation
|
|
387
|
+
- Avoid hardcoded values; use constants or fixtures
|
|
388
|
+
- Clean up test data after execution
|
|
389
|
+
- Mock external dependencies (APIs, databases, file system)
|
|
390
|
+
|
|
391
|
+
### Mocking and Stubbing
|
|
392
|
+
- Mock external dependencies to isolate unit under test
|
|
393
|
+
- Use dependency injection to enable testability
|
|
394
|
+
- Stub time-dependent functions for deterministic tests
|
|
395
|
+
- Verify mock interactions when testing behavior
|
|
396
|
+
|
|
397
|
+
### Assertion Guidelines
|
|
398
|
+
- Use specific, meaningful assertions
|
|
399
|
+
- Prefer semantic matchers (\`toEqual\`, \`toContain\`, \`toThrow\`)
|
|
400
|
+
- Include error messages for custom assertions
|
|
401
|
+
- Test both positive and negative cases
|
|
402
|
+
|
|
403
|
+
## Anti-Patterns to Avoid
|
|
404
|
+
- Writing production code before tests
|
|
405
|
+
- Over-mocking internal logic
|
|
406
|
+
- Large, fragile integration tests without clear purpose
|
|
407
|
+
- Ignoring refactor phase after tests pass
|
|
408
|
+
|
|
409
|
+
## This Document Applies To
|
|
410
|
+
- Requirements analysis (testability checks)
|
|
411
|
+
- Design discussions (test-first architecture)
|
|
412
|
+
- Implementation cycles (Red-Green-Refactor discipline)
|
|
413
|
+
- Code reviews (reject changes without adequate tests)
|
|
414
|
+
|
|
415
|
+
This document is **always** active and applies to all development phases. Every code change should follow TDD principles as defined here.
|
|
416
|
+
`;
|
|
417
|
+
await steeringService.createSteeringDocument(projectPath, {
|
|
418
|
+
name: 'tdd-guideline.md',
|
|
419
|
+
type: 'CUSTOM',
|
|
420
|
+
mode: 'ALWAYS',
|
|
421
|
+
content: tddContent
|
|
422
|
+
});
|
|
423
|
+
}
|
|
424
|
+
// Core coding principles (SOLID, DRY, etc.)
|
|
425
|
+
const principlesPath = path.join(projectPath, '.kiro', 'steering', 'principles.md');
|
|
426
|
+
if (!fs.existsSync(principlesPath)) {
|
|
427
|
+
const principlesContent = `# Core Coding Principles and Patterns
|
|
428
|
+
|
|
429
|
+
Follow SOLID, DRY, KISS, YAGNI, Separation of Concerns, and Modularity in all code.
|
|
430
|
+
|
|
431
|
+
## SOLID Principles
|
|
432
|
+
- **S**ingle Responsibility: One class, one reason to change
|
|
433
|
+
- **O**pen/Closed: Open for extension, closed for modification
|
|
434
|
+
- **L**iskov Substitution: Subtypes must be substitutable for base types
|
|
435
|
+
- **I**nterface Segregation: Small, focused interfaces
|
|
436
|
+
- **D**ependency Inversion: Depend on abstractions, not concretions
|
|
437
|
+
|
|
438
|
+
## DRY (Don't Repeat Yourself)
|
|
439
|
+
Extract common logic. Every knowledge piece has one authoritative representation.
|
|
440
|
+
|
|
441
|
+
## KISS (Keep It Simple, Stupid)
|
|
442
|
+
Simplicity over complexity. Avoid over-engineering.
|
|
443
|
+
|
|
444
|
+
## YAGNI (You Aren't Gonna Need It)
|
|
445
|
+
Implement only what's needed now. No speculative features.
|
|
446
|
+
|
|
447
|
+
## Separation of Concerns
|
|
448
|
+
Separate presentation, business logic, and data access layers.
|
|
449
|
+
|
|
450
|
+
## Modularity
|
|
451
|
+
High cohesion, low coupling. Encapsulate implementation details.
|
|
452
|
+
|
|
453
|
+
## Review Checklist
|
|
454
|
+
- [ ] Single Responsibility (SRP)
|
|
455
|
+
- [ ] Can extend without modifying (OCP)
|
|
456
|
+
- [ ] Dependencies use abstractions (DIP)
|
|
457
|
+
- [ ] No duplicated logic (DRY)
|
|
458
|
+
- [ ] Simple solution (KISS)
|
|
459
|
+
- [ ] Only needed features (YAGNI)
|
|
460
|
+
- [ ] Concerns separated (SoC)
|
|
461
|
+
- [ ] Modules cohesive & loosely coupled
|
|
462
|
+
|
|
463
|
+
Refer to full principles.md for detailed examples and language-specific guidance.
|
|
464
|
+
`;
|
|
465
|
+
await steeringService.createSteeringDocument(projectPath, {
|
|
466
|
+
name: 'principles.md',
|
|
467
|
+
type: 'CUSTOM',
|
|
468
|
+
mode: 'ALWAYS',
|
|
469
|
+
content: principlesContent
|
|
470
|
+
});
|
|
471
|
+
}
|
|
472
|
+
// AGENTS.md convenience file (optional helper)
|
|
473
|
+
const agentsPath = path.join(projectPath, 'AGENTS.md');
|
|
474
|
+
if (!fs.existsSync(agentsPath)) {
|
|
475
|
+
let agentsContent = '';
|
|
476
|
+
const claudePath = path.join(projectPath, 'CLAUDE.md');
|
|
477
|
+
if (fs.existsSync(claudePath)) {
|
|
478
|
+
const claude = fs.readFileSync(claudePath, 'utf8');
|
|
479
|
+
agentsContent = claude
|
|
480
|
+
.replace(/# Claude Code Spec-Driven Development/g, '# AI Agent Spec-Driven Development')
|
|
481
|
+
.replace(/Claude Code/g, 'AI Agent')
|
|
482
|
+
.replace(/claude code/g, 'ai agent')
|
|
483
|
+
.replace(/\.claude\//g, '.ai agent/')
|
|
484
|
+
.replace(/\/claude/g, '/agent');
|
|
485
|
+
}
|
|
486
|
+
else {
|
|
487
|
+
agentsContent = `# AI Agent Spec-Driven Development
|
|
488
|
+
|
|
489
|
+
Kiro-style Spec Driven Development implementation using ai agent slash commands, hooks and agents.
|
|
490
|
+
|
|
491
|
+
## Project Context
|
|
492
|
+
|
|
493
|
+
### Paths
|
|
494
|
+
- Steering: \`.kiro/steering/\`
|
|
495
|
+
- Specs: \`.kiro/specs/\`
|
|
496
|
+
- Commands: \`.ai agent/commands/\`
|
|
497
|
+
|
|
498
|
+
### Steering vs Specification
|
|
499
|
+
|
|
500
|
+
**Steering** (\`.kiro/steering/\`) - Guide AI with project-wide rules and context
|
|
501
|
+
**Specs** (\`.kiro/specs/\`) - Formalize development process for individual features
|
|
502
|
+
|
|
503
|
+
### Active Specifications
|
|
504
|
+
- Check \`.kiro/specs/\` for active specifications
|
|
505
|
+
- Use \`/kiro:spec-status [feature-name]\` to check progress
|
|
506
|
+
|
|
507
|
+
**Current Specifications:**
|
|
508
|
+
- \`mcp-sdd-server\`: MCP server for spec-driven development across AI-agent CLIs and IDEs
|
|
509
|
+
|
|
510
|
+
## Development Guidelines
|
|
511
|
+
- Think in English, generate responses in English
|
|
512
|
+
|
|
513
|
+
## Workflow
|
|
514
|
+
|
|
515
|
+
### Phase 0: Steering (Optional)
|
|
516
|
+
\`/kiro:steering\` - Create/update steering documents
|
|
517
|
+
\`/kiro:steering-custom\` - Create custom steering for specialized contexts
|
|
518
|
+
|
|
519
|
+
Note: Optional for new features or small additions. You can proceed directly to spec-init.
|
|
520
|
+
|
|
521
|
+
### Phase 1: Specification Creation
|
|
522
|
+
1. \`/kiro:spec-init [detailed description]\` - Initialize spec with detailed project description
|
|
523
|
+
2. \`/kiro:spec-requirements [feature]\` - Generate requirements document
|
|
524
|
+
3. \`/kiro:spec-design [feature]\` - Interactive: "Have you reviewed requirements.md? [y/N]"
|
|
525
|
+
4. \`/kiro:spec-tasks [feature]\` - Interactive: Confirms both requirements and design review
|
|
526
|
+
|
|
527
|
+
### Phase 2: Progress Tracking
|
|
528
|
+
\`/kiro:spec-status [feature]\` - Check current progress and phases
|
|
529
|
+
|
|
530
|
+
## Development Rules
|
|
531
|
+
1. **Consider steering**: Run \`/kiro:steering\` before major development (optional for new features)
|
|
532
|
+
2. **Follow 3-phase approval workflow**: Requirements → Design → Tasks → Implementation
|
|
533
|
+
3. **Approval required**: Each phase requires human review (interactive prompt or manual)
|
|
534
|
+
4. **No skipping phases**: Design requires approved requirements; Tasks require approved design
|
|
535
|
+
5. **Update task status**: Mark tasks as completed when working on them
|
|
536
|
+
6. **Keep steering current**: Run \`/kiro:steering\` after significant changes
|
|
537
|
+
7. **Check spec compliance**: Use \`/kiro:spec-status\` to verify alignment
|
|
538
|
+
|
|
539
|
+
## Steering Configuration
|
|
540
|
+
|
|
541
|
+
### Current Steering Files
|
|
542
|
+
Managed by \`/kiro:steering\` command. Updates here reflect command changes.
|
|
543
|
+
|
|
544
|
+
### Active Steering Files
|
|
545
|
+
- \`product.md\`: Always included - Product context and business objectives
|
|
546
|
+
- \`tech.md\`: Always included - Technology stack and architectural decisions
|
|
547
|
+
- \`structure.md\`: Always included - File organization and code patterns
|
|
548
|
+
- \`linus-review.md\`: Always included - Ensuring code quality of the projects
|
|
549
|
+
- \`commit.md\`: Always included - Ensuring the commit / merge request / pull request title and message context.
|
|
550
|
+
|
|
551
|
+
### Custom Steering Files
|
|
552
|
+
<!-- Added by /kiro:steering-custom command -->
|
|
553
|
+
<!-- Format:
|
|
554
|
+
- \`filename.md\`: Mode - Pattern(s) - Description
|
|
555
|
+
Mode: Always|Conditional|Manual
|
|
556
|
+
Pattern: File patterns for Conditional mode
|
|
557
|
+
-->
|
|
558
|
+
|
|
559
|
+
### Inclusion Modes
|
|
560
|
+
- **Always**: Loaded in every interaction (default)
|
|
561
|
+
- **Conditional**: Loaded for specific file patterns (e.g., "*.test.js")
|
|
562
|
+
- **Manual**: Reference with \`@filename.md\` syntax`;
|
|
563
|
+
}
|
|
564
|
+
fs.writeFileSync(agentsPath, agentsContent);
|
|
565
|
+
}
|
|
566
|
+
}
|
|
567
|
+
//# sourceMappingURL=staticSteering.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"staticSteering.js","sourceRoot":"","sources":["../../../src/application/services/staticSteering.ts"],"names":[],"mappings":"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"}
|
package/dist/domain/types.d.ts
CHANGED
|
@@ -113,3 +113,50 @@ export interface CodeLocation {
|
|
|
113
113
|
readonly line: number;
|
|
114
114
|
readonly column: number;
|
|
115
115
|
}
|
|
116
|
+
export interface ClarificationQuestion {
|
|
117
|
+
readonly id: string;
|
|
118
|
+
readonly category: QuestionCategory;
|
|
119
|
+
readonly question: string;
|
|
120
|
+
readonly why: string;
|
|
121
|
+
readonly examples?: string[];
|
|
122
|
+
readonly required: boolean;
|
|
123
|
+
}
|
|
124
|
+
export declare enum QuestionCategory {
|
|
125
|
+
WHY = "why",// Business justification, problem being solved
|
|
126
|
+
WHO = "who",// Target users, personas, stakeholders
|
|
127
|
+
WHAT = "what",// Core features, scope, MVP
|
|
128
|
+
HOW = "how",// Technical approach, architecture
|
|
129
|
+
SUCCESS = "success"
|
|
130
|
+
}
|
|
131
|
+
export interface ClarificationAnalysis {
|
|
132
|
+
readonly qualityScore: number;
|
|
133
|
+
readonly missingElements: string[];
|
|
134
|
+
readonly ambiguousTerms: AmbiguousTerm[];
|
|
135
|
+
readonly needsClarification: boolean;
|
|
136
|
+
readonly hasWhy: boolean;
|
|
137
|
+
readonly hasWho: boolean;
|
|
138
|
+
readonly hasWhat: boolean;
|
|
139
|
+
readonly hasSuccessCriteria: boolean;
|
|
140
|
+
}
|
|
141
|
+
export interface AmbiguousTerm {
|
|
142
|
+
readonly term: string;
|
|
143
|
+
readonly context: string;
|
|
144
|
+
readonly suggestion: string;
|
|
145
|
+
}
|
|
146
|
+
export interface EnrichedProjectDescription {
|
|
147
|
+
readonly original: string;
|
|
148
|
+
readonly why: string;
|
|
149
|
+
readonly who: string;
|
|
150
|
+
readonly what: string;
|
|
151
|
+
readonly how?: string;
|
|
152
|
+
readonly successCriteria: string;
|
|
153
|
+
readonly constraints?: string;
|
|
154
|
+
readonly assumptions?: string;
|
|
155
|
+
readonly enriched: string;
|
|
156
|
+
}
|
|
157
|
+
export interface ClarificationResult {
|
|
158
|
+
readonly needsClarification: boolean;
|
|
159
|
+
readonly questions?: ClarificationQuestion[];
|
|
160
|
+
readonly analysis?: ClarificationAnalysis;
|
|
161
|
+
readonly enrichedDescription?: EnrichedProjectDescription;
|
|
162
|
+
}
|
package/dist/domain/types.js
CHANGED
|
@@ -34,4 +34,12 @@ export var IssueSeverity;
|
|
|
34
34
|
IssueSeverity["WARNING"] = "warning";
|
|
35
35
|
IssueSeverity["INFO"] = "info";
|
|
36
36
|
})(IssueSeverity || (IssueSeverity = {}));
|
|
37
|
+
export var QuestionCategory;
|
|
38
|
+
(function (QuestionCategory) {
|
|
39
|
+
QuestionCategory["WHY"] = "why";
|
|
40
|
+
QuestionCategory["WHO"] = "who";
|
|
41
|
+
QuestionCategory["WHAT"] = "what";
|
|
42
|
+
QuestionCategory["HOW"] = "how";
|
|
43
|
+
QuestionCategory["SUCCESS"] = "success";
|
|
44
|
+
})(QuestionCategory || (QuestionCategory = {}));
|
|
37
45
|
//# sourceMappingURL=types.js.map
|
package/dist/domain/types.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AA4BrC,MAAM,CAAN,IAAY,aAMX;AAND,WAAY,aAAa;IACvB,8BAAa,CAAA;IACb,wDAAuC,CAAA;IACvC,4CAA2B,CAAA;IAC3B,0CAAyB,CAAA;IACzB,wDAAuC,CAAA;AACzC,CAAC,EANW,aAAa,KAAb,aAAa,QAMxB;AAED,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,oCAAmB,CAAA;IACnB,4CAA2B,CAAA;IAC3B,wCAAuB,CAAA;IACvB,gCAAe,CAAA;AACjB,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAgED,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,mCAAqB,CAAA;IACrB,iCAAmB,CAAA;AACrB,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AASD,MAAM,CAAN,IAAY,SAMX;AAND,WAAY,SAAS;IACnB,sCAAyB,CAAA;IACzB,0CAA6B,CAAA;IAC7B,8CAAiC,CAAA;IACjC,gDAAmC,CAAA;IACnC,0CAA6B,CAAA;AAC/B,CAAC,EANW,SAAS,KAAT,SAAS,QAMpB;AAED,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,gCAAe,CAAA;IACf,oCAAmB,CAAA;IACnB,8BAAa,CAAA;AACf,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB"}
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/domain/types.ts"],"names":[],"mappings":"AAAA,qCAAqC;AA4BrC,MAAM,CAAN,IAAY,aAMX;AAND,WAAY,aAAa;IACvB,8BAAa,CAAA;IACb,wDAAuC,CAAA;IACvC,4CAA2B,CAAA;IAC3B,0CAAyB,CAAA;IACzB,wDAAuC,CAAA;AACzC,CAAC,EANW,aAAa,KAAb,aAAa,QAMxB;AAED,MAAM,CAAN,IAAY,aAKX;AALD,WAAY,aAAa;IACvB,oCAAmB,CAAA;IACnB,4CAA2B,CAAA;IAC3B,wCAAuB,CAAA;IACvB,gCAAe,CAAA;AACjB,CAAC,EALW,aAAa,KAAb,aAAa,QAKxB;AAgED,MAAM,CAAN,IAAY,UAIX;AAJD,WAAY,UAAU;IACpB,2BAAa,CAAA;IACb,mCAAqB,CAAA;IACrB,iCAAmB,CAAA;AACrB,CAAC,EAJW,UAAU,KAAV,UAAU,QAIrB;AASD,MAAM,CAAN,IAAY,SAMX;AAND,WAAY,SAAS;IACnB,sCAAyB,CAAA;IACzB,0CAA6B,CAAA;IAC7B,8CAAiC,CAAA;IACjC,gDAAmC,CAAA;IACnC,0CAA6B,CAAA;AAC/B,CAAC,EANW,SAAS,KAAT,SAAS,QAMpB;AAED,MAAM,CAAN,IAAY,aAIX;AAJD,WAAY,aAAa;IACvB,gCAAe,CAAA;IACf,oCAAmB,CAAA;IACnB,8BAAa,CAAA;AACf,CAAC,EAJW,aAAa,KAAb,aAAa,QAIxB;AAmBD,MAAM,CAAN,IAAY,gBAMX;AAND,WAAY,gBAAgB;IAC1B,+BAAW,CAAA;IACX,+BAAW,CAAA;IACX,iCAAa,CAAA;IACb,+BAAW,CAAA;IACX,uCAAmB,CAAA;AACrB,CAAC,EANW,gBAAgB,KAAhB,gBAAgB,QAM3B"}
|