Engel’s notebook

App shell, sidebar and command menu

F02 · 28 mapped behaviors in the Self-Healing Codebase Project. Follow the prerequisites, actions and expected results; expand the original CLI recipe to replay it.

778 behavior IDs · 28 families · 844 named recipes & support steps
16 October 2026 · PR #18334 at 9a3c3a69
Canvas 1.27.1 · Agent Server 1.55.0 · automation 1.20.0

This is the map at the revision above, including its open bug notes. It does not incorporate later changes on main or claim a fresh verification run. Setup & reading guide · Download the scenario inventory

All scenarios & marker key · Open a script to read Given / Do / Expect. Expand the exact recipe for replayable commands.

F02 App shell, sidebar and command menu

28 behaviors · 31 scripts & contracts · Maintained source

Entry points & prerequisites

What this family covers

Every page inside the root layout shares one shell. On desktop it is a left rail with the logo, Search commands, New Chat, Customize, Automate (when the automation interface is present), the conversation list, the Getting started checklist, an update tile (only when a newer release exists) and the backend selector with a settings gear. The rail collapses to icons and remembers that choice. Below 768 px the rail turns into a drawer that opens from a top bar or the chat header. A user can pin Customize or Automate as the page / opens. A Ctrl/Cmd+K command menu searches pages, settings and actions. Failed requests show error toasts.

How a user gets here

  • Any page in the app: the left rail (desktop) or the hamburger (phone, browser viewport phone).
  • Direct URLs: / (the default home, or a redirect to the pinned page), /conversations, /customize, /automations, /settings.
  • Command menu: press Control+k or Meta+k anywhere, or click Search commands (command-menu-trigger) in the rail or drawer. Type a page or setting name, then press Enter or click the row.
  • Hover a sidebar row to reveal its pin. Hover the collapsed rail's logo to reveal the expand chevron.
  • Settings → Application (/settings/app): the Show Getting Started checklist switch.
  • The Getting started card: click an item row to go to its page, or hover it for the preview; hover the card for the X that dismisses it.
  • Keyboard: Control+k also works while the composer has focus; Tab moves from the search input into the option list.

Given

Preconditions:

  • Baseline state (launched, doctored, onboard --skip done), desktop viewport, sidebar expanded, no home pin, checklist shown.
  • F02.checklist-progress (LLM and chat items) needs control-openhands llm preset deepseek and one conversation (control-openhands conversation start --prompt "Reply with only the word: ok" --wait --timeout 180). Run both before the F02.conversation-list bullet. The preset writes through the API, so control-openhands browser reload before you read the LLM item. The conversation-header hamburger check in F02.mobile-drawer reuses that conversation.
  • F02.update-tile (the sidebar tile) is blocked unless the installed version is older than npm latest and the browser can reach registry.npmjs.org. The Settings → Application check runs either way.
  • F02.alert-banner is blocked on the local backend, whose config always reports no alerts; it needs a Cloud backend that publishes them.
  • F02.settings-404-modal is blocked: it needs a backend whose settings endpoint returns 404.
  • F02.checklist-all-complete needs an automation and an MCP server on top of the four items above. Both are added through the UI from two fixtures (see that bullet) and deleted again afterwards.
Pin as homeF02.pin-as-homeMapped behavior

Scenario F02--pin-as-home · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Hover over “Sidebar skills”.
  2. Do
    Choose “Sidebar pin home toggle customize”.
  3. Do
    Open /.
  4. Wait
    Wait for the element identified in the CLI recipe to appear.
  5. Do
    Hover over “Sidebar automations”.
  6. Do
    Choose “Sidebar pin home toggle automations”.
  7. Do
    Open /.
  8. Do
    Choose “Sidebar pin home toggle automations”.
  9. Do
    Open /.
  10. Do
    Use browser storage as specified in the exact recipe.

Expect

hovering Customize or Automate reveals a pin. Pinning makes / redirect to that page, pinning the other one moves the pin, and unpinning restores the default home. The pin is stored per backend and org.

Exact CLI recipe & bug checks

From /conversations run control-openhands browser visible 'testid=sidebar-pin-home-toggle-customize' (false), control-openhands browser hover 'testid=sidebar-skills-link', the same visible (true), then control-openhands browser click 'testid=sidebar-pin-home-toggle-customize' and control-openhands browser attr 'testid=sidebar-pin-home-toggle-customize' aria-pressed (true). Run control-openhands browser goto / and control-openhands browser wait-url '/mcp$'; the URL ends in /mcp. Run control-openhands browser screenshot 'aside[data-collapsed]' --feature F02.pin-as-home --name customize-pinned; the screenshot shows a filled pin on the Customize row with no hover. Move the pin: run control-openhands browser hover 'testid=sidebar-automations-link' and control-openhands browser click 'testid=sidebar-pin-home-toggle-automations'. The Customize pin's aria-pressed becomes false, and control-openhands browser goto / lands on /automations. Unpin with control-openhands browser click 'testid=sidebar-pin-home-toggle-automations', then run control-openhands browser goto / and control-openhands browser count 'testid=home-screen'. The URL stays / and the count is 1. control-openhands browser storage --values shows oh:pinned-home-route:<backend>:<org> as null.

Collapse and expandF02.sidebar-collapseMapped behavior

Scenario F02--collapse-and-expand · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Sidebar collapse toggle”.
  2. Do
    Reload the page.
  3. Do
    Use browser storage as specified in the exact recipe.
  4. Do
    Hover over “Sidebar automations”.
  5. Do
    Hover over “Sidebar skills”.
  6. Wait
    Wait for the tooltip to appear.
  7. Do
    Hover over “Collapsed backend selector”.
  8. Do
    Choose the element identified in the CLI recipe.
  9. Do
    Hover over the element identified in the CLI recipe.
  10. Do
    Choose “Sidebar collapse toggle”.

Expect

the chevron collapses the rail to a 60 px icon rail with hover tooltips, a Settings icon and a backend icon with a status dot that opens a backend popover. The checklist is hidden while collapsed. The state survives a reload. To expand, click the chevron that appears when you hover the logo, or click empty rail space.

Exact CLI recipe & bug checks

Run control-openhands browser click 'testid=sidebar-collapse-toggle' and control-openhands browser attr 'aside[data-collapsed]' data-collapsed (true). Run control-openhands browser reload; the attribute is still true, browser storage --values shows openhands-sidebar with "collapsed":true, and control-openhands browser bbox 'aside[data-collapsed]' reports width 60. control-openhands browser count 'testid=sidebar-onboarding-checklist' is 0. For the tooltip, hover one icon, then another: control-openhands browser hover 'testid=sidebar-automations-link', control-openhands browser hover 'testid=sidebar-skills-link', then control-openhands browser wait 'role=tooltip' and control-openhands browser text 'role=tooltip' (Customize). For the backend popover, run control-openhands browser hover 'testid=collapsed-backend-selector-link'; its aria-expanded is true, browser testids --filter backend lists add-backend-menu-item and manage-backends-menu-item, and control-openhands browser screenshot --feature F02.sidebar-collapse --name backend-popover shows the popover. Expand by clicking empty rail space with control-openhands browser click 'aside[data-collapsed]' (data-collapsed becomes false). Collapse again, then run control-openhands browser hover 'aside[data-collapsed] >> role=link[name="OpenHands Logo"]'; the toggle's class has opacity-100 and its aria-label is Expand sidebar. control-openhands browser click 'testid=sidebar-collapse-toggle' expands the rail.

Settings gearF02.settings-linkMapped behavior

Scenario F02--settings-gear · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Sidebar collapse toggle”.
  2. Do
    Choose “Collapsed settings”.
  3. Wait
    Wait for the element identified in the CLI recipe to appear.
  4. Do
    Choose “Sidebar collapse toggle”.
  5. Do
    Open /conversations.
  6. Do
    Choose “Settings”.

Expect

the gear next to the backend selector, and the collapsed Settings icon, open /settings in the same tab for a local backend. On desktop that redirects to /settings/agents.

Exact CLI recipe & bug checks

The previous bullet expanded the rail: collapse it with control-openhands browser click 'testid=sidebar-collapse-toggle', then run control-openhands browser click 'testid=collapsed-settings-link' and control-openhands browser wait-url '/settings'. Expand it again with control-openhands browser click 'testid=sidebar-collapse-toggle', then run control-openhands browser goto /conversations, control-openhands browser click 'testid=backend-selector-settings-link' and control-openhands browser url; the URL ends in /settings/agents. control-openhands browser attr 'testid=backend-selector-settings-link' target is null (same tab).

Conversation listF02.conversation-listMapped behavior

Scenario F02--conversation-list · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Start a conversation as specified in the recipe.
  2. Do
    Open /conversations.

Expect

the expanded rail embeds the conversation list (conversation-panel). The list itself belongs to the conversations family.

Exact CLI recipe & bug checks

After conversation start (preconditions), run control-openhands browser goto /conversations and control-openhands browser testids 'testid=conversation-panel'. The list includes conversation-card.

Open and close the menuF02.command-menu-open-closeMapped behavior

Scenario F02--open-and-close-the-menu · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Press Control+k.
  2. Do
    Press Escape.
  3. Do
    Press Meta+k.
  4. Do
    Enter “secr” in “Command menu” / the combobox.
  5. Do
    Choose “Command menu” / “Close command menu”.
  6. Do
    Choose “Search commands”.
  7. Do
    Press Escape.
  8. Do
    Choose “Sidebar collapse toggle”.
  9. Do
    Choose “Search commands”.
  10. Do
    Press Escape.
  11. Do
    Choose the element identified in the CLI recipe.

Expect

Control+k, Meta+k and the sidebar Search commands row (also the search icon on the collapsed rail) open a modal Command menu dialog with the input focused. Escape or the backdrop closes it, and the query is cleared on close. Escape returns focus to the element that had it before the menu opened (the Search commands row when it opened the menu). The row and the menu header show the shortcut as Ctrl+K off Apple platforms and ⌘K on macOS and iOS.

Exact CLI recipe & bug checks

From /conversations run control-openhands browser text 'testid=command-menu-trigger'. It reads Search commands and CTRL+K on Linux and Windows (the hint is Ctrl+K, drawn in capitals; macOS and iOS show ⌘K). Run control-openhands browser press Control+k, then control-openhands browser visible 'testid=command-menu' (true), control-openhands browser eval "document.activeElement && document.activeElement.id" (command-menu-search) and control-openhands browser text 'testid=command-menu >> css=kbd' (CTRL+K, the header hint). control-openhands browser screenshot --feature F02.command-menu-open-close --name open shows the dimmed, blurred backdrop. Run control-openhands browser press Escape; browser count 'testid=command-menu' is 0. Run control-openhands browser press Meta+k (count 1), control-openhands browser type 'testid=command-menu >> role=combobox' secr, then control-openhands browser click 'testid=command-menu >> role=button[name="Close command menu"]' (the backdrop; count 0). Run control-openhands browser click 'testid=command-menu-trigger' and control-openhands browser value 'testid=command-menu >> role=combobox'; the value is "" because the query was cleared on close. Close it with control-openhands browser press Escape; focus is back on the row (control-openhands browser eval "document.activeElement.dataset.testid" is command-menu-trigger). Collapsed rail: run control-openhands browser click 'testid=sidebar-collapse-toggle', control-openhands browser click 'testid=command-menu-trigger' (the search icon; count 1), control-openhands browser press Escape, then expand with control-openhands browser click 'aside[data-collapsed]'.

Every item navigatesF02.command-menu-itemsMapped behavior

Scenario F02--every-item-navigates · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Press Control+k.
  2. Do
    Press Escape.
  3. Do
    Hover over “Search commands”.
  4. Do
    Open /conversations.
  5. Do
    Press Control+k.
  6. Do
    Enter “<term>” in “Command menu” / the combobox.
  7. Do
    Press Enter.
  8. Wait
    Wait for the element identified in the CLI recipe to appear.
  9. Do
    Open /settings/app.
  10. Do
    Choose “Command menu” / “New chat”.

Expect

the menu shows Navigation (New chat, Customize, Automations, MCP servers), Settings (Settings, Agent settings, LLM profiles, Model Router, Condenser, Agent Context, Verification, Application, Secrets) and Actions (Toggle sidebar). Each Go item navigates to its route.

Exact CLI recipe & bug checks

