@ecc-hgy/ae 0.5.0 → 0.6.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/LICENSE +21 -21
- package/README.md +168 -155
- package/bin/ae.js +2 -2
- package/package.json +43 -43
- package/skills/brainstorming/SKILL.md +133 -133
- package/skills/diagnose/SKILL.md +146 -146
- package/skills/diagnose/assets/issue-7-sections.md +35 -35
- package/skills/diagnose/scripts/hitl-loop.template.sh +41 -41
- package/skills/grill-me/SKILL.md +10 -10
- package/skills/handoff/SKILL.md +19 -19
- package/skills/improve-codebase-architecture/DEEPENING.md +37 -37
- package/skills/improve-codebase-architecture/HTML-REPORT.md +123 -123
- package/skills/improve-codebase-architecture/INTERFACE-DESIGN.md +44 -44
- package/skills/improve-codebase-architecture/LANGUAGE.md +53 -53
- package/skills/improve-codebase-architecture/SKILL.md +101 -101
- package/skills/karpathy-guidelines/SKILL.md +63 -63
- package/skills/powerautomate-email-to-sharepoint-excel/powerautomate-email-to-sharepoint-excel-skill.md +496 -496
- package/skills/review/SKILL.md +119 -119
- package/skills/tdd/SKILL.md +157 -157
- package/skills/tdd/deep-modules.md +33 -33
- package/skills/tdd/interface-design.md +31 -31
- package/skills/tdd/mocking.md +59 -59
- package/skills/tdd/refactoring.md +10 -10
- package/skills/tdd/tests.md +61 -61
- package/skills/to-issues/SKILL.md +79 -79
- package/skills/to-issues/todo-template.md +25 -25
- package/skills/to-prd/SKILL.md +108 -108
- package/skills/using-agentic-engineering/SKILL.md +62 -62
- package/skills/verification-before-completion/SKILL.md +153 -153
- package/skills/writing-plans/SKILL.md +115 -115
- package/skills/zoom-out/SKILL.md +7 -7
- package/src/cli.js +61 -61
- package/src/commands/init.js +137 -137
- package/src/commands/setup.js +162 -162
- package/src/platforms.js +132 -132
- package/src/skeleton.js +134 -99
- package/src/utils/copy.js +100 -100
- package/src/utils/paths.js +60 -60
- package/src/utils/report.js +30 -30
- package/templates/entries/AGENTS.md +2 -0
- package/templates/entries/CLAUDE.md +5 -5
- package/templates/entries/README.md +33 -31
- package/templates/entries/handoff.md +1 -1
- package/templates/entries/spec/ADR/AGENTS.md +30 -30
- package/templates/entries/spec/ADR/CLAUDE.md +5 -5
- package/templates/entries/spec/AGENTS.md +34 -34
- package/templates/entries/spec/CLAUDE.md +5 -5
- package/templates/entries/spec/INDEX.md +28 -28
- package/templates/entries/spec/README.md +23 -23
|
@@ -1,31 +1,31 @@
|
|
|
1
|
-
# Interface Design for Testability
|
|
2
|
-
|
|
3
|
-
Good interfaces make testing natural:
|
|
4
|
-
|
|
5
|
-
1. **Accept dependencies, don't create them**
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// Testable
|
|
9
|
-
function processOrder(order, paymentGateway) {}
|
|
10
|
-
|
|
11
|
-
// Hard to test
|
|
12
|
-
function processOrder(order) {
|
|
13
|
-
const gateway = new StripeGateway();
|
|
14
|
-
}
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
2. **Return results, don't produce side effects**
|
|
18
|
-
|
|
19
|
-
```typescript
|
|
20
|
-
// Testable
|
|
21
|
-
function calculateDiscount(cart): Discount {}
|
|
22
|
-
|
|
23
|
-
// Hard to test
|
|
24
|
-
function applyDiscount(cart): void {
|
|
25
|
-
cart.total -= discount;
|
|
26
|
-
}
|
|
27
|
-
```
|
|
28
|
-
|
|
29
|
-
3. **Small surface area**
|
|
30
|
-
- Fewer methods = fewer tests needed
|
|
31
|
-
- Fewer params = simpler test setup
|
|
1
|
+
# Interface Design for Testability
|
|
2
|
+
|
|
3
|
+
Good interfaces make testing natural:
|
|
4
|
+
|
|
5
|
+
1. **Accept dependencies, don't create them**
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// Testable
|
|
9
|
+
function processOrder(order, paymentGateway) {}
|
|
10
|
+
|
|
11
|
+
// Hard to test
|
|
12
|
+
function processOrder(order) {
|
|
13
|
+
const gateway = new StripeGateway();
|
|
14
|
+
}
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
2. **Return results, don't produce side effects**
|
|
18
|
+
|
|
19
|
+
```typescript
|
|
20
|
+
// Testable
|
|
21
|
+
function calculateDiscount(cart): Discount {}
|
|
22
|
+
|
|
23
|
+
// Hard to test
|
|
24
|
+
function applyDiscount(cart): void {
|
|
25
|
+
cart.total -= discount;
|
|
26
|
+
}
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
3. **Small surface area**
|
|
30
|
+
- Fewer methods = fewer tests needed
|
|
31
|
+
- Fewer params = simpler test setup
|
package/skills/tdd/mocking.md
CHANGED
|
@@ -1,59 +1,59 @@
|
|
|
1
|
-
# When to Mock
|
|
2
|
-
|
|
3
|
-
Mock at **system boundaries** only:
|
|
4
|
-
|
|
5
|
-
- External APIs (payment, email, etc.)
|
|
6
|
-
- Databases (sometimes - prefer test DB)
|
|
7
|
-
- Time/randomness
|
|
8
|
-
- File system (sometimes)
|
|
9
|
-
|
|
10
|
-
Don't mock:
|
|
11
|
-
|
|
12
|
-
- Your own classes/modules
|
|
13
|
-
- Internal collaborators
|
|
14
|
-
- Anything you control
|
|
15
|
-
|
|
16
|
-
## Designing for Mockability
|
|
17
|
-
|
|
18
|
-
At system boundaries, design interfaces that are easy to mock:
|
|
19
|
-
|
|
20
|
-
**1. Use dependency injection**
|
|
21
|
-
|
|
22
|
-
Pass external dependencies in rather than creating them internally:
|
|
23
|
-
|
|
24
|
-
```typescript
|
|
25
|
-
// Easy to mock
|
|
26
|
-
function processPayment(order, paymentClient) {
|
|
27
|
-
return paymentClient.charge(order.total);
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
// Hard to mock
|
|
31
|
-
function processPayment(order) {
|
|
32
|
-
const client = new StripeClient(process.env.STRIPE_KEY);
|
|
33
|
-
return client.charge(order.total);
|
|
34
|
-
}
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
**2. Prefer SDK-style interfaces over generic fetchers**
|
|
38
|
-
|
|
39
|
-
Create specific functions for each external operation instead of one generic function with conditional logic:
|
|
40
|
-
|
|
41
|
-
```typescript
|
|
42
|
-
// GOOD: Each function is independently mockable
|
|
43
|
-
const api = {
|
|
44
|
-
getUser: (id) => fetch(`/users/${id}`),
|
|
45
|
-
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
|
46
|
-
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
|
47
|
-
};
|
|
48
|
-
|
|
49
|
-
// BAD: Mocking requires conditional logic inside the mock
|
|
50
|
-
const api = {
|
|
51
|
-
fetch: (endpoint, options) => fetch(endpoint, options),
|
|
52
|
-
};
|
|
53
|
-
```
|
|
54
|
-
|
|
55
|
-
The SDK approach means:
|
|
56
|
-
- Each mock returns one specific shape
|
|
57
|
-
- No conditional logic in test setup
|
|
58
|
-
- Easier to see which endpoints a test exercises
|
|
59
|
-
- Type safety per endpoint
|
|
1
|
+
# When to Mock
|
|
2
|
+
|
|
3
|
+
Mock at **system boundaries** only:
|
|
4
|
+
|
|
5
|
+
- External APIs (payment, email, etc.)
|
|
6
|
+
- Databases (sometimes - prefer test DB)
|
|
7
|
+
- Time/randomness
|
|
8
|
+
- File system (sometimes)
|
|
9
|
+
|
|
10
|
+
Don't mock:
|
|
11
|
+
|
|
12
|
+
- Your own classes/modules
|
|
13
|
+
- Internal collaborators
|
|
14
|
+
- Anything you control
|
|
15
|
+
|
|
16
|
+
## Designing for Mockability
|
|
17
|
+
|
|
18
|
+
At system boundaries, design interfaces that are easy to mock:
|
|
19
|
+
|
|
20
|
+
**1. Use dependency injection**
|
|
21
|
+
|
|
22
|
+
Pass external dependencies in rather than creating them internally:
|
|
23
|
+
|
|
24
|
+
```typescript
|
|
25
|
+
// Easy to mock
|
|
26
|
+
function processPayment(order, paymentClient) {
|
|
27
|
+
return paymentClient.charge(order.total);
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
// Hard to mock
|
|
31
|
+
function processPayment(order) {
|
|
32
|
+
const client = new StripeClient(process.env.STRIPE_KEY);
|
|
33
|
+
return client.charge(order.total);
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
**2. Prefer SDK-style interfaces over generic fetchers**
|
|
38
|
+
|
|
39
|
+
Create specific functions for each external operation instead of one generic function with conditional logic:
|
|
40
|
+
|
|
41
|
+
```typescript
|
|
42
|
+
// GOOD: Each function is independently mockable
|
|
43
|
+
const api = {
|
|
44
|
+
getUser: (id) => fetch(`/users/${id}`),
|
|
45
|
+
getOrders: (userId) => fetch(`/users/${userId}/orders`),
|
|
46
|
+
createOrder: (data) => fetch('/orders', { method: 'POST', body: data }),
|
|
47
|
+
};
|
|
48
|
+
|
|
49
|
+
// BAD: Mocking requires conditional logic inside the mock
|
|
50
|
+
const api = {
|
|
51
|
+
fetch: (endpoint, options) => fetch(endpoint, options),
|
|
52
|
+
};
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
The SDK approach means:
|
|
56
|
+
- Each mock returns one specific shape
|
|
57
|
+
- No conditional logic in test setup
|
|
58
|
+
- Easier to see which endpoints a test exercises
|
|
59
|
+
- Type safety per endpoint
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# Refactor Candidates
|
|
2
|
-
|
|
3
|
-
After TDD cycle, look for:
|
|
4
|
-
|
|
5
|
-
- **Duplication** → Extract function/class
|
|
6
|
-
- **Long methods** → Break into private helpers (keep tests on public interface)
|
|
7
|
-
- **Shallow modules** → Combine or deepen
|
|
8
|
-
- **Feature envy** → Move logic to where data lives
|
|
9
|
-
- **Primitive obsession** → Introduce value objects
|
|
10
|
-
- **Existing code** the new code reveals as problematic
|
|
1
|
+
# Refactor Candidates
|
|
2
|
+
|
|
3
|
+
After TDD cycle, look for:
|
|
4
|
+
|
|
5
|
+
- **Duplication** → Extract function/class
|
|
6
|
+
- **Long methods** → Break into private helpers (keep tests on public interface)
|
|
7
|
+
- **Shallow modules** → Combine or deepen
|
|
8
|
+
- **Feature envy** → Move logic to where data lives
|
|
9
|
+
- **Primitive obsession** → Introduce value objects
|
|
10
|
+
- **Existing code** the new code reveals as problematic
|
package/skills/tdd/tests.md
CHANGED
|
@@ -1,61 +1,61 @@
|
|
|
1
|
-
# Good and Bad Tests
|
|
2
|
-
|
|
3
|
-
## Good Tests
|
|
4
|
-
|
|
5
|
-
**Integration-style**: Test through real interfaces, not mocks of internal parts.
|
|
6
|
-
|
|
7
|
-
```typescript
|
|
8
|
-
// GOOD: Tests observable behavior
|
|
9
|
-
test("user can checkout with valid cart", async () => {
|
|
10
|
-
const cart = createCart();
|
|
11
|
-
cart.add(product);
|
|
12
|
-
const result = await checkout(cart, paymentMethod);
|
|
13
|
-
expect(result.status).toBe("confirmed");
|
|
14
|
-
});
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
Characteristics:
|
|
18
|
-
|
|
19
|
-
- Tests behavior users/callers care about
|
|
20
|
-
- Uses public API only
|
|
21
|
-
- Survives internal refactors
|
|
22
|
-
- Describes WHAT, not HOW
|
|
23
|
-
- One logical assertion per test
|
|
24
|
-
|
|
25
|
-
## Bad Tests
|
|
26
|
-
|
|
27
|
-
**Implementation-detail tests**: Coupled to internal structure.
|
|
28
|
-
|
|
29
|
-
```typescript
|
|
30
|
-
// BAD: Tests implementation details
|
|
31
|
-
test("checkout calls paymentService.process", async () => {
|
|
32
|
-
const mockPayment = jest.mock(paymentService);
|
|
33
|
-
await checkout(cart, payment);
|
|
34
|
-
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
|
35
|
-
});
|
|
36
|
-
```
|
|
37
|
-
|
|
38
|
-
Red flags:
|
|
39
|
-
|
|
40
|
-
- Mocking internal collaborators
|
|
41
|
-
- Testing private methods
|
|
42
|
-
- Asserting on call counts/order
|
|
43
|
-
- Test breaks when refactoring without behavior change
|
|
44
|
-
- Test name describes HOW not WHAT
|
|
45
|
-
- Verifying through external means instead of interface
|
|
46
|
-
|
|
47
|
-
```typescript
|
|
48
|
-
// BAD: Bypasses interface to verify
|
|
49
|
-
test("createUser saves to database", async () => {
|
|
50
|
-
await createUser({ name: "Alice" });
|
|
51
|
-
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
|
52
|
-
expect(row).toBeDefined();
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
// GOOD: Verifies through interface
|
|
56
|
-
test("createUser makes user retrievable", async () => {
|
|
57
|
-
const user = await createUser({ name: "Alice" });
|
|
58
|
-
const retrieved = await getUser(user.id);
|
|
59
|
-
expect(retrieved.name).toBe("Alice");
|
|
60
|
-
});
|
|
61
|
-
```
|
|
1
|
+
# Good and Bad Tests
|
|
2
|
+
|
|
3
|
+
## Good Tests
|
|
4
|
+
|
|
5
|
+
**Integration-style**: Test through real interfaces, not mocks of internal parts.
|
|
6
|
+
|
|
7
|
+
```typescript
|
|
8
|
+
// GOOD: Tests observable behavior
|
|
9
|
+
test("user can checkout with valid cart", async () => {
|
|
10
|
+
const cart = createCart();
|
|
11
|
+
cart.add(product);
|
|
12
|
+
const result = await checkout(cart, paymentMethod);
|
|
13
|
+
expect(result.status).toBe("confirmed");
|
|
14
|
+
});
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Characteristics:
|
|
18
|
+
|
|
19
|
+
- Tests behavior users/callers care about
|
|
20
|
+
- Uses public API only
|
|
21
|
+
- Survives internal refactors
|
|
22
|
+
- Describes WHAT, not HOW
|
|
23
|
+
- One logical assertion per test
|
|
24
|
+
|
|
25
|
+
## Bad Tests
|
|
26
|
+
|
|
27
|
+
**Implementation-detail tests**: Coupled to internal structure.
|
|
28
|
+
|
|
29
|
+
```typescript
|
|
30
|
+
// BAD: Tests implementation details
|
|
31
|
+
test("checkout calls paymentService.process", async () => {
|
|
32
|
+
const mockPayment = jest.mock(paymentService);
|
|
33
|
+
await checkout(cart, payment);
|
|
34
|
+
expect(mockPayment.process).toHaveBeenCalledWith(cart.total);
|
|
35
|
+
});
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Red flags:
|
|
39
|
+
|
|
40
|
+
- Mocking internal collaborators
|
|
41
|
+
- Testing private methods
|
|
42
|
+
- Asserting on call counts/order
|
|
43
|
+
- Test breaks when refactoring without behavior change
|
|
44
|
+
- Test name describes HOW not WHAT
|
|
45
|
+
- Verifying through external means instead of interface
|
|
46
|
+
|
|
47
|
+
```typescript
|
|
48
|
+
// BAD: Bypasses interface to verify
|
|
49
|
+
test("createUser saves to database", async () => {
|
|
50
|
+
await createUser({ name: "Alice" });
|
|
51
|
+
const row = await db.query("SELECT * FROM users WHERE name = ?", ["Alice"]);
|
|
52
|
+
expect(row).toBeDefined();
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// GOOD: Verifies through interface
|
|
56
|
+
test("createUser makes user retrievable", async () => {
|
|
57
|
+
const user = await createUser({ name: "Alice" });
|
|
58
|
+
const retrieved = await getUser(user.id);
|
|
59
|
+
expect(retrieved.name).toBe("Alice");
|
|
60
|
+
});
|
|
61
|
+
```
|
|
@@ -1,79 +1,79 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: to-issues
|
|
3
|
-
description: Break a design (and supporting spec context) into vertical-slice tasks and save them as `spec/needs/<need-name>/todo.md`. Use when user wants to convert a design into actionable tasks (S1 node A4).
|
|
4
|
-
---
|
|
5
|
-
|
|
6
|
-
# To Issues
|
|
7
|
-
|
|
8
|
-
Break a plan into independently-grabbable issues using vertical slices (tracer bullets).
|
|
9
|
-
|
|
10
|
-
## Process
|
|
11
|
-
|
|
12
|
-
### 1. Gather context
|
|
13
|
-
|
|
14
|
-
**Primary input:** `spec/needs/<need-name>/design.md` (produced by A3 `writing-plans`).
|
|
15
|
-
|
|
16
|
-
If the design is insufficient on its own (acceptance criteria not concrete enough, scope boundaries unclear, or a slice references behavior that's defined elsewhere), supplement with:
|
|
17
|
-
|
|
18
|
-
- The sibling `spec/needs/<need-name>/prd.md` — for user-facing acceptance criteria, out-of-scope notes
|
|
19
|
-
- The `related-needs` field in `design.md` frontmatter — read those needs' `design.md` for shared module decisions
|
|
20
|
-
- `spec/INDEX.md` and `spec/ADR/` — for vocabulary and accepted cross-need decisions
|
|
21
|
-
|
|
22
|
-
If a design gap is severe enough that you can't draft a slice, STOP and surface it as a finding — go back to A3 (`writing-plans`) to patch `design.md` first, rather than guessing.
|
|
23
|
-
|
|
24
|
-
### 2. Explore the codebase (optional)
|
|
25
|
-
|
|
26
|
-
If you have not already explored the codebase, do so to understand the current state of the code. Task titles and descriptions should use vocabulary from `spec/INDEX.md` and existing `spec/needs/*/`, and respect ADRs under `spec/ADR/`.
|
|
27
|
-
|
|
28
|
-
### 3. Draft vertical slices
|
|
29
|
-
|
|
30
|
-
Break the plan into **tracer bullet** issues. Each issue is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer.
|
|
31
|
-
|
|
32
|
-
<vertical-slice-rules>
|
|
33
|
-
- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, UI, tests)
|
|
34
|
-
- A completed slice is demoable or verifiable on its own
|
|
35
|
-
- Prefer many thin slices over few thick ones
|
|
36
|
-
</vertical-slice-rules>
|
|
37
|
-
|
|
38
|
-
### 4. Quiz the user
|
|
39
|
-
|
|
40
|
-
Present the proposed breakdown as a numbered list. For each slice, show:
|
|
41
|
-
|
|
42
|
-
- **Title**: short descriptive name
|
|
43
|
-
- **Acceptance**: one-line acceptance criterion (the observable behavior that proves it's done)
|
|
44
|
-
- **Blocked by**: which other slices (if any) must complete first; reference by slice number (e.g. "T2")
|
|
45
|
-
|
|
46
|
-
Ask the user:
|
|
47
|
-
|
|
48
|
-
- Does the granularity feel right? (too coarse / too fine)
|
|
49
|
-
- Are the dependency relationships correct?
|
|
50
|
-
- Should any slices be merged or split further?
|
|
51
|
-
|
|
52
|
-
Iterate until the user approves the breakdown.
|
|
53
|
-
|
|
54
|
-
### 5. Save the task list to `todo.md`
|
|
55
|
-
|
|
56
|
-
Save the approved breakdown to `spec/needs/<need-name>/todo.md`, using [`todo-template.md`](todo-template.md) as the starting structure. The template encodes the format and the maintenance rules; copy it, fill in the slices, then save.
|
|
57
|
-
|
|
58
|
-
`todo.md` has NO frontmatter — it is a rolling working artifact, not a stateful spec document.
|
|
59
|
-
|
|
60
|
-
Format summary (full rules live in [`todo-template.md`](todo-template.md)):
|
|
61
|
-
|
|
62
|
-
- Two sections: `## 实施` (executable slices) and `## 阻塞 / 待澄清` (open blockers)
|
|
63
|
-
- Slice IDs: `T<n>` for tasks, `B<n>` for blockers; stable across the life of the need
|
|
64
|
-
- Each `## 实施` line: `- [ ] T<n> <title> — <one-line acceptance>[; blocked by T<m>]`
|
|
65
|
-
- Each slice MUST trace back to a section in `design.md`; if it can't, that's a signal to patch `design.md`, not to smuggle scope into `todo.md`
|
|
66
|
-
|
|
67
|
-
## After Saving
|
|
68
|
-
|
|
69
|
-
1. Update `spec/INDEX.md`:
|
|
70
|
-
- Set the `todo` column to `0/N` (where N = total tasks in `## 实施`)
|
|
71
|
-
- Recompute the `当前节点` column per the rules in `spec/AGENTS.md` §INDEX 推导规则 (likely now `A5 执行`)
|
|
72
|
-
- If unsure, run `ae index-rebuild` for an idempotent rescan
|
|
73
|
-
2. Hand off to the next S1 node: A5 `tdd` will read this `todo.md` (plus `design.md`) and drive the red-green-refactor loop. Tell the user the task list is ready and recommend invoking `tdd` next.
|
|
74
|
-
|
|
75
|
-
## Boundaries
|
|
76
|
-
|
|
77
|
-
- This skill writes ONLY `spec/needs/<need-name>/todo.md` (plus the INDEX row). It does NOT modify `prd.md` or `design.md`.
|
|
78
|
-
- A task in `todo.md` MUST trace back to a section in `design.md`. New scope discovered here is a signal to patch `design.md` first.
|
|
79
|
-
- This skill does NOT execute tasks — that is A5 `tdd`.
|
|
1
|
+
---
|
|
2
|
+
name: to-issues
|
|
3
|
+
description: Break a design (and supporting spec context) into vertical-slice tasks and save them as `spec/needs/<need-name>/todo.md`. Use when user wants to convert a design into actionable tasks (S1 node A4).
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# To Issues
|
|
7
|
+
|
|
8
|
+
Break a plan into independently-grabbable issues using vertical slices (tracer bullets).
|
|
9
|
+
|
|
10
|
+
## Process
|
|
11
|
+
|
|
12
|
+
### 1. Gather context
|
|
13
|
+
|
|
14
|
+
**Primary input:** `spec/needs/<need-name>/design.md` (produced by A3 `writing-plans`).
|
|
15
|
+
|
|
16
|
+
If the design is insufficient on its own (acceptance criteria not concrete enough, scope boundaries unclear, or a slice references behavior that's defined elsewhere), supplement with:
|
|
17
|
+
|
|
18
|
+
- The sibling `spec/needs/<need-name>/prd.md` — for user-facing acceptance criteria, out-of-scope notes
|
|
19
|
+
- The `related-needs` field in `design.md` frontmatter — read those needs' `design.md` for shared module decisions
|
|
20
|
+
- `spec/INDEX.md` and `spec/ADR/` — for vocabulary and accepted cross-need decisions
|
|
21
|
+
|
|
22
|
+
If a design gap is severe enough that you can't draft a slice, STOP and surface it as a finding — go back to A3 (`writing-plans`) to patch `design.md` first, rather than guessing.
|
|
23
|
+
|
|
24
|
+
### 2. Explore the codebase (optional)
|
|
25
|
+
|
|
26
|
+
If you have not already explored the codebase, do so to understand the current state of the code. Task titles and descriptions should use vocabulary from `spec/INDEX.md` and existing `spec/needs/*/`, and respect ADRs under `spec/ADR/`.
|
|
27
|
+
|
|
28
|
+
### 3. Draft vertical slices
|
|
29
|
+
|
|
30
|
+
Break the plan into **tracer bullet** issues. Each issue is a thin vertical slice that cuts through ALL integration layers end-to-end, NOT a horizontal slice of one layer.
|
|
31
|
+
|
|
32
|
+
<vertical-slice-rules>
|
|
33
|
+
- Each slice delivers a narrow but COMPLETE path through every layer (schema, API, UI, tests)
|
|
34
|
+
- A completed slice is demoable or verifiable on its own
|
|
35
|
+
- Prefer many thin slices over few thick ones
|
|
36
|
+
</vertical-slice-rules>
|
|
37
|
+
|
|
38
|
+
### 4. Quiz the user
|
|
39
|
+
|
|
40
|
+
Present the proposed breakdown as a numbered list. For each slice, show:
|
|
41
|
+
|
|
42
|
+
- **Title**: short descriptive name
|
|
43
|
+
- **Acceptance**: one-line acceptance criterion (the observable behavior that proves it's done)
|
|
44
|
+
- **Blocked by**: which other slices (if any) must complete first; reference by slice number (e.g. "T2")
|
|
45
|
+
|
|
46
|
+
Ask the user:
|
|
47
|
+
|
|
48
|
+
- Does the granularity feel right? (too coarse / too fine)
|
|
49
|
+
- Are the dependency relationships correct?
|
|
50
|
+
- Should any slices be merged or split further?
|
|
51
|
+
|
|
52
|
+
Iterate until the user approves the breakdown.
|
|
53
|
+
|
|
54
|
+
### 5. Save the task list to `todo.md`
|
|
55
|
+
|
|
56
|
+
Save the approved breakdown to `spec/needs/<need-name>/todo.md`, using [`todo-template.md`](todo-template.md) as the starting structure. The template encodes the format and the maintenance rules; copy it, fill in the slices, then save.
|
|
57
|
+
|
|
58
|
+
`todo.md` has NO frontmatter — it is a rolling working artifact, not a stateful spec document.
|
|
59
|
+
|
|
60
|
+
Format summary (full rules live in [`todo-template.md`](todo-template.md)):
|
|
61
|
+
|
|
62
|
+
- Two sections: `## 实施` (executable slices) and `## 阻塞 / 待澄清` (open blockers)
|
|
63
|
+
- Slice IDs: `T<n>` for tasks, `B<n>` for blockers; stable across the life of the need
|
|
64
|
+
- Each `## 实施` line: `- [ ] T<n> <title> — <one-line acceptance>[; blocked by T<m>]`
|
|
65
|
+
- Each slice MUST trace back to a section in `design.md`; if it can't, that's a signal to patch `design.md`, not to smuggle scope into `todo.md`
|
|
66
|
+
|
|
67
|
+
## After Saving
|
|
68
|
+
|
|
69
|
+
1. Update `spec/INDEX.md`:
|
|
70
|
+
- Set the `todo` column to `0/N` (where N = total tasks in `## 实施`)
|
|
71
|
+
- Recompute the `当前节点` column per the rules in `spec/AGENTS.md` §INDEX 推导规则 (likely now `A5 执行`)
|
|
72
|
+
- If unsure, run `ae index-rebuild` for an idempotent rescan
|
|
73
|
+
2. Hand off to the next S1 node: A5 `tdd` will read this `todo.md` (plus `design.md`) and drive the red-green-refactor loop. Tell the user the task list is ready and recommend invoking `tdd` next.
|
|
74
|
+
|
|
75
|
+
## Boundaries
|
|
76
|
+
|
|
77
|
+
- This skill writes ONLY `spec/needs/<need-name>/todo.md` (plus the INDEX row). It does NOT modify `prd.md` or `design.md`.
|
|
78
|
+
- A task in `todo.md` MUST trace back to a section in `design.md`. New scope discovered here is a signal to patch `design.md` first.
|
|
79
|
+
- This skill does NOT execute tasks — that is A5 `tdd`.
|
|
@@ -1,25 +1,25 @@
|
|
|
1
|
-
# Todo - <need-name>
|
|
2
|
-
|
|
3
|
-
> Derived from: prd.md + design.md
|
|
4
|
-
|
|
5
|
-
## 实施
|
|
6
|
-
|
|
7
|
-
- [ ] T1 <title> — <one-line acceptance>
|
|
8
|
-
- [ ] T2 <title> — <one-line acceptance>; blocked by T1
|
|
9
|
-
- [ ] T3 <title> — <one-line acceptance>
|
|
10
|
-
|
|
11
|
-
## 阻塞 / 待澄清
|
|
12
|
-
|
|
13
|
-
- B1 <blocker description, link back to the design section that needs sharpening>
|
|
14
|
-
|
|
15
|
-
<!--
|
|
16
|
-
Rules for maintaining this file:
|
|
17
|
-
|
|
18
|
-
- NO frontmatter — this is a rolling working artifact, not a stateful spec document.
|
|
19
|
-
- Use `- [ ]` for unfinished, `- [x]` for finished. Never delete completed items — they are visible history.
|
|
20
|
-
- Sort by dependency order (blockers first); within the same level, sort by suggested execution order.
|
|
21
|
-
- If a slice depends on a design decision that is still open, put it in `## 阻塞 / 待澄清` instead of `## 实施`.
|
|
22
|
-
- Each slice MUST be traceable to a section in `design.md`. If a new slice has no traceable design section, that itself is a finding — go back and patch `design.md` rather than smuggling new scope into `todo.md`.
|
|
23
|
-
- Slice identifiers: `T<n>` for execution tasks, `B<n>` for blockers. Stable across the life of the need; do not renumber.
|
|
24
|
-
- Acceptance criteria: a single observable behavior that proves the slice is done. If it needs multiple lines, the slice is probably too coarse — split it.
|
|
25
|
-
-->
|
|
1
|
+
# Todo - <need-name>
|
|
2
|
+
|
|
3
|
+
> Derived from: prd.md + design.md
|
|
4
|
+
|
|
5
|
+
## 实施
|
|
6
|
+
|
|
7
|
+
- [ ] T1 <title> — <one-line acceptance>
|
|
8
|
+
- [ ] T2 <title> — <one-line acceptance>; blocked by T1
|
|
9
|
+
- [ ] T3 <title> — <one-line acceptance>
|
|
10
|
+
|
|
11
|
+
## 阻塞 / 待澄清
|
|
12
|
+
|
|
13
|
+
- B1 <blocker description, link back to the design section that needs sharpening>
|
|
14
|
+
|
|
15
|
+
<!--
|
|
16
|
+
Rules for maintaining this file:
|
|
17
|
+
|
|
18
|
+
- NO frontmatter — this is a rolling working artifact, not a stateful spec document.
|
|
19
|
+
- Use `- [ ]` for unfinished, `- [x]` for finished. Never delete completed items — they are visible history.
|
|
20
|
+
- Sort by dependency order (blockers first); within the same level, sort by suggested execution order.
|
|
21
|
+
- If a slice depends on a design decision that is still open, put it in `## 阻塞 / 待澄清` instead of `## 实施`.
|
|
22
|
+
- Each slice MUST be traceable to a section in `design.md`. If a new slice has no traceable design section, that itself is a finding — go back and patch `design.md` rather than smuggling new scope into `todo.md`.
|
|
23
|
+
- Slice identifiers: `T<n>` for execution tasks, `B<n>` for blockers. Stable across the life of the need; do not renumber.
|
|
24
|
+
- Acceptance criteria: a single observable behavior that proves the slice is done. If it needs multiple lines, the slice is probably too coarse — split it.
|
|
25
|
+
-->
|