@seanyao/roll 2026.503.7 → 2026.505.1

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.
@@ -1,16 +1,20 @@
1
1
  ---
2
2
  name: roll-debug
3
3
  license: MIT
4
- 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
+ allowed-tools: "Read, Edit, Write, Bash, Agent"
5
+ description: Universal web debugger. Mounts a Black Box (BB) diagnostic probe on any page, collects rich diagnostics, analyzes root causes, and suggests fixes. Cleans up after itself.
5
6
  ---
6
7
 
7
8
  # Roll Debug
8
9
 
9
- Universal web debugging tool that combines diagnostic collection and analysis into a single workflow: **Diagnose → Analyze → Suggest Fix**.
10
+ Web debugging tool that treats the **Black Box (BB) as a diagnostic probe** — mounted when needed, unmounted when done. Combines diagnostic collection and analysis into a single workflow: **MountCollect → Analyze → Unmount**.
10
11
 
11
- Two collection modes:
12
- - **Native BB Mode**: Page has Black Box integrated; click button to collect rich diagnostic data
13
- - **Universal Diagnostic Mode**: Page has no BB; use Playwright to directly collect console/network/DOM/screenshot data
12
+ ## Philosophy
13
+
14
+ - BB is a **diagnostic probe**, not a product feature. Pages do not need to integrate BB natively.
15
+ - For any web diagnosis, **mount BB first** (unless already present).
16
+ - The entire lifecycle is **explicit and visible**: you see when BB mounts, when it collects, and when it unmounts.
17
+ - A visible **BB button** appears on the page during diagnosis so you always know the probe is active.
14
18
 
15
19
  ## When to Use
16
20
 
@@ -31,15 +35,18 @@ Two collection modes:
31
35
  ## Quick Start
32
36
 
33
37
  ```bash
34
- # Full workflow: collect + analyze + suggest fix (recommended)
38
+ # Full workflow: mount + collect + analyze + unmount (recommended)
35
39
  $roll-debug https://example.com/page
36
40
 
37
41
  # Collect data only, skip analysis
38
42
  $roll-debug https://example.com/page --no-analyze
39
43
 
40
- # Force universal diagnostic mode (no BB)
44
+ # Skip BB mount, use built-in universal collector
41
45
  $roll-debug https://example.com/page --universal
42
46
 
47
+ # Use a custom BB SDK instead of the built-in stub
48
+ $roll-debug https://example.com/page --bb-sdk-url https://cdn.example.com/bb.js
49
+
43
50
  # Collect + analyze + auto-fix
44
51
  $roll-debug https://example.com/page --fix
45
52
 
@@ -51,44 +58,21 @@ $roll-debug https://site.com/page1,https://site.com/page2
51
58
  $roll-debug --file urls.txt
52
59
  ```
53
60
 
54
- ## Two Collection Modes
55
-
56
- ### Mode 1: Native BB (Page has Black Box integrated)
57
-
58
- ```
59
- Page with BB → Playwright clicks BB button → Download diagnostic JSON
60
- ```
61
-
62
- Requirements:
63
- - Page has `[data-testid="bb-toggle"]` button
64
- - Or exposes `window.__BB_DATA__`
65
- - Or stores data in `localStorage.bb_diagnostic`
66
-
67
- ### Mode 2: Universal Diagnostic (No BB required)
68
-
69
- ```
70
- Any page → Playwright injects collector → Gather console/network/DOM/screenshot
71
- ```
72
-
73
- Collects:
74
- - Console logs (error/warn/info)
75
- - Network requests (failed XHR/fetch, slow requests)
76
- - DOM state (key elements visibility, HTML length)
77
- - Screenshot (full page + viewport)
78
- - Performance metrics (load time, FCP, LCP, render blocking)
79
- - JavaScript errors with stack traces
80
-
81
- ## Full Workflow
61
+ ## BB Probe Lifecycle
82
62
 
