@seanyao/roll 0.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 +201 -0
- package/bin/roll +1375 -0
- package/conventions/config.yaml +15 -0
- package/conventions/global/.cursor-rules +31 -0
- package/conventions/global/AGENTS.md +100 -0
- package/conventions/global/CLAUDE.md +32 -0
- package/conventions/global/GEMINI.md +28 -0
- package/conventions/templates/backend-service/.cursor-rules +17 -0
- package/conventions/templates/backend-service/AGENTS.md +88 -0
- package/conventions/templates/backend-service/CLAUDE.md +18 -0
- package/conventions/templates/backend-service/GEMINI.md +16 -0
- package/conventions/templates/cli/.cursor-rules +17 -0
- package/conventions/templates/cli/AGENTS.md +66 -0
- package/conventions/templates/cli/CLAUDE.md +18 -0
- package/conventions/templates/cli/GEMINI.md +16 -0
- package/conventions/templates/frontend-only/.cursor-rules +16 -0
- package/conventions/templates/frontend-only/AGENTS.md +71 -0
- package/conventions/templates/frontend-only/CLAUDE.md +16 -0
- package/conventions/templates/frontend-only/GEMINI.md +14 -0
- package/conventions/templates/fullstack/.cursor-rules +17 -0
- package/conventions/templates/fullstack/AGENTS.md +87 -0
- package/conventions/templates/fullstack/CLAUDE.md +17 -0
- package/conventions/templates/fullstack/GEMINI.md +15 -0
- package/package.json +33 -0
- package/skills/roll-.changelog/SKILL.md +79 -0
- package/skills/roll-.clarify/SKILL.md +59 -0
- package/skills/roll-.echo/SKILL.md +113 -0
- package/skills/roll-.qa/SKILL.md +204 -0
- package/skills/roll-.review/SKILL.md +105 -0
- package/skills/roll-build/SKILL.md +559 -0
- package/skills/roll-debug/SKILL.md +428 -0
- package/skills/roll-design/ENGINEERING_CHECKLIST.md +256 -0
- package/skills/roll-design/SKILL.md +276 -0
- package/skills/roll-fix/SKILL.md +442 -0
- package/skills/roll-jot/SKILL.md +50 -0
- package/skills/roll-research/SKILL.md +307 -0
- package/skills/roll-research/references/schema.json +162 -0
- package/skills/roll-research/scripts/md_to_pdf.py +289 -0
- package/skills/roll-sentinel/SKILL.md +355 -0
- package/skills/roll-spar/SKILL.md +287 -0
- package/template/.env.example +47 -0
- package/template/.github/workflows/ci.yml +32 -0
- package/template/.github/workflows/sentinel.yml +26 -0
- package/template/AGENTS.md +80 -0
- package/template/BACKLOG.md +42 -0
- package/template/package.json +43 -0
- package/tools/roll-fetch/SKILL.md +182 -0
- package/tools/roll-fetch/package.json +15 -0
- package/tools/roll-fetch/smart-web-fetch.js +558 -0
- package/tools/roll-probe/SKILL.md +84 -0
|
@@ -0,0 +1,428 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: roll-debug
|
|
3
|
+
description: Universal web debugger. Collects diagnostics (console/network/DOM) via Playwright, analyzes root causes, and suggests fixes. Works with or without Black Box (BB) integration.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Roll Debug
|
|
7
|
+
|
|
8
|
+
Universal web debugging tool that combines diagnostic collection and analysis into a single workflow: **Diagnose โ Analyze โ Suggest Fix**.
|
|
9
|
+
|
|
10
|
+
Two collection modes:
|
|
11
|
+
- **Native BB Mode**: Page has Black Box integrated; click button to collect rich diagnostic data
|
|
12
|
+
- **Universal Diagnostic Mode**: Page has no BB; use Playwright to directly collect console/network/DOM/screenshot data
|
|
13
|
+
|
|
14
|
+
## When to Use
|
|
15
|
+
|
|
16
|
+
- "Debug the page"
|
|
17
|
+
- "See what's wrong"
|
|
18
|
+
- "Page shows blank"
|
|
19
|
+
- "Feature not working"
|
|
20
|
+
- User uploads a diagnostic file (`diagnostics-*.json`, `bb-report.json`)
|
|
21
|
+
- "Analyze BB data", "look at the diagnostic file"
|
|
22
|
+
- Any scenario requiring web page diagnosis
|
|
23
|
+
|
|
24
|
+
## Quick Start
|
|
25
|
+
|
|
26
|
+
```bash
|
|
27
|
+
# Full workflow: collect + analyze + suggest fix (recommended)
|
|
28
|
+
$roll-debug https://example.com/page
|
|
29
|
+
|
|
30
|
+
# Collect data only, skip analysis
|
|
31
|
+
$roll-debug https://example.com/page --no-analyze
|
|
32
|
+
|
|
33
|
+
# Force universal diagnostic mode (no BB)
|
|
34
|
+
$roll-debug https://example.com/page --universal
|
|
35
|
+
|
|
36
|
+
# Collect + analyze + auto-fix
|
|
37
|
+
$roll-debug https://example.com/page --fix
|
|
38
|
+
|
|
39
|
+
# Analyze an existing report file (skip collection)
|
|
40
|
+
$roll-debug --report /tmp/bb-report.json
|
|
41
|
+
|
|
42
|
+
# Batch: diagnose multiple pages
|
|
43
|
+
$roll-debug https://site.com/page1,https://site.com/page2
|
|
44
|
+
$roll-debug --file urls.txt
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
## Two Collection Modes
|
|
48
|
+
|
|
49
|
+
### Mode 1: Native BB (Page has Black Box integrated)
|
|
50
|
+
|
|
51
|
+
```
|
|
52
|
+
Page with BB โ Playwright clicks BB button โ Download diagnostic JSON
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Requirements:
|
|
56
|
+
- Page has `[data-testid="bb-toggle"]` button
|
|
57
|
+
- Or exposes `window.__BB_DATA__`
|
|
58
|
+
- Or stores data in `localStorage.bb_diagnostic`
|
|
59
|
+
|
|
60
|
+
### Mode 2: Universal Diagnostic (No BB required)
|
|
61
|
+
|
|
62
|
+
```
|
|
63
|
+
Any page โ Playwright injects collector โ Gather console/network/DOM/screenshot
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
Collects:
|
|
67
|
+
- Console logs (error/warn/info)
|
|
68
|
+
- Network requests (failed XHR/fetch, slow requests)
|
|
69
|
+
- DOM state (key elements visibility, HTML length)
|
|
70
|
+
- Screenshot (full page + viewport)
|
|
71
|
+
- Performance metrics (load time, FCP, LCP, render blocking)
|
|
72
|
+
- JavaScript errors with stack traces
|
|
73
|
+
|
|
74
|
+
## Full Workflow
|
|
75
|
+
|
|
76
|
+
```
|
|
77
|
+
User: "Debug the page"
|
|
78
|
+
โ
|
|
79
|
+
โผ
|
|
80
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
81
|
+
โ 1. Auto-detect collection mode โ
|
|
82
|
+
โ โโโ Try BB button โ found? โ
|
|
83
|
+
โ โโโ Try window.__BB_DATA__? โ
|
|
84
|
+
โ โโโ Fallback to Universal โ
|
|
85
|
+
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ
|
|
86
|
+
โ
|
|
87
|
+
โผ
|
|
88
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
89
|
+
โ 2. Collect diagnostic data โ
|
|
90
|
+
โ โโโ Console logs โ
|
|
91
|
+
โ โโโ Network requests โ
|
|
92
|
+
โ โโโ DOM state โ
|
|
93
|
+
โ โโโ Screenshot โ
|
|
94
|
+
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ
|
|
95
|
+
โ
|
|
96
|
+
โผ
|
|
97
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
98
|
+
โ 3. Analyze report โ
|
|
99
|
+
โ โโโ Read /tmp/bb-report.json โ
|
|
100
|
+
โ โโโ Root cause analysis โ
|
|
101
|
+
โ โโโ Issue severity โ
|
|
102
|
+
โ โโโ Structured findings โ
|
|
103
|
+
โโโโโโโโโโโโโโโโโโโโฌโโโโโโโโโโโโโโโโโโโ
|
|
104
|
+
โ
|
|
105
|
+
โผ
|
|
106
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
107
|
+
โ 4. Suggest (or apply) fix โ
|
|
108
|
+
โ โโโ Actionable fix suggestions โ
|
|
109
|
+
โ โโโ Auto-fix via TCR (--fix) โ
|
|
110
|
+
โ โโโ Deploy & verify โ
|
|
111
|
+
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Usage Examples
|
|
115
|
+
|
|
116
|
+
### Example 1: Full auto-detect + analyze (default)
|
|
117
|
+
|
|
118
|
+
```bash
|
|
119
|
+
$roll-debug https://yyy.up.railway.app/story/cars/chapter/1
|
|
120
|
+
|
|
121
|
+
Detecting diagnostic capability...
|
|
122
|
+
โโโ BB found: [data-testid="bb-toggle"]
|
|
123
|
+
โโโ Using: Native BB mode
|
|
124
|
+
|
|
125
|
+
Collecting data...
|
|
126
|
+
โโโ Console: 3 errors, 5 warnings
|
|
127
|
+
โโโ Network: 2 failed requests
|
|
128
|
+
โโโ DOM: #app rendered, .content empty
|
|
129
|
+
โโโ Screenshot: saved to /tmp/bb-screenshot.png
|
|
130
|
+
|
|
131
|
+
Report: /tmp/bb-report.json
|
|
132
|
+
|
|
133
|
+
Analyzing...
|
|
134
|
+
|
|
135
|
+
## Diagnostic Analysis Report
|
|
136
|
+
|
|
137
|
+
### Basic Info
|
|
138
|
+
| Field | Value |
|
|
139
|
+
|-------|-------|
|
|
140
|
+
| Diagnostic Mode | native-bb |
|
|
141
|
+
| Page URL | https://yyy.up.railway.app/story/cars/chapter/1 |
|
|
142
|
+
|
|
143
|
+
### Key Findings
|
|
144
|
+
| Metric | Value | Status |
|
|
145
|
+
|--------|-------|--------|
|
|
146
|
+
| contentLength | 0 | Not loaded |
|
|
147
|
+
| audioState.src | "" | Not set |
|
|
148
|
+
| hasText | false | No content |
|
|
149
|
+
| Console Errors | 3 | Critical |
|
|
150
|
+
| Network Failed | 2 | Critical |
|
|
151
|
+
|
|
152
|
+
### Diagnosis Conclusion
|
|
153
|
+
useEffect dependency error causing content not to load.
|
|
154
|
+
Dependency `[chapter?.id]` should be `[chapter?.number]`
|
|
155
|
+
|
|
156
|
+
### Suggested Fix
|
|
157
|
+
Modify Player.tsx line 45, change useEffect dependency
|
|
158
|
+
from `[chapter?.id]` to `[chapter?.number]`
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
### Example 2: Universal mode (no BB)
|
|
162
|
+
|
|
163
|
+
```bash
|
|
164
|
+
$roll-debug https://example.com --universal
|
|
165
|
+
|
|
166
|
+
Universal diagnostic mode (no BB required)
|
|
167
|
+
|
|
168
|
+
Collected:
|
|
169
|
+
โโโ Console Errors: 2
|
|
170
|
+
โ โโโ TypeError: Cannot read property 'id' of undefined
|
|
171
|
+
โ โ at Player.tsx:45
|
|
172
|
+
โ โโโ ReferenceError: AudioContext is not defined
|
|
173
|
+
โโโ Failed Network: 1
|
|
174
|
+
โ โโโ GET https://api.example.com/data 404
|
|
175
|
+
โโโ DOM State:
|
|
176
|
+
โ โโโ body.innerHTML length: 2340
|
|
177
|
+
โ โโโ #root: rendered
|
|
178
|
+
โ โโโ .loading: still visible (timeout?)
|
|
179
|
+
โ โโโ .error-message: visible
|
|
180
|
+
โโโ Performance:
|
|
181
|
+
โ โโโ DOMContentLoaded: 1.2s
|
|
182
|
+
โ โโโ First Contentful Paint: 2.3s
|
|
183
|
+
โ โโโ Largest Contentful Paint: 4.5s
|
|
184
|
+
โโโ Screenshot: /tmp/bb-screenshot.png
|
|
185
|
+
|
|
186
|
+
Report: /tmp/bb-report.json
|
|
187
|
+
|
|
188
|
+
Analyzing...
|
|
189
|
+
|
|
190
|
+
### Key Findings
|
|
191
|
+
| Metric | Value | Status |
|
|
192
|
+
|--------|-------|--------|
|
|
193
|
+
| Console Errors | 2 | Critical |
|
|
194
|
+
| Network Failed | 1 | Critical |
|
|
195
|
+
| DOM Rendering | Partial | Warning |
|
|
196
|
+
| Load Time (LCP) | 4.5s | Slow |
|
|
197
|
+
|
|
198
|
+
### Diagnosis Conclusion
|
|
199
|
+
API endpoint returning 404 causes content not to load.
|
|
200
|
+
AudioContext undefined suggests missing polyfill or browser incompatibility.
|
|
201
|
+
|
|
202
|
+
### Suggested Fix
|
|
203
|
+
1. Fix API route for /data endpoint (404)
|
|
204
|
+
2. Add AudioContext polyfill or guard with `typeof AudioContext !== 'undefined'`
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
### Example 3: Analyze existing report file
|
|
208
|
+
|
|
209
|
+
```bash
|
|
210
|
+
$roll-debug --report /tmp/bb-report.json
|
|
211
|
+
|
|
212
|
+
Reading report: /tmp/bb-report.json (mode: universal)
|
|
213
|
+
|
|
214
|
+
### Key Findings
|
|
215
|
+
...
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
## Analysis: Supported Report Formats
|
|
219
|
+
|
|
220
|
+
| Format | Source | Description |
|
|
221
|
+
|--------|--------|-------------|
|
|
222
|
+
| Native BB | Page with Black Box | `window.__BB_DATA__` or `localStorage.bb_diagnostic` |
|
|
223
|
+
| Universal | Playwright collector | Injected collector data |
|
|
224
|
+
| Legacy | Old diagnostic files | Backward compatible |
|
|
225
|
+
|
|
226
|
+
### Native BB Mode Fields
|
|
227
|
+
|
|
228
|
+
```javascript
|
|
229
|
+
const bbData = report.diagnostic.bbData;
|
|
230
|
+
bbData.contentState?.hasText
|
|
231
|
+
bbData.contentState?.contentLength
|
|
232
|
+
bbData.audioState?.src
|
|
233
|
+
bbData.audioState?.error
|
|
234
|
+
bbData.hasAudio
|
|
235
|
+
bbData.errors
|
|
236
|
+
```
|
|
237
|
+
|
|
238
|
+
### Universal Mode Fields
|
|
239
|
+
|
|
240
|
+
```javascript
|
|
241
|
+
const d = report.diagnostic;
|
|
242
|
+
d.console.errors
|
|
243
|
+
d.console.warnings
|
|
244
|
+
d.network.failed
|
|
245
|
+
d.network.slow
|
|
246
|
+
d.dom.title
|
|
247
|
+
d.dom['#root']
|
|
248
|
+
d.dom.htmlLength
|
|
249
|
+
d.performance.loadComplete
|
|
250
|
+
d.performance.domContentLoaded
|
|
251
|
+
d.errors
|
|
252
|
+
```
|
|
253
|
+
|
|
254
|
+
## Analysis Report Template
|
|
255
|
+
|
|
256
|
+
```markdown
|
|
257
|
+
## Diagnostic Analysis Report
|
|
258
|
+
|
|
259
|
+
### Basic Info
|
|
260
|
+
| Field | Value |
|
|
261
|
+
|-------|-------|
|
|
262
|
+
| Diagnostic Mode | {native-bb / universal} |
|
|
263
|
+
| Page URL | {url} |
|
|
264
|
+
| Collected At | {timestamp} |
|
|
265
|
+
|
|
266
|
+
### Key Findings
|
|
267
|
+
| Metric | Value | Status |
|
|
268
|
+
|--------|-------|--------|
|
|
269
|
+
| Console Errors | {N} | {Critical if >0, OK if 0} |
|
|
270
|
+
| Network Failed | {N} | {Critical if >0, OK if 0} |
|
|
271
|
+
| DOM Rendering | {status} | {OK / Not rendered} |
|
|
272
|
+
| Load Time | {X}ms | {OK <2s, Slow 2-5s, Critical >5s} |
|
|
273
|
+
|
|
274
|
+
### Diagnosis Conclusion
|
|
275
|
+
{Root cause in plain language}
|
|
276
|
+
|
|
277
|
+
### Suggested Fix
|
|
278
|
+
{Actionable fix steps}
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
## Common Issue Patterns
|
|
282
|
+
|
|
283
|
+
### Blank Page
|
|
284
|
+
- `dom.htmlLength < 500` or `dom['#root'].visible = false`
|
|
285
|
+
- Fix: Check console errors, add error boundary
|
|
286
|
+
|
|
287
|
+
### Content Not Loading
|
|
288
|
+
- `hasText = false` or `contentLength = 0`
|
|
289
|
+
- Fix: Check API, refresh OSS URL, fix useEffect dependencies
|
|
290
|
+
|
|
291
|
+
### Audio Error
|
|
292
|
+
- `audioState.error` exists
|
|
293
|
+
- Fix: Refresh signed URL, check audio format compatibility
|
|
294
|
+
|
|
295
|
+
### Network Failure
|
|
296
|
+
- `network.failed` has 4xx/5xx responses
|
|
297
|
+
- Fix: Check API routes, add CORS headers
|
|
298
|
+
|
|
299
|
+
### Performance Issues
|
|
300
|
+
- LCP > 5s or DOMContentLoaded > 3s
|
|
301
|
+
- Fix: Code-split large bundles, lazy-load images, cache API responses
|
|
302
|
+
|
|
303
|
+
## Implementation Notes
|
|
304
|
+
|
|
305
|
+
### Universal Mode Injection
|
|
306
|
+
|
|
307
|
+
When page has no BB, inject a lightweight collector via `page.evaluate()`:
|
|
308
|
+
|
|
309
|
+
```javascript
|
|
310
|
+
window.__ROLL_DEBUG_COLLECTOR__ = {
|
|
311
|
+
console: [],
|
|
312
|
+
network: [],
|
|
313
|
+
errors: [],
|
|
314
|
+
|
|
315
|
+
init() {
|
|
316
|
+
// Hook console methods
|
|
317
|
+
['error', 'warn', 'log', 'info'].forEach(method => {
|
|
318
|
+
const original = console[method];
|
|
319
|
+
console[method] = (...args) => {
|
|
320
|
+
this.console.push({method, args, timestamp: Date.now()});
|
|
321
|
+
original.apply(console, args);
|
|
322
|
+
};
|
|
323
|
+
});
|
|
324
|
+
|
|
325
|
+
// Hook fetch/XHR for network interception
|
|
326
|
+
|
|
327
|
+
// Listen for JS errors
|
|
328
|
+
window.addEventListener('error', e => {
|
|
329
|
+
this.errors.push({message: e.message, stack: e.error?.stack});
|
|
330
|
+
});
|
|
331
|
+
},
|
|
332
|
+
|
|
333
|
+
getData() {
|
|
334
|
+
return {
|
|
335
|
+
console: this.console,
|
|
336
|
+
network: this.network,
|
|
337
|
+
errors: this.errors,
|
|
338
|
+
dom: this.captureDOM(),
|
|
339
|
+
performance: this.capturePerformance()
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
```
|
|
344
|
+
|
|
345
|
+
The injected collector only exists in the Playwright browser context โ no cleanup needed.
|
|
346
|
+
|
|
347
|
+
## Data Output Formats
|
|
348
|
+
|
|
349
|
+
### Native BB Mode
|
|
350
|
+
|
|
351
|
+
```json
|
|
352
|
+
{
|
|
353
|
+
"mode": "native-bb",
|
|
354
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
355
|
+
"url": "https://example.com/page",
|
|
356
|
+
"bbData": {},
|
|
357
|
+
"collected": {
|
|
358
|
+
"console": [],
|
|
359
|
+
"network": []
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
```
|
|
363
|
+
|
|
364
|
+
### Universal Mode
|
|
365
|
+
|
|
366
|
+
```json
|
|
367
|
+
{
|
|
368
|
+
"mode": "universal",
|
|
369
|
+
"timestamp": "2024-01-15T10:30:00Z",
|
|
370
|
+
"url": "https://example.com/page",
|
|
371
|
+
"diagnostic": {
|
|
372
|
+
"console": {
|
|
373
|
+
"errors": [{"message": "...", "stack": "...", "timestamp": "..."}],
|
|
374
|
+
"warnings": [],
|
|
375
|
+
"logs": []
|
|
376
|
+
},
|
|
377
|
+
"network": {
|
|
378
|
+
"failed": [{"url": "...", "status": 404, "method": "GET"}],
|
|
379
|
+
"slow": [{"url": "...", "duration": 5000}]
|
|
380
|
+
},
|
|
381
|
+
"dom": {
|
|
382
|
+
"title": "Page Title",
|
|
383
|
+
"htmlLength": 2340,
|
|
384
|
+
"keyElements": {
|
|
385
|
+
"#root": {"exists": true, "visible": true, "children": 5},
|
|
386
|
+
".error": {"exists": false}
|
|
387
|
+
}
|
|
388
|
+
},
|
|
389
|
+
"performance": {
|
|
390
|
+
"domContentLoaded": 1200,
|
|
391
|
+
"loadComplete": 2300,
|
|
392
|
+
"firstContentfulPaint": 2300,
|
|
393
|
+
"largestContentfulPaint": 4500
|
|
394
|
+
}
|
|
395
|
+
},
|
|
396
|
+
"screenshots": {
|
|
397
|
+
"viewport": "/tmp/roll-debug-viewport.png",
|
|
398
|
+
"fullPage": "/tmp/roll-debug-fullpage.png"
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
```
|
|
402
|
+
|
|
403
|
+
## Capability Comparison
|
|
404
|
+
|
|
405
|
+
| Feature | Native BB Mode | Universal Mode |
|
|
406
|
+
|---------|---------------|----------------|
|
|
407
|
+
| Requires BB integration | Yes | No |
|
|
408
|
+
| Console logs | Yes | Yes |
|
|
409
|
+
| Network data | Yes | Yes |
|
|
410
|
+
| DOM state | Detailed | Key elements |
|
|
411
|
+
| App-specific metrics | Yes | No |
|
|
412
|
+
| Screenshot | Yes | Yes |
|
|
413
|
+
| Performance metrics | Yes | Yes |
|
|
414
|
+
| Works on any site | No | Yes |
|
|
415
|
+
|
|
416
|
+
## Integration with Build Skills
|
|
417
|
+
|
|
418
|
+
After `$roll-debug` finds issues:
|
|
419
|
+
|
|
420
|
+
```bash
|
|
421
|
+
# For a single-file bug fix
|
|
422
|
+
# โ Create FIX-XXX in backlog
|
|
423
|
+
# โ $roll-fix FIX-XXX
|
|
424
|
+
|
|
425
|
+
# For a complex multi-step fix
|
|
426
|
+
# โ Create US-XXX in backlog
|
|
427
|
+
# โ $roll-story US-XXX
|
|
428
|
+
```
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
# Wukong Engineering Common Sense Checklist
|
|
2
|
+
|
|
3
|
+
> **These are not best practices โ they are baseline requirements.** Violations are bugs.
|
|
4
|
+
|
|
5
|
+
## 1. Idempotency ๐
|
|
6
|
+
|
|
7
|
+
**Definition:** Performing the same operation N times produces the same result as performing it once.
|
|
8
|
+
|
|
9
|
+
**Must test:**
|
|
10
|
+
```typescript
|
|
11
|
+
it('should be idempotent', async () => {
|
|
12
|
+
await operation(data) // 1st
|
|
13
|
+
const result1 = await getState()
|
|
14
|
+
|
|
15
|
+
await operation(data) // 2nd
|
|
16
|
+
const result2 = await getState()
|
|
17
|
+
|
|
18
|
+
await operation(data) // 3rd
|
|
19
|
+
const result3 = await getState()
|
|
20
|
+
|
|
21
|
+
expect(result1).toEqual(result2)
|
|
22
|
+
expect(result2).toEqual(result3)
|
|
23
|
+
})
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
**Common scenarios:**
|
|
27
|
+
- [ ] Import/ingest operations
|
|
28
|
+
- [ ] Configuration updates
|
|
29
|
+
- [ ] State transitions
|
|
30
|
+
- [ ] API calls
|
|
31
|
+
- [ ] File writes
|
|
32
|
+
|
|
33
|
+
**Counter-example (this time):** Running ingest repeatedly โ files duplicated 7 times
|
|
34
|
+
|
|
35
|
+
---
|
|
36
|
+
|
|
37
|
+
## 2. Cross-Module Contract Consistency ๐
|
|
38
|
+
|
|
39
|
+
**Definition:** Data/IDs/formats shared across multiple modules must be fully consistent.
|
|
40
|
+
|
|
41
|
+
**Must check:**
|
|
42
|
+
```typescript
|
|
43
|
+
// Checklist
|
|
44
|
+
- [ ] Is the ID generation algorithm consistent?
|
|
45
|
+
- [ ] Is the data serialization format consistent?
|
|
46
|
+
- [ ] Is path handling consistent? (e.g., / vs -)
|
|
47
|
+
- [ ] Is it extracted into a shared function/constant?
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Test template:**
|
|
51
|
+
```typescript
|
|
52
|
+
it('should generate same ID across modules', () => {
|
|
53
|
+
const scannerId = generateScannerId('articles/test.md')
|
|
54
|
+
const inboxId = generateInboxId('articles/test.md')
|
|
55
|
+
expect(scannerId).toEqual(inboxId)
|
|
56
|
+
})
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
**Counter-example (this time):** Scanner replaces `/` with `-`, inbox uses raw path โ deduplication fails
|
|
60
|
+
|
|
61
|
+
---
|
|
62
|
+
|
|
63
|
+
## 3. Data Flow Integrity ๐
|
|
64
|
+
|
|
65
|
+
**Definition:** The complete data pipeline from producer to consumer must be unobstructed.
|
|
66
|
+
|
|
67
|
+
**Must verify:**
|
|
68
|
+
```typescript
|
|
69
|
+
// Integration test - must exist
|
|
70
|
+
describe('Data Flow: Producer -> Consumer', () => {
|
|
71
|
+
it('should write data that consumer can read', async () => {
|
|
72
|
+
await producer.write(testData)
|
|
73
|
+
const result = await consumer.read()
|
|
74
|
+
expect(result).toEqual(testData)
|
|
75
|
+
})
|
|
76
|
+
})
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**Checklist:**
|
|
80
|
+
- [ ] Who writes the data? (Producer)
|
|
81
|
+
- [ ] Who reads the data? (Consumer)
|
|
82
|
+
- [ ] What is the intermediate storage? (state/file/cache)
|
|
83
|
+
- [ ] Is there an integration test to verify?
|
|
84
|
+
|
|
85
|
+
**Counter-example (this time):** Ingest doesn't write state, status can't read it โ displays 0
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## 4. Atomicity โ๏ธ
|
|
90
|
+
|
|
91
|
+
**Definition:** An operation either fully succeeds or doesn't execute at all (no intermediate states).
|
|
92
|
+
|
|
93
|
+
**Must consider:**
|
|
94
|
+
- [ ] How to roll back on partial failure?
|
|
95
|
+
- [ ] Is there a transaction mechanism?
|
|
96
|
+
- [ ] How is data consistency guaranteed after a crash?
|
|
97
|
+
|
|
98
|
+
**Test template:**
|
|
99
|
+
```typescript
|
|
100
|
+
it('should be atomic', async () => {
|
|
101
|
+
try {
|
|
102
|
+
await operation([item1, item2, INVALID_ITEM, item4])
|
|
103
|
+
} catch (e) {
|
|
104
|
+
// After failure, already-processed items should be rolled back
|
|
105
|
+
const state = await getState()
|
|
106
|
+
expect(state).toEqual(initialState)
|
|
107
|
+
}
|
|
108
|
+
})
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 5. Input Validation ๐ก๏ธ
|
|
114
|
+
|
|
115
|
+
**Definition:** Never trust any external input โ it must be validated.
|
|
116
|
+
|
|
117
|
+
**Must check:**
|
|
118
|
+
- [ ] Null/undefined handling
|
|
119
|
+
- [ ] Type checking
|
|
120
|
+
- [ ] Range checking (array length, numeric range)
|
|
121
|
+
- [ ] Special character/injection attack protection
|
|
122
|
+
- [ ] File path traversal protection
|
|
123
|
+
|
|
124
|
+
**Test template:**
|
|
125
|
+
```typescript
|
|
126
|
+
it('should handle invalid inputs gracefully', async () => {
|
|
127
|
+
await expect(operation(null)).rejects.toThrow()
|
|
128
|
+
await expect(operation('')).rejects.toThrow()
|
|
129
|
+
await expect(operation({})).rejects.toThrow()
|
|
130
|
+
})
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
---
|
|
134
|
+
|
|
135
|
+
## 6. Graceful Degradation ๐ช
|
|
136
|
+
|
|
137
|
+
**Definition:** When a dependency fails, the system should still provide limited functionality.
|
|
138
|
+
|
|
139
|
+
**Must consider:**
|
|
140
|
+
- [ ] What happens when an external API fails?
|
|
141
|
+
- [ ] What happens when the database connection drops?
|
|
142
|
+
- [ ] Is there a fallback mechanism?
|
|
143
|
+
- [ ] What feedback does the user receive?
|
|
144
|
+
|
|
145
|
+
**Test template:**
|
|
146
|
+
```typescript
|
|
147
|
+
it('should degrade gracefully when dependency fails', async () => {
|
|
148
|
+
mockDependency.toThrow('Network error')
|
|
149
|
+
|
|
150
|
+
// Should not crash
|
|
151
|
+
const result = await operation()
|
|
152
|
+
|
|
153
|
+
// Should return a fallback value or partial result
|
|
154
|
+
expect(result).toEqual(fallbackValue)
|
|
155
|
+
})
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
---
|
|
159
|
+
|
|
160
|
+
## 7. Observability ๐๏ธ
|
|
161
|
+
|
|
162
|
+
**Definition:** System state must be visible and traceable.
|
|
163
|
+
|
|
164
|
+
**Must provide:**
|
|
165
|
+
- [ ] Progress feedback (for long-running operations)
|
|
166
|
+
- [ ] State query interface (e.g., status command)
|
|
167
|
+
- [ ] Error logs (failure reasons)
|
|
168
|
+
- [ ] Key metrics (counts, durations)
|
|
169
|
+
|
|
170
|
+
**Improvements made this time:**
|
|
171
|
+
- Added `kkb status` to show raw files statistics โ
|
|
172
|
+
- Added `kkb compile` progress feedback โ
|
|
173
|
+
|
|
174
|
+
---
|
|
175
|
+
|
|
176
|
+
## 8. Concurrency Safety ๐งต
|
|
177
|
+
|
|
178
|
+
**Definition:** Access to shared resources across multiple threads/processes must be safe.
|
|
179
|
+
|
|
180
|
+
**Must consider:**
|
|
181
|
+
- [ ] File read/write conflicts
|
|
182
|
+
- [ ] Database transaction isolation level
|
|
183
|
+
- [ ] Locking for shared in-memory state
|
|
184
|
+
- [ ] Race conditions
|
|
185
|
+
|
|
186
|
+
**Test template:**
|
|
187
|
+
```typescript
|
|
188
|
+
it('should handle concurrent writes', async () => {
|
|
189
|
+
await Promise.all([
|
|
190
|
+
operation(data1),
|
|
191
|
+
operation(data2),
|
|
192
|
+
operation(data3)
|
|
193
|
+
])
|
|
194
|
+
|
|
195
|
+
// Verify final state consistency
|
|
196
|
+
const state = await getState()
|
|
197
|
+
expect(state).toBeValid()
|
|
198
|
+
})
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
---
|
|
202
|
+
|
|
203
|
+
## Mandatory Check Process
|
|
204
|
+
|
|
205
|
+
During the **Test Design Review** phase of each Story, the following must be answered:
|
|
206
|
+
|
|
207
|
+
```markdown
|
|
208
|
+
### Engineering Common Sense Checklist
|
|
209
|
+
- [ ] **Idempotency**: Can it be run repeatedly? Are there tests?
|
|
210
|
+
- [ ] **Cross-module contract**: Are IDs/formats/algorithms consistent?
|
|
211
|
+
- [ ] **Data flow**: Is the producer โ consumer pipeline complete?
|
|
212
|
+
- [ ] **Atomicity**: Does partial failure trigger a rollback?
|
|
213
|
+
- [ ] **Input validation**: Are all inputs validated?
|
|
214
|
+
- [ ] **Graceful degradation**: What happens when a dependency fails?
|
|
215
|
+
- [ ] **Observability**: Can the user see progress/status?
|
|
216
|
+
- [ ] **Concurrency safety**: Is multi-threaded access safe?
|
|
217
|
+
|
|
218
|
+
**If any item is not satisfied, tests/design must be added before writing implementation code.**
|
|
219
|
+
```
|
|
220
|
+
|
|
221
|
+
---
|
|
222
|
+
|
|
223
|
+
## Automated Protection
|
|
224
|
+
|
|
225
|
+
### Sentinel Patrol Rules
|
|
226
|
+
```yaml
|
|
227
|
+
# .github/roll-sentinel-config.yml
|
|
228
|
+
checks:
|
|
229
|
+
idempotency:
|
|
230
|
+
- pattern: "ingest|import|sync"
|
|
231
|
+
require_test: "idempotency"
|
|
232
|
+
|
|
233
|
+
cross_module_contract:
|
|
234
|
+
- files: ["src/*/index.ts"]
|
|
235
|
+
check: "shared_id_generation"
|
|
236
|
+
|
|
237
|
+
data_flow:
|
|
238
|
+
- require_integration_test: true
|
|
239
|
+
```
|
|
240
|
+
|
|
241
|
+
### Pre-Commit Hook
|
|
242
|
+
```bash
|
|
243
|
+
#!/bin/bash
|
|
244
|
+
# .git/hooks/pre-commit
|
|
245
|
+
echo "๐ Checking engineering common sense..."
|
|
246
|
+
|
|
247
|
+
# Check for idempotency tests
|
|
248
|
+
if git diff --cached --name-only | grep -q "ingest\|import\|sync"; then
|
|
249
|
+
if ! grep -r "idempotency\|repeated run\|multiple times" tests/ 2>/dev/null; then
|
|
250
|
+
echo "โ Missing idempotency tests!"
|
|
251
|
+
exit 1
|
|
252
|
+
fi
|
|
253
|
+
fi
|
|
254
|
+
|
|
255
|
+
echo "โ
Basic checks passed"
|
|
256
|
+
```
|