- Broaden mobile media query to include (max-height: 480px) so landscape
phones (which exceed 768 CSS px wide) still render the bottom nav and
mobile board layout instead of desktop horizontally-scrollable columns.
- Guard useMobileKeyboard against pinch-zoom (vv.scale > 1) — Android
Chrome ignores user-scalable=no, and a focused textarea + zoom was
false-positiving keyboard-open and hiding MobileNavBar.
- Read documentElement.clientHeight instead of stale window.innerHeight
when computing keyboard overlap (Android multi-window can leave
innerHeight cached at a wildly different value than the actual layout
viewport — observed 2848 while html was 797).
- Add interactive-widget=resizes-content to the viewport meta so Android
Chrome shrinks the layout viewport with the soft keyboard, matching iOS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Adds an "advisory" `gateMode` option for workflow steps: steps in advisory mode log findings but no longer block merge completion, while steps that must block can still be configured as blocking. The change covers the workflow step types and schema, executor gating logic, dashboard UI in WorkflowSte
Fusion-Task-Id: FN-4468
Updates the restart integration test mock to account for plugin template behavior, keeping the test in sync with recent plugin template changes.
Fusion-Task-Id: FN-3096
Docs(FN-3397): Documented the add-step chooser flow in the workflow steps reference, adding 9 lines to `docs/workflow-steps.md`.
Fusion-Task-Id: FN-3397
The Settings, Workflow Steps, Automations (and friends) modals all carried
desktop `min-width: 480-520px` constraints from the resize work. On phones
that pushed them off-screen, and the overlay's 10vh top padding plus a
fractional `height: 80vh` left awkward gaps top and bottom.
Apply the same `@media (max-width: 768px)` full-screen-sheet treatment
that File Browser already had to every resize-aware modal: drop the
overlay padding, set width/height to `100vw`/`100dvh`, zero out the
min-* / max-* constraints, and disable `resize` (touchscreens can't grab
the corner grip anyway).
Also tightened the existing File Browser and GitHub Import overrides to
match (`min-width: 0`, `min-height: 0`, `resize: none`).
For TaskDetailModal the mobile rules go inside the existing first
`@media (max-width: 768px)` block to keep the FN-1331 detail-body
padding regression test happy (it captures from the first 768px media
query greedily).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Modal resize + size persistence
- Extract `useModalResizePersist` hook (ResizeObserver + localStorage),
apply to Files, Git Manager, GitHub Import, Workflow Steps, Automations
(ScheduledTasks), and Settings modals. Each gets `resize: both`, sane
min/max constraints, and a unique storage key.
- Bump default heights so the modals feel less cramped (Git: 92vh,
Workflow/Automation: 80vh, Settings: 80vh / 1100px).
Scrollbar theme
- Add a global `*::-webkit-scrollbar*` + `scrollbar-color` rule in
styles.css so chat, document, system stats, file browser, usage
indicator, etc. inherit the theme. Existing per-component overrides
(.board, .column-body, .settings-sidebar, planning modal) still win.
Document view
- Collapse "Show hidden" toggle and search input onto the same row as
the Project Files / Task Documents segmented control. Stack again
below 768px.
Mailbox / Todos
- Match Todos header treatment to the Mailbox header (typography,
padding, border).
- Add top spacing above Mailbox Inbox/Outbox/Agents tab bar so the
vertical gaps balance.
Settings
- Wider, resizable, persisted Settings modal.
- Project Models description and Authentication panel get proper
horizontal padding.
- Reorder project sidebar so "General" is first.
- Plugins page: clean margins, integrate refresh button, exclude
bundled runtimes from the "Installed Plugins" list (they were
appearing twice — once erroring, once in their own section).
- New "Updates" panel with auto-check toggle + "Check now" button
(frequency control noted as needing a backend schema field).
Background sessions
- Fix stale "AI N" / planning-icon badge: `handleDeleted` in
`useBackgroundSessions` now writes a tombstone, advances the
timestamp guard, and broadcasts completion so the cross-tab
sync store stops resurrecting the deleted session on the next
merge tick. Added regression test.
- Re-fetch list on SSE reconnect so terminal events fired during a
network blip don't get permanently lost.
System stats
- Refresh button uses correct single class (was getting both `btn`
and `btn-icon`, which conflicted on padding/border).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
- Move the WorkflowStepManager mobile modal sizing rules into the primary max-width 768px block
- Expand mobile fullscreen behavior to enforce viewport height, remove borders, and zero border radius
- Add mobile wrapping support for step card title/action rows and remove the duplicate trailing media block
- Move misclassified .mesh-topology, .connect-node, .nodes-view-topology, .node-status-indicator, and pulse-warning keyframe from AgentReflectionsTab.css to NodesView.css; relocate node-related mobile @media rules from SettingsSyncLog.css so NodesView renders standalone
- Add missing CSS import on GitManagerModal so its .gm-* styles load without depending on ScriptsModal being mounted
- Bump desktop max-widths for FileBrowser, Terminal, GitManager, GitHubImport, and WorkflowStepManager modals; raise selector specificity to .modal.X so the base .modal { width: 480px } can't win the cascade
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Split app/styles.css from ~40k lines down to ~4.5k. Created 56 co-located
component CSS files in app/components/, each imported by its owning .tsx.
The remainder of styles.css holds genuinely global rules (design tokens,
.btn/.card/.modal/.form-input primitives, cross-component @media overrides).
- Lazy-load 13 heavy views (AgentsView, RoadmapsView, NodesView, etc.) via
React.lazy + Suspense; prefetch all chunks on idle so first navigation is
instant. Initial JS bundle: 1.58 MB → 1.16 MB (-26%). Initial CSS bundle:
635 kB → 471 kB (-26%); the rest splits into 13 per-view chunks.
- Add app/test/cssFixture.ts exposing loadAllAppCss() + loadAllAppCssBaseOnly()
so CSS regression tests load the full per-component bundle (mirroring Vite
source order). Migrate 30+ tests off direct readFileSync('../styles.css').
- Enable test.css: { include: [/.+/] } in vitest.config.ts so component CSS
imports actually inject styles in jsdom (fixes getComputedStyle assertions).
- Add ESLint rule (no-restricted-syntax) banning direct styles.css reads in
dashboard test files; points at loadAllAppCss() instead.
- Restore lost utility classes (.text-muted, .text-secondary, .text-dim,
.form-input) and rescue dropped chat tool-call rules into QuickChatFAB.css.
- Mobile fixes along the way: scroll containment for view containers
(min-height:0 + -webkit-overflow-scrolling), QuickChatFAB full-screen on
mobile (with safe-area-inset for iOS home bar), AgentsView single-row
header layout, ActivityLogModal close button on right, model-combobox
z-index above the mobile quick-chat panel.
- Bug fix: SkillsView toggle was display:none which hid the input from the
accessibility tree; replaced with the visually-hidden pattern so screen
readers + getByRole still find the checkbox.
- Bug fix: standalone Delete button in TaskDetailModal for triage-column
tasks (Actions dropdown is hidden in triage state, so previously no way
to delete a freshly-created task without status change first).
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>