The previous bullet closed the menu: run control-openhands browser press Control+k, then control-openhands browser snapshot 'testid=command-menu' --feature F02.command-menu-items --name all-items; it lists 14 options under Navigation, Settings and Actions, with Model Router after LLM profiles and Agent Context after Condenser settings. Close it with control-openhands browser press Escape and rest the pointer off the list with control-openhands browser hover 'testid=command-menu-trigger' (see Gotchas). For each item run control-openhands browser goto /conversations, control-openhands browser press Control+k, control-openhands browser type 'testid=command-menu >> role=combobox' '<term>', control-openhands browser press Enter and control-openhands browser wait-url '<route>$'. Expected routes: New chat → /conversations, Customize → /mcp (via /customize), Automations → /automations, MCP servers → /mcp, Settings overview → /settings/agents (via /settings), Agent settings → /settings/agents, LLM profiles → /settings/llm, Model Router → /settings/meta-llm, Condenser → /settings/condenser, Agent Context → /settings/agent-context, Verification → /settings/verification, Application → /settings/app, Secrets → /settings/secrets. browser count 'testid=command-menu' is 0 after each run. Click path: control-openhands browser goto /settings/app, open the menu, type new chat, then control-openhands browser click 'testid=command-menu >> role=option[name=/New chat/]'; the URL becomes /conversations.

Toggle sidebarF02.command-menu-toggle-sidebarMapped behavior

Scenario F02--toggle-sidebar · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Press Control+k.
  2. Do
    Enter “toggle” in “Command menu” / the combobox.
  3. Do
    Press Enter.

Expect

the Toggle sidebar action collapses or expands the desktop rail.

Exact CLI recipe & bug checks

Run control-openhands browser press Control+k, control-openhands browser type 'testid=command-menu >> role=combobox' toggle, control-openhands browser press Enter, then control-openhands browser attr 'aside[data-collapsed]' data-collapsed (true). Repeat with the term sidebar; the value returns to false.

Search, empty state, keyboardF02.command-menu-searchMapped behavior

Scenario F02--search-empty-state-keyboard · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Press Control+k.
  2. Do
    Enter “theme” in “Command menu” / the combobox.
  3. Do
    Press Enter.
  4. Do
    Choose “Command menu” / “Clear search”.
  5. Do
    Press ArrowUp.
  6. Do
    Hover over “Command menu” / “Secrets settings”.

Expect

every search term must match the title, description or keywords. No commands found is the empty state. The X button clears the query. Arrow keys wrap around the list, hovering an item selects it, Enter runs the selected item, and Enter does nothing when nothing matches.

Exact CLI recipe & bug checks

The Toggle sidebar action closed the menu: open it with control-openhands browser press Control+k, then run control-openhands browser fill 'testid=command-menu >> role=combobox' theme and control-openhands browser count 'testid=command-menu >> role=option' (1, Application, matched by its keywords). The term settings secret leaves 1 option, secret automations leaves 0 (all terms must match) and model leaves 3 (MCP servers, LLM profiles, Model Router). Fill qa-zzz-nothing, then run control-openhands browser text 'testid=command-menu >> role=listbox' (No commands found / Try a page, action, or setting name.) and control-openhands browser screenshot --feature F02.command-menu-search --name no-results. Run control-openhands browser press Enter; the menu stays open and the URL does not change. Run control-openhands browser click 'testid=command-menu >> role=button[name="Clear search"]'; the value is "" and the count is back to 14. Keyboard: control-openhands browser attr 'testid=command-menu >> role=combobox' aria-activedescendant starts at command-menu-option-new-chat. control-openhands browser press ArrowUp wraps to command-menu-option-toggle-sidebar, and ArrowDown returns to new-chat, then moves to customize. control-openhands browser hover 'testid=command-menu >> role=option[name=/Secrets settings/]' sets the value to command-menu-option-secrets-settings.

Open in a new tabF02.command-menu-new-tabMapped behavior

Scenario F02--open-in-a-new-tab · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Command menu” / “Secrets settings”.
  2. Do
    Use browser tabs as specified in the exact recipe.
  3. Do
    Use browser close tab as specified in the exact recipe.
  4. Do
    Choose “Command menu” / “Secrets settings”.
  5. Do
    Press Escape.

Expect

a middle-click or modifier-click on a Go item opens the route in a new tab and leaves the menu open.

Exact CLI recipe & bug checks

With the menu open and secrets typed, control-openhands browser attr 'testid=command-menu >> role=option[name=/Secrets settings/]' href is /settings/secrets. Run control-openhands browser click 'testid=command-menu >> role=option[name=/Secrets settings/]' --button middle and control-openhands browser tabs; tab 1 is /settings/secrets, tab 0 keeps its URL, and browser count 'testid=command-menu' is still 1. Run control-openhands browser close-tab 1. The modifier path works the same: control-openhands browser click 'testid=command-menu >> role=option[name=/Secrets settings/]' --modifiers Control opens tab 1 with the menu still open; close that tab too. The click leaves focus on the option; control-openhands browser press Escape still closes the menu (count 0).

Keyboard focusF02.command-menu-focusMapped behavior

Scenario F02--keyboard-focus · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Message”.
  2. Do
    Press Control+k.
  3. Do
    Press Tab.
  4. Do
    Press Escape.

Expect

the shortcut works while typing in another field (the composer) and moves focus to the search input. Tab moves focus to the first option. Escape closes the menu from any focused element inside it and returns focus to the composer.

Exact CLI recipe & bug checks

From /conversations run control-openhands browser click 'testid=chat-input', control-openhands browser press Control+k, browser count 'testid=command-menu' (1) and control-openhands browser eval "document.activeElement && document.activeElement.id" (command-menu-search): the shortcut opens the menu from inside the composer. Run control-openhands browser press Tab; the same eval returns command-menu-option-new-chat. control-openhands browser press Escape closes the menu from the option (count 0), and control-openhands browser eval "document.activeElement.dataset.testid" returns chat-input: focus is back in the composer.

Phone drawerF02.mobile-drawerMapped behavior

Scenario F02--phone-drawer · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Setup
    Use the phone viewport.
  2. Do
    Open /conversations.
  3. Do
    Choose “Sidebar mobile menu toggle”.
  4. Wait
    Wait for “Sidebar mobile drawer” to appear.
  5. Wait
    Wait for “Sidebar mobile drawer” to disappear.
  6. Do
    Choose “Sidebar mobile drawer close”.
  7. Do
    Press Escape.
  8. Do
    Choose “Sidebar mobile drawer” / “Sidebar automations”.
  9. Do
    Use browser mouse click as specified in the exact recipe.
  10. Do
    Choose “Submit”.
  11. Do
    Open the URL in the recipe.
  12. Do
    Start a conversation as specified in the recipe.
  13. Setup
    Use the desktop viewport.

