Repository navigation
fix(console): announce danger feedback lines as alerts and pin the form refusals - #2931
Conversation
A feedback line that switches between a quiet hint and a refusal kept role=status in its danger and warning tones, against the status block rule (danger and warning are alerts). setStatusTone now keeps an announcing line's role in step with its tone, and the callers set the tone before writing the text, so a refusal is written into an alert. The fixed danger blocks for channel Secrets reload/unknown outcome and the plugin feedback and tool error lines are alerts too. The repository status line drops its redundant aria-live=polite so its alert role is assertive. Finding 2005, 2010.
Each migrated feedback line and notice now has its class, tone and role asserted where an existing test reaches it: the repository choices refusals and load failure, the loading hint on Retry, the unavailable and unapproved repository lines, the Secrets unavailable line, the stop and deletion notices, the channel drawer notice, the workspace explainer, the Slack directory error and the plugin selections feedback. A new channels test reaches the drawer's Dedicated execution refusal for an Agent read as Embedded. Finding 2006.
… blocks The 403 refusals of the authentication source form and the Repositories editor could go back to the grey, unfocused hint with every test green; only the preflight conflict was pinned. New tests pin, for each form: the API refusal as a focused danger alert, the unconfirmed Secret grant as a warning alert (also after the tab is rebuilt), the unknown outcome kept as a danger alert, the unfinished ChatGPT sign-in refusal, the next save's progress as a quiet status, and the edit and navigation resets. The Configuration editor's pre-save conflict is now checked to be written into an alert, and its progress, Cancel and navigation resets are pinned. The channel Secrets reload line and the plugin tool error are checked as alerts. Findings 2004, 2005, 2010.
|
🦞👀 Pull request received. I will update this pull request when review starts. ClawSweeper review completeClawSweeper finished reviewing this revision. The review result is being finalized. |
…l error a status Internal review nits: the Repositories editor and Configuration editor resets now set the tone before writing their guidance, as the refusals do. The plugin tool error stays role=status: the details pane is rebuilt on every redraw, so an alert would be announced again on each keystroke. The repository notes' no-role pins say why, and the plugin approvers helper no longer splits a comment from its test.
|
Codex review: needs maintainer review before merge. What this changesThis PR makes announcing danger and warning feedback use alert roles and adds browser coverage for refusals and status resets. Example: Saving an Agent's authentication source receives HTTP 403.
Review scores
ProductKind: Bug fix · Worth it: Yes · Fix scope: Complete Merge readiness✅ Ready for maintainer review Keep this PR open: it fixes a source-confirmed accessibility mismatch, and the earlier fixture finding is resolved with no remaining introduced code defect identified. Priority: P2 Before mergeNone. FindingsNone. Tests
Agent review detailsHow this fits togetherThe OCC console renders Agent editor feedback from validation and API outcomes; shared DOM helpers turn those outcomes into styled messages and accessibility announcements. flowchart LR
A[Agent editor action] --> B[Validation and API outcome]
B --> C[Feedback caller]
C --> D[Shared tone helper]
D --> E[DOM live region]
E --> F[Assistive technology]
Technical reviewBest possible solution: Keep announcement-role selection in the existing shared helper, with callers setting the tone before writing feedback. Do we have a high-confidence way to reproduce the issue? Pinned main leaves dynamically toned feedback at role=status, including authentication refusals; the relevant callers and existing alert contract establish the mismatch without executing target code. Is this the best way to solve the issue? The repair is appropriately centralized, preserves deliberately quiet nodes and plugin tool-error behavior, and avoids changing API or persistence contracts. AGENTS.md: found and applied where relevant. Codex review notes: model internal, reasoning medium; reviewed against f3a74292ab69. Provenance checked
TestingProof path: in-process harness. SecurityNone. EvidenceWhat I checked:
Review metrics
LabelsLabel changes:
Label justifications:
Rating scale6/6 🦀 challenger crab · 5/6 🦞 diamond lobster · 4/6 🐚 platinum hermit · 3/6 🦐 gold shrimp · 2/6 🦪 silver shellfish · 1/6 🧂 unranked krab. Overall follows the weaker of proof and patch quality; ✨ marks media proof (a screenshot, video, or linked artifact) that directly shows the changed behavior. WorkflowClawSweeper edits this one comment on every review. Comment HistoryReview history (1 earlier review cycle)
Reviewed October 19, 2026, 8:08 AM ET / 12:08 UTC (Revision 2). |
Review: the guard test rewrote a Dedicated Codex Agent's read as Embedded, a state the API never produces. It now creates an Embedded OpenClaw Agent and enables Slack through the Configuration API, which accepts it (Agent save and deploy are what refuse it), and asserts the drawer's refusal with no response rewritten.
|
@clawsweeper re-review |
|
🦞👀 Re-review progress:
|
Problem
bughunt-127 found the refusal blocks #2912 and #2923 introduced only partly pinned, and some still announced as statuses.
role=statusin several places, against the design language (danger and warning blocks arerole=alert): the authentication source and Repositories editor feedback lines, the repository picker's status line when it turns danger, the Secret picker's "Secrets unavailable", the channel Secrets reload/unknown-outcome lines, and the plugin feedback and tool-error lines.Change
Product (small):
setStatusTone(dom.mjs) now keeps an announcing line's role in step with its tone: a line withrole=statusorrole=alertbecomes an alert in the danger and warning tones and a status otherwise, the rulestatusBlockalready follows. Lines without a role are untouched.detail.mjs(authentication sourcesay, Repositories editorrefuseand resets, the retained warning/unknown lines, and the Configuration editor's refusals and resets) set the tone before writing the text, so a refusal is written into an alert and guidance into a status.credentials.mjs) and the plugin selections feedback line (plugin-fields.mjs) arerole=alert.role=status, with a comment: the details pane is rebuilt on every redraw (search typing, for one), so an alert would be announced again each time. The per-repository danger notes keep no role for the same reason, and the picker's status line does the announcing.aria-live="polite"(implied byrole=status), so its alert role is assertive when it turns danger.Tests:
console-status-block.test.mjs: the two existing conflict tests now expect an alert; new tests pin the authentication source 403 (focused danger alert, written as an alert, next save's progress a quiet status), the unfinished ChatGPT sign-in refusal, the unconfirmed Secret grant (focused warning alert, still a warning alert after the tab is rebuilt), the unknown outcome (still a danger alert after the rebuild), the Repositories editor 403 (focused alert; an edit and a held navigation turn it back into a status), the Configuration pre-save conflict (written into an alert; the navigation hold is a status) and a refused Configuration save's progress and Cancel resets.console-agents.test.mjs: the repository-recovery test now tells the create form's refusal from the repository picker's own line, which is an alert too.console-agent-draft-guards.test.mjs: the channel Secrets reload line is found as an alert.Verification
Mutants, each a temporary edit reverted with
git checkout; every one fails at least one test now:say(error.message, "danger")->say(error.message)"danger""warning"warning/dangertonesaywrites the tone onlyif (tone)(progress keeps the refusal tone)refuse()say/refusewrite the text before the tonesetStatusTonekeeps the old rolerole=statusrole=statusFails on main: the role assertions fail on main (danger lines were
role=status); the tone, focus and reset assertions kill the mutants above.Pins: every new or changed test passed 20/20 at 2 CPUs (
taskset, sequential runs). Full touched files are green, and the whole browser suite ran on this head (after merging main with fix(console): bound the long-name check so joiner runs can't hang the Agents list #2926 and fix(console): small refusal and focus fixes from the 10-19 audit #2930): 717/718, the one failure being "docs preview filters the ComputeDriver matrix", which cannot loadgithub-sluggerin a local worktree and does not touch these files.prettier --checkandeslint --max-warnings 0pass on every touched file. No new test files.UI media: none. Nothing changes on screen; the change is the announcement role, which the tests pin.
Accessibility tree (Chromium, CDP
Accessibility.getPartialAXTree) for the authentication source feedback line: idle, after a 403 Save, then during the next Save's held preflight read:f3a74292a)Open PRs:
git merge-tree --write-treeof each open PR touching these files, against origin/main and against this head; no new conflicted file or hunk:fix(console): bound the long-name check so joiner runs can't hang the Agents list #2926 and fix(console): small refusal and focus fixes from the 10-19 audit #2930 (the parallel lane) landed first; this head merges them cleanly, and fix(console): small refusal and focus fixes from the 10-19 audit #2930's channel Secrets tone change sits a few lines above the two role changes in
credentials.mjs.Risks
setStatusToneis shared. It changes the role only on lines that already announce (role=statusorrole=alert), and only to follow the tone, so a line that is quiet progress stays a status. The other callers (create form, Share Agent) were already alerts in the danger tone.Closes findings 2004, 2005, 2006 and 2010 from bughunt-127 (UX plan follow-up).