fix(chat): surface collapsed approval failures - #5562
Conversation
GPT 5.6 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo findings. |
Design Review (Fable 5, fork) — 🟡 CONCERNSDesign-level review of The base ApprovalCard contains this exact machinery — the PR copies its failure state machine wholesale. I have what I need for the verdict. Design-Verdict: CONCERNS Real fix for a real gap, but it clones ApprovalCard's entire failure state machine instead of sharing it — two copies of one gateway contract. Watch
Suggestions
[DESIGN-REVIEWED] f69cccb |
UX Review (Fable 5, fork) — 🟡 CONCERNSUX-level review of UX-Verdict: CONCERNS Terminal failure hides the buttons but leaves the pulsing amber "Approval needed" header directly contradicting the "no longer pending" notice below it. Watch
Retryable path is solid: rollback + [UX-REVIEWED] f69cccb |
Opus 4.8 Review (fork) — ✅ no blocking findingsReviewed Review detailsNo blocking issues; one advisory finding. FINDING — website/src/pages/chat/CollapsibleToolGroup.tsx:248 — a terminal refusal (404, or 400 [OPUS-REVIEWED] f69cccb |
First Principles Review (Fable 5, fork) — 🟡 CONCERNSPremise-level review of I have everything needed. The base First-Principles-Verdict: CONCERNS The fix is real and lands at mechanism level, but it ships as a ~40-line verbatim copy of ApprovalCard's failure machinery — a second spelling that will diverge. What this change shipsIntent: make a failed approval decision in a collapsed tool group visible and safely retryable by keyboard (#5554). This is a FIX.
Watch
[FIRST-PRINCIPLES-REVIEWED] f69cccb |
chenmingwei23
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (3 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean (CodeQL + Semgrep, 0 alerts), security checklist all-NO, AI reviewers green. Category: fix - surfaces collapsed approval-POST failures and restores focus to the attempted decision (#5524); presentation-layer rollback only, approval gate logic unchanged.
bolichen97
left a comment
There was a problem hiding this comment.
Approving per triage sweep: readiness passed, no blocking reviews, fix-type change. Auto-merge will be enabled; branch protection still gates.
edf7248
Head branch was pushed to by a user without write access
bolichen97
left a comment
There was a problem hiding this comment.
Re-approved after conflict resolution against the latest main; focused validation passed.
|
Full-diff overlap audit (current head Please choose one owner for this UI contract and consolidate the focused tests instead of merging both implementations. My recommendation is to preserve #6065's terminal-vs-retryable behavior after #6065 is cleaned of its unrelated carried commits, then close/supersede the other alternative. This is not covered by #5536: that PR reaches the rollback promise path but does not render this inline error or restore focus. |
Mirror ApprovalCard's terminal and retryable ApiError handling in collapsed approval groups while restoring focus to the exact failed action. Co-authored-by: Aniruddha Adak <aniruddhaadak80@users.noreply.github.com>
edf7248 to
f69cccb
Compare
bolichen97
left a comment
There was a problem hiding this comment.
Tier 1 auto-approve: fix (3 files). Criteria: no conflict, no requested changes, security path denylist clean, design-doc gate clean, SAST annotations clean, security checklist all-NO, AI reviewers green. Category: surface collapsed approval-dispatch failures with an inline notice and focus restore, classifying terminal vs retryable refusals — display only, server gate untouched. CodeQL is not applicable on this fork PR (default-setup emits no check-run); SAST coverage is Semgrep only, latest run success with 0 annotations.
Problem / Motivation
When a decision in a collapsed tool group fails, the optimistic resolved state rolls back to live buttons without telling the user that the request failed. The button that owned keyboard focus was also unmounted during the optimistic state and returned unfocused, so a keyboard user could not safely retry the same decision.
Why it matters
The silent rollback makes an unrecorded approval look like a completed action. Losing the attempted control's focus adds ambiguity: a retry can start from a different decision than the one the user just chose.
What changed (motivation → approach → change)
ApprovalCardrollback pattern and existing translated failure copy.ErrorNoticeafteronApproverejects.This does not change approval transport semantics or the expanded approval card.
Tests
vitest run src/test/CollapsibleToolGroupCov80.test.tsx src/test/CollapsibleToolGroup.purposePreview.test.tsx --pool=forks --maxWorkers=1 --fileParallelism=false— 22 passed after the final rebase.eslint src/pages/chat/CollapsibleToolGroup.tsx src/test/CollapsibleToolGroupCov80.test.tsx— passed.tsc -b— passed.node scripts/i18n-check.mjs— all 18 checks passed.Manual verification
Rendered the real
CollapsibleToolGroup, rejected the decision promise, and verified that the localized alert appears while the attempted Approve button regains focus (visible focus ring and active DOM state).Screenshots / video
Related Issues
Fixes #5554
Checklist
feat|fix|docs|refactor|perf|test|chore|ci|build|revert: ...)Contribution License Agreement