83
63
  ```
84
64
  User: "Debug the page"
85
65
 
86
66
 
87
67
  ┌─────────────────────────────────────┐
88
- │ 1. Auto-detect collection mode
89
- │ ├── Try BB button found?
90
- │ ├── Try window.__BB_DATA__?
91
- │ └── Fallback to Universal
68
+ │ 1. Mount BB Probe
69
+ │ ├── Check: page already has BB?
70
+ ├── Yes → reuse existing
71
+ └── No → inject BB
72
+ │ │ ├── Built-in stub (default)
73
+ │ │ └── Custom SDK (--bb-sdk-url)
74
+ │ ├── Wait for initialization │
75
+ │ └── BB button appears on page │
92
76
  └──────────────────┬──────────────────┘
93
77
 
94
78
 
@@ -97,6 +81,7 @@ User: "Debug the page"
97
81
  │ ├── Console logs │
98
82
  │ ├── Network requests │
99
83
  │ ├── DOM state │
84
+ │ ├── Performance metrics │
100
85
  │ └── Screenshot │
101
86
  └──────────────────┬──────────────────┘
102
87
 
@@ -111,40 +96,82 @@ User: "Debug the page"
111
96
 
112
97
 
113
98
  ┌─────────────────────────────────────┐
114
- │ 4. Suggest (or apply) fix
115
- │ ├── Actionable fix suggestions
116
- │ ├── Auto-fix via TCR (--fix)
117
- └── Deploy & verify
118
- └─────────────────────────────────────┘
99
+ │ 4. Unmount BB Probe
100
+ │ ├── Restore console/fetch/XHR
101
+ │ ├── Remove BB button from DOM
102
+ ├── Delete window.__BB_DATA__
103
+ │ └── Page state fully restored │
104
+ └──────────────────┬──────────────────┘
105
+
106
+
107
+ Fix suggestions (or --fix to apply)
119
108
  ```
120
109
 
110
+ ## Collection Modes
111
+
112
+ ### Mode 1: Mounted BB (Default)
113
+
114
+ BB probe is mounted on the page — either reused from an existing BB or freshly injected.
115
+
116
+ **Visual indicator**: a red circular **BB** button appears at the bottom-right of the page.
117
+
118
+ **Data collected via BB interface**:
119
+ - Console logs (error/warn/info)
120
+ - Network requests (failed XHR/fetch, slow requests)
121
+ - DOM state (key elements visibility, HTML length)
122
+ - Performance metrics (load time, FCP, LCP)
123
+ - JavaScript errors with stack traces
124
+
125
+ **BB Sources**:
126
+
127
+ | Source | When Used | Capability |
128
+ |--------|-----------|------------|
129
+ | Existing native BB | Page already has `[data-testid="bb-toggle"]` or `window.__BB_DATA__` | Full app-specific metrics (contentState, audioState, etc.) |
130
+ | Built-in stub | Default when no BB present | Generic metrics (console, network, DOM, performance, errors) |
131
+ | Custom SDK | `--bb-sdk-url` provided | Determined by the SDK implementation |
132
+
133
+ ### Mode 2: Universal Diagnostic (No BB)
134
+
135
+ When `--universal` is passed, skip BB mount entirely. Use Playwright's built-in event listeners directly.
136
+
137
+ ```bash
138
+ $roll-debug https://example.com/page --universal
139
+ ```
140
+
141
+ Useful when:
142
+ - You explicitly do not want to modify the page state
143
+ - The page has strict CSP that blocks script injection
144
+ - You need a quick check without probe overhead
145
+
121
146
  ## Usage Examples
122
147
 
123
- ### Example 1: Full auto-detect + analyze (default)
148
+ ### Example 1: Full auto-mount + analyze (default)
124
149
 
