fix(components): route error states through ErrorNotice (batch components-1) - #8859
Conversation
Design Review (Fable 5) — ✅ PASSDesign-level review of The diff is fully reviewed: a disciplined batch migration to The one design-shaped item: the popout's last-tab close now awaits the PTY DELETE settling ( Design-Verdict: PASS A disciplined, contract-following batch migration; every hand-off decision is grounded in the ErrorNotice draft-loss rule, and the one new mechanism is contained and justified. Suggestions
[DESIGN-REVIEWED] b6a3c68 |
First Principles Review (Fable 5) — 🟡 CONCERNSPremise-level review of All evidence gathered. The sweep is mandated by the blocking First-Principles-Verdict: CONCERNS Every migration is rule-mandated, but the terminal-close apparatus is sized for one popout edge case whose failure its own copy calls self-healing. What this change shipsIntent: make every error in these 22 components render the shared, agent-hand-off-capable notice instead of a dead-end red line — a FIX (defect: silent/dead-end error surfaces, per the blocking
Watch
Subtractions
[FIRST-PRINCIPLES-REVIEWED] b6a3c68 |
UX Review (Fable 5) — 🟡 CONCERNSUX-level review of The diff is a consistent migration of 22 components onto the established shared UX-Verdict: CONCERNS Solid migration the blind reader comprehended everywhere shown — but 4 screenshots cover 22 changed surfaces, and "agent" now means two things side by side. Watch
Evidence gaps
Suggestions
[UX-REVIEWED] b6a3c68 |
Opus 4.8 Review — ✅ no blocking findingsReviewed Review detailsI've read the instruction set, the single candidate, the base-branch rule snapshot, and the diff for the relevant hunks. Falsifying Candidate 1 ( The claim is that the stage-1
Whether "carrying" a No grounded new finding survives Step 2. No findings. [OPUS-REVIEWED] b6a3c68 Verdict parsed from the review's SHA-scoped output markers for commit False positive or not applicable? A repository writer can comment: |
GPT 5.6 Review — ✅ no blocking findings (all downgraded on adjudication)GPT 5.6 flagged blocking issues on This comment is updated in place on each push. Review detailsBLOCKING -- website/src/components/CliPanel.tsx:210 -- Terminal close failures disappear when the feature is disabled
Adjudication (Opus 4.8) — is blocking on each finding proportionate?F1 concerns whether a terminal-close DELETE failure surfaces to the user when the terminal feature is disabled and its always-mounted notice host is therefore absent.
[ADJUDICATION] b6a3c68 total=1 uphold=0 downgrade=1 False positive or not applicable? A repository writer can comment: |
238dd12 to
11ced47
Compare
11ced47 to
10cb27a
Compare
10cb27a to
ed55a33
Compare
ed55a33 to
3ea600e
Compare
3ea600e to
130356f
Compare
130356f to
e587657
Compare
bfa4aa5 to
9f6f1ca
Compare
9f6f1ca to
b344388
Compare
…ents-1)
Migrate every hand-written error surface in the components-1 batch of the
error-state audit (22 files under website/src/components/) to the shared
ErrorNotice, per AUTOSDE rule errors-use-error-notice. askAgent is on where
the hand-off loses nothing (load/list/status/action-on-persisted); off with a
`No hand-off:` comment naming the concrete draft next to unsaved input
(wizard selections, composer drafts, comment textareas, popover fields).
Also closes the batch's silent failures: AgentImportFlow renders
completionError on stages 2/3; AutoNudgePopover, ExecutionsView (jobs +
trace), ChatPane (transcript hydration), FileArtifactComments (read + every
write) render query/mutation errors; EmbedTabStrip createSlot,
BottomTerminalPanel PTY delete, ChatInput optimizer and auto-compact writes,
ChatPane agent/model switch now report in-page instead of toast-only. Each
notice is bound to a surface that is still mounted when the failure lands
(jobs notice above the empty-history return, comment-write notice in the
always-mounted popovers node while the sidebar is closed, optimizer notice on
whichever session is on screen, last-terminal-tab delete routed to the
notification centre).
Ten new user-facing strings across 13 catalogs (+ en-XA regen). Capture
harness capture/error-notice-components-1.{tsx,html} +
scripts/capture-error-notice-components-1.mjs (asserts hand-off present after,
absent before).
b344388 to
b6a3c68
Compare
Disposition — UX Review (head
|
Disposition — First Principles Review (head
|
Disposition — Design Review (head
|
Summary
Batch components-1 of the dashboard error-state sweep. Every hand-written error surface the audit lists for these 22 files under
website/src/components/now renders through the sharedErrorNotice(AUTOSDEerrors-use-error-notice, blocking), and the batch's silent failures (query/mutation with no error render, toast-only reports) get an in-page notice.Source: the audit report
research/error-states-audit.md(a KiroCrew workspace research document produced by workflowwf_000025; it is not committed to this repo), section 5 "Batch components-1" plus the matching rows in sections 1 and 3. No linked issue: driven by the audit report.askAgent decisions follow the rule: on where the hand-off loses nothing (load/list/status failures, actions on persisted inputs, crash fallbacks); off with a
No hand-off:comment naming the concrete draft next to unsaved input.Sites migrated
AgentDropdownList.tsxManageAgentsFooterAgentImportFlow.tsxsource_unreadable, ×4completionError(full-panel ×2, stage 1, stage 4), stage-1 unreadable, stage-3applyMutation— + silent:completionErrornow also renders on stages 2 and 3No hand-offon stages 1–3 (wizard selections / conflict strategy)AgentSelector.tsxAppHost.tsx<p>is dropped — the journal carries it), bundle-load failureApprovalCard.tsxErrorNoticehad no decisionArtifactBody.tsxdocSilentstays status), image load failureArtifactPanel.tsxAutoNudgePopover.tsxisError(+ Retry)No hand-off(goal / idle / max-cycle inputs)AwsConsentGate.tsxidentityDetail(identity probe failed)askAgentprop, same as the sibling noticesBottomTerminalPanel.tsxuseDeleteTerminalSessionrejection — rendered from the always-mounted panel root via a small close-error store, so a delete rejected after the LAST tab closed still lands on anErrorNotice; a boolean flag mirrored to localStorage purely as a cross-window transport (never read at launch), set by the hook itself. The DELETE iskeepalive, so the popout's last-tab request outlives the window; that tab waits for the settle with a visible closing state on its chip, so the rejection is recorded before the frame returns to mainChatInput.tsxErrorNotice), auto-compact load failure, auto-compact write failure now also in-popover — + silent: optimizer failureNo hand-off(composer draft)ChatPane.tsxisError(+ Retry)No hand-off(composerinput)CliPanel.tsxbasis-full) beneath the two toolbar actions (alsotext-red-500/text-green-500→ tokens)CommandPalette.tsxCommentThreads.tsxNo hand-off(reply draft)CommentsSidebar.tsx+FileArtifactComments.tsxremote_sync_error; silent: comments query error and every comment write (post/reply/resolve/review/reopen/delete/edit) now captured and rendered beside the composer — and, while the sidebar is closed, in the always-mounted popovers nodeNo hand-off(comment composer draft)CrewWakeSection.tsxNo hand-off(inline JobForm); load:askAgent={!creating}CrewWebhookSection.tsxEmbedTabStrip.tsxcreateSlotMutationrejection — own wrapping row beneath the tab stripExcalidrawBlock.tsxExecutionsView.tsxisError,TraceRowquery errorOne file outside
website/src/components/is touched on purpose:pages/chat/SidePanel.tsx, the other consumer ofuseDeleteTerminalSession, now routes its rejected PTY delete into the same close-error store (a two-line change; the pages batches had already merged without it, so nothing downstream would catch it).Not touched, deliberately: ChatInput's
/siderefused-press path (owned by #8730);website/AUTOSDE.yaml(settings-1 PR owns it);App.tsxtoast body (out of batch — the toast stays as transient feedback, the in-page notices above are the error surface).Rule-gap notes (for the settings-1 rule edit, not changed here)
setAgentSwitchNoticefrom ChatPane / ChatInput) — the rule's toast carve-out namesuseNotifyonly; a Redux notice rendered inApp.tsxis the same shape.role="status"slot shared by status and failure copy (ChatInputapprovalNotice) — a warn-toned status region that also carries a rejected-request message. Split here; the rule text does not name this shape.ExecutionsViewjobs list silently dropping the "deleted" annotation;EmbedTabStrip"+" appearing dead) — silent failures rather than mis-styled ones.Pattern harvest
Rule candidate: review-prompt
Pattern: an error state set behind a surface that is unmounted or bypassed when the failure lands (last tab closed, sidebar collapsed, early empty-state
return, slot-gatedsetState) —errors-use-error-noticechecks the render site exists, not that it is mounted at failure time.Strings
13 new keys (
components.autoNudgePopover.retry,components.chatInput.optimize_failed_elsewhere,components.bottomTerminalPanel.closing_terminal,components.crewWakeSection.retry,components.autoNudgePopover.watches_load_failed,bottomTerminalPanel.close_failed,chatInput.optimize_failed,chatPane.history_load_failed,chatPane.retry,commentsSidebar.comment_change_failed,commentsSidebar.comments_load_failed,embedTabStrip.new_chat_failed,executionsView.jobs_load_failed) inen.manual.json+ the 11 translation catalogs,en-XAregenerated. Existing strings reused everywhere else.Tests
src/test/ChatInput.approval.test.tsx: the non-404 approval failure now asserts theErrorNotice(approval-decision-error,role="alert") instead ofrole="status", which is now reserved for the expired-approval status copy.testIdso future assertions target it unambiguously.tsc -bclean,eslintclean on all touched files,I18N_BASE_REF=origin/main npm run i18n:checkall green. Test suites left to CI per the batch rules.Screenshot evidence
Capture harness
website/capture/error-notice-components-1.{tsx,html}+website/scripts/capture-error-notice-components-1.mjsmounts the real components withfetchrejected. The script asserts an "Ask the agent" link is present in every after frame and absent in every before frame (--before, run againstorigin/mainwith the same harness), so a pair cannot be two frames of one build.GET /api/webhooksrejectedGET /api/cronsrejected