Skip to content

fix(desktop): expand Computer Use semantic UI coverage - #2640

Open
hqhq1025 wants to merge 3 commits into
apache:mainfrom
hqhq1025:codex/cu-a11y-full-coverage
Open

fix(desktop): expand Computer Use semantic UI coverage#2640
hqhq1025 wants to merge 3 commits into
apache:mainfrom
hqhq1025:codex/cu-a11y-full-coverage

Conversation

@hqhq1025

@hqhq1025 hqhq1025 commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Summary

  • expose one primary main landmark per Electron window and stable named regions for the measured conversation, module, settings, dialog, workbar, generated-content, and runtime surfaces
  • give repeated task, message, answer, tool-output, memory, main-chat, and side-chat actions localized human-readable identities without speaking opaque storage IDs or turn-local pseudo-ordinals
  • share one test-only Chromium AX audit across Storybook and Electron E2E; reject empty exposed trees, unnamed or same-scope ambiguous actions, multiple main landmarks, unnamed dialogs, and missing checked/selected/expanded/value state
  • execute and AX-audit the complete source-defined Storybook catalog, enforce a critical Computer Use story inventory, modal focus ownership, hidden/inert focus exclusion, and action-specific final states
  • cover active xterm, Runtime Host SSH, Browser chrome, HTML artifact iframe, remote directory navigation, dialogs, confirmations, and observable action effects
  • run the production Browser WebContentsView observe -> semantic ref -> fill/click -> effect smoke in CI, while reusing the existing E2E build to avoid duplicate workspace compilation
  • keep production cost to native HTML/ARIA and localized render-time copy: no production DOM/AX walker, observer, polling loop, OCR/model load, runtime dependency, or eager asset load

Scope

This PR improves Computer Use semantic operability: target identity, state, focus, action discovery, and effect verification across the measured source-defined and runtime states.

It does not claim complete WCAG conformance or complete assistive-technology behavior. Live-region and announcement completeness are not measured by this gate. Native macOS AX and Windows UIA packaged-app spot checks remain release gates, and third-party page markup, Chromium's PDF plugin, native file dialogs, and OS permission dialogs remain platform/provider owned.

Review-fix delta

  • dropped per-turn message ordinals from spoken copy/edit names; bounded visible excerpts plus absolute timestamps remain the human differentiator
  • added an optional ToolCodeBlock.actionIdentity contract and scoped Astryx CodeBlock copy labels to each owning tool call, including connector fallback output
  • made nested AstryxLocaleProvider scopes additive by composing ambient messages, direction, and overrides before applying the inner scope
  • moved tool and memory accessible-name composition into locale copy tables
  • replaced filtered-list memory ordinals with stable title, origin, and creation-time context; the Storybook interaction asserts the name survives filtering
  • repaired the task-actions story to open the real row menu and fail loudly when the selector or final state regresses
  • aligned the capability-audit story with production's named region instead of adding a second main
  • documented why the import-settings test requires a minimal getComputedStyle shim: Astryx 0.4 Spinner reads inherited canvas color

These are deliberate contract changes rather than additive compatibility layers: the message copy function signature loses the incorrect ordinal argument, Button keeps a full accessible label while children preserve short visible copy, and Storybook uses fixture identity only in test code.

Verification

Current rebased head (e7ba0cc90, based on main@de091d638):

  • node --test scripts/ax-tree-audit.test.mjs (11 passed)
  • npm --workspace @maka/ui test (187 passed, including nested provider composition)
  • npm --workspace @maka/desktop run typecheck
  • npm --workspace @maka/desktop run build-storybook
  • npm --workspace @maka/desktop run smoke:storybook (149 stories, including play functions and AX audits)
  • node --test apps/desktop/dist/main/__tests__/import-tasks-settings-page.test.js (15 passed)
  • git diff --check

The branch's broader Electron accessibility, Browser semantic-action, and packaging checks remain in CI.

AI use

Select exactly one:

  • No generative tool made a substantive contribution
  • Generative tooling made a substantive contribution

Tool(s) and scope: Codex audited the accessibility surfaces, implemented semantic and test changes, resolved review findings, rebased the branch, updated documentation, and ran verification. The commits include the required Generated-by: Codex trailer.

Checklist

  • Tests cover the change and fail on missing or ambiguous Computer Use semantics
  • Typecheck, unit, Storybook render/interaction, and AX audit checks pass locally

Does this PR entail a change in behavior?

  • Yes - described under Summary and Review-fix delta
  • No

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch 2 times, most recently from 867d893 to 5cf74d5 Compare August 10, 2026 10:30
@hqhq1025
hqhq1025 marked this pull request as ready for review August 10, 2026 12:46
@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch 3 times, most recently from c0547c1 to 9d35265 Compare August 17, 2026 06:33
@coderabbitai