125
150
  ```bash
126
151
  $roll-debug https://yyy.up.railway.app/story/cars/chapter/1
127
152
 
128
- Detecting diagnostic capability...
129
- ├── BB found: [data-testid="bb-toggle"]
130
- └── Using: Native BB mode
131
-
132
- Collecting data...
133
- ├── Console: 3 errors, 5 warnings
134
- ├── Network: 2 failed requests
135
- ├── DOM: #app rendered, .content empty
136
- └── Screenshot: saved to /tmp/bb-screenshot.png
153
+ 🔍 Diagnosing https://yyy.up.railway.app/story/cars/chapter/1
154
+ 📡 Mounting BB probe...
155
+ ├── Source: built-in stub
156
+ └── Status: ready (320ms)
157
+ └── BB button visible on page ✓
158
+ 📊 Collecting data via BB...
159
+ ├── Console: 3 errors, 5 warnings
160
+ ├── Network: 2 failed requests
161
+ ├── DOM: #app rendered, .content empty
162
+ └── Screenshot: saved to /tmp/bb-screenshot.png
163
+ 🔬 Analyzing...
164
+ 🧹 Unmounting BB probe... done
165
+ └── Page state restored ✓
137
166
 
138
167
  Report: /tmp/bb-report.json
139
168
 
140
- Analyzing...
141
-
142
169
  ## Diagnostic Analysis Report
143
170
 
144
171
  ### Basic Info
145
172
  | Field | Value |
146
173
  |-------|-------|
147
- | Diagnostic Mode | native-bb |
174
+ | Diagnostic Mode | mounted-bb (stub) |
148
175
  | Page URL | https://yyy.up.railway.app/story/cars/chapter/1 |
149
176
 
150
177
  ### Key Findings
@@ -165,58 +192,58 @@ Modify Player.tsx line 45, change useEffect dependency
165
192
  from `[chapter?.id]` to `[chapter?.number]`
166
193
  ```
167
194
 
168
- ### Example 2: Universal mode (no BB)
195
+ ### Example 2: Reuse existing native BB
196
+
197
+ ```bash
198
+ $roll-debug https://example.com/page
199
+
200
+ 🔍 Diagnosing https://example.com/page
201
+ 📡 Mounting BB probe...
202
+ ├── Native BB detected
203
+ └── Reusing existing probe
204
+ 📊 Collecting data via BB...
205
+ ├── Console: 0 errors
206
+ ├── Network: 0 failed
207
+ └── DOM: fully rendered
208
+ 🔬 Analyzing...
209
+ 🧹 Unmounting BB probe... skipped
210
+ └── Native BB left intact
211
+
212
+ No issues found. Page is healthy.
213
+ ```
214
+
215
+ ### Example 3: Universal mode (no BB mount)
169
216
 
170
217
  ```bash
171
218
  $roll-debug https://example.com --universal
172
219
 
173
- Universal diagnostic mode (no BB required)
174
-
175
- Collected:
176
- ├── Console Errors: 2
177
- │ ├── TypeError: Cannot read property 'id' of undefined
178
- │ │ at Player.tsx:45
179
- │ └── ReferenceError: AudioContext is not defined
180
- ├── Failed Network: 1
181
- │ └── GET https://api.example.com/data 404
182
- ├── DOM State:
183
- │ ├── body.innerHTML length: 2340
184
- │ ├── #root: rendered
185
- │ ├── .loading: still visible (timeout?)
186
- │ └── .error-message: visible
187
- ├── Performance:
188
- │ ├── DOMContentLoaded: 1.2s
189
- │ ├── First Contentful Paint: 2.3s
190
- │ └── Largest Contentful Paint: 4.5s
191
- └── Screenshot: /tmp/bb-screenshot.png
220
+ 🔍 Diagnosing https://example.com (universal mode)
221
+ 📡 BB mount skipped (--universal)
222
+ 📊 Collecting data via Playwright events...
223
+ ├── Console Errors: 2
224
+ │ ├── TypeError: Cannot read property 'id' of undefined
225
+ │ │ at Player.tsx:45
226
+ │ └── ReferenceError: AudioContext is not defined
227
+ ├── Failed Network: 1
228
+ │ └── GET https://api.example.com/data 404
229
+ └── Screenshot: /tmp/bb-screenshot.png
230
+ 🔬 Analyzing...
192
231
 
193
232
  Report: /tmp/bb-report.json
194
233
 
195
- Analyzing...
196
-
197
234
  ### Key Findings
198
235
  | Metric | Value | Status |
199
236
  |--------|-------|--------|
200
237
  | Console Errors | 2 | Critical |
201
238
  | Network Failed | 1 | Critical |
202
- | DOM Rendering | Partial | Warning |
203
- | Load Time (LCP) | 4.5s | Slow |
204
-
205
- ### Diagnosis Conclusion
206
- API endpoint returning 404 causes content not to load.
207
- AudioContext undefined suggests missing polyfill or browser incompatibility.
208
-
209
- ### Suggested Fix
210
- 1. Fix API route for /data endpoint (404)
211
- 2. Add AudioContext polyfill or guard with `typeof AudioContext !== 'undefined'`
212
239
  ```
