Fixes @typescript-eslint/no-dynamic-delete lint error in api-routes.test.ts
which was breaking Lint, Typecheck, and the onboarding build check.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- centralize project existence check via validateConfiguredProject
(Object.hasOwn) and apply to spawn, issues, verify, orchestrators routes
- add AbortController (1.5s) to runtime terminal config fetch in DirectTerminal
- add runtimeFetchDone flag to prevent repeated fetches on reconnect
- restore resolveDashboardProjectFilter fallback to getPrimaryProjectId()
- expand runtime terminal endpoint tests (defaults, invalid ports, proxy path)
- add validation.test.ts covering prototype-chain bypass cases
- add undefined case test for resolveDashboardProjectFilter
- update changeset with full list of changes for npm publish
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Light mode --color-status-ready: #5B7EF8 → #5e6ad2 (DESIGN.md specifies darker shade for light backgrounds)
- Light mode --color-tint-red: rgba(207,34,46,...) → rgba(220,38,38,...) to match new #dc2626
- Dark mode --color-tint-red: rgba(255,123,114,...) → rgba(239,68,68,...) to match new #ef4444
- ActivityDot.tsx: update hardcoded bg tints — active gets green rgba(34,197,94,0.1), ready gets blue rgba(91,126,248,0.1)
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Exposes connectionStatus ("connected" | "reconnecting" | "disconnected")
from useSessionEvents via onopen/onerror EventSource handlers, and renders
a fixed ConnectionBar at the top of the viewport that shows a pulsing amber
bar while reconnecting and a red 32px "Offline · tap to retry" bar when
disconnected.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- ToastProvider now clears its setTimeout in a useEffect cleanup to prevent
memory leaks when the component unmounts while a toast is still pending.
- BottomSheet adds a focus trap on the sheet element so keyboard users cannot
Tab out of the dialog; focus is also set to the first focusable element
(Cancel button) when the sheet opens.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Quick-reply UI was invisible on mobile viewports 480–767px wide because
its styles were scoped to @media (max-width: 480px). Moved all
.quick-reply* rules into the @media (max-width: 767px) block so the
component renders correctly across the full mobile range.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On mobile (<=767px), session cards with attention level "respond" now
show an inline quick-reply panel with the agent's last message summary
(2-line clamp), Continue/Abort/Skip preset buttons, and an expandable
textarea. Enter submits; all touch targets are >=44px. Hidden on
desktop via CSS-only media query.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Extract onPillTap as handlePillTap useCallback with prefers-reduced-motion support
- Replace role="navigation" with role="group" aria-label="Session priorities" on pill strip
- Add role="status" to all-clear fallback so screen readers announce state changes
- Add :focus-visible outline to .mobile-action-pill for keyboard accessibility
- Add scroll-margin-top: 56px to .accordion-board to prevent sticky header occlusion
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
On mobile (<=767px), replace the 4 stat cards with a single-row
MobileActionStrip showing non-zero urgency pills (respond/merge/review)
with colored dots. Tapping a pill calls setExpandedLevel and scrolls to
the accordion board via id="mobile-board". Hides stat cards, dashboard
subtitle, and board-section-head on mobile to target ~92px hero height.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
- Fix Critical 1: change onToggle to (level: AttentionLevel) => void and
create stable handleAccordionToggle with useCallback, eliminating the
inline arrow that defeated memo on every render
- Fix Critical 2: remove grouped from useEffect deps so user accordion
selection is not reset on every SSE update; seed only on isMobile change
- Fix Important 3: move accordion CSS block inside @media (max-width: 767px)
so it is scoped to mobile only, consistent with rest of file
- Fix Important 4: add Safari 16+ compatibility comment on
grid-template-rows transition
- Fix Suggestion 5: replace ▶/▼ character swap with single ▶ rotated via
CSS transform so the declared transition: transform actually animates
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace vertical kanban stacking on mobile (<=767px) with a single-open
accordion ordered Respond > Merge > Review > Pending > Working.
Auto-expands the most urgent non-empty section on load; empty sections
render as header-only rows (no dashed placeholder). Desktop layout is
unchanged. Added window.matchMedia stub to the Vitest setup file so
Dashboard unit tests pass in jsdom.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Replace the lazy useState initializer that read window.matchMedia on
first render (causing SSR/client hydration mismatch) with a plain
false default; the existing useEffect already syncs the correct value
after mount. Adds a full vitest test suite covering all six specified
cases (SSR-safe default, match/no-match, number-to-query conversion,
change-event reactivity, and listener cleanup on unmount).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
caches.match() can return undefined under mobile storage pressure.
Fall back to a plain-text 503 response instead of passing undefined
to event.respondWith().
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>