From 7d0ccba64cef30fb3b322ba4044a53805eb59570 Mon Sep 17 00:00:00 2001 From: dom-panel-inspector Date: Sun, 4 Oct 2026 04:29:16 +0000 Subject: [PATCH] =?UTF-8?q?docs/DOM-CHAT-PANEL.md=20=E2=80=94=20re-verifie?= =?UTF-8?q?d=202026-10-04=20on=20opm/muse/pip;=20unread=20indicator,=20str?= =?UTF-8?q?ipped=20state,=20row=20differences?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Session: sidechat/dom-panel --- docs/DOM-CHAT-PANEL.md | 387 +++++++++++++++++++++++++---------------- 1 file changed, 241 insertions(+), 146 deletions(-) diff --git a/docs/DOM-CHAT-PANEL.md b/docs/DOM-CHAT-PANEL.md index 28b4634..7ba9aa5 100644 --- a/docs/DOM-CHAT-PANEL.md +++ b/docs/DOM-CHAT-PANEL.md @@ -1,18 +1,20 @@ # muse.ai Chat Panel & Sidechat DOM Reference -> Captured live via CDP on `opm` browser (warp-opm netns, CDP 9440) on 2026-10-04. -> Page: `https://muse.ai/`, title "Chat โ€” operator-main". +> Originally captured live via CDP on `opm` browser (warp-opm netns, CDP 9440). +> **Re-verified 2026-10-04** via CDP `Runtime.evaluate` on three nodes: +> `opm` (warp-opm, CDP 9440), `muse` (warp-muse, CDP 9410), `pip` (warp-pip, CDP 9420). +> Page: `https://muse.ai/`. Sections marked โœ… verified 2026-10-04, +> ๐Ÿ”ง corrected, ๐Ÿ†• new since original capture. > This is a development reference for reliable automation of the chat navigation panel > and sidechat creation. Prefer these selectors over text matching. --- -## 1. Chat Panel Switcher +## 1. Chat Panel Switcher โœ… (with corrections) **Selector:** `[data-testid="hatch-chat-switcher-trigger"]` -The button that toggles the chat navigation panel open/closed. Always present in the DOM, -top-left of the viewport. +The button that toggles the chat navigation panel open/closed. ```html ``` -**Key facts:** +**Key facts (โœ… verified 2026-10-04 on opm/muse/pip):** | Property | Value | |---|---| | Tag | `BUTTON` | -| Always in DOM | Yes (both panel states) | +| In DOM on `https://muse.ai/` or `/thread/` | โœ… Yes (both panel states) | +| In DOM on `/thread/new` stripped state | ๐Ÿ”ง **NO โ€” completely absent** (see ยง8) | | Visible | Yes (`offsetParent !== null`) | -| Position | Top-left: `x:84, y:12, w:82, h:36` | +| Position | Top-left: `x:84, y:12, w:82, h:36` (exact on opm) | | `aria-expanded` | **Not set** (`null`) โ€” do NOT use for state detection | -| Visible text | `Chats` | -| Screen-reader text | `Open chat and side chats` | -| Icon | Hamburger menu (3 horizontal lines), not a chat bubble | +| `data-pel-click` | `chat_threads_open_click` | +| `data-slot` | `popover-anchor` | +| Visible text | ๐Ÿ”ง **Active chat title, NOT static "Chats".** Shows e.g. `Heartbeat check for job scheduler`, `646 pip cross-operator coordination chat`; reads `Chats` only when main chat is active | +| Screen-reader text | `Open chat and side chats` (+ `Unread chats` when unread exist) | +| Icon | Hamburger menu (3 horizontal `` lines), not a chat bubble | -**Parent chain (bottom-up, 4 levels):** +**Parent chain (bottom-up, 4 levels):** โœ… unchanged ``` 1. DIV [data-testid="hatch-chat-leading-controls"] @@ -57,17 +63,42 @@ top-left of the viewport. 4. DIV (no testid) class="relative flex min-h-0 min-w-0 flex-1 flex-col overflow-hidden" ``` -**Behavior:** The switcher **toggles**. Clicking when the panel is closed opens it; -clicking when open closes it. Always check panel state before clicking โ€” never -blind-click. +**Behavior (โœ… verified atomically 2026-10-04):** The switcher **toggles in place โ€” +no navigation**. Click when closed โ†’ panel opens (shell `innerHTML` 0 โ†’ 60667, +rows 0 โ†’ 26 on opm). Click when open โ†’ panel closes. Always check panel state +before clicking โ€” never blind-click. (An earlier non-atomic probe appeared to +navigate; that was a race with the live heartbeat job driving the same browser โ€” +see ยง9.) **Child testids** (for reference): - `[data-testid="hatch-chat-switcher-icon-knockout"]` โ€” icon wrapper span - `[data-testid="hatch-chat-switcher-navigation-icon"]` โ€” the hamburger SVG span +- ๐Ÿ†• `[data-testid="hatch-chat-switcher-unread-indicator"]` โ€” unread blue dot (see ยง1b) --- -## 2. Sidechat Create Button ("New side chat") +## 1b. Unread Indicator ๐Ÿ†• (verified 2026-10-04 on muse) + +When unread chats exist, the switcher gains: + +```html + +Unread chats +``` + +| Property | Value | +|---|---| +| Selector | `[data-testid="hatch-chat-switcher-unread-indicator"]` | +| Visual | Blue dot (`bg-fill-blue`, 8px circle) overlaid on the switcher icon | +| `aria-hidden` | `true` โ€” screen readers get the sr-only `Unread chats` text instead | +| Programmatic signal | **Presence = unread chats exist.** Most reliable unread check | +| Companion signal | `document.title` gains an `(N)` prefix, e.g. `(1) Chat โ€” operator-pip` | + +--- + +## 2. Sidechat Create Button ("New side chat") โœ… **Selector:** `[data-testid="hatch-chat-compose"]` @@ -88,48 +119,31 @@ is OPEN.** This makes it the most reliable "panel is open and ready" signal. ``` -**Key facts:** +**Key facts (โœ… verified):** | Property | Value | |---|---| | Tag | `BUTTON` | | In DOM when panel closed | **No** โ€” completely absent | -| In DOM when panel open | Yes | +| In DOM when panel open | โœ… Yes (`visible: offsetParent !== null`) | | Text content | None (icon-only) | -| `aria-label` | `New side chat` | -| `title` | `New side chat` | +| `aria-label` / `title` | `New side chat` | | Icon | Plus sign (`+`), single SVG path | -**Parent chain (bottom-up, 8 levels):** +**Parent chain (bottom-up, 8 levels):** โœ… unchanged โ€” `SPAN.contents > DIV.group/nav-section` +(header row: `H3 "Side chats"` + compose) inside the `SECTION` "Side chats". -``` -1. SPAN (no testid) class="contents" โ† direct wrapper -2. DIV (no testid) class="group/nav-section flex w-full items-center" - children: [H3 "Side chats", SPAN(contents) > BUTTON#compose] -3. SECTION (no testid) class="flex flex-col" โ† "Side chats" section - children: [DIV(header: H3 + compose), DIV(chat list)] -4. DIV (no testid) class="flex flex-col relative grow-1" - children: [DIV[data-testid="hatch-thread-row"] (Main chat), - SECTION (Side chats), - DIV[data-testid="active-side-chat-load-more-sentinel"]] -5. DIV (no testid) class="flex flex-col overflow-hidden relative z-0 overflow-y-auto overscroll-y-contain min-h-0 min-w-0 flex-1 px-3 pb-3" -6. DIV (no testid) class="flex min-h-0 flex-1 flex-col" -7. DIV (no testid) class="text-text-primary flex h-full min-h-0 w-full flex-col overflow-hidden" -8. DIV (no testid) class="min-h-0 min-w-0 flex-1" -``` - -**Location in UI:** Inside the "Side chats" section header row, to the right of the -`H3` "Side chats" collapsible heading. - -**What clicking does:** Creates a new sidechat. Browser navigates to -`https://muse.ai/thread/new` (placeholder URL; the real thread UUID appears after -the first message is sent or navigation settles). +**What clicking does (โœ… verified 2026-10-04):** Creates a new sidechat draft. +Browser navigates `https://muse.ai/` โ†’ `https://muse.ai/thread/new` +(placeholder URL; the real thread UUID appears after the first message is sent +or navigation settles). **No sidechat exists server-side until a message is sent** +โ€” navigating to `/thread/new` and back is harmless. --- -## 3. Chat Navigation Panel Structure +## 3. Chat Navigation Panel Structure โœ… -### 3a. Panel shell (always in DOM) +### 3a. Panel shell (always in DOM โ€” except ยง8) **Selector:** `[data-testid="hatch-side-chats-panel-shell"]` @@ -141,70 +155,50 @@ the first message is sent or navigation settles). ``` -| State | `innerHTML` | `innerText` | +| State | `innerHTML` | `style.width` / computed | |---|---|---| -| Closed | `""` (empty string) | `""` | -| Open | Full `