@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.
- package/README.md +10 -11
- package/bin/roll +33 -84
- package/conventions/global/AGENTS.md +51 -0
- package/conventions/global/CLAUDE.md +0 -20
- package/conventions/global/GEMINI.md +0 -19
- package/conventions/global/project_rules.md +0 -19
- package/package.json +2 -2
- package/skills/roll-.changelog/SKILL.md +2 -0
- package/skills/roll-.qa/SKILL.md +1 -0
- package/skills/roll-.review/SKILL.md +2 -0
- package/skills/roll-debug/SKILL.md +253 -148
- package/skills/roll-debug/injectable-bb.js +263 -0
- package/skills/roll-design/ENGINEERING_CHECKLIST.md +1 -1
- package/skills/roll-design/SKILL.md +2 -0
- package/skills/roll-doctor/SKILL.md +168 -0
- package/skills/roll-jot/SKILL.md +2 -0
- package/skills/roll-notes/SKILL.md +13 -3
- package/skills/roll-release/SKILL.md +2 -0
- package/skills/roll-research/SKILL.md +2 -0
- package/skills/roll-sentinel/SKILL.md +1 -0
- package/skills/roll-spar/SKILL.md +2 -0
|
@@ -1,16 +1,20 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: roll-debug
|
|
3
3
|
license: MIT
|
|
4
|
-
|
|
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
|
-
|
|
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: **Mount → Collect → Analyze → Unmount**.
|
|
10
11
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
- **
|
|
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 +
|
|
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
|
-
#
|
|
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
|
-
##
|
|
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.
|
|
89
|
-
│ ├──
|
|
90
|
-
│ ├──
|
|
91
|
-
│ └──
|
|
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.
|
|
115
|
-
│ ├──
|
|
116
|
-
│ ├──
|
|
117
|
-
│
|
|
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-
|
|
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
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
├──
|
|
135
|
-
├──
|
|
136
|
-
|
|
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 |
|
|
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:
|
|
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
|
-
|
|
174
|
-
|
|
175
|
-
|
|
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
|
-
|
|
183
|
-
|
|
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
|
|
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:
|
|
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
|
-
|
|
|
230
|
-
|
|
|
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
|
-
###
|
|
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 | {
|
|
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
|
-
###
|
|
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
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
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
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
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
|
-
|
|
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
|
-
###
|
|
452
|
+
### Mounted BB Mode
|
|
357
453
|
|
|
358
454
|
```json
|
|
359
455
|
{
|
|
360
|
-
"mode": "
|
|
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
|
-
"
|
|
365
|
-
|
|
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, "
|
|
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 |
|
|
413
|
-
|
|
414
|
-
|
|
|
415
|
-
|
|
|
416
|
-
|
|
|
417
|
-
|
|
|
418
|
-
|
|
|
419
|
-
|
|
|
420
|
-
|
|
|
421
|
-
|
|
|
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
|
|