DOM inspector 5/5: verify page structure + edge states, regenerate index

Session: sidechat/dom-structure
This commit is contained in:
dom-inspector-5
2026-10-04 04:29:10 +00:00
parent c50667b626
commit e28b10edc8
3 changed files with 126 additions and 27 deletions
+57 -18
View File
@@ -88,7 +88,11 @@ const isThreadNew =
!document.querySelector('[data-testid="hatch-chat-switcher-trigger"]'));
```
**Recovery:** Send Ctrl+J via CDP to return to main chat, then open panel via switcher click.
**Recovery:** Click `button[aria-label="Back to main chat"]` (present on `/thread/new`
and on regular `/thread/<uuid>` pages — verified on all fleet nodes 2026-10-04),
or click `[data-testid="hatch-nav-chat"]`, then open the panel via the switcher.
Do NOT use Ctrl+J here: stripped states lack keyboard focus, so the keystroke
goes nowhere (supersedes earlier Ctrl+J guidance; see DOM-INDEX §5).
**Distinct testid set** (no chat-switcher testids, dock-rail based):
```
@@ -146,7 +150,7 @@ document.querySelector('[data-testid="hatch-chat-switcher-trigger"]')
|---|---|
| Tag | `BUTTON` |
| `data-testid` | `hatch-chat-switcher-trigger` |
| Inner text | `Chats\nOpen chat and side chats` (or `Chats\nUnread chats\nOpen chat and side chats` when unreads exist) |
| Inner text | **The current thread's title** (e.g. `646 pip cross-operator coordination chat\nOpen chat and side chats`) — **NOT** the literal `Chats`. Never match the switcher by text. |
| `aria-expanded` | Not used (always `null`) |
| Class (partial) | `bg-fill-blur-thick shadow-blur-elevation-01 text-body-medium` |
@@ -271,25 +275,33 @@ TEXTAREA[aria-label="Message"]
└── DIV (cls: backdrop-blur-elevation-01 bg-fill-blur-thick shadow-blur-elevation-01)
```
### 2.7 "Main Chat" Navigation Button
### 2.7 "Main Chat" Navigation
To navigate to main chat from a sidechat, find the button with **exact** text `"Main chat"`:
**Primary (verified 2026-10-04 on muse/pip/opm):** the button with
`aria-label="Back to main chat"` — present on `/thread/<uuid>` pages and on
`/thread/new`, even with the panel closed:
```javascript
const backBtn = [...document.querySelectorAll('button')]
.find(b => b.getAttribute('aria-label') === 'Back to main chat');
backBtn?.click();
```
**Panel-open alternative:** when the sidechat panel is open, find the element with
**exact** text `"Main chat"`:
```javascript
const mainBtn = [...document.querySelectorAll('button, [role="button"]')]
.find(e => (e.innerText || '').trim() === 'Main chat');
```
**Must use exact match** (`=== 'Main chat'`), not substring — thread rows may contain "Main chat" as part of longer text.
**Must use exact match** (`=== 'Main chat'`), not substring — thread rows may contain
"Main chat" as part of longer text. Note: with the panel **closed** on a thread
page there is no exact-text "Main chat" element at all — use the aria-label
button above.
**Alternative:** Ctrl+J via CDP `Input.dispatchKeyEvent` (proven reliable for main-chat navigation):
```javascript
// Via CDP websocket:
{"id": 30, "method": "Input.dispatchKeyEvent",
"params": {"type": "keyDown", "key": "j", "code": "KeyJ", "ctrlKey": True, "modifiers": 2}}
{"id": 31, "method": "Input.dispatchKeyEvent",
"params": {"type": "keyUp", "key": "j", "code": "KeyJ", "ctrlKey": True, "modifiers": 2}}
```
**Do not use Ctrl+J** for this (superseded 2026-10-04): it needs keyboard focus,
which stripped/partial states lack. Prefer DOM clicks (commit `72574ba`).
---
@@ -430,15 +442,25 @@ hatch-side-chats-panel-sliding-surface
hatch-side-chats-panel-content
hatch-side-chats-options
hatch-side-chat-unread-indicator
hatch-side-chats-open-drag-handle # present when panel CLOSED (verified 2026-10-04)
hatch-side-chats-open-drag-handle-divider-line # NEW 2026-10-04: divider for the above; absent when panel open
hatch-thread-row # Individual chat rows (× N)
active-side-chat-load-more-sentinel
```
### Navigation Dock
```
hatch-dock-rail
hatch-dock-rail # DIV; children: dock-rail-divider (SPAN),
# nav-chat, dock-chat-notification-badge,
# nav-search, 4× nav-system-item-<hex>,
# app-download-dock-mark, dock-more
hatch-dock-rail-divider # SPAN (not DIV)
hatch-dock-more
hatch-nav-chat
hatch-nav-chat # A, href="/", aria-label dynamic:
# "Chat" | "Chat, N notification(s)" —
# match testid, NEVER exact aria-label.
# aria-current="page" when Chat section active.
# Verified 2026-10-04 on muse/pip/opm.
hatch-nav-search
hatch-nav-system-item-66656564 # (hex-encoded IDs)
hatch-nav-system-item-676f616c73
@@ -456,6 +478,9 @@ hatch-status-panel-close-toolbar
hatch-status-panel-sliding-surface
hatch-composer-placeholder-overlay
hatch-browser-task-banner-host
hatch-inline-approval-card # NEW 2026-10-04 (pip): DIV, no role —
# browser-task approval card ("A task needs review" + Review button),
# no IP in text. Structure TBD — see DOM-APPROVALS-SPEC.md (inspector 3/5).
hatch-invite-friends-button
app-download-dock-mark
```
@@ -467,9 +492,14 @@ app-download-dock-mark
### 7.1 Sidechat Creation (Robust)
```python
# 1. Navigate to main chat (recover from any state)
send_ctrl_j() # CDP Input.dispatchKeyEvent
time.sleep(3)
# 1. Recover to a chat-active state (click-based; never Ctrl+J — see §2.7):
# priority: compose (already ready) -> switcher -> hatch-nav-chat
# (muse-chat-api.py cmd_sidechat_main clicks the exact-text "Main chat"
# element; the aria-label "Back to main chat" button also works)
# Poll up to ~20s for the compose button.
# NOTE: plain JS .click() on the switcher does NOT reliably toggle the panel
# (Radix control — trusted CDP Input.dispatchMouseEvent needed, verified
# 2026-10-04). Prefer the compose-button presence check over blind toggling.
# 2. Verify we're on main chat
assert window.location.href == 'https://muse.ai/'
@@ -536,3 +566,12 @@ btn.click()
## Appendix: Change Log
- **2026-10-04:** Initial mapping via live CDP inspection. Documented 5 page states, 57 testids, approval dialog logic, and the `/thread/new` poisoning behavior.
- **2026-10-04 (inspector 5/5 re-verification, muse/pip/opm via CDP):**
- `hatch-nav-chat` verified: `A`, `href="/"`, dynamic `aria-label` (`Chat` / `Chat, N notification(s)`), `aria-current="page"`.
- Switcher inner text is the **current thread title**, not `Chats` — corrected §2.1 (never match switcher by text).
- `button[aria-label="Back to main chat"]` is present on `/thread/<uuid>` pages too, not only `/thread/new` — §2.7 rewritten around it as the primary main-chat affordance; Ctrl+J guidance removed as superseded.
- Plain JS `.click()` on the switcher does **not** reliably toggle the panel (Radix control needs trusted CDP pointer events) — noted in §7.1.
- New testids: `hatch-side-chats-open-drag-handle-divider-line` (all nodes), `hatch-inline-approval-card` (pip; browser-task approval card, no IP — structure deferred to DOM-APPROVALS-SPEC.md).
- Title gains an unread prefix: `(1) Chat — <agent>` (observed on pip).
- Settled-state variance: shimmer spans 1 (not 2), `role="status"` 3–4 (not 4–7), buttons 46–57 — ranges, not fixed counts.
- Fleet browsers are shared: another agent drove pip's browser mid-probe (URL/panel state changed between probes). Never assume a probe snapshot is still current — re-probe before acting.