Expect

at phone width the rail is hidden and a hamburger (sidebar-mobile-menu-toggle) opens a 300 px drawer. The hamburger is in the top bar, or in the chat header on conversation pages. The drawer closes on its chevron, Escape, a backdrop click or any route change.

Exact CLI recipe & bug checks

Run control-openhands browser viewport phone and control-openhands browser goto /conversations. control-openhands browser visible 'aside[data-collapsed]' is false. Run control-openhands browser click 'testid=sidebar-mobile-menu-toggle' and control-openhands browser wait 'testid=sidebar-mobile-drawer'. control-openhands browser bbox 'testid=sidebar-mobile-drawer' gives width 300, insideViewport true and pageHorizontalOverflow false, and control-openhands browser screenshot --feature F02.mobile-drawer --name open shows the full rail. Close paths, each followed by control-openhands browser wait 'testid=sidebar-mobile-drawer' --state detached: control-openhands browser click 'testid=sidebar-mobile-drawer-close'; control-openhands browser press Escape; control-openhands browser click 'testid=sidebar-mobile-drawer >> testid=sidebar-automations-link' (route change; the URL becomes /automations); and a backdrop click to the right of the drawer, control-openhands browser mouse-click 350 400 (on /conversations, control-openhands browser click 'testid=submit-button' --force also lands on the backdrop, because the empty composer's send button sits at x≈326 under it). On a conversation page (browser goto the URL from conversation start), control-openhands browser bbox 'testid=sidebar-mobile-menu-toggle' is at the top-left of the chat header. control-openhands browser screenshot --feature F02.mobile-drawer --name conversation-header shows it beside the title, and clicking it opens the drawer. Return with control-openhands browser viewport desktop.

Back chevronF02.mobile-top-barMapped behavior

Scenario F02--back-chevron · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Setup
    Use the phone viewport.
  2. Do
    Open /settings/llm.
  3. Do
    Choose “Sidebar mobile back”.

Expect

at phone width, settings sub-pages and Customize detail pages (/skills, /mcp, /plugins, /apps) show a Back chevron that returns to /settings or /customize.

Exact CLI recipe & bug checks

The Phone drawer bullet returned to desktop: run control-openhands browser viewport phone, control-openhands browser goto /settings/llm and control-openhands browser attr 'testid=sidebar-mobile-back-button' aria-label (Settings). Then run control-openhands browser click 'testid=sidebar-mobile-back-button' and control-openhands browser url; the URL is /settings, and on that page browser count 'testid=sidebar-mobile-back-button' is 0. control-openhands browser screenshot --feature F02.mobile-top-bar --name settings-root shows only the hamburger above the settings menu. Do the same from /skills: the label is Customize and the click lands on /customize, which on phone is the hub (extensions-mobile-hub).

Phone command menuF02.command-menu-phoneMapped behavior

Scenario F02--phone-command-menu · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Sidebar mobile drawer” / “Search commands”.
  2. Do
    Press Escape.
  3. Do
    Choose “Sidebar mobile drawer” / “Search commands”.
  4. Wait
    Wait for the element identified in the CLI recipe to appear.
  5. Wait
    Wait for “Sidebar mobile drawer” to disappear.

Expect

at 390 px the menu fits the screen and opens from the drawer's Search row. Escape closes the menu and leaves the drawer open. Running an item closes the drawer.

Exact CLI recipe & bug checks

At phone width open the drawer, then run control-openhands browser click 'testid=sidebar-mobile-drawer >> testid=command-menu-trigger'. control-openhands browser bbox 'testid=command-menu >> role=listbox' reports insideViewport true and pageHorizontalOverflow false, and control-openhands browser screenshot --feature F02.command-menu-phone --name open shows it. control-openhands browser press Escape closes only the menu: browser count 'testid=command-menu' is 0 and control-openhands browser visible 'testid=sidebar-mobile-drawer' is still true. Reopen it with control-openhands browser click 'testid=sidebar-mobile-drawer >> testid=command-menu-trigger', type secrets and press Enter; control-openhands browser wait-url 'secrets$' passes and control-openhands browser wait 'testid=sidebar-mobile-drawer' --state detached passes.

Checklist cardF02.checklistMapped behavior

Scenario F02--checklist-card · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Setup
    Use the desktop viewport.
  2. Do
    Open /conversations.

Expect

after onboarding, the expanded rail shows a Getting started card with N complete and six items. They link to /settings/llm, /conversations, /automations, /settings/agents, /mcp and the external Slack invite.

Exact CLI recipe & bug checks

The phone bullets above leave the phone viewport on /settings/secrets: run control-openhands browser viewport desktop, control-openhands browser goto /conversations, then control-openhands browser count 'testid=sidebar-onboarding-checklist >> role=listitem' (6) and control-openhands browser text 'testid=sidebar-onboarding-checklist'. The first lines are Getting started and N complete. control-openhands browser snapshot 'aside[data-collapsed]' shows the six links: /settings/llm, /conversations, /automations, /settings/agents, /mcp and https://openhands.dev/joinslack.

ProgressF02.checklist-progressMapped behavior

Scenario F02--progress · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Open /settings/agents.
  2. Do
    Choose “Sidebar onboarding checklist item join slack”.
  3. Do
    Use browser tabs as specified in the exact recipe.
  4. Do
    Use browser close tab as specified in the exact recipe.
  5. Setup
    Configure or inspect the model profiles specified in the recipe.
  6. Do
    Reload the page.
  7. Wait
    Wait for the element identified in the CLI recipe to appear.
  8. Do
    Start a conversation as specified in the recipe.

Expect

items get a check and a strikethrough when done. The LLM item completes when a profile is configured, Start your first chat when a conversation exists, Customize your agent after a visit to /settings/agents, and Join Slack on click.

Exact CLI recipe & bug checks

Each completed item renders a struck-through label, so control-openhands browser count 'testid=sidebar-onboarding-checklist-item-<id> >> css=span.line-through' is 1. Run control-openhands browser goto /settings/agents, then come back; customize-agent is done. Run control-openhands browser click 'testid=sidebar-onboarding-checklist-item-join-slack'; join-slack is done and browser tabs shows an external Slack tab, which you close with control-openhands browser close-tab 1. After llm preset deepseek, run control-openhands browser reload (the open page does not refetch settings written through the API), then control-openhands browser wait 'testid=sidebar-onboarding-checklist-item-configure-llm >> css=span.line-through' --timeout 15000. After conversation start, start-conversation is done. The header count rises each time (4 complete after these four).

Item previewF02.checklist-previewMapped behavior

Scenario F02--item-preview · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Hover over “Sidebar onboarding checklist item join slack”.
  2. Do
    Hover over “Sidebar onboarding checklist item connect mcp”.
  3. Wait
    Wait for “Sidebar onboarding checklist preview connect mcp” to appear.
  4. Do
    Choose “Sidebar onboarding checklist preview action connect mcp”.
  5. Wait
    Wait for the element identified in the CLI recipe to appear.

Expect

hovering an item shows a preview with a description, a Documentation link and an action button that navigates.

Exact CLI recipe & bug checks

Run control-openhands browser hover 'testid=sidebar-onboarding-checklist-item-join-slack', control-openhands browser hover 'testid=sidebar-onboarding-checklist-item-connect-mcp' and control-openhands browser wait 'testid=sidebar-onboarding-checklist-preview-connect-mcp' --timeout 5000. Then run control-openhands browser text 'testid=sidebar-onboarding-checklist-preview-connect-mcp'; it reads the title, the description, Documentation and Connect. control-openhands browser attr 'testid=sidebar-onboarding-checklist-preview-docs-connect-mcp' href is https://docs.openhands.dev/overview/model-context-protocol. Take control-openhands browser screenshot --feature F02.checklist-preview --name connect-mcp, then run control-openhands browser click 'testid=sidebar-onboarding-checklist-preview-action-connect-mcp' and control-openhands browser wait-url '/mcp$'.

MinimizeF02.checklist-minimizeMapped behavior

Scenario F02--minimize · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Sidebar onboarding checklist toggle”.
  2. Do
    Reload the page.

Expect

the card header minimizes and expands the card, and the state survives a reload.

Exact CLI recipe & bug checks

Run control-openhands browser click 'testid=sidebar-onboarding-checklist-toggle', control-openhands browser attr 'testid=sidebar-onboarding-checklist' data-minimized (true) and browser count 'testid=sidebar-onboarding-checklist >> role=listitem' (0). After control-openhands browser reload the attribute is still true and the toggle's aria-label is Expand checklist. Click the toggle again to restore false.

DismissF02.checklist-dismissMapped behavior

Scenario F02--dismiss · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Hover over “Search commands”.
  2. Do
    Hover over “Sidebar onboarding checklist toggle”.
  3. Wait
    Wait for “Dismiss checklist” to appear.
  4. Do
    Choose “Dismiss checklist”.
  5. Do
    Reload the page.
  6. Do
    Use browser storage as specified in the exact recipe.
  7. Do
    Choose “Show Getting Started checklist”.
  8. Do
    Choose “Sidebar onboarding checklist toggle”.

Expect

hovering or focusing the card (expanded or minimized) reveals an X (Dismiss checklist) in its header; touch devices always show it. Clicking it hides the card for good (it stays hidden after a reload) and turns off the Show Getting Started checklist switch in Settings → Application, which brings the card back in its previous expanded or minimized state.

Exact CLI recipe & bug checks

On /conversations, control-openhands browser count 'role=button[name="Dismiss checklist"]' is 0 (the X is opacity-0 and invisible until the card is hovered). Run control-openhands browser hover 'testid=command-menu-trigger', control-openhands browser hover 'testid=sidebar-onboarding-checklist-toggle' and control-openhands browser wait 'role=button[name="Dismiss checklist"]' --state visible --timeout 5000 (browser screenshot 'aside[data-collapsed]' --feature F02.checklist-dismiss --name hover-close). Run control-openhands browser click 'role=button[name="Dismiss checklist"]': browser count 'testid=sidebar-onboarding-checklist' is 0, still 0 after control-openhands browser reload, and browser storage lists openhands-sidebar-onboarding-checklist-dismissed. On /settings/app, control-openhands browser eval "document.querySelector('[data-testid=show-getting-started-checklist-switch]').checked" is false; control-openhands browser click 'text=Show Getting Started checklist' brings the card back. Minimized: control-openhands browser click 'testid=sidebar-onboarding-checklist-toggle' (data-minimized true), hover as above, click the X (count 0), click the switch text again: the card returns with data-minimized true; click the toggle to expand it. At phone width the X shows in the drawer's card the same way.

Hide from settingsF02.checklist-hideMapped behavior

Scenario F02--hide-from-settings · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Open /settings/app.
  2. Do
    Choose “Show Getting Started checklist”.
  3. Do
    Reload the page.

Expect

the Show Getting Started checklist switch in Settings → Application hides the card (it stays hidden after a reload) and can show it again.

Exact CLI recipe & bug checks

Run control-openhands browser goto /settings/app and control-openhands browser click 'text=Show Getting Started checklist'; browser count 'testid=sidebar-onboarding-checklist' is 0. After control-openhands browser reload the count is still 0, and control-openhands browser eval "document.querySelector('[data-testid=show-getting-started-checklist-switch]').checked" is false. Click the same text again; the count is 1.

All completeF02.checklist-all-completeMapped behavior

Scenario F02--all-complete · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Setup
    Create the disposable file fixture specified in the recipe.
  2. Setup
    Create the disposable file fixture specified in the recipe.
  3. Do
    Open /mcp.
  4. Do
    Choose “Mcp add custom server”.
  5. Do
    Choose “Server type dropdown”.
  6. Do
    Choose “STDIO”.
  7. Do
    Enter “qa_f02_mcp” in “Name”.
  8. Do
    Enter “python3” in “Command”.
  9. Do
    Enter “$OH_VERIFY_RUN/evidence/_fixtures/qa-f02-mcp.py” in “Args”.
  10. Do
    Choose “Mcp custom editor” / “Submit”.
  11. Wait
    Wait for “Mcp custom editor” to disappear.
  12. Do
    Open /automations.
  13. Do
    Choose “Automations add automation”.
  14. Do
    Choose “Automations import automation”.
  15. Do
    Use browser upload as specified in the exact recipe.
  16. Do
    Choose “Import automation confirm”.
  17. Wait
    Wait for “Import automation modal” to disappear.
  18. Do
    Reload the page.
  19. Do
    Choose the element identified in the CLI recipe.
  20. Do
    Choose the list / containing “Export” / “Delete”.
  21. Do
    Choose “Delete automation” / its containing control / “Delete”.
  22. Do
    Reload the page.
  23. Do
    Open /mcp.
  24. Do
    Choose “Mcp server detail qa f02 mcp”.
  25. Do
    Choose “Mcp custom editor delete”.
  26. Do
    Choose “Confirmation dialog” / “Confirm”.
  27. Do
    Reload the page.

Expect

the card disappears once all six items are complete. Completion is recomputed from current data, so deleting the automation or the MCP server brings the card back.

Exact CLI recipe & bug checks

Start with the four items above done (5 complete would mean one fixture is left over). Arrange two fixtures: a minimal stdio MCP server, control-openhands fixture file --name qa-f02-mcp.py --content "$(printf '%s\n' 'import sys,json' 'for line in sys.stdin:' ' m=json.loads(line)' ' if "id" not in m: continue' ' r={}' ' if m.get("method")=="initialize": r={"protocolVersion":m["params"].get("protocolVersion","2024-11-05"),"capabilities":{"tools":{}},"serverInfo":{"name":"qa","version":"1"}}' ' elif m.get("method")=="tools/list": r={"tools":[]}' ' sys.stdout.write(json.dumps({"jsonrpc":"2.0","id":m["id"],"result":r})+"\n"); sys.stdout.flush()')", and control-openhands fixture file --name qa-f02.automation.json --content '{"version":1,"kind":"automation","spec":{"name":"QA_F02 Done","trigger":{"type":"cron","schedule":"0 0 1 1 *","timezone":"UTC"},"enabled":false,"prompt":"Reply with the single word: pong. Do not run any tools."}}'. Add the server in the UI: control-openhands browser goto /mcp, control-openhands browser click 'testid=mcp-add-custom-server', control-openhands browser click 'testid=server-type-dropdown', control-openhands browser click 'role=option[name="STDIO"]', control-openhands browser fill 'testid=name-input' qa_f02_mcp, control-openhands browser fill 'testid=command-input' python3, control-openhands browser fill 'testid=args-input' "$OH_VERIFY_RUN/evidence/_fixtures/qa-f02-mcp.py", control-openhands browser click 'testid=mcp-custom-editor >> testid=submit-button' and control-openhands browser wait 'testid=mcp-custom-editor' --state detached. The header reads 5 complete. Import the automation: control-openhands browser goto /automations, control-openhands browser click 'testid=automations-add-automation', control-openhands browser click 'testid=automations-import-automation', control-openhands browser upload 'testid=automations-import-file' "$OH_VERIFY_RUN/evidence/_fixtures/qa-f02.automation.json", control-openhands browser click 'testid=import-automation-confirm' and control-openhands browser wait 'testid=import-automation-modal' --state detached. Now browser count 'testid=sidebar-onboarding-checklist' is 0, still 0 after control-openhands browser reload, and control-openhands browser screenshot 'aside[data-collapsed]' --feature F02.checklist-all-complete --name rail shows the rail without the card. Restore and prove it comes back: open the card's kebab with control-openhands browser click '[data-testid^="automation-card-"] >> has-text=QA_F02 Done >> role=button[name="Automation actions"]', then control-openhands browser click 'role=list >> has-text=Export >> role=button[name="Delete"]', control-openhands browser click 'role=heading[name="Delete automation"] >> xpath=.. >> role=button[name="Delete"]' and control-openhands browser reload; the card count is 1 again (5 complete). Then control-openhands browser goto /mcp, control-openhands browser click 'testid=mcp-server-detail-qa_f02_mcp', control-openhands browser click 'testid=mcp-custom-editor-delete', control-openhands browser click 'testid=confirmation-modal >> testid=confirm-button' and control-openhands browser reload; testid=mcp-installed-empty is back and the card reads 4 complete.

Setup guideF02.super-admin-setup-guideBlocked

Scenario F02--setup-guide · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Local: control-openhands browser count 'testid=super-admin-setup-guide' is 0 at desktop and phone, browser count 'testid=sidebar-onboarding-checklist' is 1, and control-openhands browser network --filter setup-state reports total 0. The positive path is blocked locally: it needs an OHE backend with ENABLE_SUPER_ADMIN whose /api/admin/setup-state returns a guide_org_id, guide_dismissed false and at least one unfinished required step, signed in as the first Super Admin.

Expect

on an OpenHands Enterprise (cloud) backend with ENABLE_SUPER_ADMIN, the first Super Admin (/me permissions include manage_super_admins) sees a floating Setup guide panel in the lower-right corner with n/4 progress, the steps Add an LLM, Choose an automation template, Add an integration, Invite users and Optional: SAML / instance, a Next: <step> status and a Start link for that step (the positive Enterprise path remains unverified here). Close collapses it to a pill that reopens it. While the guide loads or shows, the Getting started card is hidden. Local backends never show it and make no /api/admin/setup-state request (#17969).

Exact CLI recipe & bug checks

Local: control-openhands browser count 'testid=super-admin-setup-guide' is 0 at desktop and phone, browser count 'testid=sidebar-onboarding-checklist' is 1, and control-openhands browser network --filter setup-state reports total 0. The positive path is blocked locally: it needs an OHE backend with ENABLE_SUPER_ADMIN whose /api/admin/setup-state returns a guide_org_id, guide_dismissed false and at least one unfinished required step, signed in as the first Super Admin.

Setup tourF02.super-admin-setup-tourBlocked

Scenario F02--setup-tour · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Open /?setup_tour=first-automation.

Expect

for the two setup steps done in Canvas (Choose an automation template, Add an integration), the guide walks the Super Admin through the page with a guided tour (.oh-setup-tour-popover with Back / Next / Done): the template step points at the recommended-automations section (a stop with no footer: no Back, Next or 1/2, #18243), then the setup dialog; the integration step at the MCP library on /mcp (mcp-marketplace-section, "Pick a server from the library"), then the install dialog (#18261). A plain click on a Canvas step's row in the guide starts that step's tour and closes the panel (a modifier click follows the link), and while the tour waits for its next stop's element it hides its popover and overlay, so it never covers another dialog (#18261). Finishing the guide's next step in Canvas opens the step after it the way Start does (a Canvas step's tour or page; an enterprise step reopens the guide to point at Start, or navigates on a locked-Cloud canvas). An enterprise page that links back with ?setup_tour=<step id> starts that step's tour once and drops the parameter. Local backends ignore ?setup_tour= (no tour, no guide, the parameter stays) (#18138). The positive path is blocked here, with the same Enterprise prerequisite as the setup guide above.

Exact CLI recipe & bug checks

Local, at desktop and phone: run control-openhands browser network --clear, control-openhands browser goto '/?setup_tour=first-automation', wait about 6 s, then control-openhands browser count '.oh-setup-tour-popover' and browser count 'testid=super-admin-setup-guide' are 0, browser count 'testid=home-screen' is 1, browser url still ends in ?setup_tour=first-automation, and browser network --filter setup-state reports total 0. The tour itself is blocked with the same Enterprise prerequisite as the guide.

Update tileF02.update-tileMapped behavior

Scenario F02--update-tile · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Open /settings/app.
  2. Do
    Choose “Agent canvas update toggle”.
  3. Do
    Choose “Agent canvas update check”.
  4. Do
    Choose “Close agent canvas update modal”.

Expect

when npm latest is newer than the running version, a New version tile (agent-canvas-version-tile) opens an update modal with the npm and Docker commands. The tile is never shown in locked-Cloud mode.

Exact CLI recipe & bug checks

The tile is blocked in an up-to-date checkout or without registry access. Check with control-openhands browser count 'testid=agent-canvas-version-tile'. When the count is 1, click it; the modal has agent-canvas-update-command-npm, agent-canvas-update-command-docker and agent-canvas-update-check-button. The manual check runs either way: on /settings/app (control-openhands browser goto /settings/app; the previous bullet ends on /mcp), testid=agent-canvas-update-badge reads Up to date (or New version), control-openhands browser click 'testid=agent-canvas-update-toggle' opens agent-canvas-update-modal, and control-openhands browser click 'testid=agent-canvas-update-check-button' reports the result in agent-canvas-update-status (You're running the latest version. What's new when current). Close it with control-openhands browser click 'testid=close-agent-canvas-update-modal'.

Error toastF02.error-toastsMapped behavior

Scenario F02--error-toast · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Open /conversations/00000000-0000-0000-0000-000000000001.
  2. Wait
    Wait for the element identified in the CLI recipe to appear.
  3. Wait
    Wait for “This conversation does not exist” to disappear.
  4. Do
    Choose “App settings screen” / “Sound Notifications”.
  5. Do
    Choose “Submit”.

Expect

failed requests show a top-right error toast with the product or server message, and the toast closes by itself. Toasts stay readable in every colour theme.

Exact CLI recipe & bug checks

Run control-openhands browser goto /conversations/00000000-0000-0000-0000-000000000001 and control-openhands browser wait-text 'This conversation does not exist'. The URL becomes /conversations, and control-openhands browser screenshot --feature F02.error-toasts --name missing-conversation shows a top-right error toast. It is the only toast: control-openhands browser toasts lists just the "This conversation does not exist, or you do not have permission to access it…" text, and control-openhands browser toasts --history has no entry containing this UI does not understand. control-openhands browser wait 'text=This conversation does not exist' --state hidden passes within 30 s. Light theme: arrange control-openhands browser eval "localStorage.setItem('openhands-color-theme','light-plus')", repeat the goto, and read control-openhands browser eval "(()=>{const t=[...document.querySelectorAll('[role=status]')].find(e=>e.textContent.includes('does not exist'));return getComputedStyle(t).color+' on '+getComputedStyle(t.closest('div[style]')).backgroundColor})()": rgb(31, 31, 31) on rgb(229, 229, 229): every toast uses the theme's high-emphasis ink (--oh-contrast) on its surface (the default theme reads rgb(255, 255, 255) on rgb(49, 49, 49)). A success toast reads the same: save any change on /settings/app (for example control-openhands browser click 'testid=app-settings-screen >> text=Sound Notifications', control-openhands browser click 'testid=submit-button', then toggle it back and save again) and read the Settings saved toast the same way: rgb(31, 31, 31) on rgb(229, 229, 229). Solarized Light (solarized-light) gives rgb(0, 43, 54) on rgb(230, 223, 204) for both toasts. Restore with browser eval "localStorage.removeItem('openhands-color-theme')".

Check for errorsF02 · setup / cleanupSupport step

Scenario F02--check-for-errors · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Run control-openhands browser errors --app-only after each group; it reports pageErrors 0 and appErrors 0. External registry.npmjs.org and cdn.simpleicons.org failures are sandbox noise.

Expect

Complete this support step before continuing to the next scenario.

Exact CLI recipe & bug checks

Run control-openhands browser errors --app-only after each group; it reports pageErrors 0 and appErrors 0. External registry.npmjs.org and cdn.simpleicons.org failures are sandbox noise.

RestoreF02 · setup / cleanupSupport step

Scenario F02--restore · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Setup
    Use the desktop viewport.

Expect

Complete this support step before continuing to the next scenario.

Exact CLI recipe & bug checks

Leave the sidebar expanded, unpinned, with the checklist shown and expanded, at browser viewport desktop.

Existing conversations while collapsedF02.sidebar-collapseKnown failure

Scenario F02--existing-conversations-while-collapsed · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do — reading outline

  1. Do
    Choose “Sidebar collapse toggle”.
  2. Do
    Hover over “OpenHands Logo”.
  3. Do
    Choose “Sidebar collapse toggle”.

Expect

the chevron collapses the rail to a 60 px icon rail with hover tooltips, a Settings icon and a backend icon with a status dot that opens a backend popover. The checklist is hidden while collapsed. The state survives a reload. To expand, click the chevron that appears when you hover the logo, or click empty rail space.

Known bug observations

Known failure (reproduced 2026-10-12, #15662): the count is 0, and the rail has no chooser for existing conversations; expansion is required. Restore with control-openhands browser hover 'role=link[name="OpenHands Logo"]' and control-openhands browser click 'testid=sidebar-collapse-toggle'.

Exact CLI recipe & bug checks

With at least one sidebar conversation, run control-openhands browser click 'testid=sidebar-collapse-toggle', control-openhands browser snapshot and control-openhands browser count 'testid=conversation-panel'. Known failure (reproduced 2026-10-12, #15662): the count is 0, and the rail has no chooser for existing conversations; expansion is required. Restore with control-openhands browser hover 'role=link[name="OpenHands Logo"]' and control-openhands browser click 'testid=sidebar-collapse-toggle'.

Alert bannerF02.alert-bannerBehavior contract

Scenario F02--contract-f02-alert-banner · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do

This behavior has no separately named recipe in this snapshot. Use the family’s entry points and the contract below; the page does not invent a replay.

Expect

when the server config reports maintenance, faulty models or an error message, a dismissible banner (alert-banner) appears at the top of the content area.

Settings 404 modalF02.settings-404-modalBehavior contract

Scenario F02--contract-f02-settings-404-modal · Permalink · Source

Given

Use F02’s prerequisites and the common setup. Follow the family’s order when a script uses an earlier fixture or says “as above”.

Do

This behavior has no separately named recipe in this snapshot. Use the family’s entry points and the contract below; the page does not invent a replay.

Expect

if the backend's settings return 404, the LLM settings modal opens by itself. Other settings fetch errors show a toast.

Family notes, prerequisites for known issues & limits
  • The rail animates its width for 200 ms. A bbox taken right after the collapse click reads an intermediate width (about 70); measure after browser reload.
  • browser url straight after clicking Customize can still read /customize; desktop redirects to /mcp a moment later. Use browser wait-url '/mcp$'.
  • /settings redirects to /settings/agents on desktop but shows the settings menu on phone. That redirect also marks the checklist's Customize your agent item done, so visiting Settings by any route completes it. The sidebar Customize link (/customize) does not.
  • The pin toggles are hidden until hover (visible is false), except a pinned row's toggle, which stays visible. They exist only on the expanded rail.
  • The two desktop elements share the label Sidebar navigation, and settings pages add a second complementary landmark, so role=complementary is ambiguous. Use aside[data-collapsed] for the desktop rail and testid=sidebar-mobile-drawer for the drawer.
  • HeroUI tooltips (the collapsed rail and checklist previews) often stay closed on the first browser hover after a navigation. Hover a neighbor first, then the target, and browser wait for the tooltip. Never count it right away.
  • When collapsed, the expand chevron is opacity-0 pointer-events-none until the rail is hovered. A forced click on it lands on the logo link and does nothing; hover the logo first.
  • With the full list open, the command-menu panel covers the viewport center, so clicking the backdrop button by selector only works after a filter shortens the list (type secr first). control-openhands browser mouse-click 1300 500 hits the desktop backdrop with any list length.
  • The new-tab path works with browser click ... --button middle and with --modifiers Control (or Meta). The phone drawer's backdrop has no handle; browser mouse-click 350 400 clicks it.
  • Escape closes one layer at a time (#18044): with the command menu open over the phone drawer, the first Escape closes the menu and the second closes the drawer. Focus goes back to whatever had it when the menu opened: right after browser goto /conversations that is the composer (chat-input takes focus on load), and on /settings/app it is <body>.
  • Toggle sidebar at phone width flips the stored desktop state without any visible change. Expand the rail again after returning to desktop.
  • Typing does not reset the command menu's selection. The active option keeps its index, cut down to the shorter list, from the last ArrowUp/ArrowDown or hover, and a pointer resting where the list opens hovers the option under it. A term with several matches can then run a later one on Enter: after two ArrowDown presses, typing LLM profiles (LLM profiles and Model Router) selects Model Router. Before opening the menu for an Enter check, rest the pointer with browser hover 'testid=command-menu-trigger', and read aria-activedescendant before Enter when a term matches several items. Repro candidate, not yet filed.
  • The command menu's LLM profiles item uses a magnifier icon (lucide-search, the same icon as the menu's search field).
  • Dismissing the checklist with its X and the App settings switch write the same browser-local flag, so either one undoes the other. Clicking Join the OpenHands Slack counts as joining and opens an external tab you must close.
  • Registry access depends on the sandbox. Where the browser cannot reach registry.npmjs.org (ERR_CERT_AUTHORITY_INVALID), the update check reports Couldn't check for updates; that is the environment, not the product. Where it can, the badge reads Up to date and the check says You're running the latest version.
  • Adding a custom MCP server tests the connection first and refuses an unreachable one (Could not reach the server..., or Connection failed: McpError: Connection closed for uvx mcp-server-time here), so the all-complete recipe uses the local stdio fixture.

Before you start

Use an OpenHands checkout at the source revision, with Node 24+, installed npm dependencies, uv / uvx, and a supported Chromium browser. The verification skill is the complete setup contract.

export PATH="$PWD/.agents/skills/verify-openhands/scripts:$PATH"
export OH_VERIFY_RUN=$(control-openhands launch --new --print-run)
control-openhands doctor
control-openhands onboard --skip
# Configure a model only for a scenario that needs one:
control-openhands llm preset deepseek
# When the run is complete:
control-openhands stop

F01 walks onboarding instead of skipping it. No-model checks run before model configuration. Keep OH_VERIFY_RUN set so commands address your own run. Desktop is 1440 × 1000; phone is 390 × 844. Model-backed checks need the configured provider key and budget.

Recipes run in source order within each family and can share fixtures. The page preserves that order; “as above” is a dependency on an earlier case. Setup commands and API writes arrange state. They do not prove a UI path. Follow the family cleanup steps.

A known failure preserves the intended expectation beside the observed defect. Executable known-bug blocks use xfail for a reproduced symptom and xpass when it stops reproducing. Cloud accounts, enterprise capabilities and other unavailable prerequisites remain explicit. “Not run” is different from “blocked”.

The maintained map describes application behavior at its pinned revision. Once a fix is verified in the application version under test, remove the obsolete failure note and keep the normal expectation. Dated evidence belongs in the backfill ledger.

Read the full map index and coverage boundaries, the CLI guide, or the earlier illustrated edition. The verification approach adapts Lauren Tan’s (@poteto) pstack verification-skill generators; attribution and adaptation.