@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.
Files changed (50) hide show
  1. package/README.md +201 -0
  2. package/bin/roll +1375 -0
  3. package/conventions/config.yaml +15 -0
  4. package/conventions/global/.cursor-rules +31 -0
  5. package/conventions/global/AGENTS.md +100 -0
  6. package/conventions/global/CLAUDE.md +32 -0
  7. package/conventions/global/GEMINI.md +28 -0
  8. package/conventions/templates/backend-service/.cursor-rules +17 -0
  9. package/conventions/templates/backend-service/AGENTS.md +88 -0
  10. package/conventions/templates/backend-service/CLAUDE.md +18 -0
  11. package/conventions/templates/backend-service/GEMINI.md +16 -0
  12. package/conventions/templates/cli/.cursor-rules +17 -0
  13. package/conventions/templates/cli/AGENTS.md +66 -0
  14. package/conventions/templates/cli/CLAUDE.md +18 -0
  15. package/conventions/templates/cli/GEMINI.md +16 -0
  16. package/conventions/templates/frontend-only/.cursor-rules +16 -0
  17. package/conventions/templates/frontend-only/AGENTS.md +71 -0
  18. package/conventions/templates/frontend-only/CLAUDE.md +16 -0
  19. package/conventions/templates/frontend-only/GEMINI.md +14 -0
  20. package/conventions/templates/fullstack/.cursor-rules +17 -0
  21. package/conventions/templates/fullstack/AGENTS.md +87 -0
  22. package/conventions/templates/fullstack/CLAUDE.md +17 -0
  23. package/conventions/templates/fullstack/GEMINI.md +15 -0
  24. package/package.json +33 -0
  25. package/skills/roll-.changelog/SKILL.md +79 -0
  26. package/skills/roll-.clarify/SKILL.md +59 -0
  27. package/skills/roll-.echo/SKILL.md +113 -0
  28. package/skills/roll-.qa/SKILL.md +204 -0
  29. package/skills/roll-.review/SKILL.md +105 -0
  30. package/skills/roll-build/SKILL.md +559 -0
  31. package/skills/roll-debug/SKILL.md +428 -0
  32. package/skills/roll-design/ENGINEERING_CHECKLIST.md +256 -0
  33. package/skills/roll-design/SKILL.md +276 -0
  34. package/skills/roll-fix/SKILL.md +442 -0
  35. package/skills/roll-jot/SKILL.md +50 -0
  36. package/skills/roll-research/SKILL.md +307 -0
  37. package/skills/roll-research/references/schema.json +162 -0
  38. package/skills/roll-research/scripts/md_to_pdf.py +289 -0
  39. package/skills/roll-sentinel/SKILL.md +355 -0
  40. package/skills/roll-spar/SKILL.md +287 -0
  41. package/template/.env.example +47 -0
  42. package/template/.github/workflows/ci.yml +32 -0
  43. package/template/.github/workflows/sentinel.yml +26 -0
  44. package/template/AGENTS.md +80 -0
  45. package/template/BACKLOG.md +42 -0
  46. package/template/package.json +43 -0
  47. package/tools/roll-fetch/SKILL.md +182 -0
  48. package/tools/roll-fetch/package.json +15 -0
  49. package/tools/roll-fetch/smart-web-fetch.js +558 -0
  50. 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
+ ```