Skip to content

A spine on the edge, and one screen or two or four (0.26.0) - #1284

Merged
feder-cr merged 3 commits into
mainfrom
feat/the-sessions-band
Sep 9, 2026
Merged

A spine on the edge, and one screen or two or four (0.26.0)#1284
feder-cr merged 3 commits into
mainfrom
feat/the-sessions-band

Conversation

@feder-cr

@feder-cr feder-cr commented Sep 9, 2026

Copy link
Copy Markdown
Owner

The constraint this pane was built around is four times smaller than the file said

It assumed a frame costs 22 ms of pipe, and everything followed from that: one live pane, seven previews taking turns at one every 400 ms, and a comment explaining that eight panes would want 2.3 seconds of pipe per second.

Measured again with four real browsers over the same Link the interface uses:

screens fps total fps each ms per frame an action waits
1 19.2 19.2 5 40 ms
2 41.2 20.6 5 37 ms
4 80.2 20.1 6 49 ms

A frame costs 5 to 6 ms, not 22: the capture already runs inside the engine, and the server hands over the latest picture rather than taking one. Four live screens cost about half the pipe and an action still lands in 49 ms. The pane was rationing something that had stopped being scarce.

So the stage is a grid of 1, 2 or 4 live screens, chosen from the chrome and remembered per browser - a control room's vocabulary because the job is a control room's: one screen when you are watching the work, four when you are keeping an eye on it. The budget is still spent deliberately rather than to the limit: 25 frames a second at one-up, 20 each at two, 10 each at four, so 40 requests a second at most against the 80 measured as affordable.

Clicking a screen brings that browser to the front, which at one-up means it fills the stage. The strip below carries whatever the stage does not.

Every screen says how old its picture is. On a healthy stage each is refreshed every 40 to 100 ms, so anything past two seconds means that browser has stopped answering while its last frame sits there looking alive. Stale has to look stale: the first rule in a control room, and the fifth state a real-time dashboard needs after empty, loading, error and partial.

The sessions column opens from a spine

A hamburger says "there is a menu here" only to somebody who has already learned that it does. The control is part of the frame now: the leftmost thing on the screen and the first thing in the document, the full height of the window, the word running bottom to top the way a word runs on a spine, with the accent beside it whether the column is open or shut. It is the only way in or out, because a second control that opens the same column is a second thing to keep in step with the first.

The aria-label had to go with the icon: with a word written on the button, an aria-label REPLACES that name, so a screen reader would announce something that is not there and voice control would not find it (WCAG 2.5.3).

Two defects found by looking rather than reading

The pump died and said nothing. ageAll reached for the age label on the placeholder cell, which has no caption, threw, and the throw was outside the fetch's try - so the timer at the bottom was never reached and the loop stopped for good. A dead pump reads as a server that has stopped answering rather than as a page with a bug in it. The body is a separate function now and the scheduler only schedules.

The picture was 23px taller than its box and sat over the caption: height:100% on a grid item whose parent takes its height from a flex row does not resolve, so it fell back on its own aspect ratio. Anchored instead.

Gates

The part that decides WHICH browsers are on the stage is executed under node, because it is arithmetic over the fleet and a string scan cannot see it. Six known-bads, all killed: server order instead of watched-first, no running filter, no slice by layout, a strip that stops excluding the stage, no age stamp, and the pass back inside the scheduler.

The pace gate was rewritten: it asserted a literal pause that no longer exists, and now reads the table of frames a second and checks both edges - never below what the engine is told to produce, never above what the pipe was measured to carry.

488 tests green.

A bar in the header was not it. The control belongs to the frame: the leftmost
thing on the screen and the first thing in the document, the full height of the
window, with the word running bottom to top the way a word runs on a spine.
Closed it is the word; open it is the word next to the list; and it is the only
way in or out, because a second control that opens the same column is a second
thing to keep in step with the first.

The accent runs the whole height and stays whether the column is open or shut.
A line that appears and disappears is a state indicator competing with the
background; a line that is always there is the edge of the room, and the open
state has the background and the ink to say it.

