konductor 0.6.0 → 0.7.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/agents/konductor-codebase-mapper.json +8 -0
- package/agents/konductor-discoverer.json +8 -0
- package/agents/konductor-executor.json +13 -0
- package/agents/konductor-plan-checker.json +11 -0
- package/agents/konductor-planner.json +13 -0
- package/agents/konductor-researcher.json +12 -0
- package/agents/konductor-verifier.json +12 -0
- package/agents/konductor.json +25 -0
- package/hooks/konductor-hooks.json +16 -0
- package/package.json +9 -1
- package/scripts/postinstall.js +38 -0
- package/skills/konductor-discuss/SKILL.md +179 -0
- package/skills/konductor-exec/SKILL.md +143 -0
- package/skills/konductor-exec/references/execution-guide.md +294 -0
- package/skills/konductor-exec/references/tdd.md +450 -0
- package/skills/konductor-init/SKILL.md +95 -0
- package/skills/konductor-init/references/questioning.md +197 -0
- package/skills/konductor-map-codebase/SKILL.md +190 -0
- package/skills/konductor-next/SKILL.md +150 -0
- package/skills/konductor-plan/SKILL.md +91 -0
- package/skills/konductor-plan/references/planning-guide.md +265 -0
- package/skills/konductor-plan/references/verification-patterns.md +400 -0
- package/skills/konductor-ship/SKILL.md +165 -0
- package/skills/konductor-status/SKILL.md +109 -0
- package/skills/konductor-verify/SKILL.md +116 -0
- package/skills/konductor-verify/references/verification-patterns.md +400 -0
|
@@ -0,0 +1,450 @@
|
|
|
1
|
+
# TDD Patterns — Test-Driven Development for Executors
|
|
2
|
+
|
|
3
|
+
This guide covers test-driven development (TDD) practices for executor agents implementing plans with `type = "tdd"`.
|
|
4
|
+
|
|
5
|
+
## When to Use TDD
|
|
6
|
+
|
|
7
|
+
Use TDD when the plan frontmatter specifies `type = "tdd"`.
|
|
8
|
+
|
|
9
|
+
**TDD is appropriate for:**
|
|
10
|
+
- Pure functions with clear input/output contracts
|
|
11
|
+
- Business logic and validation rules
|
|
12
|
+
- Data transformations and parsing
|
|
13
|
+
- Algorithmic code (sorting, filtering, calculations)
|
|
14
|
+
- API endpoints with well-defined contracts
|
|
15
|
+
|
|
16
|
+
**TDD is NOT appropriate for:**
|
|
17
|
+
- UI components with complex interactions
|
|
18
|
+
- Infrastructure setup (databases, servers)
|
|
19
|
+
- Exploratory work with unclear requirements
|
|
20
|
+
- Simple CRUD operations with no business logic
|
|
21
|
+
|
|
22
|
+
## The Red-Green-Refactor Cycle
|
|
23
|
+
|
|
24
|
+
TDD follows a three-phase cycle:
|
|
25
|
+
|
|
26
|
+
### 1. Red Phase: Write Failing Tests
|
|
27
|
+
|
|
28
|
+
Write tests that express the desired behavior from the plan's `must_haves.truths`.
|
|
29
|
+
|
|
30
|
+
**Rules:**
|
|
31
|
+
- Tests should fail initially (no implementation exists yet)
|
|
32
|
+
- Tests should be specific and focused (one behavior per test)
|
|
33
|
+
- Test names should describe the behavior, not the implementation
|
|
34
|
+
|
|
35
|
+
**Example (Rust):**
|
|
36
|
+
```rust
|
|
37
|
+
#[cfg(test)]
|
|
38
|
+
mod tests {
|
|
39
|
+
use super::*;
|
|
40
|
+
|
|
41
|
+
#[test]
|
|
42
|
+
fn test_password_validator_requires_minimum_length() {
|
|
43
|
+
let result = validate_password("short");
|
|
44
|
+
assert!(result.is_err());
|
|
45
|
+
assert_eq!(result.unwrap_err(), "Password must be at least 8 characters");
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
#[test]
|
|
49
|
+
fn test_password_validator_requires_uppercase() {
|
|
50
|
+
let result = validate_password("nouppercase123!");
|
|
51
|
+
assert!(result.is_err());
|
|
52
|
+
assert_eq!(result.unwrap_err(), "Password must contain at least one uppercase letter");
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
#[test]
|
|
56
|
+
fn test_password_validator_accepts_valid_password() {
|
|
57
|
+
let result = validate_password("ValidPass123!");
|
|
58
|
+
assert!(result.is_ok());
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
**Commit after red phase:**
|
|
64
|
+
```
|
|
65
|
+
test(auth-plan-2): add password validation tests (red phase)
|
|
66
|
+
|
|
67
|
+
Tests verify:
|
|
68
|
+
- Minimum 8 characters required
|
|
69
|
+
- At least one uppercase letter required
|
|
70
|
+
- Valid passwords accepted
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
### 2. Green Phase: Write Minimal Implementation
|
|
74
|
+
|
|
75
|
+
Write the simplest code that makes the tests pass.
|
|
76
|
+
|
|
77
|
+
**Rules:**
|
|
78
|
+
- Focus on making tests pass, not on perfection
|
|
79
|
+
- Avoid premature optimization
|
|
80
|
+
- Don't add features not covered by tests
|
|
81
|
+
|
|
82
|
+
**Example (Rust):**
|
|
83
|
+
```rust
|
|
84
|
+
pub fn validate_password(password: &str) -> Result<(), String> {
|
|
85
|
+
if password.len() < 8 {
|
|
86
|
+
return Err("Password must be at least 8 characters".to_string());
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if !password.chars().any(|c| c.is_uppercase()) {
|
|
90
|
+
return Err("Password must contain at least one uppercase letter".to_string());
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
Ok(())
|
|
94
|
+
}
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
**Verify:**
|
|
98
|
+
```bash
|
|
99
|
+
cargo test password
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
**Commit after green phase:**
|
|
103
|
+
```
|
|
104
|
+
feat(auth-plan-2): implement password validation (green phase)
|
|
105
|
+
|
|
106
|
+
Validates:
|
|
107
|
+
- Minimum length of 8 characters
|
|
108
|
+
- At least one uppercase letter
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
### 3. Refactor Phase: Improve Code Quality
|
|
112
|
+
|
|
113
|
+
Improve the code structure while keeping tests green.
|
|
114
|
+
|
|
115
|
+
**Rules:**
|
|
116
|
+
- Tests must continue to pass
|
|
117
|
+
- Improve readability, not functionality
|
|
118
|
+
- Extract common patterns
|
|
119
|
+
- Remove duplication
|
|
120
|
+
|
|
121
|
+
**Example (Rust):**
|
|
122
|
+
```rust
|
|
123
|
+
pub fn validate_password(password: &str) -> Result<(), String> {
|
|
124
|
+
let validators = [
|
|
125
|
+
(|p: &str| p.len() >= 8, "Password must be at least 8 characters"),
|
|
126
|
+
(|p: &str| p.chars().any(|c| c.is_uppercase()), "Password must contain at least one uppercase letter"),
|
|
127
|
+
];
|
|
128
|
+
|
|
129
|
+
for (validator, error_msg) in validators {
|
|
130
|
+
if !validator(password) {
|
|
131
|
+
return Err(error_msg.to_string());
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
Ok(())
|
|
136
|
+
}
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
**Commit after refactor phase:**
|
|
140
|
+
```
|
|
141
|
+
refactor(auth-plan-2): extract password validators into array
|
|
142
|
+
|
|
143
|
+
No behavior change. Improves readability and makes adding new validators easier.
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
## Test Structure
|
|
147
|
+
|
|
148
|
+
### Arrange-Act-Assert (AAA) Pattern
|
|
149
|
+
|
|
150
|
+
Structure tests in three parts:
|
|
151
|
+
|
|
152
|
+
```rust
|
|
153
|
+
#[test]
|
|
154
|
+
fn test_calculate_discount_for_vip_customer() {
|
|
155
|
+
// Arrange: Set up test data
|
|
156
|
+
let customer = Customer::new("vip-123", CustomerTier::VIP);
|
|
157
|
+
let order = Order::new(100.0);
|
|
158
|
+
|
|
159
|
+
// Act: Execute the behavior
|
|
160
|
+
let discount = calculate_discount(&customer, &order);
|
|
161
|
+
|
|
162
|
+
// Assert: Verify the result
|
|
163
|
+
assert_eq!(discount, 20.0); // VIP gets 20% discount
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
### Test Naming Conventions
|
|
168
|
+
|
|
169
|
+
Use descriptive names that express intent:
|
|
170
|
+
|
|
171
|
+
**Good:**
|
|
172
|
+
- `test_validates_email_format`
|
|
173
|
+
- `test_rejects_duplicate_usernames`
|
|
174
|
+
- `test_calculates_total_with_tax`
|
|
175
|
+
|
|
176
|
+
**Bad:**
|
|
177
|
+
- `test1`
|
|
178
|
+
- `test_user`
|
|
179
|
+
- `test_works`
|
|
180
|
+
|
|
181
|
+
### Test Data
|
|
182
|
+
|
|
183
|
+
Use meaningful test data that represents real scenarios:
|
|
184
|
+
|
|
185
|
+
**Good:**
|
|
186
|
+
```javascript
|
|
187
|
+
test('parses ISO date strings', () => {
|
|
188
|
+
const result = parseDate('2024-03-19T10:30:00Z');
|
|
189
|
+
expect(result.year).toBe(2024);
|
|
190
|
+
expect(result.month).toBe(3);
|
|
191
|
+
expect(result.day).toBe(19);
|
|
192
|
+
});
|
|
193
|
+
```
|
|
194
|
+
|
|
195
|
+
**Bad:**
|
|
196
|
+
```javascript
|
|
197
|
+
test('parses dates', () => {
|
|
198
|
+
const result = parseDate('foo');
|
|
199
|
+
expect(result).toBeDefined();
|
|
200
|
+
});
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
## Test-First for Observable Behaviors
|
|
204
|
+
|
|
205
|
+
Write tests for the plan's `must_haves.truths` before implementing.
|
|
206
|
+
|
|
207
|
+
**Example plan truth:** "Users cannot register with duplicate email addresses"
|
|
208
|
+
|
|
209
|
+
**Test first:**
|
|
210
|
+
```python
|
|
211
|
+
def test_registration_rejects_duplicate_email():
|
|
212
|
+
# Arrange: Create first user
|
|
213
|
+
user1 = User.create(email="test@example.com", password="Pass123!")
|
|
214
|
+
|
|
215
|
+
# Act: Try to create second user with same email
|
|
216
|
+
with pytest.raises(DuplicateEmailError):
|
|
217
|
+
user2 = User.create(email="test@example.com", password="Pass456!")
|
|
218
|
+
|
|
219
|
+
# Assert: Only one user exists
|
|
220
|
+
assert User.count_by_email("test@example.com") == 1
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
Then implement the logic to make it pass.
|
|
224
|
+
|
|
225
|
+
## Verification Commands
|
|
226
|
+
|
|
227
|
+
Tests must be automated and run quickly (< 60 seconds).
|
|
228
|
+
|
|
229
|
+
**By language/framework:**
|
|
230
|
+
|
|
231
|
+
### Rust (cargo test)
|
|
232
|
+
```bash
|
|
233
|
+
cargo test # Run all tests
|
|
234
|
+
cargo test user:: # Run tests in user module
|
|
235
|
+
cargo test --lib # Run library tests only
|
|
236
|
+
cargo test -- --nocapture # Show println! output
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
### JavaScript/TypeScript (Jest/Vitest)
|
|
240
|
+
```bash
|
|
241
|
+
npm test # Run all tests
|
|
242
|
+
npm test user.test.ts # Run specific test file
|
|
243
|
+
npm test -- --watch # Run in watch mode
|
|
244
|
+
npm test -- --coverage # Generate coverage report
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
### Python (pytest)
|
|
248
|
+
```bash
|
|
249
|
+
pytest # Run all tests
|
|
250
|
+
pytest tests/test_user.py # Run specific test file
|
|
251
|
+
pytest -k "email" # Run tests matching "email"
|
|
252
|
+
pytest -v # Verbose output
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
### Go (go test)
|
|
256
|
+
```bash
|
|
257
|
+
go test ./... # Run all tests in all packages
|
|
258
|
+
go test -v # Verbose output
|
|
259
|
+
go test -run TestUser # Run specific test
|
|
260
|
+
go test -cover # Show coverage
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
## Test Patterns by Stack
|
|
264
|
+
|
|
265
|
+
### REST API Testing
|
|
266
|
+
|
|
267
|
+
```javascript
|
|
268
|
+
// Jest + Supertest
|
|
269
|
+
test('POST /auth/register returns 201 with user JSON', async () => {
|
|
270
|
+
const response = await request(app)
|
|
271
|
+
.post('/auth/register')
|
|
272
|
+
.send({ email: 'test@example.com', password: 'Pass123!' })
|
|
273
|
+
.expect(201);
|
|
274
|
+
|
|
275
|
+
expect(response.body).toHaveProperty('id');
|
|
276
|
+
expect(response.body.email).toBe('test@example.com');
|
|
277
|
+
expect(response.body).not.toHaveProperty('password');
|
|
278
|
+
});
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
### Database Testing
|
|
282
|
+
|
|
283
|
+
```python
|
|
284
|
+
# pytest with fixtures
|
|
285
|
+
@pytest.fixture
|
|
286
|
+
def db():
|
|
287
|
+
"""Create a fresh database for each test"""
|
|
288
|
+
connection = create_test_db()
|
|
289
|
+
yield connection
|
|
290
|
+
connection.drop_all()
|
|
291
|
+
|
|
292
|
+
def test_user_saved_to_database(db):
|
|
293
|
+
user = User(email="test@example.com", password_hash="hashed")
|
|
294
|
+
db.save(user)
|
|
295
|
+
|
|
296
|
+
retrieved = db.query(User).filter_by(email="test@example.com").first()
|
|
297
|
+
assert retrieved is not None
|
|
298
|
+
assert retrieved.email == "test@example.com"
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
### Business Logic Testing
|
|
302
|
+
|
|
303
|
+
```rust
|
|
304
|
+
#[test]
|
|
305
|
+
fn test_discount_calculation_for_bulk_orders() {
|
|
306
|
+
let order = Order {
|
|
307
|
+
items: vec![
|
|
308
|
+
Item { price: 10.0, quantity: 100 },
|
|
309
|
+
Item { price: 5.0, quantity: 200 },
|
|
310
|
+
],
|
|
311
|
+
};
|
|
312
|
+
|
|
313
|
+
let discount = calculate_bulk_discount(&order);
|
|
314
|
+
|
|
315
|
+
assert_eq!(discount, 0.15); // 15% discount for orders > $1000
|
|
316
|
+
}
|
|
317
|
+
```
|
|
318
|
+
|
|
319
|
+
## Anti-Patterns to Avoid
|
|
320
|
+
|
|
321
|
+
### 1. Testing Implementation Details
|
|
322
|
+
|
|
323
|
+
**Bad:**
|
|
324
|
+
```javascript
|
|
325
|
+
test('uses Array.map internally', () => {
|
|
326
|
+
const spy = jest.spyOn(Array.prototype, 'map');
|
|
327
|
+
transform([1, 2, 3]);
|
|
328
|
+
expect(spy).toHaveBeenCalled();
|
|
329
|
+
});
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
**Good:**
|
|
333
|
+
```javascript
|
|
334
|
+
test('transforms array elements', () => {
|
|
335
|
+
const result = transform([1, 2, 3]);
|
|
336
|
+
expect(result).toEqual([2, 4, 6]);
|
|
337
|
+
});
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
### 2. Brittle Mocks
|
|
341
|
+
|
|
342
|
+
**Bad:**
|
|
343
|
+
```python
|
|
344
|
+
def test_sends_welcome_email():
|
|
345
|
+
mock_mailer = Mock()
|
|
346
|
+
mock_mailer.send.return_value = True
|
|
347
|
+
mock_mailer.template_id = "welcome-123"
|
|
348
|
+
mock_mailer.from_address = "noreply@example.com"
|
|
349
|
+
# ... 10 more mock configurations
|
|
350
|
+
|
|
351
|
+
user.send_welcome_email(mock_mailer)
|
|
352
|
+
assert mock_mailer.send.called
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Good:**
|
|
356
|
+
```python
|
|
357
|
+
def test_sends_welcome_email():
|
|
358
|
+
mock_mailer = Mock()
|
|
359
|
+
user.send_welcome_email(mock_mailer)
|
|
360
|
+
|
|
361
|
+
# Verify behavior, not every internal detail
|
|
362
|
+
mock_mailer.send.assert_called_once()
|
|
363
|
+
args = mock_mailer.send.call_args[0]
|
|
364
|
+
assert "Welcome" in args[0] # Email subject
|
|
365
|
+
assert user.email in args[1] # Recipient
|
|
366
|
+
```
|
|
367
|
+
|
|
368
|
+
### 3. Testing Getters and Setters
|
|
369
|
+
|
|
370
|
+
**Bad:**
|
|
371
|
+
```java
|
|
372
|
+
@Test
|
|
373
|
+
public void testSetName() {
|
|
374
|
+
User user = new User();
|
|
375
|
+
user.setName("John");
|
|
376
|
+
assertEquals("John", user.getName());
|
|
377
|
+
}
|
|
378
|
+
```
|
|
379
|
+
|
|
380
|
+
**Why bad:** This tests language features, not your logic. Skip trivial getters/setters.
|
|
381
|
+
|
|
382
|
+
### 4. One Giant Test
|
|
383
|
+
|
|
384
|
+
**Bad:**
|
|
385
|
+
```javascript
|
|
386
|
+
test('user registration system', () => {
|
|
387
|
+
// Tests 10 different things in one test
|
|
388
|
+
// If it fails, you don't know which part broke
|
|
389
|
+
});
|
|
390
|
+
```
|
|
391
|
+
|
|
392
|
+
**Good:**
|
|
393
|
+
```javascript
|
|
394
|
+
test('validates email format during registration', () => { /* ... */ });
|
|
395
|
+
test('hashes password during registration', () => { /* ... */ });
|
|
396
|
+
test('creates user record in database', () => { /* ... */ });
|
|
397
|
+
test('sends welcome email after registration', () => { /* ... */ });
|
|
398
|
+
```
|
|
399
|
+
|
|
400
|
+
## Coverage Goals
|
|
401
|
+
|
|
402
|
+
Aim for high coverage of critical paths, not 100% coverage of all code.
|
|
403
|
+
|
|
404
|
+
**Prioritize testing:**
|
|
405
|
+
- Business logic and validation rules
|
|
406
|
+
- Error handling and edge cases
|
|
407
|
+
- Security-critical code (auth, permissions)
|
|
408
|
+
- Data transformations with complex rules
|
|
409
|
+
|
|
410
|
+
**Lower priority:**
|
|
411
|
+
- Simple CRUD operations
|
|
412
|
+
- Framework glue code
|
|
413
|
+
- Configuration files
|
|
414
|
+
- Trivial getters/setters
|
|
415
|
+
|
|
416
|
+
## Summary Writing for TDD Plans
|
|
417
|
+
|
|
418
|
+
When writing your plan summary, include:
|
|
419
|
+
|
|
420
|
+
**Test Results:**
|
|
421
|
+
Paste the full output from your test runner showing all tests passing.
|
|
422
|
+
|
|
423
|
+
**Coverage:**
|
|
424
|
+
If the plan specifies coverage requirements, include coverage report.
|
|
425
|
+
|
|
426
|
+
**Red-Green-Refactor commits:**
|
|
427
|
+
List the commits you made for each phase of the TDD cycle.
|
|
428
|
+
|
|
429
|
+
**Example:**
|
|
430
|
+
```markdown
|
|
431
|
+
## Test Results
|
|
432
|
+
```
|
|
433
|
+
npm test
|
|
434
|
+
|
|
435
|
+
PASS src/validation/password.test.ts
|
|
436
|
+
✓ validates minimum length (3 ms)
|
|
437
|
+
✓ requires uppercase letter (1 ms)
|
|
438
|
+
✓ requires number (1 ms)
|
|
439
|
+
✓ requires special character (2 ms)
|
|
440
|
+
✓ accepts valid password (1 ms)
|
|
441
|
+
|
|
442
|
+
Test Suites: 1 passed, 1 total
|
|
443
|
+
Tests: 5 passed, 5 total
|
|
444
|
+
```
|
|
445
|
+
|
|
446
|
+
## Commits
|
|
447
|
+
1. test(auth-plan-2): add password validation tests (red phase)
|
|
448
|
+
2. feat(auth-plan-2): implement password validation (green phase)
|
|
449
|
+
3. refactor(auth-plan-2): extract validators into reusable functions
|
|
450
|
+
```
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: konductor-init
|
|
3
|
+
description: Initialize a new Konductor project with spec-driven development. Use when the user says init, initialize, new project, start project, set up konductor, or bootstrap.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Konductor Init — Project Initialization
|
|
7
|
+
|
|
8
|
+
You are the Konductor orchestrator. Initialize a new spec-driven development project.
|
|
9
|
+
|
|
10
|
+
## Step 1: Check Existing State
|
|
11
|
+
|
|
12
|
+
Check if `.konductor/` directory already exists.
|
|
13
|
+
- If it exists, call the `state_get` MCP tool. If it returns valid state, warn the user: "A Konductor project already exists here. Reinitializing will overwrite project.md, requirements.md, and roadmap.md. Proceed? (y/n)"
|
|
14
|
+
- If user declines, stop.
|
|
15
|
+
|
|
16
|
+
## Step 2: Create Directory Structure
|
|
17
|
+
|
|
18
|
+
Run:
|
|
19
|
+
```bash
|
|
20
|
+
mkdir -p .konductor/phases .konductor/milestones .konductor/.results .konductor/.tracking
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Step 3: Detect Existing Codebase
|
|
24
|
+
|
|
25
|
+
Check for existing code files:
|
|
26
|
+
```bash
|
|
27
|
+
ls src/ lib/ app/ package.json Cargo.toml go.mod pyproject.toml requirements.txt 2>/dev/null
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
If any exist, this is a brownfield project. Use the **konductor-codebase-mapper** agent to analyze the codebase. Provide it with:
|
|
31
|
+
- The project root directory
|
|
32
|
+
- Instructions to map: file structure, tech stack, patterns, conventions, testing, integrations
|
|
33
|
+
- Output to: `.kiro/steering/structure.md` and `.kiro/steering/tech.md`
|
|
34
|
+
|
|
35
|
+
Wait for completion before proceeding.
|
|
36
|
+
|
|
37
|
+
## Step 4: Project Discovery
|
|
38
|
+
|
|
39
|
+
Use the **konductor-discoverer** agent to interview the user. Provide it with:
|
|
40
|
+
- Instructions to ask 5-8 questions covering: project vision/purpose, target users, tech stack preferences, key features for v1, constraints/timeline, what's explicitly out of scope
|
|
41
|
+
- For brownfield projects: include the codebase analysis from Step 3 as context
|
|
42
|
+
- Reference: see `references/questioning.md` for question design guidelines
|
|
43
|
+
- Output: write `.konductor/project.md`, `.konductor/requirements.md`, `.konductor/roadmap.md`
|
|
44
|
+
|
|
45
|
+
Wait for the discoverer to complete.
|
|
46
|
+
|
|
47
|
+
## Step 5: Verify Outputs
|
|
48
|
+
|
|
49
|
+
Confirm these files were created and are non-empty:
|
|
50
|
+
- `.konductor/project.md`
|
|
51
|
+
- `.konductor/requirements.md`
|
|
52
|
+
- `.konductor/roadmap.md`
|
|
53
|
+
|
|
54
|
+
If any are missing, report the error and stop.
|
|
55
|
+
|
|
56
|
+
## Step 6: Write Initial State
|
|
57
|
+
|
|
58
|
+
Call the `state_init` MCP tool with:
|
|
59
|
+
- `name`: the project name from project.md
|
|
60
|
+
- `phase`: the first phase identifier from the roadmap
|
|
61
|
+
- `phases_total`: the total number of phases from the roadmap
|
|
62
|
+
|
|
63
|
+
This creates `.konductor/state.toml` with the correct initial structure.
|
|
64
|
+
|
|
65
|
+
Write `.konductor/config.toml`:
|
|
66
|
+
```toml
|
|
67
|
+
[general]
|
|
68
|
+
default_model = "claude-sonnet-4"
|
|
69
|
+
|
|
70
|
+
[execution]
|
|
71
|
+
max_wave_parallelism = 4
|
|
72
|
+
|
|
73
|
+
[git]
|
|
74
|
+
auto_commit = true
|
|
75
|
+
branching_strategy = "none"
|
|
76
|
+
|
|
77
|
+
[features]
|
|
78
|
+
research = true
|
|
79
|
+
plan_checker = true
|
|
80
|
+
verifier = true
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
## Step 7: Sync Steering Files
|
|
84
|
+
|
|
85
|
+
Create/update `.kiro/steering/` files:
|
|
86
|
+
- `.kiro/steering/product.md` — extract purpose, target users, key features from project.md
|
|
87
|
+
- `.kiro/steering/tech.md` — extract tech stack, libraries, constraints from project.md (merge with codebase mapper output if brownfield)
|
|
88
|
+
- `.kiro/steering/structure.md` — if brownfield, already created by mapper. If greenfield, write recommended structure based on tech stack.
|
|
89
|
+
|
|
90
|
+
## Step 8: Report Success
|
|
91
|
+
|
|
92
|
+
Tell the user:
|
|
93
|
+
- How many phases were identified in the roadmap
|
|
94
|
+
- List the phase names
|
|
95
|
+
- Suggest: "Say 'next' to start planning phase 1, or 'discuss phase 01' to set preferences first."
|