the-frame-ai 0.11.4 → 0.13.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
CHANGED
|
@@ -325,6 +325,7 @@ These 7 commands cover 90% of solo dev work:
|
|
|
325
325
|
|
|
326
326
|
| Command | When to use |
|
|
327
327
|
|---------|-------------|
|
|
328
|
+
| `/frame:test-plan` | After review, before ship — generates a manual "go check this as a user" checklist of what changed |
|
|
328
329
|
| `/frame:ship` | Commit, optional push/PR, update memory |
|
|
329
330
|
| `/frame:checkpoint` | Save a git tag before a risky change |
|
|
330
331
|
| `/frame:rollback` | Roll back to a checkpoint |
|
package/package.json
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# /frame:init -- Project Initialization
|
|
1
|
+
# /frame:init -- Project Initialization & Refresh
|
|
2
2
|
|
|
3
3
|
> **This is a slash command** — run it inside Claude Code after `npx the-frame init` has already installed the framework.
|
|
4
4
|
> It scans your codebase and fills MAP.md, CLAUDE.md, and CONTEXT.md.
|
|
@@ -6,9 +6,48 @@
|
|
|
6
6
|
|
|
7
7
|
Scans the project and fills MAP.md, CLAUDE.md, and CONTEXT.md with a complete project map.
|
|
8
8
|
|
|
9
|
+
**Re-runnable.** Run it again any time the project grows — new stack, new modules, new
|
|
10
|
+
dependencies. On a second run it works in **REFRESH mode**: it updates the auto-generated
|
|
11
|
+
sections and leaves your hand-written content untouched (see Step 0).
|
|
12
|
+
|
|
9
13
|
## Instructions
|
|
10
14
|
|
|
11
|
-
### Step 0:
|
|
15
|
+
### Step 0: Detect run mode (FIRST RUN vs REFRESH)
|
|
16
|
+
|
|
17
|
+
Check whether the project has already been mapped:
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
grep -l "filled by /frame:init\|to be filled after /frame:init" \
|
|
21
|
+
.planning/MAP.md CLAUDE.md .planning/CONTEXT.md 2>/dev/null
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
- **Placeholders still present** → **FIRST RUN**. Fill everything (Steps 6–10 as written).
|
|
25
|
+
- **No placeholders** (files already have real content) → **REFRESH**. Follow the
|
|
26
|
+
**Refresh rules** below. Announce: "Project already mapped — running in REFRESH mode."
|
|
27
|
+
|
|
28
|
+
#### Refresh rules (apply only in REFRESH mode)
|
|
29
|
+
|
|
30
|
+
Sections are split into two groups. Never cross the line.
|
|
31
|
+
|
|
32
|
+
| File | Auto-owned (regenerate) | User-owned (NEVER overwrite) |
|
|
33
|
+
|------|-------------------------|------------------------------|
|
|
34
|
+
| `CLAUDE.md` | Tech Stack, Architecture, Key Patterns | Code Conventions, Rules, Anti-Patterns, FRAME Framework |
|
|
35
|
+
| `MAP.md` | Quick Facts, Architecture Pattern, Entry Points, Key Layers, Data Flow, Key Patterns, File Inventory | Tech Debt / Notes (append only — keep existing lines) |
|
|
36
|
+
| `CONTEXT.md` | `## Technical Context` section only | everything else |
|
|
37
|
+
| `STATE.md` | — | **DO NOT touch Phase/Status.** Only append a refresh note (Step 9). |
|
|
38
|
+
| `memory/conventions.md` | — | merge/append only (Step 10) |
|
|
39
|
+
| `memory/dependencies.md` | — | merge/append only (Step 10) |
|
|
40
|
+
|
|
41
|
+
Before overwriting any auto-owned section, **back up the files once**:
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
mkdir -p .planning/.backup && cp CLAUDE.md .planning/MAP.md .planning/CONTEXT.md .planning/.backup/ 2>/dev/null
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
When you rewrite an auto-owned section, replace ONLY that section (match on its `##` heading,
|
|
48
|
+
stop at the next `##`). Do not reflow or reword neighbouring user-owned sections.
|
|
49
|
+
|
|
50
|
+
### Step 1: Auto-detect Stack
|
|
12
51
|
|
|
13
52
|
Identify the project type by checking for these files:
|
|
14
53
|
- `package.json` → Node.js/JS/TS (check framework: Next.js, Express, NestJS, Vue, Svelte, React)
|
|
@@ -23,7 +62,7 @@ Run: `ls -la` and `cat README.md 2>/dev/null | head -30`
|
|
|
23
62
|
|
|
24
63
|
Record: **stack**, **language**, **framework**, **project type** (web/api/cli/library/mobile).
|
|
25
64
|
|
|
26
|
-
### Step
|
|
65
|
+
### Step 2: Surface Scan
|
|
27
66
|
|
|
28
67
|
Read the project config files (those that exist):
|
|
29
68
|
- `package.json` / `go.mod` / `Cargo.toml` / `pyproject.toml` — dependencies, versions
|
|
@@ -32,7 +71,7 @@ Read the project config files (those that exist):
|
|
|
32
71
|
- `Dockerfile` / `docker-compose.yml` — deployment
|
|
33
72
|
- `README.md` — project description
|
|
34
73
|
|
|
35
|
-
### Step
|
|
74
|
+
### Step 3: Structure Scan
|
|
36
75
|
|
|
37
76
|
Adapt commands to the detected stack:
|
|
38
77
|
|
|
@@ -64,7 +103,7 @@ find . -type d -not -path "*/node_modules/*" -not -path "*/.git/*" \
|
|
|
64
103
|
-not -path "*/target/*" -not -path "*/__pycache__/*" | head -40
|
|
65
104
|
```
|
|
66
105
|
|
|
67
|
-
### Step
|
|
106
|
+
### Step 4: Patterns Scan
|
|
68
107
|
|
|
69
108
|
Look for patterns relevant to the detected stack:
|
|
70
109
|
|
|
@@ -93,7 +132,7 @@ find . -name "*_test.*" -o -name "*.test.*" -o -name "*.spec.*" \
|
|
|
93
132
|
| grep -v node_modules | head -15
|
|
94
133
|
```
|
|
95
134
|
|
|
96
|
-
### Step
|
|
135
|
+
### Step 5: Dependencies & Dynamics Scan
|
|
97
136
|
|
|
98
137
|
Determine inter-module dependencies:
|
|
99
138
|
|
|
@@ -105,8 +144,6 @@ grep -r "^import\|^from\|^require\|^use " . \
|
|
|
105
144
|
|
|
106
145
|
Check for: database, cache, queues, external APIs.
|
|
107
146
|
|
|
108
|
-
### Step 5: Dynamics Scan
|
|
109
|
-
|
|
110
147
|
Determine data flow and async patterns:
|
|
111
148
|
|
|
112
149
|
```
|
|
@@ -115,9 +152,11 @@ grep -r "async\|await\|goroutine\|channel\|Promise\|Observable\|WebSocket\|Event
|
|
|
115
152
|
-l 2>/dev/null | head -10
|
|
116
153
|
```
|
|
117
154
|
|
|
118
|
-
### Step 6: Fill MAP.md
|
|
155
|
+
### Step 6: Fill / refresh MAP.md
|
|
119
156
|
|
|
120
|
-
Write results to `.planning/MAP.md
|
|
157
|
+
Write results to `.planning/MAP.md`. In REFRESH mode regenerate only the auto-owned
|
|
158
|
+
sections (see Step 0) and **keep every existing line under `## Tech Debt / Notes`** —
|
|
159
|
+
append new findings below them, don't replace.
|
|
121
160
|
|
|
122
161
|
```markdown
|
|
123
162
|
# Project Map -- {Project Name}
|
|
@@ -159,46 +198,58 @@ Write results to `.planning/MAP.md`:
|
|
|
159
198
|
|
|
160
199
|
### Step 7: Update CLAUDE.md
|
|
161
200
|
|
|
162
|
-
Fill
|
|
201
|
+
Fill / refresh **only** these three sections — this is the main file Claude reads on every run:
|
|
163
202
|
|
|
164
|
-
- **Tech Stack** — specific stack from
|
|
165
|
-
- **Architecture** — brief description from
|
|
203
|
+
- **Tech Stack** — specific stack from Step 1
|
|
204
|
+
- **Architecture** — brief description from Step 6
|
|
166
205
|
- **Key Patterns** — 3-5 patterns from the code
|
|
167
206
|
|
|
207
|
+
In REFRESH mode, **do not touch** `Code Conventions`, `Rules`, `Anti-Patterns`, or
|
|
208
|
+
`FRAME Framework` — the user may have customised them.
|
|
209
|
+
|
|
168
210
|
### Step 8: Update CONTEXT.md
|
|
169
211
|
|
|
170
|
-
Fill
|
|
212
|
+
Fill / refresh the `## Technical Context` section in `.planning/CONTEXT.md`:
|
|
171
213
|
- Project type and stack
|
|
172
214
|
- Main entry points
|
|
173
215
|
- Key dependencies
|
|
174
216
|
|
|
217
|
+
Leave all other sections of CONTEXT.md untouched.
|
|
218
|
+
|
|
175
219
|
### Step 9: Update STATE.md
|
|
176
220
|
|
|
177
|
-
|
|
178
|
-
```markdown
|
|
179
|
-
## Current Position
|
|
180
|
-
- Phase: SETUP
|
|
181
|
-
- Status: MAP.md filled, project ready to work
|
|
182
|
-
```
|
|
221
|
+
- **FIRST RUN** — set the starting position:
|
|
222
|
+
```markdown
|
|
223
|
+
## Current Position
|
|
224
|
+
- Phase: SETUP
|
|
225
|
+
- Status: MAP.md filled, project ready to work
|
|
226
|
+
```
|
|
227
|
+
- **REFRESH** — **do not change Phase or Status** (the user may be mid-feature).
|
|
228
|
+
Only append one line to the activity/log section:
|
|
229
|
+
```markdown
|
|
230
|
+
- {date}: project map refreshed via /frame:init
|
|
231
|
+
```
|
|
183
232
|
|
|
184
|
-
### Step 10: Fill memory from scan results
|
|
233
|
+
### Step 10: Fill / merge memory from scan results
|
|
185
234
|
|
|
186
|
-
Using data already gathered in
|
|
235
|
+
Using data already gathered in Steps 2-5, update two memory files. **Merge, never
|
|
236
|
+
overwrite** — read the existing file first, keep all current lines, add only what's new.
|
|
187
237
|
|
|
188
|
-
**`.planning/memory/conventions.md`** — add
|
|
238
|
+
**`.planning/memory/conventions.md`** — add/confirm:
|
|
189
239
|
- File naming pattern (kebab-case, camelCase, etc.)
|
|
190
240
|
- Import style (named vs default, path aliases)
|
|
191
241
|
- Git commit format (if `.gitmessage` or recent commits reveal a pattern)
|
|
192
242
|
|
|
193
|
-
**`.planning/memory/dependencies.md`** — add:
|
|
243
|
+
**`.planning/memory/dependencies.md`** — add/confirm:
|
|
194
244
|
- Core dependencies (from package.json / go.mod / etc.)
|
|
195
245
|
- Dev tools (test runner, linter, bundler)
|
|
196
246
|
- Any "avoid" patterns spotted (e.g., deprecated packages)
|
|
197
247
|
|
|
198
|
-
Only
|
|
248
|
+
Only add what was actually found — no placeholders. If a line is already present, leave it.
|
|
199
249
|
|
|
200
250
|
### Step 11: Output completion checklist
|
|
201
251
|
|
|
252
|
+
**FIRST RUN:**
|
|
202
253
|
```
|
|
203
254
|
╔══════════════════════════════════════════╗
|
|
204
255
|
║ FRAME INIT — Complete ║
|
|
@@ -221,11 +272,39 @@ Only fill what was actually found — no placeholders.
|
|
|
221
272
|
╚══════════════════════════════════════════╝
|
|
222
273
|
```
|
|
223
274
|
|
|
275
|
+
**REFRESH** — print a changelog of what actually changed, so the user can eyeball it:
|
|
276
|
+
```
|
|
277
|
+
╔══════════════════════════════════════════╗
|
|
278
|
+
║ FRAME INIT — Refresh complete ║
|
|
279
|
+
╠══════════════════════════════════════════╣
|
|
280
|
+
║ Changes detected since last scan: ║
|
|
281
|
+
║ • Stack: {what changed, or "—"} ║
|
|
282
|
+
║ • Deps: {added / removed, or "—"}║
|
|
283
|
+
║ • Structure: {new modules, or "—"} ║
|
|
284
|
+
║ • Patterns: {new patterns, or "—"} ║
|
|
285
|
+
╠══════════════════════════════════════════╣
|
|
286
|
+
║ Updated (auto sections only): ║
|
|
287
|
+
║ ✓ MAP.md ✓ CLAUDE.md ✓ CONTEXT.md ║
|
|
288
|
+
║ Preserved: your Conventions / Rules / ║
|
|
289
|
+
║ Anti-Patterns / STATE phase / notes. ║
|
|
290
|
+
║ Backup: .planning/.backup/ ║
|
|
291
|
+
╚══════════════════════════════════════════╝
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
If nothing meaningful changed, say so plainly: "No significant changes since the last scan."
|
|
295
|
+
|
|
224
296
|
## Result
|
|
225
297
|
|
|
226
298
|
- `.planning/MAP.md` — complete project map
|
|
227
299
|
- `CLAUDE.md` — stack and architecture sections filled
|
|
228
300
|
- `.planning/CONTEXT.md` — technical context filled
|
|
229
|
-
- `.planning/STATE.md` — status updated
|
|
301
|
+
- `.planning/STATE.md` — status updated (FIRST RUN only)
|
|
230
302
|
- `.planning/memory/conventions.md` — conventions from scan
|
|
231
303
|
- `.planning/memory/dependencies.md` — dependencies from scan
|
|
304
|
+
|
|
305
|
+
## Rules
|
|
306
|
+
|
|
307
|
+
- Re-runnable: REFRESH mode never overwrites user-authored sections or resets STATE phase.
|
|
308
|
+
- Back up auto-owned files to `.planning/.backup/` before rewriting them on refresh.
|
|
309
|
+
- When refreshing a section, replace only that `##` block — leave neighbours byte-for-byte intact.
|
|
310
|
+
- Only write what was actually found in the scan — no placeholders, no invented content.
|
|
@@ -149,6 +149,13 @@ Create `docs/specs/{feature}/review.md`:
|
|
|
149
149
|
- Status: Review complete, ready to ship
|
|
150
150
|
```
|
|
151
151
|
|
|
152
|
+
On approve, suggest the next step:
|
|
153
|
+
```
|
|
154
|
+
✅ Review passed.
|
|
155
|
+
→ Run /frame:test-plan to get a manual "what to check as a user" list before shipping,
|
|
156
|
+
or go straight to /frame:ship.
|
|
157
|
+
```
|
|
158
|
+
|
|
152
159
|
**If request changes:**
|
|
153
160
|
```markdown
|
|
154
161
|
## Current Position
|
|
@@ -20,14 +20,14 @@ Update `.planning/STATE.md` before starting:
|
|
|
20
20
|
```
|
|
21
21
|
|
|
22
22
|
Read `.planning/STATE.md` and verify:
|
|
23
|
-
- `Phase
|
|
23
|
+
- `Phase:` is `REVIEW` OR `TEST` ✓ (TEST = manual test plan was generated after review)
|
|
24
24
|
- `Status:` is `approve` OR `Shipped` OR contains `ready to ship` ✓ (not `request changes`)
|
|
25
25
|
|
|
26
26
|
If conditions not met → **STOP**:
|
|
27
27
|
```
|
|
28
28
|
❌ Ship blocked. Review not completed or not approved.
|
|
29
29
|
Current status: {status}
|
|
30
|
-
Run /frame:review first.
|
|
30
|
+
Run /frame:review first (optionally /frame:test-plan before shipping).
|
|
31
31
|
```
|
|
32
32
|
|
|
33
33
|
Check `Deps Audit` in STATE.md:
|
|
@@ -0,0 +1,153 @@
|
|
|
1
|
+
# /frame:test-plan -- Manual User Acceptance Checklist
|
|
2
|
+
|
|
3
|
+
Generates a human-readable checklist of what YOU, as a user, should go and verify by hand after a feature is built. Not code tests (those are written during the task) — this is the "go click through it like a real user" list before shipping.
|
|
4
|
+
|
|
5
|
+
Runs in the TEST phase, between REVIEW and SHIP.
|
|
6
|
+
|
|
7
|
+
## Instructions
|
|
8
|
+
|
|
9
|
+
Build a manual test plan for: **$ARGUMENTS** (if empty — use the current feature from STATE.md).
|
|
10
|
+
|
|
11
|
+
### Step 0: Update STATE.md (start)
|
|
12
|
+
|
|
13
|
+
Update `.planning/STATE.md` before any work:
|
|
14
|
+
```markdown
|
|
15
|
+
## Current Position
|
|
16
|
+
- Phase: TEST
|
|
17
|
+
- Status: IN_PROGRESS
|
|
18
|
+
- Started: {timestamp}
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
### Step 1: Understand what changed
|
|
22
|
+
|
|
23
|
+
Read context in order (skip what doesn't exist):
|
|
24
|
+
- `.planning/STATE.md` — current feature, last completed tasks
|
|
25
|
+
- `docs/specs/{feature}/spec.md` — what the feature is supposed to do (user-facing behavior)
|
|
26
|
+
- `docs/specs/{feature}/plan.md` — which tasks were done, their Risk levels
|
|
27
|
+
- `docs/specs/{feature}/review.md` — issues found in review (verify they were actually fixed)
|
|
28
|
+
|
|
29
|
+
Then look at the real diff to ground the plan in what actually changed:
|
|
30
|
+
```bash
|
|
31
|
+
git diff --stat HEAD~1 HEAD 2>/dev/null || git diff --stat
|
|
32
|
+
git diff --stat
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
**D-step**: You now have a concrete list of what changed — features, screens, flows, endpoints, behaviors.
|
|
36
|
+
|
|
37
|
+
### Step 2: Turn changes into user-facing scenarios
|
|
38
|
+
|
|
39
|
+
For each change, ask: *"What would a user actually do that touches this, and what should they see?"*
|
|
40
|
+
|
|
41
|
+
Cover these categories (only the ones that apply):
|
|
42
|
+
|
|
43
|
+
- **Happy path** — the main flow the feature was built for, step by step as a user.
|
|
44
|
+
- **Edge cases** — empty states, long input, special characters, zero/many items, slow network, offline.
|
|
45
|
+
- **Error handling** — wrong input, denied permissions, failed request — does the user see a clear message (not a blank screen or crash)?
|
|
46
|
+
- **Regression** — existing flows near the changed code that could have broken. Use the diff to spot which screens/features sit next to the changes.
|
|
47
|
+
- **Cross-cutting** — mobile/responsive, different roles/accounts, language (i18n), refresh/back button, browser reload.
|
|
48
|
+
|
|
49
|
+
Each scenario must be written for a human to follow without reading code:
|
|
50
|
+
- **What to do** — concrete steps ("Open X → click Y → enter Z")
|
|
51
|
+
- **Expected** — what should happen ("see message «...», item appears in list")
|
|
52
|
+
|
|
53
|
+
Skip anything already fully covered by automated tests that can't be observed in the UI — this plan is about what a user *sees and does*.
|
|
54
|
+
|
|
55
|
+
### Step 3: Write the test plan file
|
|
56
|
+
|
|
57
|
+
Create `docs/specs/{feature}/test-plan.md`:
|
|
58
|
+
|
|
59
|
+
```markdown
|
|
60
|
+
# Test Plan: {Feature}
|
|
61
|
+
|
|
62
|
+
## Date
|
|
63
|
+
{date}
|
|
64
|
+
|
|
65
|
+
## What changed
|
|
66
|
+
{2–4 bullets in plain language — what's new/different from a user's point of view}
|
|
67
|
+
|
|
68
|
+
## How to verify (go do this as a user)
|
|
69
|
+
|
|
70
|
+
### Happy path
|
|
71
|
+
- [ ] **{Scenario}**
|
|
72
|
+
- Do: {steps}
|
|
73
|
+
- Expect: {result}
|
|
74
|
+
|
|
75
|
+
### Edge cases
|
|
76
|
+
- [ ] **{Scenario}**
|
|
77
|
+
- Do: {steps}
|
|
78
|
+
- Expect: {result}
|
|
79
|
+
|
|
80
|
+
### Error handling
|
|
81
|
+
- [ ] **{Scenario}**
|
|
82
|
+
- Do: {steps}
|
|
83
|
+
- Expect: {result}
|
|
84
|
+
|
|
85
|
+
### Regression (things near the change that could break)
|
|
86
|
+
- [ ] **{Scenario}**
|
|
87
|
+
- Do: {steps}
|
|
88
|
+
- Expect: {result}
|
|
89
|
+
|
|
90
|
+
### Cross-cutting (mobile / roles / i18n / reload)
|
|
91
|
+
- [ ] **{Scenario}**
|
|
92
|
+
- Do: {steps}
|
|
93
|
+
- Expect: {result}
|
|
94
|
+
|
|
95
|
+
## Where to test
|
|
96
|
+
- URL / screen / command: {from .frame/config.json devServer.url, or ask}
|
|
97
|
+
|
|
98
|
+
## Notes
|
|
99
|
+
{anything to watch for — known limitations, things review flagged}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
Keep it tight: 5–12 scenarios total, prioritized by Risk from plan.md (high-risk tasks get more scenarios). A short list that gets done beats a long one that doesn't.
|
|
103
|
+
|
|
104
|
+
### Step 4: Tell the user to go test
|
|
105
|
+
|
|
106
|
+
Output the checklist location and a short summary:
|
|
107
|
+
```
|
|
108
|
+
📋 Test plan ready: docs/specs/{feature}/test-plan.md
|
|
109
|
+
{N} scenarios to check by hand.
|
|
110
|
+
|
|
111
|
+
Top things to verify first:
|
|
112
|
+
1. {highest-risk scenario}
|
|
113
|
+
2. {next}
|
|
114
|
+
3. {next}
|
|
115
|
+
|
|
116
|
+
→ Go through the list, tick the boxes. When it passes, run /frame:ship.
|
|
117
|
+
If something fails → /frame:debug «what broke» or /frame:fast «fix».
|
|
118
|
+
```
|
|
119
|
+
|
|
120
|
+
For UI-heavy scenarios, optionally suggest:
|
|
121
|
+
```
|
|
122
|
+
For visual scenarios you can also run /frame:verify-ui to screenshot-check in a browser.
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Step 5: Update STATE.md (final)
|
|
126
|
+
|
|
127
|
+
```markdown
|
|
128
|
+
## Current Position
|
|
129
|
+
- Phase: TEST
|
|
130
|
+
- Feature: {feature}
|
|
131
|
+
- Test Plan: docs/specs/{feature}/test-plan.md
|
|
132
|
+
- Scenarios: {N}
|
|
133
|
+
- Status: Test plan ready, ready to ship
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Rules
|
|
137
|
+
|
|
138
|
+
- **User language, not code** — every scenario must be followable without reading the source.
|
|
139
|
+
- **Grounded in the diff** — scenarios come from what actually changed, not generic boilerplate.
|
|
140
|
+
- **Prioritize by Risk** — high-risk tasks from plan.md get the most attention.
|
|
141
|
+
- **Don't run the tests** — this command produces the checklist; the user (or /frame:verify-ui) executes it.
|
|
142
|
+
- **Short and finishable** — 5–12 scenarios, not 40.
|
|
143
|
+
|
|
144
|
+
## When to Use
|
|
145
|
+
|
|
146
|
+
- After `/frame:review` passes, before `/frame:ship`
|
|
147
|
+
- Whenever you want a concrete "what do I click to be sure this works" list
|
|
148
|
+
- Before shipping anything user-facing
|
|
149
|
+
|
|
150
|
+
## Result
|
|
151
|
+
|
|
152
|
+
- `docs/specs/{feature}/test-plan.md` created — manual user-acceptance checklist
|
|
153
|
+
- `.planning/STATE.md` updated (Phase: TEST, ready to ship)
|