213
240
 
214
- ### Example 3: Analyze existing report file
241
+ ### Example 4: Analyze existing report file
215
242
 
216
243
  ```bash
217
244
  $roll-debug --report /tmp/bb-report.json
218
245
 
219
- Reading report: /tmp/bb-report.json (mode: universal)
246
+ Reading report: /tmp/bb-report.json (mode: mounted-bb)
220
247
 
221
248
  ### Key Findings
222
249
  ...
@@ -226,11 +253,13 @@ Reading report: /tmp/bb-report.json (mode: universal)
226
253
 
227
254
  | Format | Source | Description |
228
255
  |--------|--------|-------------|
229
- | Native BB | Page with Black Box | `window.__BB_DATA__` or `localStorage.bb_diagnostic` |
230
- | Universal | Playwright collector | Injected collector data |
256
+ | Mounted BB (stub) | Injected built-in stub | `window.__BB_DATA__` via injectable-bb.js |
257
+ | Mounted BB (native) | Page with existing Black Box | `window.__BB_DATA__` or `localStorage.bb_diagnostic` |
258
+ | Mounted BB (custom) | Custom SDK via `--bb-sdk-url` | Determined by SDK |
259
+ | Universal | Playwright native events | Direct event listener data |
231
260
  | Legacy | Old diagnostic files | Backward compatible |
232
261
 
233
- ### Native BB Mode Fields
262
+ ### Mounted BB Mode Fields
234
263
 
235
264
  ```javascript
236
265
  const bbData = report.diagnostic.bbData;
@@ -240,6 +269,11 @@ bbData.audioState?.src
240
269
  bbData.audioState?.error
241
270
  bbData.hasAudio
242
271
  bbData.errors
272
+ bbData.console.errors
273
+ bbData.console.warnings
274
+ bbData.network.failed
275
+ bbData.dom.keyElements
276
+ bbData.performance.loadComplete
243
277
  ```
244
278
 
245
279
  ### Universal Mode Fields
@@ -255,7 +289,6 @@ d.dom['#root']
255
289
  d.dom.htmlLength
256
290
  d.performance.loadComplete
257
291
  d.performance.domContentLoaded
258
- d.errors
259
292
  ```
260
293
 
261
294
  ## Analysis Report Template
@@ -266,7 +299,8 @@ d.errors
266
299
  ### Basic Info
267
300
  | Field | Value |
268
301
  |-------|-------|
269
- | Diagnostic Mode | {native-bb / universal} |
302
+ | Diagnostic Mode | {mounted-bb / universal} |
303
+ | BB Source | {native / stub / custom-sdk} |
270
304
  | Page URL | {url} |
271
305
  | Collected At | {timestamp} |
272
306
 
@@ -309,62 +343,123 @@ d.errors
309
343
 
310
344
  ## Implementation Notes
311
345
 
312
- ### Universal Mode Injection
313
-
314
- When page has no BB, inject a lightweight collector via `page.evaluate()`:
346
+ ### BB Mount Flow (Playwright)
315
347
 
