diff --git a/DESIGN.md b/DESIGN.md index 068a7e4530b..9d53a3c844b 100644 --- a/DESIGN.md +++ b/DESIGN.md @@ -117,8 +117,8 @@ completes without a provider reply. Preserve the reply through persistence. Task chat shows execution errors and waits only while they remain relevant. Exhausted attempts use a padded, rounded notice with a destructive-tinted background, -an error icon, and foreground text. The surrounding layout supplies separation from -the conversation. Automatic retry countdowns keep their quieter inline styling. +an error icon, and foreground text. A wrapper adds top padding above the tinted +surface. Automatic retry countdowns keep their quieter inline styling. Completing or cancelling a task hides its old execution notices. A newer attempt by the same agent or an explicit successor supersedes earlier run notices; an unresolved execution hold remains visible. Historical turns keep their responses, diff --git a/tests/e2e/execution-recovery/failed-attempt-notice.spec.ts b/tests/e2e/execution-recovery/failed-attempt-notice.spec.ts index fcb8588483e..efba0a8996a 100644 --- a/tests/e2e/execution-recovery/failed-attempt-notice.spec.ts +++ b/tests/e2e/execution-recovery/failed-attempt-notice.spec.ts @@ -24,10 +24,12 @@ test.describe("failed-attempt notice", () => { return { background: style.backgroundColor, padding: [style.paddingTop, style.paddingRight, style.paddingBottom, style.paddingLeft].map(parseFloat), + topPadding: parseFloat(getComputedStyle(element.parentElement!).paddingTop), }; }); expect(surface.background).not.toBe("rgba(0, 0, 0, 0)"); expect(surface.padding.every(value => value > 0)).toBe(true); + expect(surface.topPadding).toBeCloseTo(16); const iconBounds = (await icon.boundingBox())!; const textBounds = (await message.boundingBox())!; diff --git a/ui/src/components/ExecutionBlockerNotice.tsx b/ui/src/components/ExecutionBlockerNotice.tsx index da88e57fe2e..0a343207d22 100644 --- a/ui/src/components/ExecutionBlockerNotice.tsx +++ b/ui/src/components/ExecutionBlockerNotice.tsx @@ -28,16 +28,17 @@ export function ExecutionBlockerNotice({ presentation, canRetry, onRetry, optimi !["failed", "retry_scheduled"].includes(presentation.state)) return null; const seconds = Math.max(0, Math.ceil((Date.parse(presentation.nextRetryAt ?? "") - Date.now()) / 1000)); return ( -