coderabbitai Bot commented Aug 17, 2026

Copy link
Copy Markdown

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review
📝 Walkthrough

What problem this solves

This PR completes desktop Computer Use accessibility coverage. It adds stable landmarks, localized accessible names, correct ARIA state, modal focus ownership, and hidden-surface focus exclusion. It covers settings, modules, conversations, dialogs, overlays, workbar panels, generated content, runtime surfaces, and browser interactions.

Source of truth

The PR extends the existing source of truth. Renderer components provide native HTML, ARIA semantics, and localized copy. Storybook and Electron tests inspect the resulting Chromium accessibility tree. The PR does not add a runtime DOM walker, observer, repair loop, OCR, model loading, or runtime dependency.

Solution size and complexity

The changes form the smallest coherent solution shown by the supplied diff. Production code adds only the semantics and copy required for accessible states. The AX-tree auditor, Storybook state coverage, Electron E2E coverage, browser smoke test, and CI change detection validate both source-defined semantics and rendered behavior.

Simplification opportunities

No safe deletion or simplification is evident. Removing the AX-tree auditor or the new Storybook and Electron states would weaken regression coverage. The added copy properties support required landmark, conversation, control, and scroll-action labels.

Complexity delta

  • Authorities: The renderer remains the semantic authority. No runtime repair authority was added.
  • States: Coverage adds dialogs, QR flows, confirmations, scheduled tasks, narrow layouts, terminals, browser panels, artifact previews, and remote directory registration.
  • Branches: Storybook smoke execution adds story-specific viewport selection and final-state focus and AX-tree validation.
  • Configuration: AstryxCopy and ConversationCopy gain required accessibility properties. CI change detection includes the AX auditor and browser observe-act smoke test.
  • Public surface: Copy contracts gain required properties and formatters. Storybook modules gain accessibility stories.
  • Test maintenance: The PR adds shared AX-tree auditing, audit unit tests, Storybook stories, Electron accessibility coverage, and browser interaction polling.
  • Removed complexity: Extra main landmarks are removed in favor of named section regions.

Test and copy-contract maintenance increases. This increase is necessary for the stated coverage. Total maintenance complexity remains justified.

Risks and validation

The PR changes user-visible accessibility behavior through landmark structure, region names, control names, focus behavior, and localized text. Material changes in these areas require independent human review under repository policy.

The PR changes the AstryxCopy and ConversationCopy public contracts. Material public-contract changes require independent human review under repository policy.

The Storybook smoke flow changes viewport selection and validates the full CDP accessibility tree. The Electron lane adds browser WebContentsView observe-act smoke coverage. waitForPageValue adds timeout-based polling to the browser smoke test for asynchronous effect verification.

The objectives report passing unit, typecheck, Storybook, Playwright, browser smoke, formatting, and AX audit checks. Native macOS AX and Windows UIA packaged-app checks remain release gates. Required-check status is unverified here because direct check output was not provided.

Review-relevant risks

  • Accessibility semantics, focus behavior, and localized copy affect user-visible behavior. Material changes require independent human review under repository policy.
  • AstryxCopy and ConversationCopy gain required public properties and formatter contracts. Material changes require independent human review under repository policy.
  • Storybook and Electron CI coverage changes affect release validation. Material changes to release gates require independent human review under repository policy.
  • No security, licensing, or governance effect was identified in the current diff.

The person performing the merge reviews the final diff. A maintainer makes the final determination.

Walkthrough

Changes

The PR adds native accessibility regions and localized labels across renderer pages. It adds Storybook and Playwright coverage for overlays, settings, conversations, workbar panels, runtime surfaces, and narrow layouts. It also adds accessibility-tree validation to Storybook and Electron smoke checks.

Accessibility semantics and validation