316
348
  ```javascript
317
- window.__ROLL_DEBUG_COLLECTOR__ = {
318
- console: [],
319
- network: [],
320
- errors: [],
321
-
322
- init() {
323
- // Hook console methods
324
- ['error', 'warn', 'log', 'info'].forEach(method => {
325
- const original = console[method];
326
- console[method] = (...args) => {
327
- this.console.push({method, args, timestamp: Date.now()});
328
- original.apply(console, args);
329
- };
330
- });
331
-
332
- // Hook fetch/XHR for network interception
333
-
334
- // Listen for JS errors
335
- window.addEventListener('error', e => {
336
- this.errors.push({message: e.message, stack: e.error?.stack});
337
- });
338
- },
349
+ // Pseudocode for AI agent execution
350
+ async function diagnose(page, url, args) {
351
+ log(`🔍 Diagnosing ${url}`);
352
+
353
+ // Step 1: Mount
354
+ const bbState = await mountBB(page, args);
355
+ log(`📡 Mounting BB probe...`);
356
+ log(` ├── Source: ${bbState.source}`); // native / stub / custom
357
+ log(` └── Status: ${bbState.ready ? 'ready' : 'failed'}`);
358
+
359
+ if (bbState.ready && bbState.source !== 'native') {
360
+ log(` └── BB button visible on page ✓`);
361
+ }
362
+
363
+ // Step 2: Collect
364
+ log(`📊 Collecting data via BB...`);
365
+ const data = await collectViaBB(page);
366
+
367
+ // Step 3: Analyze
368
+ log(`🔬 Analyzing...`);
369
+ const analysis = await analyze(data);
370
+
371
+ // Step 4: Unmount (unless native BB)
372
+ if (bbState.source !== 'native') {
373
+ log(`🧹 Unmounting BB probe...`);
374
+ const ok = await page.evaluate(() => window.__BB_UNMOUNT__?.());
375
+ log(` └── ${ok ? 'done' : 'failed'}`);
376
+ log(` └── Page state restored ✓`);
377
+ } else {
378
+ log(`🧹 Unmounting BB probe... skipped`);
379
+ log(` └── Native BB left intact`);
380
+ }
381
+
382
+ return analysis;
383
+ }
384
+
385
+ async function mountBB(page, args) {
386
+ // Check for existing BB
387
+ const hasNative = await page.evaluate(() =>
388
+ !!document.querySelector('[data-testid="bb-toggle"]') || !!window.__BB_DATA__
389
+ );
390
+ if (hasNative) {
391
+ return { source: 'native', ready: true };
392
+ }
393
+
394
+ if (args.universal) {
395
+ return { source: 'universal', ready: false };
396
+ }
339
397
 
340
- getData() {
341
- return {
342
- console: this.console,
343
- network: this.network,
344
- errors: this.errors,
345
- dom: this.captureDOM(),
346
- performance: this.capturePerformance()
347
- };
398
+ // Inject BB
399
+ try {
400
+ if (args.bbSdkUrl) {
401
+ await page.addScriptTag({ url: args.bbSdkUrl });
402
+ } else {
403
+ const stubPath = path.join(__dirname, 'injectable-bb.js');
404
+ await page.addScriptTag({ path: stubPath });
405
+ }
406
+
407
+ // Poll for readiness
408
+ const ready = await poll(
409
+ () => page.evaluate(() => !!window.__BB_DATA__),
410
+ { timeout: 5000, interval: 200 }
411
+ );
412
+
413
+ return { source: args.bbSdkUrl ? 'custom' : 'stub', ready };
414
+ } catch (e) {
415
+ return { source: 'stub', ready: false, error: e.message };
348
416
  }
349
- };
417
+ }
350
418
  ```
351
419
 
