@schalkneethling/toolkit 0.2.0 → 0.3.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 +29 -7
- package/dist/index.mjs +90 -6
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
- package/skills/css-coder/SKILL.md +95 -0
- package/skills/css-coder/references/patterns.md +224 -0
- package/skills/css-tokens/README.md +152 -0
- package/skills/css-tokens/SKILL.md +125 -0
- package/skills/css-tokens/references/tokens.css +162 -0
- package/skills/frontend-security/SKILL.md +134 -0
- package/skills/frontend-security/references/csp-configuration.md +191 -0
- package/skills/frontend-security/references/csrf-protection.md +327 -0
- package/skills/frontend-security/references/dom-security.md +229 -0
- package/skills/frontend-security/references/file-upload-security.md +310 -0
- package/skills/frontend-security/references/framework-patterns.md +307 -0
- package/skills/frontend-security/references/input-validation.md +232 -0
- package/skills/frontend-security/references/jwt-security.md +300 -0
- package/skills/frontend-security/references/nodejs-npm-security.md +261 -0
- package/skills/frontend-security/references/xss-prevention.md +163 -0
- package/skills/frontend-testing/SKILL.md +357 -0
- package/skills/frontend-testing/references/accessibility-testing.md +368 -0
- package/skills/frontend-testing/references/aria-snapshots.md +517 -0
- package/skills/frontend-testing/references/locator-strategies.md +295 -0
- package/skills/frontend-testing/references/visual-regression.md +466 -0
- package/skills/refined-plan-mode/SKILL.md +84 -0
|
@@ -0,0 +1,466 @@
|
|
|
1
|
+
# Visual Regression Testing
|
|
2
|
+
|
|
3
|
+
Visual regression testing (VRT) catches unintended visual changes by comparing screenshots against approved baselines.
|
|
4
|
+
|
|
5
|
+
## When to Use VRT
|
|
6
|
+
|
|
7
|
+
**Good candidates:**
|
|
8
|
+
- Design system components
|
|
9
|
+
- Critical landing pages
|
|
10
|
+
- Complex layouts (grids, dashboards)
|
|
11
|
+
- Components with CSS that changes frequently
|
|
12
|
+
- Cross-browser visual consistency
|
|
13
|
+
|
|
14
|
+
**Poor candidates:**
|
|
15
|
+
- Pages with frequently changing dynamic content
|
|
16
|
+
- Components with animations
|
|
17
|
+
- Time-dependent displays
|
|
18
|
+
- Pages with third-party content (ads, embeds)
|
|
19
|
+
|
|
20
|
+
## Playwright Visual Testing
|
|
21
|
+
|
|
22
|
+
### Basic Screenshot Comparison
|
|
23
|
+
|
|
24
|
+
```javascript
|
|
25
|
+
import { test, expect } from "@playwright/test";
|
|
26
|
+
|
|
27
|
+
test("homepage looks correct", async ({ page }) => {
|
|
28
|
+
await page.goto("/");
|
|
29
|
+
|
|
30
|
+
await expect(page).toHaveScreenshot();
|
|
31
|
+
});
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
First run creates the baseline. Subsequent runs compare against it.
|
|
35
|
+
|
|
36
|
+
### Named Screenshots
|
|
37
|
+
|
|
38
|
+
```javascript
|
|
39
|
+
test("hero section renders correctly", async ({ page }) => {
|
|
40
|
+
await page.goto("/");
|
|
41
|
+
|
|
42
|
+
await expect(page).toHaveScreenshot("homepage-hero.png");
|
|
43
|
+
});
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Element Screenshots
|
|
47
|
+
|
|
48
|
+
More stable than full-page screenshots:
|
|
49
|
+
|
|
50
|
+
```javascript
|
|
51
|
+
test("product card renders correctly", async ({ page }) => {
|
|
52
|
+
await page.goto("/products/123");
|
|
53
|
+
|
|
54
|
+
const productCard = page.getByTestId("product-card");
|
|
55
|
+
await expect(productCard).toHaveScreenshot("product-card.png");
|
|
56
|
+
});
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
### Full Page Screenshots
|
|
60
|
+
|
|
61
|
+
```javascript
|
|
62
|
+
test("full page layout", async ({ page }) => {
|
|
63
|
+
await page.goto("/about");
|
|
64
|
+
|
|
65
|
+
await expect(page).toHaveScreenshot("about-page-full.png", {
|
|
66
|
+
fullPage: true,
|
|
67
|
+
});
|
|
68
|
+
});
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
## Handling Instability
|
|
72
|
+
|
|
73
|
+
Visual tests fail due to timing, rendering, or environment differences. Stabilize tests before trusting results.
|
|
74
|
+
|
|
75
|
+
### Wait for Network and Fonts
|
|
76
|
+
|
|
77
|
+
```javascript
|
|
78
|
+
test("page renders after loading", async ({ page }) => {
|
|
79
|
+
await page.goto("/");
|
|
80
|
+
|
|
81
|
+
// Wait for network to be idle
|
|
82
|
+
await page.waitForLoadState("networkidle");
|
|
83
|
+
|
|
84
|
+
// Wait for web fonts to load
|
|
85
|
+
await page.evaluate(() => document.fonts.ready);
|
|
86
|
+
|
|
87
|
+
await expect(page).toHaveScreenshot();
|
|
88
|
+
});
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
### Disable Animations
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
// playwright.config.js
|
|
95
|
+
export default defineConfig({
|
|
96
|
+
use: {
|
|
97
|
+
// Disable CSS animations and transitions
|
|
98
|
+
contextOptions: {
|
|
99
|
+
reducedMotion: "reduce",
|
|
100
|
+
},
|
|
101
|
+
},
|
|
102
|
+
});
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
Or in test:
|
|
106
|
+
|
|
107
|
+
```javascript
|
|
108
|
+
test("static screenshot", async ({ page }) => {
|
|
109
|
+
await page.goto("/");
|
|
110
|
+
|
|
111
|
+
// Inject CSS to disable animations
|
|
112
|
+
await page.addStyleTag({
|
|
113
|
+
content: `
|
|
114
|
+
*, *::before, *::after {
|
|
115
|
+
animation-duration: 0s !important;
|
|
116
|
+
transition-duration: 0s !important;
|
|
117
|
+
}
|
|
118
|
+
`,
|
|
119
|
+
});
|
|
120
|
+
|
|
121
|
+
await expect(page).toHaveScreenshot();
|
|
122
|
+
});
|
|
123
|
+
```
|
|
124
|
+
|
|
125
|
+
### Mask Dynamic Content
|
|
126
|
+
|
|
127
|
+
Hide elements that change between runs:
|
|
128
|
+
|
|
129
|
+
```javascript
|
|
130
|
+
test("page with masked dynamic content", async ({ page }) => {
|
|
131
|
+
await page.goto("/dashboard");
|
|
132
|
+
|
|
133
|
+
await expect(page).toHaveScreenshot({
|
|
134
|
+
mask: [
|
|
135
|
+
page.locator("[data-testid='current-time']"),
|
|
136
|
+
page.locator("[data-testid='user-avatar']"),
|
|
137
|
+
page.locator(".ad-container"),
|
|
138
|
+
],
|
|
139
|
+
});
|
|
140
|
+
});
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
### Fixed Viewport
|
|
144
|
+
|
|
145
|
+
Lock viewport size for consistent screenshots:
|
|
146
|
+
|
|
147
|
+
```javascript
|
|
148
|
+
// playwright.config.js
|
|
149
|
+
export default defineConfig({
|
|
150
|
+
use: {
|
|
151
|
+
viewport: { width: 1280, height: 720 },
|
|
152
|
+
},
|
|
153
|
+
});
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
Or per-test:
|
|
157
|
+
|
|
158
|
+
```javascript
|
|
159
|
+
test("mobile view", async ({ page }) => {
|
|
160
|
+
await page.setViewportSize({ width: 375, height: 667 });
|
|
161
|
+
await page.goto("/");
|
|
162
|
+
await expect(page).toHaveScreenshot("homepage-mobile.png");
|
|
163
|
+
});
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
### Hide Scrollbars
|
|
167
|
+
|
|
168
|
+
Scrollbars vary by OS:
|
|
169
|
+
|
|
170
|
+
```javascript
|
|
171
|
+
await page.addStyleTag({
|
|
172
|
+
content: `
|
|
173
|
+
::-webkit-scrollbar { display: none; }
|
|
174
|
+
* { scrollbar-width: none; }
|
|
175
|
+
`,
|
|
176
|
+
});
|
|
177
|
+
```
|
|
178
|
+
|
|
179
|
+
## Tolerance Settings
|
|
180
|
+
|
|
181
|
+
Allow minor pixel differences to reduce flakiness.
|
|
182
|
+
|
|
183
|
+
### Global Configuration
|
|
184
|
+
|
|
185
|
+
```javascript
|
|
186
|
+
// playwright.config.js
|
|
187
|
+
export default defineConfig({
|
|
188
|
+
expect: {
|
|
189
|
+
toHaveScreenshot: {
|
|
190
|
+
maxDiffPixels: 100, // Allow up to 100 different pixels
|
|
191
|
+
maxDiffPixelRatio: 0.01, // Or 1% of total pixels
|
|
192
|
+
threshold: 0.2, // Color difference threshold (0-1)
|
|
193
|
+
},
|
|
194
|
+
},
|
|
195
|
+
});
|
|
196
|
+
```
|
|
197
|
+
|
|
198
|
+
### Per-Screenshot Settings
|
|
199
|
+
|
|
200
|
+
```javascript
|
|
201
|
+
await expect(page).toHaveScreenshot({
|
|
202
|
+
maxDiffPixels: 50,
|
|
203
|
+
threshold: 0.3,
|
|
204
|
+
});
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Threshold Guidelines
|
|
208
|
+
|
|
209
|
+
| Setting | Value | Use Case |
|
|
210
|
+
|---------|-------|----------|
|
|
211
|
+
| `threshold` | 0.1 | Strict pixel matching |
|
|
212
|
+
| `threshold` | 0.2 | Standard tolerance (default) |
|
|
213
|
+
| `threshold` | 0.3 | Generous for anti-aliasing |
|
|
214
|
+
| `maxDiffPixels` | 50 | Small components |
|
|
215
|
+
| `maxDiffPixels` | 200 | Full pages |
|
|
216
|
+
| `maxDiffPixelRatio` | 0.01 | 1% tolerance |
|
|
217
|
+
|
|
218
|
+
## Updating Baselines
|
|
219
|
+
|
|
220
|
+
### When to Update
|
|
221
|
+
|
|
222
|
+
- Intentional design changes
|
|
223
|
+
- New features affecting layout
|
|
224
|
+
- Browser rendering engine updates
|
|
225
|
+
- After fixing visual bugs
|
|
226
|
+
|
|
227
|
+
### Update Command
|
|
228
|
+
|
|
229
|
+
```bash
|
|
230
|
+
npx playwright test --update-snapshots
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
**Never update blindly.** Review changes before committing:
|
|
234
|
+
|
|
235
|
+
```bash
|
|
236
|
+
# See what changed
|
|
237
|
+
git diff --stat
|
|
238
|
+
# Review each screenshot
|
|
239
|
+
open tests/screenshots/
|
|
240
|
+
```
|
|
241
|
+
|
|
242
|
+
### Workflow
|
|
243
|
+
|
|
244
|
+
1. Test fails due to visual difference
|
|
245
|
+
2. Open test report, review diff image
|
|
246
|
+
3. If change is intentional:
|
|
247
|
+
- Update baseline with `--update-snapshots`
|
|
248
|
+
- Commit new baseline
|
|
249
|
+
4. If change is unintentional:
|
|
250
|
+
- Fix the code
|
|
251
|
+
- Run test again
|
|
252
|
+
|
|
253
|
+
## Cross-Browser Testing
|
|
254
|
+
|
|
255
|
+
Screenshots differ between browsers due to rendering differences.
|
|
256
|
+
|
|
257
|
+
### Browser-Specific Baselines
|
|
258
|
+
|
|
259
|
+
Playwright automatically creates separate baselines per browser:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
example.spec.ts-snapshots/
|
|
263
|
+
├── homepage-chromium-linux.png
|
|
264
|
+
├── homepage-firefox-linux.png
|
|
265
|
+
└── homepage-webkit-linux.png
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### Testing Specific Browsers
|
|
269
|
+
|
|
270
|
+
```javascript
|
|
271
|
+
// playwright.config.js
|
|
272
|
+
export default defineConfig({
|
|
273
|
+
projects: [
|
|
274
|
+
{
|
|
275
|
+
name: "chromium",
|
|
276
|
+
use: { ...devices["Desktop Chrome"] },
|
|
277
|
+
},
|
|
278
|
+
{
|
|
279
|
+
name: "firefox",
|
|
280
|
+
use: { ...devices["Desktop Firefox"] },
|
|
281
|
+
},
|
|
282
|
+
{
|
|
283
|
+
name: "webkit",
|
|
284
|
+
use: { ...devices["Desktop Safari"] },
|
|
285
|
+
},
|
|
286
|
+
],
|
|
287
|
+
});
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
### OS Differences
|
|
291
|
+
|
|
292
|
+
Font rendering varies by OS. Options:
|
|
293
|
+
- Run visual tests in CI only (consistent environment)
|
|
294
|
+
- Use Docker with consistent fonts
|
|
295
|
+
- Generate baselines in CI, not locally
|
|
296
|
+
|
|
297
|
+
## CI/CD Configuration
|
|
298
|
+
|
|
299
|
+
### GitHub Actions Example
|
|
300
|
+
|
|
301
|
+
```yaml
|
|
302
|
+
- name: Run visual tests
|
|
303
|
+
run: npx playwright test --project=chromium
|
|
304
|
+
|
|
305
|
+
- name: Upload diff artifacts on failure
|
|
306
|
+
if: failure()
|
|
307
|
+
uses: actions/upload-artifact@v7
|
|
308
|
+
with:
|
|
309
|
+
name: visual-diff
|
|
310
|
+
path: test-results/
|
|
311
|
+
```
|
|
312
|
+
|
|
313
|
+
### Generate Baselines in CI
|
|
314
|
+
|
|
315
|
+
For consistent baselines, generate in CI:
|
|
316
|
+
|
|
317
|
+
```yaml
|
|
318
|
+
- name: Update baselines
|
|
319
|
+
run: npx playwright test --update-snapshots
|
|
320
|
+
|
|
321
|
+
- name: Commit baselines
|
|
322
|
+
run: |
|
|
323
|
+
git config user.name "CI Bot"
|
|
324
|
+
git add "**/*.png"
|
|
325
|
+
git commit -m "Update visual baselines"
|
|
326
|
+
git push
|
|
327
|
+
```
|
|
328
|
+
|
|
329
|
+
## Organizing Screenshots
|
|
330
|
+
|
|
331
|
+
### Directory Structure
|
|
332
|
+
|
|
333
|
+
```
|
|
334
|
+
tests/
|
|
335
|
+
├── visual/
|
|
336
|
+
│ ├── homepage.spec.ts
|
|
337
|
+
│ └── components/
|
|
338
|
+
│ ├── button.spec.ts
|
|
339
|
+
│ └── card.spec.ts
|
|
340
|
+
└── visual.spec.ts-snapshots/
|
|
341
|
+
├── homepage-chromium.png
|
|
342
|
+
└── button-default-chromium.png
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
### Custom Path Template
|
|
346
|
+
|
|
347
|
+
```javascript
|
|
348
|
+
// playwright.config.js
|
|
349
|
+
export default defineConfig({
|
|
350
|
+
snapshotPathTemplate: "{testDir}/__snapshots__/{projectName}/{testFilePath}/{arg}{ext}",
|
|
351
|
+
});
|
|
352
|
+
```
|
|
353
|
+
|
|
354
|
+
## Reporting and Review
|
|
355
|
+
|
|
356
|
+
### Test Report
|
|
357
|
+
|
|
358
|
+
```bash
|
|
359
|
+
npx playwright show-report
|
|
360
|
+
```
|
|
361
|
+
|
|
362
|
+
Shows:
|
|
363
|
+
- Expected (baseline) image
|
|
364
|
+
- Actual (current) image
|
|
365
|
+
- Diff highlighting changed pixels
|
|
366
|
+
|
|
367
|
+
### Artifacts on Failure
|
|
368
|
+
|
|
369
|
+
Configure to save all artifacts:
|
|
370
|
+
|
|
371
|
+
```javascript
|
|
372
|
+
// playwright.config.js
|
|
373
|
+
export default defineConfig({
|
|
374
|
+
use: {
|
|
375
|
+
trace: "on-first-retry",
|
|
376
|
+
screenshot: "only-on-failure",
|
|
377
|
+
},
|
|
378
|
+
outputDir: "test-results/",
|
|
379
|
+
});
|
|
380
|
+
```
|
|
381
|
+
|
|
382
|
+
## Anti-Patterns
|
|
383
|
+
|
|
384
|
+
### Removing Platform Suffix
|
|
385
|
+
|
|
386
|
+
```javascript
|
|
387
|
+
// BAD: Removes platform/browser suffix from snapshot names
|
|
388
|
+
test.beforeEach(async ({}, testInfo) => {
|
|
389
|
+
testInfo.snapshotSuffix = "";
|
|
390
|
+
});
|
|
391
|
+
|
|
392
|
+
// Results in single baseline used across all platforms:
|
|
393
|
+
// button.png ← Used for Chrome/Mac, Firefox/Linux, Safari/Windows...
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
This seems appealing for "cleaner" snapshot names, but it breaks visual testing. Per [Playwright documentation](https://playwright.dev/docs/test-snapshots):
|
|
397
|
+
|
|
398
|
+
> "Different snapshots are needed for different browsers and platforms due to variations in rendering and fonts."
|
|
399
|
+
|
|
400
|
+
**Why it fails:**
|
|
401
|
+
- Font rendering differs between macOS, Windows, and Linux
|
|
402
|
+
- Anti-aliasing algorithms vary by OS and browser
|
|
403
|
+
- Subpixel rendering produces different results
|
|
404
|
+
- You'll get constant false positives or false negatives
|
|
405
|
+
|
|
406
|
+
**Keep the default naming:**
|
|
407
|
+
```
|
|
408
|
+
button-chromium-darwin.png
|
|
409
|
+
button-chromium-linux.png
|
|
410
|
+
button-firefox-linux.png
|
|
411
|
+
```
|
|
412
|
+
|
|
413
|
+
Yes, it's more files. But each baseline accurately represents that specific environment.
|
|
414
|
+
|
|
415
|
+
### Too Many Full-Page Screenshots
|
|
416
|
+
|
|
417
|
+
```javascript
|
|
418
|
+
// BAD: Full page with dynamic content
|
|
419
|
+
await expect(page).toHaveScreenshot({ fullPage: true });
|
|
420
|
+
|
|
421
|
+
// GOOD: Target stable regions
|
|
422
|
+
const header = page.getByRole("banner");
|
|
423
|
+
await expect(header).toHaveScreenshot("header.png");
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### No Stabilization
|
|
427
|
+
|
|
428
|
+
```javascript
|
|
429
|
+
// BAD: Screenshot immediately
|
|
430
|
+
await page.goto("/");
|
|
431
|
+
await expect(page).toHaveScreenshot();
|
|
432
|
+
|
|
433
|
+
// GOOD: Wait for stable state
|
|
434
|
+
await page.goto("/");
|
|
435
|
+
await page.waitForLoadState("networkidle");
|
|
436
|
+
await page.evaluate(() => document.fonts.ready);
|
|
437
|
+
await expect(page).toHaveScreenshot();
|
|
438
|
+
```
|
|
439
|
+
|
|
440
|
+
### Overly Strict Tolerance
|
|
441
|
+
|
|
442
|
+
```javascript
|
|
443
|
+
// BAD: Zero tolerance causes flaky tests
|
|
444
|
+
await expect(page).toHaveScreenshot({ maxDiffPixels: 0 });
|
|
445
|
+
|
|
446
|
+
// GOOD: Allow minor rendering differences
|
|
447
|
+
await expect(page).toHaveScreenshot({ maxDiffPixels: 50 });
|
|
448
|
+
```
|
|
449
|
+
|
|
450
|
+
### Updating Without Review
|
|
451
|
+
|
|
452
|
+
```bash
|
|
453
|
+
# BAD: Blindly update all baselines
|
|
454
|
+
npx playwright test --update-snapshots
|
|
455
|
+
|
|
456
|
+
# GOOD: Review changes first
|
|
457
|
+
npx playwright test
|
|
458
|
+
npx playwright show-report
|
|
459
|
+
# Review diffs, then update if intentional
|
|
460
|
+
npx playwright test --update-snapshots
|
|
461
|
+
```
|
|
462
|
+
|
|
463
|
+
## References
|
|
464
|
+
|
|
465
|
+
- [Playwright Visual Comparisons](https://playwright.dev/docs/test-snapshots)
|
|
466
|
+
- [Pixelmatch](https://github.com/mapbox/pixelmatch) — Image comparison library used by Playwright
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# Refined Plan Mode
|
|
2
|
+
|
|
3
|
+
Use this skill when the user starts a planning session using plan mode and wants the Refined Plan Mode review loop.
|
|
4
|
+
|
|
5
|
+
This skill is additive to the agent's current plan-mode guidance. It turns the plan into a versioned Markdown artifact that can be reviewed with line, range, and text-selection comments. The agent remains responsible for reading the feedback, revising the plan, and moving only when the user has approved the plan or explicitly asks to proceed.
|
|
6
|
+
|
|
7
|
+
## Core Protocol
|
|
8
|
+
|
|
9
|
+
1. Clarify only what is necessary to produce a useful plan.
|
|
10
|
+
2. Write the complete plan to `.plan-review/plans/plan-vN.md`.
|
|
11
|
+
3. Write the active version, such as `v1`, to `.plan-review/.current-version`.
|
|
12
|
+
4. Present a short summary to the user and point them at Refined Plan Mode for review.
|
|
13
|
+
5. After review, read `.plan-review/feedback/plan-vN-feedback.json`.
|
|
14
|
+
6. Address every feedback item in the next plan version.
|
|
15
|
+
7. Update `.plan-review/.current-version` to the new version.
|
|
16
|
+
8. Repeat until the plan is approved.
|
|
17
|
+
9. When the plan is approved, read `.plan-review/approved-plan.md` and execute it carefully.
|
|
18
|
+
|
|
19
|
+
## File Convention
|
|
20
|
+
|
|
21
|
+
```text
|
|
22
|
+
.plan-review/
|
|
23
|
+
.current-version
|
|
24
|
+
plans/
|
|
25
|
+
plan-v1.md
|
|
26
|
+
plan-v2.md
|
|
27
|
+
feedback/
|
|
28
|
+
plan-v1-feedback.json
|
|
29
|
+
plan-v2-feedback.json
|
|
30
|
+
approved-plan.md
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
Create missing directories when needed. Never summarize or truncate the plan file itself. The file should be self-contained enough for another agent to understand the goal, context, constraints, implementation steps, validation steps, and open questions.
|
|
34
|
+
|
|
35
|
+
## Plan Shape
|
|
36
|
+
|
|
37
|
+
Prefer this structure unless the task clearly calls for something else:
|
|
38
|
+
|
|
39
|
+
```markdown
|
|
40
|
+
# Plan vN: Short Title
|
|
41
|
+
|
|
42
|
+
## Goal
|
|
43
|
+
|
|
44
|
+
## Current Understanding
|
|
45
|
+
|
|
46
|
+
## Assumptions
|
|
47
|
+
|
|
48
|
+
## Open Questions
|
|
49
|
+
|
|
50
|
+
## Proposed Changes
|
|
51
|
+
|
|
52
|
+
## Validation
|
|
53
|
+
|
|
54
|
+
## Risks
|
|
55
|
+
|
|
56
|
+
## Rollback or Recovery
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
Keep the plan practical. Include file paths, commands, and decision points when known. Call out assumptions explicitly instead of hiding uncertainty inside confident prose.
|
|
60
|
+
|
|
61
|
+
## Feedback Handling
|
|
62
|
+
|
|
63
|
+
When feedback exists:
|
|
64
|
+
|
|
65
|
+
- Read the relevant JSON feedback file before revising.
|
|
66
|
+
- Treat every unresolved comment as actionable until clearly addressed.
|
|
67
|
+
- Preserve useful parts of the previous plan.
|
|
68
|
+
- Add a short `Feedback Addressed` section to the revised plan that maps comments to the changes made.
|
|
69
|
+
- If feedback conflicts or cannot be satisfied safely, explain that in the revised plan and ask the user for the smallest useful decision.
|
|
70
|
+
|
|
71
|
+
## Execution Gate
|
|
72
|
+
|
|
73
|
+
Do not begin implementation from an unapproved plan unless the user explicitly asks you to proceed. Once `.plan-review/approved-plan.md` exists or the user directly approves the plan in conversation, execute the approved plan and keep the normal agent workflow: inspect files, make focused edits, validate, and report the outcome.
|
|
74
|
+
|
|
75
|
+
## User Updates
|
|
76
|
+
|
|
77
|
+
In conversation, keep updates brief:
|
|
78
|
+
|
|
79
|
+
- Say which plan version was written.
|
|
80
|
+
- Say where feedback should be submitted.
|
|
81
|
+
- Say which feedback file was read when revising.
|
|
82
|
+
- Say when the plan is approved and execution is beginning.
|
|
83
|
+
|
|
84
|
+
The plan file carries the detail; the chat message should help the user orient without duplicating the full artifact.
|