Layer / File(s) Summary
Semantic contracts and localized labels
docs/computer-use-foundation-contract.md, docs/computer-use-ui-coverage.md, packages/ui/src/astryx-copy.ts, packages/ui/src/astryx-i18n.tsx, packages/ui/src/conversation-copy.ts, apps/desktop/src/renderer/locales/conversation-copy.ts
Defines renderer accessibility requirements and adds localized labels for app-shell, conversations, sessions, message actions, and scroll controls.
Renderer landmark and control semantics
packages/ui/src/chat-view.tsx, packages/ui/src/module-pages.tsx, packages/ui/src/skills-panel.tsx, apps/desktop/src/renderer/mcp-page.tsx, packages/ui/src/chat-surface-layout.tsx, packages/ui/src/chat-turn.tsx, apps/desktop/src/renderer/app-shell.tsx, apps/desktop/src/renderer/quote-companion-panel.tsx, apps/desktop/src/renderer/settings/memory-entry-list.tsx, packages/ui/src/session-history-list.tsx, packages/ui/src/tool-activity/tool-result-preview.tsx
Replaces duplicate main containers with named regions and adds localized or identifier-specific accessible labels to controls.
Storybook accessibility states
apps/desktop/stories/accessibility-overlays.stories.tsx, apps/desktop/stories/accessibility-runtime-surfaces.stories.tsx, packages/ui/stories/accessibility-dialogs.stories.tsx, apps/desktop/stories/module-hubs.stories.tsx
Adds overlay, dialog, QR-flow, runtime-surface, and narrow scheduled-task stories with interaction checks.
Accessibility-tree validation
scripts/ax-tree-audit.mjs, scripts/ax-tree-audit.test.mjs
Adds shared checks for unnamed controls, landmark and dialog problems, missing state, and duplicate actionable controls.
Electron coverage and CI wiring
apps/desktop/e2e/accessibility-coverage.spec.ts, scripts/storybook-visual-smoke.mjs, .github/workflows/ci.yml, scripts/ci-test-plan.mjs, apps/desktop/package.json, apps/desktop/scripts/browser-observe-act-smoke.mjs, apps/desktop/e2e/sidebar-project-row.spec.ts
Runs accessibility coverage across desktop surfaces and updates Storybook, Browser WebContentsView, and CI smoke execution.

Estimated code review effort: 4 (Complex) | ~45 minutes

Merge Risk: 🟡 Moderate · up to 006d0

The accessibility expansion adds semantic landmarks, labels, and automated audits, but the current head can leave browser validation hanging when a read stalls, while narrow-viewport coverage and ambiguous or overly revealing accessible names remain unresolved. Merge should wait for these bounded issues to be fixed or explicitly accepted by the owners.

Sequence Diagram(s)

sequenceDiagram
  participant Storybook
  participant Chromium
  participant AccessibilityTreeAudit
  participant ElectronE2E
  Storybook->>Chromium: Render stories and complete play steps
  Chromium->>AccessibilityTreeAudit: Provide full accessibility tree
  AccessibilityTreeAudit-->>Storybook: Return audit findings
  ElectronE2E->>Chromium: Navigate desktop accessibility surfaces
  Chromium->>AccessibilityTreeAudit: Provide runtime accessibility tree
  AccessibilityTreeAudit-->>ElectronE2E: Return audit findings
Loading
🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Ai Use Disclosure ✅ Passed The PR selects generative tooling, names Codex and its scope, and its sole introduced commit has the consistent standalone trailer Generated-by: Codex.
Description check ✅ Passed The description includes the required Summary, Verification, AI use, and Checklist sections with specific scope, test results, AI disclosure, and remaining release gates.
Title check ✅ Passed The title clearly and concisely summarizes the primary change: completing Computer Use accessibility coverage for desktop.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch from 9d35265 to 2711e16 Compare August 17, 2026 06:35
@hqhq1025
hqhq1025 requested a lite review from Copilot August 17, 2026 06:36

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick comments (1)
packages/ui/src/module-pages.tsx (1)

25-30: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Use one source for the Skills region label.

When hubHeader is absent, SkillsPage passes copy.skills to this fallback at Line [69]. The loaded SkillsModuleMain uses getSkillsCopy(locale).page.title at packages/ui/src/skills-panel.tsx Line [575]. If these fields differ, the region name changes during lazy loading.

Compute one label and pass it to both states, or verify that the two fields are contractually identical and keep one source of truth.

As per path instructions, keep the loading and loaded semantic label at one existing source of truth instead of maintaining parallel copy fields.

Source: Path instructions


ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 25638710-cdac-4a05-b9d5-66dc7579209f

📥 Commits

Reviewing files that changed from the base of the PR and between 5ef39c3 and 9d35265.

📒 Files selected for processing (13)
  • apps/desktop/e2e/accessibility-coverage.spec.ts
  • apps/desktop/src/renderer/mcp-page.tsx
  • apps/desktop/stories/accessibility-overlays.stories.tsx
  • apps/desktop/stories/module-hubs.stories.tsx
  • docs/computer-use-foundation-contract.md
  • packages/ui/src/astryx-copy.ts
  • packages/ui/src/astryx-i18n.tsx
  • packages/ui/src/chat-view.tsx
  • packages/ui/src/conversation-copy.ts
  • packages/ui/src/module-pages.tsx
  • packages/ui/src/skills-panel.tsx
  • packages/ui/stories/accessibility-dialogs.stories.tsx
  • scripts/storybook-visual-smoke.mjs