⛔ The text turns, not the button. `transform` on the button rotates the whole
box with it, so the border and the accent would be drawn on the edge away from
the column instead of the one beside it - correct in the element's own
coordinates and backwards on the screen.

And the column's own header lost its title: with the spine beside it, the two
sat twenty pixels apart saying the same word. The row keeps its height from its
padding, so it still lines up with the app header.

Three known-bads on the new gate: the control moved after the conversation pane,
where it reads as one of that pane's buttons; a second control carrying
`aria-controls="rail"`; and the vertical writing dropped, which leaves the word
running across a column 34px wide.
At 34px with nothing but letters the spine read as a label somebody had printed
on the frame, which is the one thing it must not read as. Wider, and with the
same chevron the step rows use, drawn from borders rather than an icon: it
points into the room when the column is shut and back out when it is open, so
the thing you press also says which way it goes. The chevron and the word are
two rows of one grid, centred together - pinned to the top the arrow sat 450px
from the word and they read as separate things on the same strip.

And a list is set apart on BOTH sides. Only stepping the left is why it still
read as prose with dots in it: measured on a real answer, the items began 26px
in from the paragraph above and ended at 548, the same pixel the paragraph
ended on, so the block was indented on one edge and flush on the other. The eye
reads that as the same column, slightly ragged, rather than as something set
inside it. 2.6em in and 1.4em back gives it two edges of its own: 36px and 20px
on the running page.
⛔ THE CONSTRAINT THIS PANE WAS BUILT AROUND IS FOUR TIMES SMALLER THAN THE
FILE SAID. It assumed a frame costs 22 ms of pipe, and everything followed from
that: one live pane, seven previews taking turns at one every 400 ms, and a
comment explaining that eight panes would want 2.3 seconds of pipe per second.
Measured again on 2026-09-09 with four real browsers over the same Link the
interface uses, a frame costs 5 to 6 ms - the capture already runs inside the
engine, and the server hands over the latest picture rather than taking one.
Four panes polled flat out delivered 80 frames a second in total, about 20
each, and an action still landed in 49 ms against 40 with a single pane. The
pane was rationing something that had stopped being scarce.

So the stage is a grid of 1, 2 or 4 live screens, chosen from the chrome and
remembered per browser. The vocabulary is a control room's because the job is a
control room's: one screen when you are watching the work, four when you are
keeping an eye on it. The budget is still spent deliberately rather than to the
limit - 25 frames a second at one-up, 20 each at two, 10 each at four, so 40
requests a second at most against the 80 measured as affordable.

Clicking a screen brings that browser to the front, which at one-up means it
fills the stage: that is what "click it and go to another screen" means. The
strip below carries whatever the stage does not, so at four-up with four
browsers it is empty and at one-up with eight it holds seven.

⛔ And every screen says how old its picture is. On a healthy stage each one is
refreshed every 40 to 100 ms, so anything past two seconds means that browser
has stopped answering while its last frame sits there looking alive. Stale has
to look stale: it is the first rule in a control room and the fifth state a
real-time dashboard needs after empty, loading, error and partial.

⛔ And the pump can no longer be killed by a bad pass, because it was, the first
time this ran. `ageAll` reached for the age label on the placeholder cell, which
has no caption, threw, and the throw was outside the fetch's try - so the timer
at the bottom was never reached and the loop stopped for good, in silence. A
dead pump reads as a server that has stopped answering rather than as a page
with a bug in it. The body is a separate function now and the scheduler only
schedules.

The picture is anchored rather than sized in percent: `height:100%` on a grid
item whose parent takes its height from a flex row does not resolve, so it fell
back on its own aspect ratio and came out 23px taller than its box - measured -
sitting over the caption underneath.

Six known-bads on the new gates, all killed, plus the pace gate rewritten: it
asserted a literal pause that no longer exists, and now reads the table of
frames a second and checks both edges - never below what the engine is told to
produce, never above what the pipe was measured to carry.
@feder-cr
feder-cr merged commit d19cf82 into main Sep 9, 2026
12 checks passed
@feder-cr
feder-cr deleted the feat/the-sessions-band branch September 9, 2026 00:08
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