Skip to content

Workbench: routing under the generator when a narrow panel is tall enough, and the grouped profile by provider then level - #269

Merged
atyrode merged 3 commits into
mainfrom
fix/narrow-stacked-routing
Oct 12, 2026
Merged

atyrode merged 3 commits into
mainfrom
fix/narrow-stacked-routing

Conversation

@atyrode

@atyrode atyrode commented Oct 11, 2026 •

Copy link
Copy Markdown
Owner

Problem

In a narrow but tall panel (the operator's preview: about 658×1033 CSS px) the generator showed the compact grouped profile with half the panel empty, and Routing and Usage were tabs. useMode chose the layout from the panel's width alone (NARROW_BELOW_PX = 760), never its height. The grouped profile was also ordered by where each group's first role appears in routing, which read as no order at all.

Behaviour

  • Beside when wide enough, under when tall enough, otherwise tabs. Below 760 px, routing stands under the generator when two things fit the visible height together (the scroll region's height less the key line): the generator without its grouped profile, and the whole routing pane without its fallback chains. Routing then keeps its own head (title, fallback chains, Hide) and usage stands under it, as in the wider layouts. There are no Routing or Usage tabs in that arrangement, and p/s hide and show the panes exactly as at wider widths. Hidden routing brings the grouped profile back into the generator and Show routing into its head. When they do not fit, the narrow layout is unchanged: the grouped profile in the generator, and Routing and Usage tabs.
  • How the fit is judged. It is measured from the rendered content in web.tsx (useStacked, bareHeight, bareRoutingHeight), never against a fixed height.
    • When. It is judged only once a resize has settled (two frames with no further resize, as data-boot lifts), or when the stage's structure changes: entering narrow, the routing's rows or the generator's rows, routing hidden or shown, a return to the main view, or the fonts becoming ready. It is never judged because the readout, the launch line or the fallback chains changed. Whatever then runs past the panel scrolls, so the launch never moves under the pointer and showing the chains never sends routing back to a tab.
    • The heights both arrangements use. The generator is weighed without the grouped profile and without the Show controls (data-reveal) that only the stacked arrangement adds; Defaults and Revert wrapping still count. The bar and routing are weighed as the stacked arrangement last laid them out at that width and route count. Routing is weighed without the lines its chains run past each lead, even while the chains show.
    • The probe. When no stacked measurement exists yet, the stacked arrangement is tried before paint (data-probing) and settles back if it does not fit. During the try, the Routing and Usage tabs keep their nodes but take no room, so focus on one stays unless the stage really stacks. A flip to stacked is measured once more as laid out. Measurements taken in a fallback font are dropped when the fonts are ready. A probe whose routing did not show ends.
    • Hysteresis. The stacked arrangement holds while it overflows by at most 4 px.
    • On a flip. A change of arrangement places things without motion, and focus on a routing or usage control that goes moves to the generator's rows.
  • Attributes. data-mode="narrow" spacing is kept in both narrow arrangements. The arrangement itself is shown by data-stacked. A tabbed flag replaces the arrangement uses of narrow in web.tsx and panel-keys.ts (PanelKey.narrow became tabbed).
  • Grouped profile order (routing-model.ts profileGroups): groups go by provider first, the default role's provider leading and the rest in familyOrder (orderedFamilies). Within a provider they go by the lead's catalog tier, strongest first (elite, smart, normal, fast), then by thinking level, highest first on the thinking scale, then by alias compared by code unit. Roles keep routing order inside a group, and the glide between groups is unchanged. The grouped block is now role="group" named "roles by model".
  • Docs and verification. The Shortcuts dialog, docs/configuration.md (top bar, grouped profile, usage, keys and layout paragraphs) and README describe the rule. The browser verifier now reads the arrangement from the tabs. Its geometry sweep adds the stacked main view at 620, 320 and 170 px, 2400 px tall. A new narrowArrangements step asserts:
    • 390×600: tabbed, with the Routing and Usage tabs and the grouped profile;
    • 390×2400: stacked, with no tabs for them and no grouped profile;
    • in the stacked arrangement, routing's top is at or below the generator's bottom, and usage's top at or below routing's bottom;
    • p hides and shows routing while the stage stays stacked;
    • f changes neither the arrangement nor the horizontal overflow.

Verification

Measured on 6de7dd8 (on main 8c0c849). The final head 9ec7903 changes only comments, the docs' tier sentence and one test row, from the delta review. The design lab ran real Chromium with the real Code and OMP bundles and no providers, in layout=full.

Scenario Size data-stacked Tabs Viewport scrollWidth/clientWidth
configured, first-use 658×1033 true Generator, Accounts, Sessions 658/658
configured, first-use 658×640 absent Generator, Routing, Usage, Accounts, Sessions 658/658
configured, first-use 390×844 absent five tabs 390/390
configured, first-use 320×568, panel constrained to 240 and 170 absent five tabs the verifier's paint check finds no overflow, cut, overlapping or outside text, and nothing past routing
configured, first-use 2400 tall, panel constrained to 320, 240 and 170 true three tabs same paint check: none
  • Stacked fit at 658×1033: generator 428 px, routing 431 px, bar 45 px and key line 46 px, so the arrangement needs 950 px of the region's height. Routing shows in full under the generator.
  • Grouped profile order (658×640, with Ladders: OpenAI's tiers are its own names, luna, terra, sol and astra, and a context window ranks nothing #268's ladder): sol:medium, terra:medium, terra:low, luna:low, fable:high, opus:low, haiku:low.
  • ≥760 px unchanged: I pixel-diffed the 760, 960 and 1280 px shots of both scenarios against main 8c0c849, built in the same lab. They are identical, except one launch-row pixel at 1280 and 960 (configured). The same pixel also differs between two shots of a single build.
  • Resize in one page (the panel's height constrained from 1033 to 640 px and back, twice): each change flips exactly once, two to three frames later when the resize settles, then holds for 30 frames. No probe was needed.
  • Boundary (658 px wide, 950 px needed), stepping 950 → 944 → 951 → 945 → 950 with 15 frames at each: it stays stacked down to 946 px, goes to tabs at 945 and stacks again at 950. Each crossing flips once.
  • Fallback chains: at exactly 950 px tall (658 wide) and 996 px (390 wide), showing the chains keeps data-stacked with 0 flips over 40 frames. Routing grows from 431 to 479 px (658) and to 647 px (390), the viewport's scrollHeight grows, and its scrollWidth stays equal to its clientWidth. With the chains shown, the routing height used for the fit measures 431 px, and the boundary is the same 946/945 px as with them hidden. At a new width of 600 px with the chains shown, the probe found a 972 px boundary (stacked at 968, tabs at 967).
  • Drag: narrowing a short panel by one pixel per frame from 657 to 571 px gave no probe during the drag and exactly one after it settled, which settled back to tabs. In a tall panel, the stacked layout is measured live and needs no probe.
  • Focus: with the Routing tab focused, a probe at a new width settles back to tabs and the same tab node keeps focus. When the panel then grows tall enough to stack, the tab goes and focus moves to the lead row.
  • Wrapping heads: at 200 and 255 px, where the generator head already takes two lines, hiding routing exactly at the boundary adds a third line for Show routing without flipping. Showing it again keeps the stacked arrangement, and 6 px less height gives tabs.
  • Launch: while stacked, the lab's launch interaction and an in-page click both change its line from empty to "Verification stopped while checking models: design_lab_native_effects_disabled". The arrangement does not flip, and the launch's top stays at 423 px.
  • Keys and pointer: when stacked, p and s hide and show routing and usage, and Hide, Show routing and Show usage work by click. When tabbed, p and s open and close the Routing and Usage tabs.
  • Checks: bun run check passes, and bun test test/routing.test.ts test/panel-keys.test.ts gives 18 pass.
  • Full gate: scripts/gate.sh on 6de7dd8 exited 0 (PASS (412s)), and on the final head 9ec7903 it exited 0 again. Both runs used Bun 1.4.2 on two CPUs. The final run gave 428 pass and 0 fail and PASS (408s), including the new narrowArrangements step and the stacked geometry pass. Native verification returned {"ok":true} for both atyrode.omp and atyrode.code.
  • Review: an independent review of the first head asked for changes, all applied in 6de7dd8. The delta review then asked for one fix: the docs and comments named a tier 0 that a compiled catalog never places. That fix is in 9ec7903, with two comment and test nits.

Not exercised: reduced motion was not emulated in the lab; the verifier's new step does run under reduced motion inside the gate. The keys in the lab were synthetic KeyboardEvents and the clicks element.click(), whereas the verifier step uses CDP input. The 170 and 240 px checks constrain the panel element, because the lab cannot shoot below 320 px. The fonts-ready re-measurement was not observed directly.

Refs #239

…ough, and the grouped profile by provider then level

Below 760 px the stage now weighs the panel's height as well: when the
generator without its grouped profile and the whole routing pane fit the
visible height together, routing stands under the generator and usage under
routing, with no Routing or Usage tabs, and p and s hide and show them as at
wider widths. Otherwise the narrow layout stays as it was. The fit is measured
from what is rendered, on resize and on structural changes only, never on a
readout or launch-line change, with the same quantities in both arrangements
and a small grace so it never oscillates.

The grouped profile orders its groups by provider (the default role's first,
then the panel's provider order) and within a provider by catalog tier, then
thinking, then alias; roles keep routing order.

Refs #239
… a resize settles

The narrow panel now decides whether routing fits under the generator from
routing's height without its fallback chains, measured even while they show,
so showing the chains never sends routing back to a tab; their extra lines
scroll. The generator's head counts every line but the Show controls only the
stacked arrangement adds. The size is taken once a resize has settled, so a
drag tries the stacked arrangement once rather than at every pixel, and a try
keeps the Routing and Usage tabs (without room) so focus on one stays unless the
stage really stacks. A flip to stacked is measured again as laid out, a
fallback-font measurement is dropped when the fonts are ready, and a probe whose
routing did not show ends. The grouped profile is a named group, aliases compare
by code unit, and the browser verifier asserts the short and tall narrow
arrangements, p and f when stacked.

Refs #239
@atyrode
atyrode force-pushed the fix/narrow-stacked-routing branch from a89eddf to 6de7dd8 Compare October 12, 2026 00:18
@atyrode
atyrode marked this pull request as ready for review October 12, 2026 00:36
@atyrode

atyrode commented Oct 12, 2026

Copy link
Copy Markdown
Owner Author

Verdict: pass

Head 9ec790396e290244606fb4d3a3785ce401457dbd, rebased on main 8c0c849b77 (#268).

  • Review:
    • The independent review of the first head (changes requested, nothing blocking) is addressed in 6de7dd89ab.
    • The delta review asked for one fix: the docs and comments named a tier 0 that a compiled catalog never places. That fix and two nits are in 9ec790396e.
  • Local gate: scripts/gate.sh on 9ec790396e exited 0:
    • 428 unit tests pass;
    • the two-browser verifier passes (408s), including the new narrow-arrangement step;
    • the native proofs answer {"ok":true} for atyrode.omp and atyrode.code.
  • CI on the final head:
    • test: run 38188619457;
    • plugins / verify: run 38188619702;
    • agent-policy: run 38188619671.
  • Visual check in the design lab (real Chromium, real bundles), images inspected:
    • at 658×1033, routing is shown in full under the generator, with no Routing or Usage tabs;
    • at 658×640 and 390×844, the grouped profile and the tabs remain, ordered by provider and then level;
    • at 760 px and wider, the shots are pixel-identical to main.

@atyrode
atyrode merged commit 94c6d44 into main Oct 12, 2026
4 checks passed
@atyrode
atyrode deleted the fix/narrow-stacked-routing branch October 12, 2026 00:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant