@browserbridge/bbx 1.0.0 → 1.1.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 +6 -4
- package/package.json +53 -53
- package/packages/agent-client/src/cli-helpers.js +43 -5
- package/packages/agent-client/src/cli.js +176 -171
- package/packages/agent-client/src/client.js +66 -21
- package/packages/agent-client/src/command-registry.js +104 -69
- package/packages/agent-client/src/detect.js +162 -54
- package/packages/agent-client/src/install.js +34 -28
- package/packages/agent-client/src/mcp-config.js +40 -40
- package/packages/agent-client/src/runtime.js +41 -20
- package/packages/agent-client/src/setup-status.js +23 -30
- package/packages/mcp-server/src/bin.js +57 -5
- package/packages/mcp-server/src/handlers.js +573 -256
- package/packages/mcp-server/src/server.js +568 -257
- package/packages/native-host/bin/bridge-daemon.js +39 -6
- package/packages/native-host/bin/install-manifest.js +26 -4
- package/packages/native-host/bin/postinstall.js +4 -2
- package/packages/native-host/src/config.js +142 -13
- package/packages/native-host/src/daemon-process.js +396 -0
- package/packages/native-host/src/daemon.js +350 -150
- package/packages/native-host/src/framing.js +131 -11
- package/packages/native-host/src/install-manifest.js +194 -29
- package/packages/native-host/src/native-host.js +154 -102
- package/packages/protocol/src/budget.js +3 -7
- package/packages/protocol/src/capabilities.js +6 -3
- package/packages/protocol/src/defaults.js +1 -0
- package/packages/protocol/src/errors.js +15 -11
- package/packages/protocol/src/payload-cost.js +19 -6
- package/packages/protocol/src/protocol.js +242 -73
- package/packages/protocol/src/registry.js +311 -45
- package/packages/protocol/src/summary.js +260 -109
- package/packages/protocol/src/types.js +29 -4
- package/skills/browser-bridge/SKILL.md +3 -2
- package/skills/browser-bridge/agents/openai.yaml +3 -3
- package/skills/browser-bridge/references/interaction.md +34 -11
- package/skills/browser-bridge/references/patch-workflow.md +3 -0
- package/skills/browser-bridge/references/protocol.md +127 -71
- package/skills/browser-bridge/references/tailwind.md +12 -11
- package/skills/browser-bridge/references/token-efficiency.md +23 -22
- package/skills/browser-bridge/references/ui-workflows.md +8 -0
- package/CHANGELOG.md +0 -55
- package/assets/banner.jpg +0 -0
- package/assets/logo.png +0 -0
- package/assets/logo.svg +0 -65
- package/docs/api-reference.md +0 -157
- package/docs/cli-guide.md +0 -128
- package/docs/index.md +0 -25
- package/docs/manual-setup.md +0 -140
- package/docs/mcp-vs-cli.md +0 -258
- package/docs/publishing.md +0 -114
- package/docs/quickstart.md +0 -104
- package/docs/troubleshooting.md +0 -59
- package/docs/usage-scenarios.md +0 -136
- package/manifest.json +0 -52
- package/packages/extension/assets/icon-128.png +0 -0
- package/packages/extension/assets/icon-16.png +0 -0
- package/packages/extension/assets/icon-32.png +0 -0
- package/packages/extension/assets/icon-48.png +0 -0
- package/packages/extension/src/background-helpers.js +0 -459
- package/packages/extension/src/background-routing.js +0 -91
- package/packages/extension/src/background.js +0 -3227
- package/packages/extension/src/content-script-helpers.js +0 -281
- package/packages/extension/src/content-script.js +0 -1977
- package/packages/extension/src/debugger-coordinator.js +0 -188
- package/packages/extension/src/sidepanel-helpers.js +0 -102
- package/packages/extension/ui/offscreen.html +0 -6
- package/packages/extension/ui/offscreen.js +0 -61
- package/packages/extension/ui/popup.html +0 -35
- package/packages/extension/ui/popup.js +0 -279
- package/packages/extension/ui/sidepanel.html +0 -102
- package/packages/extension/ui/sidepanel.js +0 -1854
- package/packages/extension/ui/ui.css +0 -1159
|
@@ -7,7 +7,7 @@ export {};
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
* @typedef {'page.read' | 'page.evaluate' | 'dom.read' | 'styles.read' | 'layout.read' | 'viewport.control' | 'navigation.control' | 'screenshot.partial' | 'patch.dom' | 'patch.styles' | 'cdp.dom_snapshot' | 'cdp.box_model' | 'cdp.styles' | 'automation.input' | 'tabs.manage' | 'performance.read' | 'network.read'} Capability
|
|
10
|
+
* @typedef {'page.read' | 'page.evaluate' | 'dom.read' | 'styles.read' | 'layout.read' | 'viewport.control' | 'navigation.control' | 'screenshot.partial' | 'patch.dom' | 'patch.styles' | 'cdp.dom_snapshot' | 'cdp.box_model' | 'cdp.styles' | 'cdp.input' | 'automation.input' | 'tabs.manage' | 'performance.read' | 'network.read'} Capability
|
|
11
11
|
*/
|
|
12
12
|
|
|
13
13
|
/**
|
|
@@ -15,7 +15,7 @@ export {};
|
|
|
15
15
|
*/
|
|
16
16
|
|
|
17
17
|
/**
|
|
18
|
-
* @typedef {'access.request' | 'tabs.list' | 'tabs.create' | 'tabs.close' | 'skill.get_runtime_context' | 'setup.get_status' | 'setup.install' | 'page.get_state' | 'page.evaluate' | 'page.get_console' | 'page.wait_for_load_state' | 'page.get_storage' | 'page.get_text' | 'page.get_network' | 'navigation.navigate' | 'navigation.reload' | 'navigation.go_back' | 'navigation.go_forward' | 'dom.query' | 'dom.describe' | 'dom.get_text' | 'dom.get_attributes' | 'dom.wait_for' | 'dom.find_by_text' | 'dom.find_by_role' | 'dom.get_html' | 'dom.get_accessibility_tree' | 'layout.get_box_model' | 'layout.hit_test' | 'styles.get_computed' | 'styles.get_matched_rules' | 'viewport.scroll' | 'viewport.resize' | 'input.click' | 'input.focus' | 'input.type' | 'input.press_key' | 'input.set_checked' | 'input.select_option' | 'input.hover' | 'input.drag' | 'input.scroll_into_view' | 'screenshot.capture_region' | 'screenshot.capture_element' | 'screenshot.capture_full_page' | 'patch.apply_styles' | 'patch.apply_dom' | 'patch.list' | 'patch.rollback' | 'patch.commit_session_baseline' | 'cdp.get_document' | 'cdp.get_dom_snapshot' | 'cdp.get_box_model' | 'cdp.get_computed_styles_for_node' | 'performance.get_metrics' | 'log.tail' | 'health.ping'} BridgeMethod
|
|
18
|
+
* @typedef {'access.request' | 'tabs.list' | 'tabs.create' | 'tabs.close' | 'skill.get_runtime_context' | 'setup.get_status' | 'setup.install' | 'page.get_state' | 'page.evaluate' | 'page.get_console' | 'page.wait_for_load_state' | 'page.get_storage' | 'page.get_text' | 'page.get_network' | 'navigation.navigate' | 'navigation.reload' | 'navigation.go_back' | 'navigation.go_forward' | 'dom.query' | 'dom.describe' | 'dom.get_text' | 'dom.get_attributes' | 'dom.wait_for' | 'dom.find_by_text' | 'dom.find_by_role' | 'dom.get_html' | 'dom.get_accessibility_tree' | 'layout.get_box_model' | 'layout.hit_test' | 'styles.get_computed' | 'styles.get_matched_rules' | 'viewport.scroll' | 'viewport.resize' | 'input.click' | 'input.focus' | 'input.type' | 'input.press_key' | 'input.set_checked' | 'input.select_option' | 'input.hover' | 'input.drag' | 'input.scroll_into_view' | 'screenshot.capture_region' | 'screenshot.capture_element' | 'screenshot.capture_full_page' | 'patch.apply_styles' | 'patch.apply_dom' | 'patch.list' | 'patch.rollback' | 'patch.commit_session_baseline' | 'cdp.get_document' | 'cdp.get_dom_snapshot' | 'cdp.get_box_model' | 'cdp.get_computed_styles_for_node' | 'cdp.dispatch_key_event' | 'performance.get_metrics' | 'log.tail' | 'health.ping'} BridgeMethod
|
|
19
19
|
*/
|
|
20
20
|
|
|
21
21
|
/**
|
|
@@ -38,7 +38,7 @@ export {};
|
|
|
38
38
|
* budget_applied?: boolean,
|
|
39
39
|
* budget_truncated?: boolean,
|
|
40
40
|
* continuation_hint?: string | null,
|
|
41
|
-
|
|
41
|
+
* [key: string]: unknown
|
|
42
42
|
* }} BridgeMeta
|
|
43
43
|
*/
|
|
44
44
|
|
|
@@ -52,11 +52,20 @@ export {};
|
|
|
52
52
|
* }} BridgeRequest
|
|
53
53
|
*/
|
|
54
54
|
|
|
55
|
+
/**
|
|
56
|
+
* @typedef {{
|
|
57
|
+
* hint: string,
|
|
58
|
+
* retry?: boolean,
|
|
59
|
+
* retryAfterMs?: number
|
|
60
|
+
* }} BridgeRecovery
|
|
61
|
+
*/
|
|
62
|
+
|
|
55
63
|
/**
|
|
56
64
|
* @typedef {{
|
|
57
65
|
* code: ErrorCode,
|
|
58
66
|
* message: string,
|
|
59
|
-
* details: unknown
|
|
67
|
+
* details: unknown,
|
|
68
|
+
* recovery?: BridgeRecovery
|
|
60
69
|
* }} BridgeFailure
|
|
61
70
|
*/
|
|
62
71
|
|
|
@@ -187,6 +196,22 @@ export {};
|
|
|
187
196
|
* }} NormalizedInputAction
|
|
188
197
|
*/
|
|
189
198
|
|
|
199
|
+
/**
|
|
200
|
+
* @typedef {{
|
|
201
|
+
* key?: string,
|
|
202
|
+
* code?: string,
|
|
203
|
+
* modifiers?: string[] | number
|
|
204
|
+
* }} CdpDispatchKeyEventParams
|
|
205
|
+
*/
|
|
206
|
+
|
|
207
|
+
/**
|
|
208
|
+
* @typedef {{
|
|
209
|
+
* key: string,
|
|
210
|
+
* code: string,
|
|
211
|
+
* modifiers: string[] | number
|
|
212
|
+
* }} NormalizedCdpDispatchKeyEventParams
|
|
213
|
+
*/
|
|
214
|
+
|
|
190
215
|
/**
|
|
191
216
|
* @typedef {{
|
|
192
217
|
* target?: InputTarget,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
name: browser-bridge
|
|
3
|
-
description:
|
|
3
|
+
description: 'Token-efficient Chrome tab inspection, interaction, and patching via local bridge extension (CLI: bbx). Reads live DOM, styles, console, network, and storage from a real Chrome tab with lower token cost than screenshots.'
|
|
4
4
|
---
|
|
5
5
|
|
|
6
6
|
# Browser Bridge
|
|
@@ -69,6 +69,7 @@ bbx click <ref> [button] # click element
|
|
|
69
69
|
bbx focus <ref> # focus element
|
|
70
70
|
bbx type <ref> <text...> # type into element
|
|
71
71
|
bbx press-key <key> [ref] # send key event
|
|
72
|
+
bbx cdp-press-key --tab <id> Escape # CDP key event without foreground focus
|
|
72
73
|
bbx hover <ref> # hover over element
|
|
73
74
|
bbx call input.scroll_into_view '{"target":{"elementRef":"el_123"}}' # ensure target is visible
|
|
74
75
|
bbx patch-style <ref> prop=val... # apply style patch
|
|
@@ -202,7 +203,7 @@ bbx page-text 2000 # extract page content
|
|
|
202
203
|
| Find | `dom.find_by_text`, `dom.find_by_role`, `dom.wait_for`, `dom.get_accessibility_tree` |
|
|
203
204
|
| Page State | `page.get_console`, `page.get_storage`, `page.get_text`, `page.wait_for_load_state`, `page.evaluate` (debugger-backed) |
|
|
204
205
|
| Network | `page.get_network` |
|
|
205
|
-
| Interact | `input.click`, `input.type`, `input.focus`, `input.press_key`, `input.hover`, `input.drag`, `input.scroll_into_view`
|
|
206
|
+
| Interact | `input.click`, `input.type`, `input.focus`, `input.press_key`, `cdp.dispatch_key_event`, `input.hover`, `input.drag`, `input.scroll_into_view` |
|
|
206
207
|
| Tabs | `tabs.list` (preferred), `tabs.create` (avoid unless necessary), `tabs.close` |
|
|
207
208
|
| Patch | `patch.apply_styles`, `patch.apply_dom`, `patch.rollback` |
|
|
208
209
|
| Navigate | `navigation.navigate`, `viewport.scroll`, `viewport.resize` |
|
|
@@ -1,4 +1,4 @@
|
|
|
1
1
|
interface:
|
|
2
|
-
display_name:
|
|
3
|
-
short_description:
|
|
4
|
-
default_prompt:
|
|
2
|
+
display_name: 'Browser Bridge'
|
|
3
|
+
short_description: 'Token-efficient Chrome tab inspection, interaction, and patching via local bridge'
|
|
4
|
+
default_prompt: 'Use the browser-bridge skill for Chrome tab inspection, interaction, and patching. Start with `bbx status` to confirm connectivity. If ACCESS_DENIED, ask the user to click Enable in the extension popup/side panel, then retry. Default routing follows the active tab; use `--tab` only for a different tab. Prefer structured reads (`dom.query`, `styles.get_computed`) over screenshots. Batch independent reads with `bbx batch`. Use `bbx skill` for runtime presets.'
|
|
@@ -2,17 +2,18 @@
|
|
|
2
2
|
|
|
3
3
|
## Input Methods
|
|
4
4
|
|
|
5
|
-
| Method
|
|
6
|
-
|
|
7
|
-
| `input.click`
|
|
8
|
-
| `input.focus`
|
|
9
|
-
| `input.type`
|
|
10
|
-
| `input.press_key`
|
|
11
|
-
| `
|
|
12
|
-
| `input.
|
|
13
|
-
| `input.
|
|
14
|
-
| `input.
|
|
15
|
-
| `input.
|
|
5
|
+
| Method | CLI Shortcut | Purpose |
|
|
6
|
+
| ------------------------ | ------------------------------------- | ----------------------------------------------------------- |
|
|
7
|
+
| `input.click` | `click <ref> [button]` | DOM-level click |
|
|
8
|
+
| `input.focus` | `focus <ref>` | Focus an element |
|
|
9
|
+
| `input.type` | `type <ref> <text>` | Type into input/textarea/contenteditable |
|
|
10
|
+
| `input.press_key` | `press-key <key> [ref]` | Send keyboard key (Enter, Backspace, etc.) |
|
|
11
|
+
| `cdp.dispatch_key_event` | `cdp-press-key --tab <id> <key>` | CDP keyDown/keyUp without focusing the target tab |
|
|
12
|
+
| `input.set_checked` | `call input.set_checked '{...}'` | Toggle checkbox/radio |
|
|
13
|
+
| `input.select_option` | `call input.select_option '{...}'` | Select native `<select>` by value/label/index |
|
|
14
|
+
| `input.hover` | `hover <ref>` | Trigger CSS `:hover` state (mouseenter/mouseover/mousemove) |
|
|
15
|
+
| `input.drag` | `call input.drag '{...}'` | Full drag-and-drop event sequence |
|
|
16
|
+
| `input.scroll_into_view` | `call input.scroll_into_view '{...}'` | Ensure a target is visible before inspect/capture |
|
|
16
17
|
|
|
17
18
|
## Navigation
|
|
18
19
|
|
|
@@ -39,6 +40,7 @@ Scrolls the window or a specific scrollable element.
|
|
|
39
40
|
### Resize Viewport
|
|
40
41
|
|
|
41
42
|
Set device viewport dimensions (useful for responsive testing):
|
|
43
|
+
|
|
42
44
|
```bash
|
|
43
45
|
bbx resize 375 812 # iPhone-size
|
|
44
46
|
bbx resize 1024 768 # tablet
|
|
@@ -50,6 +52,7 @@ Uses CDP device emulation - the page re-renders at the new size immediately.
|
|
|
50
52
|
## Tab Management
|
|
51
53
|
|
|
52
54
|
**IMPORTANT: Prefer existing tabs.** Never create new tabs unless:
|
|
55
|
+
|
|
53
56
|
- The user explicitly requests opening a new page
|
|
54
57
|
- The task requires a clean/fresh page state (e.g., testing initial load)
|
|
55
58
|
- You need to compare multiple pages simultaneously
|
|
@@ -65,6 +68,7 @@ bbx call tabs.create '{"url":"https://example.com","active":false}'
|
|
|
65
68
|
```
|
|
66
69
|
|
|
67
70
|
Typical workflow - compare two pages (only when comparison is required):
|
|
71
|
+
|
|
68
72
|
1. `tabs.list` to see current tabs
|
|
69
73
|
2. `tabs.create` with second URL
|
|
70
74
|
3. Inspect both tabs (`--tab <id>` or MCP `tabId` only when you need the non-active tab)
|
|
@@ -83,6 +87,7 @@ bbx call dom.get_accessibility_tree '{"maxNodes":100,"maxDepth":5}'
|
|
|
83
87
|
Each node: `role`, `name`, `description`, `value`, `focused`, `required`, `checked`, `disabled`, `interactive`, `childIds`.
|
|
84
88
|
|
|
85
89
|
Typical workflow - find interactive controls:
|
|
90
|
+
|
|
86
91
|
1. `dom.get_accessibility_tree` with small `maxNodes`
|
|
87
92
|
2. Scan for nodes with `interactive: true`
|
|
88
93
|
3. Use role/name to identify the right control
|
|
@@ -103,6 +108,7 @@ bbx call --tab 200 dom.query '{"selector":"main"}'
|
|
|
103
108
|
```
|
|
104
109
|
|
|
105
110
|
Open a new tab programmatically:
|
|
111
|
+
|
|
106
112
|
```bash
|
|
107
113
|
bbx tab-create https://example.com # creates a new tab in the enabled window
|
|
108
114
|
bbx call --tab <new-tabId> page.get_state
|
|
@@ -127,6 +133,7 @@ Scrolls the window by default. Pass an `elementRef` to scroll an inner scrollabl
|
|
|
127
133
|
### Scroll target into view
|
|
128
134
|
|
|
129
135
|
Use this when the page has nested containers or when you want the target centered before a screenshot or hover:
|
|
136
|
+
|
|
130
137
|
```bash
|
|
131
138
|
bbx call input.scroll_into_view '{"target":{"elementRef":"el_123"}}'
|
|
132
139
|
bbx call input.scroll_into_view '{"target":{"selector":"[data-testid=\"submit-button\"]"}}'
|
|
@@ -143,6 +150,7 @@ bbx call page.get_network '{"limit":20,"clear":true}'
|
|
|
143
150
|
Each entry: `method`, `url`, `status`, `duration`, `initiator`.
|
|
144
151
|
|
|
145
152
|
Typical workflow - debug API calls:
|
|
153
|
+
|
|
146
154
|
1. `page.get_network` to see recent requests
|
|
147
155
|
2. Filter by URL pattern or status code
|
|
148
156
|
3. Cross-reference with `page.get_console` for errors
|
|
@@ -151,11 +159,13 @@ Typical workflow - debug API calls:
|
|
|
151
159
|
## Form Controls
|
|
152
160
|
|
|
153
161
|
**Checkbox/radio:**
|
|
162
|
+
|
|
154
163
|
```bash
|
|
155
164
|
bbx call input.set_checked '{"target":{"elementRef":"el_123"},"checked":true}'
|
|
156
165
|
```
|
|
157
166
|
|
|
158
167
|
**Select dropdown:**
|
|
168
|
+
|
|
159
169
|
```bash
|
|
160
170
|
bbx call input.select_option '{"target":{"elementRef":"el_456"},"values":["us"]}'
|
|
161
171
|
```
|
|
@@ -172,11 +182,13 @@ bbx call input.hover '{"target":{"elementRef":"el_abc123"}}'
|
|
|
172
182
|
```
|
|
173
183
|
|
|
174
184
|
**Hold hover for inspection:** set `duration` (ms) to keep hover active before auto-releasing with `mouseleave`:
|
|
185
|
+
|
|
175
186
|
```bash
|
|
176
187
|
bbx call input.hover '{"target":{"elementRef":"el_abc123"},"duration":2000}'
|
|
177
188
|
```
|
|
178
189
|
|
|
179
190
|
Typical workflow - inspect a tooltip:
|
|
191
|
+
|
|
180
192
|
1. `dom.query` to find the trigger element → `elementRef`
|
|
181
193
|
2. `input.hover` with `duration: 2000`
|
|
182
194
|
3. While hover holds, `dom.query` for tooltip content (e.g. `[role="tooltip"]`)
|
|
@@ -191,6 +203,7 @@ bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRe
|
|
|
191
203
|
```
|
|
192
204
|
|
|
193
205
|
With pixel offsets for precise positioning:
|
|
206
|
+
|
|
194
207
|
```bash
|
|
195
208
|
bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRef":"el_dst"},"sourceOffset":{"x":10,"y":10},"destinationOffset":{"x":5,"y":5}}'
|
|
196
209
|
```
|
|
@@ -198,6 +211,7 @@ bbx call input.drag '{"source":{"elementRef":"el_src"},"destination":{"elementRe
|
|
|
198
211
|
Event sequence: `mousedown → dragstart → drag → dragenter → dragover → drop → dragend → mouseup`.
|
|
199
212
|
|
|
200
213
|
Typical workflow - reorder a list:
|
|
214
|
+
|
|
201
215
|
1. `dom.query` to find draggable items → get source and destination `elementRef` values
|
|
202
216
|
2. `input.drag` from source to destination
|
|
203
217
|
3. `dom.wait_for` to confirm the DOM updated
|
|
@@ -206,16 +220,21 @@ Typical workflow - reorder a list:
|
|
|
206
220
|
## Finding Elements
|
|
207
221
|
|
|
208
222
|
### By text content
|
|
223
|
+
|
|
209
224
|
Find elements matching visible text. Faster than `dom.query` when you know the label:
|
|
225
|
+
|
|
210
226
|
```bash
|
|
211
227
|
bbx find 'Submit Order'
|
|
212
228
|
bbx call dom.find_by_text '{"text":"Add to Cart","scope":"button","exact":false}'
|
|
213
229
|
```
|
|
230
|
+
|
|
214
231
|
- `scope`: optional CSS selector to narrow search (e.g. `"button"`, `".sidebar"`)
|
|
215
232
|
- `exact`: `true` for exact match, `false` (default) for substring/case-insensitive
|
|
216
233
|
|
|
217
234
|
### By ARIA role
|
|
235
|
+
|
|
218
236
|
Find elements by explicit `role` attribute or implicit HTML role (e.g. `<nav>` → `navigation`):
|
|
237
|
+
|
|
219
238
|
```bash
|
|
220
239
|
bbx find-role button 'Save'
|
|
221
240
|
bbx call dom.find_by_role '{"role":"navigation"}'
|
|
@@ -225,19 +244,23 @@ bbx call dom.find_by_role '{"role":"heading","name":"Dashboard"}'
|
|
|
225
244
|
## Waiting
|
|
226
245
|
|
|
227
246
|
### Wait for DOM condition
|
|
247
|
+
|
|
228
248
|
```bash
|
|
229
249
|
bbx wait '.success-message' 10000
|
|
230
250
|
bbx call dom.wait_for '{"selector":".modal","state":"visible","timeoutMs":10000}'
|
|
231
251
|
bbx call dom.wait_for '{"selector":".spinner","state":"detached","timeoutMs":5000}'
|
|
232
252
|
```
|
|
253
|
+
|
|
233
254
|
- `state`: `attached` (exists in DOM), `detached` (removed), `visible` (non-zero size), `hidden`
|
|
234
255
|
- Uses MutationObserver + 250 ms polling fallback
|
|
235
256
|
- Returns `{found, elementRef, duration}` - NOT an error on timeout
|
|
236
257
|
|
|
237
258
|
### Wait for page load
|
|
259
|
+
|
|
238
260
|
```bash
|
|
239
261
|
bbx call page.wait_for_load_state '{"timeoutMs":10000}'
|
|
240
262
|
```
|
|
263
|
+
|
|
241
264
|
Use after clicking navigation links.
|
|
242
265
|
|
|
243
266
|
## Interaction Flow
|
|
@@ -12,6 +12,7 @@ Use this order for layout or styling issues:
|
|
|
12
12
|
6. `patch.rollback`
|
|
13
13
|
|
|
14
14
|
Prefer style patches for:
|
|
15
|
+
|
|
15
16
|
- overflow fixes
|
|
16
17
|
- spacing adjustments
|
|
17
18
|
- flex or grid tuning
|
|
@@ -21,6 +22,7 @@ Prefer style patches for:
|
|
|
21
22
|
## DOM patch loop
|
|
22
23
|
|
|
23
24
|
Use DOM patches for:
|
|
25
|
+
|
|
24
26
|
- text replacement
|
|
25
27
|
- setting or removing an attribute
|
|
26
28
|
- toggling a class
|
|
@@ -30,6 +32,7 @@ Keep DOM patches minimal and reversible.
|
|
|
30
32
|
## Verification
|
|
31
33
|
|
|
32
34
|
After any patch:
|
|
35
|
+
|
|
33
36
|
- compare box metrics when geometry matters
|
|
34
37
|
- compare computed styles when appearance matters
|
|
35
38
|
- capture a cropped screenshot only when the visual outcome is still unclear
|