Included review availability: Your plan includes up to 3 reviews per rolling hour; 1 remains after this review.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR strengthens Desktop “Computer Use” accessibility coverage by aligning renderer semantics (single main landmark with named sub-regions), localizing Astryx app-shell accessibility strings, and adding/expanding automated AX-tree audits in both Electron e2e and Storybook smoke.

Changes:

  • Replace nested module/chat <main> landmarks with named regions (<section aria-label=...> / role="region") to enforce “one main per window”.
  • Extend Storybook smoke to run play functions, run narrow stories at a narrow viewport, and CDP-scan the full AX tree for unnamed actionable nodes + multiple main landmarks.
  • Add new Storybook fixtures and a new Electron e2e spec to validate actionable AX node naming and localized skip-link behavior across key surfaces.

Reviewed changes

Copilot reviewed 13 out of 13 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
scripts/storybook-visual-smoke.mjs Runs Storybook plays, sets narrow viewport for *narrow* stories, and audits the Chromium AX tree via CDP.
packages/ui/stories/accessibility-dialogs.stories.tsx Adds “final state” dialog stories (rename, scheduled task create, Mermaid fullscreen) for AX coverage.
packages/ui/src/skills-panel.tsx Changes nested main to a named region to avoid multiple main landmarks.
packages/ui/src/module-pages.tsx Updates module wrappers/fallbacks from main to named regions to keep a single app-shell main.
packages/ui/src/conversation-copy.ts Adds localized ARIA labels for new-task surface region and per-conversation region naming.
packages/ui/src/chat-view.tsx Converts chat surface wrapper from main to named regions for proper landmark structure.
packages/ui/src/astryx-i18n.tsx Adds Astryx app-shell a11y string overrides (skip link + mobile navigation) for zh locale.
packages/ui/src/astryx-copy.ts Extends Astryx zh copy with app-shell strings used by the override map.
docs/computer-use-foundation-contract.md Documents the renderer semantic source contract and the 3-layer validation approach.
apps/desktop/stories/module-hubs.stories.tsx Adds a narrow Scheduled Tasks story to exercise below-breakpoint semantics.
apps/desktop/stories/accessibility-overlays.stories.tsx Adds overlay stories (side-chat close, onboarding QR, WeChat QR) for AX-tree coverage.
apps/desktop/src/renderer/mcp-page.tsx Changes nested main to a named region to avoid multiple main landmarks.
apps/desktop/e2e/accessibility-coverage.spec.ts Adds Electron AX-tree coverage asserting named actionable controls across settings, modules, overlays, composer, and workbar.

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread apps/desktop/e2e/accessibility-coverage.spec.ts Outdated
@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch 2 times, most recently from d0cf0b7 to 1040c4f Compare August 17, 2026 06:44
@hqhq1025 hqhq1025 added the copilot-skip Skip automatic Copilot review request label Aug 17, 2026
@hqhq1025
hqhq1025 marked this pull request as draft August 17, 2026 06:45
@hqhq1025
hqhq1025 marked this pull request as ready for review August 17, 2026 06:45
@hqhq1025 hqhq1025 removed the copilot-skip Skip automatic Copilot review request label Aug 17, 2026
@hqhq1025
hqhq1025 requested a lite review from Copilot August 17, 2026 06:55

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

scripts/storybook-visual-smoke.mjs:26

  • ACTIONABLE_AX_ROLES is duplicated here and in apps/desktop/e2e/accessibility-coverage.spec.ts. Because this list defines what the AX audits consider “actionable”, keeping two copies risks drift (e.g., one audit flagging nodes the other ignores). Consider extracting the role list + small helpers (axString) into a shared utility (or exporting from one place) so Storybook smoke and Electron e2e stay consistent.
const ACTIONABLE_AX_ROLES = new Set([
  'button',
  'checkbox',
  'combobox',
  'link',
  'menuitem',
  'menuitemcheckbox',
  'menuitemradio',
  'option',
  'radio',
  'searchbox',
  'slider',
  'spinbutton',
  'switch',
  'tab',
  'textbox',
  'treeitem',
]);

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch from 1040c4f to 74226a5 Compare August 18, 2026 07:03
@coderabbitai

coderabbitai Bot commented Aug 18, 2026

Copy link
Copy Markdown

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

@hqhq1025
hqhq1025 requested review from Astro-Han and a lite review from Copilot August 18, 2026 07:05

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch from 74226a5 to 536dc88 Compare August 18, 2026 08:04
@hqhq1025
hqhq1025 requested a lite review from Copilot August 18, 2026 08:06
@hqhq1025
hqhq1025 requested review from Astro-Han August 18, 2026 15:51
@hqhq1025

Copy link
Copy Markdown
Contributor Author

Follow-up verification for 95439ebe1 (rebased onto 62556ab04).

Addressed the Memory P2 and the deeper review findings:

  • restored visible Memory actions to 归档 / 恢复 while retaining bounded, collision-free AX identities;
  • fixed the Chinese action-group separator;
  • made settings-page E2E coverage match the authoritative 16-page navigation inventory exactly;
  • made the shared AX audit require disclosure state, cache scope identities, avoid superlinear subtree rescans, and keep full scope identity separate from bounded diagnostics;
  • made rename, scheduled-task, side-chat, and remote-directory stories verify real close/focus behavior; repaired remote-directory focus restoration;
  • bounded the browser effect read through withBrowserPage so a timed-out CDP action cannot continue on the shared connection;
  • wired the AX audit unit suite into the selected Storybook CI lane;
  • removed eight-character tool/memory identity collision risk.

Local verification on the final rebased head:

  • npm run build
  • npm run lint
  • npm run format:check
  • npm run typecheck
  • node --test scripts/ax-tree-audit.test.mjs (8 passed)
  • focused UI identity test (5 passed)
  • Storybook render + Chromium AX smoke (145 stories)
  • Electron accessibility E2E (3 passed, including all 16 settings pages and seven workbar panels)
  • embedded Browser observe→act→effect smoke (17/17)

Memory action

Before (accessible identity leaked into visible copy):

Memory action before

After (visible copy remains stable; identity stays AX-only):

Memory action after

Localized skip link

Before (base branch default English copy):

Skip link before

After (Chinese app-shell copy):

Skip link after

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The PR substantially improves semantic coverage and, importantly, keeps the production cost to native HTML/ARIA while centralizing the test-only audit. I found one false-negative in that shared gate and one non-blocking naming tradeoff. The first-principles fix is small: define an empty accessibility tree by exposed content, not by the presence of ignored CDP records; for repeated actions, prefer stable human-readable context over raw storage identities.

AI-assisted review disclosure: Codex verified these observations against the current head, the shared AX audit, Storybook and Electron E2E call sites, and localized action-name producers. Two independent reviewer-agent passes and an OpenCode Go DeepSeek V4 Flash (high) adversarial pass were used as inputs; broader test-scope claims without a concrete failure were discarded. No local tests were run.

中文复核

这个 PR 明显补强了语义覆盖,而且生产代码只使用原生 HTML/ARIA,把复杂度集中在测试审计层,方向很好。当前保留一个审计假阴性和一个不阻塞的命名取舍:空 AX tree 应按“没有 exposed 内容”判定,而不是只看 CDP 是否返回 ignored 记录;重复操作名称应优先使用稳定、可理解的上下文,而不是原始内部 ID。

本次为 AI 辅助审查:Codex 在最新 head 上核验共享 AX audit、Storybook/Electron E2E 调用点及本地化 action-name producer;另使用两次独立 reviewer 与一次 OpenCode Go DeepSeek V4 Flash(high)对抗审查,没有具体失败证据的宽泛测试范围指控已剔除。未运行本地测试。

Comment thread scripts/ax-tree-audit.mjs Outdated
Comment thread packages/ui/src/conversation-copy.ts Outdated
@Astro-Han

Copy link
Copy Markdown
Contributor

/agentic_review

@qodo-code-review

Copy link
Copy Markdown

Code Review by Qodo

🐞 Bugs (1) 📘 Rule violations (0) 📜 Skill insights (0)

Grey Divider


Action required

1. Overlay audit races dismissal 🐞 Bug ☼ Reliability
Description
Fix-now: after Escape, the test immediately opens the command palette and checks an unnamed dialog
locator, so an asynchronously closing keyboard-help dialog can satisfy the command-palette assertion
and be audited under the wrong surface. This makes the claimed command-palette coverage
nondeterministic and permits a real command-palette AX regression to pass.
Code

apps/desktop/e2e/accessibility-coverage.spec.ts[R91-94]

+  await page.keyboard.press('Escape');
+
+  await page.keyboard.press(process.platform === 'darwin' ? 'Meta+k' : 'Control+k');
+  await expect(page.getByRole('dialog')).toBeVisible();
Relevance

●●● Strong

Recent E2E precedents accept explicit waits for asynchronous UI transitions; PR #3057 confirms event
dispatch alone is insufficient.

PR-#3057
PR-#3160
PR-#3101

ⓘ Recommendations generated based on similar findings in past PRs

Evidence
The new test dispatches Escape and then the command shortcut without any disappearance assertion,
while both overlay hooks close by scheduling React state updates; the following generic role query
therefore does not prove which dialog is visible. The same event-dispatch-versus-committed-render
race was previously accepted as a bug pattern in PR #3057.

apps/desktop/e2e/accessibility-coverage.spec.ts[88-96]
apps/desktop/src/renderer/keyboard-help.tsx[50-64]
apps/desktop/src/renderer/command-palette.tsx[34-53]
PR-#3057

Agent prompt
The issue below was found during a code review. Follow the provided context and guidance below and implement a solution

## Issue description
The command-palette accessibility check can run before the keyboard-help dialog has finished closing, and its generic dialog locator can match the previous overlay.

## Issue Context
Wait for the specifically named keyboard-help dialog to be absent after Escape, then open and assert the specifically named command-palette dialog before auditing. This reuses Playwright's existing locator/expect synchronization; no new state, branch, configuration, or public surface is needed.

## Fix Focus Areas
- apps/desktop/e2e/accessibility-coverage.spec.ts[88-96]

ⓘ Copy this prompt and use it to remediate the issue with your preferred AI generation tools


Grey Divider

Context sources
✅ Web pages:
  +4 more
Review mode: 🧠 Deep: This is a broad, behavior-changing accessibility and CI effort spanning renderer semantics, localization, dialogs/focus, Storybook/E2E AX auditing, and a production WebContentsView smoke path, with many independent logic sites where redundant review could catch subtle regressions.

Grey Divider

Tip of the day
💡 Did you know, you can keep summaries lean with Finding overflow, which tucks the rest behind 'View more'

More tips ↗ | Customize Qodo ↗ | Qodo docs ↗

Grey Divider

Qodo Logo

Comment thread apps/desktop/e2e/accessibility-coverage.spec.ts Outdated

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the accessibility pass and the before/after evidence. I re-reviewed exact head 95439ebe1bf2653ad2cad78a641bb1e14d793ec7; the AI provenance and UI screenshot gates are satisfied, but the three existing unresolved threads remain current and actionable, so I am keeping this at COMMENT.

The two approval blockers are the existing P2 threads:

  • The AX-tree audit checks the raw source-node count, so an all-ignored tree reports zero exposed nodes but still passes. Please base the empty-tree failure on exposedNodes(sourceNodes).length and add an all-ignored fixture.
  • The E2E uses a generic dialog locator and does not wait for Keyboard Shortcuts to disappear before asserting the Command Palette. Please wait for the named Keyboard Shortcuts dialog to be hidden, then assert the named Command Palette dialog.

The existing P3 about UUID-like internal IDs in spoken copy/edit/answer labels is also still valid; a stable ordinal plus short human context would be preferable, with the internal ID retained only as data.

I did not duplicate any inline finding. The cancelled test_workspaces job also needs a green rerun before merge readiness.

AI-assisted review disclosure: OpenAI Codex performed the exact-head code, thread, screenshot, provenance, and CI analysis; I verified the reproduced AX-tree behavior, severity, deduplication, and live state before posting.

中文说明

当前三个未解决线程都仍有效。两个 P2 分别是:全 ignored 的 AX tree 会被错误放过;E2E 没等“键盘快捷键”对话框消失就用通用 dialog 断言“命令面板”。另一个 P3 是读屏标签暴露内部 UUID。截图和 AI provenance 已合规,但两个 P2 与 CI 重跑完成前不能批准。

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch from 95439eb to 676320c Compare August 20, 2026 07:07
@hqhq1025
hqhq1025 requested review from Astro-Han August 20, 2026 07:07
@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch 2 times, most recently from 1f49117 to 98f0f73 Compare August 20, 2026 07:24
@hqhq1025

hqhq1025 commented Aug 20, 2026

Copy link
Copy Markdown
Contributor Author

Final follow-up on head 8c7c74773, rebased onto current main c8f16b992:

  • The first post-review core CI run exposed a real regression from this patch: the answer toolbar duplicated the turn container’s existing data-turn-id, so the long-transcript virtualizer E2E counted one turn twice. The duplicate attribute and now-unused prop were removed; the existing turn container remains the single machine-identity owner.
  • The accessibility composer E2E now waits for the visible Send action to become enabled and for the deterministic visible backend reply before auditing the session surface. This replaces an under-specified async boundary without adding sleeps or weakening AX assertions.
  • All unresolved review threads are resolved. The branch has been rebased whenever main advanced; this head is based exactly on c8f16b992.

Verification of the product diff: UI tests 197/197; Desktop workspace tests 975/975; AX audit contract 11/11; CI planner 18/18; focused Electron accessibility 3/3; the previously failing prompt-rail E2E passes; browser observe→act→effect 17/17; Storybook render/AX smoke 149/149; lint, format, typecheck, and builds pass. The full core CI and dependency audit passed on the immediately preceding product-identical head; the current head only adds the latest upstream test fixes and has restarted those checks.

