DOM inspector 5/5: verify page structure + edge states, regenerate index
Session: sidechat/dom-structure
This commit is contained in:
+57
-18
@@ -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.
|
||||
|
||||
Reference in New Issue
Block a user