352
- The injected collector only exists in the Playwright browser context — no cleanup needed.
420
+ ### Built-in Stub (`injectable-bb.js`)
421
+
422
+ The stub is injected via `page.addScriptTag({ path })` when no native BB exists.
423
+
424
+ **Capabilities**:
425
+ - Hooks `console.*` with internal error firewall (stub bugs never leak to page)
426
+ - Hooks `fetch` and `XMLHttpRequest` transparently — original behavior fully preserved
427
+ - Listens for `error` and `unhandledrejection`
428
+ - Captures Performance Navigation Timing + FCP + LCP
429
+ - Captures DOM state (title, HTML length, key element visibility)
430
+ - Renders a visible **BB** button on the page
431
+
432
+ **Cleanup**:
433
+ - `window.__BB_UNMOUNT__()` restores all modified globals to their original references
434
+ - Removes the BB button from DOM
435
+ - Deletes `window.__BB_DATA__` and `window.__BB_UNMOUNT__`
436
+
437
+ ### Universal Mode (No BB)
438
+
439
+ When `--universal` is used, collect via Playwright native events:
440
+
441
+ ```javascript
442
+ page.on('console', msg => ...);
443
+ page.on('requestfailed', req => ...);
444
+ page.on('response', res => ...);
445
+ page.on('pageerror', err => ...);
446
+ ```
447
+
448
+ No page state is modified.
353
449
 
354
450
  ## Data Output Formats
355
451
 
356
- ### Native BB Mode
452
+ ### Mounted BB Mode
357
453
 
358
454
  ```json
359
455
  {
360
- "mode": "native-bb",
456
+ "mode": "mounted-bb",
457
+ "bbSource": "stub",
361
458
  "timestamp": "2024-01-15T10:30:00Z",
362
459
  "url": "https://example.com/page",
363
460
  "bbData": {},
364
- "collected": {
365
- "console": [],
366
- "network": []
367
- }
461
+ "mountedAt": 1705315800000,
462
+ "unmountedAt": 1705315805000
368
463
  }
369
464
  ```
370
465
 
@@ -389,7 +484,7 @@ The injected collector only exists in the Playwright browser context — no clea
389
484
  "title": "Page Title",
390
485
  "htmlLength": 2340,
391
486
  "keyElements": {
392
- "#root": {"exists": true, "visible": true, "children": 5},
487
+ "#root": {"exists": true, "visible": true, "text": "..."},
393
488
  ".error": {"exists": false}
394
489
  }
395
490
  },
@@ -409,16 +504,26 @@ The injected collector only exists in the Playwright browser context — no clea
409
504
 
410
505
  ## Capability Comparison
411
506
 
412
- | Feature | Native BB Mode | Universal Mode |
413
- |---------|---------------|----------------|
414
- | Requires BB integration | Yes | No |
415
- | Console logs | Yes | Yes |
416
- | Network data | Yes | Yes |
417
- | DOM state | Detailed | Key elements |
418
- | App-specific metrics | Yes | No |
419
- | Screenshot | Yes | Yes |
420
- | Performance metrics | Yes | Yes |
421
- | Works on any site | No | Yes |
507
+ | Feature | Mounted BB (stub) | Mounted BB (native) | Universal |
508
+ |---------|-------------------|---------------------|-----------|
509
+ | Page modification | Yes (mount/unmount) | No (already there) | No |
510
+ | Visible BB button | Yes | If native has one | No |
511
+ | Console logs | Yes | Yes | Yes |
512
+ | Network data | Yes | Yes | Yes |
513
+ | DOM state | Detailed | Detailed | Key elements |
514
+ | App-specific metrics | No | Yes | No |
515
+ | Screenshot | Yes | Yes | Yes |
516
+ | Performance metrics | Yes | Yes | Yes |
517
+ | Works offline | Yes | Yes | Yes |
518
+ | Cleanup on exit | Yes (full restore) | N/A | N/A |
519
+
520
+ ## Safety & Cleanup Guarantees
521
+
522
+ 1. **Stub errors are firewalled** — every hook wraps its internal logic in try/catch. A bug in the stub cannot crash the page.
523
+ 2. **Original behavior preserved** — fetch/XHR wrappers return the exact same values/throw the exact same errors as the originals.
524
+ 3. **Full unmount** — `__BB_UNMOUNT__()` restores console, fetch, XHR, removes listeners, removes DOM element, and deletes globals.
525
+ 4. **Native BB untouched** — if a page already has BB, it is reused but never unmounted.
526
+ 5. **CSP fallback** — if script injection fails (CSP), automatically falls back to Universal mode.
422
527
 
423
528
  ## Integration with Build Skills
424
529