The separate Windows release lane remains affected by the repository-wide packaged-renderer CDP port race tracked and fixed in #3241: across three runs the same package passed upgrade verification on one attempt and failed CDP discovery at different packaged-renderer checkpoints on others, including logs where Chromium announced DevTools listening on a different port from the verifier poll. No Windows verifier or packaging code is changed by this PR, so that release-infrastructure fix is intentionally not duplicated here.

No production polling, global listener, dependency, or asset-loading path was added.

@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch 2 times, most recently from 89a0788 to 8c7c747 Compare August 20, 2026 08:14

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Posted in error — please disregard this review entirely. Its body and inline comments belong to #3255 and were sent here by a scripting mistake on my side. Nothing in it applies to this PR. Sorry for the noise; the actual review of this PR follows separately. The inline comments below have been rewritten to the same retraction.

Comment thread packages/core/src/provider-registry.ts Outdated
Comment thread packages/runtime/src/model-adapter.ts Outdated
Comment thread packages/runtime/src/model-runtime.ts Outdated
Comment thread packages/runtime/src/open-responses-compatibility.ts Outdated
Comment thread packages/runtime/src/ai-sdk-backend.ts Outdated
Comment thread packages/runtime/src/open-responses-compatibility.ts Outdated

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at 8c7c7477. (The head moved while I was reviewing; I confirmed every file this review touches is byte-identical to 89a0788e, so the force-push was a rebase onto main and the findings carry over unchanged.)

This earns the landmark and dialog-naming layer convincingly — I enumerated every <main> and role="main" in the tree at this head and the "one primary main per window" claim holds, including the mutual exclusion between the Astryx shell landmark and the settings surface (the shell goes aria-hidden/inert when obscured). The ChatSurfaceLayout and ToolOutputSurface call sites are complete. CSS is unaffected: every main reference is a class selector, none an element selector.

What it does not earn is the layer its title claims — "every actionable element has an unambiguous name" — and the new audit gate cannot demonstrate that it does. scripts/ax-tree-audit.mjs scopes its ambiguity check relatively: namedScope walks up three levels for a named ancestor and otherwise falls back to the first few text nodes of the subtree. Two buttons with byte-identical names pass as long as the surrounding prose differs. That is the mechanism by which the code-block copy buttons (inline) survive a fully green audit, and it is worth knowing before this gate is cited as evidence of coverage in future reviews.

The architectural note is about the copy seam. actionsAriaLabel and answerActionsAriaLabel changed from constants to functions — a signature change on a public copy contract. That is a fine change, but it silently breaks every exact-name selector downstream, and it has already broken one: session-list-panel.stories.tsx:139 still queries [aria-label="任务操作"] exactly, now matches nothing, and fails open through ?.. The PR body's non-additive-changes checklist says "described under Summary above", but this signature change, the Button label/children switch in MemoryEntryList, the story-id viewport heuristic in storybook-visual-smoke.mjs:123, and the weakening of chat-turn-steering-order.test.ts from markup counting to textContent counting are not individually called out. The copy-contract signature change in particular belongs in the body.

Two contract observations rather than findings: removing embed=true from the Storybook smoke means play functions now execute across the whole catalogue in CI — stated in the body, and the largest behavioural change here; and e2e/accessibility-coverage.spec.ts imports ../../../scripts/ax-tree-audit.mjs across a workspace boundary that apps/desktop/package.json does not declare, compensated for in ci-test-plan's E2E_DRIVING_SCRIPTS. Both look deliberate.

Reviewed with Claude Opus as an analysis assistant. Every claim above and below was verified against the source at this head — including the Astryx dist output for the CodeBlock and Button naming behaviour — except where a finding states otherwise. No test run was performed.

Apologies for the retracted review above: an unrelated PR's comments were posted here by a scripting mistake on my side and have been rewritten as retractions.

