fix(ui): five regressions the sidebar restyle and the token re-tier introduced #118

Merged
lz merged 1 commit from fix/sidebar-regressions into main 2026-09-04 18:00:57 +02:00
Owner

An adversarial pass over the whole merged body of work (#112–#117) found six regressions. Five are fixed here; the sixth is a knowing trade, explained at the bottom. Each was verified by reading the code, and the high one by driving the UI.

1 — HIGH: "New session…" was dead everywhere, and lied about why

focusNewSession (MainSplit.svelte) looks the workspace up by [data-worker-id] — an attribute the restyle deleted along with the .sessions-mount wrapper that carried it. Nothing in the app emitted it any more.

So the query returned null, the scroll and focus were no-ops, and control always fell through to toast('Sessions appear once the workspace has finished starting') — on healthy running workspaces, with the add-session form visible right there. The one branch written to catch a genuine failure had become the only branch that ever ran.

It is the first item of the workspace menu, reachable from the sidebar ⋯, the rail ⋯, and a workspace dock tab's context menu.

Verified live: picking "New session…" now focuses the feature-name input and shows no toast.

2 — MEDIUM: the rail's hover card lost its capability chips for good

Workers.svelte stopped calling workerImages.load() when it stopped rendering capability chips, but RailHoverCard still reads capabilitiesFor() and never loaded anything itself. The two remaining loaders only fire when a Settings panel or the New-workspace modal opens.

Worse: the hover card renders only in rail mode, where <Workers> is unmounted — so nothing could have loaded it there even before. Moved the load to MainSplit, which is mounted in both branches.

3 — MEDIUM: .ws.dormant undid the WCAG work it shipped beside

At opacity: 0.45 a stopped workspace's name composited to ~3.9:1 on --bg, and its repo line to ~2.03:1 — the exact value #113 had just been written to eliminate. 0.6 keeps the name near 6:1 and still reads clearly as recessed.

4 — LOW-MEDIUM: the empty states became full-bleed dashed boxes

.empty draws a dashed box; giving it horizontal padding insets its text and leaves the border flush against both pane edges, now that .lp-body has none of its own. Margin, not padding. Affects the load-error, no-provider and no-workspaces states — two of which are the first thing a fresh operator sees.

5 — LOW: <b> emphasis silently became a no-op

.foot b and .hint b were --muted against a --muted-2 line. After the re-tier both sides are --muted, so the palette's ↑↓ / ↵ / Tab / Esc keys and the hover card's "terminal" render identically to their labels. Raised to --text.

Deliberately not fixed

dockview no longer distinguishes the focused group from an unfocused one — the four tab-background vars were its only signal, and #112 set them all transparent. That trade was made knowingly and is called out in #112; it needs a replacement signal rather than reverting the fill, so it stays a known limitation rather than a silent one.

Gates: typecheck 4898 files / 0 errors, lint clean, 121 files / 1202 tests.

An adversarial pass over the whole merged body of work (#112–#117) found six regressions. Five are fixed here; the sixth is a knowing trade, explained at the bottom. Each was verified by reading the code, and the high one by driving the UI. ## 1 — HIGH: "New session…" was dead everywhere, and lied about why `focusNewSession` (`MainSplit.svelte`) looks the workspace up by `[data-worker-id]` — an attribute the restyle deleted along with the `.sessions-mount` wrapper that carried it. Nothing in the app emitted it any more. So the query returned `null`, the scroll and focus were no-ops, and control **always** fell through to `toast('Sessions appear once the workspace has finished starting')` — on healthy running workspaces, with the add-session form visible right there. The one branch written to catch a genuine failure had become the only branch that ever ran. It is the **first item of the workspace menu**, reachable from the sidebar ⋯, the rail ⋯, and a workspace dock tab's context menu. **Verified live:** picking "New session…" now focuses the `feature-name` input and shows no toast. ## 2 — MEDIUM: the rail's hover card lost its capability chips for good `Workers.svelte` stopped calling `workerImages.load()` when it stopped rendering capability chips, but `RailHoverCard` still reads `capabilitiesFor()` and never loaded anything itself. The two remaining loaders only fire when a Settings panel or the New-workspace modal opens. Worse: the hover card renders **only** in rail mode, where `<Workers>` is unmounted — so nothing could have loaded it there even before. Moved the load to `MainSplit`, which is mounted in both branches. ## 3 — MEDIUM: `.ws.dormant` undid the WCAG work it shipped beside At `opacity: 0.45` a stopped workspace's **name** composited to ~3.9:1 on `--bg`, and its repo line to ~2.03:1 — the exact value #113 had just been written to eliminate. `0.6` keeps the name near 6:1 and still reads clearly as recessed. ## 4 — LOW-MEDIUM: the empty states became full-bleed dashed boxes `.empty` draws a dashed **box**; giving it horizontal *padding* insets its text and leaves the border flush against both pane edges, now that `.lp-body` has none of its own. Margin, not padding. Affects the load-error, no-provider and no-workspaces states — two of which are the first thing a fresh operator sees. ## 5 — LOW: `<b>` emphasis silently became a no-op `.foot b` and `.hint b` were `--muted` against a `--muted-2` line. After the re-tier both sides are `--muted`, so the palette's ↑↓ / ↵ / Tab / Esc keys and the hover card's "terminal" render identically to their labels. Raised to `--text`. ## Deliberately not fixed dockview no longer distinguishes the **focused group** from an unfocused one — the four tab-background vars were its only signal, and #112 set them all transparent. That trade was made knowingly and is called out in #112; it needs a replacement signal rather than reverting the fill, so it stays a known limitation rather than a silent one. Gates: typecheck 4898 files / 0 errors, lint clean, 121 files / 1202 tests.
fix(ui): five regressions the sidebar restyle and the token re-tier introduced
All checks were successful
ci / nexus (pull_request) Successful in 10m17s
pr-image-cleanup / delete-pr-images (pull_request) Successful in 12s
ci / images (pull_request) Successful in 11m31s
cf1d9cf0cc
Found by an adversarial pass over the whole merged body of work, each verified
by reading the code and, where it was reachable, by driving the UI.

**1 (high) — "New session…" was dead everywhere, and lied about why.**
`focusNewSession` looks the workspace up by `[data-worker-id]`, an attribute the
restyle deleted along with the `.sessions-mount` wrapper that carried it. The
query returned null, so the scroll and the focus were no-ops and control always
fell through to a toast saying the workspace had not finished starting — on
healthy running workspaces, with the add-session form visible right there. It is
the FIRST item of the workspace menu, reachable from the sidebar, the rail and a
dock tab. The attribute is back on the section that replaced the wrapper.
Verified live: picking it now focuses the `feature-name` input and shows no
toast.

**2 (medium) — the rail's hover card lost its capability chips for good.**
`Workers.svelte` stopped calling `workerImages.load()` when it stopped rendering
capability chips, but `RailHoverCard` still reads `capabilitiesFor()` and never
loaded anything itself. The two remaining loaders only run when a Settings panel
or the New-workspace modal opens. Worse, the hover card renders ONLY in rail
mode, where `<Workers>` is unmounted — so nothing could have loaded it there
anyway. Moved the load to `MainSplit`, which is mounted in both branches.

**3 (medium) — `.ws.dormant` undid the WCAG work it shipped beside.** At opacity
0.45 a stopped workspace's NAME composited to ~3.9:1 on `--bg` and its repo line
to ~2.03:1 — the exact value the token re-tier had just been written to
eliminate. 0.6 keeps the name near 6:1 and still reads as clearly recessed.

**4 (low-medium) — the empty states became full-bleed dashed boxes.** `.empty`
draws a dashed BOX; giving it horizontal PADDING insets its text and leaves the
border flush against both pane edges, now that `.lp-body` has no padding of its
own. Margin, not padding. Affects the load-error, no-provider and no-workspaces
states — two of which are the first thing a fresh operator sees.

**5 (low) — `<b>` emphasis silently became a no-op.** `.foot b` and `.hint b`
were `--muted` against a `--muted-2` line; after the re-tier both sides are
`--muted`, so the palette's ↑↓ / ↵ / Tab / Esc keys and the hover card's
"terminal" render identically to their labels. Raised to `--text`.

Deliberately NOT fixed: dockview no longer distinguishes the focused GROUP from
an unfocused one, because the four tab-background vars were its only signal.
That trade was made knowingly in the tab PR and is called out there; it needs a
replacement signal rather than reverting the fill.

Gates: typecheck 4898 files / 0 errors, lint clean, 121 files / 1202 tests.
lz merged commit dc587bb33c into main 2026-09-04 18:00:57 +02:00
Sign in to join this conversation.
No reviewers
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
lz/agent-nexus!118
No description provided.