Comment thread packages/ui/src/chat-turn.tsx Outdated
Comment thread packages/ui/src/tool-activity.tsx
Comment thread packages/ui/src/conversation-copy.ts
Comment thread docs/computer-use-ui-coverage.md
Comment thread apps/desktop/src/renderer/settings/memory-entry-list.tsx Outdated
Comment thread packages/ui/src/tool-activity/tool-result-preview.tsx Outdated
Comment thread packages/ui/src/tool-activity/tool-result-preview.tsx
Comment thread apps/desktop/src/main/__tests__/import-tasks-settings-page.test.ts
@hqhq1025
hqhq1025 force-pushed the codex/cu-a11y-full-coverage branch from 8c7c747 to 22af3b7 Compare August 20, 2026 08:40
@hqhq1025 hqhq1025 changed the title fix(desktop): complete Computer Use accessibility coverage fix(desktop): expand Computer Use semantic UI coverage Aug 20, 2026
@hqhq1025
hqhq1025 requested review from Astro-Han August 20, 2026 08:42

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at 22af3b72. All eight findings from my previous round are fixed, most of them more thoroughly than I asked. One new P3, inline.

  • P1, per-turn message ordinal — fixed by deletion, which was the better of the two options I offered. messageNumber is gone from UserMessageBody, MessageCopyButton, ConversationSegment, splitTimelineAtUserMessages, and from messageActionAriaLabel's signature in both locales. Excerpt plus timestamp carries the disambiguation on its own, and no false position is asserted any more.
  • P2, code-block copy buttons all named alike — fixed, and extended past what I flagged. outputActionIdentity now reaches ToolCodeBlock on all four branches and LoadToolResultPreview, which I had missed. Implementing it as scoped @astryx.codeBlock.* locale overrides rather than a new prop on the Astryx component is the right seam.
  • P2, silently broken story selector — fixed properly. [aria-label$="任务操作"], plus the fixture now throws when the row or the menu button is missing instead of no-opping through ?., plus a new ActiveTaskActionsOpen story whose play waits for the menu and asserts a menuitem by name. The opened-menu nodes are now genuinely audited rather than counted as covered.
  • P2, "complete" vs. what the gate measures — resolved by narrowing the claim, which is the honest fix. The document is now "Computer Use Semantic UI Coverage", scopes "covered" to Computer Use operability, and states outright that live-region and announcement completeness are not measured and need separate accessibility testing. The PR title was narrowed to match.
  • P3, memory entry ordinal — fixed. memoryEntryActionIdentity composes title, origin label, and a stable timestamp (falling back to a content excerpt), so the name no longer moves when the list is filtered — and the 80-character truncation now carries an ellipsis.
  • P3, composed names bypassing the copy seam — fixed at both sites. copy.actionAriaLabel and entryActionAria live in the copy tables with per-locale punctuation ( vs : ), isomorphic to messageActionAriaLabel.
  • P3, unreachable props.kind fallback — removed. Still safe: the copy button only renders when command is non-empty, so actionIdentity cannot be empty.
  • P3, unexplained getComputedStyle stub — answered rather than deleted, which is the right outcome given the answer. The comment names Astryx 0.4's Spinner resolving its inherited canvas colour during render, so the stub is a real requirement and no longer reads as rebase residue.

The capability-audit-strip story that escaped the landmark sweep was also converted to <section> with a label, so the story tree's landmark shape matches production again.

I checked the one thing this approach could plausibly have broken: AstryxLocaleProvider merges {...base, ...scopedOverrides} rather than replacing, so wrapping a CodeBlock does not strip the rest of the Astryx locale bundle. What it does do is discard an ancestor's scoped overrides — see the inline note. Hook order is fine: useUiLocale and useMemo both run before the if (!props.code) return null early return.

Reviewed with Claude Opus as an analysis assistant. Every disposition above was verified by reading source at this head and diffing against the head I previously reviewed, including astryx-i18n.tsx's merge semantics; no tests or stories were executed.

Comment thread packages/ui/src/tool-activity/tool-code-block.tsx

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Re-reviewed at e7ba0cc9. The P3 from my previous round is fixed correctly. No remaining findings.

AstryxLocaleProvider now reads the ambient InternationalizationContext and merges base → inherited → scoped, so a nested provider is additive instead of rebuilding from the locale defaults. Two details make it a better fix than the minimum:

  • Spreading ambient.overrides into the returned map preserves the outer provider's entries for other locales, not just the active one.
  • Forwarding messages and dir when ambient.locale === locale means the inner provider no longer resets direction and catalog while inheriting overrides — which the narrow fix would have left broken.

I checked the case this could have regressed: with no provider above, useContext yields Astryx's default { locale: 'en', direction: 'ltr', messages: {} }, so ambient.locale cannot throw, and passing that same messages: {} through is exactly the shape resolve() already falls through from to the shipped English catalog. Isolated renders — markdown-body.test.ts mounts AstryxLocaleProvider directly — are unaffected.

The added test asserts the real property: an outer and an inner override both resolve in the inner subtree. That is the assertion that would have caught the original defect.

Reviewed with Claude Opus as an analysis assistant; verified by reading the change, the new test, and the Astryx dist context default at this head. No tests were executed.

@hqhq1025
hqhq1025 requested review from Astro-Han August 20, 2026 09:00

@Astro-Han Astro-Han left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving at e7ba0cc9. All eight findings from my first round were fixed, and the follow-up P3 about nested Astryx locale providers is fixed correctly too — the provider now inherits the ambient overrides and forwards messages/dir, with a test asserting that an outer and an inner override both resolve. Detail in the two previous reviews; nothing outstanding from my side.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants